diff options
author | Patrick Lam <plam@MIT.EDU> | 2005-06-28 03:41:02 +0000 |
---|---|---|
committer | Patrick Lam <plam@MIT.EDU> | 2005-06-28 03:41:02 +0000 |
commit | cd2ec1a940888ebcbd323a8000d2fcced41ddf9e (patch) | |
tree | 841e371cb0e28b003cdfbab8d109e30d84b2a3db /src/fcpat.c | |
parent | f1a42f6b5f9bcd774d09002509b2872c04025c1b (diff) |
Add functionality to allow fontconfig data structure serialization.
This patch allows the fundamental fontconfig data structures to be
serialized. I've converted everything from FcPattern down to be able to
use *Ptr objects, which can be either static or dynamic (using a union
which either contains a pointer or an index) and replaced storage of
pointers in the heap with the appropriate *Ptr object. I then changed
all writes of pointers to the heap with a *CreateDynamic call, which
creates a dynamic Ptr object pointing to the same object as before.
This way, the fundamental fontconfig semantics should be unchanged; I
did not have to change external signatures this way, although I did
change some internal signatures. When given a *Ptr object, just run *U
to get back to a normal pointer; it gives the right answer regardless
of whether we're using static or dynamic storage.
I've also implemented a Fc*Serialize call. Calling FcFontSetSerialize
converts the dynamic FcFontSets contained in the config object to
static FcFontSets and also converts its dependencies (e.g. everything
you'd need to write to disk) to static objects. Note that you have to
call Fc*PrepareSerialize first; this call will count the number of
objects that actually needs to be allocated, so that we can avoid
realloc. The Fc*Serialize calls then check the static pointers for
nullness, and allocate the buffers if necessary. I've tested the
execution of fc-list and fc-match after Fc*Serialize and they appear to
work the same way.
Diffstat (limited to 'src/fcpat.c')
-rw-r--r-- | src/fcpat.c | 866 |
1 files changed, 686 insertions, 180 deletions
diff --git a/src/fcpat.c b/src/fcpat.c index c886c92..af68205 100644 --- a/src/fcpat.c +++ b/src/fcpat.c @@ -25,8 +25,26 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <sys/mman.h> #include "fcint.h" +static FcPattern * fcpatterns = NULL; +static int fcpattern_ptr, fcpattern_count; +static FcPatternElt * fcpatternelts = NULL; +static int fcpatternelt_ptr, fcpatternelt_count; +static FcValueList * fcvaluelists = NULL; +static int fcvaluelist_ptr, fcvaluelist_count; + +static char * object_content; +static int object_content_count; +static int object_content_ptr; + +static FcBool +FcPatternEltIsDynamic (FcPatternEltPtr pei); + +static FcPatternEltPtr +FcPatternEltPtrCreateDynamic (FcPatternElt * e); + FcPattern * FcPatternCreate (void) { @@ -38,7 +56,7 @@ FcPatternCreate (void) FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern)); p->num = 0; p->size = 0; - p->elts = 0; + p->elts = FcPatternEltPtrCreateDynamic(0); p->ref = 1; return p; } @@ -48,16 +66,16 @@ FcValueDestroy (FcValue v) { switch (v.type) { case FcTypeString: - FcStrFree ((FcChar8 *) v.u.s); + FcObjectPtrDestroy (v.u.si); break; case FcTypeMatrix: - FcMatrixFree ((FcMatrix *) v.u.m); + FcMatrixPtrDestroy (v.u.mi); break; case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) v.u.c); + FcCharSetPtrDestroy (v.u.ci); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) v.u.l); + FcLangSetPtrDestroy (v.u.li); break; default: break; @@ -69,23 +87,26 @@ FcValueSave (FcValue v) { switch (v.type) { case FcTypeString: - v.u.s = FcStrCopy (v.u.s); - if (!v.u.s) + v.u.si = FcObjectPtrCreateDynamic(FcStrCopy (FcObjectPtrU(v.u.si))); + if (!FcObjectPtrU(v.u.si)) v.type = FcTypeVoid; break; case FcTypeMatrix: - v.u.m = FcMatrixCopy (v.u.m); - if (!v.u.m) + v.u.mi = FcMatrixPtrCreateDynamic + (FcMatrixCopy (FcMatrixPtrU(v.u.mi))); + if (!FcMatrixPtrU(v.u.mi)) v.type = FcTypeVoid; break; case FcTypeCharSet: - v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c); - if (!v.u.c) + v.u.ci = FcCharSetPtrCreateDynamic + (FcCharSetCopy (FcCharSetPtrU(v.u.ci))); + if (!FcCharSetPtrU(v.u.ci)) v.type = FcTypeVoid; break; case FcTypeLangSet: - v.u.l = FcLangSetCopy (v.u.l); - if (!v.u.l) + v.u.li = FcLangSetPtrCreateDynamic + (FcLangSetCopy (FcLangSetPtrU(v.u.li))); + if (!FcLangSetPtrU(v.u.li)) v.type = FcTypeVoid; break; default: @@ -95,30 +116,34 @@ FcValueSave (FcValue v) } void -FcValueListDestroy (FcValueList *l) +FcValueListDestroy (FcValueListPtr l) { - FcValueList *next; - for (; l; l = next) + FcValueListPtr next; + for (; FcValueListPtrU(l); l = next) { - switch (l->value.type) { + switch (FcValueListPtrU(l)->value.type) { case FcTypeString: - FcStrFree ((FcChar8 *) l->value.u.s); + FcObjectPtrDestroy (FcValueListPtrU(l)->value.u.si); break; case FcTypeMatrix: - FcMatrixFree ((FcMatrix *) l->value.u.m); + FcMatrixPtrDestroy (FcValueListPtrU(l)->value.u.mi); break; case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) l->value.u.c); + FcCharSetDestroy + (FcCharSetPtrU (FcValueListPtrU(l)->value.u.ci)); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) l->value.u.l); + FcLangSetDestroy + (FcLangSetPtrU (FcValueListPtrU(l)->value.u.li)); break; default: break; } - next = l->next; + next = FcValueListPtrU(l)->next; + FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); - free (l); + if (l.storage == FcStorageDynamic) + free(l.u.dyn); } } @@ -148,17 +173,21 @@ FcValueEqual (FcValue va, FcValue vb) case FcTypeDouble: return va.u.d == vb.u.d; case FcTypeString: - return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0; + return FcStrCmpIgnoreCase (FcObjectPtrU(va.u.si), + FcObjectPtrU(vb.u.si)) == 0; case FcTypeBool: return va.u.b == vb.u.b; case FcTypeMatrix: - return FcMatrixEqual (va.u.m, vb.u.m); + return FcMatrixEqual (FcMatrixPtrU(va.u.mi), + FcMatrixPtrU(vb.u.mi)); case FcTypeCharSet: - return FcCharSetEqual (va.u.c, vb.u.c); + return FcCharSetEqual (FcCharSetPtrU(va.u.ci), + FcCharSetPtrU(vb.u.ci)); case FcTypeFTFace: return va.u.f == vb.u.f; case FcTypeLangSet: - return FcLangSetEqual (va.u.l, vb.u.l); + return FcLangSetEqual (FcLangSetPtrU(va.u.li), + FcLangSetPtrU(vb.u.li)); } return FcFalse; } @@ -196,52 +225,57 @@ FcValueHash (FcValue v) case FcTypeDouble: return FcDoubleHash (v.u.d); case FcTypeString: - return FcStringHash (v.u.s); + return FcStringHash (FcObjectPtrU(v.u.si)); case FcTypeBool: return (FcChar32) v.u.b; case FcTypeMatrix: - return (FcDoubleHash (v.u.m->xx) ^ - FcDoubleHash (v.u.m->xy) ^ - FcDoubleHash (v.u.m->yx) ^ - FcDoubleHash (v.u.m->yy)); + { + FcMatrix * m = FcMatrixPtrU(v.u.mi); + return (FcDoubleHash (m->xx) ^ + FcDoubleHash (m->xy) ^ + FcDoubleHash (m->yx) ^ + FcDoubleHash (m->yy)); + } case FcTypeCharSet: - return (FcChar32) v.u.c->num; + return (FcChar32) (FcCharSetPtrU(v.u.ci))->num; case FcTypeFTFace: return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^ FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name); case FcTypeLangSet: - return FcLangSetHash (v.u.l); + return FcLangSetHash (FcLangSetPtrU(v.u.li)); } return FcFalse; } static FcBool -FcValueListEqual (FcValueList *la, FcValueList *lb) +FcValueListEqual (FcValueListPtr la, FcValueListPtr lb) { - if (la == lb) + if (FcValueListPtrU(la) == FcValueListPtrU(lb)) return FcTrue; - while (la && lb) + while (FcValueListPtrU(la) && FcValueListPtrU(lb)) { - if (!FcValueEqual (la->value, lb->value)) + if (!FcValueEqual (FcValueListPtrU(la)->value, + FcValueListPtrU(lb)->value)) return FcFalse; - la = la->next; - lb = lb->next; + la = FcValueListPtrU(la)->next; + lb = FcValueListPtrU(lb)->next; } - if (la || lb) + if (FcValueListPtrU(la) || FcValueListPtrU(lb)) return FcFalse; return FcTrue; } static FcChar32 -FcValueListHash (FcValueList *l) +FcValueListHash (FcValueListPtr l) { FcChar32 hash = 0; - while (l) + while (FcValueListPtrU(l)) { - hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value); - l = l->next; + hash = ((hash << 1) | (hash >> 31)) ^ + FcValueHash (FcValueListPtrU(l)->value); + l = FcValueListPtrU(l)->next; } return hash; } @@ -255,14 +289,14 @@ FcPatternDestroy (FcPattern *p) return; for (i = 0; i < p->num; i++) - FcValueListDestroy (p->elts[i].values); + FcValueListDestroy ((FcPatternEltU(p->elts)+i)->values); p->num = 0; - if (p->elts) + if (FcPatternEltU(p->elts) && FcPatternEltIsDynamic(p->elts)) { FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt)); - free (p->elts); - p->elts = 0; + free (FcPatternEltU(p->elts)); + p->elts = FcPatternEltPtrCreateDynamic(0); } p->size = 0; FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern)); @@ -276,7 +310,7 @@ typedef struct _FcValueListEnt FcValueListEnt; struct _FcValueListEnt { FcValueListEnt *next; - FcValueList *list; + FcValueListPtr list; FcChar32 hash, pad; }; @@ -315,43 +349,54 @@ FcValueListReport (void) } static FcValueListEnt * -FcValueListEntCreate (FcValueList *h) +FcValueListEntCreate (FcValueListPtr h) { FcValueListAlign *ea; FcValueListEnt *e; - FcValueList *l, *new; + FcValueListPtr l; + FcValueList *new; int n; int size; n = 0; - for (l = h; l; l = l->next) + for (l = h; FcValueListPtrU(l); l = FcValueListPtrU(l)->next) n++; size = sizeof (FcValueListAlign) + n * sizeof (FcValueList); - FcValueListFrozenCount[h->value.type]++; - FcValueListFrozenBytes[h->value.type] += size; - ea = malloc (size); + FcValueListFrozenCount[FcValueListPtrU(h)->value.type]++; + FcValueListFrozenBytes[FcValueListPtrU(h)->value.type] += size; + // this leaks for some reason + ea = malloc (sizeof (FcValueListAlign)); if (!ea) return 0; + new = malloc (n * sizeof (FcValueList)); + if (!new) + return 0; + memset(new, 0, n * sizeof (FcValueList)); FcMemAlloc (FC_MEM_VALLIST, size); e = &ea->ent; - e->list = (FcValueList *) (ea + 1); - new = e->list; - for (l = h; l; l = l->next, new++) + e->list = (FcValueListPtr) FcValueListPtrCreateDynamic(new); + for (l = h; FcValueListPtrU(l); + l = FcValueListPtrU(l)->next, new++) { - if (l->value.type == FcTypeString) + if (FcValueListPtrU(l)->value.type == FcTypeString) { new->value.type = FcTypeString; - new->value.u.s = FcObjectStaticName (l->value.u.s); + new->value.u.si = FcObjectStaticName + (FcObjectPtrU(FcValueListPtrU(l)->value.u.si)); } else { - new->value = FcValueSave (l->value); + new->value = FcValueSave (FcValueListPtrU(l)->value); + } + new->binding = FcValueListPtrU(l)->binding; + if (FcValueListPtrU(FcValueListPtrU(l)->next)) + { + new->next = FcValueListPtrCreateDynamic(new + 1); } - new->binding = l->binding; - if (l->next) - new->next = new + 1; else - new->next = 0; + { + new->next = FcValueListPtrCreateDynamic(0); + } } return e; } @@ -359,9 +404,9 @@ FcValueListEntCreate (FcValueList *h) static void FcValueListEntDestroy (FcValueListEnt *e) { - FcValueList *l; + FcValueListPtr l; - FcValueListFrozenCount[e->list->value.type]--; + FcValueListFrozenCount[FcValueListPtrU(e->list)->value.type]--; /* XXX: We should perform these two operations with "size" as computed in FcValueListEntCreate, but we don't have access to @@ -372,10 +417,11 @@ FcValueListEntDestroy (FcValueListEnt *e) FcMemFree (FC_MEM_VALLIST, size); */ - for (l = e->list; l; l = l->next) + for (l = e->list; FcValueListPtrU(l); + l = FcValueListPtrU(l)->next) { - if (l->value.type != FcTypeString) - FcValueDestroy (l->value); + if (FcValueListPtrU(l)->value.type != FcTypeString) + FcValueDestroy (FcValueListPtrU(l)->value); } /* XXX: Are we being too chummy with the implementation here to free(e) when it was actually the enclosing FcValueListAlign @@ -388,8 +434,8 @@ static int FcValueListUsed; static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE]; -static FcValueList * -FcValueListFreeze (FcValueList *l) +static FcValueListPtr +FcValueListFreeze (FcValueListPtr l) { FcChar32 hash = FcValueListHash (l); FcValueListEnt **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE]; @@ -404,7 +450,7 @@ FcValueListFreeze (FcValueList *l) ent = FcValueListEntCreate (l); if (!ent) - return 0; + return FcValueListPtrCreateDynamic(0); FcValueListUsed++; ent->hash = hash; @@ -440,7 +486,8 @@ FcPatternBaseHash (FcPattern *b) int i; for (i = 0; i < b->num; i++) - hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values); + hash = ((hash << 1) | (hash >> 31)) ^ + (long) (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values)); return hash; } @@ -449,7 +496,7 @@ typedef struct _FcPatternEnt FcPatternEnt; struct _FcPatternEnt { FcPatternEnt *next; FcChar32 hash; - FcPattern pattern; + FcPattern *pattern; }; static int FcPatternTotal; @@ -460,55 +507,74 @@ static FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE]; static FcPattern * FcPatternBaseFreeze (FcPattern *b) { + FcPattern *ep; + FcPatternElt *epp; FcChar32 hash = FcPatternBaseHash (b); FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE]; FcPatternEnt *ent; int i; - int size; FcPatternTotal++; for (ent = *bucket; ent; ent = ent->next) { - if (ent->hash == hash && b->num == ent->pattern.num) - { + if (ent->hash == hash && b->num == ent->pattern->num) + { for (i = 0; i < b->num; i++) { - if (b->elts[i].object != ent->pattern.elts[i].object) + if (FcObjectPtrCompare((FcPatternEltU(b->elts)+i)->object, + (FcPatternEltU(ent->pattern->elts)+i)->object) != 0) break; - if (b->elts[i].values != ent->pattern.elts[i].values) + if (FcValueListPtrU((FcPatternEltU(b->elts)+i)->values) != + FcValueListPtrU((FcPatternEltU(ent->pattern->elts)+i)->values)) break; } if (i == b->num) - return &ent->pattern; + return ent->pattern; } } /* * Compute size of pattern + elts */ - size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt); - ent = malloc (size); + ent = malloc (sizeof (FcPatternEnt)); if (!ent) return 0; - FcMemAlloc (FC_MEM_PATTERN, size); + FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPatternEnt)); FcPatternUsed++; - ent->pattern.elts = (FcPatternElt *) (ent + 1); - ent->pattern.num = b->num; - ent->pattern.size = b->num; - ent->pattern.ref = FC_REF_CONSTANT; + ep = FcPatternCreate(); + if (!ep) + return 0; + ent->pattern = ep; + epp = malloc(b->num * sizeof (FcPatternElt)); + if (!epp) + goto bail; + ep->elts = FcPatternEltPtrCreateDynamic(epp); + + FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num)); + + ep->num = b->num; + ep->size = b->num; + ep->ref = FC_REF_CONSTANT; for (i = 0; i < b->num; i++) { - ent->pattern.elts[i].values = b->elts[i].values; - ent->pattern.elts[i].object = b->elts[i].object; + (FcPatternEltU(ep->elts)+i)->values = + (FcPatternEltU(b->elts)+i)->values; + (FcPatternEltU(ep->elts)+i)->object = + (FcPatternEltU(b->elts)+i)->object; } ent->hash = hash; ent->next = *bucket; *bucket = ent; - return &ent->pattern; + return ent->pattern; + bail: + free(ent); + FcMemFree (FC_MEM_PATTERN, sizeof (FcPatternEnt)); + FcPatternUsed--; + return 0; } static void @@ -535,29 +601,36 @@ FcPattern * FcPatternFreeze (FcPattern *p) { FcPattern *b, *n = 0; - int size; + FcPatternElt *e; int i; if (p->ref == FC_REF_CONSTANT) return p; - size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt); - b = (FcPattern *) malloc (size); + b = FcPatternCreate(); if (!b) - return 0; - FcMemAlloc (FC_MEM_PATTERN, size); + return 0; + b->num = p->num; b->size = b->num; b->ref = 1; - b->elts = (FcPatternElt *) (b + 1); + + e = malloc(b->num * sizeof (FcPatternElt)); + if (!e) + return 0; + b->elts = FcPatternEltPtrCreateDynamic(e); + FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num)); + /* * Freeze object lists */ for (i = 0; i < p->num; i++) { - b->elts[i].object = p->elts[i].object; - b->elts[i].values = FcValueListFreeze (p->elts[i].values); - if (!b->elts[i].values) + (FcPatternEltU(b->elts)+i)->object = + (FcPatternEltU(p->elts)+i)->object; + (FcPatternEltU(b->elts)+i)->values = + FcValueListFreeze((FcPatternEltU(p->elts)+i)->values); + if (!FcValueListPtrU((FcPatternEltU(p->elts)+i)->values)) goto bail; } /* @@ -571,8 +644,11 @@ FcPatternFreeze (FcPattern *p) printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed); } #endif -bail: - free (b); + bail: + free(FcPatternEltU(b->elts)); + b->elts = FcPatternEltPtrCreateDynamic(0); + FcMemFree (FC_MEM_PATELT, sizeof (FcPatternElt)*(b->num)); + b->num = -1; #ifdef DEBUG assert (FcPatternEqual (n, p)); #endif @@ -590,8 +666,9 @@ static int FcPatternPosition (const FcPattern *p, const char *object) { int low, high, mid, c; + FcObjectPtr obj; - object = FcObjectStaticName(object); + obj = FcObjectStaticName(object); low = 0; high = p->num - 1; c = 1; @@ -599,7 +676,7 @@ FcPatternPosition (const FcPattern *p, const char *object) while (low <= high) { mid = (low + high) >> 1; - c = p->elts[mid].object - object; + c = FcObjectPtrCompare((FcPatternEltU(p->elts)+mid)->object, obj); if (c == 0) return mid; if (c < 0) @@ -618,7 +695,7 @@ FcPatternFindElt (const FcPattern *p, const char *object) int i = FcPatternPosition (p, object); if (i < 0) return 0; - return &p->elts[i]; + return FcPatternEltU(p->elts)+i; } FcPatternElt * @@ -632,42 +709,52 @@ FcPatternInsertElt (FcPattern *p, const char *object) { i = -i - 1; - /* grow array */ + /* reallocate array */ if (p->num + 1 >= p->size) { int s = p->size + 16; - if (p->elts) - e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt)); + if (FcPatternEltU(p->elts)) + { + FcPatternElt *e0 = FcPatternEltU(p->elts); + e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt)); + if (!e) /* maybe it was mmapped */ + { + e = malloc(s * sizeof (FcPatternElt)); + if (e) + memcpy(e, e0, p->num * sizeof (FcPatternElt)); + } + } else e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt)); if (!e) return FcFalse; - p->elts = e; + p->elts = FcPatternEltPtrCreateDynamic(e); if (p->size) FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt)); FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt)); while (p->size < s) { - p->elts[p->size].object = 0; - p->elts[p->size].values = 0; + (FcPatternEltU(p->elts)+p->size)->object = FcObjectPtrCreateDynamic(0); + (FcPatternEltU(p->elts)+p->size)->values = + FcValueListPtrCreateDynamic(0); p->size++; } } /* move elts up */ - memmove (p->elts + i + 1, - p->elts + i, + memmove (FcPatternEltU(p->elts) + i + 1, + FcPatternEltU(p->elts) + i, sizeof (FcPatternElt) * (p->num - i)); /* bump count */ p->num++; - p->elts[i].object = FcObjectStaticName (object); - p->elts[i].values = 0; + (FcPatternEltU(p->elts)+i)->object = FcObjectStaticName (object); + (FcPatternEltU(p->elts)+i)->values = FcValueListPtrCreateDynamic(0); } - return &p->elts[i]; + return FcPatternEltU(p->elts)+i; } FcBool @@ -682,9 +769,11 @@ FcPatternEqual (const FcPattern *pa, const FcPattern *pb) return FcFalse; for (i = 0; i < pa->num; i++) { - if (pa->elts[i].object != pb->elts[i].object) + if (FcObjectPtrCompare((FcPatternEltU(pa->elts)+i)->object, + (FcPatternEltU(pb->elts)+i)->object) != 0) return FcFalse; - if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values)) + if (!FcValueListEqual ((FcPatternEltU(pa->elts)+i)->values, + (FcPatternEltU(pb->elts)+i)->values)) return FcFalse; } return FcTrue; @@ -699,22 +788,22 @@ FcPatternHash (const FcPattern *p) for (i = 0; i < p->num; i++) { h = (((h << 1) | (h >> 31)) ^ - FcStringHash ((const FcChar8 *) p->elts[i].object) ^ - FcValueListHash (p->elts[i].values)); + FcStringHash ((const FcChar8 *) FcObjectPtrU(((FcPatternEltU(p->elts)+i)->object))) ^ + FcValueListHash ((FcPatternEltU(p->elts)+i)->values)); } return h; } FcBool -FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os) +FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os) { FcPatternElt *ea, *eb; int i; for (i = 0; i < os->nobject; i++) { - ea = FcPatternFindElt (pa, os->objects[i]); - eb = FcPatternFindElt (pb, os->objects[i]); + ea = FcPatternFindElt (pai, FcObjectPtrU(os->objects[i])); + eb = FcPatternFindElt (pbi, FcObjectPtrU(os->objects[i])); if (ea) { if (!eb) @@ -739,24 +828,27 @@ FcPatternAddWithBinding (FcPattern *p, FcBool append) { FcPatternElt *e; - FcValueList *new, **prev; + FcValueListPtr new, *prev; + FcValueList * newp; if (p->ref == FC_REF_CONSTANT) goto bail0; - new = (FcValueList *) malloc (sizeof (FcValueList)); - if (!new) + newp = malloc (sizeof (FcValueList)); + if (!newp) goto bail0; + memset(newp, 0, sizeof (FcValueList)); + new = FcValueListPtrCreateDynamic(newp); FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList)); /* dup string */ value = FcValueSave (value); if (value.type == FcTypeVoid) goto bail1; - new->value = value; - new->binding = binding; - new->next = 0; + FcValueListPtrU(new)->value = value; + FcValueListPtrU(new)->binding = binding; + FcValueListPtrU(new)->next = FcValueListPtrCreateDynamic(0); e = FcPatternInsertElt (p, object); if (!e) @@ -764,12 +856,13 @@ FcPatternAddWithBinding (FcPattern *p, if (append) { - for (prev = &e->values; *prev; prev = &(*prev)->next); + for (prev = &e->values; FcValueListPtrU(*prev); prev = &FcValueListPtrU(*prev)->next) + ; *prev = new; } else { - new->next = e->values; + FcValueListPtrU(new)->next = e->values; e->values = new; } @@ -778,23 +871,23 @@ FcPatternAddWithBinding (FcPattern *p, bail2: switch (value.type) { case FcTypeString: - FcStrFree ((FcChar8 *) value.u.s); + FcStrFree ((FcChar8 *) FcObjectPtrU(value.u.si)); break; case FcTypeMatrix: - FcMatrixFree ((FcMatrix *) value.u.m); + FcMatrixFree (FcMatrixPtrU(value.u.mi)); break; case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) value.u.c); + FcCharSetDestroy (FcCharSetPtrU(value.u.ci)); break; case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) value.u.l); + FcLangSetDestroy (FcLangSetPtrU(value.u.li)); break; default: break; } bail1: FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); - free (new); + free (FcValueListPtrU(new)); bail0: return FcFalse; } @@ -815,42 +908,43 @@ FcBool FcPatternDel (FcPattern *p, const char *object) { FcPatternElt *e; - int i; e = FcPatternFindElt (p, object); if (!e) return FcFalse; - i = e - p->elts; - /* destroy value */ FcValueListDestroy (e->values); /* shuffle existing ones down */ - memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt)); + memmove (e, e+1, + (FcPatternEltU(p->elts) + p->num - (e + 1)) * + sizeof (FcPatternElt)); p->num--; - p->elts[p->num].object = 0; - p->elts[p->num].values = 0; + (FcPatternEltU(p->elts)+p->num)->object = FcObjectPtrCreateDynamic(0); + (FcPatternEltU(p->elts)+p->num)->values = FcValueListPtrCreateDynamic(0); return FcTrue; } FcBool FcPatternRemove (FcPattern *p, const char *object, int id) { - FcPatternElt *e; - FcValueList **prev, *l; + FcPatternElt *e; + FcValueListPtr *prev, l; e = FcPatternFindElt (p, object); if (!e) return FcFalse; - for (prev = &e->values; (l = *prev); prev = &l->next) + for (prev = &e->values; + FcValueListPtrU(l = *prev); + prev = &FcValueListPtrU(l)->next) { if (!id) { - *prev = l->next; - l->next = 0; + *prev = FcValueListPtrU(l)->next; + FcValueListPtrU(l)->next = FcValueListPtrCreateDynamic(0); FcValueListDestroy (l); - if (!e->values) + if (!FcValueListPtrU(e->values)) FcPatternDel (p, object); return FcTrue; } @@ -886,7 +980,7 @@ FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s) FcValue v; v.type = FcTypeString; - v.u.s = s; + v.u.si = FcObjectPtrCreateDynamic(s); return FcPatternAdd (p, object, v, FcTrue); } @@ -896,7 +990,7 @@ FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s) FcValue v; v.type = FcTypeMatrix; - v.u.m = (FcMatrix *) s; + v.u.mi = FcMatrixPtrCreateDynamic((FcMatrix *) s); return FcPatternAdd (p, object, v, FcTrue); } @@ -917,7 +1011,7 @@ FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c) FcValue v; v.type = FcTypeCharSet; - v.u.c = (FcCharSet *) c; + v.u.ci = FcCharSetPtrCreateDynamic((FcCharSet *)c); return FcPatternAdd (p, object, v, FcTrue); } @@ -937,7 +1031,7 @@ FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls) FcValue v; v.type = FcTypeLangSet; - v.u.l = (FcLangSet *) ls; + v.u.li = FcLangSetPtrCreateDynamic((FcLangSet *)ls); return FcPatternAdd (p, object, v, FcTrue); } @@ -945,16 +1039,16 @@ FcResult FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v) { FcPatternElt *e; - FcValueList *l; + FcValueListPtr l; e = FcPatternFindElt (p, object); if (!e) return FcResultNoMatch; - for (l = e->values; l; l = l->next) + for (l = e->values; FcValueListPtrU(l); l = FcValueListPtrU(l)->next) { if (!id) { - *v = l->value; + *v = FcValueListPtrU(l)->value; return FcResultMatch; } id--; @@ -1017,7 +1111,7 @@ FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s return r; if (v.type != FcTypeString) return FcResultTypeMismatch; - *s = (FcChar8 *) v.u.s; + *s = (FcChar8 *) FcObjectPtrU(v.u.si); return FcResultMatch; } @@ -1032,7 +1126,7 @@ FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m) return r; if (v.type != FcTypeMatrix) return FcResultTypeMismatch; - *m = (FcMatrix *) v.u.m; + *m = FcMatrixPtrU(v.u.mi); return FcResultMatch; } @@ -1063,7 +1157,7 @@ FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet ** return r; if (v.type != FcTypeCharSet) return FcResultTypeMismatch; - *c = (FcCharSet *) v.u.c; + *c = FcCharSetPtrU(v.u.ci); return FcResultMatch; } @@ -1093,7 +1187,7 @@ FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet ** return r; if (v.type != FcTypeLangSet) return FcResultTypeMismatch; - *ls = (FcLangSet *) v.u.l; + *ls = FcLangSetPtrU(v.u.li); return FcResultMatch; } @@ -1101,17 +1195,23 @@ FcPattern * FcPatternDuplicate (const FcPattern *orig) { FcPattern *new; + FcPatternElt *e; int i; - FcValueList *l; + FcValueListPtr l; new = FcPatternCreate (); if (!new) goto bail0; + e = FcPatternEltU(orig->elts); + for (i = 0; i < orig->num; i++) { - for (l = orig->elts[i].values; l; l = l->next) - if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue)) + for (l = (e + i)->values; + FcValueListPtrU(l); + l = FcValueListPtrU(l)->next) + if (!FcPatternAdd (new, FcObjectPtrU((e + i)->object), + FcValueListPtrU(l)->value, FcTrue)) goto bail1; } @@ -1158,45 +1258,451 @@ FcPatternAppend (FcPattern *p, FcPattern *s) { int i; FcPatternElt *e; - FcValueList *v; + FcValueListPtr v; for (i = 0; i < s->num; i++) { - e = &s->elts[i]; - for (v = e->values; v; v = v->next) + e = FcPatternEltU(s->elts)+i; + for (v = e->values; FcValueListPtrU(v); + v = FcValueListPtrU(v)->next) { - if (!FcPatternAddWithBinding (p, e->object, - v->value, v->binding, FcTrue)) + if (!FcPatternAddWithBinding (p, FcObjectPtrU(e->object), + FcValueListPtrU(v)->value, + FcValueListPtrU(v)->binding, FcTrue)) return FcFalse; } } return FcTrue; } -const char * +#define OBJECT_HASH_SIZE 31 +struct objectBucket { + struct objectBucket *next; + FcChar32 hash; +}; +static struct objectBucket **buckets = 0; + +FcObjectPtr FcObjectStaticName (const char *name) { -#define OBJECT_HASH_SIZE 31 - static struct objectBucket { - struct objectBucket *next; - FcChar32 hash; - } *buckets[OBJECT_HASH_SIZE]; FcChar32 hash = FcStringHash ((const FcChar8 *) name); struct objectBucket **p; struct objectBucket *b; + const char * nn; int size; + FcObjectPtr new; + + if (!buckets) + { + buckets = malloc(sizeof (struct objectBucket *)*OBJECT_HASH_SIZE); + memset (buckets, 0, sizeof (struct objectBucket *)*OBJECT_HASH_SIZE); + } for (p = &buckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) - if (b->hash == hash && !strcmp (name, (char *) (b + 1))) - return (char *) (b + 1); - size = sizeof (struct objectBucket) + strlen (name) + 1; + if (b->hash == hash && !strcmp (name, FcObjectPtrU(*((FcObjectPtr *) (b + 1))))) + return *((FcObjectPtr *) (b + 1)); + size = sizeof (struct objectBucket) + sizeof (FcObjectPtr) + 1; b = malloc (size); FcMemAlloc (FC_MEM_STATICSTR, size); if (!b) - return NULL; + return FcObjectPtrCreateDynamic(0); b->next = 0; b->hash = hash; - strcpy ((char *) (b + 1), name); + nn = malloc(strlen(name)+1); + if (!nn) + goto bail; + strcpy ((char *)nn, name); + new = FcObjectPtrCreateDynamic ((char *) nn); + *((FcObjectPtr *)(b+1)) = new; *p = b; - return (char *) (b + 1); + return new; + + bail: + free(b); + return FcObjectPtrCreateDynamic(0); +} + +FcPatternElt * +FcPatternEltU (FcPatternEltPtr pei) +{ + switch (pei.storage) + { + case FcStorageStatic: + if (pei.u.stat == 0) return 0; + return &fcpatternelts[pei.u.stat]; + case FcStorageDynamic: + return pei.u.dyn; + default: + return 0; + } +} + +static FcPatternEltPtr +FcPatternEltPtrCreateDynamic (FcPatternElt * e) +{ + FcPatternEltPtr new; + new.storage = FcStorageDynamic; + new.u.dyn = e; + return new; +} + +static FcPatternEltPtr +FcPatternEltPtrCreateStatic (int i) +{ + FcPatternEltPtr new; + new.storage = FcStorageStatic; + new.u.stat = i; + return new; +} + +static FcBool +FcPatternEltIsDynamic (FcPatternEltPtr pei) +{ + return pei.storage == FcStorageDynamic; +} + +struct objectTree { + struct objectTree * left, * right; + char * s; +}; + +FcObjectPtr +FcObjectPtrCreateDynamic (const char * s) +{ + FcObjectPtr new; + new.storage = FcStorageDynamic; + new.u.dyn = s; + if (s) + new.hash = FcStringHash(s); + else + new.hash = 0; + return new; +} + +void +FcObjectPtrDestroy (FcObjectPtr p) +{ + if (p.storage == FcStorageDynamic) + FcStrFree ((char *)p.u.dyn); +} + +const char * +FcObjectPtrU (FcObjectPtr si) +{ + switch (si.storage) + { + case FcStorageStatic: + if (si.u.stat == 0) return 0; + return &object_content[si.u.stat]; + case FcStorageDynamic: + return si.u.dyn; + default: + return 0; + } +} + +int +FcObjectPtrCompare (const FcObjectPtr a, const FcObjectPtr b) +{ + int r = a.hash - b.hash; + + if (r == 0) + return strcmp (FcObjectPtrU(a), FcObjectPtrU(b)); + return r; +} + +void +FcObjectClearStatic(void) +{ + object_content = 0; + object_content_count = 0; + object_content_ptr = 0; +} + +static FcObjectPtr +FcObjectSerialize (FcObjectPtr si) +{ + struct objectBucket **p; + struct objectBucket *b; + + if (!object_content) + { + object_content = malloc(object_content_count * sizeof(char)); + if (!object_content) + return FcObjectPtrCreateDynamic(0); + } + + if (!buckets) + return FcObjectPtrCreateDynamic(0); + + for (p = &buckets[si.hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) + if (b->hash == si.hash && !strcmp (FcObjectPtrU(si), FcObjectPtrU(*((FcObjectPtr *) (b + 1))))) + { + FcObjectPtr *op = (FcObjectPtr *) (b + 1); + if (op->storage == FcStorageStatic) + return *op; + + if (object_content_ptr >= object_content_count) + return FcObjectPtrCreateDynamic(0); + + strcpy (object_content+object_content_ptr, + FcObjectPtrU(si)); + + op->storage = FcStorageStatic; + op->u.stat = object_content_ptr; + + object_content_ptr += strlen(FcObjectPtrU(si))+1; + + return *op; + } + + return FcObjectPtrCreateDynamic(0); +} + +FcBool +FcObjectPrepareSerialize (FcObjectPtr si) +{ + object_content_count += strlen(FcObjectPtrU(si)) + 1; + return FcTrue; +} + +void +FcPatternClearStatic (void) +{ + fcpatterns = 0; + fcpattern_ptr = 0; + fcpattern_count = 0; + + fcpatternelts = 0; + fcpatternelt_ptr = 0; + fcpatternelt_count = 0; +} + +void +FcValueListClearStatic (void) +{ + fcvaluelists = 0; + fcvaluelist_ptr = 0; + fcvaluelist_count = 0; +} + +FcBool +FcPatternPrepareSerialize (FcPattern * p) +{ + int i; + + fcpattern_count++; + fcpatternelt_count += p->num; + + for (i = 0; i < p->num; i++) + { + FcObjectPrepareSerialize + ((FcPatternEltU(p->elts)+i)->object); + if (!FcValueListPrepareSerialize + (FcValueListPtrU(((FcPatternEltU(p->elts)+i)->values)))) + return FcFalse; + } + + return FcTrue; +} + +FcBool +FcValueListPrepareSerialize (FcValueList *p) +{ + FcValueList *vl; + + for (vl = p; + vl; + vl = FcValueListPtrU(vl->next)) + { + FcValue v = vl->value; + + switch (v.type) + { + case FcTypeMatrix: + FcMatrixPrepareSerialize(FcMatrixPtrU(v.u.mi)); + break; + case FcTypeCharSet: + FcCharSetPrepareSerialize(FcCharSetPtrU(v.u.ci)); + break; + case FcTypeLangSet: + FcLangSetPrepareSerialize(FcLangSetPtrU(v.u.li)); + break; + case FcTypeString: + FcObjectPrepareSerialize(v.u.si); + default: + break; + } + fcvaluelist_count++; + } + + return FcTrue; +} + +FcPattern * +FcPatternSerialize (FcPattern *old) +{ + FcPattern *p; + FcPatternElt *e, *nep; + FcValueList * nv; + FcValueListPtr v, nv_head, nvp; + int i, elts; + + if (!fcpatterns) + { + p = malloc (sizeof (FcPattern) * fcpattern_count); + if (!p) + goto bail; + + FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * fcpattern_count); + fcpatterns = p; + fcpattern_ptr = 0; + + e = malloc (sizeof (FcPatternElt) * fcpatternelt_count); + if (!e) + goto bail1; + + FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt) * fcpatternelt_count); + fcpatternelts = e; + fcpatternelt_ptr = 0; + } + + p = FcPatternCreate(); + elts = fcpatternelt_ptr; + nep = &fcpatternelts[elts]; + if (!nep) + return FcFalse; + fcpatternelt_ptr += old->num; + + for (e = FcPatternEltU(old->elts), i=0; i < old->num; i++, e++) + { + v = e->values; + nvp = nv_head = FcValueListSerialize(FcValueListPtrU(v)); + if (!FcValueListPtrU(nv_head)) + goto bail2; + nv = FcValueListPtrU(nvp); + + for (; + FcValueListPtrU(v); + v = FcValueListPtrU(v)->next, + nv = FcValueListPtrU(nv->next)) + { + + if (FcValueListPtrU(FcValueListPtrU(v)->next)) + { + nvp = FcValueListSerialize + (FcValueListPtrU(FcValueListPtrU(v)->next)); + nv->next = nvp; + } + } + + nep[i].values = nv_head; + nep[i].object = FcObjectSerialize + (FcObjectStaticName(FcObjectPtrU(e->object))); + } + + p->elts = FcPatternEltPtrCreateStatic(elts); + p->size = old->num; + p->ref = FC_REF_CONSTANT; + return p; + + bail2: + free (fcpatternelts); + bail1: + free (fcpatterns); + bail: + return 0; + } + +FcValueListPtr +FcValueListSerialize(FcValueList *pi) +{ + FcValueListPtr new; + FcValue * v; + FcValueList * vl; + + if (!fcvaluelists) + { + vl = malloc (sizeof (FcValueList) * fcvaluelist_count); + if (!vl) + return FcValueListPtrCreateDynamic(0); + + FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList) * fcvaluelist_count); + fcvaluelists = vl; + fcvaluelist_ptr = 0; + } + + fcvaluelists[fcvaluelist_ptr] = *pi; + new.storage = FcStorageStatic; + new.u.stat = fcvaluelist_ptr++; + v = &fcvaluelists[new.u.stat].value; + switch (v->type) + { + case FcTypeString: + if (FcObjectPtrU(v->u.si)) + { + FcObjectPtr si = + FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v->u.si))); + if (!FcObjectPtrU(v->u.si)) + return FcValueListPtrCreateDynamic(pi); + v->u.si = si; + } + break; + case FcTypeMatrix: + if (FcMatrixPtrU(v->u.mi)) + { + FcMatrixPtr mi = FcMatrixSerialize(FcMatrixPtrU(v->u.mi)); + + if (!FcMatrixPtrU(mi)) + return FcValueListPtrCreateDynamic(pi); + v->u.mi = mi; + } + break; + case FcTypeCharSet: + if (FcCharSetPtrU(v->u.ci)) + { + FcCharSetPtr ci = FcCharSetSerialize(FcCharSetPtrU(v->u.ci)); + if (!FcCharSetPtrU(v->u.ci)) + return FcValueListPtrCreateDynamic(pi); + v->u.ci = ci; + } + break; + case FcTypeLangSet: + if (FcLangSetPtrU(v->u.li)) + { + FcLangSetPtr li = FcLangSetSerialize(FcLangSetPtrU(v->u.li)); + if (!FcLangSetPtrU(v->u.li)) + return FcValueListPtrCreateDynamic(pi); + v->u.li = li; + } + break; + default: + break; + } + return new; +} + +FcValueList * +FcValueListPtrU (FcValueListPtr pi) +{ + switch (pi.storage) + { + case FcStorageStatic: + if (pi.u.stat == 0) return 0; + return &fcvaluelists[pi.u.stat]; + case FcStorageDynamic: + return pi.u.dyn; + default: + return 0; + } +} + +FcValueListPtr +FcValueListPtrCreateDynamic(FcValueList * p) +{ + FcValueListPtr r; + + r.storage = FcStorageDynamic; + r.u.dyn = p; + return r; } |