2 * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
4 * Copyright © 2000 Keith Packard
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 Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD 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.
31 static FcPattern
* fcpatterns
= NULL
;
32 static int fcpattern_ptr
, fcpattern_count
;
33 static FcPatternElt
* fcpatternelts
= NULL
;
34 static int fcpatternelt_ptr
, fcpatternelt_count
;
35 static FcValueList
* fcvaluelists
= NULL
;
36 static int fcvaluelist_ptr
, fcvaluelist_count
;
39 FcPatternEltIsDynamic (FcPatternEltPtr pei
);
41 static FcPatternEltPtr
42 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
);
45 FcPatternCreate (void)
49 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
52 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
55 p
->elts
= FcPatternEltPtrCreateDynamic(0);
61 FcValueDestroy (FcValue v
)
65 FcObjectPtrDestroy (v
.u
.si
);
68 FcMatrixPtrDestroy (v
.u
.mi
);
71 FcCharSetPtrDestroy (v
.u
.ci
);
74 FcLangSetPtrDestroy (v
.u
.li
);
82 FcValueSave (FcValue v
)
86 v
.u
.si
= FcObjectStaticName(FcObjectPtrU(v
.u
.si
));
87 if (!FcObjectPtrU(v
.u
.si
))
91 v
.u
.mi
= FcMatrixPtrCreateDynamic
92 (FcMatrixCopy (FcMatrixPtrU(v
.u
.mi
)));
93 if (!FcMatrixPtrU(v
.u
.mi
))
97 v
.u
.ci
= FcCharSetCopyPtr (v
.u
.ci
);
98 if (!FcCharSetPtrU(v
.u
.ci
))
102 v
.u
.li
= FcLangSetPtrCreateDynamic
103 (FcLangSetCopy (FcLangSetPtrU(v
.u
.li
)));
104 if (!FcLangSetPtrU(v
.u
.li
))
114 FcValueListDestroy (FcValueListPtr l
)
117 for (; FcValueListPtrU(l
); l
= next
)
119 switch (FcValueListPtrU(l
)->value
.type
) {
121 FcObjectPtrDestroy (FcValueListPtrU(l
)->value
.u
.si
);
124 FcMatrixPtrDestroy (FcValueListPtrU(l
)->value
.u
.mi
);
128 (FcCharSetPtrU (FcValueListPtrU(l
)->value
.u
.ci
));
132 (FcLangSetPtrU (FcValueListPtrU(l
)->value
.u
.li
));
137 next
= FcValueListPtrU(l
)->next
;
139 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
140 if (l
.storage
== FcStorageDynamic
)
146 FcValueEqual (FcValue va
, FcValue vb
)
148 if (va
.type
!= vb
.type
)
150 if (va
.type
== FcTypeInteger
)
152 va
.type
= FcTypeDouble
;
155 if (vb
.type
== FcTypeInteger
)
157 vb
.type
= FcTypeDouble
;
160 if (va
.type
!= vb
.type
)
167 return va
.u
.i
== vb
.u
.i
;
169 return va
.u
.d
== vb
.u
.d
;
171 return FcStrCmpIgnoreCase (FcObjectPtrU(va
.u
.si
),
172 FcObjectPtrU(vb
.u
.si
)) == 0;
174 return va
.u
.b
== vb
.u
.b
;
176 return FcMatrixEqual (FcMatrixPtrU(va
.u
.mi
),
177 FcMatrixPtrU(vb
.u
.mi
));
179 return FcCharSetEqual (FcCharSetPtrU(va
.u
.ci
),
180 FcCharSetPtrU(vb
.u
.ci
));
182 return va
.u
.f
== vb
.u
.f
;
184 return FcLangSetEqual (FcLangSetPtrU(va
.u
.li
),
185 FcLangSetPtrU(vb
.u
.li
));
191 FcDoubleHash (double d
)
201 FcStringHash (const FcChar8
*s
)
208 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
213 FcValueHash (FcValue v
)
219 return (FcChar32
) v
.u
.i
;
221 return FcDoubleHash (v
.u
.d
);
223 return FcStringHash (FcObjectPtrU(v
.u
.si
));
225 return (FcChar32
) v
.u
.b
;
228 FcMatrix
* m
= FcMatrixPtrU(v
.u
.mi
);
229 return (FcDoubleHash (m
->xx
) ^
230 FcDoubleHash (m
->xy
) ^
231 FcDoubleHash (m
->yx
) ^
232 FcDoubleHash (m
->yy
));
235 return (FcChar32
) (FcCharSetPtrU(v
.u
.ci
))->num
;
237 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
238 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
240 return FcLangSetHash (FcLangSetPtrU(v
.u
.li
));
246 FcValueListEqual (FcValueListPtr la
, FcValueListPtr lb
)
248 if (FcValueListPtrU(la
) == FcValueListPtrU(lb
))
251 while (FcValueListPtrU(la
) && FcValueListPtrU(lb
))
253 if (!FcValueEqual (FcValueListPtrU(la
)->value
,
254 FcValueListPtrU(lb
)->value
))
256 la
= FcValueListPtrU(la
)->next
;
257 lb
= FcValueListPtrU(lb
)->next
;
259 if (FcValueListPtrU(la
) || FcValueListPtrU(lb
))
265 FcValueListHash (FcValueListPtr l
)
269 while (FcValueListPtrU(l
))
271 hash
= ((hash
<< 1) | (hash
>> 31)) ^
272 FcValueHash (FcValueListPtrU(l
)->value
);
273 l
= FcValueListPtrU(l
)->next
;
279 FcPatternDestroy (FcPattern
*p
)
283 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
286 for (i
= 0; i
< p
->num
; i
++)
287 FcValueListDestroy ((FcPatternEltU(p
->elts
)+i
)->values
);
290 if (FcPatternEltU(p
->elts
) && FcPatternEltIsDynamic(p
->elts
))
292 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
293 free (FcPatternEltU(p
->elts
));
294 p
->elts
= FcPatternEltPtrCreateDynamic(0);
297 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
301 #define FC_VALUE_LIST_HASH_SIZE 257
302 #define FC_PATTERN_HASH_SIZE 67
304 typedef struct _FcValueListEnt FcValueListEnt
;
306 struct _FcValueListEnt
{
307 FcValueListEnt
*next
;
312 typedef union _FcValueListAlign
{
317 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
318 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
319 static char *FcValueListFrozenName
[] = {
332 FcValueListReport (void);
335 FcValueListReport (void)
339 printf ("Fc Frozen Values:\n");
340 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
341 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
342 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
343 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
346 static FcValueListEnt
*
347 FcValueListEntCreate (FcValueListPtr h
)
349 FcValueListAlign
*ea
;
357 for (l
= h
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
359 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
360 FcValueListFrozenCount
[FcValueListPtrU(h
)->value
.type
]++;
361 FcValueListFrozenBytes
[FcValueListPtrU(h
)->value
.type
] += size
;
362 // this leaks for some reason
363 ea
= malloc (sizeof (FcValueListAlign
));
366 new = malloc (n
* sizeof (FcValueList
));
369 memset(new, 0, n
* sizeof (FcValueList
));
370 FcMemAlloc (FC_MEM_VALLIST
, size
);
372 e
->list
= (FcValueListPtr
) FcValueListPtrCreateDynamic(new);
373 for (l
= h
; FcValueListPtrU(l
);
374 l
= FcValueListPtrU(l
)->next
, new++)
376 if (FcValueListPtrU(l
)->value
.type
== FcTypeString
)
378 new->value
.type
= FcTypeString
;
379 new->value
.u
.si
= FcObjectStaticName
380 (FcObjectPtrU(FcValueListPtrU(l
)->value
.u
.si
));
384 new->value
= FcValueSave (FcValueListPtrU(l
)->value
);
386 new->binding
= FcValueListPtrU(l
)->binding
;
387 if (FcValueListPtrU(FcValueListPtrU(l
)->next
))
389 new->next
= FcValueListPtrCreateDynamic(new + 1);
393 new->next
= FcValueListPtrCreateDynamic(0);
400 FcValueListEntDestroy (FcValueListEnt
*e
)
404 FcValueListFrozenCount
[FcValueListPtrU(e
->list
)->value
.type
]--;
406 /* XXX: We should perform these two operations with "size" as
407 computed in FcValueListEntCreate, but we don't have access to
408 that value here. Without this, the FcValueListFrozenBytes
409 values will be wrong as will the FcMemFree counts.
411 FcValueListFrozenBytes[e->list->value.type] -= size;
412 FcMemFree (FC_MEM_VALLIST, size);
415 for (l
= e
->list
; FcValueListPtrU(l
);
416 l
= FcValueListPtrU(l
)->next
)
418 if (FcValueListPtrU(l
)->value
.type
!= FcTypeString
)
419 FcValueDestroy (FcValueListPtrU(l
)->value
);
421 /* XXX: Are we being too chummy with the implementation here to
422 free(e) when it was actually the enclosing FcValueListAlign
423 that was allocated? */
427 static int FcValueListTotal
;
428 static int FcValueListUsed
;
430 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
432 static FcValueListPtr
433 FcValueListFreeze (FcValueListPtr l
)
435 FcChar32 hash
= FcValueListHash (l
);
436 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
440 for (ent
= *bucket
; ent
; ent
= ent
->next
)
442 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
446 ent
= FcValueListEntCreate (l
);
448 return FcValueListPtrCreateDynamic(0);
458 FcValueListThawAll (void)
461 FcValueListEnt
*ent
, *next
;
463 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
465 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
468 FcValueListEntDestroy (ent
);
470 FcValueListHashTable
[i
] = 0;
473 FcValueListTotal
= 0;
478 FcPatternBaseHash (FcPattern
*b
)
480 FcChar32 hash
= b
->num
;
483 for (i
= 0; i
< b
->num
; i
++)
484 hash
= ((hash
<< 1) | (hash
>> 31)) ^
485 (long) (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
));
489 typedef struct _FcPatternEnt FcPatternEnt
;
491 struct _FcPatternEnt
{
497 static int FcPatternTotal
;
498 static int FcPatternUsed
;
500 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
503 FcPatternBaseFreeze (FcPattern
*b
)
507 FcChar32 hash
= FcPatternBaseHash (b
);
508 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
513 for (ent
= *bucket
; ent
; ent
= ent
->next
)
515 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
->num
)
517 for (i
= 0; i
< b
->num
; i
++)
519 if (FcObjectPtrCompare((FcPatternEltU(b
->elts
)+i
)->object
,
520 (FcPatternEltU(ent
->pattern
->elts
)+i
)->object
) != 0)
522 if (FcValueListPtrU((FcPatternEltU(b
->elts
)+i
)->values
) !=
523 FcValueListPtrU((FcPatternEltU(ent
->pattern
->elts
)+i
)->values
))
532 * Compute size of pattern + elts
534 ent
= malloc (sizeof (FcPatternEnt
));
538 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
541 ep
= FcPatternCreate();
545 epp
= malloc(b
->num
* sizeof (FcPatternElt
));
548 ep
->elts
= FcPatternEltPtrCreateDynamic(epp
);
550 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
554 ep
->ref
= FC_REF_CONSTANT
;
556 for (i
= 0; i
< b
->num
; i
++)
558 (FcPatternEltU(ep
->elts
)+i
)->values
=
559 (FcPatternEltU(b
->elts
)+i
)->values
;
560 (FcPatternEltU(ep
->elts
)+i
)->object
=
561 (FcPatternEltU(b
->elts
)+i
)->object
;
570 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPatternEnt
));
576 FcPatternBaseThawAll (void)
579 FcPatternEnt
*ent
, *next
;
581 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
583 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
588 FcPatternHashTable
[i
] = 0;
596 FcPatternFreeze (FcPattern
*p
)
598 FcPattern
*b
, *n
= 0;
602 if (p
->ref
== FC_REF_CONSTANT
)
605 b
= FcPatternCreate();
613 e
= malloc(b
->num
* sizeof (FcPatternElt
));
616 b
->elts
= FcPatternEltPtrCreateDynamic(e
);
617 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
620 * Freeze object lists
622 for (i
= 0; i
< p
->num
; i
++)
624 (FcPatternEltU(b
->elts
)+i
)->object
=
625 (FcPatternEltU(p
->elts
)+i
)->object
;
626 (FcPatternEltU(b
->elts
)+i
)->values
=
627 FcValueListFreeze((FcPatternEltU(p
->elts
)+i
)->values
);
628 if (!FcValueListPtrU((FcPatternEltU(p
->elts
)+i
)->values
))
634 n
= FcPatternBaseFreeze (b
);
636 if (FcDebug() & FC_DBG_MEMORY
)
638 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
639 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
643 free(FcPatternEltU(b
->elts
));
644 b
->elts
= FcPatternEltPtrCreateDynamic(0);
645 FcMemFree (FC_MEM_PATELT
, sizeof (FcPatternElt
)*(b
->num
));
648 assert (FcPatternEqual (n
, p
));
654 FcPatternPosition (const FcPattern
*p
, const char *object
)
656 int low
, high
, mid
, c
;
659 obj
= FcObjectStaticName(object
);
666 mid
= (low
+ high
) >> 1;
667 c
= FcObjectPtrCompare((FcPatternEltU(p
->elts
)+mid
)->object
, obj
);
681 FcPatternFindElt (const FcPattern
*p
, const char *object
)
683 int i
= FcPatternPosition (p
, object
);
686 return FcPatternEltU(p
->elts
)+i
;
690 FcPatternInsertElt (FcPattern
*p
, const char *object
)
695 i
= FcPatternPosition (p
, object
);
700 /* reallocate array */
701 if (p
->num
+ 1 >= p
->size
)
703 int s
= p
->size
+ 16;
704 if (FcPatternEltU(p
->elts
))
706 FcPatternElt
*e0
= FcPatternEltU(p
->elts
);
707 e
= (FcPatternElt
*) realloc (e0
, s
* sizeof (FcPatternElt
));
708 if (!e
) /* maybe it was mmapped */
710 e
= malloc(s
* sizeof (FcPatternElt
));
712 memcpy(e
, e0
, p
->num
* sizeof (FcPatternElt
));
716 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
719 p
->elts
= FcPatternEltPtrCreateDynamic(e
);
721 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
722 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
725 (FcPatternEltU(p
->elts
)+p
->size
)->object
= 0;
726 (FcPatternEltU(p
->elts
)+p
->size
)->values
=
727 FcValueListPtrCreateDynamic(0);
733 memmove (FcPatternEltU(p
->elts
) + i
+ 1,
734 FcPatternEltU(p
->elts
) + i
,
735 sizeof (FcPatternElt
) *
741 (FcPatternEltU(p
->elts
)+i
)->object
= FcObjectStaticName (object
);
742 (FcPatternEltU(p
->elts
)+i
)->values
= FcValueListPtrCreateDynamic(0);
745 return FcPatternEltU(p
->elts
)+i
;
749 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
756 if (pa
->num
!= pb
->num
)
758 for (i
= 0; i
< pa
->num
; i
++)
760 if (FcObjectPtrCompare((FcPatternEltU(pa
->elts
)+i
)->object
,
761 (FcPatternEltU(pb
->elts
)+i
)->object
) != 0)
763 if (!FcValueListEqual ((FcPatternEltU(pa
->elts
)+i
)->values
,
764 (FcPatternEltU(pb
->elts
)+i
)->values
))
771 FcPatternHash (const FcPattern
*p
)
776 for (i
= 0; i
< p
->num
; i
++)
778 h
= (((h
<< 1) | (h
>> 31)) ^
779 FcStringHash ((const FcChar8
*) FcObjectPtrU(((FcPatternEltU(p
->elts
)+i
)->object
))) ^
780 FcValueListHash ((FcPatternEltU(p
->elts
)+i
)->values
));
786 FcPatternEqualSubset (const FcPattern
*pai
, const FcPattern
*pbi
, const FcObjectSet
*os
)
788 FcPatternElt
*ea
, *eb
;
791 for (i
= 0; i
< os
->nobject
; i
++)
793 ea
= FcPatternFindElt (pai
, FcObjectPtrU(os
->objects
[i
]));
794 eb
= FcPatternFindElt (pbi
, FcObjectPtrU(os
->objects
[i
]));
799 if (!FcValueListEqual (ea
->values
, eb
->values
))
812 FcPatternAddWithBinding (FcPattern
*p
,
815 FcValueBinding binding
,
819 FcValueListPtr
new, *prev
;
822 if (p
->ref
== FC_REF_CONSTANT
)
825 newp
= malloc (sizeof (FcValueList
));
829 memset(newp
, 0, sizeof (FcValueList
));
830 new = FcValueListPtrCreateDynamic(newp
);
831 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
833 value
= FcValueSave (value
);
834 if (value
.type
== FcTypeVoid
)
837 FcValueListPtrU(new)->value
= value
;
838 FcValueListPtrU(new)->binding
= binding
;
839 FcValueListPtrU(new)->next
= FcValueListPtrCreateDynamic(0);
841 e
= FcPatternInsertElt (p
, object
);
847 for (prev
= &e
->values
; FcValueListPtrU(*prev
); prev
= &FcValueListPtrU(*prev
)->next
)
853 FcValueListPtrU(new)->next
= e
->values
;
860 switch (value
.type
) {
862 FcStrFree ((FcChar8
*) FcObjectPtrU(value
.u
.si
));
865 FcMatrixFree (FcMatrixPtrU(value
.u
.mi
));
868 FcCharSetDestroy (FcCharSetPtrU(value
.u
.ci
));
871 FcLangSetDestroy (FcLangSetPtrU(value
.u
.li
));
877 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
878 free (FcValueListPtrU(new));
884 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
886 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
890 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
892 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
896 FcPatternDel (FcPattern
*p
, const char *object
)
900 e
= FcPatternFindElt (p
, object
);
905 FcValueListDestroy (e
->values
);
907 /* shuffle existing ones down */
909 (FcPatternEltU(p
->elts
) + p
->num
- (e
+ 1)) *
910 sizeof (FcPatternElt
));
912 (FcPatternEltU(p
->elts
)+p
->num
)->object
= 0;
913 (FcPatternEltU(p
->elts
)+p
->num
)->values
= FcValueListPtrCreateDynamic(0);
918 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
921 FcValueListPtr
*prev
, l
;
923 e
= FcPatternFindElt (p
, object
);
926 for (prev
= &e
->values
;
927 FcValueListPtrU(l
= *prev
);
928 prev
= &FcValueListPtrU(l
)->next
)
932 *prev
= FcValueListPtrU(l
)->next
;
933 FcValueListPtrU(l
)->next
= FcValueListPtrCreateDynamic(0);
934 FcValueListDestroy (l
);
935 if (!FcValueListPtrU(e
->values
))
936 FcPatternDel (p
, object
);
945 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
949 v
.type
= FcTypeInteger
;
951 return FcPatternAdd (p
, object
, v
, FcTrue
);
955 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
959 v
.type
= FcTypeDouble
;
961 return FcPatternAdd (p
, object
, v
, FcTrue
);
966 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
970 v
.type
= FcTypeString
;
971 v
.u
.si
= FcObjectStaticName(s
);
972 return FcPatternAdd (p
, object
, v
, FcTrue
);
976 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
980 v
.type
= FcTypeMatrix
;
981 v
.u
.mi
= FcMatrixPtrCreateDynamic((FcMatrix
*) s
);
982 return FcPatternAdd (p
, object
, v
, FcTrue
);
987 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
993 return FcPatternAdd (p
, object
, v
, FcTrue
);
997 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
1001 v
.type
= FcTypeCharSet
;
1002 v
.u
.ci
= FcCharSetPtrCreateDynamic((FcCharSet
*)c
);
1003 return FcPatternAdd (p
, object
, v
, FcTrue
);
1007 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
1011 v
.type
= FcTypeFTFace
;
1013 return FcPatternAdd (p
, object
, v
, FcTrue
);
1017 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
1021 v
.type
= FcTypeLangSet
;
1022 v
.u
.li
= FcLangSetPtrCreateDynamic((FcLangSet
*)ls
);
1023 return FcPatternAdd (p
, object
, v
, FcTrue
);
1027 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
1032 e
= FcPatternFindElt (p
, object
);
1034 return FcResultNoMatch
;
1035 for (l
= e
->values
; FcValueListPtrU(l
); l
= FcValueListPtrU(l
)->next
)
1039 *v
= FcValueListPtrU(l
)->value
;
1040 return FcResultMatch
;
1044 return FcResultNoId
;
1048 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
1053 r
= FcPatternGet (p
, object
, id
, &v
);
1054 if (r
!= FcResultMatch
)
1064 return FcResultTypeMismatch
;
1066 return FcResultMatch
;
1070 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1075 r
= FcPatternGet (p
, object
, id
, &v
);
1076 if (r
!= FcResultMatch
)
1083 *d
= (double) v
.u
.i
;
1086 return FcResultTypeMismatch
;
1088 return FcResultMatch
;
1092 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1097 r
= FcPatternGet (p
, object
, id
, &v
);
1098 if (r
!= FcResultMatch
)
1100 if (v
.type
!= FcTypeString
)
1101 return FcResultTypeMismatch
;
1102 *s
= (FcChar8
*) FcObjectPtrU(v
.u
.si
);
1103 return FcResultMatch
;
1107 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1112 r
= FcPatternGet (p
, object
, id
, &v
);
1113 if (r
!= FcResultMatch
)
1115 if (v
.type
!= FcTypeMatrix
)
1116 return FcResultTypeMismatch
;
1117 *m
= FcMatrixPtrU(v
.u
.mi
);
1118 return FcResultMatch
;
1123 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1128 r
= FcPatternGet (p
, object
, id
, &v
);
1129 if (r
!= FcResultMatch
)
1131 if (v
.type
!= FcTypeBool
)
1132 return FcResultTypeMismatch
;
1134 return FcResultMatch
;
1138 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1143 r
= FcPatternGet (p
, object
, id
, &v
);
1144 if (r
!= FcResultMatch
)
1146 if (v
.type
!= FcTypeCharSet
)
1147 return FcResultTypeMismatch
;
1148 *c
= FcCharSetPtrU(v
.u
.ci
);
1149 return FcResultMatch
;
1153 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1158 r
= FcPatternGet (p
, object
, id
, &v
);
1159 if (r
!= FcResultMatch
)
1161 if (v
.type
!= FcTypeFTFace
)
1162 return FcResultTypeMismatch
;
1163 *f
= (FT_Face
) v
.u
.f
;
1164 return FcResultMatch
;
1168 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1173 r
= FcPatternGet (p
, object
, id
, &v
);
1174 if (r
!= FcResultMatch
)
1176 if (v
.type
!= FcTypeLangSet
)
1177 return FcResultTypeMismatch
;
1178 *ls
= FcLangSetPtrU(v
.u
.li
);
1179 return FcResultMatch
;
1183 FcPatternDuplicate (const FcPattern
*orig
)
1190 new = FcPatternCreate ();
1194 e
= FcPatternEltU(orig
->elts
);
1196 for (i
= 0; i
< orig
->num
; i
++)
1198 for (l
= (e
+ i
)->values
;
1200 l
= FcValueListPtrU(l
)->next
)
1201 if (!FcPatternAdd (new, FcObjectPtrU((e
+ i
)->object
),
1202 FcValueListPtrU(l
)->value
, FcTrue
))
1209 FcPatternDestroy (new);
1215 FcPatternReference (FcPattern
*p
)
1217 if (p
->ref
!= FC_REF_CONSTANT
)
1222 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1226 FcPatternVapBuild (ret
, orig
, va
);
1231 FcPatternBuild (FcPattern
*orig
, ...)
1235 va_start (va
, orig
);
1236 FcPatternVapBuild (orig
, orig
, va
);
1242 * Add all of the elements in 's' to 'p'
1245 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1251 for (i
= 0; i
< s
->num
; i
++)
1253 e
= FcPatternEltU(s
->elts
)+i
;
1254 for (v
= e
->values
; FcValueListPtrU(v
);
1255 v
= FcValueListPtrU(v
)->next
)
1257 if (!FcPatternAddWithBinding (p
, FcObjectPtrU(e
->object
),
1258 FcValueListPtrU(v
)->value
,
1259 FcValueListPtrU(v
)->binding
, FcTrue
))
1267 FcPatternEltU (FcPatternEltPtr pei
)
1269 switch (pei
.storage
)
1271 case FcStorageStatic
:
1272 return &fcpatternelts
[pei
.u
.stat
];
1273 case FcStorageDynamic
:
1280 static FcPatternEltPtr
1281 FcPatternEltPtrCreateDynamic (FcPatternElt
* e
)
1283 FcPatternEltPtr
new;
1284 new.storage
= FcStorageDynamic
;
1289 static FcPatternEltPtr
1290 FcPatternEltPtrCreateStatic (int i
)
1292 FcPatternEltPtr
new;
1293 new.storage
= FcStorageStatic
;
1299 FcPatternEltIsDynamic (FcPatternEltPtr pei
)
1301 return pei
.storage
== FcStorageDynamic
;
1306 FcPatternClearStatic (void)
1310 fcpattern_count
= 0;
1313 fcpatternelt_ptr
= 0;
1314 fcpatternelt_count
= 0;
1318 FcValueListClearStatic (void)
1321 fcvaluelist_ptr
= 0;
1322 fcvaluelist_count
= 0;
1326 FcObjectPrepareSerialize (FcObjectPtr si
);
1328 FcObjectSerialize (FcObjectPtr si
);
1331 FcPatternPrepareSerialize (FcPattern
* p
)
1336 fcpatternelt_count
+= p
->num
;
1338 for (i
= 0; i
< p
->num
; i
++)
1340 FcObjectPrepareSerialize
1341 ((FcPatternEltU(p
->elts
)+i
)->object
);
1342 if (!FcValueListPrepareSerialize
1343 (FcValueListPtrU(((FcPatternEltU(p
->elts
)+i
)->values
))))
1351 FcValueListPrepareSerialize (FcValueList
*p
)
1357 vl
= FcValueListPtrU(vl
->next
))
1359 FcValue v
= vl
->value
;
1364 FcMatrixPrepareSerialize(FcMatrixPtrU(v
.u
.mi
));
1367 FcCharSetPrepareSerialize(FcCharSetPtrU(v
.u
.ci
));
1370 FcLangSetPrepareSerialize(FcLangSetPtrU(v
.u
.li
));
1373 FcObjectPrepareSerialize(v
.u
.si
);
1377 fcvaluelist_count
++;
1384 FcPatternSerialize (FcPattern
*old
)
1387 FcPatternElt
*e
, *nep
;
1389 FcValueListPtr v
, nv_head
, nvp
;
1394 p
= malloc (sizeof (FcPattern
) * fcpattern_count
);
1398 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
) * fcpattern_count
);
1402 e
= malloc (sizeof (FcPatternElt
) * fcpatternelt_count
);
1406 FcMemAlloc (FC_MEM_PATELT
, sizeof (FcPatternElt
) * fcpatternelt_count
);
1408 fcpatternelt_ptr
= 0;
1411 p
= &fcpatterns
[fcpattern_ptr
++];
1412 elts
= fcpatternelt_ptr
;
1413 nep
= &fcpatternelts
[elts
];
1417 fcpatternelt_ptr
+= old
->num
;
1419 for (e
= FcPatternEltU(old
->elts
), i
=0; i
< old
->num
; i
++, e
++)
1422 nvp
= nv_head
= FcValueListSerialize(FcValueListPtrU(v
));
1423 if (!FcValueListPtrU(nv_head
))
1425 nv
= FcValueListPtrU(nvp
);
1429 v
= FcValueListPtrU(v
)->next
,
1430 nv
= FcValueListPtrU(nv
->next
))
1433 if (FcValueListPtrU(FcValueListPtrU(v
)->next
))
1435 nvp
= FcValueListSerialize
1436 (FcValueListPtrU(FcValueListPtrU(v
)->next
));
1441 nep
[i
].values
= nv_head
;
1442 nep
[i
].object
= FcObjectSerialize (e
->object
);
1445 p
->elts
= old
->elts
;
1446 p
->elts
= FcPatternEltPtrCreateStatic(elts
);
1449 p
->ref
= FC_REF_CONSTANT
;
1453 free (fcpatternelts
);
1461 FcPatternRead (int fd
, FcCache metadata
)
1463 fcpatterns
= mmap(NULL
,
1464 metadata
.pattern_length
* sizeof (FcPattern
),
1466 MAP_SHARED
, fd
, metadata
.pattern_offset
);
1467 if (fcpatterns
== MAP_FAILED
)
1469 fcpattern_count
= fcpattern_ptr
= metadata
.pattern_length
;
1475 FcPatternWrite (int fd
, FcCache
*metadata
)
1477 int c
= fcpattern_ptr
;
1478 off_t w
= FcCacheNextOffset(fd
);
1480 metadata
->pattern_offset
= w
;
1481 metadata
->pattern_length
= c
;
1485 lseek(fd
, w
, SEEK_SET
);
1486 return write(fd
, fcpatterns
, c
*sizeof(FcPattern
)) != -1;
1492 FcPatternEltRead (int fd
, FcCache metadata
)
1494 fcpatternelts
= mmap(NULL
,
1495 metadata
.patternelt_length
* sizeof (FcPatternElt
),
1497 MAP_SHARED
, fd
, metadata
.patternelt_offset
);
1498 if (fcpatternelts
== MAP_FAILED
)
1500 fcpatternelt_count
= fcpatternelt_ptr
= metadata
.patternelt_length
;
1506 FcPatternEltWrite (int fd
, FcCache
*metadata
)
1508 int c
= fcpatternelt_ptr
;
1509 off_t w
= FcCacheNextOffset(fd
);
1511 metadata
->patternelt_offset
= w
;
1512 metadata
->patternelt_length
= c
;
1516 lseek(fd
, w
, SEEK_SET
);
1517 return write(fd
, fcpatternelts
, c
*sizeof(FcPatternElt
)) != -1;
1523 FcValueListSerialize(FcValueList
*pi
)
1531 vl
= malloc (sizeof (FcValueList
) * fcvaluelist_count
);
1533 return FcValueListPtrCreateDynamic(0);
1535 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
) * fcvaluelist_count
);
1537 fcvaluelist_ptr
= 0;
1540 fcvaluelists
[fcvaluelist_ptr
] = *pi
;
1541 new.storage
= FcStorageStatic
;
1542 new.u
.stat
= fcvaluelist_ptr
++;
1543 v
= &fcvaluelists
[new.u
.stat
].value
;
1547 /* this departs from the usual convention of dereferencing
1548 * foo before serialization; FcObjectSerialize does the
1549 * translation itself. */
1550 /* also, v->u.si is 0 iff the string is null. */
1551 /* also, have to update the old pi */
1554 FcObjectPtr si
= FcObjectSerialize(v
->u
.si
);
1555 if (!FcObjectPtrU(si
))
1556 return FcValueListPtrCreateDynamic(pi
);
1558 pi
->value
.u
.si
= si
;
1562 if (FcMatrixPtrU(v
->u
.mi
))
1564 FcMatrixPtr mi
= FcMatrixSerialize(FcMatrixPtrU(v
->u
.mi
));
1566 if (!FcMatrixPtrU(mi
))
1567 return FcValueListPtrCreateDynamic(pi
);
1572 if (FcCharSetPtrU(v
->u
.ci
))
1574 FcCharSetPtr ci
= FcCharSetSerialize(FcCharSetPtrU(v
->u
.ci
));
1575 if (!FcCharSetPtrU(ci
))
1576 return FcValueListPtrCreateDynamic(pi
);
1581 if (FcLangSetPtrU(v
->u
.li
))
1583 FcLangSetPtr li
= FcLangSetSerialize(FcLangSetPtrU(v
->u
.li
));
1584 if (!FcLangSetPtrU(li
))
1585 return FcValueListPtrCreateDynamic(pi
);
1596 FcValueListRead (int fd
, FcCache metadata
)
1598 fcvaluelists
= mmap(NULL
,
1599 metadata
.valuelist_length
* sizeof (FcValueList
),
1601 MAP_SHARED
, fd
, metadata
.valuelist_offset
);
1602 if (fcvaluelists
== MAP_FAILED
)
1604 fcvaluelist_count
= fcvaluelist_ptr
= metadata
.valuelist_length
;
1610 FcValueListWrite (int fd
, FcCache
*metadata
)
1612 metadata
->valuelist_offset
= FcCacheNextOffset(fd
);
1613 metadata
->valuelist_length
= fcvaluelist_ptr
;
1615 if (fcvaluelist_ptr
> 0)
1617 lseek(fd
, metadata
->valuelist_offset
, SEEK_SET
);
1618 return write(fd
, fcvaluelists
,
1619 fcvaluelist_ptr
* sizeof(FcValueList
)) != -1;
1625 FcValueListPtrU (FcValueListPtr pi
)
1629 case FcStorageStatic
:
1630 return &fcvaluelists
[pi
.u
.stat
];
1631 case FcStorageDynamic
:
1639 FcValueListPtrCreateDynamic(FcValueList
* p
)
1643 r
.storage
= FcStorageDynamic
;
1648 /* Indices allow us to convert dynamic strings into static
1649 * strings without having to reassign IDs. We do reassign IDs
1650 * when serializing, which effectively performs mark-and-sweep
1651 * garbage collection. */
1653 /* objectptr_count maps FcObjectPtr to:
1654 + offsets in objectcontent_static_buf (if positive)
1655 - entries in objectcontent_dynamic (if negative)
1657 static int objectptr_count
= 1;
1658 static int objectptr_alloc
= 0;
1659 static int * objectptr_indices
= 0;
1661 /* invariant: objectcontent_static_buf must be sorted. */
1662 /* e.g. objectptr_static_buf = "name\0style\0weight\0" */
1663 static int objectcontent_static_bytes
= 0;
1664 static char * objectcontent_static_buf
;
1666 /* just a bunch of strings. */
1667 static int objectcontent_dynamic_count
= 1;
1668 static int objectcontent_dynamic_alloc
= 0;
1669 static const char ** objectcontent_dynamic
= 0;
1670 static int * objectcontent_dynamic_refcount
= 0;
1672 #define OBJECT_HASH_SIZE 31
1673 struct objectBucket
{
1674 struct objectBucket
*next
;
1677 static struct objectBucket
**FcObjectBuckets
= 0;
1680 FcObjectStaticName (const char *name
)
1682 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1683 struct objectBucket
**p
;
1684 struct objectBucket
*b
;
1689 if (!FcObjectBuckets
)
1691 FcObjectBuckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1692 memset (FcObjectBuckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1695 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1697 FcObjectPtr bp
= *((FcObjectPtr
*) (b
+ 1));
1698 if (b
->hash
== hash
&& FcObjectPtrU(bp
) && !strcmp (name
, FcObjectPtrU(bp
)))
1700 if (objectptr_indices
[bp
] < 0)
1701 objectcontent_dynamic_refcount
[-objectptr_indices
[bp
]]++;
1706 /* didn't find it, so add a new dynamic string */
1707 if (objectcontent_dynamic_count
>= objectcontent_dynamic_alloc
)
1709 int s
= objectcontent_dynamic_alloc
+ 4;
1711 const char ** d
= realloc (objectcontent_dynamic
,
1715 FcMemFree(FC_MEM_STATICSTR
,
1716 objectcontent_dynamic_alloc
* sizeof(char *));
1717 FcMemAlloc(FC_MEM_STATICSTR
, s
*sizeof(char *));
1718 objectcontent_dynamic
= d
;
1719 objectcontent_dynamic_alloc
= s
;
1721 int * rc
= realloc (objectcontent_dynamic_refcount
, s
*sizeof(int));
1724 FcMemFree(FC_MEM_STATICSTR
,
1725 objectcontent_dynamic_alloc
* sizeof(int));
1726 FcMemAlloc(FC_MEM_STATICSTR
, s
* sizeof(int));
1727 objectcontent_dynamic_refcount
= rc
;
1729 if (objectptr_count
>= objectptr_alloc
)
1731 int s
= objectptr_alloc
+ 4;
1732 int * d
= realloc (objectptr_indices
, s
*sizeof(int));
1735 FcMemFree(FC_MEM_STATICSTR
, objectptr_alloc
* sizeof(int));
1736 FcMemAlloc(FC_MEM_STATICSTR
, s
);
1737 objectptr_indices
= d
;
1738 objectptr_indices
[0] = 0;
1739 objectptr_alloc
= s
;
1742 size
= sizeof (struct objectBucket
) + sizeof (char *);
1746 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1749 nn
= malloc(strlen(name
)+1);
1752 strcpy ((char *)nn
, name
);
1753 objectptr_indices
[objectptr_count
] = -objectcontent_dynamic_count
;
1754 objectcontent_dynamic_refcount
[objectcontent_dynamic_count
] = 1;
1755 objectcontent_dynamic
[objectcontent_dynamic_count
++] = nn
;
1756 new = objectptr_count
++;
1757 *((FcObjectPtr
*)(b
+1)) = new;
1767 FcObjectPtrDestroy (FcObjectPtr p
)
1769 if (objectptr_indices
[p
] < 0)
1771 objectcontent_dynamic_refcount
[-objectptr_indices
[p
]]--;
1772 if (objectcontent_dynamic_refcount
[-objectptr_indices
[p
]] == 0)
1774 /* this code doesn't seem to be reached terribly often. */
1775 /* (note that objectcontent_dynamic overapproximates
1776 * the use count, because not every result from
1777 * StaticName is stored. */
1778 FcStrFree((char *)objectcontent_dynamic
[-objectptr_indices
[p
]]);
1779 objectcontent_dynamic
[-objectptr_indices
[p
]] = 0;
1785 FcObjectPtrU (FcObjectPtr si
)
1790 if (objectptr_indices
[si
] > 0)
1791 return &objectcontent_static_buf
[objectptr_indices
[si
]];
1793 return objectcontent_dynamic
[-objectptr_indices
[si
]];
1796 static FcBool objectptr_first_serialization
= FcFalse
;
1797 static int * object_old_id_to_new
= 0;
1800 FcObjectRebuildStaticNameHashtable (void)
1803 struct objectBucket
*b
, *bn
;
1805 if (FcObjectBuckets
)
1807 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
1809 b
= FcObjectBuckets
[i
];
1814 FcMemFree (FC_MEM_STATICSTR
,
1815 sizeof (struct objectBucket
)+sizeof (FcObjectPtr
));
1819 free (FcObjectBuckets
);
1822 FcObjectBuckets
= malloc(sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1823 memset (FcObjectBuckets
, 0, sizeof (struct objectBucket
*)*OBJECT_HASH_SIZE
);
1825 for (i
= 1; i
< objectptr_count
; i
++)
1827 if (FcObjectPtrU(i
))
1829 const char * name
= FcObjectPtrU(i
);
1830 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1831 struct objectBucket
**p
;
1834 for (p
= &FcObjectBuckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
);
1837 size
= sizeof (struct objectBucket
) + sizeof (FcObjectPtr
);
1841 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1844 *((FcObjectPtr
*)(b
+1)) = i
;
1850 /* Hmm. This will have a terrible effect on the memory size,
1851 * because the mmapped strings now get reallocated on the heap.
1852 * Is it all worth it? (Of course, the Serialization codepath is
1853 * not problematic, because the program quits just afterwards.) */
1855 FcObjectPtrConvertToStatic(FcBool renumber
)
1857 int active_count
, i
, j
, longest_string
= 0,
1858 new_static_bytes
= 1;
1859 char * fixed_length_buf
, * new_static_buf
, * p
;
1863 objectptr_first_serialization
= FcFalse
;
1865 /* collect statistics */
1866 for (i
= 1, active_count
= 1; i
< objectptr_count
; i
++)
1867 if (!renumber
|| object_old_id_to_new
[i
] == -1)
1869 int sl
= strlen(FcObjectPtrU(i
));
1871 if (sl
> longest_string
)
1872 longest_string
= sl
;
1873 new_static_bytes
+= sl
+ 1;
1876 /* allocate storage */
1877 fixed_length_buf
= malloc
1878 ((longest_string
+1) * active_count
* sizeof(char));
1879 if (!fixed_length_buf
)
1881 new_static_buf
= malloc (new_static_bytes
* sizeof(char));
1882 if (!new_static_buf
)
1884 new_indices
= malloc (active_count
* sizeof(int));
1888 new_static_buf
[0] = 0;
1890 FcMemAlloc (FC_MEM_STATICSTR
, new_static_bytes
);
1891 FcMemFree (FC_MEM_STATICSTR
, objectptr_count
* sizeof (int));
1892 FcMemAlloc (FC_MEM_STATICSTR
, active_count
* sizeof (int));
1894 /* copy strings to temporary buffers */
1895 for (j
= 0, i
= 1; i
< objectptr_count
; i
++)
1896 if (!renumber
|| object_old_id_to_new
[i
] == -1)
1898 strcpy (fixed_length_buf
+(j
*(longest_string
+1)), FcObjectPtrU(i
));
1902 /* sort the new statics */
1903 qsort (fixed_length_buf
, active_count
-1, longest_string
+1,
1904 (int (*)(const void *, const void *)) FcStrCmp
);
1906 /* now we create the new static buffer in sorted order. */
1907 p
= new_static_buf
+1;
1908 for (i
= 0; i
< active_count
-1; i
++)
1910 strcpy(p
, fixed_length_buf
+ i
* (longest_string
+1));
1914 /* create translation table by iterating over sorted strings
1915 * and getting their old values */
1916 p
= new_static_buf
+1;
1917 for (i
= 0; i
< active_count
-1; i
++)
1919 int n
= FcObjectStaticName(fixed_length_buf
+i
*(longest_string
+1));
1922 object_old_id_to_new
[n
] = i
+1;
1923 new_indices
[i
+1] = p
-new_static_buf
;
1926 new_indices
[n
] = p
-new_static_buf
;
1930 free (objectptr_indices
);
1931 objectptr_indices
= new_indices
;
1932 objectptr_count
= active_count
;
1933 objectptr_alloc
= active_count
;
1935 /* free old storage */
1936 for (i
= 1; i
< objectcontent_dynamic_count
; i
++)
1938 if (objectcontent_dynamic
[i
])
1940 FcMemFree (FC_MEM_STATICSTR
, strlen(objectcontent_dynamic
[i
])+1);
1941 free ((char *)objectcontent_dynamic
[i
]);
1944 free (objectcontent_dynamic
);
1945 free (objectcontent_dynamic_refcount
);
1946 FcMemFree (FC_MEM_STATICSTR
, objectcontent_dynamic_count
*sizeof (int));
1947 objectcontent_dynamic
= 0;
1948 objectcontent_dynamic_refcount
= 0;
1949 objectcontent_dynamic_count
= 1;
1950 objectcontent_dynamic_alloc
= 0;
1951 free (objectcontent_static_buf
);
1952 FcMemFree (FC_MEM_STATICSTR
, objectcontent_static_bytes
);
1953 objectcontent_static_buf
= new_static_buf
;
1954 objectcontent_static_bytes
= new_static_bytes
;
1956 /* fix up hash table */
1957 FcObjectRebuildStaticNameHashtable();
1959 free (fixed_length_buf
);
1963 free (new_static_buf
);
1965 free (fixed_length_buf
);
1970 #define OBJECT_PTR_CONVERSION_TRIGGER 100000
1973 FcObjectPtrCompare (const FcObjectPtr a
, const FcObjectPtr b
)
1975 /* This is the dynamic count. We could also use a static
1976 * count, i.e. the number of slow strings being created.
1977 * I think dyncount gives us a better estimate of inefficiency. -PL */
1978 static int compare_count
= OBJECT_PTR_CONVERSION_TRIGGER
;
1980 /* count on sortedness for fast objectptrs. */
1981 if ((a
== b
) || (objectptr_indices
[a
] > 0 && objectptr_indices
[b
] > 0))
1982 return objectptr_indices
[a
] - objectptr_indices
[b
];
1987 FcObjectPtrConvertToStatic(FcFalse
);
1988 compare_count
= OBJECT_PTR_CONVERSION_TRIGGER
;
1991 return strcmp (FcObjectPtrU(a
), FcObjectPtrU(b
));
1995 FcObjectClearStatic(void)
1997 objectptr_count
= 1;
1998 objectptr_alloc
= 0;
1999 objectptr_indices
= 0;
2001 objectcontent_static_bytes
= 0;
2002 objectcontent_static_buf
= 0;
2004 objectcontent_dynamic_count
= 1;
2005 objectcontent_dynamic_alloc
= 0;
2006 objectcontent_dynamic
= 0;
2007 objectcontent_dynamic_refcount
= 0;
2009 object_old_id_to_new
= 0;
2012 /* In the pre-serialization phase, mark the used strings with
2013 * -1 in the mapping array. */
2014 /* The first call to the serialization phase assigns actual
2015 * static indices to the strings (sweep). */
2017 FcObjectPrepareSerialize (FcObjectPtr si
)
2019 if (object_old_id_to_new
== 0)
2021 object_old_id_to_new
= malloc(objectptr_count
* sizeof(int));
2022 if (!object_old_id_to_new
)
2024 memset (object_old_id_to_new
, 0,
2025 objectptr_count
* sizeof(int));
2028 object_old_id_to_new
[si
] = -1;
2029 objectptr_first_serialization
= FcTrue
;
2038 FcObjectSerialize (FcObjectPtr si
)
2040 if (objectptr_first_serialization
)
2041 if (!FcObjectPtrConvertToStatic(FcTrue
))
2044 return object_old_id_to_new
[si
];
2048 FcObjectRead (int fd
, FcCache metadata
)
2050 /* do we have to merge strings?
2051 * it's possible to merge dynamic strings, as long as we only store
2052 * static strings to disk and as long as all static strings have lower
2053 * ids than any dynamic strings. */
2055 objectcontent_dynamic_count
= 1;
2056 objectcontent_dynamic_alloc
= 0;
2057 objectcontent_dynamic
= 0;
2058 objectcontent_dynamic_refcount
= 0;
2060 /* well, we do need to allocate dynamic strings all the time,
2061 * so this would just have to be converted. It takes 1.4k on
2062 * my system. - PL */
2063 /* objectptr_indices = mmap(NULL, */
2064 /* metadata.object_length * sizeof (int), */
2066 /* MAP_SHARED, fd, metadata.object_offset); */
2067 /* if (objectptr_indices == MAP_FAILED) */
2070 objectptr_count
= metadata
.object_length
;
2071 objectptr_alloc
= metadata
.object_length
;
2072 objectptr_indices
= malloc (metadata
.object_length
* sizeof (int));
2073 if (!objectptr_indices
)
2075 FcMemAlloc (FC_MEM_STATICSTR
, metadata
.object_length
* sizeof (int));
2076 lseek (fd
, metadata
.object_offset
, SEEK_SET
);
2077 read (fd
, objectptr_indices
, metadata
.object_length
* sizeof (int));
2079 objectcontent_static_buf
=
2081 metadata
.objectcontent_length
* sizeof (char),
2083 MAP_SHARED
, fd
, metadata
.objectcontent_offset
);
2084 if (objectptr_indices
== MAP_FAILED
)
2086 objectcontent_static_bytes
= metadata
.objectcontent_length
;
2088 FcObjectRebuildStaticNameHashtable ();
2093 /*munmap(objectptr_indices, metadata.object_length * sizeof(int));*/
2094 free (objectptr_indices
);
2100 FcObjectWrite (int fd
, FcCache
* metadata
)
2102 /* there should be no dynamic strings:
2103 * serialize ought to have zapped 'em. */
2104 if (objectcontent_dynamic_alloc
)
2107 metadata
->object_length
= objectptr_count
;
2108 metadata
->object_offset
= FcCacheNextOffset(fd
);
2109 lseek(fd
, metadata
->object_offset
, SEEK_SET
);
2110 if (write (fd
, objectptr_indices
,
2111 metadata
->object_length
* sizeof (int)) == -1)
2114 metadata
->objectcontent_length
= objectcontent_static_bytes
;
2115 metadata
->objectcontent_offset
= FcCacheNextOffset(fd
);
2116 lseek(fd
, metadata
->objectcontent_offset
, SEEK_SET
);
2117 if (write (fd
, objectcontent_static_buf
,
2118 metadata
->objectcontent_length
* sizeof (char)) == -1)
2125 FcObjectStaticNameFini (void)
2128 struct objectBucket
*b
, *next
;
2131 for (i
= 0; i
< OBJECT_HASH_SIZE
; i
++)
2133 for (b
= FcObjectBuckets
[i
]; b
; b
= next
)
2136 name
= (char *) (b
+ 1);
2137 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
2138 FcMemFree (FC_MEM_STATICSTR
, size
);
2141 FcObjectBuckets
[i
] = 0;
2146 FcPatternFini (void)
2148 FcPatternBaseThawAll ();
2149 FcValueListThawAll ();
2150 FcObjectStaticNameFini ();