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 FcPatternCreate (void)
35 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
38 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
47 FcValueDestroy (FcValue v
)
51 FcStrFree ((FcChar8
*) v
.u
.s
);
54 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
57 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
60 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
68 FcValueSave (FcValue v
)
72 v
.u
.s
= FcStrCopy (v
.u
.s
);
77 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
82 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
87 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
98 FcValueListDestroy (FcValueList
*l
)
103 switch (l
->value
.type
) {
105 FcStrFree ((FcChar8
*) l
->value
.u
.s
);
108 FcMatrixFree ((FcMatrix
*) l
->value
.u
.m
);
111 FcCharSetDestroy ((FcCharSet
*) l
->value
.u
.c
);
114 FcLangSetDestroy ((FcLangSet
*) l
->value
.u
.l
);
120 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
126 FcValueEqual (FcValue va
, FcValue vb
)
128 if (va
.type
!= vb
.type
)
130 if (va
.type
== FcTypeInteger
)
132 va
.type
= FcTypeDouble
;
135 if (vb
.type
== FcTypeInteger
)
137 vb
.type
= FcTypeDouble
;
140 if (va
.type
!= vb
.type
)
147 return va
.u
.i
== vb
.u
.i
;
149 return va
.u
.d
== vb
.u
.d
;
151 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
153 return va
.u
.b
== vb
.u
.b
;
155 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
157 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
159 return va
.u
.f
== vb
.u
.f
;
161 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
167 FcDoubleHash (double d
)
177 FcStringHash (const FcChar8
*s
)
184 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
189 FcValueHash (FcValue v
)
195 return (FcChar32
) v
.u
.i
;
197 return FcDoubleHash (v
.u
.d
);
199 return FcStringHash (v
.u
.s
);
201 return (FcChar32
) v
.u
.b
;
203 return (FcDoubleHash (v
.u
.m
->xx
) ^
204 FcDoubleHash (v
.u
.m
->xy
) ^
205 FcDoubleHash (v
.u
.m
->yx
) ^
206 FcDoubleHash (v
.u
.m
->yy
));
208 return (FcChar32
) v
.u
.c
->num
;
210 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
211 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
213 return FcLangSetHash (v
.u
.l
);
219 FcValueListEqual (FcValueList
*la
, FcValueList
*lb
)
226 if (!FcValueEqual (la
->value
, lb
->value
))
237 FcValueListHash (FcValueList
*l
)
243 hash
= ((hash
<< 1) | (hash
>> 31)) ^ FcValueHash (l
->value
);
250 FcPatternDestroy (FcPattern
*p
)
254 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
257 for (i
= 0; i
< p
->num
; i
++)
258 FcValueListDestroy (p
->elts
[i
].values
);
263 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
268 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
272 #define FC_VALUE_LIST_HASH_SIZE 257
273 #define FC_PATTERN_HASH_SIZE 67
275 typedef struct _FcValueListEnt FcValueListEnt
;
277 struct _FcValueListEnt
{
278 FcValueListEnt
*next
;
283 typedef union _FcValueListAlign
{
288 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
289 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
290 static char *FcValueListFrozenName
[] = {
303 FcValueListReport (void);
306 FcValueListReport (void)
310 printf ("Fc Frozen Values:\n");
311 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
312 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
313 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
314 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
317 static FcValueListEnt
*
318 FcValueListEntCreate (FcValueList
*h
)
320 FcValueListAlign
*ea
;
322 FcValueList
*l
, *new;
329 for (l
= h
; l
; l
= l
->next
)
331 if (l
->value
.type
== FcTypeString
)
332 string_size
+= strlen ((char *) l
->value
.u
.s
) + 1;
335 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
) + string_size
;
336 FcValueListFrozenCount
[h
->value
.type
]++;
337 FcValueListFrozenBytes
[h
->value
.type
] += size
;
341 FcMemAlloc (FC_MEM_VALLIST
, size
);
343 e
->list
= (FcValueList
*) (ea
+ 1);
344 strs
= (FcChar8
*) (e
->list
+ n
);
346 for (l
= h
; l
; l
= l
->next
, new++)
348 if (l
->value
.type
== FcTypeString
)
350 new->value
.type
= FcTypeString
;
351 new->value
.u
.s
= strs
;
352 strcpy ((char *) strs
, (char *) l
->value
.u
.s
);
353 strs
+= strlen ((char *) strs
) + 1;
357 new->value
= l
->value
;
358 new->value
= FcValueSave (new->value
);
360 new->binding
= l
->binding
;
370 FcValueListEntDestroy (FcValueListEnt
*e
)
374 FcValueListFrozenCount
[e
->list
->value
.type
]--;
376 /* XXX: We should perform these two operations with "size" as
377 computed in FcValueListEntCreate, but we don't have access to
378 that value here. Without this, the FcValueListFrozenBytes
379 values will be wrong as will the FcMemFree counts.
381 FcValueListFrozenBytes[e->list->value.type] -= size;
382 FcMemFree (FC_MEM_VALLIST, size);
385 for (l
= e
->list
; l
; l
= l
->next
)
387 if (l
->value
.type
!= FcTypeString
)
388 FcValueDestroy (l
->value
);
390 /* XXX: Are we being too chummy with the implementation here to
391 free(e) when it was actually the enclosing FcValueListAlign
392 that was allocated? */
396 static int FcValueListTotal
;
397 static int FcValueListUsed
;
399 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
402 FcValueListFreeze (FcValueList
*l
)
404 FcChar32 hash
= FcValueListHash (l
);
405 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
409 for (ent
= *bucket
; ent
; ent
= ent
->next
)
411 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
415 ent
= FcValueListEntCreate (l
);
427 FcValueListThawAll (void)
430 FcValueListEnt
*ent
, *next
;
432 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
434 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
437 FcValueListEntDestroy (ent
);
439 FcValueListHashTable
[i
] = 0;
442 FcValueListTotal
= 0;
447 FcPatternBaseHash (FcPattern
*b
)
449 FcChar32 hash
= b
->num
;
452 for (i
= 0; i
< b
->num
; i
++)
453 hash
= ((hash
<< 1) | (hash
>> 31)) ^ ((long) b
->elts
[i
].values
);
457 typedef struct _FcPatternEnt FcPatternEnt
;
459 struct _FcPatternEnt
{
465 static int FcPatternTotal
;
466 static int FcPatternUsed
;
468 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
471 FcPatternBaseFreeze (FcPattern
*b
)
473 FcChar32 hash
= FcPatternBaseHash (b
);
474 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
482 for (ent
= *bucket
; ent
; ent
= ent
->next
)
484 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
.num
)
486 for (i
= 0; i
< b
->num
; i
++)
488 if (strcmp (b
->elts
[i
].object
, ent
->pattern
.elts
[i
].object
))
490 if (b
->elts
[i
].values
!= ent
->pattern
.elts
[i
].values
)
494 return &ent
->pattern
;
499 * Compute size of pattern + elts + object names
502 for (i
= 0; i
< b
->num
; i
++)
503 size_objects
+= strlen (b
->elts
[i
].object
) + 1;
505 size
= sizeof (FcPatternEnt
) + b
->num
*sizeof (FcPatternElt
) + size_objects
;
510 FcMemAlloc (FC_MEM_PATTERN
, size
);
513 ent
->pattern
.elts
= (FcPatternElt
*) (ent
+ 1);
514 ent
->pattern
.num
= b
->num
;
515 ent
->pattern
.size
= b
->num
;
516 ent
->pattern
.ref
= FC_REF_CONSTANT
;
518 objects
= (char *) (ent
->pattern
.elts
+ b
->num
);
519 for (i
= 0; i
< b
->num
; i
++)
521 ent
->pattern
.elts
[i
].values
= b
->elts
[i
].values
;
522 strcpy (objects
, b
->elts
[i
].object
);
523 ent
->pattern
.elts
[i
].object
= objects
;
524 objects
+= strlen (objects
) + 1;
530 return &ent
->pattern
;
534 FcPatternBaseThawAll (void)
537 FcPatternEnt
*ent
, *next
;
539 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
541 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
546 FcPatternHashTable
[i
] = 0;
554 FcPatternFreeze (FcPattern
*p
)
556 FcPattern
*b
, *n
= 0;
560 size
= sizeof (FcPattern
) + p
->num
* sizeof (FcPatternElt
);
561 b
= (FcPattern
*) malloc (size
);
564 FcMemAlloc (FC_MEM_PATTERN
, size
);
568 b
->elts
= (FcPatternElt
*) (b
+ 1);
570 * Freeze object lists
572 for (i
= 0; i
< p
->num
; i
++)
574 b
->elts
[i
].object
= p
->elts
[i
].object
;
575 b
->elts
[i
].values
= FcValueListFreeze (p
->elts
[i
].values
);
576 if (!b
->elts
[i
].values
)
582 n
= FcPatternBaseFreeze (b
);
584 if (FcDebug() & FC_DBG_MEMORY
)
586 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
587 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
593 assert (FcPatternEqual (n
, p
));
599 FcPatternThawAll (void)
601 FcPatternBaseThawAll ();
602 FcValueListThawAll ();
606 FcPatternPosition (const FcPattern
*p
, const char *object
)
608 int low
, high
, mid
, c
;
616 mid
= (low
+ high
) >> 1;
617 c
= strcmp (p
->elts
[mid
].object
, object
);
631 FcPatternFindElt (const FcPattern
*p
, const char *object
)
633 int i
= FcPatternPosition (p
, object
);
640 FcPatternInsertElt (FcPattern
*p
, const char *object
)
645 i
= FcPatternPosition (p
, object
);
651 if (p
->num
+ 1 >= p
->size
)
653 int s
= p
->size
+ 16;
655 e
= (FcPatternElt
*) realloc (p
->elts
, s
* sizeof (FcPatternElt
));
657 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
662 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
663 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
666 p
->elts
[p
->size
].object
= 0;
667 p
->elts
[p
->size
].values
= 0;
673 memmove (p
->elts
+ i
+ 1,
675 sizeof (FcPatternElt
) *
681 p
->elts
[i
].object
= object
;
682 p
->elts
[i
].values
= 0;
689 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
696 if (pa
->num
!= pb
->num
)
698 for (i
= 0; i
< pa
->num
; i
++)
700 if (strcmp (pa
->elts
[i
].object
, pb
->elts
[i
].object
) != 0)
702 if (!FcValueListEqual (pa
->elts
[i
].values
, pb
->elts
[i
].values
))
709 FcPatternHash (const FcPattern
*p
)
714 for (i
= 0; i
< p
->num
; i
++)
716 h
= (((h
<< 1) | (h
>> 31)) ^
717 FcStringHash ((const FcChar8
*) p
->elts
[i
].object
) ^
718 FcValueListHash (p
->elts
[i
].values
));
724 FcPatternEqualSubset (const FcPattern
*pa
, const FcPattern
*pb
, const FcObjectSet
*os
)
726 FcPatternElt
*ea
, *eb
;
729 for (i
= 0; i
< os
->nobject
; i
++)
731 ea
= FcPatternFindElt (pa
, os
->objects
[i
]);
732 eb
= FcPatternFindElt (pb
, os
->objects
[i
]);
737 if (!FcValueListEqual (ea
->values
, eb
->values
))
750 FcPatternAddWithBinding (FcPattern
*p
,
753 FcValueBinding binding
,
757 FcValueList
*new, **prev
;
759 if (p
->ref
== FC_REF_CONSTANT
)
762 new = (FcValueList
*) malloc (sizeof (FcValueList
));
766 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
768 value
= FcValueSave (value
);
769 if (value
.type
== FcTypeVoid
)
773 new->binding
= binding
;
776 e
= FcPatternInsertElt (p
, object
);
782 for (prev
= &e
->values
; *prev
; prev
= &(*prev
)->next
);
787 new->next
= e
->values
;
794 switch (value
.type
) {
796 FcStrFree ((FcChar8
*) value
.u
.s
);
799 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
802 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
805 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
811 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
818 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
820 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
824 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
826 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
830 FcPatternDel (FcPattern
*p
, const char *object
)
835 e
= FcPatternFindElt (p
, object
);
842 FcValueListDestroy (e
->values
);
844 /* shuffle existing ones down */
845 memmove (e
, e
+1, (p
->elts
+ p
->num
- (e
+ 1)) * sizeof (FcPatternElt
));
847 p
->elts
[p
->num
].object
= 0;
848 p
->elts
[p
->num
].values
= 0;
853 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
856 FcValueList
**prev
, *l
;
858 e
= FcPatternFindElt (p
, object
);
861 for (prev
= &e
->values
; (l
= *prev
); prev
= &l
->next
)
867 FcValueListDestroy (l
);
869 FcPatternDel (p
, object
);
878 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
882 v
.type
= FcTypeInteger
;
884 return FcPatternAdd (p
, object
, v
, FcTrue
);
888 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
892 v
.type
= FcTypeDouble
;
894 return FcPatternAdd (p
, object
, v
, FcTrue
);
899 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
903 v
.type
= FcTypeString
;
905 return FcPatternAdd (p
, object
, v
, FcTrue
);
909 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
913 v
.type
= FcTypeMatrix
;
914 v
.u
.m
= (FcMatrix
*) s
;
915 return FcPatternAdd (p
, object
, v
, FcTrue
);
920 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
926 return FcPatternAdd (p
, object
, v
, FcTrue
);
930 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
934 v
.type
= FcTypeCharSet
;
935 v
.u
.c
= (FcCharSet
*) c
;
936 return FcPatternAdd (p
, object
, v
, FcTrue
);
940 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
944 v
.type
= FcTypeFTFace
;
946 return FcPatternAdd (p
, object
, v
, FcTrue
);
950 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
954 v
.type
= FcTypeLangSet
;
955 v
.u
.l
= (FcLangSet
*) ls
;
956 return FcPatternAdd (p
, object
, v
, FcTrue
);
960 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
965 e
= FcPatternFindElt (p
, object
);
967 return FcResultNoMatch
;
968 for (l
= e
->values
; l
; l
= l
->next
)
973 return FcResultMatch
;
981 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
986 r
= FcPatternGet (p
, object
, id
, &v
);
987 if (r
!= FcResultMatch
)
997 return FcResultTypeMismatch
;
999 return FcResultMatch
;
1003 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
1008 r
= FcPatternGet (p
, object
, id
, &v
);
1009 if (r
!= FcResultMatch
)
1016 *d
= (double) v
.u
.i
;
1019 return FcResultTypeMismatch
;
1021 return FcResultMatch
;
1025 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1030 r
= FcPatternGet (p
, object
, id
, &v
);
1031 if (r
!= FcResultMatch
)
1033 if (v
.type
!= FcTypeString
)
1034 return FcResultTypeMismatch
;
1035 *s
= (FcChar8
*) v
.u
.s
;
1036 return FcResultMatch
;
1040 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1045 r
= FcPatternGet (p
, object
, id
, &v
);
1046 if (r
!= FcResultMatch
)
1048 if (v
.type
!= FcTypeMatrix
)
1049 return FcResultTypeMismatch
;
1050 *m
= (FcMatrix
*) v
.u
.m
;
1051 return FcResultMatch
;
1056 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1061 r
= FcPatternGet (p
, object
, id
, &v
);
1062 if (r
!= FcResultMatch
)
1064 if (v
.type
!= FcTypeBool
)
1065 return FcResultTypeMismatch
;
1067 return FcResultMatch
;
1071 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1076 r
= FcPatternGet (p
, object
, id
, &v
);
1077 if (r
!= FcResultMatch
)
1079 if (v
.type
!= FcTypeCharSet
)
1080 return FcResultTypeMismatch
;
1081 *c
= (FcCharSet
*) v
.u
.c
;
1082 return FcResultMatch
;
1086 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1091 r
= FcPatternGet (p
, object
, id
, &v
);
1092 if (r
!= FcResultMatch
)
1094 if (v
.type
!= FcTypeFTFace
)
1095 return FcResultTypeMismatch
;
1096 *f
= (FT_Face
) v
.u
.f
;
1097 return FcResultMatch
;
1101 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1106 r
= FcPatternGet (p
, object
, id
, &v
);
1107 if (r
!= FcResultMatch
)
1109 if (v
.type
!= FcTypeLangSet
)
1110 return FcResultTypeMismatch
;
1111 *ls
= (FcLangSet
*) v
.u
.l
;
1112 return FcResultMatch
;
1116 FcPatternDuplicate (const FcPattern
*orig
)
1122 new = FcPatternCreate ();
1126 for (i
= 0; i
< orig
->num
; i
++)
1128 for (l
= orig
->elts
[i
].values
; l
; l
= l
->next
)
1129 if (!FcPatternAdd (new, orig
->elts
[i
].object
, l
->value
, FcTrue
))
1136 FcPatternDestroy (new);
1142 FcPatternReference (FcPattern
*p
)
1144 if (p
->ref
!= FC_REF_CONSTANT
)
1149 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1153 FcPatternVapBuild (ret
, orig
, va
);
1158 FcPatternBuild (FcPattern
*orig
, ...)
1162 va_start (va
, orig
);
1163 FcPatternVapBuild (orig
, orig
, va
);
1169 * Add all of the elements in 's' to 'p'
1172 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1178 for (i
= 0; i
< s
->num
; i
++)
1181 for (v
= e
->values
; v
; v
= v
->next
)
1183 if (!FcPatternAddWithBinding (p
, e
->object
,
1184 v
->value
, v
->binding
, FcTrue
))
1192 FcObjectStaticName (const char *name
)
1194 #define OBJECT_HASH_SIZE 31
1195 static struct objectBucket
{
1196 struct objectBucket
*next
;
1198 } *buckets
[OBJECT_HASH_SIZE
];
1199 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1200 struct objectBucket
**p
;
1201 struct objectBucket
*b
;
1203 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1204 if (b
->hash
== hash
&& !strcmp (name
, (char *) (b
+ 1)))
1205 return (char *) (b
+ 1);
1206 b
= malloc (sizeof (struct objectBucket
) + strlen (name
) + 1);
1211 strcpy ((char *) (b
+ 1), name
);
1213 return (char *) (b
+ 1);