2 * Copyright © 2000 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the author(s) not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors make no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
24 #include <uuid/uuid.h>
27 #define FC_HASH_SIZE 227
29 typedef struct _FcHashBucket {
30 struct _FcHashBucket *next;
36 FcHashBucket *buckets[FC_HASH_SIZE];
38 FcCompareFunc compare_func;
39 FcCopyFunc key_copy_func;
40 FcCopyFunc value_copy_func;
41 FcDestroyFunc key_destroy_func;
42 FcDestroyFunc value_destroy_func;
47 FcHashStrCopy (const void *src,
50 *dest = FcStrdup (src);
56 FcHashUuidCopy (const void *src,
60 *dest = malloc (sizeof (uuid_t));
61 uuid_copy (*dest, src);
67 FcHashUuidFree (void *data)
73 FcHashTableCreate (FcHashFunc hash_func,
74 FcCompareFunc compare_func,
75 FcCopyFunc key_copy_func,
76 FcCopyFunc value_copy_func,
77 FcDestroyFunc key_destroy_func,
78 FcDestroyFunc value_destroy_func)
80 FcHashTable *ret = malloc (sizeof (FcHashTable));
84 memset (ret->buckets, 0, sizeof (FcHashBucket *) * FC_HASH_SIZE);
85 ret->hash_func = hash_func;
86 ret->compare_func = compare_func;
87 ret->key_copy_func = key_copy_func;
88 ret->value_copy_func = value_copy_func;
89 ret->key_destroy_func = key_destroy_func;
90 ret->value_destroy_func = value_destroy_func;
96 FcHashTableDestroy (FcHashTable *table)
100 for (i = 0; i < FC_HASH_SIZE; i++)
102 FcHashBucket *bucket = table->buckets[i], *prev;
106 if (table->key_destroy_func)
107 table->key_destroy_func (bucket->key);
108 if (table->value_destroy_func)
109 table->value_destroy_func (bucket->value);
111 bucket = bucket->next;
114 table->buckets[i] = NULL;
120 FcHashTableFind (FcHashTable *table,
124 FcHashBucket *bucket;
125 FcChar32 hash = table->hash_func (key);
127 for (bucket = table->buckets[hash % FC_HASH_SIZE]; bucket; bucket = bucket->next)
129 if (!table->compare_func(bucket->key, key))
131 if (table->value_copy_func)
133 if (!table->value_copy_func (bucket->value, value))
137 *value = bucket->value;
145 FcHashTableAddInternal (FcHashTable *table,
150 FcHashBucket **prev, *bucket, *b;
151 FcChar32 hash = table->hash_func (key);
152 FcBool ret = FcFalse;
154 bucket = (FcHashBucket *) malloc (sizeof (FcHashBucket));
157 memset (bucket, 0, sizeof (FcHashBucket));
158 if (table->key_copy_func)
159 ret |= !table->key_copy_func (key, &bucket->key);
162 if (table->value_copy_func)
163 ret |= !table->value_copy_func (value, &bucket->value);
165 bucket->value = value;
169 if (bucket->key && table->key_destroy_func)
170 table->key_destroy_func (bucket->key);
171 if (bucket->value && table->value_destroy_func)
172 table->value_destroy_func (bucket->value);
178 for (prev = &table->buckets[hash % FC_HASH_SIZE];
179 (b = fc_atomic_ptr_get (prev)); prev = &(b->next))
181 if (!table->compare_func (b->key, key))
185 bucket->next = b->next;
186 if (!fc_atomic_ptr_cmpexch (prev, b, bucket))
196 if (!fc_atomic_ptr_cmpexch (prev, b, bucket))
203 FcHashTableAdd (FcHashTable *table,
207 return FcHashTableAddInternal (table, key, value, FcFalse);
211 FcHashTableReplace (FcHashTable *table,
215 return FcHashTableAddInternal (table, key, value, FcTrue);
219 FcHashTableRemove (FcHashTable *table,
222 FcHashBucket **prev, *bucket;
223 FcChar32 hash = table->hash_func (key);
224 FcBool ret = FcFalse;
227 for (prev = &table->buckets[hash % FC_HASH_SIZE];
228 (bucket = fc_atomic_ptr_get (prev)); prev = &(bucket->next))
230 if (!table->compare_func (bucket->key, key))
232 if (!fc_atomic_ptr_cmpexch (prev, bucket, bucket->next))
234 if (table->key_destroy_func)
235 table->key_destroy_func (bucket->key);
236 if (table->value_destroy_func)
237 table->value_destroy_func (bucket->value);