abstract hash table functions
This commit is contained in:
parent
68ff99c414
commit
8f88b1c47c
|
@ -140,6 +140,7 @@ libfontconfig_la_SOURCES = \
|
||||||
fcfreetype.c \
|
fcfreetype.c \
|
||||||
fcfs.c \
|
fcfs.c \
|
||||||
fcptrlist.c \
|
fcptrlist.c \
|
||||||
|
fchash.c \
|
||||||
fcinit.c \
|
fcinit.c \
|
||||||
fclang.c \
|
fclang.c \
|
||||||
fclist.c \
|
fclist.c \
|
||||||
|
|
241
src/fccache.c
241
src/fccache.c
|
@ -44,92 +44,10 @@
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FC_UUID_HASH_SIZE 4099
|
|
||||||
|
|
||||||
typedef struct _FcUuidBucket {
|
|
||||||
struct _FcUuidBucket *next;
|
|
||||||
FcChar8 *file;
|
|
||||||
uuid_t uuid;
|
|
||||||
} FcUuidBucket;
|
|
||||||
|
|
||||||
typedef struct _FcUuidHashTable {
|
|
||||||
FcUuidBucket *buckets[FC_UUID_HASH_SIZE];
|
|
||||||
} FcUuidHashTable;
|
|
||||||
|
|
||||||
static FcUuidHashTable uuid_table;
|
|
||||||
|
|
||||||
static FcBool
|
|
||||||
FcCacheUuidAdd (FcUuidHashTable *table,
|
|
||||||
const FcChar8 *file,
|
|
||||||
uuid_t uuid)
|
|
||||||
{
|
|
||||||
FcUuidBucket **prev, *bucket;
|
|
||||||
FcChar32 hash = FcStrHashIgnoreCase (file);
|
|
||||||
|
|
||||||
for (prev = &table->buckets[hash % FC_UUID_HASH_SIZE];
|
|
||||||
(bucket = *prev); prev = &(bucket->next))
|
|
||||||
{
|
|
||||||
if (FcStrCmp (bucket->file, file) == 0)
|
|
||||||
return FcTrue;
|
|
||||||
}
|
|
||||||
bucket = (FcUuidBucket *) malloc (sizeof (FcUuidBucket));
|
|
||||||
if (!bucket)
|
|
||||||
return FcFalse;
|
|
||||||
bucket->next = NULL;
|
|
||||||
bucket->file = FcStrdup (file);
|
|
||||||
uuid_copy (bucket->uuid, uuid);
|
|
||||||
if (!bucket->file)
|
|
||||||
{
|
|
||||||
free (bucket);
|
|
||||||
return FcFalse;
|
|
||||||
}
|
|
||||||
*prev = bucket;
|
|
||||||
|
|
||||||
return FcTrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
FcCacheUuidDestroy (FcUuidHashTable *table)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < FC_UUID_HASH_SIZE; i++)
|
|
||||||
{
|
|
||||||
FcUuidBucket *bucket = table->buckets[i], *prev;
|
|
||||||
|
|
||||||
while (bucket)
|
|
||||||
{
|
|
||||||
FcStrFree (bucket->file);
|
|
||||||
prev = bucket;
|
|
||||||
bucket = bucket->next;
|
|
||||||
free (prev);
|
|
||||||
}
|
|
||||||
table->buckets[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FcBool
|
|
||||||
FcCacheUuidFind (FcUuidHashTable *table,
|
|
||||||
const FcChar8 *file,
|
|
||||||
uuid_t ret)
|
|
||||||
{
|
|
||||||
FcUuidBucket *bucket;
|
|
||||||
FcChar32 hash = FcStrHashIgnoreCase (file);
|
|
||||||
|
|
||||||
for (bucket = table->buckets[hash % FC_UUID_HASH_SIZE]; bucket; bucket = bucket->next)
|
|
||||||
{
|
|
||||||
if (FcStrCmp (bucket->file, file) == 0)
|
|
||||||
{
|
|
||||||
uuid_copy (ret, bucket->uuid);
|
|
||||||
return FcTrue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FcFalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcDirCacheCreateUUID (const FcChar8 *dir,
|
FcDirCacheCreateUUID (FcChar8 *dir,
|
||||||
FcBool force)
|
FcBool force,
|
||||||
|
FcConfig *config)
|
||||||
{
|
{
|
||||||
FcBool ret = FcTrue;
|
FcBool ret = FcTrue;
|
||||||
FcChar8 *uuidname;
|
FcChar8 *uuidname;
|
||||||
|
@ -163,7 +81,11 @@ FcDirCacheCreateUUID (const FcChar8 *dir,
|
||||||
goto bail3;
|
goto bail3;
|
||||||
}
|
}
|
||||||
uuid_generate_random (uuid);
|
uuid_generate_random (uuid);
|
||||||
FcCacheUuidAdd (&uuid_table, dir, uuid);
|
if (!FcHashTableAdd (config->uuid_table, dir, uuid))
|
||||||
|
{
|
||||||
|
ret = FcFalse;
|
||||||
|
goto bail3;
|
||||||
|
}
|
||||||
uuid_unparse (uuid, out);
|
uuid_unparse (uuid, out);
|
||||||
if (FcDebug () & FC_DBG_CACHE)
|
if (FcDebug () & FC_DBG_CACHE)
|
||||||
printf ("FcDirCacheCreateUUID %s: %s\n", uuidname, out);
|
printf ("FcDirCacheCreateUUID %s: %s\n", uuidname, out);
|
||||||
|
@ -182,11 +104,13 @@ FcDirCacheCreateUUID (const FcChar8 *dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FcDirCacheReadUUID (const FcChar8 *dir)
|
FcDirCacheReadUUID (FcChar8 *dir,
|
||||||
|
FcConfig *config)
|
||||||
{
|
{
|
||||||
|
void *u;
|
||||||
uuid_t uuid;
|
uuid_t uuid;
|
||||||
|
|
||||||
if (!FcCacheUuidFind (&uuid_table, dir, uuid))
|
if (!FcHashTableFind (config->uuid_table, dir, &u))
|
||||||
{
|
{
|
||||||
FcChar8 *uuidname = FcStrBuildFilename (dir, ".uuid", NULL);
|
FcChar8 *uuidname = FcStrBuildFilename (dir, ".uuid", NULL);
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -203,7 +127,7 @@ FcDirCacheReadUUID (const FcChar8 *dir)
|
||||||
{
|
{
|
||||||
if (FcDebug () & FC_DBG_CACHE)
|
if (FcDebug () & FC_DBG_CACHE)
|
||||||
printf ("FcDirCacheReadUUID %s -> %s\n", uuidname, suuid);
|
printf ("FcDirCacheReadUUID %s -> %s\n", uuidname, suuid);
|
||||||
FcCacheUuidAdd (&uuid_table, dir, uuid);
|
FcHashTableAdd (config->uuid_table, dir, uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close (fd);
|
close (fd);
|
||||||
|
@ -215,111 +139,8 @@ FcDirCacheReadUUID (const FcChar8 *dir)
|
||||||
}
|
}
|
||||||
FcStrFree (uuidname);
|
FcStrFree (uuidname);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
FcHashUuidFree (u);
|
||||||
#define FC_ALIAS_HASH_SIZE 4099
|
|
||||||
|
|
||||||
typedef struct _FcAliasBucket {
|
|
||||||
struct _FcAliasBucket *next;
|
|
||||||
FcChar8 *orig;
|
|
||||||
FcChar8 *alias;
|
|
||||||
} FcAliasBucket;
|
|
||||||
|
|
||||||
typedef struct _FcAliasHashTable {
|
|
||||||
FcAliasBucket *buckets[FC_ALIAS_HASH_SIZE];
|
|
||||||
} FcAliasHashTable;
|
|
||||||
|
|
||||||
static FcAliasHashTable alias_table;
|
|
||||||
|
|
||||||
static FcBool
|
|
||||||
FcCacheAliasAdd (FcAliasHashTable *table,
|
|
||||||
const FcChar8 *orig,
|
|
||||||
const FcChar8 *alias)
|
|
||||||
{
|
|
||||||
FcAliasBucket **prev, *bucket;
|
|
||||||
FcChar32 hash = FcStrHashIgnoreCase (orig);
|
|
||||||
|
|
||||||
for (prev = &table->buckets[hash % FC_ALIAS_HASH_SIZE];
|
|
||||||
(bucket = *prev); prev = &(bucket->next))
|
|
||||||
{
|
|
||||||
if (FcStrCmp (bucket->orig, orig) == 0)
|
|
||||||
return FcTrue;
|
|
||||||
}
|
|
||||||
bucket = (FcAliasBucket *) malloc (sizeof (FcAliasBucket));
|
|
||||||
if (!bucket)
|
|
||||||
return FcFalse;
|
|
||||||
bucket->next = NULL;
|
|
||||||
bucket->orig = FcStrdup (orig);
|
|
||||||
bucket->alias = FcStrdup (alias);
|
|
||||||
if (!bucket->orig || !bucket->alias)
|
|
||||||
{
|
|
||||||
if (bucket->orig)
|
|
||||||
FcStrFree (bucket->orig);
|
|
||||||
if (bucket->alias)
|
|
||||||
FcStrFree (bucket->alias);
|
|
||||||
free (bucket);
|
|
||||||
return FcFalse;
|
|
||||||
}
|
|
||||||
*prev = bucket;
|
|
||||||
|
|
||||||
return FcTrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
FcCacheAliasDestroy (FcAliasHashTable *table)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < FC_ALIAS_HASH_SIZE; i++)
|
|
||||||
{
|
|
||||||
FcAliasBucket *bucket = table->buckets[i], *prev;
|
|
||||||
|
|
||||||
while (bucket)
|
|
||||||
{
|
|
||||||
prev = bucket;
|
|
||||||
FcStrFree (bucket->orig);
|
|
||||||
FcStrFree (bucket->alias);
|
|
||||||
bucket = bucket->next;
|
|
||||||
free (prev);
|
|
||||||
}
|
|
||||||
table->buckets[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FcBool
|
|
||||||
FcCacheAliasFind (FcAliasHashTable *table,
|
|
||||||
const FcChar8 *orig,
|
|
||||||
const FcChar8 **ret)
|
|
||||||
{
|
|
||||||
FcAliasBucket *bucket;
|
|
||||||
FcChar32 hash = FcStrHashIgnoreCase (orig);
|
|
||||||
|
|
||||||
for (bucket = table->buckets[hash % FC_ALIAS_HASH_SIZE]; bucket; bucket = bucket->next)
|
|
||||||
{
|
|
||||||
if (FcStrCmp (bucket->orig, orig) == 0)
|
|
||||||
{
|
|
||||||
*ret = bucket->alias;
|
|
||||||
return FcTrue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FcFalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
FcDirCacheAddAliasPath (const FcChar8 *orig,
|
|
||||||
const FcChar8 *alias)
|
|
||||||
{
|
|
||||||
FcCacheAliasAdd (&alias_table, orig, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FcChar8 *
|
|
||||||
FcDirCacheFindAliasPath (const FcChar8 *dir)
|
|
||||||
{
|
|
||||||
const FcChar8 *ret = NULL;
|
|
||||||
|
|
||||||
if (FcCacheAliasFind (&alias_table, dir, &ret))
|
|
||||||
return ret;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MD5Context {
|
struct MD5Context {
|
||||||
|
@ -398,20 +219,21 @@ FcDirCacheBasenameMD5 (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcChar8 *
|
static FcChar8 *
|
||||||
FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
|
FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN], FcConfig *config)
|
||||||
{
|
{
|
||||||
uuid_t uuid;
|
uuid_t uuid;
|
||||||
const FcChar8 *alias;
|
FcChar8 *alias;
|
||||||
|
|
||||||
alias = FcDirCacheFindAliasPath (dir);
|
if (!FcHashTableFind (config->alias_table, dir, (void **)&alias))
|
||||||
if (!alias)
|
alias = FcStrdup (dir);
|
||||||
alias = dir;
|
if (FcHashTableFind (config->uuid_table, alias, (void **)&uuid))
|
||||||
if (FcCacheUuidFind (&uuid_table, alias, uuid))
|
|
||||||
{
|
{
|
||||||
uuid_unparse (uuid, (char *) cache_base);
|
uuid_unparse (uuid, (char *) cache_base);
|
||||||
strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
|
strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
|
||||||
|
FcStrFree (alias);
|
||||||
return cache_base;
|
return cache_base;
|
||||||
}
|
}
|
||||||
|
FcStrFree (alias);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +246,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
||||||
FcChar8 *cache_dir;
|
FcChar8 *cache_dir;
|
||||||
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
|
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
|
||||||
|
|
||||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||||
|
|
||||||
list = FcStrListCreate (config->cacheDirs);
|
list = FcStrListCreate (config->cacheDirs);
|
||||||
|
@ -501,7 +323,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
|
||||||
}
|
}
|
||||||
FcStrFree (d);
|
FcStrFree (d);
|
||||||
|
|
||||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||||
|
|
||||||
list = FcStrListCreate (config->cacheDirs);
|
list = FcStrListCreate (config->cacheDirs);
|
||||||
|
@ -832,14 +654,7 @@ FcCacheObjectDereference (void *object)
|
||||||
if (skip)
|
if (skip)
|
||||||
{
|
{
|
||||||
if (FcRefDec (&skip->ref) == 1)
|
if (FcRefDec (&skip->ref) == 1)
|
||||||
{
|
|
||||||
FcDirCacheDisposeUnlocked (skip->cache);
|
FcDirCacheDisposeUnlocked (skip->cache);
|
||||||
if (fcCacheMaxLevel == 0)
|
|
||||||
{
|
|
||||||
FcCacheUuidDestroy (&uuid_table);
|
|
||||||
FcCacheAliasDestroy (&alias_table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unlock_cache ();
|
unlock_cache ();
|
||||||
}
|
}
|
||||||
|
@ -1099,7 +914,7 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
||||||
FcCache *cache = NULL;
|
FcCache *cache = NULL;
|
||||||
const FcChar8 *d;
|
const FcChar8 *d;
|
||||||
|
|
||||||
FcDirCacheReadUUID (dir);
|
FcDirCacheReadUUID ((FcChar8 *) dir, config);
|
||||||
if (!FcDirCacheProcess (config, dir,
|
if (!FcDirCacheProcess (config, dir,
|
||||||
FcDirCacheMapHelper,
|
FcDirCacheMapHelper,
|
||||||
&cache, cache_file))
|
&cache, cache_file))
|
||||||
|
@ -1107,7 +922,7 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
||||||
|
|
||||||
d = FcCacheDir (cache);
|
d = FcCacheDir (cache);
|
||||||
if (FcStrCmp (dir, d))
|
if (FcStrCmp (dir, d))
|
||||||
FcDirCacheAddAliasPath (d, dir);
|
FcHashTableAdd (config->alias_table, (FcChar8 *) d, (FcChar8 *) dir);
|
||||||
|
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
@ -1360,7 +1175,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
|
||||||
if (!cache_dir)
|
if (!cache_dir)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
|
|
||||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||||
cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
|
cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
|
||||||
if (!cache_hashed)
|
if (!cache_hashed)
|
||||||
|
@ -1558,7 +1373,7 @@ FcDirCacheLock (const FcChar8 *dir,
|
||||||
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
|
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||||
list = FcStrListCreate (config->cacheDirs);
|
list = FcStrListCreate (config->cacheDirs);
|
||||||
if (!list)
|
if (!list)
|
||||||
|
|
21
src/fccfg.c
21
src/fccfg.c
|
@ -151,6 +151,19 @@ FcConfigCreate (void)
|
||||||
if (!config->availConfigFiles)
|
if (!config->availConfigFiles)
|
||||||
goto bail10;
|
goto bail10;
|
||||||
|
|
||||||
|
config->uuid_table = FcHashTableCreate ((FcHashFunc) FcStrHashIgnoreCase,
|
||||||
|
(FcCompareFunc) FcStrCmp,
|
||||||
|
FcHashStrCopy,
|
||||||
|
FcHashUuidCopy,
|
||||||
|
(FcDestroyFunc) FcStrFree,
|
||||||
|
FcHashUuidFree);
|
||||||
|
config->alias_table = FcHashTableCreate ((FcHashFunc) FcStrHashIgnoreCase,
|
||||||
|
(FcCompareFunc) FcStrCmp,
|
||||||
|
FcHashStrCopy,
|
||||||
|
FcHashStrCopy,
|
||||||
|
(FcDestroyFunc) FcStrFree,
|
||||||
|
(FcDestroyFunc) FcStrFree);
|
||||||
|
|
||||||
FcRefInit (&config->ref, 1);
|
FcRefInit (&config->ref, 1);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
@ -312,6 +325,9 @@ FcConfigDestroy (FcConfig *config)
|
||||||
if (config->sysRoot)
|
if (config->sysRoot)
|
||||||
FcStrFree (config->sysRoot);
|
FcStrFree (config->sysRoot);
|
||||||
|
|
||||||
|
FcHashTableDestroy (config->uuid_table);
|
||||||
|
FcHashTableDestroy (config->alias_table);
|
||||||
|
|
||||||
free (config);
|
free (config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,14 +387,15 @@ FcConfigAddCache (FcConfig *config, FcCache *cache,
|
||||||
for (i = 0; i < cache->dirs_count; i++)
|
for (i = 0; i < cache->dirs_count; i++)
|
||||||
{
|
{
|
||||||
const FcChar8 *dir = FcCacheSubdir (cache, i);
|
const FcChar8 *dir = FcCacheSubdir (cache, i);
|
||||||
const FcChar8 *alias;
|
FcChar8 *alias;
|
||||||
FcChar8 *d = FcStrDirname (dir);
|
FcChar8 *d = FcStrDirname (dir);
|
||||||
FcChar8 *s = NULL;
|
FcChar8 *s = NULL;
|
||||||
|
|
||||||
if ((alias = FcDirCacheFindAliasPath (d)))
|
if (FcHashTableFind (config->alias_table, d, (void **)&alias))
|
||||||
{
|
{
|
||||||
FcChar8 *base = FcStrBasename (dir);
|
FcChar8 *base = FcStrBasename (dir);
|
||||||
dir = s = FcStrBuildFilename (alias, base, NULL);
|
dir = s = FcStrBuildFilename (alias, base, NULL);
|
||||||
|
FcStrFree (alias);
|
||||||
FcStrFree (base);
|
FcStrFree (base);
|
||||||
}
|
}
|
||||||
FcStrFree (d);
|
FcStrFree (d);
|
||||||
|
|
|
@ -409,7 +409,7 @@ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
|
||||||
{
|
{
|
||||||
FcCache *cache = NULL;
|
FcCache *cache = NULL;
|
||||||
|
|
||||||
FcDirCacheCreateUUID (dir, force);
|
FcDirCacheCreateUUID ((FcChar8 *) dir, force, config);
|
||||||
/* Try to use existing cache file */
|
/* Try to use existing cache file */
|
||||||
if (!force)
|
if (!force)
|
||||||
cache = FcDirCacheLoad (dir, config, NULL);
|
cache = FcDirCacheLoad (dir, config, NULL);
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2000 Keith Packard
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of the author(s) not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the software without
|
||||||
|
* specific, written prior permission. The authors make no
|
||||||
|
* representations about the suitability of this software for any purpose. It
|
||||||
|
* is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "fcint.h"
|
||||||
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
|
#define FC_HASH_SIZE 4099
|
||||||
|
|
||||||
|
typedef struct _FcHashBucket {
|
||||||
|
struct _FcHashBucket *next;
|
||||||
|
void *key;
|
||||||
|
void *value;
|
||||||
|
} FcHashBucket;
|
||||||
|
|
||||||
|
struct _FcHashTable {
|
||||||
|
FcHashBucket *buckets[FC_HASH_SIZE];
|
||||||
|
FcHashFunc hash_func;
|
||||||
|
FcCompareFunc compare_func;
|
||||||
|
FcCopyFunc key_copy_func;
|
||||||
|
FcCopyFunc value_copy_func;
|
||||||
|
FcDestroyFunc key_destroy_func;
|
||||||
|
FcDestroyFunc value_destroy_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcHashStrCopy (const void *src,
|
||||||
|
void **dest)
|
||||||
|
{
|
||||||
|
*dest = FcStrdup (src);
|
||||||
|
|
||||||
|
return *dest != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcHashUuidCopy (const void *src,
|
||||||
|
void **dest)
|
||||||
|
{
|
||||||
|
*dest = malloc (sizeof (uuid_t));
|
||||||
|
uuid_copy (*dest, src);
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FcHashUuidFree (void *data)
|
||||||
|
{
|
||||||
|
free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
FcHashTable *
|
||||||
|
FcHashTableCreate (FcHashFunc hash_func,
|
||||||
|
FcCompareFunc compare_func,
|
||||||
|
FcCopyFunc key_copy_func,
|
||||||
|
FcCopyFunc value_copy_func,
|
||||||
|
FcDestroyFunc key_destroy_func,
|
||||||
|
FcDestroyFunc value_destroy_func)
|
||||||
|
{
|
||||||
|
FcHashTable *ret = malloc (sizeof (FcHashTable));
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
memset (ret->buckets, 0, sizeof (FcHashBucket *) * FC_HASH_SIZE);
|
||||||
|
ret->hash_func = hash_func;
|
||||||
|
ret->compare_func = compare_func;
|
||||||
|
ret->key_copy_func = key_copy_func;
|
||||||
|
ret->value_copy_func = value_copy_func;
|
||||||
|
ret->key_destroy_func = key_destroy_func;
|
||||||
|
ret->value_destroy_func = value_destroy_func;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FcHashTableDestroy (FcHashTable *table)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < FC_HASH_SIZE; i++)
|
||||||
|
{
|
||||||
|
FcHashBucket *bucket = table->buckets[i], *prev;
|
||||||
|
|
||||||
|
while (bucket)
|
||||||
|
{
|
||||||
|
if (table->key_destroy_func)
|
||||||
|
table->key_destroy_func (bucket->key);
|
||||||
|
if (table->value_destroy_func)
|
||||||
|
table->value_destroy_func (bucket->value);
|
||||||
|
prev = bucket;
|
||||||
|
bucket = bucket->next;
|
||||||
|
free (prev);
|
||||||
|
}
|
||||||
|
table->buckets[i] = NULL;
|
||||||
|
}
|
||||||
|
free (table);
|
||||||
|
}
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcHashTableFind (FcHashTable *table,
|
||||||
|
const void *key,
|
||||||
|
void **value)
|
||||||
|
{
|
||||||
|
FcHashBucket *bucket;
|
||||||
|
FcChar32 hash = table->hash_func (key);
|
||||||
|
|
||||||
|
for (bucket = table->buckets[hash % FC_HASH_SIZE]; bucket; bucket = bucket->next)
|
||||||
|
{
|
||||||
|
if (!table->compare_func(bucket->key, key))
|
||||||
|
{
|
||||||
|
if (table->value_copy_func)
|
||||||
|
{
|
||||||
|
if (!table->value_copy_func (bucket->value, value))
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*value = bucket->value;
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
FcBool
|
||||||
|
FcHashTableAdd (FcHashTable *table,
|
||||||
|
void *key,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
FcHashBucket **prev, *bucket, *b;
|
||||||
|
FcChar32 hash = table->hash_func (key);
|
||||||
|
FcBool ret = FcFalse;
|
||||||
|
|
||||||
|
bucket = (FcHashBucket *) malloc (sizeof (FcHashBucket));
|
||||||
|
if (!bucket)
|
||||||
|
return FcFalse;
|
||||||
|
memset (bucket, 0, sizeof (FcHashBucket));
|
||||||
|
if (table->key_copy_func)
|
||||||
|
ret |= !table->key_copy_func (key, &bucket->key);
|
||||||
|
else
|
||||||
|
bucket->key = key;
|
||||||
|
if (table->value_copy_func)
|
||||||
|
ret |= !table->value_copy_func (value, &bucket->value);
|
||||||
|
else
|
||||||
|
bucket->value = value;
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
destroy:
|
||||||
|
if (bucket->key && table->key_destroy_func)
|
||||||
|
table->key_destroy_func (bucket->key);
|
||||||
|
if (bucket->value && table->value_destroy_func)
|
||||||
|
table->value_destroy_func (bucket->value);
|
||||||
|
free (bucket);
|
||||||
|
|
||||||
|
return !ret;
|
||||||
|
}
|
||||||
|
for (prev = &table->buckets[hash & FC_HASH_SIZE];
|
||||||
|
(b = *prev); prev = &(b->next))
|
||||||
|
{
|
||||||
|
if (!table->compare_func (bucket->key, key))
|
||||||
|
goto destroy;
|
||||||
|
}
|
||||||
|
*prev = bucket;
|
||||||
|
|
||||||
|
return FcTrue;
|
||||||
|
}
|
51
src/fcint.h
51
src/fcint.h
|
@ -392,6 +392,13 @@ typedef struct _FcStrBuf {
|
||||||
FcChar8 buf_static[16 * sizeof (void *)];
|
FcChar8 buf_static[16 * sizeof (void *)];
|
||||||
} FcStrBuf;
|
} FcStrBuf;
|
||||||
|
|
||||||
|
typedef struct _FcHashTable FcHashTable;
|
||||||
|
|
||||||
|
typedef FcChar32 (* FcHashFunc) (const void *data);
|
||||||
|
typedef int (* FcCompareFunc) (const void *v1, const void *v2);
|
||||||
|
typedef FcBool (* FcCopyFunc) (const void *src, void **dest);
|
||||||
|
|
||||||
|
|
||||||
struct _FcCache {
|
struct _FcCache {
|
||||||
unsigned int magic; /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
|
unsigned int magic; /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
|
||||||
int version; /* FC_CACHE_VERSION_NUMBER */
|
int version; /* FC_CACHE_VERSION_NUMBER */
|
||||||
|
@ -558,6 +565,8 @@ struct _FcConfig {
|
||||||
FcChar8 *sysRoot; /* override the system root directory */
|
FcChar8 *sysRoot; /* override the system root directory */
|
||||||
FcStrSet *availConfigFiles; /* config files available */
|
FcStrSet *availConfigFiles; /* config files available */
|
||||||
FcPtrList *rulesetList; /* List of rulesets being installed */
|
FcPtrList *rulesetList; /* List of rulesets being installed */
|
||||||
|
FcHashTable *uuid_table; /* UUID table for cachedirs */
|
||||||
|
FcHashTable *alias_table; /* alias table for cachedirs */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _FcFileTime {
|
typedef struct _FcFileTime {
|
||||||
|
@ -588,11 +597,9 @@ struct _FcValuePromotionBuffer {
|
||||||
/* fccache.c */
|
/* fccache.c */
|
||||||
|
|
||||||
FcPrivate FcBool
|
FcPrivate FcBool
|
||||||
FcDirCacheCreateUUID (const FcChar8 *dir,
|
FcDirCacheCreateUUID (FcChar8 *dir,
|
||||||
FcBool force);
|
FcBool force,
|
||||||
|
FcConfig *config);
|
||||||
FcPrivate const FcChar8 *
|
|
||||||
FcDirCacheFindAliasPath (const FcChar8 *dir);
|
|
||||||
|
|
||||||
FcPrivate FcCache *
|
FcPrivate FcCache *
|
||||||
FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
|
FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
|
||||||
|
@ -1300,4 +1307,38 @@ FcObjectLookupOtherTypeById (FcObject id);
|
||||||
FcPrivate const FcObjectType *
|
FcPrivate const FcObjectType *
|
||||||
FcObjectLookupOtherTypeByName (const char *str);
|
FcObjectLookupOtherTypeByName (const char *str);
|
||||||
|
|
||||||
|
/* fchash.c */
|
||||||
|
FcPrivate FcBool
|
||||||
|
FcHashStrCopy (const void *src,
|
||||||
|
void **dest);
|
||||||
|
|
||||||
|
FcPrivate FcBool
|
||||||
|
FcHashUuidCopy (const void *src,
|
||||||
|
void **dest);
|
||||||
|
|
||||||
|
FcPrivate void
|
||||||
|
FcHashUuidFree (void *data);
|
||||||
|
|
||||||
|
FcPrivate FcHashTable *
|
||||||
|
FcHashTableCreate (FcHashFunc hash_func,
|
||||||
|
FcCompareFunc compare_func,
|
||||||
|
FcCopyFunc key_copy_func,
|
||||||
|
FcCopyFunc value_copy_func,
|
||||||
|
FcDestroyFunc key_destroy_func,
|
||||||
|
FcDestroyFunc value_destroy_func);
|
||||||
|
|
||||||
|
FcPrivate void
|
||||||
|
FcHashTableDestroy (FcHashTable *table);
|
||||||
|
|
||||||
|
FcPrivate FcBool
|
||||||
|
FcHashTableFind (FcHashTable *table,
|
||||||
|
const void *key,
|
||||||
|
void **value);
|
||||||
|
|
||||||
|
FcPrivate FcBool
|
||||||
|
FcHashTableAdd (FcHashTable *table,
|
||||||
|
void *key,
|
||||||
|
void *value);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _FC_INT_H_ */
|
#endif /* _FC_INT_H_ */
|
||||||
|
|
|
@ -458,14 +458,16 @@ FcListAppend (FcListHashTable *table,
|
||||||
if (FcStat (FcValueString (&v->value), &statb) < 0)
|
if (FcStat (FcValueString (&v->value), &statb) < 0)
|
||||||
{
|
{
|
||||||
FcChar8 *dir = FcStrDirname (FcValueString (&v->value));
|
FcChar8 *dir = FcStrDirname (FcValueString (&v->value));
|
||||||
const FcChar8 *alias;
|
FcChar8 *alias;
|
||||||
|
FcConfig *config = FcConfigGetCurrent (); /* FIXME: this may need to be exported as API? */
|
||||||
|
|
||||||
if ((alias = FcDirCacheFindAliasPath (dir)))
|
if (FcHashTableFind (config->alias_table, dir, (void **) &alias))
|
||||||
{
|
{
|
||||||
FcChar8 *base = FcStrBasename (FcValueString (&v->value));
|
FcChar8 *base = FcStrBasename (FcValueString (&v->value));
|
||||||
FcChar8 *s = FcStrBuildFilename (alias, base, NULL);
|
FcChar8 *s = FcStrBuildFilename (alias, base, NULL);
|
||||||
FcValue vv;
|
FcValue vv;
|
||||||
|
|
||||||
|
FcStrFree (alias);
|
||||||
FcStrFree (base);
|
FcStrFree (base);
|
||||||
vv.type = FcTypeString;
|
vv.type = FcTypeString;
|
||||||
vv.u.s = s;
|
vv.u.s = s;
|
||||||
|
|
|
@ -653,14 +653,15 @@ FcFontRenderPrepare (FcConfig *config,
|
||||||
if (FcStat (FcValueString (&l->value), &statb) < 0)
|
if (FcStat (FcValueString (&l->value), &statb) < 0)
|
||||||
{
|
{
|
||||||
FcChar8 *dir = FcStrDirname (FcValueString (&l->value));
|
FcChar8 *dir = FcStrDirname (FcValueString (&l->value));
|
||||||
const FcChar8 *alias;
|
FcChar8 *alias;
|
||||||
|
|
||||||
if ((alias = FcDirCacheFindAliasPath (dir)))
|
if (FcHashTableFind (config->alias_table, dir, (void **) &alias))
|
||||||
{
|
{
|
||||||
FcChar8 *base = FcStrBasename (FcValueString (&l->value));
|
FcChar8 *base = FcStrBasename (FcValueString (&l->value));
|
||||||
FcChar8 *s = FcStrBuildFilename (alias, base, NULL);
|
FcChar8 *s = FcStrBuildFilename (alias, base, NULL);
|
||||||
FcValue v;
|
FcValue v;
|
||||||
|
|
||||||
|
FcStrFree (alias);
|
||||||
FcStrFree (base);
|
FcStrFree (base);
|
||||||
v.type = FcTypeString;
|
v.type = FcTypeString;
|
||||||
v.u.s = s;
|
v.u.s = s;
|
||||||
|
|
Loading…
Reference in New Issue