/*
- * $XFree86: xc/lib/fontconfig/src/fccache.c,v 1.7 2002/05/21 17:06:22 keithp Exp $
+ * $XFree86: xc/lib/fontconfig/src/fccache.c,v 1.12 2002/08/22 07:36:44 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
#include "fcint.h"
+/*
+ * POSIX has broken stdio so that getc must do thread-safe locking,
+ * this is a serious performance problem for applications doing large
+ * amounts of IO with getc (as is done here). If available, use
+ * the getc_unlocked varient instead.
+ */
+
+#if defined(getc_unlocked) || defined(_IO_getc_unlocked)
+#define GETC(f) getc_unlocked(f)
+#define PUTC(c,f) putc_unlocked(c,f)
+#else
+#define GETC(f) getc(f)
+#define PUTC(c,f) putc(c,f)
+#endif
+
#define FC_DBG_CACHE_REF 1024
static FcChar8 *
int size;
int i;
- while ((c = getc (f)) != EOF)
+ while ((c = GETC (f)) != EOF)
if (c == '"')
break;
if (c == EOF)
i = 0;
d = dest;
escape = FcFalse;
- while ((c = getc (f)) != EOF)
+ while ((c = GETC (f)) != EOF)
{
if (!escape)
{
}
if (i == size)
{
- FcChar8 *new = malloc (size * 2);
+ FcChar8 *new = malloc (size * 2); /* freed in caller */
if (!new)
break;
memcpy (new, d, size);
unsigned long t;
int c;
- while ((c = getc (f)) != EOF)
+ while ((c = GETC (f)) != EOF)
{
if (!isspace (c))
break;
if (!isdigit (c))
return FcFalse;
t = t * 10 + (c - '0');
- c = getc (f);
+ c = GETC (f);
}
*dest = t;
return FcTrue;
switch (c) {
case '"':
case '\\':
- if (putc ('\\', f) == EOF)
+ if (PUTC ('\\', f) == EOF)
return FcFalse;
/* fall through */
default:
- if (putc (c, f) == EOF)
+ if (PUTC (c, f) == EOF)
return FcFalse;
}
}
FcCacheWriteString (FILE *f, const FcChar8 *string)
{
- if (putc ('"', f) == EOF)
+ if (PUTC ('"', f) == EOF)
return FcFalse;
if (!FcCacheWriteChars (f, string))
return FcFalse;
- if (putc ('"', f) == EOF)
+ if (PUTC ('"', f) == EOF)
return FcFalse;
return FcTrue;
}
static FcBool
FcCacheWritePath (FILE *f, const FcChar8 *dir, const FcChar8 *file)
{
- if (putc ('"', f) == EOF)
+ if (PUTC ('"', f) == EOF)
return FcFalse;
if (dir)
if (!FcCacheWriteChars (f, dir))
return FcFalse;
if (dir && dir[strlen((const char *) dir) - 1] != '/')
- if (putc ('/', f) == EOF)
+ if (PUTC ('/', f) == EOF)
return FcFalse;
if (!FcCacheWriteChars (f, file))
return FcFalse;
- if (putc ('"', f) == EOF)
+ if (PUTC ('"', f) == EOF)
return FcFalse;
return FcTrue;
}
while (pow)
{
digit = temp / pow;
- if (putc ((char) digit + '0', f) == EOF)
+ if (PUTC ((char) digit + '0', f) == EOF)
return FcFalse;
temp = temp - pow * digit;
pow = pow / 10;
int len;
FcBool ret = FcFalse;
FcPattern *font;
+ FcPattern *frozen;
path = path_buf;
len = (dir_len + 1 + strlen ((const char *) file) + 1);
if (len > sizeof (path_buf))
{
- path = malloc (len);
+ path = malloc (len); /* freed down below */
if (!path)
return FcFalse;
}
{
if (FcDebug () & FC_DBG_CACHEV)
printf (" dir cache file \"%s\"\n", file);
- ret = (FcPatternAddString (font, FC_FILE, path) &&
- FcFontSetAdd (set, font));
- if (!ret)
- FcPatternDestroy (font);
+ ret = FcPatternAddString (font, FC_FILE, path);
+ if (ret)
+ {
+ frozen = FcPatternFreeze (font);
+ ret = (frozen != 0);
+ if (ret)
+ ret = FcFontSetAdd (set, frozen);
+ }
+ FcPatternDestroy (font);
}
}
if (path != path_buf) free (path);
d = malloc (sizeof (FcGlobalCacheDir) + len + 1);
if (!d)
return 0;
+ FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + len + 1);
d->next = *prev;
*prev = d;
d->info.hash = hash;
parent = FcGlobalCacheDirGet (cache, i.dir, i.dir_len, FcTrue);
if (!parent)
return 0;
- subdir = malloc (sizeof (FcGlobalCacheSubdir) +
- strlen ((const char *) i.base) + 1);
+ subdir = malloc (sizeof (FcGlobalCacheSubdir));
if (!subdir)
return 0;
- subdir->file = (FcChar8 *) (subdir + 1);
- strcpy ((char *) subdir->file, (const char *) i.base);
+ FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
+ subdir->ent = d;
subdir->next = parent->subdirs;
parent->subdirs = subdir;
return &d->info;
for (f = d->ents[h]; f; f = next)
{
next = f->next;
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
+ strlen ((char *) f->info.file) + 1 +
+ strlen ((char *) f->name) + 1);
free (f);
}
for (s = d->subdirs; s; s = nexts)
{
nexts = s->next;
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
free (s);
}
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + d->len + 1);
free (d);
}
}
for (subdir = d->subdirs; subdir; subdir = subdir->next)
{
+ FcFilePathInfo info = FcFilePathInfoGet (subdir->ent->info.file);
+
if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
- subdir->file, FC_FONT_FILE_DIR))
+ info.base, FC_FONT_FILE_DIR))
{
cache->broken = FcTrue;
return FcFalse;
}
+ FcGlobalCacheReferenced (cache, &subdir->ent->info);
}
FcGlobalCacheReferenced (cache, &d->info);
FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, i.dir,
i.dir_len, FcTrue);
FcGlobalCacheFile *f, **prev;
+ int size;
if (!d)
return 0;
if (f->info.referenced)
cache->referenced--;
*prev = f->next;
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
+ strlen ((char *) f->info.file) + 1 +
+ strlen ((char *) f->name) + 1);
free (f);
}
- f = malloc (sizeof (FcGlobalCacheFile) +
- strlen ((char *) i.base) + 1 +
- strlen ((char *) name) + 1);
+ size = (sizeof (FcGlobalCacheFile) +
+ strlen ((char *) i.base) + 1 +
+ strlen ((char *) name) + 1);
+ f = malloc (size);
if (!f)
return 0;
+ FcMemAlloc (FC_MEM_CACHE, size);
f->next = *prev;
*prev = f;
f->info.hash = i.base_hash;
cache = malloc (sizeof (FcGlobalCache));
if (!cache)
return 0;
+ FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCache));
for (h = 0; h < FC_GLOBAL_CACHE_DIR_HASH_SIZE; h++)
cache->ents[h] = 0;
cache->entries = 0;
cache->referenced = 0;
cache->updated = FcFalse;
+ cache->broken = FcFalse;
return cache;
}
FcGlobalCacheDirDestroy (d);
}
}
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCache));
free (cache);
}
continue;
if (!FcCacheWriteString (f, dir->info.file))
goto bail4;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail4;
if (!FcCacheWriteInt (f, 0))
goto bail4;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail4;
if (!FcCacheWriteTime (f, dir->info.time))
goto bail4;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail4;
if (!FcCacheWriteString (f, (FcChar8 *) FC_FONT_FILE_DIR))
goto bail4;
- if (putc ('\n', f) == EOF)
+ if (PUTC ('\n', f) == EOF)
goto bail4;
for (file_hash = 0; file_hash < FC_GLOBAL_CACHE_FILE_HASH_SIZE; file_hash++)
continue;
if (!FcCacheWritePath (f, dir->info.file, file->info.file))
goto bail4;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail4;
if (!FcCacheWriteInt (f, file->id < 0 ? 0 : file->id))
goto bail4;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail4;
if (!FcCacheWriteTime (f, file->info.time))
goto bail4;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail4;
if (!FcCacheWriteString (f, file->name))
goto bail4;
- if (putc ('\n', f) == EOF)
+ if (PUTC ('\n', f) == EOF)
goto bail4;
}
}
bail2:
fclose (f);
bail1:
- free (cache_file);
+ FcStrFree (cache_file);
bail0:
return ret;
}
base = FcFileBaseName (cache_file, dir);
if (!FcCacheWriteString (f, base))
goto bail3;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail3;
if (!FcCacheWriteInt (f, 0))
goto bail3;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail3;
if (!FcCacheWriteString (f, FC_FONT_FILE_DIR))
goto bail3;
- if (putc ('\n', f) == EOF)
+ if (PUTC ('\n', f) == EOF)
goto bail3;
}
printf (" write file \"%s\"\n", base);
if (!FcCacheWriteString (f, base))
goto bail3;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail3;
if (!FcCacheWriteInt (f, id))
goto bail3;
- if (putc (' ', f) == EOF)
+ if (PUTC (' ', f) == EOF)
goto bail3;
name = FcNameUnparse (font);
if (!name)
goto bail3;
ret = FcCacheWriteString (f, name);
- free (name);
+ FcStrFree (name);
if (!ret)
goto bail3;
- if (putc ('\n', f) == EOF)
+ if (PUTC ('\n', f) == EOF)
goto bail3;
}
if (fclose (f) == EOF)
goto bail1;
- free (cache_file);
+ FcStrFree (cache_file);
if (FcDebug () & FC_DBG_CACHE)
printf (" cache written\n");
fclose (f);
bail1:
unlink ((char *) cache_file);
- free (cache_file);
+ FcStrFree (cache_file);
bail0:
return FcFalse;
}