abstract hash table functions
This commit is contained in:
parent
68ff99c414
commit
8f88b1c47c
|
@ -140,6 +140,7 @@ libfontconfig_la_SOURCES = \
|
|||
fcfreetype.c \
|
||||
fcfs.c \
|
||||
fcptrlist.c \
|
||||
fchash.c \
|
||||
fcinit.c \
|
||||
fclang.c \
|
||||
fclist.c \
|
||||
|
|
241
src/fccache.c
241
src/fccache.c
|
@ -44,92 +44,10 @@
|
|||
#define O_BINARY 0
|
||||
#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
|
||||
FcDirCacheCreateUUID (const FcChar8 *dir,
|
||||
FcBool force)
|
||||
FcDirCacheCreateUUID (FcChar8 *dir,
|
||||
FcBool force,
|
||||
FcConfig *config)
|
||||
{
|
||||
FcBool ret = FcTrue;
|
||||
FcChar8 *uuidname;
|
||||
|
@ -163,7 +81,11 @@ FcDirCacheCreateUUID (const FcChar8 *dir,
|
|||
goto bail3;
|
||||
}
|
||||
uuid_generate_random (uuid);
|
||||
FcCacheUuidAdd (&uuid_table, dir, uuid);
|
||||
if (!FcHashTableAdd (config->uuid_table, dir, uuid))
|
||||
{
|
||||
ret = FcFalse;
|
||||
goto bail3;
|
||||
}
|
||||
uuid_unparse (uuid, out);
|
||||
if (FcDebug () & FC_DBG_CACHE)
|
||||
printf ("FcDirCacheCreateUUID %s: %s\n", uuidname, out);
|
||||
|
@ -182,11 +104,13 @@ FcDirCacheCreateUUID (const FcChar8 *dir,
|
|||
}
|
||||
|
||||
static void
|
||||
FcDirCacheReadUUID (const FcChar8 *dir)
|
||||
FcDirCacheReadUUID (FcChar8 *dir,
|
||||
FcConfig *config)
|
||||
{
|
||||
void *u;
|
||||
uuid_t uuid;
|
||||
|
||||
if (!FcCacheUuidFind (&uuid_table, dir, uuid))
|
||||
if (!FcHashTableFind (config->uuid_table, dir, &u))
|
||||
{
|
||||
FcChar8 *uuidname = FcStrBuildFilename (dir, ".uuid", NULL);
|
||||
int fd;
|
||||
|
@ -203,7 +127,7 @@ FcDirCacheReadUUID (const FcChar8 *dir)
|
|||
{
|
||||
if (FcDebug () & FC_DBG_CACHE)
|
||||
printf ("FcDirCacheReadUUID %s -> %s\n", uuidname, suuid);
|
||||
FcCacheUuidAdd (&uuid_table, dir, uuid);
|
||||
FcHashTableAdd (config->uuid_table, dir, uuid);
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
|
@ -215,111 +139,8 @@ FcDirCacheReadUUID (const FcChar8 *dir)
|
|||
}
|
||||
FcStrFree (uuidname);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
else
|
||||
FcHashUuidFree (u);
|
||||
}
|
||||
|
||||
struct MD5Context {
|
||||
|
@ -398,20 +219,21 @@ FcDirCacheBasenameMD5 (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
|
|||
}
|
||||
|
||||
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;
|
||||
const FcChar8 *alias;
|
||||
FcChar8 *alias;
|
||||
|
||||
alias = FcDirCacheFindAliasPath (dir);
|
||||
if (!alias)
|
||||
alias = dir;
|
||||
if (FcCacheUuidFind (&uuid_table, alias, uuid))
|
||||
if (!FcHashTableFind (config->alias_table, dir, (void **)&alias))
|
||||
alias = FcStrdup (dir);
|
||||
if (FcHashTableFind (config->uuid_table, alias, (void **)&uuid))
|
||||
{
|
||||
uuid_unparse (uuid, (char *) cache_base);
|
||||
strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
|
||||
FcStrFree (alias);
|
||||
return cache_base;
|
||||
}
|
||||
FcStrFree (alias);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -424,7 +246,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
|||
FcChar8 *cache_dir;
|
||||
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
|
||||
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||
|
||||
list = FcStrListCreate (config->cacheDirs);
|
||||
|
@ -501,7 +323,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
|
|||
}
|
||||
FcStrFree (d);
|
||||
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||
|
||||
list = FcStrListCreate (config->cacheDirs);
|
||||
|
@ -832,14 +654,7 @@ FcCacheObjectDereference (void *object)
|
|||
if (skip)
|
||||
{
|
||||
if (FcRefDec (&skip->ref) == 1)
|
||||
{
|
||||
FcDirCacheDisposeUnlocked (skip->cache);
|
||||
if (fcCacheMaxLevel == 0)
|
||||
{
|
||||
FcCacheUuidDestroy (&uuid_table);
|
||||
FcCacheAliasDestroy (&alias_table);
|
||||
}
|
||||
}
|
||||
}
|
||||
unlock_cache ();
|
||||
}
|
||||
|
@ -1099,7 +914,7 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
|||
FcCache *cache = NULL;
|
||||
const FcChar8 *d;
|
||||
|
||||
FcDirCacheReadUUID (dir);
|
||||
FcDirCacheReadUUID ((FcChar8 *) dir, config);
|
||||
if (!FcDirCacheProcess (config, dir,
|
||||
FcDirCacheMapHelper,
|
||||
&cache, cache_file))
|
||||
|
@ -1107,7 +922,7 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
|||
|
||||
d = FcCacheDir (cache);
|
||||
if (FcStrCmp (dir, d))
|
||||
FcDirCacheAddAliasPath (d, dir);
|
||||
FcHashTableAdd (config->alias_table, (FcChar8 *) d, (FcChar8 *) dir);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
@ -1360,7 +1175,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
|
|||
if (!cache_dir)
|
||||
return FcFalse;
|
||||
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||
cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
|
||||
if (!cache_hashed)
|
||||
|
@ -1558,7 +1373,7 @@ FcDirCacheLock (const FcChar8 *dir,
|
|||
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
|
||||
int fd = -1;
|
||||
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base))
|
||||
if (!FcDirCacheBasenameUUID (dir, cache_base, config))
|
||||
FcDirCacheBasenameMD5 (dir, cache_base);
|
||||
list = FcStrListCreate (config->cacheDirs);
|
||||
if (!list)
|
||||
|
|
21
src/fccfg.c
21
src/fccfg.c
|
@ -151,6 +151,19 @@ FcConfigCreate (void)
|
|||
if (!config->availConfigFiles)
|
||||
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);
|
||||
|
||||
return config;
|
||||
|
@ -312,6 +325,9 @@ FcConfigDestroy (FcConfig *config)
|
|||
if (config->sysRoot)
|
||||
FcStrFree (config->sysRoot);
|
||||
|
||||
FcHashTableDestroy (config->uuid_table);
|
||||
FcHashTableDestroy (config->alias_table);
|
||||
|
||||
free (config);
|
||||
}
|
||||
|
||||
|
@ -371,14 +387,15 @@ FcConfigAddCache (FcConfig *config, FcCache *cache,
|
|||
for (i = 0; i < cache->dirs_count; i++)
|
||||
{
|
||||
const FcChar8 *dir = FcCacheSubdir (cache, i);
|
||||
const FcChar8 *alias;
|
||||
FcChar8 *alias;
|
||||
FcChar8 *d = FcStrDirname (dir);
|
||||
FcChar8 *s = NULL;
|
||||
|
||||
if ((alias = FcDirCacheFindAliasPath (d)))
|
||||
if (FcHashTableFind (config->alias_table, d, (void **)&alias))
|
||||
{
|
||||
FcChar8 *base = FcStrBasename (dir);
|
||||
dir = s = FcStrBuildFilename (alias, base, NULL);
|
||||
FcStrFree (alias);
|
||||
FcStrFree (base);
|
||||
}
|
||||
FcStrFree (d);
|
||||
|
|
|
@ -409,7 +409,7 @@ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
|
|||
{
|
||||
FcCache *cache = NULL;
|
||||
|
||||
FcDirCacheCreateUUID (dir, force);
|
||||
FcDirCacheCreateUUID ((FcChar8 *) dir, force, config);
|
||||
/* Try to use existing cache file */
|
||||
if (!force)
|
||||
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 *)];
|
||||
} 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 {
|
||||
unsigned int magic; /* FC_CACHE_MAGIC_MMAP or FC_CACHE_ALLOC */
|
||||
int version; /* FC_CACHE_VERSION_NUMBER */
|
||||
|
@ -558,6 +565,8 @@ struct _FcConfig {
|
|||
FcChar8 *sysRoot; /* override the system root directory */
|
||||
FcStrSet *availConfigFiles; /* config files available */
|
||||
FcPtrList *rulesetList; /* List of rulesets being installed */
|
||||
FcHashTable *uuid_table; /* UUID table for cachedirs */
|
||||
FcHashTable *alias_table; /* alias table for cachedirs */
|
||||
};
|
||||
|
||||
typedef struct _FcFileTime {
|
||||
|
@ -588,11 +597,9 @@ struct _FcValuePromotionBuffer {
|
|||
/* fccache.c */
|
||||
|
||||
FcPrivate FcBool
|
||||
FcDirCacheCreateUUID (const FcChar8 *dir,
|
||||
FcBool force);
|
||||
|
||||
FcPrivate const FcChar8 *
|
||||
FcDirCacheFindAliasPath (const FcChar8 *dir);
|
||||
FcDirCacheCreateUUID (FcChar8 *dir,
|
||||
FcBool force,
|
||||
FcConfig *config);
|
||||
|
||||
FcPrivate FcCache *
|
||||
FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
|
||||
|
@ -1300,4 +1307,38 @@ FcObjectLookupOtherTypeById (FcObject id);
|
|||
FcPrivate const FcObjectType *
|
||||
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_ */
|
||||
|
|
|
@ -458,14 +458,16 @@ FcListAppend (FcListHashTable *table,
|
|||
if (FcStat (FcValueString (&v->value), &statb) < 0)
|
||||
{
|
||||
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 *s = FcStrBuildFilename (alias, base, NULL);
|
||||
FcValue vv;
|
||||
|
||||
FcStrFree (alias);
|
||||
FcStrFree (base);
|
||||
vv.type = FcTypeString;
|
||||
vv.u.s = s;
|
||||
|
|
|
@ -653,14 +653,15 @@ FcFontRenderPrepare (FcConfig *config,
|
|||
if (FcStat (FcValueString (&l->value), &statb) < 0)
|
||||
{
|
||||
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 *s = FcStrBuildFilename (alias, base, NULL);
|
||||
FcValue v;
|
||||
|
||||
FcStrFree (alias);
|
||||
FcStrFree (base);
|
||||
v.type = FcTypeString;
|
||||
v.u.s = s;
|
||||
|
|
Loading…
Reference in New Issue