Replace static strings with reference counted strings. --- fontconfig-2.8.0/src/fccfg.c.2.8.0 2010-03-03 16:37:56.000000000 +1300 +++ fontconfig-2.8.0/src/fccfg.c 2010-03-03 18:08:14.000000000 +1300 @@ -999,17 +999,17 @@ FcConfigEvaluate (FcPattern *p, FcExpr * break; } break; case FcTypeString: switch (e->op) { case FcOpPlus: v.type = FcTypeString; str = FcStrPlus (vl.u.s, vr.u.s); - v.u.s = FcStrStaticName (str); + v.u.s = FcSharedStr (str); FcStrFree (str); if (!v.u.s) v.type = FcTypeVoid; break; default: v.type = FcTypeVoid; break; --- fontconfig-2.8.0/src/fcinit.c.2.8.0 2010-03-03 17:20:37.000000000 +1300 +++ fontconfig-2.8.0/src/fcinit.c 2010-03-03 19:04:30.000000000 +1300 @@ -134,17 +134,17 @@ FcInit (void) * Free all library-allocated data structures. */ void FcFini (void) { if (_fcConfig) FcConfigDestroy (_fcConfig); - FcPatternFini (); + FcObjectFini (); FcCacheFini (); if (FcDebug() & FC_DBG_MEMORY) FcMemReport (); } /* * Reread the configuration and available font lists */ @@ -216,17 +216,17 @@ static struct { { "subst" }, { "objecttype" }, { "constant" }, { "test" }, { "expr" }, { "vstack" }, { "attr" }, { "pstack" }, - { "staticstr" }, + { "sharedstr" }, }; static int FcAllocCount, FcAllocMem; static int FcFreeCount, FcFreeMem; static int FcMemNotice = 1*1024*1024; static int FcAllocNotify, FcFreeNotify; --- fontconfig-2.8.0/src/fcint.h.2.8.0 2010-03-03 16:37:46.000000000 +1300 +++ fontconfig-2.8.0/src/fcint.h 2010-03-03 19:05:17.000000000 +1300 @@ -98,17 +98,17 @@ #define FC_MEM_SUBST 21 #define FC_MEM_OBJECTTYPE 22 #define FC_MEM_CONSTANT 23 #define FC_MEM_TEST 24 #define FC_MEM_EXPR 25 #define FC_MEM_VSTACK 26 #define FC_MEM_ATTR 27 #define FC_MEM_PSTACK 28 -#define FC_MEM_STATICSTR 29 +#define FC_MEM_SHAREDSTR 29 #define FC_MEM_NUM 30 #define FC_MIN(a,b) ((a) < (b) ? (a) : (b)) #define FC_MAX(a,b) ((a) > (b) ? (a) : (b)) #define FC_ABS(a) ((a) < 0 ? -(a) : (a)) /* slim_internal.h */ @@ -230,17 +230,17 @@ typedef enum _FcOp { FcOpInvalid } FcOp; typedef struct _FcExpr { FcOp op; union { int ival; double dval; - FcChar8 *sval; + const FcChar8 *sval; FcMatrix *mval; FcBool bval; FcCharSet *cval; FcObject object; FcChar8 *constant; struct { struct _FcExpr *left, *right; } tree; @@ -935,24 +935,24 @@ FcPrivate FcResult FcPatternObjectGetCharSet (const FcPattern *p, FcObject object, int n, FcCharSet **c); FcPrivate FcResult FcPatternObjectGetBool (const FcPattern *p, FcObject object, int n, FcBool *b); FcPrivate FcResult FcPatternObjectGetLangSet (const FcPattern *p, FcObject object, int n, FcLangSet **ls); -FcPrivate void -FcPatternFini (void); - FcPrivate FcBool FcPatternAppend (FcPattern *p, FcPattern *s); FcPrivate const FcChar8 * -FcStrStaticName (const FcChar8 *name); +FcSharedStr (const FcChar8 *name); + +FcPrivate FcBool +FcSharedStrFree (const FcChar8 *name); FcPrivate FcChar32 FcStringHash (const FcChar8 *s); FcPrivate FcBool FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat); FcPrivate FcPattern * --- fontconfig-2.8.0/src/fclist.c.2.8.0 2010-03-03 16:33:22.000000000 +1300 +++ fontconfig-2.8.0/src/fclist.c 2010-03-03 18:08:14.000000000 +1300 @@ -62,23 +62,25 @@ FcObjectSetAdd (FcObjectSet *os, const c FcMemAlloc (FC_MEM_OBJECTPTR, s * sizeof (const char *)); os->objects = objects; os->sobject = s; } high = os->nobject - 1; low = 0; mid = 0; c = 1; - object = (char *)FcStrStaticName ((FcChar8 *)object); + object = (char *)FcSharedStr ((FcChar8 *)object); while (low <= high) { mid = (low + high) >> 1; c = os->objects[mid] - object; - if (c == 0) + if (c == 0) { + FcSharedStrFree ((FcChar8 *)object); return FcTrue; + } if (c < 0) low = mid + 1; else high = mid - 1; } if (c < 0) mid++; memmove (os->objects + mid + 1, os->objects + mid, @@ -86,18 +88,23 @@ FcObjectSetAdd (FcObjectSet *os, const c os->objects[mid] = object; os->nobject++; return FcTrue; } void FcObjectSetDestroy (FcObjectSet *os) { + int i; + if (os->objects) { + for (i = 0; i < os->nobject; i++) + FcSharedStrFree ((FcChar8 *)os->objects[i]); + FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *)); free ((void *) os->objects); } FcMemFree (FC_MEM_OBJECTSET, sizeof (FcObjectSet)); free (os); } FcObjectSet * --- fontconfig-2.8.0/src/fcname.c.2.8.0 2010-03-03 16:37:35.000000000 +1300 +++ fontconfig-2.8.0/src/fcname.c 2010-03-03 18:08:14.000000000 +1300 @@ -569,41 +569,42 @@ FcNameBool (const FcChar8 *v, FcBool *re *result = FcFalse; return FcTrue; } } return FcFalse; } static FcValue -FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m) +FcNameConvert (FcType type, FcChar8 *string) { FcValue v; + FcMatrix m; v.type = type; switch (v.type) { case FcTypeInteger: if (!FcNameConstant (string, &v.u.i)) v.u.i = atoi ((char *) string); break; case FcTypeString: - v.u.s = FcStrStaticName(string); + v.u.s = FcSharedStr (string); if (!v.u.s) v.type = FcTypeVoid; break; case FcTypeBool: if (!FcNameBool (string, &v.u.b)) v.u.b = FcFalse; break; case FcTypeDouble: v.u.d = strtod ((char *) string, 0); break; case FcTypeMatrix: - v.u.m = m; - sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy); + sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy); + v.u.m = FcMatrixCopy (&m); break; case FcTypeCharSet: v.u.c = FcNameParseCharSet (string); if (!v.u.c) v.type = FcTypeVoid; break; case FcTypeLangSet: v.u.l = FcNameParseLangSet (string); @@ -645,17 +646,16 @@ FcPattern * FcNameParse (const FcChar8 *name) { FcChar8 *save; FcPattern *pat; double d; FcChar8 *e; FcChar8 delim; FcValue v; - FcMatrix m; const FcObjectType *t; const FcConstant *c; /* freed below */ save = malloc (strlen ((char *) name) + 1); if (!save) goto bail0; pat = FcPatternCreate (); @@ -696,41 +696,23 @@ FcNameParse (const FcChar8 *name) if (delim == '=' || delim == '_') { t = FcNameGetObjectType ((char *) save); for (;;) { name = FcNameFindNext (name, ":,", save, &delim); if (t) { - v = FcNameConvert (t->type, save, &m); + v = FcNameConvert (t->type, save); if (!FcPatternAdd (pat, t->object, v, FcTrue)) { - switch (v.type) { - case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) v.u.c); - break; - case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) v.u.l); - break; - default: - break; - } + FcValueDestroy (v); goto bail2; } - switch (v.type) { - case FcTypeCharSet: - FcCharSetDestroy ((FcCharSet *) v.u.c); - break; - case FcTypeLangSet: - FcLangSetDestroy ((FcLangSet *) v.u.l); - break; - default: - break; - } + FcValueDestroy (v); } if (delim != ',') break; } } else { if ((c = FcNameGetConstant (save))) --- fontconfig-2.8.0/src/fcpat.c.2.8.0 2010-03-03 16:38:06.000000000 +1300 +++ fontconfig-2.8.0/src/fcpat.c 2010-03-03 19:05:43.000000000 +1300 @@ -21,19 +21,16 @@ */ #include "fcint.h" #include "fcftint.h" #include #include #include -static FcBool -FcHashOwnsName(const FcChar8 *name); - FcPattern * FcPatternCreate (void) { FcPattern *p; p = (FcPattern *) malloc (sizeof (FcPattern)); if (!p) return 0; @@ -45,17 +42,17 @@ FcPatternCreate (void) return p; } void FcValueDestroy (FcValue v) { switch (v.type) { case FcTypeString: - if (!FcHashOwnsName(v.u.s)) + if (!FcSharedStrFree (v.u.s)) FcStrFree ((FcChar8 *) v.u.s); break; case FcTypeMatrix: FcMatrixFree ((FcMatrix *) v.u.m); break; case FcTypeCharSet: FcCharSetDestroy ((FcCharSet *) v.u.c); break; @@ -93,17 +90,17 @@ FcValueCanonicalize (const FcValue *v) return new; } FcValue FcValueSave (FcValue v) { switch (v.type) { case FcTypeString: - v.u.s = FcStrStaticName (v.u.s); + v.u.s = FcSharedStr (v.u.s); if (!v.u.s) v.type = FcTypeVoid; break; case FcTypeMatrix: v.u.m = FcMatrixCopy (v.u.m); if (!v.u.m) v.type = FcTypeVoid; break; @@ -126,17 +123,17 @@ FcValueSave (FcValue v) void FcValueListDestroy (FcValueListPtr l) { FcValueListPtr next; for (; l; l = next) { switch (l->value.type) { case FcTypeString: - if (!FcHashOwnsName((FcChar8 *)l->value.u.s)) + if (!FcSharedStrFree ((FcChar8 *)l->value.u.s)) FcStrFree ((FcChar8 *)l->value.u.s); break; case FcTypeMatrix: FcMatrixFree ((FcMatrix *)l->value.u.m); break; case FcTypeCharSet: FcCharSetDestroy ((FcCharSet *) (l->value.u.c)); @@ -647,17 +644,17 @@ FcPatternObjectAddString (FcPattern *p, if (!s) { v.type = FcTypeVoid; v.u.s = 0; return FcPatternObjectAdd (p, object, v, FcTrue); } v.type = FcTypeString; - v.u.s = FcStrStaticName(s); + v.u.s = s; return FcPatternObjectAdd (p, object, v, FcTrue); } FcBool FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s) { return FcPatternObjectAddString (p, FcObjectFromName (object), s); } @@ -1025,83 +1022,68 @@ bail0: FcPatternDestroy (ret); return NULL; } #define OBJECT_HASH_SIZE 31 static struct objectBucket { struct objectBucket *next; FcChar32 hash; + int ref_count; } *FcObjectBuckets[OBJECT_HASH_SIZE]; -static FcBool -FcHashOwnsName (const FcChar8 *name) +FcBool +FcSharedStrFree (const FcChar8 *name) { FcChar32 hash = FcStringHash (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 && ((char *)name == (char *) (b + 1))) + if (b->hash == hash && ((char *)name == (char *) (b + 1))) { + b->ref_count--; + if (!b->ref_count) { + *p = b->next; + size = sizeof (struct objectBucket) + strlen ((char *)name) + 1; + FcMemFree (FC_MEM_SHAREDSTR, size + sizeof (int)); + free (b); + } return FcTrue; + } return FcFalse; } const FcChar8 * -FcStrStaticName (const FcChar8 *name) +FcSharedStr (const FcChar8 *name) { FcChar32 hash = FcStringHash (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 ((char *)name, (char *) (b + 1))) + if (b->hash == hash && !strcmp ((char *)name, (char *) (b + 1))) { + b->ref_count++; return (FcChar8 *) (b + 1); + } size = sizeof (struct objectBucket) + strlen ((char *)name) + 1; b = malloc (size + sizeof (int)); /* workaround glibc bug which reads strlen in groups of 4 */ - FcMemAlloc (FC_MEM_STATICSTR, size + sizeof (int)); + FcMemAlloc (FC_MEM_SHAREDSTR, size + sizeof (int)); if (!b) return NULL; b->next = 0; b->hash = hash; + b->ref_count = 1; strcpy ((char *) (b + 1), (char *)name); *p = b; return (FcChar8 *) (b + 1); } -static void -FcStrStaticNameFini (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 + sizeof (int)); - free (b); - } - FcObjectBuckets[i] = 0; - } -} - -void -FcPatternFini (void) -{ - FcStrStaticNameFini (); - FcObjectFini (); -} - FcBool FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat) { int i; FcPatternElt *elts = FcPatternElts(pat); if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern))) return FcFalse; --- fontconfig-2.8.0/src/fcxml.c.2.8.0 2010-03-03 16:38:13.000000000 +1300 +++ fontconfig-2.8.0/src/fcxml.c 2010-03-03 18:23:16.000000000 +1300 @@ -99,17 +99,17 @@ FcExprCreateDouble (FcConfig *config, do static FcExpr * FcExprCreateString (FcConfig *config, const FcChar8 *s) { FcExpr *e = FcConfigAllocExpr (config); if (e) { e->op = FcOpString; - e->u.sval = FcStrStaticName (s); + e->u.sval = FcSharedStr (s); } return e; } static FcExpr * FcExprCreateMatrix (FcConfig *config, const FcMatrix *m) { FcExpr *e = FcConfigAllocExpr (config); @@ -147,17 +147,17 @@ FcExprCreateField (FcConfig *config, con static FcExpr * FcExprCreateConst (FcConfig *config, const FcChar8 *constant) { FcExpr *e = FcConfigAllocExpr (config); if (e) { e->op = FcOpConst; - e->u.constant = FcStrStaticName (constant); + e->u.constant = FcSharedStr (constant); } return e; } static FcExpr * FcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right) { FcExpr *e = FcConfigAllocExpr (config); @@ -176,28 +176,30 @@ FcExprDestroy (FcExpr *e) if (!e) return; switch (e->op) { case FcOpInteger: break; case FcOpDouble: break; case FcOpString: + FcSharedStrFree (e->u.sval); break; case FcOpMatrix: FcMatrixFree (e->u.mval); break; case FcOpCharSet: FcCharSetDestroy (e->u.cval); break; case FcOpBool: break; case FcOpField: break; case FcOpConst: + FcSharedStrFree (e->u.constant); break; case FcOpAssign: case FcOpAssignReplace: case FcOpPrepend: case FcOpPrependFirst: case FcOpAppend: case FcOpAppendLast: break; @@ -1904,17 +1906,17 @@ FcPopValue (FcConfigParse *parse) value.type = FcTypeVoid; if (!vstack) return value; switch (vstack->tag) { case FcVStackString: - value.u.s = FcStrStaticName (vstack->u.string); + value.u.s = FcSharedStr (vstack->u.string); if (value.u.s) value.type = FcTypeString; break; case FcVStackConstant: if (FcNameConstant (vstack->u.string, &value.u.i)) value.type = FcTypeInteger; break; case FcVStackInteger: