]> git.wh0rd.org Git - fontconfig.git/commitdiff
Overhaul the serialization system to create one mmapable file per directory
authorPatrick Lam <plam@MIT.EDU>
Wed, 24 Aug 2005 06:21:30 +0000 (06:21 +0000)
committerPatrick Lam <plam@MIT.EDU>
Wed, 24 Aug 2005 06:21:30 +0000 (06:21 +0000)
    and distribute bytes for each directory from a single malloc for that
    directory. Store pointers as differences between the data pointed to
    and the pointer's address (s_off = s - v). Don't serialize data
    structures that never actually get serialized. Separate strings used
    for keys from strings used for values (in FcPatternElt and FcValue,
    respectively). Bump FC_CACHE_VERSION to 2.

20 files changed:
fc-cache/fc-cache.c
fc-lang/fc-lang.c
fontconfig/fcprivate.h
fontconfig/fontconfig.h
src/fccache.c
src/fccfg.c
src/fccharset.c
src/fcdbg.c
src/fcdir.c
src/fcfs.c
src/fcinit.c
src/fcint.h
src/fclang.c
src/fclist.c
src/fcmatch.c
src/fcmatrix.c
src/fcname.c
src/fcpat.c
src/fcstr.c
src/fcxml.c

index 7d01ccf9997f2490e4469fbfd9198be1d07cbca3..d2809ee24f876b76ce8d062d6f5b38937137ed16 100644 (file)
@@ -93,7 +93,6 @@ usage (char *program)
     exit (1);
 }
 
-#if 0
 static int
 nsubdirs (FcStrSet *set)
 {
@@ -192,6 +191,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
            ret++;
            continue;
        }
+#if 0 // put this back later after fixing DirCacheValid
        if (!force && FcDirCacheValid (dir))
        {
            if (verbose)
@@ -199,11 +199,13 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
                        set->nfont, nsubdirs(subdirs));
        }
        else
+#endif
        {
            if (verbose)
                printf ("caching, %d fonts, %d dirs\n", 
                        set->nfont, nsubdirs (subdirs));
-           if (!FcDirSave (set, subdirs, dir))
+
+           if (!FcDirSave (set, dir))
            {
                fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
                ret++;
@@ -223,7 +225,6 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
     FcStrListDone (list);
     return ret;
 }
-#endif
 
 int
 main (int argc, char **argv)
@@ -280,10 +281,6 @@ main (int argc, char **argv)
        return 1;
     }
 
-    /* We don't yet have per-directory caches. */
-    ret = (FcCacheWrite (config) == FcFalse);
-
-#if 0
     if (argv[i])
     {
        dirs = FcStrSetCreate ();
@@ -308,7 +305,6 @@ main (int argc, char **argv)
     else
        list = FcConfigGetConfigDirs (config);
     ret = scanDirs (list, config, argv[0], force, verbose);
-#endif
     /* 
      * Now we need to sleep a second  (or two, to be extra sure), to make
      * sure that timestamps for changes after this run of fc-cache are later
index e302c4a69f6a0db82286b4a8d3d099aa7efb1d3c..9ec84186c2287127e1d5f865a2f962ef2d12bc55 100644 (file)
@@ -48,7 +48,7 @@ FcMemFree (int kind, int size)
 }
 
 int
-FcCacheNextOffset (int fd)
+FcCacheBankToIndex (int bank)
 {
     return -1;
 }
@@ -404,7 +404,7 @@ main (int argc, char **argv)
        if (j < 0)
            j = i;
        printf ("    { (FcChar8 *) \"%s\",\n"
-               "      { FC_REF_CONSTANT, %d, FcStorageDynamic, "
+               "      { FC_REF_CONSTANT, %d, FC_BANK_DYNAMIC, "
                "{ { (FcCharLeaf **) leaves_%s, "
                "(FcChar16 *) numbers_%s } } } },\n",
                langs[i],
index 2b73945bb71f88f4774c7233f034adc071538e0a..8f8d36735b9e3e7859cbf058a4bc6699a9581f1b 100644 (file)
            __v__.u.d = va_arg (va, double);                        \
            break;                                                  \
        case FcTypeString:                                          \
-           __v__.u.si = va_arg (va, FcObjectPtr);                  \
+           __v__.u.s = va_arg (va, const char *);                  \
            break;                                                  \
        case FcTypeBool:                                            \
            __v__.u.b = va_arg (va, FcBool);                        \
            break;                                                  \
        case FcTypeMatrix:                                          \
-           __v__.u.mi = va_arg (va, FcMatrixPtr);                  \
+           __v__.u.m = va_arg (va, const FcMatrix *);              \
            break;                                                  \
        case FcTypeCharSet:                                         \
-           __v__.u.ci = va_arg (va, FcCharSetPtr);                 \
+           __v__.u.c = va_arg (va, const FcCharSet *);             \
            break;                                                  \
        case FcTypeFTFace:                                          \
            __v__.u.f = va_arg (va, FT_Face);                       \
            break;                                                  \
        case FcTypeLangSet:                                         \
-           __v__.u.li = va_arg (va, FcLangSetPtr);                 \
+           __v__.u.l = va_arg (va, const FcLangSet *);             \
            break;                                                  \
        }                                                           \
        if (!FcPatternAdd (__p__, __o__, __v__, FcTrue))            \
index 7d36e9eb04eb05ebf1624adb87e5fd47b7e4be2f..8d0975e4149131fe6ce5b6bef1f4687b0b152b56 100644 (file)
@@ -54,7 +54,7 @@ typedef int           FcBool;
  * it means multiple copies of the font information.
  */
 
-#define FC_CACHE_VERSION    "1"
+#define FC_CACHE_VERSION    "2"
 
 #define FcTrue         1
 #define FcFalse                0
@@ -196,52 +196,28 @@ typedef enum _FcResult {
     FcResultOutOfMemory
 } FcResult;
 
-typedef enum _FcStorage {
-    FcStorageStatic, FcStorageDynamic
-} FcStorage;
-
 typedef struct _FcPattern   FcPattern;
 
 typedef struct _FcLangSet   FcLangSet;
 
-typedef struct _FcMatrixPtr {
-    FcStorage               storage;
-    union {
-        int                stat;
-        FcMatrix           *dyn;
-    } u;
-} FcMatrixPtr;
-
-typedef struct _FcCharSetPtr {
-    FcStorage               storage;
-    union {
-        int                stat;
-        FcCharSet          *dyn;
-    } u;
-} FcCharSetPtr;
-
-typedef struct _FcLangSetPtr {
-    FcStorage               storage;
-    union {
-        int                stat;
-        FcLangSet          *dyn;
-    } u;
-} FcLangSetPtr;
-
-typedef int FcObjectPtr;
+#define FC_BANK_DYNAMIC 0
+#define FC_BANK_FIRST 1
 
 typedef struct _FcValue {
     FcType     type;
     union {
-       FcObjectPtr     si;
+       const FcChar8  *s;
+       int             s_off;
        int             i;
        FcBool          b;
        double          d;
-       FcMatrixPtr     mi;
-       FcCharSetPtr    ci;
+       const FcMatrix  *m;
+       const FcCharSet *c;
+       int             c_off;
        void            *f;
        const FcPattern *p;
-       FcLangSetPtr    li;
+       const FcLangSet *l;
+       int             l_off; // this is a difference of char *s
     } u;
 } FcValue;
 
@@ -254,7 +230,7 @@ typedef struct _FcFontSet {
 typedef struct _FcObjectSet {
     int                nobject;
     int                sobject;
-    FcObjectPtr        *objects;
+    const char **objects;
 } FcObjectSet;
     
 typedef enum _FcMatchKind {
@@ -471,7 +447,7 @@ FcDirScan (FcFontSet            *set,
           FcBool           force);
 
 FcBool
-FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
+FcDirSave (FcFontSet *set, const FcChar8 *dir);
 
 /* fcfreetype.c */
 FcPattern *
@@ -648,9 +624,6 @@ FcMatrixScale (FcMatrix *m, double sx, double sy);
 void
 FcMatrixShear (FcMatrix *m, double sh, double sv);
 
-FcMatrix *
-FcMatrixPtrU (FcMatrixPtr mi);
-
 /* fcname.c */
 
 FcBool
index 9b92173b2c129f0fb638061f3a47f19a9b81742d..55187c9a258f1d2ff54e0ef9070046893f98ed59 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <fcntl.h>
+#include <dirent.h>
 #include <sys/mman.h>
 #include <sys/utsname.h>
 #include "fcint.h"
@@ -192,12 +193,6 @@ FcGlobalCacheDestroy (FcGlobalCache *cache)
     free (cache);
 }
 
-/*
- * Cache file syntax is quite simple:
- *
- * "file_name" id time "font_name" \n
- */
 void
 FcGlobalCacheLoad (FcGlobalCache    *cache,
                   const FcChar8    *cache_file)
@@ -388,89 +383,15 @@ bail0:
  * Find the next presumably-mmapable offset after the current file
  * pointer.
  */
-int
-FcCacheNextOffset(int fd)
+static int
+FcCacheNextOffset(off_t w)
 {
-    off_t w;
-    w = lseek(fd, 0, SEEK_END);
-
     if (w % PAGESIZE == 0) 
        return w;
     else
        return ((w / PAGESIZE)+1)*PAGESIZE;
 }
 
-/* will go away once we use config->cache */
-#define CACHE_DEFAULT_TMPDIR "/tmp"
-#define CACHE_DEFAULT_NAME "/fontconfig-mmap"
-static char *
-FcCacheFilename(void)
-{
-    struct utsname b;
-    static char * name = 0;
-
-    if (name)
-        return name;
-
-    if (uname(&b) == -1)
-        name = CACHE_DEFAULT_NAME;
-    else
-    {
-        char * tmpname = getenv("TMPDIR");
-        char * logname = getenv("LOGNAME");
-        if (!tmpname)
-            tmpname = CACHE_DEFAULT_TMPDIR;
-
-        name = malloc(strlen(CACHE_DEFAULT_NAME) +
-                      strlen(tmpname) +
-                      (logname ? strlen(logname) : 0) + 5);
-        strcpy(name, tmpname);
-        strcat(name, CACHE_DEFAULT_NAME);
-        strcat(name, "-");
-        strcat(name, logname ? logname : "");
-    }
-    return name;
-}
-
-/* 
- * Wipe out static state.
- */
-void
-FcCacheClearStatic()
-{
-    FcFontSetClearStatic();
-    FcPatternClearStatic();
-    FcValueListClearStatic();
-    FcObjectClearStatic();
-    FcMatrixClearStatic();
-    FcCharSetClearStatic();
-    FcLangSetClearStatic();
-}
-
-/*
- * Trigger the counting phase: this tells us how much to allocate.
- */
-FcBool
-FcCachePrepareSerialize (FcConfig * config)
-{
-    int i;
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
-       if (config->fonts[i] && !FcFontSetPrepareSerialize(config->fonts[i]))
-           return FcFalse;
-    return FcTrue;
-}
-
-/* allocate and populate static structures */
-FcBool
-FcCacheSerialize (FcConfig * config)
-{
-    int i;
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
-       if (config->fonts[i] && !FcFontSetSerialize(config->fonts[i]))
-           return FcFalse;
-    return FcTrue;
-}
-
 /* get the current arch name */
 /* caller is responsible for freeing returned pointer */
 static char *
@@ -531,7 +452,7 @@ FcCacheMoveDown (int fd, off_t start)
 {
     char * buf = malloc (BUF_SIZE);
     char candidate_arch_machine_name[64], bytes_to_skip[7];
-    long bs; off_t pos;
+    long bs;
     int c, bytes_skipped;
 
     if (!buf)
@@ -571,131 +492,294 @@ FcCacheMoveDown (int fd, off_t start)
     return FcFalse;
 }
 
+static int
+FcCacheReadDirs (FcStrList *list, FcFontSet * set)
+{
+    DIR                        *d;
+    struct dirent      *e;
+    int                        ret = 0;
+    FcChar8            *dir;
+    FcChar8            *file, *base;
+    FcStrSet           *subdirs;
+    FcStrList          *sublist;
+    struct stat                statb;
+
+    /*
+     * Now scan all of the directories into separate databases
+     * and write out the results
+     */
+    while ((dir = FcStrListNext (list)))
+    {
+       /* freed below */
+       file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
+       if (!file)
+           return FcFalse;
+
+       strcpy ((char *) file, (char *) dir);
+       strcat ((char *) file, "/");
+       base = file + strlen ((char *) file);
+
+       subdirs = FcStrSetCreate ();
+       if (!subdirs)
+       {
+           fprintf (stderr, "Can't create directory set\n");
+           ret++;
+           free (file);
+           continue;
+       }
+       
+       if (access ((char *) dir, X_OK) < 0)
+       {
+           switch (errno) {
+           case ENOENT:
+           case ENOTDIR:
+           case EACCES:
+               break;
+           default:
+               fprintf (stderr, "\"%s\": ", dir);
+               perror ("");
+               ret++;
+           }
+           FcStrSetDestroy (subdirs);
+           free (file);
+           continue;
+       }
+       if (stat ((char *) dir, &statb) == -1)
+       {
+           fprintf (stderr, "\"%s\": ", dir);
+           perror ("");
+           FcStrSetDestroy (subdirs);
+           ret++;
+           free (file);
+           continue;
+       }
+       if (!S_ISDIR (statb.st_mode))
+       {
+           fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
+           FcStrSetDestroy (subdirs);
+           free (file);
+           continue;
+       }
+       d = opendir ((char *) dir);
+       if (!d)
+       {
+           FcStrSetDestroy (subdirs);
+           free (file);
+           continue;
+       }
+       while ((e = readdir (d)))
+       {
+           if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
+           {
+               strcpy ((char *) base, (char *) e->d_name);
+               if (FcFileIsDir (file) && !FcStrSetAdd (subdirs, file))
+                   ret++;
+           }
+       }
+       closedir (d);
+       if (1 || FcDirCacheValid (dir))
+       {
+           FcDirCacheRead (set, dir);
+       }
+       else
+       {
+           ret++;
+#if 0 // (implement per-dir loading)
+           if (verbose)
+               printf ("caching, %d fonts, %d dirs\n", 
+                       set->nfont, nsubdirs (subdirs));
+
+           if (!FcDirSave (set, dir))
+           {
+               fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
+               ret++;
+           }
+#endif
+       }
+       sublist = FcStrListCreate (subdirs);
+       FcStrSetDestroy (subdirs);
+       if (!sublist)
+       {
+           fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
+           ret++;
+           free (file);
+           continue;
+       }
+       ret += FcCacheReadDirs (sublist, set);
+       free (file);
+    }
+    FcStrListDone (list);
+    return ret;
+}
+
+FcFontSet *
+FcCacheRead (FcConfig *config)
+{
+    FcFontSet * s = FcFontSetCreate();
+    if (!s) 
+       return 0;
+
+    if (force)
+       goto bail;
+
+    if (FcCacheReadDirs (FcConfigGetConfigDirs (config), s))
+       goto bail;
+
+    return s;
+
+ bail:
+    FcFontSetDestroy (s);
+    return 0;
+}
+
 /* read serialized state from the cache file */
 FcBool
-FcCacheRead (FcConfig *config)
+FcDirCacheRead (FcFontSet * set, const FcChar8 *dir)
 {
-    int fd, i;
+    FcChar8         *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    int fd;
     FcCache metadata;
+    void * current_dir_block;
     char * current_arch_machine_name;
     char candidate_arch_machine_name[64], bytes_in_block[7];
     off_t current_arch_start = 0;
 
     if (force)
-       return FcFalse;
+       goto bail;
+    if (!cache_file)
+        goto bail;
 
-    fd = open(FcCacheFilename(), O_RDONLY);
+    current_arch_machine_name = FcCacheGetCurrentArch();
+    fd = open(cache_file, O_RDONLY);
     if (fd == -1)
-        return FcFalse;
+        goto bail0;
 
-    current_arch_machine_name = FcCacheGetCurrentArch();
     current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
     if (current_arch_start < 0)
-        goto bail;
+        goto bail1;
 
     lseek (fd, current_arch_start, SEEK_SET);
     if (FcCacheReadString (fd, candidate_arch_machine_name, 
                           sizeof (candidate_arch_machine_name)) == 0)
-       goto bail;
+       goto bail1;
     if (FcCacheReadString (fd, bytes_in_block, 7) == 0)
-       goto bail;
+       goto bail1;
 
     // sanity check for endianness issues
     read(fd, &metadata, sizeof(FcCache));
     if (metadata.magic != FC_CACHE_MAGIC)
-        goto bail;
+        goto bail1;
 
-    if (!FcObjectRead(fd, metadata)) goto bail1;
-    if (!FcStrSetRead(fd, metadata)) goto bail1;
-    if (!FcCharSetRead(fd, metadata)) goto bail1;
-    if (!FcMatrixRead(fd, metadata)) goto bail1;
-    if (!FcLangSetRead(fd, metadata)) goto bail1;
-    if (!FcValueListRead(fd, metadata)) goto bail1;
-    if (!FcPatternEltRead(fd, metadata)) goto bail1;
-    if (!FcPatternRead(fd, metadata)) goto bail1;
-    if (!FcFontSetRead(fd, config, metadata)) goto bail1;
+    if (metadata.count)
+    {
+       off_t pos = FcCacheNextOffset (lseek(fd, 0, SEEK_CUR));
+       current_dir_block = mmap (0, metadata.count, 
+                                 PROT_READ, MAP_SHARED, fd, pos);
+       if (current_dir_block == MAP_FAILED)
+           perror("");
+
+       if (!FcFontSetUnserialize (metadata, set, current_dir_block))
+           goto bail1;
+    }
+       
     close(fd);
     free (current_arch_machine_name);
+    free (cache_file);
     return FcTrue;
 
  bail1:
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
-        config->fonts[i] = 0;
     close(fd);
- bail:
+ bail0:
     free (current_arch_machine_name);
+ bail:
+    free (cache_file);
     return FcFalse;
 }
 
 /* write serialized state to the cache file */
 FcBool
-FcCacheWrite (FcConfig * config)
+FcDirCacheWrite (int bank, FcFontSet *set, const FcChar8 *dir)
 {
-    int fd;
+    FcChar8         *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    int fd, bytes_to_write, metadata_bytes;
     FcCache metadata;
     off_t current_arch_start = 0, truncate_to;
     char * current_arch_machine_name, bytes_written[7] = "dedbef";
+    void * current_dir_block, *final_dir_block;
 
-    if (!FcCachePrepareSerialize (config))
-       return FcFalse;
+    if (!cache_file)
+        goto bail;
+
+    FcFontSetNewBank();
+    bytes_to_write = FcFontSetNeededBytes (set);
+    metadata_bytes = FcCacheNextOffset (sizeof (FcCache));
 
-    if (!FcCacheSerialize (config))
+    if (!bytes_to_write)
+    {
+       unlink (cache_file);
+       free (cache_file);
+       return FcTrue;
+    }
+
+    current_dir_block = malloc (bytes_to_write);
+    memset (&metadata, 0, sizeof(FcCache));
+    metadata.count = bytes_to_write;
+    metadata.bank = bank;
+    if (!current_dir_block)
+       goto bail;
+    final_dir_block = FcFontSetDistributeBytes (&metadata, current_dir_block);
+                             
+    if (!FcFontSetSerialize (bank, set))
        return FcFalse;
 
-    fd = open(FcCacheFilename(), O_RDWR | O_CREAT, 0666);
+    if (FcDebug () & FC_DBG_CACHE)
+        printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
+
+    fd = open(cache_file, O_RDWR | O_CREAT, 0666);
     if (fd == -1)
         return FcFalse;
 
     current_arch_machine_name = FcCacheGetCurrentArch();
     current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
     if (current_arch_start < 0)
-       current_arch_start = FcCacheNextOffset (fd);
+       current_arch_start = FcCacheNextOffset (lseek(fd, 0, SEEK_END));
 
     if (!FcCacheMoveDown(fd, current_arch_start))
-       goto bail;
+       goto bail1;
 
     current_arch_start = lseek(fd, 0, SEEK_CUR);
     if (ftruncate (fd, current_arch_start) == -1)
-       goto bail;
+       goto bail1;
 
     /* reserve space for arch, count & metadata */
     if (!FcCacheWriteString (fd, current_arch_machine_name))
-       goto bail;
-    if (!FcCacheWriteString (fd, bytes_written))
-       goto bail;
-    memset (&metadata, 0, sizeof(FcCache));
-    metadata.magic = FC_CACHE_MAGIC;
-    write(fd, &metadata, sizeof(FcCache));
-
-    if (!FcFontSetWrite(fd, config, &metadata)) goto bail;
-    if (!FcPatternWrite(fd, &metadata)) goto bail;
-    if (!FcPatternEltWrite(fd, &metadata)) goto bail;
-    if (!FcValueListWrite(fd, &metadata)) goto bail;
-    if (!FcLangSetWrite(fd, &metadata)) goto bail;
-    if (!FcCharSetWrite(fd, &metadata)) goto bail;
-    if (!FcMatrixWrite(fd, &metadata)) goto bail;
-    if (!FcStrSetWrite(fd, &metadata)) goto bail;
-    if (!FcObjectWrite(fd, &metadata)) goto bail;
+       goto bail1;
 
     /* now write the address of the next offset */
-    truncate_to = FcCacheNextOffset(fd) - current_arch_start;
-    lseek(fd, current_arch_start + strlen(current_arch_machine_name)+1, 
-         SEEK_SET);
+    truncate_to = FcCacheNextOffset(current_arch_start + bytes_to_write + metadata_bytes) -
+       current_arch_start;
     strcpy (bytes_written, l64a(truncate_to));
     if (!FcCacheWriteString (fd, bytes_written))
-       goto bail;
+       goto bail1;
 
-    /* now rewrite metadata & truncate file */
-    if (write(fd, &metadata, sizeof(FcCache)) != sizeof (FcCache)) 
-       goto bail;
+    metadata.magic = FC_CACHE_MAGIC;
+    write (fd, &metadata, sizeof(FcCache));
+    lseek (fd, FcCacheNextOffset (lseek(fd, 0, SEEK_END)), SEEK_SET);
+    write (fd, current_dir_block, bytes_to_write);
+
+    /* this actually serves to pad out the cache file */
     if (ftruncate (fd, current_arch_start + truncate_to) == -1)
-       goto bail;
+       goto bail1;
 
     close(fd);
     return FcTrue;
 
- bail:
+ bail1:
+    free (current_dir_block);
     free (current_arch_machine_name);
+ bail:
+    unlink (cache_file);
+    free (cache_file);
     return FcFalse;
 }
 
@@ -705,3 +789,56 @@ FcCacheForce (FcBool f)
 {
     force = f;
 }
+
+static int banks_ptr = 0, banks_alloc = 0;
+static int * bankId = 0;
+
+int
+FcCacheBankCount (void)
+{
+    return banks_ptr;
+}
+
+FcBool
+FcCacheHaveBank (int bank)
+{
+    int i;
+
+    if (bank < FC_BANK_FIRST)
+       return FcTrue;
+
+    for (i = 0; i < banks_ptr; i++)
+       if (bankId[i] == bank)
+           return FcTrue;
+
+    return FcFalse;
+}
+
+int
+FcCacheBankToIndex (int bank)
+{
+    static int lastBank = FC_BANK_DYNAMIC, lastIndex = -1;
+    int i;
+    int * b;
+
+    if (bank == lastBank)
+       return lastIndex;
+
+    for (i = 0; i < banks_ptr; i++)
+       if (bankId[i] == bank)
+           return i;
+
+    if (banks_ptr <= banks_alloc)
+    {
+       b = realloc (bankId, banks_alloc + 4);
+       if (!b)
+           return -1;
+
+       bankId = b;
+       banks_alloc += 4;
+    }
+
+    i = banks_ptr++;
+    bankId[i] = bank;
+    return i;
+}
index a5de075f2a9c7bc04bda6c20e1069bba7997f1ae..aaa05f56b47341ca34a3fb07eb0faaa7c1778f5f 100644 (file)
@@ -247,7 +247,7 @@ FcConfigDestroy (FcConfig *config)
 FcBool
 FcConfigBuildFonts (FcConfig *config)
 {
-    FcFontSet      *fonts;
+    FcFontSet      *fonts, *cached_fonts;
     FcGlobalCache   *cache;
     FcStrList      *list;
     FcChar8        *dir;
@@ -269,20 +269,35 @@ FcConfigBuildFonts (FcConfig *config)
        goto bail1;
 #endif
 
-    list = FcConfigGetFontDirs (config);
-    if (!list)
-       goto bail1;
-
-    while ((dir = FcStrListNext (list)))
+    cached_fonts = FcCacheRead(config);
+    if (!cached_fonts)
+    {
+       list = FcConfigGetFontDirs (config);
+       if (!list)
+           goto bail1;
+       
+       while ((dir = FcStrListNext (list)))
+       {
+           if (FcDebug () & FC_DBG_FONTSET)
+               printf ("scan dir %s\n", dir);
+           FcDirScanConfig (fonts, config->fontDirs, cache, 
+                            config->blanks, dir, FcFalse, config);
+       }
+       
+       FcStrListDone (list);
+    }
+    else
     {
-       if (FcDebug () & FC_DBG_FONTSET)
-           printf ("scan dir %s\n", dir);
-       FcDirScanConfig (fonts, config->fontDirs, cache, 
-                        config->blanks, dir, FcFalse, config);
+       int i;
+
+       for (i = 0; i < cached_fonts->nfont; i++)
+       {
+           if (FcConfigAcceptFont (config, cached_fonts->fonts[i]))
+               FcFontSetAdd (fonts, cached_fonts->fonts[i]);
+       }
+       FcFontSetDestroy (cached_fonts);
     }
     
-    FcStrListDone (list);
-    
     if (FcDebug () & FC_DBG_FONTSET)
        FcFontSetPrint (fonts);
 
@@ -558,25 +573,24 @@ FcConfigPromote (FcValue v, FcValue u)
     }
     else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
     {
-       v.u.mi = FcIdentityMatrix;
+       v.u.m = &FcIdentityMatrix;
        v.type = FcTypeMatrix;
     }
     else if (v.type == FcTypeString && u.type == FcTypeLangSet)
     {
-       v.u.li = FcLangSetPtrCreateDynamic(FcLangSetPromote 
-                                          (FcObjectPtrU(v.u.si)));
+       v.u.l = FcLangSetPromote (v.u.s);
        v.type = FcTypeLangSet;
     }
     return v;
 }
 
 FcBool
-FcConfigCompareValue (const FcValue    left_o,
+FcConfigCompareValue (const FcValue    *left_o,
                      FcOp              op,
-                     const FcValue     right_o)
+                     const FcValue     *right_o)
 {
-    FcValue    left = left_o;
-    FcValue    right = right_o;
+    FcValue    left = FcValueCanonicalize(left_o);
+    FcValue    right = FcValueCanonicalize(right_o);
     FcBool     ret = FcFalse;
     
     left = FcConfigPromote (left, right);
@@ -632,20 +646,16 @@ FcConfigCompareValue (const FcValue       left_o,
            switch (op) {
            case FcOpEqual:    
            case FcOpListing:
-               ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), 
-                                         FcObjectPtrU(right.u.si)) == 0;
+               ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
                break;
            case FcOpContains:
-               ret = FcStrStrIgnoreCase (FcObjectPtrU(left.u.si), 
-                                         FcObjectPtrU(right.u.si)) != 0;
+               ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
                break;
            case FcOpNotEqual:
-               ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), 
-                                         FcObjectPtrU(right.u.si)) != 0;
+               ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
                break;
            case FcOpNotContains:
-               ret = FcStrCmpIgnoreCase (FcObjectPtrU(left.u.si), 
-                                         FcObjectPtrU(right.u.si)) == 0;
+               ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
                break;
            default:
                break;
@@ -656,11 +666,11 @@ FcConfigCompareValue (const FcValue       left_o,
            case FcOpEqual:
            case FcOpContains:
            case FcOpListing:
-               ret = FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi));
+               ret = FcMatrixEqual (left.u.m, right.u.m);
                break;
            case FcOpNotEqual:
            case FcOpNotContains:
-               ret = !FcMatrixEqual (FcMatrixPtrU(left.u.mi), FcMatrixPtrU(right.u.mi));
+               ret = !FcMatrixEqual (left.u.m, right.u.m);
                break;
            default:
                break;
@@ -671,17 +681,17 @@ FcConfigCompareValue (const FcValue       left_o,
            case FcOpContains:
            case FcOpListing:
                /* left contains right if right is a subset of left */
-               ret = FcCharSetIsSubset (FcCharSetPtrU(right.u.ci), FcCharSetPtrU(left.u.ci));
+               ret = FcCharSetIsSubset (right.u.c, left.u.c);
                break;
            case FcOpNotContains:
                /* left contains right if right is a subset of left */
-               ret = !FcCharSetIsSubset (FcCharSetPtrU(right.u.ci), FcCharSetPtrU(left.u.ci));
+               ret = !FcCharSetIsSubset (right.u.c, left.u.c);
                break;
            case FcOpEqual:
-               ret = FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci));
+               ret = FcCharSetEqual (left.u.c, right.u.c);
                break;
            case FcOpNotEqual:
-               ret = !FcCharSetEqual (FcCharSetPtrU(left.u.ci), FcCharSetPtrU(right.u.ci));
+               ret = !FcCharSetEqual (left.u.c, right.u.c);
                break;
            default:
                break;
@@ -691,16 +701,16 @@ FcConfigCompareValue (const FcValue       left_o,
            switch (op) {
            case FcOpContains:
            case FcOpListing:
-               ret = FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
+               ret = FcLangSetContains (left.u.l, right.u.l);
                break;
            case FcOpNotContains:
-               ret = !FcLangSetContains (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
+               ret = !FcLangSetContains (left.u.l, right.u.l);
                break;
            case FcOpEqual:
-               ret = FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
+               ret = FcLangSetEqual (left.u.l, right.u.l);
                break;
            case FcOpNotEqual:
-               ret = !FcLangSetEqual (FcLangSetPtrU(left.u.li), FcLangSetPtrU(right.u.li));
+               ret = !FcLangSetEqual (left.u.l, right.u.l);
                break;
            default:
                break;
@@ -768,17 +778,17 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
        break;
     case FcOpString:
        v.type = FcTypeString;
-       v.u.si = FcObjectStaticName(e->u.sval);
+       v.u.s = FcObjectStaticName(e->u.sval);
        v = FcValueSave (v);
        break;
     case FcOpMatrix:
        v.type = FcTypeMatrix;
-       v.u.mi = FcMatrixPtrCreateDynamic(e->u.mval);
+       v.u.m = e->u.mval;
        v = FcValueSave (v);
        break;
     case FcOpCharSet:
        v.type = FcTypeCharSet;
-       v.u.ci = FcCharSetPtrCreateDynamic(e->u.cval);
+       v.u.c = e->u.cval;
        v = FcValueSave (v);
        break;
     case FcOpBool:
@@ -821,7 +831,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
        vl = FcConfigEvaluate (p, e->u.tree.left);
        vr = FcConfigEvaluate (p, e->u.tree.right);
        v.type = FcTypeBool;
-       v.u.b = FcConfigCompareValue (vl, e->op, vr);
+       v.u.b = FcConfigCompareValue (&vl, e->op, &vr);
        FcValueDestroy (vl);
        FcValueDestroy (vr);
        break;  
@@ -886,11 +896,9 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
                switch (e->op) {
                case FcOpPlus:
                    v.type = FcTypeString;
-                   v.u.si = FcObjectStaticName
-                       (FcStrPlus (FcObjectPtrU(vl.u.si), 
-                                   FcObjectPtrU(vr.u.si)));
+                   v.u.s = FcObjectStaticName (FcStrPlus (vl.u.s, vr.u.s));
                         
-                   if (!FcObjectPtrU(v.u.si))
+                   if (!v.u.s)
                        v.type = FcTypeVoid;
                    break;
                default:
@@ -906,9 +914,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
                    if (m)
                    {
                        FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
-                       FcMatrixMultiply (m, FcMatrixPtrU(vl.u.mi), 
-                                         FcMatrixPtrU(vr.u.mi));
-                       v.u.mi = FcMatrixPtrCreateDynamic(m);
+                       FcMatrixMultiply (m, vl.u.m, vr.u.m);
+                       v.u.m = m;
                    }
                    else
                    {
@@ -1041,7 +1048,7 @@ FcConfigMatchValueList (FcPattern *p,
        for (v = values; v; v = FcValueListPtrU(v->next))
        {
            /* Compare the pattern value to the match expression value */
-           if (FcConfigCompareValue (v->value, t->op, value))
+           if (FcConfigCompareValue (&v->value, t->op, &value))
            {
                if (!ret)
                    ret = v;
@@ -1088,7 +1095,7 @@ FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
     {
        FcValueListPtr  next = FcValueListPtrU(lp)->next;
 
-       if (lp.storage == FcStorageDynamic)
+       if (lp.bank == FC_BANK_DYNAMIC)
        {
            FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
            free (l);
@@ -1866,7 +1873,7 @@ FcConfigGlobsMatch (const FcStrSet        *globs,
     int        i;
 
     for (i = 0; i < globs->num; i++)
-       if (FcConfigGlobMatch (FcStrSetGet(globs, i), string))
+       if (FcConfigGlobMatch (globs->strs[i], string))
            return FcTrue;
     return FcFalse;
 }
index 00b2010e5aac399c7f452b1203204931d0d658e9..d0fee82e8df6b09ce129542e9bd824097aaf3ba0 100644 (file)
  */
 
 #include <stdlib.h>
-#include <sys/mman.h>
 #include "fcint.h"
 
 /* #define CHECK */
 
 /* #define CHATTY */
 
-static FcCharSet * charsets = 0;
-static FcChar16 * numbers = 0;
-static int charset_ptr, charset_count;
+static FcCharSet ** charsets = 0;
+static FcChar16 ** numbers = 0;
+static int charset_bank_count = 0, charset_ptr, charset_count;
 static int charset_numbers_ptr, charset_numbers_count;
-static FcCharLeaf * leaves = 0;
+static FcCharLeaf ** leaves = 0;
 static int charset_leaf_ptr, charset_leaf_count;
-static int * leaf_idx = 0;
+static int ** leaf_idx = 0;
 static int charset_leaf_idx_ptr, charset_leaf_idx_count;
 
-void
-FcCharSetClearStatic()
-{
-    charsets = 0;
-    numbers = 0;
-    charset_ptr = 0; charset_count = 0;
-    leaves = 0;
-    charset_leaf_ptr = 0; charset_leaf_count = 0;
-    leaf_idx = 0;
-    charset_leaf_idx_ptr = 0; charset_leaf_idx_count = 0;
-}
-
 FcCharSet *
 FcCharSetCreate (void)
 {
@@ -62,7 +49,7 @@ FcCharSetCreate (void)
     FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
     fcs->ref = 1;
     fcs->num = 0;
-    fcs->storage = FcStorageDynamic;
+    fcs->bank = FC_BANK_DYNAMIC;
     fcs->u.dyn.leaves = 0;
     fcs->u.dyn.numbers = 0;
     return fcs;
@@ -77,18 +64,6 @@ FcCharSetNew (void)
     return FcCharSetCreate ();
 }
 
-void
-FcCharSetPtrDestroy (FcCharSetPtr fcs)
-{
-    FcCharSetDestroy (FcCharSetPtrU(fcs));
-    if (fcs.storage == FcStorageDynamic && 
-       FcCharSetPtrU(fcs)->ref != FC_REF_CONSTANT)
-    {
-       free (fcs.u.dyn);
-       FcMemFree (FC_MEM_CHARSET, sizeof(FcCharSet));
-    }
-}
-
 void
 FcCharSetDestroy (FcCharSet *fcs)
 {
@@ -97,7 +72,7 @@ FcCharSetDestroy (FcCharSet *fcs)
        return;
     if (--fcs->ref > 0)
        return;
-    if (fcs->storage == FcStorageDynamic)
+    if (fcs->bank == FC_BANK_DYNAMIC)
     {
        for (i = 0; i < fcs->num; i++)
        {
@@ -173,7 +148,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
     ucs4 >>= 8;
     if (ucs4 >= 0x10000)
        return FcFalse;
-    if (fcs->storage == FcStorageStatic)
+    if (fcs->bank != FC_BANK_DYNAMIC)
     {
        int i;
 
@@ -190,7 +165,6 @@ FcCharSetPutLeaf (FcCharSet *fcs,
            leaves[i] = FcCharSetGetLeaf(fcs, i);
        memcpy (numbers, FcCharSetGetNumbers(fcs), 
                fcs->num * sizeof (FcChar16));
-       fcs->storage = FcStorageDynamic;
     }
     else
     {
@@ -264,14 +238,14 @@ FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf)
     if (pos >= 0)
     {
        FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
-       if (fcs->storage == FcStorageDynamic)
+       if (fcs->bank == FC_BANK_DYNAMIC)
        {
            free (fcs->u.dyn.leaves[pos]);
            fcs->u.dyn.leaves[pos] = leaf;
        }
        else
        {
-           leaves[leaf_idx[fcs->u.stat.leafidx_offset]+pos] = *leaf;
+           leaves[fcs->bank][leaf_idx[fcs->bank][fcs->u.stat.leafidx_offset]+pos] = *leaf;
        }
        return FcTrue;
     }
@@ -384,14 +358,6 @@ FcCharSetCopy (FcCharSet *src)
     return src;
 }
 
-FcCharSetPtr
-FcCharSetCopyPtr (FcCharSetPtr src)
-{
-    if (FcCharSetPtrU(src)->ref != FC_REF_CONSTANT)
-       FcCharSetPtrU(src)->ref++;
-    return src;
-}
-
 FcBool
 FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
 {
@@ -1081,8 +1047,8 @@ FcCharSetFreezeBase (FcCharSet *fcs)
     
     ent->set.ref = FC_REF_CONSTANT;
     ent->set.num = fcs->num;
-    ent->set.storage = fcs->storage;
-    if (fcs->storage == FcStorageDynamic)
+    ent->set.bank = fcs->bank;
+    if (fcs->bank == FC_BANK_DYNAMIC)
     {
        if (fcs->num)
        {
@@ -1154,7 +1120,7 @@ FcCharSetFreeze (FcCharSet *fcs)
     }
     n = FcCharSetFreezeBase (b);
 bail1:
-    if (b->storage == FcStorageDynamic)
+    if (b->bank == FC_BANK_DYNAMIC)
     {
        if (b->u.dyn.leaves)
        {
@@ -1231,7 +1197,7 @@ FcNameParseCharSet (FcChar8 *string)
 #endif
     n = FcCharSetFreezeBase (c);
 bail1:
-    if (c->storage == FcStorageDynamic)
+    if (c->bank == FC_BANK_DYNAMIC)
     {
        if (c->u.dyn.leaves)
        {
@@ -1323,205 +1289,160 @@ FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
     return FcTrue;
 }
 
-
-FcCharSet *
-FcCharSetPtrU (FcCharSetPtr ci)
-{
-    switch (ci.storage)
-    {
-    case FcStorageDynamic:
-       return ci.u.dyn;
-    case FcStorageStatic:
-       return &charsets[ci.u.stat];
-    default:
-       return 0;
-    }
-}
-
-FcCharSetPtr
-FcCharSetPtrCreateDynamic(FcCharSet *c)
+void
+FcCharSetNewBank(void)
 {
-    FcCharSetPtr new;
-
-    new.storage = FcStorageDynamic;
-    new.u.dyn = c;
-    return new;
+    charset_count = 0;
+    charset_numbers_count = 0;
+    charset_leaf_count = 0;
+    charset_leaf_idx_count = 0;
 }
 
-FcBool
-FcCharSetPrepareSerialize(FcCharSet *c)
+int
+FcCharSetNeededBytes (const FcCharSet *c)
 {
-    /* note the redundancy */
+    /* yes, there's redundancy */
     charset_count++;
     charset_leaf_idx_count++;
     charset_leaf_count += c->num;
     charset_numbers_count += c->num;
+    return sizeof (FcCharSet) + 
+       sizeof (int) +                  /* leaf_idx */
+       sizeof (FcCharLeaf) * c->num +  /* leaf */
+       sizeof (FcChar16) * c->num;     /* number */
+}
+
+static FcBool
+FcCharSetEnsureBank (int bi)
+{
+    if (!charsets || charset_bank_count <= bi)
+    {
+       int new_count = charset_bank_count + 2;
+       FcCharSet ** cs;
+       FcChar16 ** n;
+       FcCharLeaf ** lvs;
+       int ** lvi;
+       int i;
+       
+       cs = realloc(charsets, sizeof(FcCharSet*) * new_count);
+       if (!cs) return 0;
+       n = realloc(numbers, sizeof(FcChar16*) * new_count);
+       if (!n) return 0;
+       lvs = realloc(leaves, sizeof(FcCharLeaf*) * new_count);
+       if (!lvs) return 0;
+       lvi = realloc(leaf_idx, sizeof(int*) * new_count);
+       if (!lvi) return 0;
+
+       charsets = cs; numbers = n; leaves = lvs; leaf_idx = lvi;
+       for (i = charset_bank_count; i < new_count; i++)
+       {
+           charsets[i] = 0;
+           numbers[i] = 0;
+           leaves[i] = 0;
+           leaf_idx[i] = 0;
+       }
+       charset_bank_count = new_count;
+    }
     return FcTrue;
 }
 
-FcCharSetPtr
-FcCharSetSerialize(FcCharSet *c)
+void *
+FcCharSetDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+    int bi = FcCacheBankToIndex(metadata->bank);
+    if (!FcCharSetEnsureBank(bi))
+       return 0;
+
+    charsets[bi] = (FcCharSet *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                    (sizeof (FcCharSet) * charset_count));
+    numbers[bi] = (FcChar16 *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                    (sizeof(FcChar16) * charset_numbers_count));
+    leaves[bi] = (FcCharLeaf *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr +
+                    (sizeof(FcCharLeaf) * charset_leaf_count));
+    leaf_idx[bi] = (int *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr +
+                    (sizeof(int) * charset_leaf_idx_count));
+
+    metadata->charset_count = charset_count;
+    metadata->charset_numbers_count = charset_numbers_count;
+    metadata->charset_leaf_count = charset_leaf_count;
+    metadata->charset_leaf_idx_count = charset_leaf_idx_count;
+    charset_ptr = 0; charset_leaf_ptr = 0;
+    charset_leaf_idx_ptr = 0; charset_numbers_ptr = 0;
+    return block_ptr;
+}
+
+FcCharSet *
+FcCharSetSerialize(int bank, FcCharSet *c)
 {
     int i;
-    FcCharSetPtr newp;
     FcCharSet new;
-
-    if (!charsets)
-    {
-       charsets = malloc(sizeof(FcCharSet) * charset_count);
-       if (!charsets) goto bail;
-       numbers = malloc(sizeof(FcChar16) * charset_numbers_count);
-       if (!numbers) goto bail1;
-       leaves = malloc(sizeof(FcCharLeaf) * charset_leaf_count);
-       if (!leaves) goto bail2;
-       leaf_idx = malloc(sizeof(int)*charset_leaf_idx_count);
-       if (!leaf_idx) goto bail3;
-    }
+    int bi = FcCacheBankToIndex(bank), cp = charset_ptr;
 
     new.ref = FC_REF_CONSTANT;
-    new.storage = FcStorageStatic;
+    new.bank = bank;
     new.u.stat.leafidx_offset = charset_leaf_idx_ptr;
     new.u.stat.numbers_offset = charset_numbers_ptr;
     new.num = c->num;
 
-    newp.storage = FcStorageStatic;
-    newp.u.stat = charset_ptr;
-    charsets[charset_ptr++] = new;
+    charsets[bi][charset_ptr++] = new;
 
-    leaf_idx[charset_leaf_idx_ptr++] = charset_leaf_ptr;
+    leaf_idx[bi][charset_leaf_idx_ptr++] = charset_leaf_ptr;
     for (i = 0; i < c->num; i++)
     {
-       memcpy (&leaves[charset_leaf_ptr++], 
+       memcpy (&leaves[bi][charset_leaf_ptr++], 
                c->u.dyn.leaves[i], sizeof(FcCharLeaf));
-       numbers[charset_numbers_ptr++] = c->u.dyn.numbers[i];
+       numbers[bi][charset_numbers_ptr++] = c->u.dyn.numbers[i];
     }
 
-    return newp;
-
- bail3: 
-    free (leaves);
- bail2:
-    free (numbers);
- bail1:
-    free (charsets);
- bail:
-    return FcCharSetPtrCreateDynamic(0);
-}
-
-FcBool
-FcCharSetRead (int fd, FcCache metadata)
-{
-    charsets = mmap(NULL, 
-                   metadata.charsets_length * sizeof (FcCharSet),
-                   PROT_READ,
-                   MAP_SHARED, fd, metadata.charsets_offset);
-    if (charsets == MAP_FAILED)
-        goto bail;
-    charset_count = charset_ptr = metadata.charsets_length;
-
-    leaves = mmap(NULL, 
-                 metadata.charset_num_sum * sizeof (FcCharLeaf),
-                 PROT_READ,
-                 MAP_SHARED, fd, metadata.charset_leaf_offset);
-    if (leaves == MAP_FAILED)
-        goto bail1;
-    charset_leaf_count = charset_leaf_ptr = metadata.charset_num_sum;
-
-    leaf_idx = mmap(NULL,
-                   metadata.charsets_length * sizeof (FcCharLeaf*),
-                   PROT_READ,
-                   MAP_SHARED, fd, metadata.charset_leafidx_offset);
-    if (leaf_idx == MAP_FAILED)
-       goto bail2;
-    charset_leaf_idx_count = charset_leaf_idx_ptr = metadata.charsets_length;
-
-    numbers = mmap(NULL, 
-                  metadata.charset_num_sum * sizeof (FcChar16),
-                  PROT_READ,
-                  MAP_SHARED, fd, metadata.charset_numbers_offset);
-    if (numbers == MAP_FAILED)
-        goto bail3;
-    charset_numbers_count = charset_numbers_ptr = metadata.charset_num_sum;
-
-    return FcTrue;
-
- bail3:
-    munmap (leaf_idx, metadata.charsets_length * sizeof (FcCharLeaf*));
- bail2:
-    munmap (leaves, metadata.charset_num_sum * sizeof (FcCharLeaf));
- bail1:
-    munmap (charsets, metadata.charsets_length * sizeof (FcCharSet));
- bail:
-    return FcFalse;
+    return &charsets[bi][cp];
 }
 
-FcBool
-FcCharSetWrite (int fd, FcCache *metadata)
+void *
+FcCharSetUnserialize (FcCache metadata, void *block_ptr)
 {
-    metadata->charsets_length = charset_ptr;
-    metadata->charsets_offset = FcCacheNextOffset(fd);
-
-    if (charset_ptr > 0)
-    {
-       lseek (fd, metadata->charsets_offset, SEEK_SET);
-       if (write (fd, charsets, charset_ptr * sizeof(FcCharSet)) == -1)
-           return FcFalse;
-    }
-
-    metadata->charset_leaf_offset = FcCacheNextOffset(fd);
-    metadata->charset_num_sum = charset_leaf_ptr;
-    if (charset_leaf_ptr > 0)
-    {
-       lseek (fd, metadata->charset_leaf_offset, SEEK_SET);
-       if (write (fd, leaves, charset_leaf_ptr * sizeof(FcCharLeaf)) == -1)
-           return FcFalse;
-    }
-
-    metadata->charset_leafidx_offset = FcCacheNextOffset(fd);
-    if (charset_leaf_idx_ptr > 0)
-    {
-       lseek (fd, metadata->charset_leafidx_offset, SEEK_SET);
-       if (write (fd, leaf_idx, charset_leaf_idx_ptr * sizeof(FcCharLeaf*)) == -1)
-           return FcFalse;
-    }
-
-
-    metadata->charset_numbers_offset = FcCacheNextOffset(fd);
-    if (charset_leaf_ptr > 0)
-    {
-       lseek (fd, metadata->charset_numbers_offset, SEEK_SET);
-       if (write (fd, numbers, charset_leaf_ptr * sizeof(FcChar16)) == -1)
-           return FcFalse;
-    }
+    int bi = FcCacheBankToIndex(metadata.bank);
+    if (!FcCharSetEnsureBank(bi))
+       return 0;
 
-    return FcTrue;
+    charsets[bi] = (FcCharSet *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                    (sizeof (FcCharSet) * metadata.charset_count));
+    numbers[bi] = (FcChar16 *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                    (sizeof(FcChar16) * metadata.charset_numbers_count));
+    leaves[bi] = (FcCharLeaf *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr +
+                    (sizeof(FcCharLeaf) * metadata.charset_leaf_count));
+    leaf_idx[bi] = (int *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr +
+                    (sizeof(int) * metadata.charset_leaf_idx_count));
+
+    return block_ptr;
 }
 
 FcCharLeaf *
 FcCharSetGetLeaf(const FcCharSet *c, int i)
 {
-    switch (c->storage)
-    {
-    case FcStorageDynamic:
+    int bi;
+    if (c->bank == FC_BANK_DYNAMIC)
        return c->u.dyn.leaves[i];
-    case FcStorageStatic:
-       return &leaves[leaf_idx[c->u.stat.leafidx_offset]+i];
-    default:
-       return 0;
-    }
+    bi = FcCacheBankToIndex(c->bank);
+
+    return &leaves[bi][leaf_idx[bi][c->u.stat.leafidx_offset]+i];
 }
 
 FcChar16 *
 FcCharSetGetNumbers(const FcCharSet *c)
 {
-    switch (c->storage)
-    {
-    case FcStorageDynamic:
+    int bi;
+    if (c->bank == FC_BANK_DYNAMIC)
        return c->u.dyn.numbers;
-    case FcStorageStatic:
-       return &numbers[c->u.stat.numbers_offset];
-    default:
-       return 0;
-    }
+    bi = FcCacheBankToIndex(c->bank);
+
+    return &numbers[bi][c->u.stat.numbers_offset];
 }
 
index c8b7127b356ae97fc5a5283ee7d41a5ff06aad45..c7e05701cbc2480555ca7913a673bf89c7b3c490 100644 (file)
@@ -40,24 +40,20 @@ FcValuePrint (const FcValue v)
        printf (" %g(f)", v.u.d);
        break;
     case FcTypeString:
-       printf (" \"%s\"", FcObjectPtrU(v.u.si));
+       printf (" \"%s\"", v.u.s);
        break;
     case FcTypeBool:
        printf (" %s", v.u.b ? "FcTrue" : "FcFalse");
        break;
     case FcTypeMatrix:
-    {
-       FcMatrix *m = FcMatrixPtrU(v.u.mi);
-
-       printf (" (%f %f; %f %f)", m->xx, m->xy, m->yx, m->yy);
+       printf (" (%f %f; %f %f)", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
        break;
-    }
     case FcTypeCharSet:        /* XXX */
        printf (" set");
        break;
     case FcTypeLangSet:
        printf (" ");
-       FcLangSetPrint (FcLangSetPtrU(v.u.li));
+       FcLangSetPrint (v.u.l);
        break;
     case FcTypeFTFace:
        printf (" face");
@@ -70,7 +66,7 @@ FcValueListPrint (FcValueListPtr l)
 {
     for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
     {
-       FcValuePrint (FcValueListPtrU(l)->value);
+       FcValuePrint (FcValueCanonicalize(&FcValueListPtrU(l)->value));
        switch (FcValueListPtrU(l)->binding) {
        case FcValueBindingWeak:
            printf ("(w)");
index 595e22a0f6ed8e4ada9f46dc2a6fe05069063d12..4f69f228bc0688fb98fb65df81b13d3a597f3fb1 100644 (file)
@@ -274,10 +274,17 @@ FcDirScan (FcFontSet          *set,
 }
 
 FcBool
-FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
+FcDirSave (FcFontSet *set, const FcChar8 *dir)
 {
-#if 0
-    return FcDirCacheWriteDir (set, dirs, dir);
-#endif
-    return FcTrue;
+    static int rand_state = 0;
+    int bank;
+
+    if (!rand_state) 
+       rand_state = time(0L);
+    bank = rand_r(&rand_state);
+
+    while (FcCacheHaveBank(bank))
+       bank = rand_r(&rand_state);
+
+    return FcDirCacheWrite (bank, set, dir);
 }
index f362e2b428a8b2ec0fa34025c85688cf27a14ff0..1e5aa81fe16c2a40ad0ee97007e2c0dc3fdb2348 100644 (file)
@@ -81,27 +81,58 @@ FcFontSetAdd (FcFontSet *s, FcPattern *font)
     return FcTrue;
 }
 
-FcBool
-FcFontSetPrepareSerialize (FcFontSet *s)
+static int * fcfs_pat_count;
+
+void
+FcFontSetNewBank (void)
 {
-    int i;
+    FcPatternNewBank();
+    FcObjectNewBank();
+}
+
+int
+FcFontSetNeededBytes (FcFontSet *s)
+{
+    int i, c, cum = 0;
 
     for (i = 0; i < s->nfont; i++)
-       if (!FcPatternPrepareSerialize(s->fonts[i]))
-           return FcFalse;
+    {
+       c = FcPatternNeededBytes(s->fonts[i]);
+       if (c < 0)
+           return c;
+       cum += c;
+    }
 
-    return FcTrue;
+    if (cum > 0)
+       return cum + sizeof(int);
+    else
+       return 0;
+}
+
+void *
+FcFontSetDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+    fcfs_pat_count = (int *)block_ptr;
+    block_ptr = (int *)block_ptr + 1;
+    // we don't consume any bytes for the fontset itself,
+    // since we don't allocate it statically.
+    block_ptr = FcPatternDistributeBytes (metadata, block_ptr);
+
+    // for good measure, write out the object ids used for
+    // this bank to the file.
+    return FcObjectDistributeBytes (metadata, block_ptr);
 }
 
 FcBool
-FcFontSetSerialize (FcFontSet * s)
+FcFontSetSerialize (int bank, FcFontSet * s)
 {
     int i;
     FcPattern * p;
+    *fcfs_pat_count = s->nfont;
 
     for (i = 0; i < s->nfont; i++)
     {
-       p = FcPatternSerialize (s->fonts[i]);
+       p = FcPatternSerialize (bank, s->fonts[i]);
        if (!p) return FcFalse;
        FcPatternDestroy (s->fonts[i]);
 
@@ -111,103 +142,34 @@ FcFontSetSerialize (FcFontSet * s)
     return FcTrue;
 }
 
-void
-FcFontSetClearStatic (void)
-{
-    FcPatternClearStatic();
-}
-
 FcBool
-FcFontSetRead(int fd, FcConfig * config, FcCache metadata)
+FcFontSetUnserialize(FcCache metadata, FcFontSet * s, void * block_ptr)
 {
-    int i, mz, j;
-    FcPattern * buf;
+    int nfont;
+    int i, n;
 
-    lseek(fd, metadata.fontsets_offset, SEEK_SET);
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
-    {
-        if (config->fonts[i])
-        {
-            if (config->fonts[i]->nfont > 0 && config->fonts[i]->fonts)
-                free (config->fonts[i]->fonts);
-            free (config->fonts[i]);
-        }
-    }
+    nfont = *(int *)block_ptr;
+    block_ptr = (int *)block_ptr + 1;
 
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
+    if (s->sfont < s->nfont + nfont)
     {
-        read(fd, &mz, sizeof(int));
-        if (mz != FC_CACHE_MAGIC)
-            continue;
-
-        config->fonts[i] = malloc(sizeof(FcFontSet));
-        if (!config->fonts[i])
-            return FcFalse;
-        FcMemAlloc(FC_MEM_FONTSET, sizeof(FcFontSet));
-
-        if (read(fd, config->fonts[i], sizeof(FcFontSet)) == -1)
-            goto bail;
-        if (config->fonts[i]->sfont > 0)
-        {
-            config->fonts[i]->fonts = malloc
-                (config->fonts[i]->sfont*sizeof(FcPattern *));
-           buf = malloc (config->fonts[i]->sfont * sizeof(FcPattern));
-           if (!config->fonts[i]->fonts || !buf)
-               goto bail;
-           for (j = 0; j < config->fonts[i]->nfont; j++)
-           {
-               config->fonts[i]->fonts[j] = buf+j;
-               if (read(fd, buf+j, sizeof(FcPattern)) == -1)
-                   goto bail;
-           }
-        }
+       int sfont = s->nfont + nfont;
+       FcPattern ** pp;
+       pp = realloc (s->fonts, sfont * sizeof (FcPattern));
+       if (!pp)
+           return FcFalse;
+       s->fonts = pp;
+       s->sfont = sfont;
     }
+    n = s->nfont;
+    s->nfont += nfont;
 
-    return FcTrue;
- bail:
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
+    if (nfont > 0)
     {
-        if (config->fonts[i])
-        {
-            if (config->fonts[i]->fonts)
-                free (config->fonts[i]->fonts);
-            free(config->fonts[i]);
-        }
-        config->fonts[i] = 0;
+       FcPattern * p = FcPatternUnserialize (metadata, block_ptr);
+       for (i = 0; i < nfont; i++)
+           s->fonts[n + i] = p+i;
     }
-    return FcFalse;
-}
 
-FcBool
-FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata)
-{
-    int c, t, i, j;
-    int m = FC_CACHE_MAGIC, z = 0;
-
-    metadata->fontsets_offset = FcCacheNextOffset(fd);
-    lseek(fd, metadata->fontsets_offset, SEEK_SET);
-    for (i = FcSetSystem; i <= FcSetApplication; i++)
-    {
-        if (!config->fonts[i])
-        {
-            write(fd, &z, sizeof(int));
-            continue;
-        }
-        else
-            write(fd, &m, sizeof(int));
-
-        if ((c = write(fd, config->fonts[i], sizeof(FcFontSet))) == -1)
-            return FcFalse;
-        t = c;
-        if (config->fonts[i]->nfont > 0)
-        {
-           for (j = 0; j < config->fonts[i]->nfont; j++)
-           {
-               if ((c = write(fd, config->fonts[i]->fonts[j],
-                              sizeof(FcPattern))) == -1)
-                   return FcFalse;
-           }
-        }
-    }
     return FcTrue;
 }
index 9c51c28c97b4dcbdb46a0faff2e05b3bd35aeb39..8a9bdbda8c6e1634bdbb39deb60ae221838b1d99 100644 (file)
@@ -61,9 +61,6 @@ FcInitLoadConfig (void)
     if (!config)
        return FcFalse;
     
-    if (!FcCacheRead(config))
-        FcCacheForce(FcTrue);
-
     if (!FcConfigParseAndLoad (config, 0, FcTrue))
     {
        FcConfigDestroy (config);
index 992c09f8e6f72638ad0bcaeaa87c7710daa39d6e..529548c20eb47e49e4a6065dc7881418872a00f1 100644 (file)
@@ -109,16 +109,8 @@ typedef enum _FcValueBinding {
     FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
 } FcValueBinding;
 
-typedef struct _FcStrSetPtr {
-    FcStorage               storage;
-    union {
-        int                stat;
-        struct _FcStrSet    *dyn;
-    } u;
-} FcStrSetPtr;
-
 typedef struct _FcValueListPtr {
-    FcStorage               storage;
+    int                        bank;
     union {
         int                stat;
         struct _FcValueList *dyn;
@@ -132,8 +124,10 @@ typedef struct _FcValueList {
     FcValueBinding         binding;
 } FcValueList;
 
+typedef int FcObjectPtr;
+
 typedef struct _FcPatternEltPtr {
-    FcStorage               storage;
+    int                        bank;
     union {
         int                stat;
         struct _FcPatternElt *dyn;
@@ -150,6 +144,7 @@ struct _FcPattern {
     int                    size;
     FcPatternEltPtr elts;
     int                    ref;
+    int                    bank;
 };
 
 typedef enum _FcOp {
@@ -222,7 +217,7 @@ typedef struct _FcCharLeaf {
 struct _FcCharSet {
     int                    ref;        /* reference count */
     int                    num;        /* size of leaves and numbers arrays */
-    FcStorage      storage;
+    int                    bank;
     union {
        struct {
            FcCharLeaf  **leaves;
@@ -239,11 +234,7 @@ struct _FcStrSet {
     int                    ref;        /* reference count */
     int                    num;
     int                    size;
-    FcStorage      storage;
-    union {
-       FcChar8     **strs;
-       int         stridx_offset;
-    } u;
+    FcChar8        **strs;
 };
 
 struct _FcStrList {
@@ -261,21 +252,17 @@ typedef struct _FcStrBuf {
 
 typedef struct _FcCache {
     int            magic;
-    off_t   fontsets_offset;
-    off_t   pattern_offset;     int pattern_length;
-    off_t   patternelt_offset;  int patternelt_length;
-    off_t   valuelist_offset;   int valuelist_length;
-    off_t   object_offset;     int object_length;
-    off_t   objectcontent_offset; int objectcontent_length;
-    off_t   langsets_offset;    int langsets_length;
-    off_t   charsets_offset;    int charsets_length;
-    off_t   charset_leaf_offset; int charset_num_sum;
-    off_t   charset_leafidx_offset; 
-    off_t   charset_numbers_offset;
-    off_t   matrices_offset;    int matrices_length;
-    off_t   strsets_offset;     int strsets_length;
-    off_t   strsets_idx_offset; int strsets_idx_length;
-    off_t   strset_buf_offset;  int strset_buf_length;
+    int            count;
+    int     bank;
+    int     pattern_count;
+    int     patternelt_count;
+    int     valuelist_count;
+    int     str_count;
+    int            langset_count;
+    int     charset_count;
+    int     charset_numbers_count;
+    int     charset_leaf_count;
+    int     charset_leaf_idx_count;
 } FcCache;
 
 /*
@@ -321,6 +308,11 @@ typedef struct _FcCaseFold {
 
 #define FC_MAX_FILE_LEN            4096
 
+#define FC_STORAGE_STATIC 0x80
+#define fc_value_string(v)  (((v)->type & FC_STORAGE_STATIC) ? ((FcChar8 *) v) + (v)->u.s_off : (v) -> u.s)
+#define fc_value_charset(v)  (((v)->type & FC_STORAGE_STATIC) ? (const FcCharSet *)(((char *) v) + (v)->u.c_off) : (v) -> u.c)
+#define fc_value_langset(v)  (((v)->type & FC_STORAGE_STATIC) ? (const FcLangSet *)(((char *) v) + (v)->u.l_off) : (v) -> u.l)
+
 /*
  * The per-user ~/.fonts.cache-<version> file is loaded into
  * this data structure.  Each directory gets a substructure
@@ -449,26 +441,29 @@ typedef struct _FcCharMap FcCharMap;
 
 /* fccache.c */
 
-int
-FcCacheNextOffset(int fd);
-
 void
 FcCacheForce(FcBool force);
 
-void
-FcCacheClearStatic(void);
-
 FcBool
-FcCachePrepareSerialize(FcConfig * config);
+FcCacheSerialize (int bank, FcConfig * config);
+
+FcFontSet *
+FcCacheRead (FcConfig *config);
 
 FcBool
-FcCacheSerialize (FcConfig * config);
+FcDirCacheRead (FcFontSet * set, const FcChar8 *dir);
 
 FcBool
-FcCacheRead (FcConfig *config);
+FcDirCacheWrite (int bank, FcFontSet *set, const FcChar8 *dir);
+
+int
+FcCacheBankCount (void);
 
 FcBool
-FcCacheWrite (FcConfig * config);
+FcCacheHaveBank (int bank);
+
+int
+FcCacheBankToIndex (int bank);
  
 /* fccfg.c */
 
@@ -508,9 +503,9 @@ FcConfigSetFonts (FcConfig  *config,
                  FcSetName     set);
 
 FcBool
-FcConfigCompareValue (const FcValue m,
+FcConfigCompareValue (const FcValue *m,
                      FcOp          op,
-                     const FcValue v);
+                     const FcValue *v);
 
 FcBool
 FcConfigGlobAdd (FcConfig      *config,
@@ -534,9 +529,6 @@ FcConfigAcceptFont (FcConfig            *config,
 FcCharSet *
 FcCharSetFreeze (FcCharSet *cs);
 
-FcCharSetPtr
-FcCharSetCopyPtr (FcCharSetPtr src);
-
 void
 FcCharSetThawAll (void);
 
@@ -550,19 +542,20 @@ FcCharLeaf *
 FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4);
 
 void
-FcCharSetPtrDestroy (FcCharSetPtr fcs);
+FcCharSetNewBank (void);
 
-void
-FcCharSetClearStatic(void);
+int
+FcCharSetNeededBytes (const FcCharSet *c);
 
-FcBool
-FcCharSetPrepareSerialize(FcCharSet *c);
+void *
+FcCharSetDistributeBytes (FcCache * metadata,
+                         void * block_ptr);
 
-FcCharSetPtr
-FcCharSetSerialize(FcCharSet *c);
+FcCharSet *
+FcCharSetSerialize(int bank, FcCharSet *c);
 
-FcCharSetPtr
-FcCharSetPtrCreateDynamic(FcCharSet *c);
+void *
+FcCharSetUnserialize (FcCache metadata, void *block_ptr);
 
 FcCharLeaf *
 FcCharSetGetLeaf(const FcCharSet *c, int i);
@@ -570,12 +563,6 @@ FcCharSetGetLeaf(const FcCharSet *c, int i);
 FcChar16 *
 FcCharSetGetNumbers(const FcCharSet *c);
 
-FcBool
-FcCharSetRead (int fd, FcCache metadata);
-
-FcBool
-FcCharSetWrite (int fd, FcCache *metadata);
-
 /* fcdbg.c */
 void
 FcValueListPrint (const FcValueListPtr l);
@@ -601,9 +588,6 @@ FcSubstPrint (const FcSubst *subst);
 int
 FcDebug (void);
 
-FcCharSet *
-FcCharSetPtrU (FcCharSetPtr mi);
-
 /* fcdir.c */
 
 FcBool
@@ -650,19 +634,19 @@ FcFreeTypeGetPrivateMap (FT_Encoding encoding);
 /* fcfs.c */
 
 void
-FcFontSetClearStatic (void);
+FcFontSetNewBank (void);
 
-FcBool
-FcFontSetPrepareSerialize (FcFontSet * s);
+int
+FcFontSetNeededBytes (FcFontSet *s);
 
-FcBool
-FcFontSetSerialize (FcFontSet * s);
+void *
+FcFontSetDistributeBytes (FcCache * metadata, void * block_ptr);
 
 FcBool
-FcFontSetRead(int fd, FcConfig * config, FcCache metadata);
+FcFontSetSerialize (int bank, FcFontSet * s);
 
 FcBool
-FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata);
+FcFontSetUnserialize(FcCache metadata, FcFontSet * s, void * block_ptr);
 
 /* fcgram.y */
 int
@@ -745,28 +729,20 @@ FcBool
 FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls);
 
 void
-FcLangSetClearStatic (void);
+FcLangSetNewBank (void);
 
-FcBool
-FcLangSetPrepareSerialize (FcLangSet *l);
+int
+FcLangSetNeededBytes (const FcLangSet *l);
 
-FcLangSetPtr
-FcLangSetSerialize (FcLangSet *l);
+void *
+FcLangSetDistributeBytes (FcCache * metadata,
+                         void * block_ptr);
 
 FcLangSet *
-FcLangSetPtrU (FcLangSetPtr li);
-
-FcLangSetPtr
-FcLangSetPtrCreateDynamic (FcLangSet *l);
-
-void
-FcLangSetPtrDestroy (FcLangSetPtr li);
+FcLangSetSerialize (int bank, FcLangSet *l);
 
-FcBool
-FcLangSetRead (int fd, FcCache metadata);
-
-FcBool
-FcLangSetWrite (int fd, FcCache *metadata);
+void *
+FcLangSetUnserialize (FcCache metadata, void *block_ptr);
 
 /* fclist.c */
 
@@ -781,7 +757,30 @@ FcListPatternMatchAny (const FcPattern *p,
 FcBool
 FcNameBool (const FcChar8 *v, FcBool *result);
 
+void
+FcObjectNewBank(void);
+
+void *
+FcObjectDistributeBytes (FcCache * metadata,
+                        void * block_ptr);
+
+FcObjectPtr
+FcObjectToPtr (const char * si);
+
+int
+FcObjectNeededBytes (FcObjectPtr p);
+
+void
+FcObjectUnserialize (FcCache metadata, FcConfig * config, void *block_ptr);
+
+FcObjectPtr
+FcObjectSerialize (FcObjectPtr s);
+
 /* fcpat.c */
+
+FcValue
+FcValueCanonicalize (const FcValue *v);
+
 void
 FcValueListDestroy (FcValueListPtr l);
 
@@ -807,18 +806,9 @@ FcPatternFini (void);
 FcBool
 FcPatternAppend (FcPattern *p, FcPattern *s);
 
-void
-FcObjectClearStatic(void);
-
-FcObjectPtr
+const char *
 FcObjectStaticName (const char *name);
 
-FcBool
-FcObjectRead (int fd, FcCache metadata);
-
-FcBool
-FcObjectWrite (int fd, FcCache * metadata);
-
 const char *
 FcObjectPtrU (FcObjectPtr p);
 
@@ -826,16 +816,13 @@ int
 FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b);
 
 void
-FcObjectPtrDestroy (FcObjectPtr p);
-
-FcBool
-FcPatternPrepareSerialize (FcPattern *p);
+FcPatternNewBank (void);
 
-void
-FcValueListClearStatic (void);
+int
+FcPatternNeededBytes (FcPattern *p);
 
-void
-FcPatternClearStatic (void);
+void *
+FcPatternDistributeBytes (FcCache * metadata, void * block_ptr);
 
 FcValueList * 
 FcValueListPtrU(FcValueListPtr p);
@@ -846,85 +833,25 @@ FcPatternEltU (FcPatternEltPtr pei);
 FcValueListPtr
 FcValueListPtrCreateDynamic(FcValueList * p);
 
-FcBool
-FcValueListPrepareSerialize (FcValueList *p);
-
-FcValueListPtr
-FcValueListSerialize(FcValueList *pi);
-
 FcPattern *
-FcPatternSerialize (FcPattern * p);
-
-FcBool
-FcPatternRead (int fd, FcCache metadata);
-
-FcBool
-FcPatternWrite (int fd, FcCache *metadata);
-
-FcBool
-FcPatternEltRead (int fd, FcCache metadata);
-
-FcBool
-FcPatternEltWrite (int fd, FcCache *metadata);
-
-FcBool
-FcValueListRead (int fd, FcCache metadata);
+FcPatternSerialize (int bank, FcPattern * p);
 
-FcBool
-FcValueListWrite (int fd, FcCache *metadata);
+FcPattern *
+FcPatternUnserialize (FcCache metadata, void *block_ptr);
 
 /* fcrender.c */
 
 /* fcmatrix.c */
 
-extern const FcMatrixPtr    FcIdentityMatrix;
+extern const FcMatrix    FcIdentityMatrix;
 
 void
 FcMatrixFree (FcMatrix *mat);
 
-void
-FcMatrixPtrDestroy (FcMatrixPtr mi);
-
-FcBool
-FcMatrixPrepareSerialize(FcMatrix *m);
-
-FcMatrixPtr
-FcMatrixSerialize(FcMatrix *m);
-
-FcMatrix *
-FcMatrixPtrU (FcMatrixPtr mi);
-
-FcMatrixPtr
-FcMatrixPtrCreateDynamic (FcMatrix *m);
-
-void 
-FcMatrixClearStatic (void);
-
-FcBool
-FcMatrixWrite (int fd, FcCache *metadata);
-
-FcBool
-FcMatrixRead (int fd, FcCache metadata);
-
 /* fcstr.c */
-FcStrSet *
-FcStrSetPtrU (const FcStrSetPtr set);
-
-FcStrSetPtr
-FcStrSetPtrCreateDynamic (const FcStrSet * set);
-
-void
-FcStrSetClearStatic (void);
-
-FcBool
-FcStrSetPrepareSerialize (const FcStrSet *set);
-
 void
 FcStrSetSort (FcStrSet * set);
 
-FcChar8 *
-FcStrSetGet (const FcStrSet *set, int i);
-
 FcChar8 *
 FcStrPlus (const FcChar8 *s1, const FcChar8 *s2);
     
@@ -949,15 +876,6 @@ FcStrBufString (FcStrBuf *buf, const FcChar8 *s);
 FcBool
 FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
 
-FcStrSetPtr
-FcStrSetSerialize (FcStrSet *set);
-
-FcBool
-FcStrSetRead (int fd, FcCache metadata);
-
-FcBool
-FcStrSetWrite (int fd, FcCache *metadata);
-
 int
 FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
 
index 515e3cf74d29449b4717281c2b4134ccf8f7c83f..711cdc75aa9c6e40fa1480df4d38ce35972a88ff 100644 (file)
@@ -22,8 +22,6 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <fcntl.h>
-#include <sys/mman.h>
 #include "fcint.h"
 
 typedef struct {
@@ -40,7 +38,7 @@ typedef struct {
 
 struct _FcLangSet {
     FcChar32   map[NUM_LANG_SET_MAP];
-    FcStrSetPtr        extra;
+    FcStrSet   *extra;
 };
 
 #define FcLangSetBitSet(ls, id)        ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
@@ -217,22 +215,15 @@ FcLangSetCreate (void)
        return 0;
     FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
     memset (ls->map, '\0', sizeof (ls->map));
-    ls->extra = FcStrSetPtrCreateDynamic(0);
+    ls->extra = 0;
     return ls;
 }
 
-void
-FcLangSetPtrDestroy (FcLangSetPtr li)
-{
-    if (li.storage == FcStorageDynamic)
-       FcLangSetDestroy(FcLangSetPtrU(li));
-}
-
 void
 FcLangSetDestroy (FcLangSet *ls)
 {
-    if (FcStrSetPtrU(ls->extra))
-       FcStrSetDestroy (FcStrSetPtrU(ls->extra));
+    if (ls->extra)
+       FcStrSetDestroy (ls->extra);
     FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
     free (ls);
 }
@@ -246,21 +237,21 @@ FcLangSetCopy (const FcLangSet *ls)
     if (!new)
        goto bail0;
     memcpy (new->map, ls->map, sizeof (new->map));
-    if (FcStrSetPtrU(ls->extra))
+    if (ls->extra)
     {
        FcStrList       *list;
        FcChar8         *extra;
        
-       new->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ());
-       if (!FcStrSetPtrU(new->extra))
+       new->extra = FcStrSetCreate ();
+       if (!new->extra)
            goto bail1;
 
-       list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+       list = FcStrListCreate (ls->extra);     
        if (!list)
            goto bail1;
        
        while ((extra = FcStrListNext (list)))
-           if (!FcStrSetAdd (FcStrSetPtrU(new->extra), extra))
+           if (!FcStrSetAdd (new->extra, extra))
            {
                FcStrListDone (list);
                goto bail1;
@@ -341,13 +332,13 @@ FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
        FcLangSetBitSet (ls, id);
        return FcTrue;
     }
-    if (!FcStrSetPtrU(ls->extra))
+    if (!ls->extra)
     {
-       ls->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ());
-       if (!FcStrSetPtrU(ls->extra))
+       ls->extra = FcStrSetCreate ();
+       if (!ls->extra)
            return FcFalse;
     }
-    return FcStrSetAdd (FcStrSetPtrU(ls->extra), lang);
+    return FcStrSetAdd (ls->extra, lang);
 }
 
 FcLangResult
@@ -379,9 +370,9 @@ FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
        if (FcLangSetBitGet (ls, i) && r < best)
            best = r;
     }
-    if (FcStrSetPtrU(ls->extra))
+    if (ls->extra)
     {
-       FcStrList       *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+       FcStrList       *list = FcStrListCreate (ls->extra);
        FcChar8         *extra;
        FcLangResult    r;
        
@@ -437,15 +428,15 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
                best = FcLangDifferentCountry;
                break;
            }
-    if (FcStrSetPtrU(lsa->extra))
+    if (lsa->extra)
     {
-       r = FcLangSetCompareStrSet (lsb, FcStrSetPtrU(lsa->extra));
+       r = FcLangSetCompareStrSet (lsb, lsa->extra);
        if (r < best)
            best = r;
     }
-    if (best > FcLangEqual && FcStrSetPtrU(lsb->extra))
+    if (best > FcLangEqual && lsb->extra)
     {
-       r = FcLangSetCompareStrSet (lsa, FcStrSetPtrU(lsb->extra));
+       r = FcLangSetCompareStrSet (lsa, lsb->extra);
        if (r < best)
            best = r;
     }
@@ -464,7 +455,7 @@ FcLangSetPromote (const FcChar8 *lang)
     int                        id;
 
     memset (ls.map, '\0', sizeof (ls.map));
-    ls.extra = FcStrSetPtrCreateDynamic(0);
+    ls.extra = 0;
     id = FcLangSetIndex (lang);
     if (id > 0)
     {
@@ -472,11 +463,10 @@ FcLangSetPromote (const FcChar8 *lang)
     }
     else
     {
-       ls.extra = FcStrSetPtrCreateDynamic(&strs);
+       ls.extra = &strs;
        strs.num = 1;
        strs.size = 1;
-       strs.storage = FcStorageDynamic;
-       strs.u.strs = &str;
+       strs.strs = &str;
        strs.ref = 1;
        str = (FcChar8 *) lang;
     }
@@ -491,8 +481,8 @@ FcLangSetHash (const FcLangSet *ls)
 
     for (i = 0; i < NUM_LANG_SET_MAP; i++)
        h ^= ls->map[i];
-    if (FcStrSetPtrU(ls->extra))
-       h ^= FcStrSetPtrU(ls->extra)->num;
+    if (ls->extra)
+       h ^= ls->extra->num;
     return h;
 }
 
@@ -553,9 +543,9 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
                }
        }
     }
-    if (FcStrSetPtrU(ls->extra))
+    if (ls->extra)
     {
-       FcStrList   *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+       FcStrList   *list = FcStrListCreate (ls->extra);
        FcChar8     *extra;
 
        if (!list)
@@ -583,10 +573,10 @@ FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
        if (lsa->map[i] != lsb->map[i])
            return FcFalse;
     }
-    if (!FcStrSetPtrU(lsa->extra) && !FcStrSetPtrU(lsb->extra))
+    if (!lsa->extra && !lsb->extra)
        return FcTrue;
-    if (FcStrSetPtrU(lsa->extra) && FcStrSetPtrU(lsb->extra))
-       return FcStrSetEqual (FcStrSetPtrU(lsa->extra), FcStrSetPtrU(lsb->extra));
+    if (lsa->extra && lsb->extra)
+       return FcStrSetEqual (lsa->extra, lsb->extra);
     return FcFalse;
 }
 
@@ -620,9 +610,9 @@ FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
            FcLangContains (fcLangCharSets[i].lang, lang))
            return FcTrue;
     }
-    if (FcStrSetPtrU(ls->extra))
+    if (ls->extra)
     {
-       FcStrList       *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+       FcStrList       *list = FcStrListCreate (ls->extra);
        FcChar8         *extra;
        
        if (list)
@@ -676,9 +666,9 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
                }
        }
     }
-    if (FcStrSetPtrU(lsb->extra))
+    if (lsb->extra)
     {
-       FcStrList   *list = FcStrListCreate (FcStrSetPtrU(lsb->extra));
+       FcStrList   *list = FcStrListCreate (lsb->extra);
        FcChar8     *extra;
 
        if (list)
@@ -700,105 +690,82 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
     return FcTrue;
 }
 
-static FcLangSet * langsets = 0;
-static int langset_ptr = 0, langset_count = 0;
-
-FcLangSet *
-FcLangSetPtrU (FcLangSetPtr li)
-{
-    switch (li.storage)
-    {
-    case FcStorageDynamic:
-       return li.u.dyn;
-    case FcStorageStatic:
-       return &langsets[li.u.stat];
-    default:
-       return 0;
-
-    }
-}
-
-FcLangSetPtr
-FcLangSetPtrCreateDynamic (FcLangSet *li)
-{
-    FcLangSetPtr new;
-    new.storage = FcStorageDynamic;
-    new.u.dyn = li;
-    return new;
-}
+static FcLangSet ** langsets = 0;
+static int langset_bank_count = 0, langset_ptr = 0, langset_count = 0;
 
 void
-FcLangSetClearStatic (void)
+FcLangSetNewBank (void)
 {
-    FcStrSetClearStatic();
-    langset_ptr = 0;
     langset_count = 0;
 }
 
-/* should only write one copy of any particular FcLangSet */
-FcBool
-FcLangSetPrepareSerialize (FcLangSet *l)
+/* ideally, should only write one copy of any particular FcLangSet */
+int
+FcLangSetNeededBytes (const FcLangSet *l)
 {
     langset_count++;
-    if (l && FcStrSetPtrU(l->extra))
-       return FcStrSetPrepareSerialize (FcStrSetPtrU(l->extra));
-    return FcTrue;
+    return sizeof (FcLangSet);
 }
 
-FcLangSetPtr
-FcLangSetSerialize(FcLangSet *l)
+static FcBool
+FcLangSetEnsureBank (int bi)
 {
-    FcLangSetPtr new;
-    int p = langset_ptr;
-
-    if (!l) return FcLangSetPtrCreateDynamic(0);
-
-    if (!langsets)
+    if (!langsets || bi >= langset_bank_count)
     {
-       FcLangSet* t;
-       t = (FcLangSet *)malloc(langset_count * sizeof(FcLangSet));
-       if (!t)
-           return FcLangSetPtrCreateDynamic(0);
-       langsets = t;
-       langset_ptr = 0;
+       int new_count = langset_bank_count + 2;
+       int i;
+       FcLangSet** tt;
+       tt = realloc(langsets, new_count * sizeof(FcLangSet *));
+       if (!tt)
+           return FcFalse;
+
+       langsets = tt;
+       for (i = langset_bank_count; i < new_count; i++)
+           langsets[i] = 0; 
+       langset_bank_count = new_count;
     }
 
-    langsets[langset_ptr] = *l;
-    if (FcStrSetPtrU(l->extra))
-       langsets[langset_ptr].extra = 
-           FcStrSetSerialize(FcStrSetPtrU(l->extra));
-    else
-       langsets[langset_ptr].extra = FcStrSetPtrCreateDynamic(0);
-    langset_ptr++;
-    new.storage = FcStorageStatic;
-    new.u.stat = p;
-    return new;
+    return FcTrue;
 }
 
-FcBool
-FcLangSetWrite (int fd, FcCache *metadata)
+void *
+FcLangSetDistributeBytes (FcCache * metadata, void * block_ptr)
 {
-    metadata->langsets_length = langset_ptr;
-    metadata->langsets_offset = FcCacheNextOffset(fd);
+    int bi = FcCacheBankToIndex(metadata->bank);
+    if (!FcLangSetEnsureBank(bi))
+       return 0;
 
-    if (langset_ptr > 0)
-    {
-       lseek (fd, metadata->langsets_offset, SEEK_SET);
-       return write(fd, langsets, 
-                    metadata->langsets_length * sizeof(FcLangSet)) != -1;
-    }
-    return FcTrue;
+    langsets[bi] = block_ptr;
+    block_ptr = (void *)((char *)block_ptr +
+                        langset_count * sizeof(FcLangSet));
+    langset_ptr = 0;
+    metadata->langset_count = langset_count;
+    return block_ptr;
 }
 
-FcBool
-FcLangSetRead (int fd, FcCache metadata)
+FcLangSet *
+FcLangSetSerialize(int bank, FcLangSet *l)
 {
-    langsets = mmap(NULL, 
-                   metadata.langsets_length * sizeof (FcLangSet),
-                   PROT_READ,
-                   MAP_SHARED, fd, metadata.langsets_offset);
-    if (langsets == MAP_FAILED)
-       return FcFalse;
-    langset_count = langset_ptr = metadata.langsets_length;
-    return FcTrue;
+    int p = langset_ptr, bi = FcCacheBankToIndex(bank);
+
+    if (!l) return 0;
+
+    langsets[bi][langset_ptr] = *l;
+    langsets[bi][langset_ptr].extra = 0;
+    langset_ptr++;
+    return &langsets[bi][p];
+}
+
+void *
+FcLangSetUnserialize (FcCache metadata, void *block_ptr)
+{
+    int bi = FcCacheBankToIndex(metadata.bank);
+    if (!FcLangSetEnsureBank(bi))
+       return 0;
+
+    FcMemAlloc (FC_MEM_LANGSET, metadata.langset_count * sizeof(FcLangSet));
+    langsets[bi] = (FcLangSet *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr +
+                        metadata.langset_count * sizeof(FcLangSet));
+    return block_ptr;
 }
index b3ecdb82cf2d71e792355093fd88fcad315475da..db63058f9a93d19819aefd0eae96d3481bbcbad3 100644 (file)
@@ -23,9 +23,6 @@
  */
 
 #include <stdlib.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <unistd.h>
 #include "fcint.h"
 
 FcObjectSet *
@@ -47,18 +44,17 @@ FcBool
 FcObjectSetAdd (FcObjectSet *os, const char *object)
 {
     int                s;
-    FcObjectPtr        *objects;
-    FcObjectPtr obj;
+    const char **objects;
     int                high, low, mid, c;
     
     if (os->nobject == os->sobject)
     {
        s = os->sobject + 4;
        if (os->objects)
-           objects = (FcObjectPtr *) realloc ((void *) os->objects,
-                                              s * sizeof (FcObjectPtr));
+           objects = (const char **) realloc ((void *) os->objects,
+                                              s * sizeof (const char *));
        else
-           objects = (FcObjectPtr *) malloc (s * sizeof (FcObjectPtr));
+           objects = (const char **) malloc (s * sizeof (const char *));
        if (!objects)
            return FcFalse;
        if (os->sobject)
@@ -71,11 +67,11 @@ FcObjectSetAdd (FcObjectSet *os, const char *object)
     low = 0;
     mid = 0;
     c = 1;
-    obj = FcObjectStaticName (object);
+    object = FcObjectStaticName (object);
     while (low <= high)
     {
        mid = (low + high) >> 1;
-       c = FcObjectPtrCompare(os->objects[mid], obj);
+       c = os->objects[mid] - object;
        if (c == 0)
            return FcTrue;
        if (c < 0)
@@ -86,8 +82,8 @@ FcObjectSetAdd (FcObjectSet *os, const char *object)
     if (c < 0)
        mid++;
     memmove (os->objects + mid + 1, os->objects + mid, 
-            (os->nobject - mid) * sizeof (FcObjectPtr));
-    os->objects[mid] = obj;
+            (os->nobject - mid) * sizeof (const char *));
+    os->objects[mid] = object;
     os->nobject++;
     return FcTrue;
 }
@@ -145,9 +141,9 @@ FcListValueListMatchAny (FcValueListPtr patOrig,        /* pattern */
             * (OpListing is OpContains except for strings
             *  where it requires an exact match)
             */
-           if (FcConfigCompareValue (FcValueListPtrU(fnt)->value,
+           if (FcConfigCompareValue (&FcValueListPtrU(fnt)->value,
                                      FcOpListing, 
-                                     FcValueListPtrU(pat)->value)) 
+                                     &FcValueListPtrU(pat)->value)) 
                break;
        }
        if (!FcValueListPtrU(fnt))
@@ -167,8 +163,8 @@ FcListValueListEqual (FcValueListPtr v1orig,
     {
        for (v2 = v2orig; FcValueListPtrU(v2); 
             v2 = FcValueListPtrU(v2)->next)
-           if (FcValueEqual (FcValueListPtrU(v1)->value, 
-                             FcValueListPtrU(v2)->value))
+           if (FcValueEqual (FcValueCanonicalize(&FcValueListPtrU(v1)->value),
+                             FcValueCanonicalize(&FcValueListPtrU(v2)->value)))
                break;
        if (!FcValueListPtrU(v2))
            return FcFalse;
@@ -178,8 +174,8 @@ FcListValueListEqual (FcValueListPtr v1orig,
     {
        for (v1 = v1orig; FcValueListPtrU(v1); 
             v1 = FcValueListPtrU(v1)->next)
-           if (FcValueEqual (FcValueListPtrU(v1)->value, 
-                             FcValueListPtrU(v2)->value))
+           if (FcValueEqual (FcValueCanonicalize(&FcValueListPtrU(v1)->value),
+                             FcValueCanonicalize(&FcValueListPtrU(v2)->value)))
                break;
        if (!FcValueListPtrU(v1))
            return FcFalse;
@@ -197,8 +193,8 @@ FcListPatternEqual (FcPattern       *p1,
 
     for (i = 0; i < os->nobject; i++)
     {
-       e1 = FcPatternFindElt (p1, FcObjectPtrU(os->objects[i]));
-       e2 = FcPatternFindElt (p2, FcObjectPtrU(os->objects[i]));
+       e1 = FcPatternFindElt (p1, os->objects[i]);
+       e2 = FcPatternFindElt (p2, os->objects[i]);
        if (!e1 && !e2)
            continue;
        if (!e1 || !e2)
@@ -245,8 +241,9 @@ FcListMatrixHash (const FcMatrix *m)
 }
 
 static FcChar32
-FcListValueHash (FcValue    v)
+FcListValueHash (FcValue    *value)
 {
+    FcValue v = FcValueCanonicalize(value);
     switch (v.type) {
     case FcTypeVoid:
        return 0;
@@ -255,17 +252,17 @@ FcListValueHash (FcValue    v)
     case FcTypeDouble:
        return (FcChar32) (int) v.u.d;
     case FcTypeString:
-       return FcStrHashIgnoreCase (FcObjectPtrU(v.u.si));
+       return FcStrHashIgnoreCase (v.u.s);
     case FcTypeBool:
        return (FcChar32) v.u.b;
     case FcTypeMatrix:
-       return FcListMatrixHash (FcMatrixPtrU(v.u.mi));
+       return FcListMatrixHash (v.u.m);
     case FcTypeCharSet:
-       return FcCharSetCount (FcCharSetPtrU(v.u.ci));
+       return FcCharSetCount (v.u.c);
     case FcTypeFTFace:
        return (long) v.u.f;
     case FcTypeLangSet:
-       return FcLangSetHash (FcLangSetPtrU(v.u.li));
+       return FcLangSetHash (v.u.l);
     }
     return 0;
 }
@@ -277,7 +274,7 @@ FcListValueListHash (FcValueListPtr list)
     
     while (FcValueListPtrU(list))
     {
-       h = h ^ FcListValueHash (FcValueListPtrU(list)->value);
+       h = h ^ FcListValueHash (&FcValueListPtrU(list)->value);
        list = FcValueListPtrU(list)->next;
     }
     return h;
@@ -293,7 +290,7 @@ FcListPatternHash (FcPattern        *font,
 
     for (n = 0; n < os->nobject; n++)
     {
-       e = FcPatternFindElt (font, FcObjectPtrU(os->objects[n]));
+       e = FcPatternFindElt (font, os->objects[n]);
        if (e)
            h = h ^ FcListValueListHash (e->values);
     }
@@ -371,15 +368,15 @@ FcListAppend (FcListHashTable     *table,
     
     for (o = 0; o < os->nobject; o++)
     {
-       e = FcPatternFindElt (font, FcObjectPtrU(os->objects[o]));
+       e = FcPatternFindElt (font, os->objects[o]);
        if (e)
        {
            for (v = e->values; FcValueListPtrU(v); 
                 v = FcValueListPtrU(v)->next)
            {
                if (!FcPatternAdd (bucket->pattern, 
-                                  FcObjectPtrU(os->objects[o])
-                                  FcValueListPtrU(v)->value, FcTrue))
+                                  os->objects[o]
+                                  FcValueCanonicalize(&FcValueListPtrU(v)->value), FcTrue))
                    goto bail2;
            }
        }
index 9e70271687176ef8af900f5cff81643fe61b46e4..b2b2c8d519eb647878be0f3193ce0a4fb7ce32af 100644 (file)
 #include <stdio.h>
 
 static double
-FcCompareNumber (char *object, FcValue value1, FcValue value2)
+FcCompareNumber (char *object, FcValue *value1, FcValue *value2)
 {
     double  v1, v2, v;
     
-    switch (value1.type) {
+    switch (value1->type) {
     case FcTypeInteger:
-       v1 = (double) value1.u.i;
+       v1 = (double) value1->u.i;
        break;
     case FcTypeDouble:
-       v1 = value1.u.d;
+       v1 = value1->u.d;
        break;
     default:
        return -1.0;
     }
-    switch (value2.type) {
+    switch (value2->type) {
     case FcTypeInteger:
-       v2 = (double) value2.u.i;
+       v2 = (double) value2->u.i;
        break;
     case FcTypeDouble:
-       v2 = value2.u.d;
+       v2 = value2->u.d;
        break;
     default:
        return -1.0;
@@ -59,38 +59,38 @@ FcCompareNumber (char *object, FcValue value1, FcValue value2)
 }
 
 static double
-FcCompareString (char *object, FcValue value1, FcValue value2)
+FcCompareString (char *object, FcValue *v1, FcValue *v2)
 {
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
     if (value2.type != FcTypeString || value1.type != FcTypeString)
        return -1.0;
-    return (double) FcStrCmpIgnoreCase 
-       (FcObjectPtrU(value1.u.si), FcObjectPtrU(value2.u.si)) != 0;
+    return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0;
 }
 
 static double
-FcCompareFamily (char *object, FcValue value1, FcValue value2)
+FcCompareFamily (char *object, FcValue *v1, FcValue *v2)
 {
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
     if (value2.type != FcTypeString || value1.type != FcTypeString)
        return -1.0;
-    return (double) FcStrCmpIgnoreBlanksAndCase 
-       (FcObjectPtrU(value1.u.si), FcObjectPtrU(value2.u.si)) != 0;
+    return (double) FcStrCmpIgnoreBlanksAndCase (value1.u.s, value2.u.s) != 0;
 }
 
 static double
-FcCompareLang (char *object, FcValue value1, FcValue value2)
+FcCompareLang (char *object, FcValue *v1, FcValue *v2)
 {
     FcLangResult    result;
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
     
     switch (value1.type) {
     case FcTypeLangSet:
        switch (value2.type) {
        case FcTypeLangSet:
-           result = FcLangSetCompare (FcLangSetPtrU(value1.u.li), 
-                                      FcLangSetPtrU(value2.u.li));
+           result = FcLangSetCompare (value1.u.l, value2.u.l);
            break;
        case FcTypeString:
-           result = FcLangSetHasLang (FcLangSetPtrU(value1.u.li)
-                                      FcObjectPtrU(value2.u.si));
+           result = FcLangSetHasLang (value1.u.l
+                                      value2.u.s);
            break;
        default:
            return -1.0;
@@ -99,12 +99,11 @@ FcCompareLang (char *object, FcValue value1, FcValue value2)
     case FcTypeString:
        switch (value2.type) {
        case FcTypeLangSet:
-           result = FcLangSetHasLang (FcLangSetPtrU(value2.u.li), 
-                                      FcObjectPtrU(value1.u.si));
+           result = FcLangSetHasLang (value2.u.l, value1.u.s);
            break;
        case FcTypeString:
-           result = FcLangCompare (FcObjectPtrU(value1.u.si)
-                                   FcObjectPtrU(value2.u.si));
+           result = FcLangCompare (value1.u.s
+                                   value2.u.s);
            break;
        default:
            return -1.0;
@@ -125,43 +124,44 @@ FcCompareLang (char *object, FcValue value1, FcValue value2)
 }
 
 static double
-FcCompareBool (char *object, FcValue value1, FcValue value2)
+FcCompareBool (char *object, FcValue *value1, FcValue *value2)
 {
-    if (value2.type != FcTypeBool || value1.type != FcTypeBool)
+    if (value2->type != FcTypeBool || value1->type != FcTypeBool)
        return -1.0;
-    return (double) value2.u.b != value1.u.b;
+    return (double) value2->u.b != value1->u.b;
 }
 
 static double
-FcCompareCharSet (char *object, FcValue value1, FcValue value2)
+FcCompareCharSet (char *object, FcValue *v1, FcValue *v2)
 {
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
+    
     if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet)
        return -1.0;
-    return (double) FcCharSetSubtractCount (FcCharSetPtrU(value1.u.ci), 
-                                           FcCharSetPtrU(value2.u.ci));
+    return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c);
 }
 
 static double
-FcCompareSize (char *object, FcValue value1, FcValue value2)
+FcCompareSize (char *object, FcValue *value1, FcValue *value2)
 {
     double  v1, v2, v;
 
-    switch (value1.type) {
+    switch (value1->type) {
     case FcTypeInteger:
-       v1 = value1.u.i;
+       v1 = value1->u.i;
        break;
     case FcTypeDouble:
-       v1 = value1.u.d;
+       v1 = value1->u.d;
        break;
     default:
        return -1;
     }
-    switch (value2.type) {
+    switch (value2->type) {
     case FcTypeInteger:
-       v2 = value2.u.i;
+       v2 = value2->u.i;
        break;
     case FcTypeDouble:
-       v2 = value2.u.d;
+       v2 = value2->u.d;
        break;
     default:
        return -1;
@@ -176,7 +176,7 @@ FcCompareSize (char *object, FcValue value1, FcValue value2)
 
 typedef struct _FcMatcher {
     char           *object;
-    double         (*compare) (char *object, FcValue value1, FcValue value2);
+    double         (*compare) (char *object, FcValue *value1, FcValue *value2);
     int                    strong, weak;
 } FcMatcher;
 
@@ -315,7 +315,7 @@ FcCompareValueList (const char  *object,
                            (FcChar8 *) object) != 0)
     {
        if (bestValue)
-           *bestValue = FcValueListPtrU(v2orig)->value;
+           *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2orig)->value);
        return FcTrue;
     }
 #if 0
@@ -343,8 +343,8 @@ FcCompareValueList (const char  *object,
             v2 = FcValueListPtrU(v2)->next)
        {
            v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
-                                           FcValueListPtrU(v1)->value,
-                                           FcValueListPtrU(v2)->value);
+                                           &FcValueListPtrU(v1)->value,
+                                           &FcValueListPtrU(v2)->value);
            if (v < 0)
            {
                *result = FcResultTypeMismatch;
@@ -356,7 +356,7 @@ FcCompareValueList (const char  *object,
            if (v < best)
            {
                if (bestValue)
-                   *bestValue = FcValueListPtrU(v2)->value;
+                   *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2)->value);
                best = v;
            }
            if (FcValueListPtrU(v1)->binding == FcValueBindingStrong)
@@ -478,7 +478,7 @@ FcFontRenderPrepare (FcConfig           *config,
            }
        }
        else
-           v = FcValueListPtrU(fe->values)->value;
+           v = FcValueCanonicalize(&FcValueListPtrU(fe->values)->value);
        FcPatternAdd (new, FcObjectPtrU(fe->object), v, FcFalse);
     }
     for (i = 0; i < pat->num; i++)
@@ -487,7 +487,7 @@ FcFontRenderPrepare (FcConfig           *config,
        fe = FcPatternFindElt (font, FcObjectPtrU(pe->object));
        if (!fe)
            FcPatternAdd (new, FcObjectPtrU(pe->object), 
-                          FcValueListPtrU(pe->values)->value, FcTrue);
+                          FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue);
     }
     FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
     return new;
@@ -780,8 +780,8 @@ FcFontSetSort (FcConfig         *config,
                    FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
                    FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
                {
-                   double  compare = FcCompareLang (FC_LANG, patternLang, 
-                                                    nodeLang);
+                   double  compare = FcCompareLang (FC_LANG, &patternLang, 
+                                                    &nodeLang);
                    if (compare >= 0 && compare < 2)
                    {
                        if (FcDebug () & FC_DBG_MATCHV)
index 9b69bc909d6cdd632aa57886874126befe8c804c..863fe692c9056a84aa5676d1114048ca7b8ef635 100644 (file)
 #include <math.h>
 #include <stdlib.h>
 #include <ctype.h>
-#include <sys/mman.h>
 #include "fcint.h"
 
-FcMatrix    _id = { 1, 0, 0, 1 };
-const FcMatrixPtr    FcIdentityMatrix = {
-    .storage = FcStorageDynamic,
-    .u.dyn = &_id
-};
+const FcMatrix    FcIdentityMatrix = { 1, 0, 0, 1 };
 
 FcMatrix *
 FcMatrixCopy (const FcMatrix *mat) 
@@ -48,17 +43,10 @@ FcMatrixCopy (const FcMatrix *mat)
     return r;
 }
 
-void
-FcMatrixPtrDestroy (FcMatrixPtr mi)
-{
-    if (mi.storage == FcStorageDynamic)
-       FcMatrixFree (mi.u.dyn);
-}
-
 void
 FcMatrixFree (FcMatrix *mat)
 {
-    if (mat != FcMatrixPtrU(FcIdentityMatrix))
+    if (mat != &FcIdentityMatrix)
     {
        FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
        free (mat);
@@ -127,87 +115,3 @@ FcMatrixShear (FcMatrix *m, double sh, double sv)
     r.yy = 1;
     FcMatrixMultiply (m, &r, m);
 }
-
-static FcMatrix * matrices = 0;
-static int matrix_ptr = 0, matrix_count = 0;
-
-void 
-FcMatrixClearStatic (void)
-{
-    matrices = 0;
-    matrix_ptr = 0;
-    matrix_count = 0;
-}
-
-FcMatrix *
-FcMatrixPtrU (FcMatrixPtr mi)
-{
-    switch (mi.storage)
-    {
-    case FcStorageDynamic:
-       return mi.u.dyn;
-    case FcStorageStatic:
-       return &matrices[mi.u.stat];
-    default:
-       return 0;
-
-    }
-}
-
-FcMatrixPtr
-FcMatrixPtrCreateDynamic (FcMatrix *mi)
-{
-    FcMatrixPtr new;
-    new.storage = FcStorageDynamic;
-    new.u.dyn = mi;
-    return new;
-}
-
-FcBool
-FcMatrixPrepareSerialize(FcMatrix *m)
-{
-    matrix_count++;
-    return FcTrue;
-}
-
-FcMatrixPtr
-FcMatrixSerialize(FcMatrix *m)
-{
-    FcMatrixPtr new;
-
-    if (matrix_count == matrix_ptr)
-       return FcMatrixPtrCreateDynamic(0);
-
-    new.storage = FcStorageStatic;
-    new.u.stat = matrix_ptr++;
-    return new;
-}
-
-FcBool
-FcMatrixRead (int fd, FcCache metadata)
-{
-    matrices = mmap(NULL, 
-                   metadata.matrices_length * sizeof (FcMatrix),
-                   PROT_READ,
-                   MAP_SHARED, fd, metadata.matrices_offset);
-    if (matrices == MAP_FAILED)
-       return FcFalse;
-
-    matrix_count = matrix_ptr = metadata.matrices_length;
-    return FcTrue;
-}
-
-FcBool
-FcMatrixWrite (int fd, FcCache *metadata)
-{
-    metadata->matrices_length = matrix_ptr;
-    metadata->matrices_offset = FcCacheNextOffset(fd);
-
-    if (matrix_ptr > 0)
-    {
-       lseek(fd, metadata->matrices_offset, SEEK_SET);
-       return write(fd, matrices, 
-                     metadata->matrices_length * sizeof(FcMatrix)) != -1;
-    }
-    return FcTrue;
-}
index a2524ad82d22116506c9685e6ec8786cffc7453d..1cdba565305ec3c77ef1b4d121ae57f15fe62925 100644 (file)
@@ -145,6 +145,74 @@ FcNameGetObjectType (const char *object)
     return 0;
 }
 
+static int objectptr_count = 1;
+static int objectptr_alloc = 0;
+static int * objectptr_indices = 0;
+
+void
+FcObjectNewBank(void)
+{
+    objectptr_count = 1;
+    objectptr_alloc = 0;
+    objectptr_indices = 0;
+}
+
+// XXX todo: introduce a hashtable for faster lookup
+FcObjectPtr
+FcObjectToPtr (const char * object)
+{
+    int                            i;
+    const FcObjectTypeList  *l;
+    const FcObjectType     *t;
+    
+    for (l = _FcObjectTypes; l; l = l->next)
+    {
+       for (i = 0; i < l->ntypes; i++)
+       {
+           t = &l->types[i];
+           if (!strcmp (object, t->object))
+               return i;
+       }
+    }
+    abort();
+    return 0;
+}
+
+const char *
+FcObjectPtrU (FcObjectPtr si)
+{
+    return _FcObjectTypes->types[si].object;
+}
+
+int
+FcObjectNeededBytes (FcObjectPtr si)
+{
+    return 0;
+}
+
+void *
+FcObjectDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+    return block_ptr;
+}
+
+FcObjectPtr
+FcObjectSerialize (FcObjectPtr si)
+{
+    return si;
+}
+
+void
+FcObjectUnserialize (FcCache metadata, FcConfig * config, void *block_ptr)
+{
+}
+
+int
+FcObjectPtrCompare (const FcObjectPtr a, const FcObjectPtr b)
+{
+    return a - b;
+}
+
 static const FcConstant _FcBaseConstants[] = {
     { (FcChar8 *) "thin",          "weight",   FC_WEIGHT_THIN, },
     { (FcChar8 *) "extralight",            "weight",   FC_WEIGHT_EXTRALIGHT, },
@@ -321,7 +389,7 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
            v.u.i = atoi ((char *) string);
        break;
     case FcTypeString:
-       v.u.si = FcObjectStaticName(string);
+       v.u.s = FcObjectStaticName(string);
        break;
     case FcTypeBool:
        if (!FcNameBool (string, &v.u.b))
@@ -331,14 +399,14 @@ FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
        v.u.d = strtod ((char *) string, 0);
        break;
     case FcTypeMatrix:
-       v.u.mi = FcMatrixPtrCreateDynamic(m);
+       v.u.m = m;
        sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
        break;
     case FcTypeCharSet:
-       v.u.ci = FcCharSetPtrCreateDynamic(FcNameParseCharSet (string));
+       v.u.c = FcNameParseCharSet (string);
        break;
     case FcTypeLangSet:
-       v.u.li = FcLangSetPtrCreateDynamic(FcNameParseLangSet (string));
+       v.u.l = FcNameParseLangSet (string);
        break;
     default:
        break;
@@ -436,10 +504,10 @@ FcNameParse (const FcChar8 *name)
                        {
                            switch (v.type) {
                            case FcTypeCharSet:
-                               FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci));
+                               FcCharSetDestroy ((FcCharSet *) v.u.c);
                                break;
                            case FcTypeLangSet:
-                               FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li));
+                               FcLangSetDestroy ((FcLangSet *) v.u.l);
                                break;
                            default:
                                break;
@@ -448,10 +516,10 @@ FcNameParse (const FcChar8 *name)
                        }
                        switch (v.type) {
                        case FcTypeCharSet:
-                           FcCharSetDestroy ((FcCharSet *) FcCharSetPtrU(v.u.ci));
+                           FcCharSetDestroy ((FcCharSet *) v.u.c);
                            break;
                        case FcTypeLangSet:
-                           FcLangSetDestroy ((FcLangSet *) FcLangSetPtrU(v.u.li));
+                           FcLangSetDestroy ((FcLangSet *) v.u.l);
                            break;
                        default:
                            break;
@@ -503,10 +571,12 @@ FcNameUnparseString (FcStrBuf         *buf,
 
 static FcBool
 FcNameUnparseValue (FcStrBuf   *buf,
-                   FcValue     v,
+                   int         bank,
+                   FcValue     *v0,
                    FcChar8     *escape)
 {
     FcChar8    temp[1024];
+    FcValue v = FcValueCanonicalize(v0);
     
     switch (v.type) {
     case FcTypeVoid:
@@ -518,20 +588,17 @@ FcNameUnparseValue (FcStrBuf      *buf,
        sprintf ((char *) temp, "%g", v.u.d);
        return FcNameUnparseString (buf, temp, 0);
     case FcTypeString:
-       return FcNameUnparseString (buf, FcObjectPtrU(v.u.si), escape);
+       return FcNameUnparseString (buf, v.u.s, escape);
     case FcTypeBool:
        return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
     case FcTypeMatrix:
-    {
-       FcMatrix * m = FcMatrixPtrU(v.u.mi);
        sprintf ((char *) temp, "%g %g %g %g", 
-                m->xx, m->xy, m->yx, m->yy);
+                v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
        return FcNameUnparseString (buf, temp, 0);
-    }
     case FcTypeCharSet:
-       return FcNameUnparseCharSet (buf, FcCharSetPtrU(v.u.ci));
+       return FcNameUnparseCharSet (buf, v.u.c);
     case FcTypeLangSet:
-       return FcNameUnparseLangSet (buf, FcLangSetPtrU(v.u.li));
+       return FcNameUnparseLangSet (buf, v.u.l);
     case FcTypeFTFace:
        return FcTrue;
     }
@@ -545,7 +612,7 @@ FcNameUnparseValueList (FcStrBuf    *buf,
 {
     while (FcValueListPtrU(v))
     {
-       if (!FcNameUnparseValue (buf, FcValueListPtrU(v)->value, escape))
+       if (!FcNameUnparseValue (buf, v.bank, &FcValueListPtrU(v)->value, escape))
            return FcFalse;
        if (FcValueListPtrU(v = FcValueListPtrU(v)->next))
            if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
index 956ed669c0734d070042d2f6981ac310b91770d5..d42401d0dd9c7a6c6b9d311a1081d2725dbf6da0 100644 (file)
 #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 FcPattern ** fcpatterns = 0;
+static int fcpattern_bank_count = 0, fcpattern_ptr, fcpattern_count;
+static FcPatternElt ** fcpatternelts = 0;
 static int fcpatternelt_ptr, fcpatternelt_count;
-static FcValueList * fcvaluelists = NULL;
-static int fcvaluelist_ptr, fcvaluelist_count;
-
-static FcBool
-FcPatternEltIsDynamic (FcPatternEltPtr pei);
+static FcValueList ** fcvaluelists = 0;
+static int fcvaluelist_bank_count = 0, fcvaluelist_ptr, fcvaluelist_count;
 
 static FcPatternEltPtr
 FcPatternEltPtrCreateDynamic (FcPatternElt * e);
@@ -53,6 +49,7 @@ FcPatternCreate (void)
     p->num = 0;
     p->size = 0;
     p->elts = FcPatternEltPtrCreateDynamic(0);
+    p->bank = FC_BANK_DYNAMIC;
     p->ref = 1;
     return p;
 }
@@ -62,46 +59,71 @@ FcValueDestroy (FcValue v)
 {
     switch (v.type) {
     case FcTypeString:
-       FcObjectPtrDestroy (v.u.si);
+       FcStrFree ((FcChar8 *) v.u.s);
        break;
     case FcTypeMatrix:
-       FcMatrixPtrDestroy (v.u.mi);
+       FcMatrixFree ((FcMatrix *) v.u.m);
        break;
     case FcTypeCharSet:
-       FcCharSetPtrDestroy (v.u.ci);
+       FcCharSetDestroy ((FcCharSet *) v.u.c);
        break;
     case FcTypeLangSet:
-       FcLangSetPtrDestroy (v.u.li);
+       FcLangSetDestroy ((FcLangSet *) v.u.l);
        break;
     default:
        break;
     }
 }
 
+FcValue
+FcValueCanonicalize (const FcValue *v)
+{
+    if (v->type & FC_STORAGE_STATIC)
+    {
+       FcValue new = *v;
+
+       switch (v->type & ~FC_STORAGE_STATIC)
+       {
+       case FcTypeString:
+           new.u.s = fc_value_string(v);
+           new.type = FcTypeString;
+           break;
+       case FcTypeCharSet:
+           new.u.c = fc_value_charset(v);
+           new.type = FcTypeCharSet;
+           break;
+       case FcTypeLangSet:
+           new.u.l = fc_value_langset(v);
+           new.type = FcTypeLangSet;
+           break;
+       }
+       return new;
+    }
+    return *v;
+}
+
 FcValue
 FcValueSave (FcValue v)
 {
     switch (v.type) {
     case FcTypeString:
-       v.u.si = FcObjectStaticName(FcObjectPtrU(v.u.si));
-       if (!FcObjectPtrU(v.u.si))
+       v.u.s = FcStrCopy (v.u.s);
+       if (!v.u.s)
            v.type = FcTypeVoid;
        break;
     case FcTypeMatrix:
-       v.u.mi = FcMatrixPtrCreateDynamic
-           (FcMatrixCopy (FcMatrixPtrU(v.u.mi)));
-       if (!FcMatrixPtrU(v.u.mi))
+       v.u.m = FcMatrixCopy (v.u.m);
+       if (!v.u.m)
            v.type = FcTypeVoid;
        break;
     case FcTypeCharSet:
-       v.u.ci = FcCharSetCopyPtr (v.u.ci);
-       if (!FcCharSetPtrU(v.u.ci))
+       v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
+       if (!v.u.c)
            v.type = FcTypeVoid;
        break;
     case FcTypeLangSet:
-       v.u.li = FcLangSetPtrCreateDynamic
-           (FcLangSetCopy (FcLangSetPtrU(v.u.li)));
-       if (!FcLangSetPtrU(v.u.li))
+       v.u.l = FcLangSetCopy (v.u.l);
+       if (!v.u.l)
            v.type = FcTypeVoid;
        break;
     default:
@@ -118,26 +140,25 @@ FcValueListDestroy (FcValueListPtr l)
     {
        switch (FcValueListPtrU(l)->value.type) {
        case FcTypeString:
-           FcObjectPtrDestroy (FcValueListPtrU(l)->value.u.si);
+           FcStrFree ((FcChar8 *)FcValueListPtrU(l)->value.u.s);
            break;
        case FcTypeMatrix:
-           FcMatrixPtrDestroy (FcValueListPtrU(l)->value.u.mi);
+           FcMatrixFree ((FcMatrix *)FcValueListPtrU(l)->value.u.m);
            break;
        case FcTypeCharSet:
            FcCharSetDestroy 
-               (FcCharSetPtrU (FcValueListPtrU(l)->value.u.ci));
+               ((FcCharSet *) (FcValueListPtrU(l)->value.u.c));
            break;
        case FcTypeLangSet:
            FcLangSetDestroy 
-               (FcLangSetPtrU (FcValueListPtrU(l)->value.u.li));
+               ((FcLangSet *) (FcValueListPtrU(l)->value.u.l));
            break;
        default:
            break;
        }
        next = FcValueListPtrU(l)->next;
-
        FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
-       if (l.storage == FcStorageDynamic)
+       if (l.bank == FC_BANK_DYNAMIC)
            free(l.u.dyn);
     }
 }
@@ -168,21 +189,17 @@ FcValueEqual (FcValue va, FcValue vb)
     case FcTypeDouble:
        return va.u.d == vb.u.d;
     case FcTypeString:
-       return FcStrCmpIgnoreCase (FcObjectPtrU(va.u.si), 
-                                  FcObjectPtrU(vb.u.si)) == 0;
+       return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
     case FcTypeBool:
        return va.u.b == vb.u.b;
     case FcTypeMatrix:
-       return FcMatrixEqual (FcMatrixPtrU(va.u.mi), 
-                             FcMatrixPtrU(vb.u.mi));
+       return FcMatrixEqual (va.u.m, vb.u.m);
     case FcTypeCharSet:
-       return FcCharSetEqual (FcCharSetPtrU(va.u.ci), 
-                              FcCharSetPtrU(vb.u.ci));
+       return FcCharSetEqual (va.u.c, vb.u.c);
     case FcTypeFTFace:
        return va.u.f == vb.u.f;
     case FcTypeLangSet:
-       return FcLangSetEqual (FcLangSetPtrU(va.u.li), 
-                              FcLangSetPtrU(vb.u.li));
+       return FcLangSetEqual (va.u.l, vb.u.l);
     }
     return FcFalse;
 }
@@ -210,8 +227,9 @@ FcStringHash (const FcChar8 *s)
 }
 
 static FcChar32
-FcValueHash (FcValue v)
+FcValueHash (const FcValue *v0)
 {
+    FcValue v = FcValueCanonicalize(v0);
     switch (v.type) {
     case FcTypeVoid:
        return 0;
@@ -220,24 +238,21 @@ FcValueHash (FcValue v)
     case FcTypeDouble:
        return FcDoubleHash (v.u.d);
     case FcTypeString:
-       return FcStringHash (FcObjectPtrU(v.u.si));
+       return FcStringHash (v.u.s);
     case FcTypeBool:
        return (FcChar32) v.u.b;
     case FcTypeMatrix:
-    {
-       FcMatrix * m = FcMatrixPtrU(v.u.mi);
-       return (FcDoubleHash (m->xx) ^ 
-               FcDoubleHash (m->xy) ^ 
-               FcDoubleHash (m->yx) ^ 
-               FcDoubleHash (m->yy));
-    }
+       return (FcDoubleHash (v.u.m->xx) ^ 
+               FcDoubleHash (v.u.m->xy) ^ 
+               FcDoubleHash (v.u.m->yx) ^ 
+               FcDoubleHash (v.u.m->yy));
     case FcTypeCharSet:
-       return (FcChar32) (FcCharSetPtrU(v.u.ci))->num;
+       return (FcChar32) v.u.c->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 (FcLangSetPtrU(v.u.li));
+       return FcLangSetHash (v.u.l);
     }
     return FcFalse;
 }
@@ -269,7 +284,7 @@ FcValueListHash (FcValueListPtr l)
     while (FcValueListPtrU(l))
     {
        hash = ((hash << 1) | (hash >> 31)) ^ 
-           FcValueHash (FcValueListPtrU(l)->value);
+           FcValueHash (&FcValueListPtrU(l)->value);
        l = FcValueListPtrU(l)->next;
     }
     return hash;
@@ -287,7 +302,7 @@ FcPatternDestroy (FcPattern *p)
        FcValueListDestroy ((FcPatternEltU(p->elts)+i)->values);
 
     p->num = 0;
-    if (FcPatternEltU(p->elts) && FcPatternEltIsDynamic(p->elts))
+    if (FcPatternEltU(p->elts) && p->elts.bank == FC_BANK_DYNAMIC)
     {
        FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
        free (FcPatternEltU(p->elts));
@@ -373,15 +388,16 @@ FcValueListEntCreate (FcValueListPtr h)
     for (l = h; FcValueListPtrU(l); 
         l = FcValueListPtrU(l)->next, new++)
     {
-       if (FcValueListPtrU(l)->value.type == FcTypeString)
+       if ((FcValueListPtrU(l)->value.type & ~FC_STORAGE_STATIC) == FcTypeString)
        {
            new->value.type = FcTypeString;
-           new->value.u.si = FcObjectStaticName
-               (FcObjectPtrU(FcValueListPtrU(l)->value.u.si));
+           new->value.u.s = FcObjectStaticName
+               (fc_value_string(&FcValueListPtrU(l)->value));
        }
        else
        {
-           new->value = FcValueSave (FcValueListPtrU(l)->value);
+           new->value = FcValueSave (FcValueCanonicalize
+                                     (&FcValueListPtrU(l)->value));
        }
        new->binding = FcValueListPtrU(l)->binding;
        if (FcValueListPtrU(FcValueListPtrU(l)->next))
@@ -656,7 +672,7 @@ FcPatternPosition (const FcPattern *p, const char *object)
     int            low, high, mid, c;
     FcObjectPtr obj;
 
-    obj = FcObjectStaticName(object);
+    obj = FcObjectToPtr(object);
     low = 0;
     high = p->num - 1;
     c = 1;
@@ -738,7 +754,7 @@ FcPatternInsertElt (FcPattern *p, const char *object)
        /* bump count */
        p->num++;
        
-       (FcPatternEltU(p->elts)+i)->object = FcObjectStaticName (object);
+       (FcPatternEltU(p->elts)+i)->object = FcObjectToPtr (object);
        (FcPatternEltU(p->elts)+i)->values = FcValueListPtrCreateDynamic(0);
     }
     
@@ -776,7 +792,7 @@ FcPatternHash (const FcPattern *p)
     for (i = 0; i < p->num; i++)
     {
        h = (((h << 1) | (h >> 31)) ^ 
-            FcStringHash ((const FcChar8 *) FcObjectPtrU(((FcPatternEltU(p->elts)+i)->object))) ^
+            FcStringHash ((const FcChar8 *) ((FcPatternEltU(p->elts)+i)->object)) ^
             FcValueListHash ((FcPatternEltU(p->elts)+i)->values));
     }
     return h;
@@ -790,8 +806,8 @@ FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObject
     
     for (i = 0; i < os->nobject; i++)
     {
-       ea = FcPatternFindElt (pai, FcObjectPtrU(os->objects[i]));
-       eb = FcPatternFindElt (pbi, FcObjectPtrU(os->objects[i]));
+       ea = FcPatternFindElt (pai, os->objects[i]);
+       eb = FcPatternFindElt (pbi, os->objects[i]);
        if (ea)
        {
            if (!eb)
@@ -859,16 +875,16 @@ FcPatternAddWithBinding  (FcPattern           *p,
 bail2:    
     switch (value.type) {
     case FcTypeString:
-       FcStrFree ((FcChar8 *) FcObjectPtrU(value.u.si));
+       FcStrFree ((FcChar8 *) value.u.s);
        break;
     case FcTypeMatrix:
-       FcMatrixFree (FcMatrixPtrU(value.u.mi));
+       FcMatrixFree ((FcMatrix *) value.u.m);
        break;
     case FcTypeCharSet:
-       FcCharSetDestroy (FcCharSetPtrU(value.u.ci));
+       FcCharSetDestroy ((FcCharSet *) value.u.c);
        break;
     case FcTypeLangSet:
-       FcLangSetDestroy (FcLangSetPtrU(value.u.li));
+       FcLangSetDestroy ((FcLangSet *) value.u.l);
        break;
     default:
        break;
@@ -968,7 +984,7 @@ FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
     FcValue    v;
 
     v.type = FcTypeString;
-    v.u.si = FcObjectStaticName(s);
+    v.u.s = FcObjectStaticName(s);
     return FcPatternAdd (p, object, v, FcTrue);
 }
 
@@ -978,7 +994,7 @@ FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
     FcValue    v;
 
     v.type = FcTypeMatrix;
-    v.u.mi = FcMatrixPtrCreateDynamic((FcMatrix *) s);
+    v.u.m = s;
     return FcPatternAdd (p, object, v, FcTrue);
 }
 
@@ -999,7 +1015,7 @@ FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
     FcValue    v;
 
     v.type = FcTypeCharSet;
-    v.u.ci = FcCharSetPtrCreateDynamic((FcCharSet *)c);
+    v.u.c = (FcCharSet *)c;
     return FcPatternAdd (p, object, v, FcTrue);
 }
 
@@ -1019,7 +1035,7 @@ FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
     FcValue    v;
 
     v.type = FcTypeLangSet;
-    v.u.li = FcLangSetPtrCreateDynamic((FcLangSet *)ls);
+    v.u.l = (FcLangSet *)ls;
     return FcPatternAdd (p, object, v, FcTrue);
 }
 
@@ -1036,7 +1052,7 @@ FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
     {
        if (!id)
        {
-           *v = FcValueListPtrU(l)->value;
+           *v = FcValueCanonicalize(&FcValueListPtrU(l)->value);
            return FcResultMatch;
        }
        id--;
@@ -1099,7 +1115,7 @@ FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s
        return r;
     if (v.type != FcTypeString)
         return FcResultTypeMismatch;
-    *s = (FcChar8 *) FcObjectPtrU(v.u.si);
+    *s = (FcChar8 *) v.u.s;
     return FcResultMatch;
 }
 
@@ -1114,7 +1130,7 @@ FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
        return r;
     if (v.type != FcTypeMatrix)
         return FcResultTypeMismatch;
-    *m = FcMatrixPtrU(v.u.mi);
+    *m = (FcMatrix *)v.u.m;
     return FcResultMatch;
 }
 
@@ -1145,7 +1161,7 @@ FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **
        return r;
     if (v.type != FcTypeCharSet)
         return FcResultTypeMismatch;
-    *c = FcCharSetPtrU(v.u.ci);
+    *c = (FcCharSet *)v.u.c;
     return FcResultMatch;
 }
 
@@ -1175,7 +1191,7 @@ FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **
        return r;
     if (v.type != FcTypeLangSet)
         return FcResultTypeMismatch;
-    *ls = FcLangSetPtrU(v.u.li);
+    *ls = (FcLangSet *)v.u.l;
     return FcResultMatch;
 }
 
@@ -1255,7 +1271,7 @@ FcPatternAppend (FcPattern *p, FcPattern *s)
             v = FcValueListPtrU(v)->next)
        {
            if (!FcPatternAddWithBinding (p, FcObjectPtrU(e->object),
-                                         FcValueListPtrU(v)->value
+                                         FcValueCanonicalize(&FcValueListPtrU(v)->value)
                                          FcValueListPtrU(v)->binding, FcTrue))
                return FcFalse;
        }
@@ -1263,154 +1279,225 @@ FcPatternAppend (FcPattern *p, FcPattern *s)
     return FcTrue;
 }
 
-FcPatternElt *
-FcPatternEltU (FcPatternEltPtr pei)
+#define OBJECT_HASH_SIZE    31
+struct objectBucket {
+    struct objectBucket        *next;
+    FcChar32           hash;
+};
+static struct objectBucket *FcObjectBuckets[OBJECT_HASH_SIZE];
+
+const char *
+FcObjectStaticName (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 (char *) (b + 1);
+    size = sizeof (struct objectBucket) + strlen (name) + 1;
+    b = malloc (size);
+    FcMemAlloc (FC_MEM_STATICSTR, size);
+    if (!b)
+        return NULL;
+    b->next = 0;
+    b->hash = hash;
+    strcpy ((char *) (b + 1), name);
+    *p = b;
+    return (char *) (b + 1);
+}
+
+static void
+FcObjectStaticNameFini (void)
 {
-    switch (pei.storage)
+    int i, size;
+    struct objectBucket *b, *next;
+    char *name;
+
+    for (i = 0; i < OBJECT_HASH_SIZE; i++)
     {
-    case FcStorageStatic:
-        return &fcpatternelts[pei.u.stat];
-    case FcStorageDynamic:
-        return pei.u.dyn;
-    default:
-       return 0;
+       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;
     }
 }
 
+void
+FcPatternFini (void)
+{
+    FcPatternBaseThawAll ();
+    FcValueListThawAll ();
+    FcObjectStaticNameFini ();
+}
+
+FcPatternElt *
+FcPatternEltU (FcPatternEltPtr pei)
+{
+    if (pei.bank == FC_BANK_DYNAMIC)
+       return pei.u.dyn;
+
+    return &fcpatternelts[FcCacheBankToIndex(pei.bank)][pei.u.stat];
+}
+
 static FcPatternEltPtr
 FcPatternEltPtrCreateDynamic (FcPatternElt * e)
 {
     FcPatternEltPtr new;
-    new.storage = FcStorageDynamic;
+    new.bank = FC_BANK_DYNAMIC;
     new.u.dyn = e;
     return new;
 }
 
 static FcPatternEltPtr
-FcPatternEltPtrCreateStatic (int i)
+FcPatternEltPtrCreateStatic (int bank, int i)
 {
     FcPatternEltPtr new;
-    new.storage = FcStorageStatic;
+    new.bank = bank;
     new.u.stat = i;
     return new;
 }
 
-static FcBool
-FcPatternEltIsDynamic (FcPatternEltPtr pei)
-{
-    return pei.storage == FcStorageDynamic;
-}
+static void
+FcStrNewBank (void);
+static int
+FcStrNeededBytes (const char * s);
+static void *
+FcStrDistributeBytes (FcCache * metadata, void * block_ptr);
+static const char *
+FcStrSerialize (int bank, const char * s);
+static void *
+FcStrUnserialize (FcCache metadata, void *block_ptr);
+
+static void
+FcValueListNewBank (void);
+static int
+FcValueListNeededBytes (FcValueList * vl);
+static void *
+FcValueListDistributeBytes (FcCache * metadata, void *block_ptr);
+static FcValueListPtr
+FcValueListSerialize(int bank, FcValueList *pi);
+static void *
+FcValueListUnserialize (FcCache metadata, void *block_ptr);
 
 
 void
-FcPatternClearStatic (void)
+FcPatternNewBank (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;
+    FcStrNewBank();
+    FcValueListNewBank();
 }
 
-static FcBool
-FcObjectPrepareSerialize (FcObjectPtr si);
-static FcObjectPtr
-FcObjectSerialize (FcObjectPtr si);
-
-FcBool
-FcPatternPrepareSerialize (FcPattern * p)
+int
+FcPatternNeededBytes (FcPattern * p)
 {
-    int i;
+    int i, cum = 0, c;
 
     fcpattern_count++;
     fcpatternelt_count += p->num;
 
     for (i = 0; i < p->num; i++)
     {
-       FcObjectPrepareSerialize 
+       cum += FcObjectNeededBytes 
            ((FcPatternEltU(p->elts)+i)->object);
-       if (!FcValueListPrepareSerialize 
-           (FcValueListPtrU(((FcPatternEltU(p->elts)+i)->values))))
-           return FcFalse;
+       c = FcValueListNeededBytes (FcValueListPtrU
+                                   (((FcPatternEltU(p->elts)+i)->values)));
+       if (c < 0)
+           return c;
+       cum += c;
     }
 
-    return FcTrue;
+    return cum + sizeof (FcPattern) + sizeof(FcPatternElt)*p->num;
 }
 
-FcBool
-FcValueListPrepareSerialize (FcValueList *p)
+static FcBool
+FcPatternEnsureBank (int bi)
 {
-    FcValueList *vl;
+    FcPattern **pp;
+    FcPatternElt **ep;
+    int i;
 
-    for (vl = p;
-        vl; 
-        vl = FcValueListPtrU(vl->next))
+    if (!fcpatterns || fcpattern_bank_count <= bi)
     {
-       FcValue v = vl->value;
+       int new_count = bi + 4;
+       pp = realloc (fcpatterns, sizeof (FcPattern *) * new_count);
+       if (!pp)
+           return 0;
 
-       switch (v.type)
+       FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern *) * new_count);
+       fcpatterns = pp;
+
+       ep = realloc (fcpatternelts, sizeof (FcPatternElt *) * new_count);
+       if (!ep)
+           return 0;
+
+       FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt *) * new_count);
+       fcpatternelts = ep;
+
+       for (i = fcpattern_bank_count; i < new_count; i++)
        {
-       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;
+           fcpatterns[i] = 0;
+           fcpatternelts[i] = 0;
        }
-       fcvaluelist_count++;
+
+       fcpattern_bank_count = new_count;
     }
-    
+
+    FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * fcpattern_count);
     return FcTrue;
 }
 
+void *
+FcPatternDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+    int bi = FcCacheBankToIndex(metadata->bank);
+
+    if (!FcPatternEnsureBank(bi))
+       return 0;
+
+    fcpattern_ptr = 0;
+    fcpatterns[bi] = (FcPattern *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (FcPattern) * fcpattern_count));
+    
+    FcMemAlloc (FC_MEM_PATELT, sizeof (FcPatternElt) * fcpatternelt_count);
+    fcpatternelt_ptr = 0;
+    fcpatternelts[bi] = (FcPatternElt *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (FcPatternElt) * fcpatternelt_count));
+
+    metadata->pattern_count = fcpattern_count;
+    metadata->patternelt_count = fcpatternelt_count;
+
+    block_ptr = FcStrDistributeBytes (metadata, block_ptr);
+    block_ptr = FcValueListDistributeBytes (metadata, block_ptr);
+    return block_ptr;
+}
+
 FcPattern *
-FcPatternSerialize (FcPattern *old)
+FcPatternSerialize (int bank, FcPattern *old)
 {
     FcPattern *p;
     FcPatternElt *e, *nep;
     FcValueList * nv;
     FcValueListPtr v, nv_head, nvp;
-    int i, elts;
+    int i, elts, bi = FcCacheBankToIndex(bank);
 
-    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 = &fcpatterns[fcpattern_ptr++];
+    p = &fcpatterns[bi][fcpattern_ptr++];
+    p->bank = bank;
     elts = fcpatternelt_ptr;
-    nep = &fcpatternelts[elts];
+    nep = &fcpatternelts[bi][elts];
     if (!nep)
        return FcFalse;
 
@@ -1419,9 +1506,9 @@ FcPatternSerialize (FcPattern *old)
     for (e = FcPatternEltU(old->elts), i=0; i < old->num; i++, e++) 
     {
         v = e->values;
-        nvp = nv_head = FcValueListSerialize(FcValueListPtrU(v));
+        nvp = nv_head = FcValueListSerialize(bank, FcValueListPtrU(v));
         if (!FcValueListPtrU(nv_head))
-            goto bail2;
+            return 0;
        nv = FcValueListPtrU(nvp);
        
         for (;
@@ -1433,7 +1520,7 @@ FcPatternSerialize (FcPattern *old)
            if (FcValueListPtrU(FcValueListPtrU(v)->next))
            {
                 nvp = FcValueListSerialize
-                   (FcValueListPtrU(FcValueListPtrU(v)->next));
+                   (bank, FcValueListPtrU(FcValueListPtrU(v)->next));
                 nv->next = nvp;
            }
         }
@@ -1443,147 +1530,173 @@ FcPatternSerialize (FcPattern *old)
     }
 
     p->elts = old->elts;
-    p->elts = FcPatternEltPtrCreateStatic(elts);
+    p->elts = FcPatternEltPtrCreateStatic(bank, elts);
     p->size = old->num;
     p->num = old->num;
     p->ref = FC_REF_CONSTANT;
     return p;
-    
- bail2:
-    free (fcpatternelts);
- bail1:
-    free (fcpatterns);
- bail:
-    return 0;
 }
 
-FcBool
-FcPatternRead (int fd, FcCache metadata)
+FcPattern *
+FcPatternUnserialize (FcCache metadata, void *block_ptr)
 {
-    fcpatterns = mmap(NULL, 
-                     metadata.pattern_length * sizeof (FcPattern),
-                     PROT_READ,
-                     MAP_SHARED, fd, metadata.pattern_offset);
-    if (fcpatterns == MAP_FAILED)
+    int bi = FcCacheBankToIndex(metadata.bank);
+    if (!FcPatternEnsureBank(bi))
        return FcFalse;
-    fcpattern_count = fcpattern_ptr = metadata.pattern_length;
 
-    return FcTrue;
+    FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern) * metadata.pattern_count);
+    fcpatterns[bi] = (FcPattern *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (FcPattern) * metadata.pattern_count));
+    
+    FcMemAlloc (FC_MEM_PATELT, 
+               sizeof (FcPatternElt) * metadata.patternelt_count);
+    fcpatternelts[bi] = (FcPatternElt *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (FcPatternElt) * metadata.patternelt_count));
+       
+    block_ptr = FcStrUnserialize (metadata, block_ptr);
+    block_ptr = FcValueListUnserialize (metadata, block_ptr);
+
+    return fcpatterns[bi];
 }
 
-FcBool
-FcPatternWrite (int fd, FcCache *metadata)
+static void
+FcValueListNewBank (void)
 {
-    int c = fcpattern_ptr;
-    off_t w = FcCacheNextOffset(fd);
+    fcvaluelist_count = 0;
+
+    FcCharSetNewBank();
+    FcLangSetNewBank();
+}
 
-    metadata->pattern_offset = w;
-    metadata->pattern_length = c;
+static int
+FcValueListNeededBytes (FcValueList *p)
+{
+    FcValueList *vl;
+    int cum = 0;
 
-    if (c > 0)
+    for (vl = p;
+        vl; 
+        vl = FcValueListPtrU(vl->next))
     {
-       lseek(fd, w, SEEK_SET);
-       return write(fd, fcpatterns, c*sizeof(FcPattern)) != -1;
+       FcValue v = FcValueCanonicalize(&vl->value); // unserialize just in case
+
+       switch (v.type)
+       {
+       case FcTypeCharSet:
+           cum += FcCharSetNeededBytes(v.u.c);
+           break;
+       case FcTypeLangSet:
+           cum += FcLangSetNeededBytes(v.u.l);
+           break;
+       case FcTypeString:
+           cum += FcStrNeededBytes(v.u.s);
+       default:
+           break;
+       }
+       fcvaluelist_count++;
+       cum += sizeof (FcValueList);
     }
-    return FcTrue;
+    
+    return cum;
 }
 
-FcBool
-FcPatternEltRead (int fd, FcCache metadata)
+static FcBool
+FcValueListEnsureBank (int bi)
 {
-    fcpatternelts = mmap(NULL, 
-                        metadata.patternelt_length * sizeof (FcPatternElt),
-                        PROT_READ,
-                        MAP_SHARED, fd, metadata.patternelt_offset);
-    if (fcpatternelts == MAP_FAILED)
-       return FcFalse;
-    fcpatternelt_count = fcpatternelt_ptr = metadata.patternelt_length;
+    FcValueList **pvl;
+
+    if (!fcvaluelists || fcvaluelist_bank_count <= bi)
+    {
+       int new_count = bi + 2, i;
+
+       pvl = realloc (fcvaluelists, sizeof (FcValueList *) * new_count);
+       if (!pvl)
+           return FcFalse;
 
+       FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList *) * new_count);
+
+       fcvaluelists = pvl;
+       for (i = fcvaluelist_bank_count; i < new_count; i++)
+           fcvaluelists[i] = 0;
+
+       fcvaluelist_bank_count = new_count;
+    }
     return FcTrue;
 }
 
-FcBool
-FcPatternEltWrite (int fd, FcCache *metadata)
+static void *
+FcValueListDistributeBytes (FcCache * metadata, void *block_ptr)
 {
-    int c = fcpatternelt_ptr;
-    off_t w = FcCacheNextOffset(fd);
+    int bi = FcCacheBankToIndex(metadata->bank);
 
-    metadata->patternelt_offset = w;
-    metadata->patternelt_length = c;
+    if (!FcValueListEnsureBank(bi))
+       return 0;
 
-    if (c > 0)
-    {
-       lseek(fd, w, SEEK_SET);
-       return write(fd, fcpatternelts, c*sizeof(FcPatternElt)) != -1;
-    }
-    return FcTrue;
+    FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList) * fcvaluelist_count);
+    fcvaluelist_ptr = 0;
+    fcvaluelists[bi] = (FcValueList *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (FcValueList) * fcvaluelist_count));
+    metadata->valuelist_count = fcvaluelist_count;
+
+    block_ptr = FcCharSetDistributeBytes(metadata, block_ptr);
+    block_ptr = FcLangSetDistributeBytes(metadata, block_ptr);
+
+    return block_ptr;
 }
 
-FcValueListPtr
-FcValueListSerialize(FcValueList *pi)
+static FcValueListPtr
+FcValueListSerialize(int bank, FcValueList *pi)
 {
     FcValueListPtr new; 
     FcValue * v;
-    FcValueList * vl;
+    int bi = FcCacheBankToIndex(bank);
 
-    if (!fcvaluelists)
+    if (!pi)
     {
-       vl = malloc (sizeof (FcValueList) * fcvaluelist_count);
-       if (!vl)
-           return FcValueListPtrCreateDynamic(0);
-
-       FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList) * fcvaluelist_count);
-       fcvaluelists = vl;
-       fcvaluelist_ptr = 0;
+       new.bank = FC_BANK_DYNAMIC;
+       new.u.dyn = 0;
+       return new;
     }
 
-    fcvaluelists[fcvaluelist_ptr] = *pi;
-    new.storage = FcStorageStatic;
+    fcvaluelists[bi][fcvaluelist_ptr] = *pi;
+    new.bank = bank;
     new.u.stat = fcvaluelist_ptr++;
-    v = &fcvaluelists[new.u.stat].value;
+    v = &fcvaluelists[bi][new.u.stat].value;
     switch (v->type)
     {
     case FcTypeString:
-       /* this departs from the usual convention of dereferencing
-        * foo before serialization; FcObjectSerialize does the
-        * translation itself. */
-       /* also, v->u.si is 0 iff the string is null. */
-       /* also, have to update the old pi */
-       if (v->u.si)
+       if (v->u.s)
        {
-           FcObjectPtr si = FcObjectSerialize(v->u.si);
-           if (!FcObjectPtrU(si))
+           const char * s = FcStrSerialize(bank, v->u.s);
+           if (!s)
                return FcValueListPtrCreateDynamic(pi);
-           v->u.si = si;
-           pi->value.u.si = si;
+           v->u.s_off = s - (const char *)v;
+           v->type |= FC_STORAGE_STATIC;
        }
        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))
+       if (v->u.c)
        {
-           FcCharSetPtr ci = FcCharSetSerialize(FcCharSetPtrU(v->u.ci));
-           if (!FcCharSetPtrU(ci))
+           FcCharSet * c = FcCharSetSerialize(bank, (FcCharSet *)v->u.c);
+           if (!c)
                return FcValueListPtrCreateDynamic(pi);
-           v->u.ci = ci;
+           v->u.c_off = (char *)c - (char *)v;
+           v->type |= FC_STORAGE_STATIC;
        }
        break;
     case FcTypeLangSet:
-       if (FcLangSetPtrU(v->u.li))
+       if (v->u.l)
        {
-           FcLangSetPtr li = FcLangSetSerialize(FcLangSetPtrU(v->u.li));
-           if (!FcLangSetPtrU(li))
+           FcLangSet * l = FcLangSetSerialize(bank, (FcLangSet *)v->u.l);
+           if (!l)
                return FcValueListPtrCreateDynamic(pi);
-           v->u.li = li;
+           v->u.l_off = (char *)l - (char *)v;
+           v->type |= FC_STORAGE_STATIC;
        }
        break;
     default:
@@ -1592,47 +1705,33 @@ FcValueListSerialize(FcValueList *pi)
     return new;
 }
 
-FcBool
-FcValueListRead (int fd, FcCache metadata)
+static void *
+FcValueListUnserialize (FcCache metadata, void *block_ptr)
 {
-    fcvaluelists = mmap(NULL, 
-                       metadata.valuelist_length * sizeof (FcValueList),
-                       PROT_READ,
-                       MAP_SHARED, fd, metadata.valuelist_offset);
-    if (fcvaluelists == MAP_FAILED)
-       return FcFalse;
-    fcvaluelist_count = fcvaluelist_ptr = metadata.valuelist_length;
+    int bi = FcCacheBankToIndex(metadata.bank);
 
-    return FcTrue;
-}
+    if (!FcValueListEnsureBank(bi))
+       return 0;
 
-FcBool
-FcValueListWrite (int fd, FcCache *metadata)
-{
-    metadata->valuelist_offset = FcCacheNextOffset(fd);
-    metadata->valuelist_length = fcvaluelist_ptr;
+    FcMemAlloc (FC_MEM_VALLIST, 
+               sizeof (FcValueList) * metadata.valuelist_count);
+    fcvaluelists[bi] = (FcValueList *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (FcValueList) * metadata.valuelist_count));
 
-    if (fcvaluelist_ptr > 0)
-    {
-       lseek(fd, metadata->valuelist_offset, SEEK_SET);
-       return write(fd, fcvaluelists, 
-                    fcvaluelist_ptr * sizeof(FcValueList)) != -1;
-    }
-    return FcTrue;
+    block_ptr = FcCharSetUnserialize(metadata, block_ptr);
+    block_ptr = FcLangSetUnserialize(metadata, block_ptr);
+
+    return block_ptr;
 }
 
 FcValueList * 
 FcValueListPtrU (FcValueListPtr pi)
 {
-    switch (pi.storage)
-    {
-    case FcStorageStatic:
-        return &fcvaluelists[pi.u.stat];
-    case FcStorageDynamic:
+    if (pi.bank == FC_BANK_DYNAMIC)
         return pi.u.dyn;
-    default:
-       return 0;
-    }
+
+    return &fcvaluelists[FcCacheBankToIndex(pi.bank)][pi.u.stat];
 }
 
 FcValueListPtr
@@ -1640,512 +1739,139 @@ FcValueListPtrCreateDynamic(FcValueList * p)
 {
     FcValueListPtr r; 
 
-    r.storage = FcStorageDynamic
+    r.bank = FC_BANK_DYNAMIC
     r.u.dyn = p;
     return r;
 }
 
-/* Indices allow us to convert dynamic strings into static
- * strings without having to reassign IDs.  We do reassign IDs
- * when serializing, which effectively performs mark-and-sweep 
- * garbage collection. */
+static char ** static_strs;
+static int static_str_bank_count = 0, fcstr_ptr, fcstr_count;
 
-/* objectptr_count maps FcObjectPtr to:
-     + offsets in objectcontent_static_buf (if positive)
-     - entries in objectcontent_dynamic (if negative)
-*/
-static int objectptr_count = 1;
-static int objectptr_alloc = 0;
-static int * objectptr_indices = 0;
+static struct objectBucket *FcStrBuckets[OBJECT_HASH_SIZE];
 
-/* invariant: objectcontent_static_buf must be sorted. */
-/* e.g. objectptr_static_buf = "name\0style\0weight\0" */
-static int objectcontent_static_bytes = 0;
-static char * objectcontent_static_buf;
-
-/* just a bunch of strings. */
-static int objectcontent_dynamic_count = 1;
-static int objectcontent_dynamic_alloc = 0;
-static const char ** objectcontent_dynamic = 0;
-static int * objectcontent_dynamic_refcount = 0;
-
-#define OBJECT_HASH_SIZE    31
-struct objectBucket {
-    struct objectBucket        *next;
-    FcChar32           hash;
-};
-static struct objectBucket **FcObjectBuckets = 0;
-
-FcObjectPtr
-FcObjectStaticName (const char *name)
+static void
+FcStrNewBank (void)
 {
-    FcChar32           hash = FcStringHash ((const FcChar8 *) name);
-    struct objectBucket        **p;
-    struct objectBucket        *b;
-    const char *        nn;
-    int                        size;
-    FcObjectPtr                new;
-
-    if (!FcObjectBuckets)
-    {
-        FcObjectBuckets = malloc(sizeof (struct objectBucket *)*OBJECT_HASH_SIZE);
-        memset (FcObjectBuckets, 0, sizeof (struct objectBucket *)*OBJECT_HASH_SIZE);
-    }
+    int i, size;
+    struct objectBucket *b, *next;
+    char *name;
 
-    for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+    for (i = 0; i < OBJECT_HASH_SIZE; i++)
     {
-       FcObjectPtr bp = *((FcObjectPtr *) (b + 1));
-       if (b->hash == hash && FcObjectPtrU(bp) && !strcmp (name, FcObjectPtrU(bp)))
+       for (b = FcStrBuckets[i]; b; b = next)
        {
-           if (objectptr_indices[bp] < 0)
-               objectcontent_dynamic_refcount[-objectptr_indices[bp]]++;
-           return bp;
+           next = b->next;
+           name = (char *) (b + 1);
+           size = sizeof (struct objectBucket) + strlen (name) + 1;
+           FcMemFree (FC_MEM_STATICSTR, size);
+           free (b);
        }
+       FcStrBuckets[i] = 0;
     }
 
-    /* didn't find it, so add a new dynamic string */
-    if (objectcontent_dynamic_count >= objectcontent_dynamic_alloc)
-    {
-       int s = objectcontent_dynamic_alloc + 4;
+    fcstr_count = 0;
+}
 
-       const char ** d = realloc (objectcontent_dynamic, 
-                                  s*sizeof(char *));
-       if (!d)
-           return 0;
-       FcMemFree(FC_MEM_STATICSTR, 
-                 objectcontent_dynamic_alloc * sizeof(char *));
-       FcMemAlloc(FC_MEM_STATICSTR, s*sizeof(char *));
-       objectcontent_dynamic = d;
-       objectcontent_dynamic_alloc = s;
-
-       int * rc = realloc (objectcontent_dynamic_refcount, s*sizeof(int));
-       if (!rc)
-           return 0;
-       FcMemFree(FC_MEM_STATICSTR, 
-                 objectcontent_dynamic_alloc * sizeof(int));
-       FcMemAlloc(FC_MEM_STATICSTR, s * sizeof(int));
-       objectcontent_dynamic_refcount = rc;
-    }
-    if (objectptr_count >= objectptr_alloc)
-    {
-       int s = objectptr_alloc + 4;
-       int * d = realloc (objectptr_indices, s*sizeof(int));
-       if (!d)
-           return 0;
-       FcMemFree(FC_MEM_STATICSTR, objectptr_alloc * sizeof(int));
-       FcMemAlloc(FC_MEM_STATICSTR, s);
-       objectptr_indices = d;
-       objectptr_indices[0] = 0;
-       objectptr_alloc = s;
-    }
+static int
+FcStrNeededBytes (const char * s)
+{
+    FcChar32            hash = FcStringHash ((const FcChar8 *) s);
+    struct objectBucket **p;
+    struct objectBucket *b;
+    int                 size;
 
-    size = sizeof (struct objectBucket) + sizeof (char *);
+    for (p = &FcStrBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+        if (b->hash == hash && !strcmp (s, (char *) (b + 1)))
+            return 0;
+    size = sizeof (struct objectBucket) + strlen (s) + 1 + sizeof(char *);
     b = malloc (size);
-    if (!b)
-       return 0;
     FcMemAlloc (FC_MEM_STATICSTR, size);
+    if (!b)
+        return -1;
     b->next = 0;
     b->hash = hash;
-    nn = malloc(strlen(name)+1);
-    if (!nn)
-        goto bail;
-    strcpy ((char *)nn, name);
-    objectptr_indices[objectptr_count] = -objectcontent_dynamic_count;
-    objectcontent_dynamic_refcount[objectcontent_dynamic_count] = 1;
-    objectcontent_dynamic[objectcontent_dynamic_count++] = nn;
-    new = objectptr_count++;
-    *((FcObjectPtr *)(b+1)) = new;
+    strcpy ((char *) (b + 1), s);
+    *(char **)((char *) (b + 1) + strlen(s) + 1) = 0;
     *p = b;
-    return new;
-
- bail:
-    free(b);
-    return 0;
-}
-
-void
-FcObjectPtrDestroy (FcObjectPtr p)
-{
-    if (objectptr_indices[p] < 0)
-    {
-       objectcontent_dynamic_refcount[-objectptr_indices[p]]--;
-       if (objectcontent_dynamic_refcount[-objectptr_indices[p]] == 0)
-       {
-           /* this code doesn't seem to be reached terribly often. */
-           /* (note that objectcontent_dynamic overapproximates 
-            * the use count, because not every result from
-            * StaticName is stored. */
-           FcStrFree((char *)objectcontent_dynamic[-objectptr_indices[p]]);
-           objectcontent_dynamic[-objectptr_indices[p]] = 0;
-       }
-    }
-}
-
-const char *
-FcObjectPtrU (FcObjectPtr si)
-{
-    if (si == 0)
-       return 0;
-
-    if (objectptr_indices[si] > 0)
-       return &objectcontent_static_buf[objectptr_indices[si]];
-    else
-       return objectcontent_dynamic[-objectptr_indices[si]];
-}
-
-static FcBool objectptr_first_serialization = FcFalse;
-static int * object_old_id_to_new = 0;
-
-static void 
-FcObjectRebuildStaticNameHashtable (void)
-{
-    int i;
-    struct objectBucket        *b, *bn;
-
-    if (FcObjectBuckets)
-    {
-       for (i = 0; i < OBJECT_HASH_SIZE; i++)
-       {
-           b = FcObjectBuckets[i];
-           while (b)
-           {
-               bn = b->next;
-               free(b);
-               FcMemFree (FC_MEM_STATICSTR,
-                          sizeof (struct objectBucket)+sizeof (FcObjectPtr));
-               b = bn;
-           }
-       }
-       free (FcObjectBuckets);
-    }
-
-    FcObjectBuckets = malloc(sizeof (struct objectBucket *)*OBJECT_HASH_SIZE);
-    memset (FcObjectBuckets, 0, sizeof (struct objectBucket *)*OBJECT_HASH_SIZE);
 
-    for (i = 1; i < objectptr_count; i++)
-    {
-       if (FcObjectPtrU(i))
-       {
-           const char * name = FcObjectPtrU(i);
-           FcChar32     hash = FcStringHash ((const FcChar8 *) name);
-           struct objectBucket **p;
-           int size;
-
-           for (p = &FcObjectBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); 
-                p = &(b->next))
-               ;
-           size = sizeof (struct objectBucket) + sizeof (FcObjectPtr);
-           b = malloc (size);
-           if (!b)
-               return;
-           FcMemAlloc (FC_MEM_STATICSTR, size);
-           b->next = 0;
-           b->hash = hash;
-           *((FcObjectPtr *)(b+1)) = i;
-           *p = b;
-       }
-    }
+    fcstr_count += strlen(s) + 1;
+    return strlen(s) + 1;
 }
 
-/* Hmm.  This will have a terrible effect on the memory size,
- * because the mmapped strings now get reallocated on the heap. 
- * Is it all worth it? (Of course, the Serialization codepath is
- * not problematic, because the program quits just afterwards.) */
 static FcBool
-FcObjectPtrConvertToStatic(FcBool renumber)
+FcStrEnsureBank (int bi)
 {
-    int active_count, i, j, longest_string = 0, 
-       new_static_bytes = 1;
-    char * fixed_length_buf, * new_static_buf, * p;
-    int * new_indices;
-
-    if (renumber)
-       objectptr_first_serialization = FcFalse;
-
-    /* collect statistics */
-    for (i = 1, active_count = 1; i < objectptr_count; i++)
-       if (!renumber || object_old_id_to_new[i] == -1)
-       {
-           int sl = strlen(FcObjectPtrU(i));
-           active_count++;
-           if (sl > longest_string)
-               longest_string = sl;
-           new_static_bytes += sl + 1;
-       } 
-
-    /* allocate storage */
-    fixed_length_buf = malloc 
-       ((longest_string+1) * active_count * sizeof(char));
-    if (!fixed_length_buf)
-       goto bail;
-    new_static_buf = malloc (new_static_bytes * sizeof(char));
-    if (!new_static_buf)
-       goto bail1;
-    new_indices = malloc (active_count * sizeof(int));
-    if (!new_indices)
-       goto bail2;
-    new_indices[0] = 0;
-    new_static_buf[0] = 0;
-    
-    FcMemAlloc (FC_MEM_STATICSTR, new_static_bytes);
-    FcMemFree (FC_MEM_STATICSTR, objectptr_count * sizeof (int));
-    FcMemAlloc (FC_MEM_STATICSTR, active_count * sizeof (int));
-    
-    /* copy strings to temporary buffers */
-    for (j = 0, i = 1; i < objectptr_count; i++)
-       if (!renumber || object_old_id_to_new[i] == -1)
-       {
-           strcpy (fixed_length_buf+(j*(longest_string+1)), FcObjectPtrU(i));
-           j++;
-       }
-    
-    /* sort the new statics */
-    qsort (fixed_length_buf, active_count-1, longest_string+1, 
-          (int (*)(const void *, const void *)) FcStrCmp);
-    
-    /* now we create the new static buffer in sorted order. */
-    p = new_static_buf+1;
-    for (i = 0; i < active_count-1; i++)
-    {
-       strcpy(p, fixed_length_buf + i * (longest_string+1));
-       p += strlen(p)+1;
-    }
+    char ** ss;
 
-    /* create translation table by iterating over sorted strings
-     * and getting their old values */
-    p = new_static_buf+1;
-    for (i = 0; i < active_count-1; i++)
+    if (!static_strs || static_str_bank_count <= bi)
     {
-       int n = FcObjectStaticName(fixed_length_buf+i*(longest_string+1));
-       if (renumber)
-       {
-           object_old_id_to_new[n] = i+1;
-           new_indices[i+1] = p-new_static_buf;
-       }
-       else
-           new_indices[n] = p-new_static_buf;
-       p += strlen(p)+1;
-    }
+       int new_count = bi + 4, i;
+       ss = realloc (static_strs, sizeof (const char *) * new_count);
+       if (!ss)
+           return FcFalse;
 
-    free (objectptr_indices);
-    objectptr_indices = new_indices;
-    objectptr_count = active_count;
-    objectptr_alloc = active_count;
+       FcMemAlloc (FC_MEM_STRING, sizeof (const char *) * (new_count-static_str_bank_count));
+       static_strs = ss;
 
-    /* free old storage */
-    for (i = 1; i < objectcontent_dynamic_count; i++)
-    {
-       if (objectcontent_dynamic[i])
-       {
-           FcMemFree (FC_MEM_STATICSTR, strlen(objectcontent_dynamic[i])+1);
-           free ((char *)objectcontent_dynamic[i]);
-       }       
+       for (i = static_str_bank_count; i < new_count; i++)
+           static_strs[i] = 0;
+       static_str_bank_count = new_count;
     }
-    free (objectcontent_dynamic);
-    free (objectcontent_dynamic_refcount);
-    FcMemFree (FC_MEM_STATICSTR, objectcontent_dynamic_count*sizeof (int));
-    objectcontent_dynamic = 0;
-    objectcontent_dynamic_refcount = 0;
-    objectcontent_dynamic_count = 1;
-    objectcontent_dynamic_alloc = 0;
-    free (objectcontent_static_buf);
-    FcMemFree (FC_MEM_STATICSTR, objectcontent_static_bytes);
-    objectcontent_static_buf = new_static_buf;
-    objectcontent_static_bytes = new_static_bytes;
-
-    /* fix up hash table */
-    FcObjectRebuildStaticNameHashtable();
-
-    free (fixed_length_buf);
     return FcTrue;
-
- bail2: 
-    free (new_static_buf);
- bail1: 
-    free (fixed_length_buf);
- bail:
-    return FcFalse;
 }
 
-#define OBJECT_PTR_CONVERSION_TRIGGER 100000
-
-int
-FcObjectPtrCompare (const FcObjectPtr a, const FcObjectPtr b)
+static void *
+FcStrDistributeBytes (FcCache * metadata, void * block_ptr)
 {
-    /* This is the dynamic count.  We could also use a static
-     * count, i.e. the number of slow strings being created.
-     * I think dyncount gives us a better estimate of inefficiency. -PL */
-    static int compare_count = OBJECT_PTR_CONVERSION_TRIGGER;
-
-    /* count on sortedness for fast objectptrs. */
-    if ((a == b) || (objectptr_indices[a] > 0 && objectptr_indices[b] > 0))
-       return objectptr_indices[a] - objectptr_indices[b];
-
-    compare_count--;
-    if (!compare_count)
-    {
-       FcObjectPtrConvertToStatic(FcFalse);
-       compare_count = OBJECT_PTR_CONVERSION_TRIGGER;
-    }
-
-    return strcmp (FcObjectPtrU(a), FcObjectPtrU(b));
-}
-
-void
-FcObjectClearStatic(void)
-{
-    objectptr_count = 1;
-    objectptr_alloc = 0;
-    objectptr_indices = 0;
-
-    objectcontent_static_bytes = 0;
-    objectcontent_static_buf = 0;
-
-    objectcontent_dynamic_count = 1;
-    objectcontent_dynamic_alloc = 0;
-    objectcontent_dynamic = 0;
-    objectcontent_dynamic_refcount = 0;
-
-    object_old_id_to_new = 0;
-}
-
-/* In the pre-serialization phase, mark the used strings with
- * -1 in the mapping array. */
-/* The first call to the serialization phase assigns actual 
- * static indices to the strings (sweep). */
-static FcBool
-FcObjectPrepareSerialize (FcObjectPtr si)
-{
-    if (object_old_id_to_new == 0)
-    {
-       object_old_id_to_new = malloc(objectptr_count * sizeof(int));
-       if (!object_old_id_to_new)
-           goto bail;
-       memset (object_old_id_to_new, 0, 
-               objectptr_count * sizeof(int));
-    }
-
-    object_old_id_to_new[si] = -1;
-    objectptr_first_serialization = FcTrue;
+    int bi = FcCacheBankToIndex(metadata->bank);
+    if (!FcStrEnsureBank(bi)) 
+       return 0;
 
-    return FcTrue;
+    FcMemAlloc (FC_MEM_STRING, sizeof (char) * fcstr_count);
+    static_strs[bi] = (char *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + (sizeof (char) * fcstr_count));
+    metadata->str_count = fcstr_count;
+    fcstr_ptr = 0;
 
- bail:
-    return FcFalse;
+    return block_ptr;
 }
 
-static FcObjectPtr
-FcObjectSerialize (FcObjectPtr si)
+static const char *
+FcStrSerialize (int bank, const char * s)
 {
-    if (objectptr_first_serialization)
-       if (!FcObjectPtrConvertToStatic(FcTrue))
-           return 0;
-
-    return object_old_id_to_new[si];
-}
+    FcChar32            hash = FcStringHash ((const FcChar8 *) s);
+    struct objectBucket **p;
+    struct objectBucket *b;
+    int bi = FcCacheBankToIndex(bank);
 
-FcBool
-FcObjectRead (int fd, FcCache metadata)
-{
-    /* do we have to merge strings? 
-     * it's possible to merge dynamic strings, as long as we only store
-     * static strings to disk and as long as all static strings have lower
-     * ids than any dynamic strings. */
-
-    objectcontent_dynamic_count = 1;
-    objectcontent_dynamic_alloc = 0;
-    objectcontent_dynamic = 0;
-    objectcontent_dynamic_refcount = 0;
-
-    /* well, we do need to allocate dynamic strings all the time,
-     * so this would just have to be converted.  It takes 1.4k on
-     * my system. - PL */
-/*     objectptr_indices = mmap(NULL,  */
-/*                          metadata.object_length * sizeof (int), */
-/*                          PROT_READ, */
-/*                          MAP_SHARED, fd, metadata.object_offset); */
-/*     if (objectptr_indices == MAP_FAILED) */
-/*         goto bail; */
-
-    objectptr_count = metadata.object_length;
-    objectptr_alloc = metadata.object_length;
-    objectptr_indices = malloc (metadata.object_length * sizeof (int));
-    if (!objectptr_indices) 
-       goto bail;
-    FcMemAlloc (FC_MEM_STATICSTR, metadata.object_length * sizeof (int));
-    lseek (fd, metadata.object_offset, SEEK_SET);
-    read (fd, objectptr_indices, metadata.object_length * sizeof (int));
-
-    objectcontent_static_buf = 
-       mmap(NULL,
-            metadata.objectcontent_length * sizeof (char),
-            PROT_READ,
-            MAP_SHARED, fd, metadata.objectcontent_offset);
-    if (objectptr_indices == MAP_FAILED)
-       goto bail1;
-    objectcontent_static_bytes = metadata.objectcontent_length;
-
-    FcObjectRebuildStaticNameHashtable ();
-
-    return FcTrue;
-
- bail1:
-    /*munmap(objectptr_indices, metadata.object_length * sizeof(int));*/
-    free (objectptr_indices);
- bail:
-    return FcFalse;
+    for (p = &FcStrBuckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+        if (b->hash == hash && !strcmp (s, (char *) (b + 1)))
+       {
+           char * t = *(char **)(((char *)(b + 1)) + strlen (s) + 1);
+           if (!t)
+           {
+               strcpy(static_strs[bi] + fcstr_ptr, s);
+               *(char **)((char *) (b + 1) + strlen(s) + 1) = (static_strs[bi] + fcstr_ptr);
+               fcstr_ptr += strlen(s) + 1;
+               t = *(char **)(((char *)(b + 1)) + strlen (s) + 1);
+           }
+           return t;
+       }
+    return 0;
 }
 
-FcBool
-FcObjectWrite (int fd, FcCache * metadata)
+static void *
+FcStrUnserialize (FcCache metadata, void *block_ptr)
 {
-    /* there should be no dynamic strings: 
-     * serialize ought to have zapped 'em. */
-    if (objectcontent_dynamic_alloc)
-       return FcFalse;
-
-    metadata->object_length = objectptr_count;
-    metadata->object_offset = FcCacheNextOffset(fd);    
-    lseek(fd, metadata->object_offset, SEEK_SET);
-    if (write (fd, objectptr_indices, 
-              metadata->object_length * sizeof (int)) == -1)
-       return FcFalse;
-
-    metadata->objectcontent_length = objectcontent_static_bytes;
-    metadata->objectcontent_offset = FcCacheNextOffset(fd);
-    lseek(fd, metadata->objectcontent_offset, SEEK_SET);
-    if (write (fd, objectcontent_static_buf, 
-              metadata->objectcontent_length * sizeof (char)) == -1)
-       return FcFalse;
-
-    return FcTrue;
-}
+    int bi = FcCacheBankToIndex(metadata.bank);
+    if (!FcStrEnsureBank(bi))
+       return 0;
 
-static void
-FcObjectStaticNameFini (void)
-{
-    int i, size;
-    struct objectBucket *b, *next;
-    char *name;
+    FcMemAlloc (FC_MEM_STRING, sizeof (char) * metadata.str_count);
+    static_strs[bi] = (char *)block_ptr;
+    block_ptr = (void *)((char *)block_ptr + 
+                        (sizeof (char) * metadata.str_count));
 
-    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;
-    }
+    return block_ptr;
 }
 
-void
-FcPatternFini (void)
-{
-    FcPatternBaseThawAll ();
-    FcValueListThawAll ();
-    FcObjectStaticNameFini ();
-}
index dfa7697c8c7de2d7e450b884758ab03f9114c27e..730e44061eecfaa475bf6a598bc1a42a70a22c06 100644 (file)
@@ -25,7 +25,6 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
-#include <sys/mman.h>
 #include "fcint.h"
 
 FcChar8 *
@@ -849,67 +848,10 @@ FcStrSetCreate (void)
     set->ref = 1;
     set->num = 0;
     set->size = 0;
-    set->storage = FcStorageDynamic;
-    set->u.strs = 0;
+    set->strs = 0;
     return set;
 }
 
-static FcChar8 * strset_buf = 0; 
-static int strset_buf_ptr = 0, strset_buf_count = 0;
-static int * strset_idx = 0; 
-static int strset_idx_ptr = 0, strset_idx_count = 0;
-static FcStrSet * strsets = 0; 
-static int strset_ptr = 0, strset_count = 0;
-
-void FcStrSetClearStatic()
-{
-    strset_buf = 0; strset_buf_ptr = 0; strset_buf_count = 0;
-    strset_idx = 0; strset_idx_ptr = 0; strset_idx_count = 0;
-    strsets = 0; strset_ptr = 0; strset_count = 0;
-}
-
-FcChar8 *
-FcStrSetGet (const FcStrSet *set, int i)
-{
-    int index;
-    switch (set->storage)
-    {
-    case FcStorageStatic:
-       index = strset_idx[set->u.stridx_offset];
-       if (index == -1)
-           return 0;
-       return &strset_buf[index];
-    case FcStorageDynamic:
-       return set->u.strs[i];
-    default:
-       return 0;
-    }
-}
-
-FcStrSet *
-FcStrSetPtrU (const FcStrSetPtr set)
-{
-    switch (set.storage)
-    {
-    case FcStorageStatic:
-       return &strsets[set.u.stat];
-    case FcStorageDynamic:
-       return (FcStrSet *)set.u.dyn;
-    default:
-       return 0;
-    }
-}
-
-FcStrSetPtr
-FcStrSetPtrCreateDynamic (const FcStrSet * set)
-{
-    FcStrSetPtr new;
-
-    new.storage = FcStorageDynamic;
-    new.u.dyn = (FcStrSet *)set;
-    return new;
-}
-
 static FcBool
 _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
 {
@@ -918,7 +860,7 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
        FcStrFree (s);
        return FcTrue;
     }
-    if (set->num == set->size || set->storage == FcStorageStatic)
+    if (set->num == set->size)
     {
        FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
 
@@ -926,24 +868,14 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
            return FcFalse;
        FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
        set->size = set->size + 1;
-       if (set->storage == FcStorageDynamic)
-       {
-           if (set->num)
-               memcpy (strs, set->u.strs, set->num * sizeof (FcChar8 *));
-           if (set->u.strs)
-               free (set->u.strs);
-       }
-       else 
-       {
-           if (set->num)
-               memcpy (strs, strset_idx+set->u.stridx_offset, 
-                       set->num * sizeof (FcChar8 *));
-           set->storage = FcStorageDynamic;
-       }
-       set->u.strs = strs;
-    }
-    set->u.strs[set->num++] = s;
-    set->u.strs[set->num] = 0;
+       if (set->num)
+           memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
+       if (set->strs)
+           free (set->strs);
+       set->strs = strs;
+    }
+    set->strs[set->num++] = s;
+    set->strs[set->num] = 0;
     return FcTrue;
 }
 
@@ -953,7 +885,7 @@ FcStrSetMember (FcStrSet *set, const FcChar8 *s)
     int        i;
 
     for (i = 0; i < set->num; i++)
-       if (!FcStrCmp (FcStrSetGet(set, i), s))
+       if (!FcStrCmp (set->strs[i], s))
            return FcTrue;
     return FcFalse;
 }
@@ -965,7 +897,7 @@ FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
     if (sa->num != sb->num)
        return FcFalse;
     for (i = 0; i < sa->num; i++)
-       if (!FcStrSetMember (sb, FcStrSetGet(sa, i)))
+       if (!FcStrSetMember (sb, sa->strs[i]))
            return FcFalse;
     return FcTrue;
 }
@@ -1004,15 +936,14 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s)
     int        i;
 
     for (i = 0; i < set->num; i++)
-       if (!FcStrCmp (FcStrSetGet(set, i), s))
+       if (!FcStrCmp (set->strs[i], s))
        {
-           if (set->storage == FcStorageDynamic)
-               FcStrFree (set->u.strs[i]);
+           FcStrFree (set->strs[i]);
            /*
             * copy remaining string pointers and trailing
             * NULL
             */
-           memmove (FcStrSetGet(set, i), FcStrSetGet(set, i+1),
+           memmove (&set->strs[i], &set->strs[i+1], 
                     (set->num - i) * sizeof (FcChar8 *));
            set->num--;
            return FcTrue;
@@ -1027,194 +958,16 @@ FcStrSetDestroy (FcStrSet *set)
     {
        int     i;
     
-       if (set->storage == FcStorageDynamic)
-       {
-           for (i = 0; i < set->num; i++)
-               FcStrFree (set->u.strs[i]);
-           FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
-           if (set->u.strs)
-               free (set->u.strs);
-           FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
-       }
+       for (i = 0; i < set->num; i++)
+           FcStrFree (set->strs[i]);
+       FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
+       if (set->strs)
+           free (set->strs);
+       FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
        free (set);
     }
 }
 
-static int _FcStrSetSort_helper (const void * a, const void * b)
-{
-    return FcStrCmp (&strset_buf[(int)a], 
-                    &strset_buf[(int)b]);
-}
-
-void
-FcStrSetSort (FcStrSet * set)
-{
-    switch (set->storage)
-    {
-    case FcStorageDynamic:
-       qsort (set->u.strs, set->num, sizeof (FcChar8 *), 
-              (int (*)(const void *, const void *)) FcStrCmp);
-       break;
-    case FcStorageStatic:
-       qsort (strset_idx+set->u.stridx_offset, set->num, sizeof (int), 
-              _FcStrSetSort_helper);
-       break;
-    default:
-       break;
-    }
-}
-
-FcBool
-FcStrSetPrepareSerialize (const FcStrSet *set)
-{
-    int i;
-
-    if (!set)
-       return FcTrue;
-
-    strset_count ++;
-    strset_idx_count += set->num;
-    for (i = 0; i < set->num; i++)
-    {
-       if (FcStrSetGet(set, i))
-           strset_buf_count += strlen(FcStrSetGet(set, i));
-    }
-
-    return FcTrue;
-}
-
-FcStrSetPtr
-FcStrSetSerialize (FcStrSet *set)
-{
-    FcStrSet * new;
-    FcStrSetPtr newp;
-    int i;
-
-    if (!strsets)
-    {
-       strsets = malloc (strset_count * sizeof(FcStrSet));
-       if (!strsets) goto bail1;
-       strset_idx = malloc (strset_idx_count * sizeof(int));
-       if (!strset_idx) goto bail2;
-       strset_buf = malloc (strset_buf_count * sizeof (FcChar8));
-       if (!strset_buf) goto bail3;
-    }
-
-    if (!set)
-       return FcStrSetPtrCreateDynamic(0);
-
-    newp.storage = FcStorageStatic;
-    newp.u.stat = strset_ptr;
-
-    new = &strsets[strset_ptr++];
-    new->ref = set->ref;
-    new->num = set->num;
-    new->size = set->num;
-    new->storage = FcStorageStatic;
-    new->u.stridx_offset = strset_idx_ptr;
-    for (i = 0; i < set->num; i++)
-    {
-       FcChar8 * s = FcStrSetGet(set, i);
-
-       if (s)
-       {
-           memcpy(strset_buf+strset_buf_ptr, s,
-                  strlen((char *)s));
-           strset_idx[strset_idx_ptr++] = strset_buf_ptr;
-           strset_buf_ptr += strlen((char *)s)+1;
-       }
-       else
-           strset_idx[strset_idx_ptr++] = -1;
-    }
-
-    if (strset_ptr > strset_count || strset_idx_ptr > strset_idx_count)
-       return FcStrSetPtrCreateDynamic(0);
-
-    // problem with multiple ptrs to the same StrSet.
-    // should hash StrSets or something.
-    // FcStrSetDestroy (set);
-
-    return newp;
-
- bail3:
-    free (strset_idx);
- bail2:
-    free (strsets);
- bail1:
-    return FcStrSetPtrCreateDynamic(0);
-}
-
-FcBool
-FcStrSetRead (int fd, FcCache metadata)
-{
-    strsets = mmap(NULL, 
-                  metadata.strsets_length * sizeof (FcStrSet),
-                  PROT_READ,
-                  MAP_SHARED, fd, metadata.strsets_offset);
-    if (strsets == MAP_FAILED)
-        goto bail;
-    strset_count = strset_ptr = metadata.strsets_length;
-
-    strset_idx = mmap(NULL, 
-                     metadata.strsets_idx_length * sizeof (int),
-                     PROT_READ,
-                     MAP_SHARED, fd, metadata.strsets_idx_offset);
-    if (strset_idx == MAP_FAILED)
-        goto bail1;
-    strset_idx_count = strset_idx_ptr = metadata.strsets_length;
-
-    strset_buf = mmap(NULL,
-                     metadata.strset_buf_length * sizeof (char),
-                     PROT_READ,
-                     MAP_SHARED, fd, metadata.strset_buf_offset);
-    if (strset_buf == MAP_FAILED)
-       goto bail2;
-    strset_buf_count = strset_buf_ptr = metadata.strset_buf_length;
-
-    return FcTrue;
-
- bail2:
-    munmap (strset_idx, metadata.strsets_idx_length * sizeof (int));
- bail1:
-    munmap (strsets, metadata.strsets_length * sizeof (FcStrSet));
- bail:
-    return FcFalse;
-}
-
-FcBool
-FcStrSetWrite (int fd, FcCache *metadata)
-{
-    metadata->strsets_length = strset_ptr;
-    metadata->strsets_offset = FcCacheNextOffset(fd);
-    if (strset_ptr > 0)
-    {
-       lseek (fd, metadata->strsets_offset, SEEK_SET);
-       if (write (fd, strsets, strset_ptr * sizeof(FcStrSet)) == -1)
-           return FcFalse;
-    }
-
-    metadata->strsets_idx_length = strset_idx_ptr;
-    metadata->strsets_idx_offset = FcCacheNextOffset(fd);
-    if (strset_idx_ptr > 0)
-    {
-       lseek (fd, metadata->strsets_idx_offset, SEEK_SET);
-       if (write (fd, strset_idx, strset_idx_ptr * sizeof (int)) == -1)
-           return FcFalse;
-    }
-
-    metadata->strset_buf_offset = FcCacheNextOffset(fd);
-    metadata->strset_buf_length = strset_buf_ptr;
-    if (strset_buf_ptr > 0)
-    {
-       lseek (fd, metadata->strset_buf_offset, SEEK_SET);
-       if (write (fd, strset_buf, 
-                  metadata->strset_buf_length * sizeof (char)) == -1)
-           return FcFalse;
-    }
-
-    return FcTrue;
-}
-
 FcStrList *
 FcStrListCreate (FcStrSet *set)
 {
@@ -1235,7 +988,7 @@ FcStrListNext (FcStrList *list)
 {
     if (list->n >= list->set->num)
        return 0;
-    return FcStrSetGet(list->set, list->n++);
+    return list->set->strs[list->n++];
 }
 
 void
index d982755eccdcc615eb38a620dcd92e57ea8c5777..4176c73e874a17b11b566a4b3d5e263f6681c0de 100644 (file)
@@ -1878,8 +1878,8 @@ FcPopValue (FcConfigParse *parse)
     
     switch (vstack->tag) {
     case FcVStackString:
-       value.u.si = FcObjectStaticName(FcStrCopy (vstack->u.string));
-       if (FcObjectPtrU(value.u.si))
+       value.u.s = FcStrCopy (vstack->u.string);
+       if (value.u.s)
            value.type = FcTypeString;
        break;
     case FcVStackConstant:
@@ -1895,8 +1895,8 @@ FcPopValue (FcConfigParse *parse)
        value.type = FcTypeInteger;
        break;
     case FcVStackMatrix:
-       value.u.mi = FcMatrixPtrCreateDynamic(FcMatrixCopy (vstack->u.matrix));
-       if (FcMatrixPtrU(value.u.mi))
+       value.u.m = FcMatrixCopy (vstack->u.matrix);
+       if (value.u.m)
            value.type = FcTypeMatrix;
        break;
     case FcVStackBool:
@@ -2281,9 +2281,10 @@ FcConfigParseAndLoadDir (FcConfig        *config,
     if (ret)
     {
        int i;
-       FcStrSetSort (files);
+       qsort (files->strs, files->num, sizeof (FcChar8 *), 
+              (int (*)(const void *, const void *)) FcStrCmp);
        for (i = 0; ret && i < files->num; i++)
-           ret = FcConfigParseAndLoad (config, FcStrSetGet(files, i), complain);
+           ret = FcConfigParseAndLoad (config, files->strs[i], complain);
     }
 bail3:
     FcStrSetDestroy (files);