exit (1);
}
-#if 0
static int
nsubdirs (FcStrSet *set)
{
ret++;
continue;
}
+#if 0 // put this back later after fixing DirCacheValid
if (!force && FcDirCacheValid (dir))
{
if (verbose)
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++;
FcStrListDone (list);
return ret;
}
-#endif
int
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 ();
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
}
int
-FcCacheNextOffset (int fd)
+FcCacheBankToIndex (int bank)
{
return -1;
}
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],
__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)) \
* it means multiple copies of the font information.
*/
-#define FC_CACHE_VERSION "1"
+#define FC_CACHE_VERSION "2"
#define FcTrue 1
#define FcFalse 0
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;
typedef struct _FcObjectSet {
int nobject;
int sobject;
- FcObjectPtr *objects;
+ const char **objects;
} FcObjectSet;
typedef enum _FcMatchKind {
FcBool force);
FcBool
-FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
+FcDirSave (FcFontSet *set, const FcChar8 *dir);
/* fcfreetype.c */
FcPattern *
void
FcMatrixShear (FcMatrix *m, double sh, double sv);
-FcMatrix *
-FcMatrixPtrU (FcMatrixPtr mi);
-
/* fcname.c */
FcBool
*/
#include <fcntl.h>
+#include <dirent.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include "fcint.h"
free (cache);
}
-/*
- * Cache file syntax is quite simple:
- *
- * "file_name" id time "font_name" \n
- */
-
void
FcGlobalCacheLoad (FcGlobalCache *cache,
const FcChar8 *cache_file)
* 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 *
{
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)
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;
}
{
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;
+}
FcBool
FcConfigBuildFonts (FcConfig *config)
{
- FcFontSet *fonts;
+ FcFontSet *fonts, *cached_fonts;
FcGlobalCache *cache;
FcStrList *list;
FcChar8 *dir;
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);
}
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);
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;
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;
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;
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;
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:
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;
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:
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
{
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;
{
FcValueListPtr next = FcValueListPtrU(lp)->next;
- if (lp.storage == FcStorageDynamic)
+ if (lp.bank == FC_BANK_DYNAMIC)
{
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
free (l);
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;
}
*/
#include <stdlib.h>
-#include <sys/mman.h>
#include "fcint.h"
/* #define CHECK */
/* #define CHATTY */
-static FcCharSet * charsets = 0;
-static FcChar16 * numbers = 0;
-static int charset_ptr, charset_count;
+static FcCharSet ** charsets = 0;
+static FcChar16 ** numbers = 0;
+static int charset_bank_count = 0, charset_ptr, charset_count;
static int charset_numbers_ptr, charset_numbers_count;
-static FcCharLeaf * leaves = 0;
+static FcCharLeaf ** leaves = 0;
static int charset_leaf_ptr, charset_leaf_count;
-static int * leaf_idx = 0;
+static int ** leaf_idx = 0;
static int charset_leaf_idx_ptr, charset_leaf_idx_count;
-void
-FcCharSetClearStatic()
-{
- charsets = 0;
- numbers = 0;
- charset_ptr = 0; charset_count = 0;
- leaves = 0;
- charset_leaf_ptr = 0; charset_leaf_count = 0;
- leaf_idx = 0;
- charset_leaf_idx_ptr = 0; charset_leaf_idx_count = 0;
-}
-
FcCharSet *
FcCharSetCreate (void)
{
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;
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)
{
return;
if (--fcs->ref > 0)
return;
- if (fcs->storage == FcStorageDynamic)
+ if (fcs->bank == FC_BANK_DYNAMIC)
{
for (i = 0; i < fcs->num; i++)
{
ucs4 >>= 8;
if (ucs4 >= 0x10000)
return FcFalse;
- if (fcs->storage == FcStorageStatic)
+ if (fcs->bank != FC_BANK_DYNAMIC)
{
int i;
leaves[i] = FcCharSetGetLeaf(fcs, i);
memcpy (numbers, FcCharSetGetNumbers(fcs),
fcs->num * sizeof (FcChar16));
- fcs->storage = FcStorageDynamic;
}
else
{
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;
}
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)
{
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)
{
}
n = FcCharSetFreezeBase (b);
bail1:
- if (b->storage == FcStorageDynamic)
+ if (b->bank == FC_BANK_DYNAMIC)
{
if (b->u.dyn.leaves)
{
#endif
n = FcCharSetFreezeBase (c);
bail1:
- if (c->storage == FcStorageDynamic)
+ if (c->bank == FC_BANK_DYNAMIC)
{
if (c->u.dyn.leaves)
{
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];
}
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");
{
for (; FcValueListPtrU(l); l = FcValueListPtrU(l)->next)
{
- FcValuePrint (FcValueListPtrU(l)->value);
+ FcValuePrint (FcValueCanonicalize(&FcValueListPtrU(l)->value));
switch (FcValueListPtrU(l)->binding) {
case FcValueBindingWeak:
printf ("(w)");
}
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);
}
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]);
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;
}
if (!config)
return FcFalse;
- if (!FcCacheRead(config))
- FcCacheForce(FcTrue);
-
if (!FcConfigParseAndLoad (config, 0, FcTrue))
{
FcConfigDestroy (config);
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;
FcValueBinding binding;
} FcValueList;
+typedef int FcObjectPtr;
+
typedef struct _FcPatternEltPtr {
- FcStorage storage;
+ int bank;
union {
int stat;
struct _FcPatternElt *dyn;
int size;
FcPatternEltPtr elts;
int ref;
+ int bank;
};
typedef enum _FcOp {
struct _FcCharSet {
int ref; /* reference count */
int num; /* size of leaves and numbers arrays */
- FcStorage storage;
+ int bank;
union {
struct {
FcCharLeaf **leaves;
int ref; /* reference count */
int num;
int size;
- FcStorage storage;
- union {
- FcChar8 **strs;
- int stridx_offset;
- } u;
+ FcChar8 **strs;
};
struct _FcStrList {
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;
/*
#define FC_MAX_FILE_LEN 4096
+#define FC_STORAGE_STATIC 0x80
+#define fc_value_string(v) (((v)->type & FC_STORAGE_STATIC) ? ((FcChar8 *) v) + (v)->u.s_off : (v) -> u.s)
+#define fc_value_charset(v) (((v)->type & FC_STORAGE_STATIC) ? (const FcCharSet *)(((char *) v) + (v)->u.c_off) : (v) -> u.c)
+#define fc_value_langset(v) (((v)->type & FC_STORAGE_STATIC) ? (const FcLangSet *)(((char *) v) + (v)->u.l_off) : (v) -> u.l)
+
/*
* The per-user ~/.fonts.cache-<version> file is loaded into
* this data structure. Each directory gets a substructure
/* 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 */
FcSetName set);
FcBool
-FcConfigCompareValue (const FcValue m,
+FcConfigCompareValue (const FcValue *m,
FcOp op,
- const FcValue v);
+ const FcValue *v);
FcBool
FcConfigGlobAdd (FcConfig *config,
FcCharSet *
FcCharSetFreeze (FcCharSet *cs);
-FcCharSetPtr
-FcCharSetCopyPtr (FcCharSetPtr src);
-
void
FcCharSetThawAll (void);
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);
FcChar16 *
FcCharSetGetNumbers(const FcCharSet *c);
-FcBool
-FcCharSetRead (int fd, FcCache metadata);
-
-FcBool
-FcCharSetWrite (int fd, FcCache *metadata);
-
/* fcdbg.c */
void
FcValueListPrint (const FcValueListPtr l);
int
FcDebug (void);
-FcCharSet *
-FcCharSetPtrU (FcCharSetPtr mi);
-
/* fcdir.c */
FcBool
/* 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
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 */
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);
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);
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);
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);
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);
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <fcntl.h>
-#include <sys/mman.h>
#include "fcint.h"
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)))
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);
}
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;
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
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;
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;
}
int id;
memset (ls.map, '\0', sizeof (ls.map));
- ls.extra = FcStrSetPtrCreateDynamic(0);
+ ls.extra = 0;
id = FcLangSetIndex (lang);
if (id > 0)
{
}
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;
}
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;
}
}
}
}
- if (FcStrSetPtrU(ls->extra))
+ if (ls->extra)
{
- FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+ FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra;
if (!list)
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;
}
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)
}
}
}
- if (FcStrSetPtrU(lsb->extra))
+ if (lsb->extra)
{
- FcStrList *list = FcStrListCreate (FcStrSetPtrU(lsb->extra));
+ FcStrList *list = FcStrListCreate (lsb->extra);
FcChar8 *extra;
if (list)
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;
}
*/
#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <unistd.h>
#include "fcint.h"
FcObjectSet *
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)
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)
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;
}
* (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))
{
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;
{
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;
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)
}
static FcChar32
-FcListValueHash (FcValue v)
+FcListValueHash (FcValue *value)
{
+ FcValue v = FcValueCanonicalize(value);
switch (v.type) {
case FcTypeVoid:
return 0;
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;
}
while (FcValueListPtrU(list))
{
- h = h ^ FcListValueHash (FcValueListPtrU(list)->value);
+ h = h ^ FcListValueHash (&FcValueListPtrU(list)->value);
list = FcValueListPtrU(list)->next;
}
return h;
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);
}
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;
}
}
#include <stdio.h>
static double
-FcCompareNumber (char *object, FcValue value1, FcValue value2)
+FcCompareNumber (char *object, FcValue *value1, FcValue *value2)
{
double v1, v2, v;
- switch (value1.type) {
+ switch (value1->type) {
case FcTypeInteger:
- v1 = (double) value1.u.i;
+ v1 = (double) value1->u.i;
break;
case FcTypeDouble:
- v1 = value1.u.d;
+ v1 = value1->u.d;
break;
default:
return -1.0;
}
- switch (value2.type) {
+ switch (value2->type) {
case FcTypeInteger:
- v2 = (double) value2.u.i;
+ v2 = (double) value2->u.i;
break;
case FcTypeDouble:
- v2 = value2.u.d;
+ v2 = value2->u.d;
break;
default:
return -1.0;
}
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;
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;
}
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;
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;
(FcChar8 *) object) != 0)
{
if (bestValue)
- *bestValue = FcValueListPtrU(v2orig)->value;
+ *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2orig)->value);
return FcTrue;
}
#if 0
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;
if (v < best)
{
if (bestValue)
- *bestValue = FcValueListPtrU(v2)->value;
+ *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2)->value);
best = v;
}
if (FcValueListPtrU(v1)->binding == FcValueBindingStrong)
}
}
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++)
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;
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)
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
-#include <sys/mman.h>
#include "fcint.h"
-FcMatrix _id = { 1, 0, 0, 1 };
-const FcMatrixPtr FcIdentityMatrix = {
- .storage = FcStorageDynamic,
- .u.dyn = &_id
-};
+const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
FcMatrix *
FcMatrixCopy (const FcMatrix *mat)
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);
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;
-}
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, },
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))
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;
{
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;
}
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;
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:
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;
}
{
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))
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include <sys/mman.h>
#include "fcint.h"
-static FcPattern * fcpatterns = NULL;
-static int fcpattern_ptr, fcpattern_count;
-static FcPatternElt * fcpatternelts = NULL;
+static FcPattern ** fcpatterns = 0;
+static int fcpattern_bank_count = 0, fcpattern_ptr, fcpattern_count;
+static FcPatternElt ** fcpatternelts = 0;
static int fcpatternelt_ptr, fcpatternelt_count;
-static FcValueList * fcvaluelists = NULL;
-static int fcvaluelist_ptr, fcvaluelist_count;
-
-static FcBool
-FcPatternEltIsDynamic (FcPatternEltPtr pei);
+static FcValueList ** fcvaluelists = 0;
+static int fcvaluelist_bank_count = 0, fcvaluelist_ptr, fcvaluelist_count;
static FcPatternEltPtr
FcPatternEltPtrCreateDynamic (FcPatternElt * e);
p->num = 0;
p->size = 0;
p->elts = FcPatternEltPtrCreateDynamic(0);
+ p->bank = FC_BANK_DYNAMIC;
p->ref = 1;
return p;
}
{
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:
{
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);
}
}
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;
}
}
static FcChar32
-FcValueHash (FcValue v)
+FcValueHash (const FcValue *v0)
{
+ FcValue v = FcValueCanonicalize(v0);
switch (v.type) {
case FcTypeVoid:
return 0;
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;
}
while (FcValueListPtrU(l))
{
hash = ((hash << 1) | (hash >> 31)) ^
- FcValueHash (FcValueListPtrU(l)->value);
+ FcValueHash (&FcValueListPtrU(l)->value);
l = FcValueListPtrU(l)->next;
}
return hash;
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));
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))
int low, high, mid, c;
FcObjectPtr obj;
- obj = FcObjectStaticName(object);
+ obj = FcObjectToPtr(object);
low = 0;
high = p->num - 1;
c = 1;
/* 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);
}
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;
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)
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;
FcValue v;
v.type = FcTypeString;
- v.u.si = FcObjectStaticName(s);
+ v.u.s = FcObjectStaticName(s);
return FcPatternAdd (p, object, v, FcTrue);
}
FcValue v;
v.type = FcTypeMatrix;
- v.u.mi = FcMatrixPtrCreateDynamic((FcMatrix *) s);
+ v.u.m = s;
return FcPatternAdd (p, object, v, FcTrue);
}
FcValue v;
v.type = FcTypeCharSet;
- v.u.ci = FcCharSetPtrCreateDynamic((FcCharSet *)c);
+ v.u.c = (FcCharSet *)c;
return FcPatternAdd (p, object, v, FcTrue);
}
FcValue v;
v.type = FcTypeLangSet;
- v.u.li = FcLangSetPtrCreateDynamic((FcLangSet *)ls);
+ v.u.l = (FcLangSet *)ls;
return FcPatternAdd (p, object, v, FcTrue);
}
{
if (!id)
{
- *v = FcValueListPtrU(l)->value;
+ *v = FcValueCanonicalize(&FcValueListPtrU(l)->value);
return FcResultMatch;
}
id--;
return r;
if (v.type != FcTypeString)
return FcResultTypeMismatch;
- *s = (FcChar8 *) FcObjectPtrU(v.u.si);
+ *s = (FcChar8 *) v.u.s;
return FcResultMatch;
}
return r;
if (v.type != FcTypeMatrix)
return FcResultTypeMismatch;
- *m = FcMatrixPtrU(v.u.mi);
+ *m = (FcMatrix *)v.u.m;
return FcResultMatch;
}
return r;
if (v.type != FcTypeCharSet)
return FcResultTypeMismatch;
- *c = FcCharSetPtrU(v.u.ci);
+ *c = (FcCharSet *)v.u.c;
return FcResultMatch;
}
return r;
if (v.type != FcTypeLangSet)
return FcResultTypeMismatch;
- *ls = FcLangSetPtrU(v.u.li);
+ *ls = (FcLangSet *)v.u.l;
return FcResultMatch;
}
v = FcValueListPtrU(v)->next)
{
if (!FcPatternAddWithBinding (p, FcObjectPtrU(e->object),
- FcValueListPtrU(v)->value,
+ FcValueCanonicalize(&FcValueListPtrU(v)->value),
FcValueListPtrU(v)->binding, FcTrue))
return FcFalse;
}
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;
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 (;
if (FcValueListPtrU(FcValueListPtrU(v)->next))
{
nvp = FcValueListSerialize
- (FcValueListPtrU(FcValueListPtrU(v)->next));
+ (bank, FcValueListPtrU(FcValueListPtrU(v)->next));
nv->next = nvp;
}
}
}
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:
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
{
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 ();
-}
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
-#include <sys/mman.h>
#include "fcint.h"
FcChar8 *
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)
{
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 *));
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;
}
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;
}
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;
}
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;
{
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)
{
{
if (list->n >= list->set->num)
return 0;
- return FcStrSetGet(list->set, list->n++);
+ return list->set->strs[list->n++];
}
void
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:
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:
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);