diff -ru fontconfig-2.1.pristine/src/fccache.c fontconfig-2.1/src/fccache.c --- fontconfig-2.1.pristine/src/fccache.c 2002-09-25 19:16:23.000000000 -0500 +++ fontconfig-2.1/src/fccache.c 2003-01-10 15:47:35.000000000 -0600 @@ -22,6 +22,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include +#include + #include "fcint.h" /* @@ -41,107 +46,127 @@ #define FC_DBG_CACHE_REF 1024 -static FcChar8 * -FcCacheReadString (FILE *f, FcChar8 *dest, int len) +/* + * All FcCacheRead* functions return a boolean indicating successful read + * set the target indicated by dest to, and modify the src* provided to + * point after the values they consumed + */ + +/* note that this is a zerocopy operation, and may modify src to handle quoting - dest will point inside the region owned by src */ +static FcBool +FcCacheReadString (FcChar8 **src, FcChar8 **dest) { int c; - FcBool escape; - FcChar8 *d; - int size; - int i; + FcChar8 *d,*s = *src; + FcBool quoted = FcFalse; - while ((c = GETC (f)) != EOF) + while ((c = *s++) != '\0') + { if (c == '"') + { + *dest = d = s; /* mark the start */ break; - if (c == EOF) - return FcFalse; - if (len == 0) - return FcFalse; - - size = len; - i = 0; - d = dest; - escape = FcFalse; - while ((c = GETC (f)) != EOF) - { - if (!escape) + } + } + if(c == '\0') + return FcFalse; // early end + + while ((c = *s++) != '\0') + { /* run a fastpath loop that does no copying until we encounter a quoted character - + * after that we have to do copying to avoid getting a 'hole' */ + if(c == '"') { - switch (c) { - case '"': - c = '\0'; - break; - case '\\': - escape = FcTrue; - continue; + *(s-1) = '\0'; /* replace the quote with a null terminator since this is now a sub-string */ + *src = s; + return FcTrue; + } + else if(c == '\\') + { + quoted = FcTrue; /* next char is quoted */ + d = s-1; /* update d, since we haven't been using it */ + break; /* fall to the next loop, which handles quoting */ + } + else if(c == '\0') + { + return FcFalse; + } + } + if(c == '\0') + return FcFalse; // early end + + while ((c = *s++) != '\0') + { /* copy of the above loop, but this one does handle quoted characters so it must track d separately */ + if(!quoted) + { + if(c == '\\') + quoted = FcTrue; + else if(c == '"') + { + *d++ = '\0'; + *src = s; + return FcTrue; } + else + *d++ = c; } - if (i == size) + else //if(quoted) { - FcChar8 *new = malloc (size * 2); /* freed in caller */ - if (!new) - break; - memcpy (new, d, size); - size *= 2; - if (d != dest) - free (d); - d = new; + *d++ = c; + quoted = FcFalse; } - d[i++] = c; - if (c == '\0') - return d; - escape = FcFalse; } - if (d != dest) - free (d); - return 0; + return FcFalse; } static FcBool -FcCacheReadUlong (FILE *f, unsigned long *dest) +FcCacheReadUlong (FcChar8 **src, unsigned long *dest) { unsigned long t; int c; + FcChar8 *s = *src; - while ((c = GETC (f)) != EOF) + while ((c = *s++) != '\0') { if (!isspace (c)) break; } - if (c == EOF) + if (c == '\0') return FcFalse; + t = 0; for (;;) { - if (c == EOF || isspace (c)) + if (c == '\0' || isspace (c)) break; if (!isdigit (c)) return FcFalse; t = t * 10 + (c - '0'); - c = GETC (f); + c = (c = *s++); } *dest = t; + *src = s; return FcTrue; } static FcBool -FcCacheReadInt (FILE *f, int *dest) +FcCacheReadInt (FcChar8 **src, int *dest) { unsigned long t; FcBool ret; - ret = FcCacheReadUlong (f, &t); + ret = FcCacheReadUlong (src, &t); if (ret) *dest = (int) t; return ret; } static FcBool -FcCacheReadTime (FILE *f, time_t *dest) +FcCacheReadTime (FcChar8 **src, time_t *dest) { unsigned long t; FcBool ret; - ret = FcCacheReadUlong (f, &t); + ret = FcCacheReadUlong (src, &t); if (ret) *dest = (time_t) t; return ret; @@ -681,34 +706,60 @@ free (cache); } -/* +static FcChar8 *FcCacheReadFile (const FcChar8 *cache_file) +{ + int fd; + struct stat fileInfo; + FcChar8 *data; + + fd = open((char *) cache_file, O_RDONLY); + if (fd < 0) + return NULL; + if (fstat(fd,&fileInfo) < 0) + return NULL; + data = malloc(fileInfo.st_size+1); + if (!data) + return NULL; + + if(read(fd,data,fileInfo.st_size) < 0) + { + free(data); + return NULL; + } + data[fileInfo.st_size] = '\0'; + return data; +} + + /* * Cache file syntax is quite simple: * * "file_name" id time "font_name" \n */ - + void FcGlobalCacheLoad (FcGlobalCache *cache, const FcChar8 *cache_file) { - FILE *f; - FcChar8 file_buf[8192], *file; + FcChar8 *file; int id; time_t time; - FcChar8 name_buf[8192], *name; + FcChar8 *name; FcGlobalCacheInfo *info; - f = fopen ((char *) cache_file, "r"); - if (!f) + FcChar8 *file_data,*src_ptr; + file_data = FcCacheReadFile(cache_file); + if (!file_data) return; cache->updated = FcFalse; file = 0; name = 0; - while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) && - FcCacheReadInt (f, &id) && - FcCacheReadTime (f, &time) && - (name = FcCacheReadString (f, name_buf, sizeof (name_buf)))) + + src_ptr = file_data; + while (FcCacheReadString (&src_ptr, &file) && + FcCacheReadInt (&src_ptr, &id) && + FcCacheReadTime (&src_ptr, &time) && + FcCacheReadString (&src_ptr, &name) ) { if (FcDebug () & FC_DBG_CACHEV) printf ("FcGlobalCacheLoad \"%s\" \"%20.20s\"\n", file, name); @@ -723,18 +774,10 @@ if (FcDebug () & FC_DBG_CACHE_REF) printf ("FcGlobalCacheLoad entry %d %s\n", cache->entries, file); - if (file != file_buf) - free (file); - if (name != name_buf) - free (name); file = 0; name = 0; } - if (file && file != file_buf) - free (file); - if (name && name != name_buf) - free (name); - fclose (f); + free (file_data); } FcBool @@ -904,8 +947,8 @@ FcChar8 *base; int id; int dir_len; - FcChar8 file_buf[8192], *file; - FcChar8 name_buf[8192], *name; + FcChar8 *file; + FcChar8 *name; FcBool ret = FcFalse; if (!cache_file) @@ -914,7 +957,11 @@ if (FcDebug () & FC_DBG_CACHE) printf ("FcDirCacheReadDir cache_file \"%s\"\n", cache_file); - f = fopen ((char *) cache_file, "r"); + FcChar8 *file_data,*src_ptr; + file_data = FcCacheReadFile(cache_file); + if (!file_data) + return; + if (!f) { if (FcDebug () & FC_DBG_CACHE) @@ -937,30 +984,22 @@ file = 0; name = 0; - while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) && - FcCacheReadInt (f, &id) && - (name = FcCacheReadString (f, name_buf, sizeof (name_buf)))) + src_ptr = file_data; + while (FcCacheReadString (&src_ptr, &file) && + FcCacheReadInt (&src_ptr, &id) && + FcCacheReadString (&src_ptr, &name)) { if (!FcCacheFontSetAdd (set, dirs, cache_file, dir_len, file, name)) - goto bail3; - if (file != file_buf) - free (file); - if (name != name_buf) - free (name); + goto bail2; file = name = 0; } if (FcDebug () & FC_DBG_CACHE) printf (" cache loaded\n"); ret = FcTrue; -bail3: - if (file && file != file_buf) - free (file); - if (name && name != name_buf) - free (name); bail2: - fclose (f); + free (file_data); bail1: FcStrFree (cache_file); bail0: