From 4262e0b3853bc2153270eb33d09a063f852f3f90 Mon Sep 17 00:00:00 2001 From: Patrick Lam Date: Wed, 24 Aug 2005 06:21:30 +0000 Subject: [PATCH] Overhaul the serialization system to create one mmapable file per directory 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. --- fc-cache/fc-cache.c | 12 +- fc-lang/fc-lang.c | 4 +- fontconfig/fcprivate.h | 8 +- fontconfig/fontconfig.h | 51 +- src/fccache.c | 415 ++++++++----- src/fccfg.c | 109 ++-- src/fccharset.c | 333 ++++------- src/fcdbg.c | 12 +- src/fcdir.c | 17 +- src/fcfs.c | 154 ++--- src/fcinit.c | 3 - src/fcint.h | 276 ++++----- src/fclang.c | 213 +++---- src/fclist.c | 57 +- src/fcmatch.c | 88 +-- src/fcmatrix.c | 100 +--- src/fcname.c | 101 +++- src/fcpat.c | 1218 +++++++++++++++------------------------ src/fcstr.c | 291 +--------- src/fcxml.c | 13 +- 20 files changed, 1402 insertions(+), 2073 deletions(-) diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c index 7d01ccf..d2809ee 100644 --- a/fc-cache/fc-cache.c +++ b/fc-cache/fc-cache.c @@ -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 diff --git a/fc-lang/fc-lang.c b/fc-lang/fc-lang.c index e302c4a..9ec8418 100644 --- a/fc-lang/fc-lang.c +++ b/fc-lang/fc-lang.c @@ -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], diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h index 2b73945..8f8d367 100644 --- a/fontconfig/fcprivate.h +++ b/fontconfig/fcprivate.h @@ -59,22 +59,22 @@ __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)) \ diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index 7d36e9e..8d0975e 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -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 diff --git a/src/fccache.c b/src/fccache.c index 9b92173..55187c9 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #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; +} diff --git a/src/fccfg.c b/src/fccfg.c index a5de075..aaa05f5 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -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; } diff --git a/src/fccharset.c b/src/fccharset.c index 00b2010..d0fee82 100644 --- a/src/fccharset.c +++ b/src/fccharset.c @@ -23,34 +23,21 @@ */ #include -#include #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]; } diff --git a/src/fcdbg.c b/src/fcdbg.c index c8b7127..c7e0570 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -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)"); diff --git a/src/fcdir.c b/src/fcdir.c index 595e22a..4f69f22 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -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); } diff --git a/src/fcfs.c b/src/fcfs.c index f362e2b..1e5aa81 100644 --- a/src/fcfs.c +++ b/src/fcfs.c @@ -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; } diff --git a/src/fcinit.c b/src/fcinit.c index 9c51c28..8a9bdbd 100644 --- a/src/fcinit.c +++ b/src/fcinit.c @@ -61,9 +61,6 @@ FcInitLoadConfig (void) if (!config) return FcFalse; - if (!FcCacheRead(config)) - FcCacheForce(FcTrue); - if (!FcConfigParseAndLoad (config, 0, FcTrue)) { FcConfigDestroy (config); diff --git a/src/fcint.h b/src/fcint.h index 992c09f..529548c 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -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- 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); diff --git a/src/fclang.c b/src/fclang.c index 515e3cf..711cdc7 100644 --- a/src/fclang.c +++ b/src/fclang.c @@ -22,8 +22,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include -#include #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; } diff --git a/src/fclist.c b/src/fclist.c index b3ecdb8..db63058 100644 --- a/src/fclist.c +++ b/src/fclist.c @@ -23,9 +23,6 @@ */ #include -#include -#include -#include #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; } } diff --git a/src/fcmatch.c b/src/fcmatch.c index 9e70271..b2b2c8d 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -28,26 +28,26 @@ #include 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) diff --git a/src/fcmatrix.c b/src/fcmatrix.c index 9b69bc9..863fe69 100644 --- a/src/fcmatrix.c +++ b/src/fcmatrix.c @@ -25,14 +25,9 @@ #include #include #include -#include #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; -} diff --git a/src/fcname.c b/src/fcname.c index a2524ad..1cdba56 100644 --- a/src/fcname.c +++ b/src/fcname.c @@ -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)) diff --git a/src/fcpat.c b/src/fcpat.c index 956ed66..d42401d 100644 --- a/src/fcpat.c +++ b/src/fcpat.c @@ -25,18 +25,14 @@ #include #include #include -#include #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 (); -} diff --git a/src/fcstr.c b/src/fcstr.c index dfa7697..730e440 100644 --- a/src/fcstr.c +++ b/src/fcstr.c @@ -25,7 +25,6 @@ #include #include #include -#include #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 diff --git a/src/fcxml.c b/src/fcxml.c index d982755..4176c73 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -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); -- 2.39.2