]> git.wh0rd.org Git - fontconfig.git/commitdiff
Rework Object name database to unify typechecking and object lookup.
authorKeith Packard <keithp@neko.keithp.com>
Thu, 31 Aug 2006 01:50:58 +0000 (18:50 -0700)
committerKeith Packard <keithp@neko.keithp.com>
Thu, 31 Aug 2006 01:50:58 +0000 (18:50 -0700)
Eliminate ancient list of object name databases and load names into single
hash table that includes type information. Typecheck all pattern values to
avoid mis-typed pattern elements.

fc-case/fc-case.c
src/fcint.h
src/fcmatch.c
src/fcname.c
src/fcpat.c

index bd28517f49233610f6e73e879300d5bcd603fb45..a4fffdef76d745aab0d2aacb06d86457498c6459 100644 (file)
 #define MAX_OUT            32
 #define MAX_LINE    8192
 
-/* stub definitions for declarations from fcint.h.. */
-int * _fcBankId = 0, * _fcBankIdx = 0;
-FcValueList ** _fcValueLists = 0;
-FcPatternElt ** _fcPatternElts = 0;
-int FcDebugVal = 0;
-
-int
-FcCacheBankToIndexMTF (int bank)
-{
-    return 0;
-}
-/* end stub definitions */
-
 typedef enum _caseFoldClass { CaseFoldCommon, CaseFoldFull, CaseFoldSimple, CaseFoldTurkic } CaseFoldClass;
 
 typedef struct _caseFoldClassMap {
index adb3b16b5f47ef499c89ad628863c4e9e3e2df04..c62a5bb370fddf7694e0e3a92d1ed0bce223b255 100644 (file)
@@ -858,10 +858,13 @@ FcObjectFromName (const char * name);
 const char *
 FcObjectName (FcObject object);
 
-#define FcObjectCompare(a, b)  ((int) a - (int) b)
+FcBool
+FcObjectInit (void);
 
 void
-FcObjectStaticNameFini (void);
+FcObjectFini (void);
+
+#define FcObjectCompare(a, b)  ((int) a - (int) b)
 
 /* fcpat.c */
 
index 7e3353b3d42e610b1e5ba6a387eee20aeb08de76..d688c98b9eaad659f8cb19f0dc1d070b6f0a9ba2 100644 (file)
@@ -313,7 +313,7 @@ FcCompareValueList (FcObject         object,
     j = 0;
     for (v1 = v1orig; v1; v1 = FcValueListNext(v1))
     {
-       for (v2 = v1orig; v2; v2 = FcValueListNext(v2))
+       for (v2 = v2orig; v2; v2 = FcValueListNext(v2))
        {
            v = (match->compare) (&v1->value, &v2->value);
            if (v < 0)
@@ -608,7 +608,7 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool tri
                 }
 
                FcPatternReference (node->pattern);
-               if (FcDebug () & FC_DBG_MATCH)
+               if (FcDebug () & FC_DBG_MATCHV)
                {
                    printf ("Add ");
                    FcPatternPrint (node->pattern);
@@ -788,6 +788,11 @@ FcFontSetSort (FcConfig        *config,
 
     free (nodes);
 
+    if (FcDebug() & FC_DBG_MATCH)
+    {
+       printf ("First font ");
+       FcPatternPrint (ret->fonts[0]);
+    }
     return ret;
 
 bail2:
index 96adc62ee34fb14c104b70649c46a85ed68e13c5..74411d7253234c8eefd02cb42ddfb176ab608782 100644 (file)
 #include <string.h>
 #include <stdio.h>
 
-/* Please do not revoke any of these bindings. */
-/* The __DUMMY__ object enables callers to distinguish the error return
- * of FcObjectToPtrLookup from FC_FAMILY's FcObject, which would
- * otherwise be 0. */
+/* 
+ * Please do not change this list, it is used to initialize the object
+ * list in this order to match the FC_foo_OBJECT constants. Those 
+ * constants are written into cache files.
+ */
+
 static const FcObjectType _FcBaseObjectTypes[] = {
-    { "__DUMMY__",      FcTypeVoid, }, 
-    { FC_FAMILY,       FcTypeString, },
+    { FC_FAMILY,       FcTypeString, },    /* 1 */
     { FC_FAMILYLANG,   FcTypeString, },
     { FC_STYLE,                FcTypeString, },
     { FC_STYLELANG,    FcTypeString, },
@@ -72,253 +73,303 @@ static const FcObjectType _FcBaseObjectTypes[] = {
     { FC_CAPABILITY,   FcTypeString },
     { FC_FONTFORMAT,   FcTypeString },
     { FC_EMBOLDEN,     FcTypeBool },
-    { FC_EMBEDDED_BITMAP,   FcTypeBool },
+    { FC_EMBEDDED_BITMAP,   FcTypeBool }, /* 39 */
 };
 
 #define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
 
-static FcObjectType * _FcUserObjectNames = 0;
-static int user_obj_alloc = 0;
-static int next_basic_offset = NUM_OBJECT_TYPES;
-
 typedef struct _FcObjectTypeList    FcObjectTypeList;
 
 struct _FcObjectTypeList {
     const FcObjectTypeList  *next;
     const FcObjectType     *types;
     int                            ntypes;
-    int                            basic_offset;
 };
 
 static const FcObjectTypeList _FcBaseObjectTypesList = {
     0,
     _FcBaseObjectTypes,
     NUM_OBJECT_TYPES,
-    0
 };
 
 static const FcObjectTypeList  *_FcObjectTypes = &_FcBaseObjectTypesList;
 
-FcBool
-FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
-{
-    FcObjectTypeList   *l;
+#define OBJECT_HASH_SIZE    31
 
-    l = (FcObjectTypeList *) malloc (sizeof (FcObjectTypeList));
-    if (!l)
-       return FcFalse;
-    FcMemAlloc (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
-    l->types = types;
-    l->ntypes = ntypes;
-    l->next = _FcObjectTypes;
-    l->basic_offset = next_basic_offset;
-    next_basic_offset += ntypes;
-    _FcObjectTypes = l;
-    return FcTrue;
-}
+typedef struct _FcObjectBucket {
+    struct _FcObjectBucket  *next;
+    FcChar32               hash;
+    FcObject               id;
+} FcObjectBucket;
 
-static FcBool
-FcNameUnregisterObjectTypesFree (const FcObjectType *types, int ntypes, 
-                                FcBool do_free)
-{
-    const FcObjectTypeList     *l, **prev;
+static FcObjectBucket  *FcObjectBuckets[OBJECT_HASH_SIZE];
 
-    for (prev = &_FcObjectTypes; 
-        (l = *prev); 
-        prev = (const FcObjectTypeList **) &(l->next))
+static FcObjectType    *FcObjects = (FcObjectType *) _FcBaseObjectTypes;
+static int             FcObjectsNumber = NUM_OBJECT_TYPES;
+static int             FcObjectsSize = 0;
+static FcBool          FcObjectsInited;
+
+static FcObjectType *
+FcObjectInsert (const char *name, FcType type)
+{
+    FcObjectType    *o;
+    if (FcObjectsNumber >= FcObjectsSize)
     {
-       if (l->types == types && l->ntypes == ntypes)
+       int             newsize = FcObjectsNumber * 2;
+       FcObjectType    *newobjects;
+       
+       if (FcObjectsSize)
+           newobjects = realloc (FcObjects, newsize * sizeof (FcObjectType));
+       else
        {
-           *prev = l->next;
-           if (do_free) {
-               FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
-               free ((void *) l);
-           }
-           return FcTrue;
+           newobjects = malloc (newsize * sizeof (FcObjectType));
+           if (newobjects)
+               memcpy (newobjects, FcObjects,
+                       FcObjectsNumber * sizeof (FcObjectType));
        }
+       if (!newobjects)
+           return NULL;
+       FcObjects = newobjects;
+       FcObjectsSize = newsize;
     }
-    return FcFalse;
+    o = &FcObjects[FcObjectsNumber];
+    o->object = name;
+    o->type = type;
+    ++FcObjectsNumber;
+    return o;
 }
 
-FcBool
-FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+static FcObject
+FcObjectId (FcObjectType *o)
 {
-    return FcNameUnregisterObjectTypesFree (types, ntypes, FcTrue);
+    return o - FcObjects + 1;
 }
 
-const FcObjectType *
-FcNameGetObjectType (const char *object)
+static FcObjectType *
+FcObjectFindByName (const char *object, FcBool insert)
 {
-    int                            i;
-    const FcObjectTypeList  *l;
-    const FcObjectType     *t;
-    
-    for (l = _FcObjectTypes; l; l = l->next)
+    FcChar32       hash = FcStringHash ((const FcChar8 *) object);
+    FcObjectBucket  **p;
+    FcObjectBucket  *b;
+    FcObjectType    *o;
+
+    if (!FcObjectsInited)
+       FcObjectInit ();
+    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
     {
-        if (l == (FcObjectTypeList*)_FcUserObjectNames)
-            continue;
+       o = FcObjects + b->id - 1;
+        if (b->hash == hash && !strcmp (object, (o->object)))
+            return o;
+    }
+    if (!insert)
+       return NULL;
+    /*
+     * Hook it into the hash chain
+     */
+    b = malloc (sizeof(FcObjectBucket));
+    if (!b) 
+       return NULL;
+    object = (const char *) FcStrCopy ((FcChar8 *) object);
+    if (!object) {
+       free (b);
+       return NULL;
+    }
+    o = FcObjectInsert (object, -1);
+    b->next = NULL;
+    b->hash = hash;
+    b->id = FcObjectId (o);
+    *p = b;
+    return o;
+}
 
-       for (i = 0; i < l->ntypes; i++)
+static FcObjectType *
+FcObjectFindById (FcObject object)
+{
+    if (1 <= object && object <= FcObjectsNumber)
+       return FcObjects + object - 1;
+    return NULL;
+}
+
+static FcBool
+FcObjectHashInsert (const FcObjectType *object, FcBool copy)
+{
+    FcChar32       hash = FcStringHash ((const FcChar8 *) object->object);
+    FcObjectBucket  **p;
+    FcObjectBucket  *b;
+    FcObjectType    *o;
+
+    if (!FcObjectsInited)
+       FcObjectInit ();
+    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+    {
+       o = FcObjects + b->id - 1;
+        if (b->hash == hash && !strcmp (object->object, o->object))
+            return FcFalse;
+    }
+    /*
+     * Hook it into the hash chain
+     */
+    b = malloc (sizeof(FcObjectBucket));
+    if (!b) 
+       return FcFalse;
+    if (copy)
+    {
+       o = FcObjectInsert (object->object, object->type);
+       if (!o)
        {
-           t = &l->types[i];
-           if (!strcmp (object, t->object))
-               return t;
+           free (b);
+           return FcFalse;
        }
     }
-    return 0;
+    else
+       o = (FcObjectType *) object;
+    b->next = NULL;
+    b->hash = hash;
+    b->id = FcObjectId (o);
+    *p = b;
+    return FcTrue;
 }
 
-#define OBJECT_HASH_SIZE    31
-struct objectBucket {
-    struct objectBucket        *next;
-    FcChar32           hash;
-    int                        id;
-};
-static struct objectBucket *FcObjectBuckets[OBJECT_HASH_SIZE];
-
-/* Design constraint: biggest_known_ntypes must never change
- * after any call to FcNameRegisterObjectTypes. */
-static const FcObjectType *biggest_known_types = _FcBaseObjectTypes; 
-static int biggest_known_ntypes = NUM_OBJECT_TYPES;
-
-
-static FcObject
-FcObjectToPtrLookup (const char * object)
+static void
+FcObjectHashRemove (const FcObjectType *object, FcBool cleanobj)
 {
-    FcObject               i = 0, n;
-    const FcObjectTypeList  *l;
-    FcObjectType           *t = _FcUserObjectNames;
-    FcBool                 replace;
-
-    for (l = _FcObjectTypes; l; l = l->next)
+    FcChar32       hash = FcStringHash ((const FcChar8 *) object->object);
+    FcObjectBucket  **p;
+    FcObjectBucket  *b;
+    FcObjectType    *o;
+
+    if (!FcObjectsInited)
+       FcObjectInit ();
+    for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
     {
-       for (i = 0; i < l->ntypes; i++)
+       o = FcObjects + b->id - 1;
+        if (b->hash == hash && !strcmp (object->object, o->object))
        {
-           t = (FcObjectType *)&l->types[i];
-           if (!strcmp (object, t->object))
+           *p = b->next;
+           free (b);
+           if (cleanobj)
            {
-               if (l->types == _FcUserObjectNames)
-                    return -i;
-               else
-                   return l->basic_offset + i;
+               /* Clean up object array */
+               o->object = NULL;
+               o->type = -1;
+               while (FcObjects[FcObjectsNumber-1].object == NULL)
+                   --FcObjectsNumber;
            }
+            break;
        }
     }
+}
 
-    /* We didn't match.  Look for the application's FcObjectTypeList
-     * and replace it in-place. */
-    for (l = _FcObjectTypes; l; l = l->next)
-    {
-       if (l->types == _FcUserObjectNames)
-           break;
-    }
-
-    replace = l && l->types == _FcUserObjectNames;
-    if (!_FcUserObjectNames || 
-        (replace && user_obj_alloc <= l->ntypes))
-    {
-       int nt = user_obj_alloc + 4;
-        FcObjectType * tt = realloc (_FcUserObjectNames, 
-                                   nt * sizeof (FcObjectType));
-        if (!tt)
-            return 0;
-       _FcUserObjectNames = tt;
-       user_obj_alloc = nt;
-    }
-
-    if (replace)
-    {
-       n = l->ntypes;
-       FcNameUnregisterObjectTypesFree (l->types, l->ntypes, FcFalse);
-    }
-    else
-       n = 0;
+FcBool
+FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    int        i;
 
-    FcNameRegisterObjectTypes (_FcUserObjectNames, n+1);
+    for (i = 0; i < ntypes; i++)
+       if (!FcObjectHashInsert (&types[i], FcTrue))
+           return FcFalse;
+    return FcTrue;
+}
 
-    if (!_FcUserObjectNames)
-       return 0;
+FcBool
+FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    int        i;
 
-    _FcUserObjectNames[n].object = object;
-    _FcUserObjectNames[n].type = FcTypeVoid;
+    for (i = 0; i < ntypes; i++)
+       FcObjectHashRemove (&types[i], FcTrue);
+    return FcTrue;
+}
 
-    return -n;
+const FcObjectType *
+FcNameGetObjectType (const char *object)
+{
+    return FcObjectFindByName (object, FcFalse);
 }
 
 FcBool
 FcObjectValidType (FcObject object, FcType type)
 {
-    if (object < NUM_OBJECT_TYPES && _FcBaseObjectTypes[object].type != type)
+    FcObjectType    *t = FcObjectFindById (object);
+
+    if (t) {
+       switch (t->type) {
+       case -1:
+           return FcTrue;
+       case FcTypeDouble:
+       case FcTypeInteger:
+           if (type == FcTypeDouble || type == FcTypeInteger)
+               return FcTrue;
+           break;
+       default:
+           if (type == t->type)
+               return FcTrue;
+           break;
+       }
        return FcFalse;
+    }
     return FcTrue;
 }
 
 FcObject
 FcObjectFromName (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;
-    /* workaround glibc bug which reads strlen in groups of 4 */
-    b = malloc (size + sizeof (int));
-    FcMemAlloc (FC_MEM_STATICSTR, size + sizeof(int));
-    if (!b)
-        return 0;
-    b->next = 0;
-    b->hash = hash;
-    b->id = FcObjectToPtrLookup (name);
-    strcpy ((char *) (b + 1), name);
-    *p = b;
-    return b->id;
+    FcObjectType    *o = FcObjectFindByName (name, FcTrue);
+
+    if (o)
+       return FcObjectId (o);
+    return 0;
+}
+
+FcBool
+FcObjectInit (void)
+{
+    int        i;
+
+    if (FcObjectsInited)
+       return FcTrue;
+
+    FcObjectsInited = FcTrue;
+    for (i = 0; i < NUM_OBJECT_TYPES; i++)
+       if (!FcObjectHashInsert (&_FcBaseObjectTypes[i], FcFalse))
+           return FcFalse;
+    return FcTrue;
 }
 
 void
-FcObjectStaticNameFini (void)
+FcObjectFini (void)
 {
-    int i, size;
-    struct objectBucket *b, *next;
-    char *name;
+    int                    i;
+    FcObjectBucket  *b, *next;
 
     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;
     }
+    for (i = 0; i < FcObjectsNumber; i++)
+       if (FcObjects[i].type == -1)
+           free ((void*) FcObjects[i].object);
+    if (FcObjects != _FcBaseObjectTypes)
+       free (FcObjects);
+    FcObjects = (FcObjectType *) _FcBaseObjectTypes;
+    FcObjectsNumber = NUM_OBJECT_TYPES;
+    FcObjectsSize = 0;
+    FcObjectsInited = FcFalse;
 }
 
 const char *
 FcObjectName (FcObject object)
 {
-    const FcObjectTypeList  *l;
-    int i, j;
-
-    if (object > 0)
-    {
-        if (object < biggest_known_ntypes)
-            return biggest_known_types[object].object;
-
-        j = 0;
-        for (l = _FcObjectTypes; l; l = l->next)
-            for (i = 0; i < l->ntypes; i++, j++)
-                if (j == object)
-                    return l->types[i].object;
-    }
+    FcObjectType    *o = FcObjectFindById (object);
 
-    return _FcUserObjectNames[-object].object;
+    if (o)
+       return o->object;
+    return NULL;
 }
 
 static const FcConstant _FcBaseConstants[] = {
index 3eb8a73707ecae51e17373e7b16baffd49c16974..bc0bab7460f062f04b928b24e3fbd22535753b76 100644 (file)
@@ -1044,7 +1044,7 @@ void
 FcPatternFini (void)
 {
     FcStrStaticNameFini ();
-    FcObjectStaticNameFini ();
+    FcObjectFini ();
 }
 
 FcBool