diff --git a/src/fccfg.c b/src/fccfg.c index 4d2e024..0032a9b 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -773,7 +773,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) break; case FcOpString: v.type = FcTypeString; - v.u.s = FcObjectStaticName(e->u.sval); + v.u.s = FcStrStaticName(e->u.sval); v = FcValueSave (v); break; case FcOpMatrix: @@ -891,7 +891,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e) switch (e->op) { case FcOpPlus: v.type = FcTypeString; - v.u.s = FcObjectStaticName (FcStrPlus (vl.u.s, vr.u.s)); + v.u.s = FcStrStaticName (FcStrPlus (vl.u.s, vr.u.s)); if (!v.u.s) v.type = FcTypeVoid; diff --git a/src/fcfs.c b/src/fcfs.c index 1e5aa81..90e8580 100644 --- a/src/fcfs.c +++ b/src/fcfs.c @@ -87,7 +87,6 @@ void FcFontSetNewBank (void) { FcPatternNewBank(); - FcObjectNewBank(); } int @@ -104,7 +103,7 @@ FcFontSetNeededBytes (FcFontSet *s) } if (cum > 0) - return cum + sizeof(int); + return cum + sizeof(int) + FcObjectNeededBytes(); else return 0; } @@ -138,6 +137,7 @@ FcFontSetSerialize (int bank, FcFontSet * s) s->fonts[i] = p; } + FcObjectSerialize(); return FcTrue; } @@ -166,10 +166,13 @@ FcFontSetUnserialize(FcCache metadata, FcFontSet * s, void * block_ptr) if (nfont > 0) { - FcPattern * p = FcPatternUnserialize (metadata, block_ptr); + FcPattern * p = (FcPattern *)block_ptr; + block_ptr = FcPatternUnserialize (metadata, block_ptr); for (i = 0; i < nfont; i++) s->fonts[n + i] = p+i; + + block_ptr = FcObjectUnserialize (metadata, block_ptr); } - return FcTrue; + return block_ptr != 0; } diff --git a/src/fcint.h b/src/fcint.h index 73039f4..446e164 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -808,9 +808,6 @@ FcListPatternMatchAny (const FcPattern *p, FcBool FcNameBool (const FcChar8 *v, FcBool *result); -void -FcObjectNewBank(void); - void * FcObjectDistributeBytes (FcCache * metadata, void * block_ptr); @@ -819,13 +816,22 @@ FcObjectPtr FcObjectToPtr (const char * si); int -FcObjectNeededBytes (FcObjectPtr p); +FcObjectNeededBytes (void); + +void * +FcObjectUnserialize (FcCache metadata, void *block_ptr); void -FcObjectUnserialize (FcCache metadata, FcConfig * config, void *block_ptr); +FcObjectSerialize (void); -FcObjectPtr -FcObjectSerialize (FcObjectPtr s); +const char * +FcObjectPtrU (FcObjectPtr p); + +int +FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b); + +void +FcObjectStaticNameFini (void); /* fcpat.c */ @@ -858,13 +864,10 @@ FcBool FcPatternAppend (FcPattern *p, FcPattern *s); const char * -FcObjectStaticName (const char *name); +FcStrStaticName (const char *name); -const char * -FcObjectPtrU (FcObjectPtr p); - -int -FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b); +FcChar32 +FcStringHash (const FcChar8 *s); void FcPatternNewBank (void); @@ -887,7 +890,7 @@ FcValueListPtrCreateDynamic(FcValueList * p); FcPattern * FcPatternSerialize (int bank, FcPattern * p); -FcPattern * +void * FcPatternUnserialize (FcCache metadata, void *block_ptr); /* fcrender.c */ diff --git a/src/fclist.c b/src/fclist.c index db63058..02ef877 100644 --- a/src/fclist.c +++ b/src/fclist.c @@ -67,7 +67,7 @@ FcObjectSetAdd (FcObjectSet *os, const char *object) low = 0; mid = 0; c = 1; - object = FcObjectStaticName (object); + object = FcStrStaticName (object); while (low <= high) { mid = (low + high) >> 1; diff --git a/src/fcname.c b/src/fcname.c index 1cdba56..e50f75f 100644 --- a/src/fcname.c +++ b/src/fcname.c @@ -28,6 +28,7 @@ #include #include "fcint.h" +/* Please do not revoke any of these bindings. */ static const FcObjectType _FcBaseObjectTypes[] = { { FC_FAMILY, FcTypeString, }, { FC_FAMILYLANG, FcTypeString, }, @@ -106,8 +107,9 @@ FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes) return FcTrue; } -FcBool -FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes) +static FcBool +FcNameUnregisterObjectTypesFree (const FcObjectType *types, int ntypes, + FcBool do_free) { const FcObjectTypeList *l, **prev; @@ -118,14 +120,22 @@ FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes) if (l->types == types && l->ntypes == ntypes) { *prev = l->next; - FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList)); - free ((void *) l); + if (do_free) { + FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList)); + free ((void *) l); + } return FcTrue; } } return FcFalse; } +FcBool +FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes) +{ + return FcNameUnregisterObjectTypesFree (types, ntypes, FcTrue); +} + const FcObjectType * FcNameGetObjectType (const char *object) { @@ -145,26 +155,13 @@ FcNameGetObjectType (const char *object) return 0; } -static int objectptr_count = 1; -static int objectptr_alloc = 0; -static int * objectptr_indices = 0; - -void -FcObjectNewBank(void) +static FcObjectPtr +FcObjectToPtrLookup (const char * object) { - objectptr_count = 1; - objectptr_alloc = 0; - objectptr_indices = 0; -} - -// XXX todo: introduce a hashtable for faster lookup -FcObjectPtr -FcObjectToPtr (const char * object) -{ - int i; + FcObjectPtr i; const FcObjectTypeList *l; const FcObjectType *t; - + for (l = _FcObjectTypes; l; l = l->next) { for (i = 0; i < l->ntypes; i++) @@ -174,37 +171,159 @@ FcObjectToPtr (const char * object) return i; } } - abort(); return 0; } +#define OBJECT_HASH_SIZE 31 +struct objectBucket { + struct objectBucket *next; + FcChar32 hash; + int id; +}; +static struct objectBucket *FcObjectBuckets[OBJECT_HASH_SIZE]; + +static const FcObjectType *biggest_known_types = _FcBaseObjectTypes; +static FcBool allocated_biggest_known_types; +static int biggest_known_ntypes = NUM_OBJECT_TYPES; +static int biggest_known_count = 0; +static char * biggest_ptr; + +FcObjectPtr +FcObjectToPtr (const char * name) +{ + FcChar32 hash = FcStringHash ((const FcChar8 *) name); + struct objectBucket **p; + struct objectBucket *b; + int size; + + for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next) +) + if (b->hash == hash && !strcmp (name, (char *) (b + 1))) + return b->id; + size = sizeof (struct objectBucket) + strlen (name) + 1; + b = malloc (size); + FcMemAlloc (FC_MEM_STATICSTR, size); + if (!b) + return -1; + b->next = 0; + b->hash = hash; + b->id = FcObjectToPtrLookup (name); + strcpy ((char *) (b + 1), name); + *p = b; + return b->id; +} + +void +FcObjectStaticNameFini (void) +{ + int i, size; + struct objectBucket *b, *next; + char *name; + + for (i = 0; i < OBJECT_HASH_SIZE; i++) + { + for (b = FcObjectBuckets[i]; b; b = next) + { + next = b->next; + name = (char *) (b + 1); + size = sizeof (struct objectBucket) + strlen (name) + 1; + FcMemFree (FC_MEM_STATICSTR, size); + free (b); + } + FcObjectBuckets[i] = 0; + } +} + const char * FcObjectPtrU (FcObjectPtr si) { - return _FcObjectTypes->types[si].object; + return biggest_known_types[si].object; } int -FcObjectNeededBytes (FcObjectPtr si) +FcObjectNeededBytes () { - return 0; + int num = 0, i; + for (i = 0; i < biggest_known_ntypes; i++) + { + const char * t = biggest_known_types[i].object; + num = num + strlen(t) + 1; + } + biggest_known_count = num; + return num + sizeof(int); } void * FcObjectDistributeBytes (FcCache * metadata, void * block_ptr) { + *(int *)block_ptr = biggest_known_ntypes; + block_ptr = (int *) block_ptr + 1; + biggest_ptr = block_ptr; + block_ptr = (char *) block_ptr + biggest_known_count; return block_ptr; } -FcObjectPtr -FcObjectSerialize (FcObjectPtr si) +void +FcObjectSerialize () { - return si; + int i; + for (i = 0; i < biggest_known_ntypes; i++) + { + const char * t = biggest_known_types[i].object; + strcpy (biggest_ptr, t); + biggest_ptr = biggest_ptr + strlen(t) + 1; + } } -void -FcObjectUnserialize (FcCache metadata, FcConfig * config, void *block_ptr) +void * +FcObjectUnserialize (FcCache metadata, void *block_ptr) { + int new_biggest; + new_biggest = *(int *)block_ptr; + block_ptr = (int *) block_ptr + 1; + if (biggest_known_ntypes < new_biggest) + { + int i; + char * bp = (char *)block_ptr; + FcObjectType * bn; + FcObjectTypeList * bnl; + + bn = malloc (sizeof (const FcObjectType) * (new_biggest + 1)); + if (!bn) + return 0; + + bnl = malloc (sizeof (FcObjectTypeList)); + if (!bnl) + { + free (bn); + return 0; + } + + for (i = 0; i < new_biggest; i++) + { + const FcObjectType * t = FcNameGetObjectType(bp); + if (t) + bn[i].type = t->type; + else + bn[i].type = FcTypeVoid; + bn[i].object = bp; + bp = bp + strlen(bp) + 1; + } + + FcNameUnregisterObjectTypesFree (biggest_known_types, biggest_known_ntypes, FcFalse); + if (allocated_biggest_known_types) + { + free ((FcObjectTypeList *)biggest_known_types); + } + else + allocated_biggest_known_types = FcTrue; + + FcNameRegisterObjectTypes (bn, new_biggest); + biggest_known_ntypes = new_biggest; + biggest_known_types = (const FcObjectType *)bn; + } + block_ptr = (char *) block_ptr + biggest_known_count; + return block_ptr; } int @@ -389,7 +508,7 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m) v.u.i = atoi ((char *) string); break; case FcTypeString: - v.u.s = FcObjectStaticName(string); + v.u.s = FcStrStaticName(string); break; case FcTypeBool: if (!FcNameBool (string, &v.u.b)) diff --git a/src/fcpat.c b/src/fcpat.c index d42401d..e3f244a 100644 --- a/src/fcpat.c +++ b/src/fcpat.c @@ -214,7 +214,7 @@ FcDoubleHash (double d) return (FcChar32) d; } -static FcChar32 +FcChar32 FcStringHash (const FcChar8 *s) { FcChar8 c; @@ -391,7 +391,7 @@ FcValueListEntCreate (FcValueListPtr h) if ((FcValueListPtrU(l)->value.type & ~FC_STORAGE_STATIC) == FcTypeString) { new->value.type = FcTypeString; - new->value.u.s = FcObjectStaticName + new->value.u.s = FcStrStaticName (fc_value_string(&FcValueListPtrU(l)->value)); } else @@ -984,7 +984,7 @@ FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s) FcValue v; v.type = FcTypeString; - v.u.s = FcObjectStaticName(s); + v.u.s = FcStrStaticName(s); return FcPatternAdd (p, object, v, FcTrue); } @@ -1287,7 +1287,7 @@ struct objectBucket { static struct objectBucket *FcObjectBuckets[OBJECT_HASH_SIZE]; const char * -FcObjectStaticName (const char *name) +FcStrStaticName (const char *name) { FcChar32 hash = FcStringHash ((const FcChar8 *) name); struct objectBucket **p; @@ -1311,7 +1311,7 @@ FcObjectStaticName (const char *name) } static void -FcObjectStaticNameFini (void) +FcStrStaticNameFini (void) { int i, size; struct objectBucket *b, *next; @@ -1336,6 +1336,7 @@ FcPatternFini (void) { FcPatternBaseThawAll (); FcValueListThawAll (); + FcStrStaticNameFini (); FcObjectStaticNameFini (); } @@ -1409,8 +1410,6 @@ FcPatternNeededBytes (FcPattern * p) for (i = 0; i < p->num; i++) { - cum += FcObjectNeededBytes - ((FcPatternEltU(p->elts)+i)->object); c = FcValueListNeededBytes (FcValueListPtrU (((FcPatternEltU(p->elts)+i)->values))); if (c < 0) @@ -1526,7 +1525,7 @@ FcPatternSerialize (int bank, FcPattern *old) } nep[i].values = nv_head; - nep[i].object = FcObjectSerialize (e->object); + nep[i].object = e->object; } p->elts = old->elts; @@ -1537,7 +1536,7 @@ FcPatternSerialize (int bank, FcPattern *old) return p; } -FcPattern * +void * FcPatternUnserialize (FcCache metadata, void *block_ptr) { int bi = FcCacheBankToIndex(metadata.bank); @@ -1558,7 +1557,7 @@ FcPatternUnserialize (FcCache metadata, void *block_ptr) block_ptr = FcStrUnserialize (metadata, block_ptr); block_ptr = FcValueListUnserialize (metadata, block_ptr); - return fcpatterns[bi]; + return block_ptr; } static void