Bug Summary

File:src/fccharset.c
Location:line 216, column 5
Description:Potential leak of memory pointed to by 'leaves'

Annotated Source Code

1/*
2 * fontconfig/src/fccharset.c
3 *
4 * Copyright © 2001 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25#include "fcint.h"
26#include <stdlib.h>
27
28/* #define CHECK */
29
30FcCharSet *
31FcCharSetCreate (void)
32{
33 FcCharSet *fcs;
34
35 fcs = (FcCharSet *) malloc (sizeof (FcCharSet));
36 if (!fcs)
37 return 0;
38 FcRefInit (&fcs->ref, 1);
39 fcs->num = 0;
40 fcs->leaves_offset = 0;
41 fcs->numbers_offset = 0;
42 return fcs;
43}
44
45FcCharSet *
46FcCharSetPromote (FcValuePromotionBuffer *vbuf)
47{
48 FcCharSet *fcs = (FcCharSet *) vbuf;
49
50 FC_ASSERT_STATIC (sizeof (FcCharSet) <= sizeof (FcValuePromotionBuffer))typedef int _static_assert_on_line_50_failed[(((sizeof (FcCharSet
) <= sizeof (FcValuePromotionBuffer))))?1:-1] __attribute__
((unused))
;
51
52 FcRefSetConst (&fcs->ref);
53 fcs->num = 0;
54 fcs->leaves_offset = 0;
55 fcs->numbers_offset = 0;
56
57 return fcs;
58}
59
60FcCharSet *
61FcCharSetNew (void)
62{
63 return FcCharSetCreate ();
64}
65
66void
67FcCharSetDestroy (FcCharSet *fcs)
68{
69 int i;
70
71 if (fcs)
72 {
73 if (FcRefIsConst (&fcs->ref))
74 {
75 FcCacheObjectDereference (fcs);
76 return;
77 }
78 if (FcRefDec (&fcs->ref) != 1)
79 return;
80 for (i = 0; i < fcs->num; i++)
81 free (FcCharSetLeaf (fcs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[i]))))
);
82 if (fcs->num)
83 {
84 free (FcCharSetLeaves (fcs)((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset))));
85 free (FcCharSetNumbers (fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
);
86 }
87 free (fcs);
88 }
89}
90
91/*
92 * Search for the leaf containing with the specified num.
93 * Return its index if it exists, otherwise return negative of
94 * the (position + 1) where it should be inserted
95 */
96
97
98static int
99FcCharSetFindLeafForward (const FcCharSet *fcs, int start, FcChar16 num)
100{
101 FcChar16 *numbers = FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
;
102 FcChar16 page;
103 int low = start;
104 int high = fcs->num - 1;
105
106 if (!numbers)
107 return -1;
108 while (low <= high)
109 {
110 int mid = (low + high) >> 1;
111 page = numbers[mid];
112 if (page == num)
113 return mid;
114 if (page < num)
115 low = mid + 1;
116 else
117 high = mid - 1;
118 }
119 if (high < 0 || (high < fcs->num && numbers[high] < num))
120 high++;
121 return -(high + 1);
122}
123
124/*
125 * Locate the leaf containing the specified char, return
126 * its index if it exists, otherwise return negative of
127 * the (position + 1) where it should be inserted
128 */
129
130static int
131FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
132{
133 return FcCharSetFindLeafForward (fcs, 0, ucs4 >> 8);
134}
135
136static FcCharLeaf *
137FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
138{
139 int pos = FcCharSetFindLeafPos (fcs, ucs4);
140 if (pos >= 0)
141 return FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[pos]))))
;
142 return 0;
143}
144
145#define FC_IS_ZERO_OR_POWER_OF_TWO(x)(!((x) & ((x)-1))) (!((x) & ((x)-1)))
146
147static FcBool
148FcCharSetPutLeaf (FcCharSet *fcs,
149 FcChar32 ucs4,
150 FcCharLeaf *leaf,
151 int pos)
152{
153 intptr_t *leaves = FcCharSetLeaves (fcs)((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)));
154 FcChar16 *numbers = FcCharSetNumbers (fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
;
155
156 ucs4 >>= 8;
157 if (ucs4 >= 0x10000)
13
Assuming 'ucs4' is < 65536
14
Taking false branch
158 return FcFalse0;
159
160 if (FC_IS_ZERO_OR_POWER_OF_TWO (fcs->num)(!((fcs->num) & ((fcs->num)-1))))
15
Taking true branch
161 {
162 if (!fcs->num)
16
Taking true branch
163 {
164 unsigned int alloced = 8;
165 leaves = malloc (alloced * sizeof (*leaves));
17
Memory is allocated
166 numbers = malloc (alloced * sizeof (*numbers));
167 if (!leaves || !numbers)
18
Assuming 'leaves' is non-null
19
Assuming 'numbers' is non-null
20
Taking false branch
168 {
169 if (leaves)
170 free (leaves);
171 if (numbers)
172 free (numbers);
173 return FcFalse0;
174 }
175 }
176 else
177 {
178 unsigned int alloced = fcs->num;
179 intptr_t *new_leaves, distance;
180
181 alloced *= 2;
182 new_leaves = realloc (leaves, alloced * sizeof (*leaves));
183 if (!new_leaves)
184 return FcFalse0;
185 numbers = realloc (numbers, alloced * sizeof (*numbers));
186 if (!numbers)
187 {
188 /* Revert the reallocation of leaves */
189 leaves = realloc (new_leaves, (alloced / 2) * sizeof (*new_leaves));
190 /* unlikely to fail though */
191 if (!leaves)
192 return FcFalse0;
193 fcs->leaves_offset = FcPtrToOffset (fcs, leaves)((intptr_t) (leaves) - (intptr_t) (fcs));
194 return FcFalse0;
195 }
196 distance = (intptr_t) new_leaves - (intptr_t) leaves;
197 if (new_leaves && distance)
198 {
199 int i;
200 for (i = 0; i < fcs->num; i++)
201 new_leaves[i] -= distance;
202 }
203 leaves = new_leaves;
204 }
205
206 fcs->leaves_offset = FcPtrToOffset (fcs, leaves)((intptr_t) (leaves) - (intptr_t) (fcs));
207 fcs->numbers_offset = FcPtrToOffset (fcs, numbers)((intptr_t) (numbers) - (intptr_t) (fcs));
208 }
209
210 memmove (leaves + pos + 1, leaves + pos,__builtin___memmove_chk (leaves + pos + 1, leaves + pos, (fcs
->num - pos) * sizeof (*leaves), __builtin_object_size (leaves
+ pos + 1, 0))
211 (fcs->num - pos) * sizeof (*leaves))__builtin___memmove_chk (leaves + pos + 1, leaves + pos, (fcs
->num - pos) * sizeof (*leaves), __builtin_object_size (leaves
+ pos + 1, 0))
;
212 memmove (numbers + pos + 1, numbers + pos,__builtin___memmove_chk (numbers + pos + 1, numbers + pos, (fcs
->num - pos) * sizeof (*numbers), __builtin_object_size (numbers
+ pos + 1, 0))
213 (fcs->num - pos) * sizeof (*numbers))__builtin___memmove_chk (numbers + pos + 1, numbers + pos, (fcs
->num - pos) * sizeof (*numbers), __builtin_object_size (numbers
+ pos + 1, 0))
;
214 numbers[pos] = (FcChar16) ucs4;
215 leaves[pos] = FcPtrToOffset (leaves, leaf)((intptr_t) (leaf) - (intptr_t) (leaves));
216 fcs->num++;
21
Potential leak of memory pointed to by 'leaves'
217 return FcTrue1;
218}
219
220/*
221 * Locate the leaf containing the specified char, creating it
222 * if desired
223 */
224
225FcCharLeaf *
226FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
227{
228 int pos;
229 FcCharLeaf *leaf;
230
231 pos = FcCharSetFindLeafPos (fcs, ucs4);
232 if (pos >= 0)
233 return FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[pos]))))
;
234
235 leaf = calloc (1, sizeof (FcCharLeaf));
236 if (!leaf)
237 return 0;
238
239 pos = -pos - 1;
240 if (!FcCharSetPutLeaf (fcs, ucs4, leaf, pos))
241 {
242 free (leaf);
243 return 0;
244 }
245 return leaf;
246}
247
248static FcBool
249FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf)
250{
251 int pos;
252
253 pos = FcCharSetFindLeafPos (fcs, ucs4);
254 if (pos >= 0)
10
Assuming 'pos' is < 0
11
Taking false branch
255 {
256 free (FcCharSetLeaf (fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[pos]))))
);
257 FcCharSetLeaves(fcs)((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))[pos] = FcPtrToOffset (FcCharSetLeaves(fcs),((intptr_t) (leaf) - (intptr_t) (((intptr_t *) ((intptr_t) (fcs
) + ((fcs)->leaves_offset)))))
258 leaf)((intptr_t) (leaf) - (intptr_t) (((intptr_t *) ((intptr_t) (fcs
) + ((fcs)->leaves_offset)))))
;
259 return FcTrue1;
260 }
261 pos = -pos - 1;
262 return FcCharSetPutLeaf (fcs, ucs4, leaf, pos);
12
Calling 'FcCharSetPutLeaf'
263}
264
265FcBool
266FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
267{
268 FcCharLeaf *leaf;
269 FcChar32 *b;
270
271 if (fcs == NULL((void*)0) || FcRefIsConst (&fcs->ref))
272 return FcFalse0;
273 leaf = FcCharSetFindLeafCreate (fcs, ucs4);
274 if (!leaf)
275 return FcFalse0;
276 b = &leaf->map[(ucs4 & 0xff) >> 5];
277 *b |= (1 << (ucs4 & 0x1f));
278 return FcTrue1;
279}
280
281FcBool
282FcCharSetDelChar (FcCharSet *fcs, FcChar32 ucs4)
283{
284 FcCharLeaf *leaf;
285 FcChar32 *b;
286
287 if (fcs == NULL((void*)0) || FcRefIsConst (&fcs->ref))
288 return FcFalse0;
289 leaf = FcCharSetFindLeaf (fcs, ucs4);
290 if (!leaf)
291 return FcTrue1;
292 b = &leaf->map[(ucs4 & 0xff) >> 5];
293 *b &= ~(1 << (ucs4 & 0x1f));
294 /* We don't bother removing the leaf if it's empty */
295 return FcTrue1;
296}
297
298/*
299 * An iterator for the leaves of a charset
300 */
301
302typedef struct _fcCharSetIter {
303 FcCharLeaf *leaf;
304 FcChar32 ucs4;
305 int pos;
306} FcCharSetIter;
307
308/*
309 * Set iter->leaf to the leaf containing iter->ucs4 or higher
310 */
311
312static void
313FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
314{
315 int pos = FcCharSetFindLeafPos (fcs, iter->ucs4);
316
317 if (pos < 0)
318 {
319 pos = -pos - 1;
320 if (pos == fcs->num)
321 {
322 iter->ucs4 = ~0;
323 iter->leaf = 0;
324 return;
325 }
326 iter->ucs4 = (FcChar32) FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
[pos] << 8;
327 }
328 iter->leaf = FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[pos]))))
;
329 iter->pos = pos;
330}
331
332static void
333FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
334{
335 int pos = iter->pos + 1;
336 if (pos >= fcs->num)
337 {
338 iter->ucs4 = ~0;
339 iter->leaf = 0;
340 }
341 else
342 {
343 iter->ucs4 = (FcChar32) FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
[pos] << 8;
344 iter->leaf = FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[pos]))))
;
345 iter->pos = pos;
346 }
347}
348
349
350static void
351FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
352{
353 iter->ucs4 = 0;
354 iter->pos = 0;
355 FcCharSetIterSet (fcs, iter);
356}
357
358FcCharSet *
359FcCharSetCopy (FcCharSet *src)
360{
361 if (src)
362 {
363 if (!FcRefIsConst (&src->ref))
364 FcRefInc (&src->ref);
365 else
366 FcCacheObjectReference (src);
367 }
368 return src;
369}
370
371FcBool
372FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
373{
374 FcCharSetIter ai, bi;
375 int i;
376
377 if (a == b)
378 return FcTrue1;
379 if (!a || !b)
380 return FcFalse0;
381 for (FcCharSetIterStart (a, &ai), FcCharSetIterStart (b, &bi);
382 ai.leaf && bi.leaf;
383 FcCharSetIterNext (a, &ai), FcCharSetIterNext (b, &bi))
384 {
385 if (ai.ucs4 != bi.ucs4)
386 return FcFalse0;
387 for (i = 0; i < 256/32; i++)
388 if (ai.leaf->map[i] != bi.leaf->map[i])
389 return FcFalse0;
390 }
391 return ai.leaf == bi.leaf;
392}
393
394static FcBool
395FcCharSetAddLeaf (FcCharSet *fcs,
396 FcChar32 ucs4,
397 FcCharLeaf *leaf)
398{
399 FcCharLeaf *new = FcCharSetFindLeafCreate (fcs, ucs4);
400 if (!new)
401 return FcFalse0;
402 *new = *leaf;
403 return FcTrue1;
404}
405
406static FcCharSet *
407FcCharSetOperate (const FcCharSet *a,
408 const FcCharSet *b,
409 FcBool (*overlap) (FcCharLeaf *result,
410 const FcCharLeaf *al,
411 const FcCharLeaf *bl),
412 FcBool aonly,
413 FcBool bonly)
414{
415 FcCharSet *fcs;
416 FcCharSetIter ai, bi;
417
418 if (!a || !b)
419 goto bail0;
420 fcs = FcCharSetCreate ();
421 if (!fcs)
422 goto bail0;
423 FcCharSetIterStart (a, &ai);
424 FcCharSetIterStart (b, &bi);
425 while ((ai.leaf || (bonly && bi.leaf)) && (bi.leaf || (aonly && ai.leaf)))
426 {
427 if (ai.ucs4 < bi.ucs4)
428 {
429 if (aonly)
430 {
431 if (!FcCharSetAddLeaf (fcs, ai.ucs4, ai.leaf))
432 goto bail1;
433 FcCharSetIterNext (a, &ai);
434 }
435 else
436 {
437 ai.ucs4 = bi.ucs4;
438 FcCharSetIterSet (a, &ai);
439 }
440 }
441 else if (bi.ucs4 < ai.ucs4 )
442 {
443 if (bonly)
444 {
445 if (!FcCharSetAddLeaf (fcs, bi.ucs4, bi.leaf))
446 goto bail1;
447 FcCharSetIterNext (b, &bi);
448 }
449 else
450 {
451 bi.ucs4 = ai.ucs4;
452 FcCharSetIterSet (b, &bi);
453 }
454 }
455 else
456 {
457 FcCharLeaf leaf;
458
459 if ((*overlap) (&leaf, ai.leaf, bi.leaf))
460 {
461 if (!FcCharSetAddLeaf (fcs, ai.ucs4, &leaf))
462 goto bail1;
463 }
464 FcCharSetIterNext (a, &ai);
465 FcCharSetIterNext (b, &bi);
466 }
467 }
468 return fcs;
469bail1:
470 FcCharSetDestroy (fcs);
471bail0:
472 return 0;
473}
474
475static FcBool
476FcCharSetIntersectLeaf (FcCharLeaf *result,
477 const FcCharLeaf *al,
478 const FcCharLeaf *bl)
479{
480 int i;
481 FcBool nonempty = FcFalse0;
482
483 for (i = 0; i < 256/32; i++)
484 if ((result->map[i] = al->map[i] & bl->map[i]))
485 nonempty = FcTrue1;
486 return nonempty;
487}
488
489FcCharSet *
490FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b)
491{
492 return FcCharSetOperate (a, b, FcCharSetIntersectLeaf, FcFalse0, FcFalse0);
493}
494
495static FcBool
496FcCharSetUnionLeaf (FcCharLeaf *result,
497 const FcCharLeaf *al,
498 const FcCharLeaf *bl)
499{
500 int i;
501
502 for (i = 0; i < 256/32; i++)
503 result->map[i] = al->map[i] | bl->map[i];
504 return FcTrue1;
505}
506
507FcCharSet *
508FcCharSetUnion (const FcCharSet *a, const FcCharSet *b)
509{
510 return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue1, FcTrue1);
511}
512
513FcBool
514FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed)
515{
516 int ai = 0, bi = 0;
517 FcChar16 an, bn;
518
519 if (!a || !b)
520 return FcFalse0;
521
522 if (FcRefIsConst (&a->ref)) {
523 if (changed)
524 *changed = FcFalse0;
525 return FcFalse0;
526 }
527
528 if (changed) {
529 *changed = !FcCharSetIsSubset(b, a);
530 if (!*changed)
531 return FcTrue1;
532 }
533
534 while (bi < b->num)
535 {
536 an = ai < a->num ? FcCharSetNumbers(a)((FcChar16 *) ((intptr_t) (a) + ((a)->numbers_offset)))[ai] : ~0;
537 bn = FcCharSetNumbers(b)((FcChar16 *) ((intptr_t) (b) + ((b)->numbers_offset)))[bi];
538
539 if (an < bn)
540 {
541 ai = FcCharSetFindLeafForward (a, ai + 1, bn);
542 if (ai < 0)
543 ai = -ai - 1;
544 }
545 else
546 {
547 FcCharLeaf *bl = FcCharSetLeaf(b, bi)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (b) +
((b)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (b) +
((b)->leaves_offset)))[bi]))))
;
548 if (bn < an)
549 {
550 if (!FcCharSetAddLeaf (a, bn << 8, bl))
551 return FcFalse0;
552 }
553 else
554 {
555 FcCharLeaf *al = FcCharSetLeaf(a, ai)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (a) +
((a)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (a) +
((a)->leaves_offset)))[ai]))))
;
556 FcCharSetUnionLeaf (al, al, bl);
557 }
558
559 ai++;
560 bi++;
561 }
562 }
563
564 return FcTrue1;
565}
566
567static FcBool
568FcCharSetSubtractLeaf (FcCharLeaf *result,
569 const FcCharLeaf *al,
570 const FcCharLeaf *bl)
571{
572 int i;
573 FcBool nonempty = FcFalse0;
574
575 for (i = 0; i < 256/32; i++)
576 if ((result->map[i] = al->map[i] & ~bl->map[i]))
577 nonempty = FcTrue1;
578 return nonempty;
579}
580
581FcCharSet *
582FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b)
583{
584 return FcCharSetOperate (a, b, FcCharSetSubtractLeaf, FcTrue1, FcFalse0);
585}
586
587FcBool
588FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4)
589{
590 FcCharLeaf *leaf;
591
592 if (!fcs)
593 return FcFalse0;
594 leaf = FcCharSetFindLeaf (fcs, ucs4);
595 if (!leaf)
596 return FcFalse0;
597 return (leaf->map[(ucs4 & 0xff) >> 5] & (1 << (ucs4 & 0x1f))) != 0;
598}
599
600static FcChar32
601FcCharSetPopCount (FcChar32 c1)
602{
603#if __GNUC__4 > 3 || (__GNUC__4 == 3 && __GNUC_MINOR__2 >= 4)
604 return __builtin_popcount (c1);
605#else
606 /* hackmem 169 */
607 FcChar32 c2 = (c1 >> 1) & 033333333333;
608 c2 = c1 - c2 - ((c2 >> 1) & 033333333333);
609 return (((c2 + (c2 >> 3)) & 030707070707) % 077);
610#endif
611}
612
613FcChar32
614FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b)
615{
616 FcCharSetIter ai, bi;
617 FcChar32 count = 0;
618
619 if (a && b)
620 {
621 FcCharSetIterStart (a, &ai);
622 FcCharSetIterStart (b, &bi);
623 while (ai.leaf && bi.leaf)
624 {
625 if (ai.ucs4 == bi.ucs4)
626 {
627 FcChar32 *am = ai.leaf->map;
628 FcChar32 *bm = bi.leaf->map;
629 int i = 256/32;
630 while (i--)
631 count += FcCharSetPopCount (*am++ & *bm++);
632 FcCharSetIterNext (a, &ai);
633 }
634 else if (ai.ucs4 < bi.ucs4)
635 {
636 ai.ucs4 = bi.ucs4;
637 FcCharSetIterSet (a, &ai);
638 }
639 if (bi.ucs4 < ai.ucs4)
640 {
641 bi.ucs4 = ai.ucs4;
642 FcCharSetIterSet (b, &bi);
643 }
644 }
645 }
646 return count;
647}
648
649FcChar32
650FcCharSetCount (const FcCharSet *a)
651{
652 FcCharSetIter ai;
653 FcChar32 count = 0;
654
655 if (a)
656 {
657 for (FcCharSetIterStart (a, &ai); ai.leaf; FcCharSetIterNext (a, &ai))
658 {
659 int i = 256/32;
660 FcChar32 *am = ai.leaf->map;
661
662 while (i--)
663 count += FcCharSetPopCount (*am++);
664 }
665 }
666 return count;
667}
668
669FcChar32
670FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b)
671{
672 FcCharSetIter ai, bi;
673 FcChar32 count = 0;
674
675 if (a && b)
676 {
677 FcCharSetIterStart (a, &ai);
678 FcCharSetIterStart (b, &bi);
679 while (ai.leaf)
680 {
681 if (ai.ucs4 <= bi.ucs4)
682 {
683 FcChar32 *am = ai.leaf->map;
684 int i = 256/32;
685 if (ai.ucs4 == bi.ucs4)
686 {
687 FcChar32 *bm = bi.leaf->map;
688 while (i--)
689 count += FcCharSetPopCount (*am++ & ~*bm++);
690 }
691 else
692 {
693 while (i--)
694 count += FcCharSetPopCount (*am++);
695 }
696 FcCharSetIterNext (a, &ai);
697 }
698 else if (bi.leaf)
699 {
700 bi.ucs4 = ai.ucs4;
701 FcCharSetIterSet (b, &bi);
702 }
703 }
704 }
705 return count;
706}
707
708/*
709 * return FcTrue iff a is a subset of b
710 */
711FcBool
712FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
713{
714 int ai, bi;
715 FcChar16 an, bn;
716
717 if (a == b)
718 return FcTrue1;
719 if (!a || !b)
720 return FcFalse0;
721 bi = 0;
722 ai = 0;
723 while (ai < a->num && bi < b->num)
724 {
725 an = FcCharSetNumbers(a)((FcChar16 *) ((intptr_t) (a) + ((a)->numbers_offset)))[ai];
726 bn = FcCharSetNumbers(b)((FcChar16 *) ((intptr_t) (b) + ((b)->numbers_offset)))[bi];
727 /*
728 * Check matching pages
729 */
730 if (an == bn)
731 {
732 FcChar32 *am = FcCharSetLeaf(a, ai)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (a) +
((a)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (a) +
((a)->leaves_offset)))[ai]))))
->map;
733 FcChar32 *bm = FcCharSetLeaf(b, bi)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (b) +
((b)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (b) +
((b)->leaves_offset)))[bi]))))
->map;
734
735 if (am != bm)
736 {
737 int i = 256/32;
738 /*
739 * Does am have any bits not in bm?
740 */
741 while (i--)
742 if (*am++ & ~*bm++)
743 return FcFalse0;
744 }
745 ai++;
746 bi++;
747 }
748 /*
749 * Does a have any pages not in b?
750 */
751 else if (an < bn)
752 return FcFalse0;
753 else
754 {
755 bi = FcCharSetFindLeafForward (b, bi + 1, an);
756 if (bi < 0)
757 bi = -bi - 1;
758 }
759 }
760 /*
761 * did we look at every page?
762 */
763 return ai >= a->num;
764}
765
766/*
767 * These two functions efficiently walk the entire charmap for
768 * other software (like pango) that want their own copy
769 */
770
771FcChar32
772FcCharSetNextPage (const FcCharSet *a,
773 FcChar32 map[FC_CHARSET_MAP_SIZE(256/32)],
774 FcChar32 *next)
775{
776 FcCharSetIter ai;
777 FcChar32 page;
778
779 if (!a)
780 return FC_CHARSET_DONE((FcChar32) -1);
781 ai.ucs4 = *next;
782 FcCharSetIterSet (a, &ai);
783 if (!ai.leaf)
784 return FC_CHARSET_DONE((FcChar32) -1);
785
786 /*
787 * Save current information
788 */
789 page = ai.ucs4;
790 memcpy (map, ai.leaf->map, sizeof (ai.leaf->map))__builtin___memcpy_chk (map, ai.leaf->map, sizeof (ai.leaf
->map), __builtin_object_size (map, 0))
;
791 /*
792 * Step to next page
793 */
794 FcCharSetIterNext (a, &ai);
795 *next = ai.ucs4;
796
797 return page;
798}
799
800FcChar32
801FcCharSetFirstPage (const FcCharSet *a,
802 FcChar32 map[FC_CHARSET_MAP_SIZE(256/32)],
803 FcChar32 *next)
804{
805 *next = 0;
806 return FcCharSetNextPage (a, map, next);
807}
808
809/*
810 * old coverage API, rather hard to use correctly
811 */
812
813FcChar32
814FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result)
815{
816 FcCharSetIter ai;
817
818 ai.ucs4 = page;
819 FcCharSetIterSet (a, &ai);
820 if (!ai.leaf)
821 {
822 memset (result, '\0', 256 / 8)__builtin___memset_chk (result, '\0', 256 / 8, __builtin_object_size
(result, 0))
;
823 page = 0;
824 }
825 else
826 {
827 memcpy (result, ai.leaf->map, sizeof (ai.leaf->map))__builtin___memcpy_chk (result, ai.leaf->map, sizeof (ai.leaf
->map), __builtin_object_size (result, 0))
;
828 FcCharSetIterNext (a, &ai);
829 page = ai.ucs4;
830 }
831 return page;
832}
833
834static FcBool
835FcNameParseRange (FcChar8 **string, FcChar32 *pfirst, FcChar32 *plast)
836{
837 char *s = (char *) *string;
838 char *t;
839 long first, last;
840
841 while (isspace(*s))
842 s++;
843 t = s;
844 errno(*__error()) = 0;
845 first = last = strtol (s, &s, 16);
846 if (errno(*__error()))
847 return FcFalse0;
848 while (isspace(*s))
849 s++;
850 if (*s == '-')
851 {
852 s++;
853 errno(*__error()) = 0;
854 last = strtol (s, &s, 16);
855 if (errno(*__error()))
856 return FcFalse0;
857 }
858
859 if (s == t || first < 0 || last < 0 || last < first || last > 0x10ffff)
860 return FcFalse0;
861
862 *string = (FcChar8 *) s;
863 *pfirst = first;
864 *plast = last;
865 return FcTrue1;
866}
867
868FcCharSet *
869FcNameParseCharSet (FcChar8 *string)
870{
871 FcCharSet *c;
872 FcChar32 first, last;
873
874 c = FcCharSetCreate ();
875 if (!c)
876 goto bail0;
877 while (*string)
878 {
879 FcChar32 u;
880
881 if (!FcNameParseRange (&string, &first, &last))
882 goto bail1;
883
884 for (u = first; u < last + 1; u++)
885 FcCharSetAddChar (c, u);
886 }
887 return c;
888bail1:
889 FcCharSetDestroy (c);
890bail0:
891 return NULL((void*)0);
892}
893
894static void
895FcNameUnparseUnicode (FcStrBuf *buf, FcChar32 u)
896{
897 FcChar8 buf_static[64];
898 snprintf ((char *) buf_static, sizeof (buf_static), "%x", u)__builtin___snprintf_chk ((char *) buf_static, sizeof (buf_static
), 0, __builtin_object_size ((char *) buf_static, 2 > 1 ? 1
: 0), "%x", u)
;
899 FcStrBufString (buf, buf_static);
900}
901
902FcBool
903FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
904{
905 FcCharSetIter ci;
906 FcChar32 first, last;
907 int i;
908#ifdef CHECK
909 int len = buf->len;
910#endif
911
912 first = last = 0x7FFFFFFF;
913
914 for (FcCharSetIterStart (c, &ci);
915 ci.leaf;
916 FcCharSetIterNext (c, &ci))
917 {
918 for (i = 0; i < 256/32; i++)
919 {
920 FcChar32 bits = ci.leaf->map[i];
921 FcChar32 u = ci.ucs4 + i * 32;
922
923 while (bits)
924 {
925 if (bits & 1)
926 {
927 if (u != last + 1)
928 {
929 if (last != first)
930 {
931 FcStrBufChar (buf, '-');
932 FcNameUnparseUnicode (buf, last);
933 }
934 if (last != 0x7FFFFFFF)
935 FcStrBufChar (buf, ' ');
936 /* Start new range. */
937 first = u;
938 FcNameUnparseUnicode (buf, u);
939 }
940 last = u;
941 }
942 bits >>= 1;
943 u++;
944 }
945 }
946 }
947 if (last != first)
948 {
949 FcStrBufChar (buf, '-');
950 FcNameUnparseUnicode (buf, last);
951 }
952#ifdef CHECK
953 {
954 FcCharSet *check;
955 FcChar32 missing;
956 FcCharSetIter ci, checki;
957
958 /* null terminate for parser */
959 FcStrBufChar (buf, '\0');
960 /* step back over null for life after test */
961 buf->len--;
962 check = FcNameParseCharSet (buf->buf + len);
963 FcCharSetIterStart (c, &ci);
964 FcCharSetIterStart (check, &checki);
965 while (ci.leaf || checki.leaf)
966 {
967 if (ci.ucs4 < checki.ucs4)
968 {
969 printf ("Missing leaf node at 0x%x\n", ci.ucs4);
970 FcCharSetIterNext (c, &ci);
971 }
972 else if (checki.ucs4 < ci.ucs4)
973 {
974 printf ("Extra leaf node at 0x%x\n", checki.ucs4);
975 FcCharSetIterNext (check, &checki);
976 }
977 else
978 {
979 int i = 256/32;
980 FcChar32 *cm = ci.leaf->map;
981 FcChar32 *checkm = checki.leaf->map;
982
983 for (i = 0; i < 256; i += 32)
984 {
985 if (*cm != *checkm)
986 printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
987 ci.ucs4 + i, *cm, *checkm);
988 cm++;
989 checkm++;
990 }
991 FcCharSetIterNext (c, &ci);
992 FcCharSetIterNext (check, &checki);
993 }
994 }
995 if ((missing = FcCharSetSubtractCount (c, check)))
996 printf ("%d missing in reparsed result\n", missing);
997 if ((missing = FcCharSetSubtractCount (check, c)))
998 printf ("%d extra in reparsed result\n", missing);
999 FcCharSetDestroy (check);
1000 }
1001#endif
1002
1003 return FcTrue1;
1004}
1005
1006typedef struct _FcCharLeafEnt FcCharLeafEnt;
1007
1008struct _FcCharLeafEnt {
1009 FcCharLeafEnt *next;
1010 FcChar32 hash;
1011 FcCharLeaf leaf;
1012};
1013
1014#define FC_CHAR_LEAF_BLOCK(4096 / sizeof (FcCharLeafEnt)) (4096 / sizeof (FcCharLeafEnt))
1015#define FC_CHAR_LEAF_HASH_SIZE257 257
1016
1017typedef struct _FcCharSetEnt FcCharSetEnt;
1018
1019struct _FcCharSetEnt {
1020 FcCharSetEnt *next;
1021 FcChar32 hash;
1022 FcCharSet set;
1023};
1024
1025typedef struct _FcCharSetOrigEnt FcCharSetOrigEnt;
1026
1027struct _FcCharSetOrigEnt {
1028 FcCharSetOrigEnt *next;
1029 const FcCharSet *orig;
1030 const FcCharSet *frozen;
1031};
1032
1033#define FC_CHAR_SET_HASH_SIZE67 67
1034
1035struct _FcCharSetFreezer {
1036 FcCharLeafEnt *leaf_hash_table[FC_CHAR_LEAF_HASH_SIZE257];
1037 FcCharLeafEnt **leaf_blocks;
1038 int leaf_block_count;
1039 FcCharSetEnt *set_hash_table[FC_CHAR_SET_HASH_SIZE67];
1040 FcCharSetOrigEnt *orig_hash_table[FC_CHAR_SET_HASH_SIZE67];
1041 FcCharLeafEnt *current_block;
1042 int leaf_remain;
1043 int leaves_seen;
1044 int charsets_seen;
1045 int leaves_allocated;
1046 int charsets_allocated;
1047};
1048
1049static FcCharLeafEnt *
1050FcCharLeafEntCreate (FcCharSetFreezer *freezer)
1051{
1052 if (!freezer->leaf_remain)
1053 {
1054 FcCharLeafEnt **newBlocks;
1055
1056 freezer->leaf_block_count++;
1057 newBlocks = realloc (freezer->leaf_blocks, freezer->leaf_block_count * sizeof (FcCharLeafEnt *));
1058 if (!newBlocks)
1059 return 0;
1060 freezer->leaf_blocks = newBlocks;
1061 freezer->current_block = freezer->leaf_blocks[freezer->leaf_block_count-1] = malloc (FC_CHAR_LEAF_BLOCK(4096 / sizeof (FcCharLeafEnt)) * sizeof (FcCharLeafEnt));
1062 if (!freezer->current_block)
1063 return 0;
1064 freezer->leaf_remain = FC_CHAR_LEAF_BLOCK(4096 / sizeof (FcCharLeafEnt));
1065 }
1066 freezer->leaf_remain--;
1067 freezer->leaves_allocated++;
1068 return freezer->current_block++;
1069}
1070
1071static FcChar32
1072FcCharLeafHash (FcCharLeaf *leaf)
1073{
1074 FcChar32 hash = 0;
1075 int i;
1076
1077 for (i = 0; i < 256/32; i++)
1078 hash = ((hash << 1) | (hash >> 31)) ^ leaf->map[i];
1079 return hash;
1080}
1081
1082static FcCharLeaf *
1083FcCharSetFreezeLeaf (FcCharSetFreezer *freezer, FcCharLeaf *leaf)
1084{
1085 FcChar32 hash = FcCharLeafHash (leaf);
1086 FcCharLeafEnt **bucket = &freezer->leaf_hash_table[hash % FC_CHAR_LEAF_HASH_SIZE257];
1087 FcCharLeafEnt *ent;
1088
1089 for (ent = *bucket; ent; ent = ent->next)
1090 {
1091 if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
1092 return &ent->leaf;
1093 }
1094
1095 ent = FcCharLeafEntCreate(freezer);
1096 if (!ent)
1097 return 0;
1098 ent->leaf = *leaf;
1099 ent->hash = hash;
1100 ent->next = *bucket;
1101 *bucket = ent;
1102 return &ent->leaf;
1103}
1104
1105static FcChar32
1106FcCharSetHash (FcCharSet *fcs)
1107{
1108 FcChar32 hash = 0;
1109 int i;
1110
1111 /* hash in leaves */
1112 for (i = 0; i < fcs->num; i++)
1113 hash = ((hash << 1) | (hash >> 31)) ^ FcCharLeafHash (FcCharSetLeaf(fcs,i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[i]))))
);
1114 /* hash in numbers */
1115 for (i = 0; i < fcs->num; i++)
1116 hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
;
1117 return hash;
1118}
1119
1120static FcBool
1121FcCharSetFreezeOrig (FcCharSetFreezer *freezer, const FcCharSet *orig, const FcCharSet *frozen)
1122{
1123 FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE67];
1124 FcCharSetOrigEnt *ent;
1125
1126 ent = malloc (sizeof (FcCharSetOrigEnt));
1127 if (!ent)
1128 return FcFalse0;
1129 ent->orig = orig;
1130 ent->frozen = frozen;
1131 ent->next = *bucket;
1132 *bucket = ent;
1133 return FcTrue1;
1134}
1135
1136static FcCharSet *
1137FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs)
1138{
1139 FcChar32 hash = FcCharSetHash (fcs);
1140 FcCharSetEnt **bucket = &freezer->set_hash_table[hash % FC_CHAR_SET_HASH_SIZE67];
1141 FcCharSetEnt *ent;
1142 int size;
1143 int i;
1144
1145 for (ent = *bucket; ent; ent = ent->next)
1146 {
1147 if (ent->hash == hash &&
1148 ent->set.num == fcs->num &&
1149 !memcmp (FcCharSetNumbers(&ent->set)((FcChar16 *) ((intptr_t) (&ent->set) + ((&ent->
set)->numbers_offset)))
,
1150 FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
,
1151 fcs->num * sizeof (FcChar16)))
1152 {
1153 FcBool ok = FcTrue1;
1154 int i;
1155
1156 for (i = 0; i < fcs->num; i++)
1157 if (FcCharSetLeaf(&ent->set, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (&
ent->set) + ((&ent->set)->leaves_offset)))) + ((
(intptr_t *) ((intptr_t) (&ent->set) + ((&ent->
set)->leaves_offset)))[i]))))
!= FcCharSetLeaf(fcs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[i]))))
)
1158 ok = FcFalse0;
1159 if (ok)
1160 return &ent->set;
1161 }
1162 }
1163
1164 size = (sizeof (FcCharSetEnt) +
1165 fcs->num * sizeof (FcCharLeaf *) +
1166 fcs->num * sizeof (FcChar16));
1167 ent = malloc (size);
1168 if (!ent)
1169 return 0;
1170
1171 freezer->charsets_allocated++;
1172
1173 FcRefSetConst (&ent->set.ref);
1174 ent->set.num = fcs->num;
1175 if (fcs->num)
1176 {
1177 intptr_t *ent_leaves;
1178
1179 ent->set.leaves_offset = sizeof (ent->set);
1180 ent->set.numbers_offset = (ent->set.leaves_offset +
1181 fcs->num * sizeof (intptr_t));
1182
1183 ent_leaves = FcCharSetLeaves (&ent->set)((intptr_t *) ((intptr_t) (&ent->set) + ((&ent->
set)->leaves_offset)))
;
1184 for (i = 0; i < fcs->num; i++)
1185 ent_leaves[i] = FcPtrToOffset (ent_leaves,((intptr_t) ((((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t
) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t
) (fcs) + ((fcs)->leaves_offset)))[i]))))) - (intptr_t) (ent_leaves
))
1186 FcCharSetLeaf (fcs, i))((intptr_t) ((((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t
) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t
) (fcs) + ((fcs)->leaves_offset)))[i]))))) - (intptr_t) (ent_leaves
))
;
1187 memcpy (FcCharSetNumbers (&ent->set),__builtin___memcpy_chk (((FcChar16 *) ((intptr_t) (&ent->
set) + ((&ent->set)->numbers_offset))), ((FcChar16 *
) ((intptr_t) (fcs) + ((fcs)->numbers_offset))), fcs->num
* sizeof (FcChar16), __builtin_object_size (((FcChar16 *) ((
intptr_t) (&ent->set) + ((&ent->set)->numbers_offset
))), 0))
1188 FcCharSetNumbers (fcs),__builtin___memcpy_chk (((FcChar16 *) ((intptr_t) (&ent->
set) + ((&ent->set)->numbers_offset))), ((FcChar16 *
) ((intptr_t) (fcs) + ((fcs)->numbers_offset))), fcs->num
* sizeof (FcChar16), __builtin_object_size (((FcChar16 *) ((
intptr_t) (&ent->set) + ((&ent->set)->numbers_offset
))), 0))
1189 fcs->num * sizeof (FcChar16))__builtin___memcpy_chk (((FcChar16 *) ((intptr_t) (&ent->
set) + ((&ent->set)->numbers_offset))), ((FcChar16 *
) ((intptr_t) (fcs) + ((fcs)->numbers_offset))), fcs->num
* sizeof (FcChar16), __builtin_object_size (((FcChar16 *) ((
intptr_t) (&ent->set) + ((&ent->set)->numbers_offset
))), 0))
;
1190 }
1191 else
1192 {
1193 ent->set.leaves_offset = 0;
1194 ent->set.numbers_offset = 0;
1195 }
1196
1197 ent->hash = hash;
1198 ent->next = *bucket;
1199 *bucket = ent;
1200
1201 return &ent->set;
1202}
1203
1204static const FcCharSet *
1205FcCharSetFindFrozen (FcCharSetFreezer *freezer, const FcCharSet *orig)
1206{
1207 FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE67];
1208 FcCharSetOrigEnt *ent;
1209
1210 for (ent = *bucket; ent; ent = ent->next)
1211 if (ent->orig == orig)
1212 return ent->frozen;
1213 return NULL((void*)0);
1214}
1215
1216const FcCharSet *
1217FcCharSetFreeze (FcCharSetFreezer *freezer, const FcCharSet *fcs)
1218{
1219 FcCharSet *b;
1220 const FcCharSet *n = 0;
1221 FcCharLeaf *l;
1222 int i;
1223
1224 b = FcCharSetCreate ();
1225 if (!b)
5
Taking false branch
1226 goto bail0;
1227 for (i = 0; i < fcs->num; i++)
6
Loop condition is true. Entering loop body
1228 {
1229 l = FcCharSetFreezeLeaf (freezer, FcCharSetLeaf(fcs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs)
+ ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (
fcs) + ((fcs)->leaves_offset)))[i]))))
);
1230 if (!l)
7
Assuming 'l' is non-null
8
Taking false branch
1231 goto bail1;
1232 if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset))
)
[i] << 8, l)
)
9
Calling 'FcCharSetInsertLeaf'
1233 goto bail1;
1234 }
1235 n = FcCharSetFreezeBase (freezer, b);
1236 if (!FcCharSetFreezeOrig (freezer, fcs, n))
1237 {
1238 n = NULL((void*)0);
1239 goto bail1;
1240 }
1241 freezer->charsets_seen++;
1242 freezer->leaves_seen += fcs->num;
1243bail1:
1244 if (b->num)
1245 free (FcCharSetLeaves (b)((intptr_t *) ((intptr_t) (b) + ((b)->leaves_offset))));
1246 if (b->num)
1247 free (FcCharSetNumbers (b)((FcChar16 *) ((intptr_t) (b) + ((b)->numbers_offset))));
1248 free (b);
1249bail0:
1250 return n;
1251}
1252
1253FcCharSetFreezer *
1254FcCharSetFreezerCreate (void)
1255{
1256 FcCharSetFreezer *freezer;
1257
1258 freezer = calloc (1, sizeof (FcCharSetFreezer));
1259 return freezer;
1260}
1261
1262void
1263FcCharSetFreezerDestroy (FcCharSetFreezer *freezer)
1264{
1265 int i;
1266
1267 if (FcDebug()(FcDebugVal) & FC_DBG_CACHE16)
1268 {
1269 printf ("\ncharsets %d -> %d leaves %d -> %d\n",
1270 freezer->charsets_seen, freezer->charsets_allocated,
1271 freezer->leaves_seen, freezer->leaves_allocated);
1272 }
1273 for (i = 0; i < FC_CHAR_SET_HASH_SIZE67; i++)
1274 {
1275 FcCharSetEnt *ent, *next;
1276 for (ent = freezer->set_hash_table[i]; ent; ent = next)
1277 {
1278 next = ent->next;
1279 free (ent);
1280 }
1281 }
1282
1283 for (i = 0; i < FC_CHAR_SET_HASH_SIZE67; i++)
1284 {
1285 FcCharSetOrigEnt *ent, *next;
1286 for (ent = freezer->orig_hash_table[i]; ent; ent = next)
1287 {
1288 next = ent->next;
1289 free (ent);
1290 }
1291 }
1292
1293 for (i = 0; i < freezer->leaf_block_count; i++)
1294 free (freezer->leaf_blocks[i]);
1295
1296 free (freezer->leaf_blocks);
1297 free (freezer);
1298}
1299
1300FcBool
1301FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
1302{
1303 intptr_t *leaves;
1304 FcChar16 *numbers;
1305 int i;
1306
1307 if (!FcRefIsConst (&cs->ref))
1
Taking true branch
1308 {
1309 if (!serialize->cs_freezer)
2
Taking false branch
1310 {
1311 serialize->cs_freezer = FcCharSetFreezerCreate ();
1312 if (!serialize->cs_freezer)
1313 return FcFalse0;
1314 }
1315 if (FcCharSetFindFrozen (serialize->cs_freezer, cs))
3
Taking false branch
1316 return FcTrue1;
1317
1318 cs = FcCharSetFreeze (serialize->cs_freezer, cs);
4
Calling 'FcCharSetFreeze'
1319 }
1320
1321 leaves = FcCharSetLeaves (cs)((intptr_t *) ((intptr_t) (cs) + ((cs)->leaves_offset)));
1322 numbers = FcCharSetNumbers (cs)((FcChar16 *) ((intptr_t) (cs) + ((cs)->numbers_offset)));
1323
1324 if (!FcSerializeAlloc (serialize, cs, sizeof (FcCharSet)))
1325 return FcFalse0;
1326 if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t)))
1327 return FcFalse0;
1328 if (!FcSerializeAlloc (serialize, numbers, cs->num * sizeof (FcChar16)))
1329 return FcFalse0;
1330 for (i = 0; i < cs->num; i++)
1331 if (!FcSerializeAlloc (serialize, FcCharSetLeaf(cs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (cs) +
((cs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (cs
) + ((cs)->leaves_offset)))[i]))))
,
1332 sizeof (FcCharLeaf)))
1333 return FcFalse0;
1334 return FcTrue1;
1335}
1336
1337FcCharSet *
1338FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
1339{
1340 FcCharSet *cs_serialized;
1341 intptr_t *leaves, *leaves_serialized;
1342 FcChar16 *numbers, *numbers_serialized;
1343 FcCharLeaf *leaf, *leaf_serialized;
1344 int i;
1345
1346 if (!FcRefIsConst (&cs->ref) && serialize->cs_freezer)
1347 {
1348 cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
1349 if (!cs)
1350 return NULL((void*)0);
1351 }
1352
1353 cs_serialized = FcSerializePtr (serialize, cs);
1354 if (!cs_serialized)
1355 return NULL((void*)0);
1356
1357 FcRefSetConst (&cs_serialized->ref);
1358 cs_serialized->num = cs->num;
1359
1360 if (cs->num)
1361 {
1362 leaves = FcCharSetLeaves (cs)((intptr_t *) ((intptr_t) (cs) + ((cs)->leaves_offset)));
1363 leaves_serialized = FcSerializePtr (serialize, leaves);
1364 if (!leaves_serialized)
1365 return NULL((void*)0);
1366
1367 cs_serialized->leaves_offset = FcPtrToOffset (cs_serialized,((intptr_t) (leaves_serialized) - (intptr_t) (cs_serialized))
1368 leaves_serialized)((intptr_t) (leaves_serialized) - (intptr_t) (cs_serialized));
1369
1370 numbers = FcCharSetNumbers (cs)((FcChar16 *) ((intptr_t) (cs) + ((cs)->numbers_offset)));
1371 numbers_serialized = FcSerializePtr (serialize, numbers);
1372 if (!numbers)
1373 return NULL((void*)0);
1374
1375 cs_serialized->numbers_offset = FcPtrToOffset (cs_serialized,((intptr_t) (numbers_serialized) - (intptr_t) (cs_serialized)
)
1376 numbers_serialized)((intptr_t) (numbers_serialized) - (intptr_t) (cs_serialized)
)
;
1377
1378 for (i = 0; i < cs->num; i++)
1379 {
1380 leaf = FcCharSetLeaf (cs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (cs) +
((cs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (cs
) + ((cs)->leaves_offset)))[i]))))
;
1381 leaf_serialized = FcSerializePtr (serialize, leaf);
1382 if (!leaf_serialized)
1383 return NULL((void*)0);
1384 *leaf_serialized = *leaf;
1385 leaves_serialized[i] = FcPtrToOffset (leaves_serialized,((intptr_t) (leaf_serialized) - (intptr_t) (leaves_serialized
))
1386 leaf_serialized)((intptr_t) (leaf_serialized) - (intptr_t) (leaves_serialized
))
;
1387 numbers_serialized[i] = numbers[i];
1388 }
1389 }
1390 else
1391 {
1392 cs_serialized->leaves_offset = 0;
1393 cs_serialized->numbers_offset = 0;
1394 }
1395
1396 return cs_serialized;
1397}
1398#define __fccharset__
1399#include "fcaliastail.h"
1400#undef __fccharset__