]> git.wh0rd.org Git - fontconfig.git/commitdiff
#ifdef out old cache stuff, replace with first version of new mmapping
authorPatrick Lam <plam@MIT.EDU>
Mon, 25 Jul 2005 04:10:09 +0000 (04:10 +0000)
committerPatrick Lam <plam@MIT.EDU>
Mon, 25 Jul 2005 04:10:09 +0000 (04:10 +0000)
    cache. Add *Read and *Write procedures which mmap in and write out the
    fontconfig data structures to disk. Currently, create cache in /tmp,
    with different sections for each architecture (as returned by uname's
    .machine field. Run the fc-cache binary to create a new cache file;
    fontconfig then uses this cache file on subsequent runs, saving lots of
    memory. Also fixes a few bugs and leaks.

13 files changed:
fc-cache/fc-cache.c
fc-lang/fc-lang.c
src/fccache.c
src/fccfg.c
src/fccharset.c
src/fcdir.c
src/fcfs.c
src/fcinit.c
src/fcint.h
src/fclang.c
src/fcmatrix.c
src/fcpat.c
src/fcstr.c

index 1e8fdf29605fd351d65d08a6df9606113b01f4ae..7d01ccf9997f2490e4469fbfd9198be1d07cbca3 100644 (file)
@@ -93,6 +93,7 @@ usage (char *program)
     exit (1);
 }
 
+#if 0
 static int
 nsubdirs (FcStrSet *set)
 {
@@ -222,6 +223,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
     FcStrListDone (list);
     return ret;
 }
+#endif
 
 int
 main (int argc, char **argv)
@@ -268,12 +270,20 @@ main (int argc, char **argv)
 
     if (systemOnly)
        FcConfigEnableHome (FcFalse);
-    config = FcInitLoadConfig ();
+    FcCacheForce (FcTrue);
+    /* need to use FcInitLoadConfig when we use dirs */
+    FcInit ();
+    config = FcConfigGetCurrent ();
     if (!config)
     {
        fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
        return 1;
     }
+
+    /* We don't yet have per-directory caches. */
+    ret = (FcCacheWrite (config) == FcFalse);
+
+#if 0
     if (argv[i])
     {
        dirs = FcStrSetCreate ();
@@ -298,6 +308,7 @@ 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 a2699a3c7d23bc0065293101e1f89cb4438a15d0..e302c4a69f6a0db82286b4a8d3d099aa7efb1d3c 100644 (file)
@@ -47,6 +47,12 @@ FcMemFree (int kind, int size)
 {
 }
 
+int
+FcCacheNextOffset (int fd)
+{
+    return -1;
+}
+
 FcChar8 *
 FcConfigHome (void)
 {
index a9d87019892527e23547931f31eec10d44458a7b..9b92173b2c129f0fb638061f3a47f19a9b81742d 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
 #include "fcint.h"
 
-/*
- * POSIX has broken stdio so that getc must do thread-safe locking,
- * this is a serious performance problem for applications doing large
- * amounts of IO with getc (as is done here).  If available, use
- * the getc_unlocked varient instead.
- */
-#if defined(getc_unlocked) || defined(_IO_getc_unlocked)
-#define GETC(f) getc_unlocked(f)
-#define PUTC(c,f) putc_unlocked(c,f)
-#else
-#define GETC(f) getc(f)
-#define PUTC(c,f) putc(c,f)
-#endif
+#define PAGESIZE 8192
 
-#define FC_DBG_CACHE_REF    1024
+static FcBool force;
 
 static FcChar8 *
-FcCacheReadString (FILE *f, FcChar8 *dest, int len)
+FcCacheReadString (int fd, FcChar8 *dest, int len)
 {
-    int                c;
+    FcChar8    c;
     FcBool     escape;
-    FcChar8    *d;
     int                size;
     int                i;
 
-    while ((c = GETC (f)) != EOF)
-       if (c == '"')
-           break;
-    if (c == EOF)
-       return FcFalse;
     if (len == 0)
        return FcFalse;
     
     size = len;
     i = 0;
-    d = dest;
     escape = FcFalse;
-    while ((c = GETC (f)) != EOF)
+    while (read (fd, &c, 1) == 1)
     {
        if (!escape)
        {
@@ -77,260 +60,26 @@ FcCacheReadString (FILE *f, FcChar8 *dest, int len)
        }
        if (i == size)
        {
-           FcChar8 *new = malloc (size * 2);   /* freed in caller */
-           if (!new)
-               break;
-           memcpy (new, d, size);
-           size *= 2;
-           if (d != dest)
-               free (d);
-           d = new;
+           dest[i++] = 0;
+           return dest;
        }
-       d[i++] = c;
+       dest[i++] = c;
        if (c == '\0')
-           return d;
+           return dest;
        escape = FcFalse;
     }
-    if (d != dest)
-       free (d);
     return 0;
 }
 
 static FcBool
-FcCacheReadUlong (FILE *f, unsigned long *dest)
-{
-    unsigned long   t;
-    int                    c;
-
-    while ((c = GETC (f)) != EOF)
-    {
-       if (!isspace (c))
-           break;
-    }
-    if (c == EOF)
-       return FcFalse;
-    t = 0;
-    for (;;)
-    {
-       if (c == EOF || isspace (c))
-           break;
-       if (!isdigit (c))
-           return FcFalse;
-       t = t * 10 + (c - '0');
-       c = GETC (f);
-    }
-    *dest = t;
-    return FcTrue;
-}
-
-static FcBool
-FcCacheReadInt (FILE *f, int *dest)
-{
-    unsigned long   t;
-    FcBool         ret;
-
-    ret = FcCacheReadUlong (f, &t);
-    if (ret)
-       *dest = (int) t;
-    return ret;
-}
-
-static FcBool
-FcCacheReadTime (FILE *f, time_t *dest)
-{
-    unsigned long   t;
-    FcBool         ret;
-
-    ret = FcCacheReadUlong (f, &t);
-    if (ret)
-       *dest = (time_t) t;
-    return ret;
-}
-
-static FcBool
-FcCacheWriteChars (FILE *f, const FcChar8 *chars)
-{
-    FcChar8    c;
-    while ((c = *chars++))
-    {
-       switch (c) {
-       case '"':
-       case '\\':
-           if (PUTC ('\\', f) == EOF)
-               return FcFalse;
-           /* fall through */
-       default:
-           if (PUTC (c, f) == EOF)
-               return FcFalse;
-       }
-    }
-    return FcTrue;
-}
-
-static FcBool
-FcCacheWriteString (FILE *f, const FcChar8 *string)
-{
-
-    if (PUTC ('"', f) == EOF)
-       return FcFalse;
-    if (!FcCacheWriteChars (f, string))
-       return FcFalse;
-    if (PUTC ('"', f) == EOF)
-       return FcFalse;
-    return FcTrue;
-}
-
-static FcBool
-FcCacheWritePath (FILE *f, const FcChar8 *dir, const FcChar8 *file)
+FcCacheWriteString (int fd, const FcChar8 *chars)
 {
-    if (PUTC ('"', f) == EOF)
-       return FcFalse;
-    if (dir)
-       if (!FcCacheWriteChars (f, dir))
-           return FcFalse;
-#ifdef _WIN32
-    if (dir &&
-       dir[strlen((const char *) dir) - 1] != '/' &&
-       dir[strlen((const char *) dir) - 1] != '\\')
-    {
-       if (!FcCacheWriteChars (f, "\\"))
-           return FcFalse;
-    }
-#else
-    if (dir && dir[strlen((const char *) dir) - 1] != '/')
-       if (PUTC ('/', f) == EOF)
-           return FcFalse;
-#endif
-    if (!FcCacheWriteChars (f, file))
+    if (write (fd, chars, strlen(chars)+1) != strlen(chars)+1)
        return FcFalse;
-    if (PUTC ('"', f) == EOF)
-       return FcFalse;
-    return FcTrue;
-}
-
-static FcBool
-FcCacheWriteUlong (FILE *f, unsigned long t)
-{
-    int            pow;
-    unsigned long   temp, digit;
-
-    temp = t;
-    pow = 1;
-    while (temp >= 10)
-    {
-       temp /= 10;
-       pow *= 10;
-    }
-    temp = t;
-    while (pow)
-    {
-       digit = temp / pow;
-       if (PUTC ((char) digit + '0', f) == EOF)
-           return FcFalse;
-       temp = temp - pow * digit;
-       pow = pow / 10;
-    }
     return FcTrue;
 }
 
-static FcBool
-FcCacheWriteInt (FILE *f, int i)
-{
-    return FcCacheWriteUlong (f, (unsigned long) i);
-}
-
-static FcBool
-FcCacheWriteTime (FILE *f, time_t t)
-{
-    return FcCacheWriteUlong (f, (unsigned long) t);
-}
-
-static FcBool
-FcCacheFontSetAdd (FcFontSet       *set,
-                  FcStrSet         *dirs,
-                  const FcChar8    *dir,
-                  int              dir_len,
-                  const FcChar8    *file,
-                  const FcChar8    *name,
-                  FcConfig         *config)
-{
-    FcChar8    path_buf[8192], *path;
-    int                len;
-    FcBool     ret = FcFalse;
-    FcPattern  *font;
-    FcPattern  *frozen;
-
-    path = path_buf;
-    len = (dir_len + 1 + strlen ((const char *) file) + 1);
-    if (len > sizeof (path_buf))
-    {
-       path = malloc (len);    /* freed down below */
-       if (!path)
-           return FcFalse;
-    }
-    strncpy ((char *) path, (const char *) dir, dir_len);
-#ifdef _WIN32
-    if (dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\' )
-       path[dir_len++] = '\\';
-#else
-    if (dir[dir_len - 1] != '/')
-       path[dir_len++] = '/';
-#endif
-    strcpy ((char *) path + dir_len, (const char *) file);
-    if (config && !FcConfigAcceptFilename (config, path))
-       ret = FcTrue;
-    else if (!FcStrCmp (name, FC_FONT_FILE_DIR))
-    {
-       if (FcDebug () & FC_DBG_CACHEV)
-           printf (" dir cache dir \"%s\"\n", path);
-       ret = FcStrSetAdd (dirs, path);
-    }
-    else if (!FcStrCmp (name, FC_FONT_FILE_INVALID))
-    {
-       ret = FcTrue;
-    }
-    else
-    {
-       font = FcNameParse (name);
-       if (font)
-       {
-           FcChar8 *family;
-           
-           if (FcDebug () & FC_DBG_CACHEV)
-               printf (" dir cache file \"%s\"\n", file);
-           ret = FcPatternAddString (font, FC_FILE, path);
-           /*
-            * Make sure the pattern has the file name as well as
-            * already containing at least one family name.
-            */
-           if (ret && 
-               FcPatternGetString (font, FC_FAMILY, 0, &family) == FcResultMatch &&
-               (!config || FcConfigAcceptFont (config, font)))
-           {
-               frozen = FcPatternFreeze (font);
-               ret = (frozen != 0);
-               if (ret)
-                  ret = FcFontSetAdd (set, frozen);
-           }
-           FcPatternDestroy (font);
-       }
-    }
-    if (path != path_buf) free (path);
-    return ret;
-    
-}
-
-static unsigned int
-FcCacheHash (const FcChar8 *string, int len)
-{
-    unsigned int    h = 0;
-    FcChar8        c;
-
-    while (len-- && (c = *string++))
-       h = (h << 1) ^ c;
-    return h;
-}
-
+#if 0
 /*
  * Verify the saved timestamp for a file
  */
@@ -406,328 +155,6 @@ FcFilePathInfoGet (const FcChar8    *path)
     return i;
 }
 
-FcGlobalCacheDir *
-FcGlobalCacheDirGet (FcGlobalCache  *cache,
-                    const FcChar8  *dir,
-                    int            len,
-                    FcBool         create_missing)
-{
-    unsigned int       hash = FcCacheHash (dir, len);
-    FcGlobalCacheDir   *d, **prev;
-
-    for (prev = &cache->ents[hash % FC_GLOBAL_CACHE_DIR_HASH_SIZE];
-        (d = *prev);
-        prev = &(*prev)->next)
-    {
-       if (d->info.hash == hash && d->len == len &&
-           !strncmp ((const char *) d->info.file,
-                     (const char *) dir, len))
-           break;
-    }
-    if (!(d = *prev))
-    {
-       int     i;
-       if (!create_missing)
-           return 0;
-       d = malloc (sizeof (FcGlobalCacheDir) + len + 1);
-       if (!d)
-           return 0;
-       FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + len + 1);
-       d->next = *prev;
-       *prev = d;
-       d->info.hash = hash;
-       d->info.file = (FcChar8 *) (d + 1);
-       strncpy ((char *) d->info.file, (const char *) dir, len);
-       d->info.file[len] = '\0';
-       d->info.time = 0;
-       d->info.referenced = FcFalse;
-       d->len = len;
-       for (i = 0; i < FC_GLOBAL_CACHE_FILE_HASH_SIZE; i++)
-           d->ents[i] = 0;
-       d->subdirs = 0;
-    }
-    return d;
-}
-
-static FcGlobalCacheInfo *
-FcGlobalCacheDirAdd (FcGlobalCache  *cache,
-                    const FcChar8  *dir,
-                    time_t         time,
-                    FcBool         replace,
-                    FcBool         create_missing)
-{
-    FcGlobalCacheDir   *d;
-    FcFilePathInfo     i;
-    FcGlobalCacheSubdir        *subdir;
-    FcGlobalCacheDir   *parent;
-
-    i = FcFilePathInfoGet (dir);
-    parent = FcGlobalCacheDirGet (cache, i.dir, i.dir_len, create_missing);
-    /*
-     * Tricky here -- directories containing fonts.cache-1 files
-     * need entries only when the parent doesn't have a cache file.
-     * That is, when the parent already exists in the cache, is
-     * referenced and has a "real" timestamp.  The time of 0 is
-     * special and marks directories which got stuck in the
-     * global cache for this very reason.  Yes, it could
-     * use a separate boolean field, and probably should.
-     */
-    if (!parent || (!create_missing && 
-                   (!parent->info.referenced ||
-                   (parent->info.time == 0))))
-       return 0;
-    /*
-     * Add this directory to the cache
-     */
-    d = FcGlobalCacheDirGet (cache, dir, strlen ((const char *) dir), FcTrue);
-    if (!d)
-       return 0;
-    d->info.time = time;
-    /*
-     * Add this directory to the subdirectory list of the parent
-     */
-    subdir = malloc (sizeof (FcGlobalCacheSubdir));
-    if (!subdir)
-       return 0;
-    FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
-    subdir->ent = d;
-    subdir->next = parent->subdirs;
-    parent->subdirs = subdir;
-    return &d->info;
-}
-
-static void
-FcGlobalCacheDirDestroy (FcGlobalCacheDir *d)
-{
-    FcGlobalCacheFile  *f, *next;
-    int                        h;
-    FcGlobalCacheSubdir        *s, *nexts;
-
-    for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
-       for (f = d->ents[h]; f; f = next)
-       {
-           next = f->next;
-           FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
-                      strlen ((char *) f->info.file) + 1 +
-                      strlen ((char *) f->name) + 1);
-           free (f);
-       }
-    for (s = d->subdirs; s; s = nexts)
-    {
-       nexts = s->next;
-       FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
-       free (s);
-    }
-    FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + d->len + 1);
-    free (d);
-}
-
-/*
- * If the parent is in the global cache and referenced, add
- * an entry for 'dir' to the global cache.  This is used
- * for directories with fonts.cache files
- */
-
-void
-FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
-                             const FcChar8 *dir)
-{
-    FcGlobalCacheInfo  *info;
-    info = FcGlobalCacheDirAdd (cache, dir, 0, FcFalse, FcFalse);
-    if (info && !info->referenced)
-    {
-       info->referenced = FcTrue;
-       cache->referenced++;
-    }
-}
-
-/*
- * Check to see if the global cache contains valid data for 'dir'.
- * If so, scan the global cache for files and directories in 'dir'.
- * else, return False.
- */
-FcBool
-FcGlobalCacheScanDir (FcFontSet                *set,
-                     FcStrSet          *dirs,
-                     FcGlobalCache     *cache,
-                     const FcChar8     *dir,
-                     FcConfig          *config)
-{
-    FcGlobalCacheDir   *d = FcGlobalCacheDirGet (cache, dir,
-                                                 strlen ((const char *) dir),
-                                                 FcFalse);
-    FcGlobalCacheFile  *f;
-    int                        h;
-    int                        dir_len;
-    FcGlobalCacheSubdir        *subdir;
-    FcBool             any_in_cache = FcFalse;
-
-    if (FcDebug() & FC_DBG_CACHE)
-       printf ("FcGlobalCacheScanDir %s\n", dir);
-    
-    if (!d)
-    {
-       if (FcDebug () & FC_DBG_CACHE)
-           printf ("\tNo dir cache entry\n");
-       return FcFalse;
-    }
-
-    /*
-     * See if the timestamp recorded in the global cache
-     * matches the directory time, if not, return False
-     */
-    if (!FcGlobalCacheCheckTime (d->info.file, &d->info))
-    {
-       if (FcDebug () & FC_DBG_CACHE)
-           printf ("\tdir cache entry time mismatch\n");
-       return FcFalse;
-    }
-
-    /*
-     * Add files from 'dir' to the fontset
-     */
-    dir_len = strlen ((const char *) dir);
-    for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
-       for (f = d->ents[h]; f; f = f->next)
-       {
-           if (FcDebug() & FC_DBG_CACHEV)
-               printf ("FcGlobalCacheScanDir add file %s\n", f->info.file);
-           any_in_cache = FcTrue;
-           if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
-                                   f->info.file, f->name, config))
-           {
-               cache->broken = FcTrue;
-               return FcFalse;
-           }
-           FcGlobalCacheReferenced (cache, &f->info);
-       }
-    /*
-     * Add directories in 'dir' to 'dirs'
-     */
-    for (subdir = d->subdirs; subdir; subdir = subdir->next)
-    {
-       FcFilePathInfo  info = FcFilePathInfoGet (subdir->ent->info.file);
-       
-        any_in_cache = FcTrue;
-       if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
-                               info.base, FC_FONT_FILE_DIR, config))
-       {
-           cache->broken = FcTrue;
-           return FcFalse;
-       }
-       FcGlobalCacheReferenced (cache, &subdir->ent->info);
-    }
-    
-    FcGlobalCacheReferenced (cache, &d->info);
-
-    /*
-     * To recover from a bug in previous versions of fontconfig,
-     * return FcFalse if no entries in the cache were found
-     * for this directory.  This will cause any empty directories
-     * to get rescanned every time fontconfig is initialized.  This
-     * might get removed at some point when the older cache files are
-     * presumably fixed.
-     */
-    return any_in_cache;
-}
-
-/*
- * Locate the cache entry for a particular file
- */
-FcGlobalCacheFile *
-FcGlobalCacheFileGet (FcGlobalCache *cache,
-                     const FcChar8 *file,
-                     int           id,
-                     int           *count)
-{
-    FcFilePathInfo     i = FcFilePathInfoGet (file);
-    FcGlobalCacheDir   *d = FcGlobalCacheDirGet (cache, i.dir, 
-                                                 i.dir_len, FcFalse);
-    FcGlobalCacheFile  *f, *match = 0;
-    int                        max = -1;
-
-    if (!d)
-       return 0;
-    for (f = d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE]; f; f = f->next)
-    {
-       if (f->info.hash == i.base_hash &&
-           !strcmp ((const char *) f->info.file, (const char *) i.base))
-       {
-           if (f->id == id)
-               match = f;
-           if (f->id > max)
-               max = f->id;
-       }
-    }
-    if (count)
-       *count = max + 1;
-    return match;
-}
-    
-/*
- * Add a file entry to the cache
- */
-static FcGlobalCacheInfo *
-FcGlobalCacheFileAdd (FcGlobalCache *cache,
-                     const FcChar8 *path,
-                     int           id,
-                     time_t        time,
-                     const FcChar8 *name,
-                     FcBool        replace)
-{
-    FcFilePathInfo     i = FcFilePathInfoGet (path);
-    FcGlobalCacheDir   *d = FcGlobalCacheDirGet (cache, i.dir, 
-                                                 i.dir_len, FcTrue);
-    FcGlobalCacheFile  *f, **prev;
-    int                        size;
-
-    if (!d)
-       return 0;
-    for (prev = &d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE];
-        (f = *prev);
-        prev = &(*prev)->next)
-    {
-       if (f->info.hash == i.base_hash && 
-           f->id == id &&
-           !strcmp ((const char *) f->info.file, (const char *) i.base))
-       {
-           break;
-       }
-    }
-    if (*prev)
-    {
-       if (!replace)
-           return 0;
-
-       f = *prev;
-       if (f->info.referenced)
-           cache->referenced--;
-       *prev = f->next;
-       FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
-                  strlen ((char *) f->info.file) + 1 +
-                  strlen ((char *) f->name) + 1);
-       free (f);
-    }
-    size = (sizeof (FcGlobalCacheFile) +
-           strlen ((char *) i.base) + 1 +
-           strlen ((char *) name) + 1);
-    f = malloc (size);
-    if (!f)
-       return 0;
-    FcMemAlloc (FC_MEM_CACHE, size);
-    f->next = *prev;
-    *prev = f;
-    f->info.hash = i.base_hash;
-    f->info.file = (FcChar8 *) (f + 1);
-    f->info.time = time;
-    f->info.referenced = FcFalse;
-    f->id = id;
-    f->name = f->info.file + strlen ((char *) i.base) + 1;
-    strcpy ((char *) f->info.file, (const char *) i.base);
-    strcpy ((char *) f->name, (const char *) name);
-    return &f->info;
-}
-
 FcGlobalCache *
 FcGlobalCacheCreate (void)
 {
@@ -955,218 +382,59 @@ bail1:
 bail0:
     return FcFalse;
 }
+#endif
 
-FcBool
-FcDirCacheValid (const FcChar8 *dir)
+/* 
+ * Find the next presumably-mmapable offset after the current file
+ * pointer.
+ */
+int
+FcCacheNextOffset(int fd)
 {
-    FcChar8    *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
-    struct stat        file_stat, dir_stat;
+    off_t w;
+    w = lseek(fd, 0, SEEK_END);
 
-    if (stat ((char *) dir, &dir_stat) < 0)
-    {
-       FcStrFree (cache_file);
-       return FcFalse;
-    }
-    if (stat ((char *) cache_file, &file_stat) < 0)
-    {
-       FcStrFree (cache_file);
-       return FcFalse;
-    }
-    FcStrFree (cache_file);
-    /*
-     * If the directory has been modified more recently than
-     * the cache file, the cache is not valid
-     */
-    if (dir_stat.st_mtime - file_stat.st_mtime > 0)
-       return FcFalse;
-    return FcTrue;
+    if (w % PAGESIZE == 0) 
+       return w;
+    else
+       return ((w / PAGESIZE)+1)*PAGESIZE;
 }
 
-FcBool
-FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config)
+/* will go away once we use config->cache */
+#define CACHE_DEFAULT_TMPDIR "/tmp"
+#define CACHE_DEFAULT_NAME "/fontconfig-mmap"
+static char *
+FcCacheFilename(void)
 {
-    FcChar8        *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
-    FILE           *f;
-    FcChar8        *base;
-    int                    id;
-    int                    dir_len;
-    FcChar8        file_buf[8192], *file;
-    FcChar8        name_buf[8192], *name;
-    FcBool         ret = FcFalse;
+    struct utsname b;
+    static char * name = 0;
 
-    if (!cache_file)
-       goto bail0;
-    
-    if (FcDebug () & FC_DBG_CACHE)
-       printf ("FcDirCacheReadDir cache_file \"%s\"\n", cache_file);
-    
-    f = fopen ((char *) cache_file, "r");
-    if (!f)
-    {
-       if (FcDebug () & FC_DBG_CACHE)
-           printf (" no cache file\n");
-       goto bail1;
-    }
+    if (name)
+        return name;
 
-    if (!FcDirCacheValid (dir))
-    {
-       if (FcDebug () & FC_DBG_CACHE)
-           printf (" cache file older than directory\n");
-       goto bail2;
-    }
-    
-    base = (FcChar8 *) strrchr ((char *) cache_file, '/');
-    if (!base)
-       goto bail2;
-    base++;
-    dir_len = base - cache_file;
-    
-    file = 0;
-    name = 0;
-    while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) &&
-          FcCacheReadInt (f, &id) &&
-          (name = FcCacheReadString (f, name_buf, sizeof (name_buf))))
+    if (uname(&b) == -1)
+        name = CACHE_DEFAULT_NAME;
+    else
     {
-       if (!FcCacheFontSetAdd (set, dirs, cache_file, dir_len,
-                               file, name, config))
-           goto bail3;
-       if (file != file_buf)
-           free (file);
-       if (name != name_buf)
-           free (name);
-       file = name = 0;
-    }
-    if (FcDebug () & FC_DBG_CACHE)
-       printf (" cache loaded\n");
-    
-    ret = FcTrue;
-bail3:
-    if (file && file != file_buf)
-       free (file);
-    if (name && name != name_buf)
-       free (name);
-bail2:
-    fclose (f);
-bail1:
-    FcStrFree (cache_file);
-bail0:
-    return ret;
-}
+        char * tmpname = getenv("TMPDIR");
+        char * logname = getenv("LOGNAME");
+        if (!tmpname)
+            tmpname = CACHE_DEFAULT_TMPDIR;
 
-/*
- * return the path from the directory containing 'cache' to 'file'
- */
-
-static const FcChar8 *
-FcFileBaseName (const FcChar8 *cache, const FcChar8 *file)
-{
-    const FcChar8   *cache_slash;
-
-    cache_slash = FcStrLastSlash (cache);
-    if (cache_slash && !strncmp ((const char *) cache, (const char *) file,
-                                (cache_slash + 1) - cache))
-       return file + ((cache_slash + 1) - cache);
-    return file;
-}
-
-FcBool
-FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
-{
-    FcChar8        *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
-    FcPattern      *font;
-    FILE           *f;
-    FcChar8        *name;
-    const FcChar8   *file, *base;
-    int                    n;
-    int                    id;
-    FcBool         ret;
-    FcStrList      *list;
-
-    if (!cache_file)
-       goto bail0;
-    if (FcDebug () & FC_DBG_CACHE)
-       printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
-    
-    f = fopen ((char *) cache_file, "w");
-    if (!f)
-    {
-       if (FcDebug () & FC_DBG_CACHE)
-           printf (" can't create \"%s\"\n", cache_file);
-       goto bail1;
-    }
-    
-    list = FcStrListCreate (dirs);
-    if (!list)
-       goto bail2;
-    
-    while ((dir = FcStrListNext (list)))
-    {
-       base = FcFileBaseName (cache_file, dir);
-       if (!FcCacheWriteString (f, base))
-           goto bail3;
-       if (PUTC (' ', f) == EOF)
-           goto bail3;
-       if (!FcCacheWriteInt (f, 0))
-           goto bail3;
-        if (PUTC (' ', f) == EOF)
-           goto bail3;
-       if (!FcCacheWriteString (f, FC_FONT_FILE_DIR))
-           goto bail3;
-       if (PUTC ('\n', f) == EOF)
-           goto bail3;
+        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 : "");
     }
-    
-    for (n = 0; n < set->nfont; n++)
-    {
-       font = set->fonts[n];
-       if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
-           goto bail3;
-       base = FcFileBaseName (cache_file, file);
-       if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
-           goto bail3;
-       if (FcDebug () & FC_DBG_CACHEV)
-           printf (" write file \"%s\"\n", base);
-       if (!FcCacheWriteString (f, base))
-           goto bail3;
-       if (PUTC (' ', f) == EOF)
-           goto bail3;
-       if (!FcCacheWriteInt (f, id))
-           goto bail3;
-        if (PUTC (' ', f) == EOF)
-           goto bail3;
-       name = FcNameUnparse (font);
-       if (!name)
-           goto bail3;
-       ret = FcCacheWriteString (f, name);
-       FcStrFree (name);
-       if (!ret)
-           goto bail3;
-       if (PUTC ('\n', f) == EOF)
-           goto bail3;
-    }
-    
-    FcStrListDone (list);
-
-    if (fclose (f) == EOF)
-       goto bail1;
-    
-    FcStrFree (cache_file);
-
-    if (FcDebug () & FC_DBG_CACHE)
-       printf (" cache written\n");
-    return FcTrue;
-    
-bail3:
-    FcStrListDone (list);
-bail2:
-    fclose (f);
-bail1:
-    unlink ((char *) cache_file);
-    FcStrFree (cache_file);
-bail0:
-    return FcFalse;
+    return name;
 }
 
+/* 
+ * Wipe out static state.
+ */
 void
 FcCacheClearStatic()
 {
@@ -1179,6 +447,9 @@ FcCacheClearStatic()
     FcLangSetClearStatic();
 }
 
+/*
+ * Trigger the counting phase: this tells us how much to allocate.
+ */
 FcBool
 FcCachePrepareSerialize (FcConfig * config)
 {
@@ -1189,6 +460,7 @@ FcCachePrepareSerialize (FcConfig * config)
     return FcTrue;
 }
 
+/* allocate and populate static structures */
 FcBool
 FcCacheSerialize (FcConfig * config)
 {
@@ -1198,3 +470,238 @@ FcCacheSerialize (FcConfig * config)
            return FcFalse;
     return FcTrue;
 }
+
+/* get the current arch name */
+/* caller is responsible for freeing returned pointer */
+static char *
+FcCacheGetCurrentArch (void)
+{
+    struct utsname b;
+    char * current_arch_machine_name;
+
+    if (uname(&b) == -1)
+       return FcFalse;
+    current_arch_machine_name = strdup(b.machine);
+    /* if (getenv ("FAKE_ARCH")) // testing purposes
+       current_arch_machine_name = strdup(getenv("FAKE_ARCH")); */
+    return current_arch_machine_name;
+}
+
+/* return the address of the segment for the provided arch,
+ * or -1 if arch not found */
+static off_t
+FcCacheSkipToArch (int fd, const char * arch)
+{
+    char candidate_arch_machine_name[64], bytes_to_skip[7];
+    off_t current_arch_start = 0;
+
+    /* skip arches that are not the current arch */
+    while (1)
+    {
+       long bs;
+
+       lseek (fd, current_arch_start, SEEK_SET);
+       if (FcCacheReadString (fd, candidate_arch_machine_name, 
+                              sizeof (candidate_arch_machine_name)) == 0)
+           break;
+       if (FcCacheReadString (fd, bytes_to_skip, 7) == 0)
+           break;
+       bs = a64l(bytes_to_skip);
+       if (bs == 0)
+           break;
+
+       if (strcmp (candidate_arch_machine_name, arch)==0)
+           break;
+       current_arch_start += bs;
+    }
+
+    if (strcmp (candidate_arch_machine_name, arch)!=0)
+       return -1;
+
+    return current_arch_start;
+}
+
+/* Cuts out the segment at the file pointer (moves everything else
+ * down to cover it), and leaves the file pointer at the end of the
+ * file. */
+#define BUF_SIZE 8192
+
+static FcBool 
+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;
+    int c, bytes_skipped;
+
+    if (!buf)
+       return FcFalse;
+
+    lseek (fd, start, SEEK_SET);
+    if (FcCacheReadString (fd, candidate_arch_machine_name, 
+                          sizeof (candidate_arch_machine_name)) == 0)
+       goto done;
+    if (FcCacheReadString (fd, bytes_to_skip, 7) == 0)
+       goto done;
+
+    bs = a64l(bytes_to_skip);
+    if (bs == 0)
+       goto done;
+
+    bytes_skipped = 0;
+    do
+    {
+       lseek (fd, start+bs+bytes_skipped, SEEK_SET);
+       if ((c = read (fd, buf, BUF_SIZE)) <= 0)
+           break;
+       lseek (fd, start+bytes_skipped, SEEK_SET);
+       if (write (fd, buf, c) < 0)
+           goto bail;
+       bytes_skipped += c;
+    }
+    while (c > 0);
+    lseek (fd, start+bytes_skipped, SEEK_SET);
+
+ done:
+    free (buf);
+    return FcTrue;
+
+ bail:
+    free (buf);
+    return FcFalse;
+}
+
+/* read serialized state from the cache file */
+FcBool
+FcCacheRead (FcConfig *config)
+{
+    int fd, i;
+    FcCache metadata;
+    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;
+
+    fd = open(FcCacheFilename(), O_RDONLY);
+    if (fd == -1)
+        return FcFalse;
+
+    current_arch_machine_name = FcCacheGetCurrentArch();
+    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
+    if (current_arch_start < 0)
+        goto bail;
+
+    lseek (fd, current_arch_start, SEEK_SET);
+    if (FcCacheReadString (fd, candidate_arch_machine_name, 
+                          sizeof (candidate_arch_machine_name)) == 0)
+       goto bail;
+    if (FcCacheReadString (fd, bytes_in_block, 7) == 0)
+       goto bail;
+
+    // sanity check for endianness issues
+    read(fd, &metadata, sizeof(FcCache));
+    if (metadata.magic != FC_CACHE_MAGIC)
+        goto bail;
+
+    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;
+    close(fd);
+    free (current_arch_machine_name);
+    return FcTrue;
+
+ bail1:
+    for (i = FcSetSystem; i <= FcSetApplication; i++)
+        config->fonts[i] = 0;
+    close(fd);
+ bail:
+    free (current_arch_machine_name);
+    return FcFalse;
+}
+
+/* write serialized state to the cache file */
+FcBool
+FcCacheWrite (FcConfig * config)
+{
+    int fd;
+    FcCache metadata;
+    off_t current_arch_start = 0, truncate_to;
+    char * current_arch_machine_name, bytes_written[7] = "dedbef";
+
+    if (!FcCachePrepareSerialize (config))
+       return FcFalse;
+
+    if (!FcCacheSerialize (config))
+       return FcFalse;
+
+    fd = open(FcCacheFilename(), 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);
+
+    if (!FcCacheMoveDown(fd, current_arch_start))
+       goto bail;
+
+    current_arch_start = lseek(fd, 0, SEEK_CUR);
+    if (ftruncate (fd, current_arch_start) == -1)
+       goto bail;
+
+    /* 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;
+
+    /* 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);
+    strcpy (bytes_written, l64a(truncate_to));
+    if (!FcCacheWriteString (fd, bytes_written))
+       goto bail;
+
+    /* now rewrite metadata & truncate file */
+    if (write(fd, &metadata, sizeof(FcCache)) != sizeof (FcCache)) 
+       goto bail;
+    if (ftruncate (fd, current_arch_start + truncate_to) == -1)
+       goto bail;
+
+    close(fd);
+    return FcTrue;
+
+ bail:
+    free (current_arch_machine_name);
+    return FcFalse;
+}
+
+/* if true, ignore the cache file */
+void
+FcCacheForce (FcBool f)
+{
+    force = f;
+}
index 7be4cdd4bd375880d7384f43f714a21651762a91..a5de075f2a9c7bc04bda6c20e1069bba7997f1ae 100644 (file)
@@ -252,16 +252,22 @@ FcConfigBuildFonts (FcConfig *config)
     FcStrList      *list;
     FcChar8        *dir;
 
+#if 0
+    if (config->cache)
+       FcGlobalCacheLoad (cache, config->cache);
+#endif
+    if (config->fonts[FcSetSystem])
+       return FcTrue;
+
     fonts = FcFontSetCreate ();
     if (!fonts)
        goto bail0;
-    
+
+#if 0
     cache = FcGlobalCacheCreate ();
     if (!cache)
        goto bail1;
-
-    if (config->cache)
-       FcGlobalCacheLoad (cache, config->cache);
+#endif
 
     list = FcConfigGetFontDirs (config);
     if (!list)
@@ -280,9 +286,11 @@ FcConfigBuildFonts (FcConfig *config)
     if (FcDebug () & FC_DBG_FONTSET)
        FcFontSetPrint (fonts);
 
+#if 0
     if (config->cache)
        FcGlobalCacheSave (cache, config->cache);
     FcGlobalCacheDestroy (cache);
+#endif
 
     FcConfigSetFonts (config, fonts, FcSetSystem);
     
index 6c6f0f5d79b247f32824a75aaa9d952562f87a48..00b2010e5aac399c7f452b1203204931d0d658e9 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <stdlib.h>
+#include <sys/mman.h>
 #include "fcint.h"
 
 /* #define CHECK */
@@ -383,6 +384,14 @@ 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)
 {
@@ -1369,10 +1378,11 @@ FcCharSetSerialize(FcCharSet *c)
        if (!leaf_idx) goto bail3;
     }
 
-    new.ref = c->ref;
+    new.ref = FC_REF_CONSTANT;
     new.storage = FcStorageStatic;
-    new.u.stat.leafidx_offset = charset_leaf_ptr;
+    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;
@@ -1398,6 +1408,95 @@ FcCharSetSerialize(FcCharSet *c)
     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;
+}
+
+FcBool
+FcCharSetWrite (int fd, FcCache *metadata)
+{
+    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;
+    }
+
+    return FcTrue;
+}
+
 FcCharLeaf *
 FcCharSetGetLeaf(const FcCharSet *c, int i)
 {
index 974886d362c0ab19e4561e70056d6c12d27da46b..595e22a0f6ed8e4ada9f46dc2a6fe05069063d12 100644 (file)
@@ -45,13 +45,15 @@ FcFileScanConfig (FcFontSet *set,
                  FcConfig      *config)
 {
     int                        id;
+#if 0
     FcChar8            *name;
+    FcGlobalCacheFile  *cache_file;
+    FcGlobalCacheDir   *cache_dir;
+#endif
     FcPattern          *font;
     FcBool             ret = FcTrue;
     FcBool             isDir;
     int                        count = 0;
-    FcGlobalCacheFile  *cache_file;
-    FcGlobalCacheDir   *cache_dir;
     FcBool             need_scan;
     
     if (config && !FcConfigAcceptFilename (config, file))
@@ -64,6 +66,7 @@ FcFileScanConfig (FcFontSet   *set,
     {
        need_scan = FcTrue;
        font = 0;
+#if 0
        /*
         * Check the cache
         */
@@ -104,6 +107,7 @@ FcFileScanConfig (FcFontSet *set,
                }
            }
        }
+#endif
        /*
         * Nothing in the cache, scan the file
         */
@@ -123,6 +127,7 @@ FcFileScanConfig (FcFontSet *set,
                isDir = FcTrue;
                ret = FcStrSetAdd (dirs, file);
            }
+#if 0
            /*
             * Update the cache
             */
@@ -137,6 +142,7 @@ FcFileScanConfig (FcFontSet *set,
                    FcStrFree (unparse);
                }
            }
+#endif
        }
        /*
         * Add the font
@@ -193,6 +199,7 @@ FcDirScanConfig (FcFontSet  *set,
 
     if (!force)
     {
+#if 0
        /*
         * Check fonts.cache-<version> file
         */
@@ -208,6 +215,7 @@ FcDirScanConfig (FcFontSet  *set,
         */
        if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir, config))
            return FcTrue;
+#endif
     }
     
     /* freed below */
@@ -246,8 +254,10 @@ FcDirScanConfig (FcFontSet *set,
      * Now that the directory has been scanned,
      * add the cache entry 
      */
+#if 0
     if (ret && cache)
        FcGlobalCacheUpdate (cache, dir, 0, 0);
+#endif
        
     return ret;
 }
@@ -266,5 +276,8 @@ FcDirScan (FcFontSet            *set,
 FcBool
 FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
 {
+#if 0
     return FcDirCacheWriteDir (set, dirs, dir);
+#endif
+    return FcTrue;
 }
index c2020402e663093d1b8fbb8764e05e445c8f907a..f362e2b428a8b2ec0fa34025c85688cf27a14ff0 100644 (file)
@@ -116,3 +116,98 @@ FcFontSetClearStatic (void)
 {
     FcPatternClearStatic();
 }
+
+FcBool
+FcFontSetRead(int fd, FcConfig * config, FcCache metadata)
+{
+    int i, mz, j;
+    FcPattern * buf;
+
+    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]);
+        }
+    }
+
+    for (i = FcSetSystem; i <= FcSetApplication; i++)
+    {
+        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;
+           }
+        }
+    }
+
+    return FcTrue;
+ bail:
+    for (i = FcSetSystem; i <= FcSetApplication; i++)
+    {
+        if (config->fonts[i])
+        {
+            if (config->fonts[i]->fonts)
+                free (config->fonts[i]->fonts);
+            free(config->fonts[i]);
+        }
+        config->fonts[i] = 0;
+    }
+    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 8a9bdbda8c6e1634bdbb39deb60ae221838b1d99..9c51c28c97b4dcbdb46a0faff2e05b3bd35aeb39 100644 (file)
@@ -61,6 +61,9 @@ FcInitLoadConfig (void)
     if (!config)
        return FcFalse;
     
+    if (!FcCacheRead(config))
+        FcCacheForce(FcTrue);
+
     if (!FcConfigParseAndLoad (config, 0, FcTrue))
     {
        FcConfigDestroy (config);
index f29b459703ddc0a8dd4f40da0ebc714ce0765cdf..992c09f8e6f72638ad0bcaeaa87c7710daa39d6e 100644 (file)
@@ -259,6 +259,25 @@ typedef struct _FcStrBuf {
     int            size;
 } 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;
+} FcCache;
+
 /*
  * To map adobe glyph names to unicode values, a precomputed hash
  * table is used
@@ -312,6 +331,7 @@ typedef struct _FcCaseFold {
  * cache which is then rewritten to the users home directory
  */
 
+#define FC_CACHE_MAGIC 0x12345678
 #define FC_GLOBAL_CACHE_DIR_HASH_SIZE      37
 #define FC_GLOBAL_CACHE_FILE_HASH_SIZE     67
 
@@ -429,66 +449,27 @@ typedef struct _FcCharMap FcCharMap;
 
 /* fccache.c */
 
-FcGlobalCache *
-FcGlobalCacheCreate (void);
-
-void
-FcGlobalCacheDestroy (FcGlobalCache *cache);
-
-FcBool
-FcGlobalCacheCheckTime (const FcChar8*file, FcGlobalCacheInfo *info);
+int
+FcCacheNextOffset(int fd);
 
 void
-FcGlobalCacheReferenced (FcGlobalCache     *cache,
-                        FcGlobalCacheInfo  *info);
+FcCacheForce(FcBool force);
 
 void
-FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
-                             const FcChar8 *dir);
-
-FcGlobalCacheDir *
-FcGlobalCacheDirGet (FcGlobalCache  *cache,
-                    const FcChar8  *dir,
-                    int            len,
-                    FcBool         create_missing);
-
-FcBool
-FcGlobalCacheScanDir (FcFontSet                *set,
-                     FcStrSet          *dirs,
-                     FcGlobalCache     *cache,
-                     const FcChar8     *dir,
-                     FcConfig          *config);
-
-FcGlobalCacheFile *
-FcGlobalCacheFileGet (FcGlobalCache *cache,
-                     const FcChar8 *file,
-                     int           id,
-                     int           *count);
-
-
-void
-FcGlobalCacheLoad (FcGlobalCache    *cache,
-                  const FcChar8    *cache_file);
+FcCacheClearStatic(void);
 
 FcBool
-FcGlobalCacheUpdate (FcGlobalCache  *cache,
-                    const FcChar8  *file,
-                    int            id,
-                    const FcChar8  *name);
+FcCachePrepareSerialize(FcConfig * config);
 
 FcBool
-FcGlobalCacheSave (FcGlobalCache    *cache,
-                  const FcChar8    *cache_file);
+FcCacheSerialize (FcConfig * config);
 
 FcBool
-FcDirCacheReadDir (FcFontSet       *set, 
-                  FcStrSet         *dirs,
-                  const FcChar8    *dir,
-                  FcConfig         *config);
+FcCacheRead (FcConfig *config);
 
 FcBool
-FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
-    
+FcCacheWrite (FcConfig * config);
 /* fccfg.c */
 
 FcBool
@@ -553,6 +534,9 @@ FcConfigAcceptFont (FcConfig            *config,
 FcCharSet *
 FcCharSetFreeze (FcCharSet *cs);
 
+FcCharSetPtr
+FcCharSetCopyPtr (FcCharSetPtr src);
+
 void
 FcCharSetThawAll (void);
 
@@ -586,6 +570,12 @@ 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);
@@ -668,6 +658,12 @@ FcFontSetPrepareSerialize (FcFontSet * s);
 FcBool
 FcFontSetSerialize (FcFontSet * s);
 
+FcBool
+FcFontSetRead(int fd, FcConfig * config, FcCache metadata);
+
+FcBool
+FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata);
+
 /* fcgram.y */
 int
 FcConfigparse (void);
@@ -766,6 +762,12 @@ FcLangSetPtrCreateDynamic (FcLangSet *l);
 void
 FcLangSetPtrDestroy (FcLangSetPtr li);
 
+FcBool
+FcLangSetRead (int fd, FcCache metadata);
+
+FcBool
+FcLangSetWrite (int fd, FcCache *metadata);
+
 /* fclist.c */
 
 FcBool
@@ -774,18 +776,6 @@ FcListPatternMatchAny (const FcPattern *p,
 
 /* fcmatch.c */
 
-/* fcmmap.c */
-
-void
-FcCacheClearStatic(void);
-
-FcBool
-FcCachePrepareSerialize(FcConfig * config);
-
-FcBool
-FcCacheSerialize (FcConfig * config);
-
-
 /* fcname.c */
 
 FcBool
@@ -824,7 +814,10 @@ FcObjectPtr
 FcObjectStaticName (const char *name);
 
 FcBool
-FcObjectPrepareSerialize (FcObjectPtr si);
+FcObjectRead (int fd, FcCache metadata);
+
+FcBool
+FcObjectWrite (int fd, FcCache * metadata);
 
 const char *
 FcObjectPtrU (FcObjectPtr p);
@@ -832,9 +825,6 @@ FcObjectPtrU (FcObjectPtr p);
 int
 FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b);
 
-FcObjectPtr
-FcObjectPtrCreateDynamic (const char * s);
-
 void
 FcObjectPtrDestroy (FcObjectPtr p);
 
@@ -865,6 +855,24 @@ 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);
+
+FcBool
+FcValueListWrite (int fd, FcCache *metadata);
+
 /* fcrender.c */
 
 /* fcmatrix.c */
@@ -892,6 +900,12 @@ 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);
@@ -938,6 +952,12 @@ 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 28b2d9b9c6965755b72b80981da54eafc7d3b1b3..515e3cf74d29449b4717281c2b4134ccf8f7c83f 100644 (file)
@@ -774,3 +774,31 @@ FcLangSetSerialize(FcLangSet *l)
     new.u.stat = p;
     return new;
 }
+
+FcBool
+FcLangSetWrite (int fd, FcCache *metadata)
+{
+    metadata->langsets_length = langset_ptr;
+    metadata->langsets_offset = FcCacheNextOffset(fd);
+
+    if (langset_ptr > 0)
+    {
+       lseek (fd, metadata->langsets_offset, SEEK_SET);
+       return write(fd, langsets, 
+                    metadata->langsets_length * sizeof(FcLangSet)) != -1;
+    }
+    return FcTrue;
+}
+
+FcBool
+FcLangSetRead (int fd, FcCache metadata)
+{
+    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;
+}
index 6a5aa5dd8fa6b71b79f298ae7ad9d0e1b7dcae8d..9b69bc909d6cdd632aa57886874126befe8c804c 100644 (file)
@@ -25,6 +25,7 @@
 #include <math.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <sys/mman.h>
 #include "fcint.h"
 
 FcMatrix    _id = { 1, 0, 0, 1 };
@@ -182,3 +183,31 @@ FcMatrixSerialize(FcMatrix *m)
     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 0633c5ac4f122c8cc0a830c3ce1e45dce463d854..956ed669c0734d070042d2f6981ac310b91770d5 100644 (file)
@@ -94,8 +94,7 @@ FcValueSave (FcValue v)
            v.type = FcTypeVoid;
        break;
     case FcTypeCharSet:
-       v.u.ci = FcCharSetPtrCreateDynamic
-           (FcCharSetCopy (FcCharSetPtrU(v.u.ci)));
+       v.u.ci = FcCharSetCopyPtr (v.u.ci);
        if (!FcCharSetPtrU(v.u.ci))
            v.type = FcTypeVoid;
        break;
@@ -1270,7 +1269,6 @@ FcPatternEltU (FcPatternEltPtr pei)
     switch (pei.storage)
     {
     case FcStorageStatic:
-       if (pei.u.stat == 0) return 0;
         return &fcpatternelts[pei.u.stat];
     case FcStorageDynamic:
         return pei.u.dyn;
@@ -1324,6 +1322,8 @@ FcValueListClearStatic (void)
     fcvaluelist_count = 0;
 }
 
+static FcBool
+FcObjectPrepareSerialize (FcObjectPtr si);
 static FcObjectPtr
 FcObjectSerialize (FcObjectPtr si);
 
@@ -1408,13 +1408,14 @@ FcPatternSerialize (FcPattern *old)
        fcpatternelt_ptr = 0;
     }
 
-    p = FcPatternCreate();
+    p = &fcpatterns[fcpattern_ptr++];
     elts = fcpatternelt_ptr;
     nep = &fcpatternelts[elts];
     if (!nep)
        return FcFalse;
+
     fcpatternelt_ptr += old->num;
-    
+
     for (e = FcPatternEltU(old->elts), i=0; i < old->num; i++, e++) 
     {
         v = e->values;
@@ -1438,12 +1439,13 @@ FcPatternSerialize (FcPattern *old)
         }
        
        nep[i].values = nv_head;
-       nep[i].object = FcObjectSerialize
-           (FcObjectStaticName(FcObjectPtrU(e->object)));
+       nep[i].object = FcObjectSerialize (e->object);
     }
-    
+
+    p->elts = old->elts;
     p->elts = FcPatternEltPtrCreateStatic(elts);
     p->size = old->num;
+    p->num = old->num;
     p->ref = FC_REF_CONSTANT;
     return p;
     
@@ -1453,7 +1455,69 @@ FcPatternSerialize (FcPattern *old)
     free (fcpatterns);
  bail:
     return 0;
- }
+}
+
+FcBool
+FcPatternRead (int fd, FcCache metadata)
+{
+    fcpatterns = mmap(NULL, 
+                     metadata.pattern_length * sizeof (FcPattern),
+                     PROT_READ,
+                     MAP_SHARED, fd, metadata.pattern_offset);
+    if (fcpatterns == MAP_FAILED)
+       return FcFalse;
+    fcpattern_count = fcpattern_ptr = metadata.pattern_length;
+
+    return FcTrue;
+}
+
+FcBool
+FcPatternWrite (int fd, FcCache *metadata)
+{
+    int c = fcpattern_ptr;
+    off_t w = FcCacheNextOffset(fd);
+
+    metadata->pattern_offset = w;
+    metadata->pattern_length = c;
+
+    if (c > 0)
+    {
+       lseek(fd, w, SEEK_SET);
+       return write(fd, fcpatterns, c*sizeof(FcPattern)) != -1;
+    }
+    return FcTrue;
+}
+
+FcBool
+FcPatternEltRead (int fd, FcCache metadata)
+{
+    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;
+
+    return FcTrue;
+}
+
+FcBool
+FcPatternEltWrite (int fd, FcCache *metadata)
+{
+    int c = fcpatternelt_ptr;
+    off_t w = FcCacheNextOffset(fd);
+
+    metadata->patternelt_offset = w;
+    metadata->patternelt_length = c;
+
+    if (c > 0)
+    {
+       lseek(fd, w, SEEK_SET);
+       return write(fd, fcpatternelts, c*sizeof(FcPatternElt)) != -1;
+    }
+    return FcTrue;
+}
 
 FcValueListPtr
 FcValueListSerialize(FcValueList *pi)
@@ -1480,13 +1544,18 @@ FcValueListSerialize(FcValueList *pi)
     switch (v->type)
     {
     case FcTypeString:
-       if (FcObjectPtrU(v->u.si))
+       /* 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)
        {
-           FcObjectPtr si = 
-               FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v->u.si)));
-           if (!FcObjectPtrU(v->u.si))
+           FcObjectPtr si = FcObjectSerialize(v->u.si);
+           if (!FcObjectPtrU(si))
                return FcValueListPtrCreateDynamic(pi);
            v->u.si = si;
+           pi->value.u.si = si;
        }
        break;
     case FcTypeMatrix:
@@ -1503,7 +1572,7 @@ FcValueListSerialize(FcValueList *pi)
        if (FcCharSetPtrU(v->u.ci))
        {
            FcCharSetPtr ci = FcCharSetSerialize(FcCharSetPtrU(v->u.ci));
-           if (!FcCharSetPtrU(v->u.ci))
+           if (!FcCharSetPtrU(ci))
                return FcValueListPtrCreateDynamic(pi);
            v->u.ci = ci;
        }
@@ -1512,7 +1581,7 @@ FcValueListSerialize(FcValueList *pi)
        if (FcLangSetPtrU(v->u.li))
        {
            FcLangSetPtr li = FcLangSetSerialize(FcLangSetPtrU(v->u.li));
-           if (!FcLangSetPtrU(v->u.li))
+           if (!FcLangSetPtrU(li))
                return FcValueListPtrCreateDynamic(pi);
            v->u.li = li;
        }
@@ -1523,13 +1592,41 @@ FcValueListSerialize(FcValueList *pi)
     return new;
 }
 
+FcBool
+FcValueListRead (int fd, FcCache metadata)
+{
+    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;
+
+    return FcTrue;
+}
+
+FcBool
+FcValueListWrite (int fd, FcCache *metadata)
+{
+    metadata->valuelist_offset = FcCacheNextOffset(fd);
+    metadata->valuelist_length = fcvaluelist_ptr;
+
+    if (fcvaluelist_ptr > 0)
+    {
+       lseek(fd, metadata->valuelist_offset, SEEK_SET);
+       return write(fd, fcvaluelists, 
+                    fcvaluelist_ptr * sizeof(FcValueList)) != -1;
+    }
+    return FcTrue;
+}
+
 FcValueList * 
 FcValueListPtrU (FcValueListPtr pi)
 {
     switch (pi.storage)
     {
     case FcStorageStatic:
-       if (pi.u.stat == 0) return 0;
         return &fcvaluelists[pi.u.stat];
     case FcStorageDynamic:
         return pi.u.dyn;
@@ -1642,7 +1739,7 @@ FcObjectStaticName (const char *name)
        objectptr_alloc = s;
     }
 
-    size = sizeof (struct objectBucket) + strlen (name) + 1;
+    size = sizeof (struct objectBucket) + sizeof (char *);
     b = malloc (size);
     if (!b)
        return 0;
@@ -1687,6 +1784,9 @@ FcObjectPtrDestroy (FcObjectPtr p)
 const char *
 FcObjectPtrU (FcObjectPtr si)
 {
+    if (si == 0)
+       return 0;
+
     if (objectptr_indices[si] > 0)
        return &objectcontent_static_buf[objectptr_indices[si]];
     else
@@ -1750,7 +1850,7 @@ FcObjectRebuildStaticNameHashtable (void)
 /* 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.) */
+ * not problematic, because the program quits just afterwards.) */
 static FcBool
 FcObjectPtrConvertToStatic(FcBool renumber)
 {
@@ -1784,6 +1884,8 @@ FcObjectPtrConvertToStatic(FcBool renumber)
     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));
@@ -1817,8 +1919,8 @@ FcObjectPtrConvertToStatic(FcBool renumber)
        int n = FcObjectStaticName(fixed_length_buf+i*(longest_string+1));
        if (renumber)
        {
-           object_old_id_to_new[n] = i;
-           new_indices[i] = p-new_static_buf;
+           object_old_id_to_new[n] = i+1;
+           new_indices[i+1] = p-new_static_buf;
        }
        else
            new_indices[n] = p-new_static_buf;
@@ -1907,21 +2009,11 @@ FcObjectClearStatic(void)
     object_old_id_to_new = 0;
 }
 
-static FcObjectPtr
-FcObjectSerialize (FcObjectPtr si)
-{
-    if (objectptr_first_serialization)
-       if (!FcObjectPtrConvertToStatic(FcTrue))
-           return 0;
-
-    return object_old_id_to_new[si];
-}
-
 /* 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). */
-FcBool
+static FcBool
 FcObjectPrepareSerialize (FcObjectPtr si)
 {
     if (object_old_id_to_new == 0)
@@ -1942,6 +2034,93 @@ FcObjectPrepareSerialize (FcObjectPtr si)
     return FcFalse;
 }
 
+static FcObjectPtr
+FcObjectSerialize (FcObjectPtr si)
+{
+    if (objectptr_first_serialization)
+       if (!FcObjectPtrConvertToStatic(FcTrue))
+           return 0;
+
+    return object_old_id_to_new[si];
+}
+
+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;
+}
+
+FcBool
+FcObjectWrite (int fd, FcCache * metadata)
+{
+    /* 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;
+}
+
 static void
 FcObjectStaticNameFini (void)
 {
index 1391b6554dbc5dede8a737e839853114448d8108..dfa7697c8c7de2d7e450b884758ab03f9114c27e 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include <sys/mman.h>
 #include "fcint.h"
 
 FcChar8 *
@@ -1129,8 +1130,8 @@ FcStrSetSerialize (FcStrSet *set)
     if (strset_ptr > strset_count || strset_idx_ptr > strset_idx_count)
        return FcStrSetPtrCreateDynamic(0);
 
-    // problem with multiple ptrs to the same LangSet.
-    // should hash LangSets or something.
+    // problem with multiple ptrs to the same StrSet.
+    // should hash StrSets or something.
     // FcStrSetDestroy (set);
 
     return newp;
@@ -1143,6 +1144,77 @@ FcStrSetSerialize (FcStrSet *set)
     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)
 {