Update to version p5.9.20211031.0 of ctags
[geany-mirror.git] / ctags / main / htable.c
blob0ebfbd815f8d62427f802c943432a8207f046986
1 /*
3 * Copyright (c) 2014, Red Hat, Inc.
4 * Copyright (c) 2014, Masatake YAMATO
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License version 2 or (at your option) any later version.
9 * Defines hashtable
12 #include "general.h"
13 #include "htable.h"
15 #ifndef MAIN
16 #include <stdio.h>
17 #include "routines.h"
18 #else
19 #include <stdlib.h>
20 #ifndef xCalloc
21 #define xCalloc(n,Type) (Type *)calloc((size_t)(n), sizeof (Type))
22 #endif
23 #ifndef xMalloc
24 #define xMalloc(n,Type) (Type *)malloc((size_t)(n) * sizeof (Type))
25 #endif
26 #ifndef eFree
27 #define eFree(x) free(x)
28 #endif
29 #endif /* MAIN */
31 #include <string.h>
34 typedef struct sHashEntry hentry;
35 struct sHashEntry {
36 void *key;
37 void *value;
38 hentry *next;
41 struct sHashTable {
42 hentry** table;
43 unsigned int size;
44 hashTableHashFunc hashfn;
45 hashTableEqualFunc equalfn;
46 hashTableDeleteFunc keyfreefn;
47 hashTableDeleteFunc valfreefn;
48 void *valForNotUnknownKey;
49 hashTableDeleteFunc valForNotUnknownKeyfreefn;
52 struct chainTracker {
53 const void *const target_key;
54 hashTableForeachFunc user_proc;
55 void *user_data;
56 hashTableEqualFunc equalfn;
59 static hentry* entry_new (void *key, void *value, hentry* next)
61 hentry* entry = xMalloc (1, hentry);
63 entry->key = key;
64 entry->value = value;
65 entry->next = next;
67 return entry;
70 static void entry_reset (hentry* entry,
71 void *newkey,
72 void *newval,
73 hashTableDeleteFunc keyfreefn,
74 hashTableDeleteFunc valfreefn)
76 if (keyfreefn)
77 keyfreefn (entry->key);
78 if (valfreefn)
79 valfreefn (entry->value);
80 entry->key = newkey;
81 entry->value = newval;
84 static hentry* entry_destroy (hentry* entry,
85 hashTableDeleteFunc keyfreefn,
86 hashTableDeleteFunc valfreefn)
88 hentry* tmp;
90 entry_reset (entry, NULL, NULL, keyfreefn, valfreefn);
91 tmp = entry->next;
92 eFree (entry);
94 return tmp;
97 static void entry_reclaim (hentry* entry,
98 hashTableDeleteFunc keyfreefn,
99 hashTableDeleteFunc valfreefn)
101 while (entry)
102 entry = entry_destroy (entry, keyfreefn, valfreefn);
105 static void *entry_find (hentry* entry, const void* const key, hashTableEqualFunc equalfn,
106 void *valForNotUnknownKey)
108 while (entry)
110 if (equalfn( key, entry->key))
111 return entry->value;
112 entry = entry->next;
114 return valForNotUnknownKey;
117 static bool entry_delete (hentry **entry, const void *key, hashTableEqualFunc equalfn,
118 hashTableDeleteFunc keyfreefn, hashTableDeleteFunc valfreefn)
120 while (*entry)
122 if (equalfn (key, (*entry)->key))
124 *entry = entry_destroy (*entry, keyfreefn, valfreefn);
125 return true;
127 entry = &((*entry)->next);
129 return false;
132 static bool entry_update (hentry *entry, void *key, void *value, hashTableEqualFunc equalfn,
133 hashTableDeleteFunc keyfreefn, hashTableDeleteFunc valfreefn)
135 while (entry)
137 if (equalfn (key, entry->key))
139 entry_reset (entry, key, value, keyfreefn, valfreefn);
140 return true;
142 entry = entry->next;
144 return false;
147 static bool entry_foreach (hentry *entry, hashTableForeachFunc proc, void *user_data)
149 while (entry)
151 if (!proc (entry->key, entry->value, user_data))
152 return false;
153 entry = entry->next;
155 return true;
158 extern hashTable *hashTableNew (unsigned int size,
159 hashTableHashFunc hashfn,
160 hashTableEqualFunc equalfn,
161 hashTableDeleteFunc keyfreefn,
162 hashTableDeleteFunc valfreefn)
164 hashTable *htable;
166 htable = xMalloc (1, hashTable);
167 htable->size = size;
168 htable->table = xCalloc (size, hentry*);
170 htable->hashfn = hashfn;
171 htable->equalfn = equalfn;
172 htable->keyfreefn = keyfreefn;
173 htable->valfreefn = valfreefn;
174 htable->valForNotUnknownKey = NULL;
175 htable->valForNotUnknownKeyfreefn = NULL;
177 return htable;
180 extern void hashTableSetValueForUnknownKey (hashTable *htable,
181 void *val,
182 hashTableDeleteFunc valfreefn)
184 if (htable->valfreefn)
185 htable->valfreefn (htable->valForNotUnknownKey);
187 htable->valForNotUnknownKey = val;
188 htable->valForNotUnknownKeyfreefn = valfreefn;
191 extern void hashTableDelete (hashTable *htable)
193 if (!htable)
194 return;
196 hashTableClear (htable);
198 if (htable->valForNotUnknownKeyfreefn)
199 htable->valForNotUnknownKeyfreefn (htable->valForNotUnknownKey);
200 eFree (htable->table);
201 eFree (htable);
204 extern void hashTableClear (hashTable *htable)
206 unsigned int i;
207 if (!htable)
208 return;
210 for (i = 0; i < htable->size; i++)
212 hentry *entry;
214 entry = htable->table[i];
215 entry_reclaim (entry, htable->keyfreefn, htable->valfreefn);
216 htable->table[i] = NULL;
220 extern void hashTablePutItem (hashTable *htable, void *key, void *value)
222 unsigned int i;
224 i = htable->hashfn (key) % htable->size;
225 htable->table[i] = entry_new(key, value, htable->table[i]);
228 extern void* hashTableGetItem (hashTable *htable, const void * key)
230 unsigned int i;
232 i = htable->hashfn (key) % htable->size;
233 return entry_find(htable->table[i], key, htable->equalfn, htable->valForNotUnknownKey);
236 extern bool hashTableDeleteItem (hashTable *htable, const void *key)
238 unsigned int i;
240 i = htable->hashfn (key) % htable->size;
241 return entry_delete(&htable->table[i], key,
242 htable->equalfn, htable->keyfreefn, htable->valfreefn);
245 extern bool hashTableUpdateItem (hashTable *htable, void *key, void *value)
247 unsigned int i;
249 i = htable->hashfn (key) % htable->size;
250 bool r = entry_update(htable->table[i], key, value,
251 htable->equalfn, htable->keyfreefn, htable->valfreefn);
252 if (!r)
253 htable->table[i] = entry_new(key, value, htable->table[i]);
254 return r;
257 extern bool hashTableHasItem (hashTable *htable, const void *key)
259 return hashTableGetItem (htable, key) == htable->valForNotUnknownKey? false: true;
262 extern bool hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data)
264 unsigned int i;
266 for (i = 0; i < htable->size; i++)
267 if (!entry_foreach(htable->table[i], proc, user_data))
268 return false;
269 return true;
272 static bool track_chain (const void *const key, void *value, void *chain_data)
274 struct chainTracker *chain_tracker = chain_data;
276 if (chain_tracker->equalfn (chain_tracker->target_key, key))
278 if (! chain_tracker->user_proc (key, value, chain_tracker->user_data))
279 return false;
281 return true;
284 extern bool hashTableForeachItemOnChain (hashTable *htable, const void *key, hashTableForeachFunc proc, void *user_data)
286 unsigned int i;
287 struct chainTracker chain_tracker = {
288 .target_key = key,
289 .user_proc = proc,
290 .user_data = user_data,
291 .equalfn = htable->equalfn,
294 i = htable->hashfn (key) % htable->size;
295 if (!entry_foreach(htable->table[i], track_chain, &chain_tracker))
296 return false;
297 return true;
300 static bool count (const void *const key CTAGS_ATTR_UNUSED, void *value CTAGS_ATTR_UNUSED, void *data)
302 int *c = data;
303 ++*c;
304 return true;
307 extern unsigned int hashTableCountItem (hashTable *htable)
309 int c = 0;
310 hashTableForeachItem (htable, count, &c);
311 return c;
314 unsigned int hashPtrhash (const void * const x)
316 union {
317 const void * ptr;
318 unsigned int ui;
319 } v;
320 v.ui = 0;
321 v.ptr = x;
323 return v.ui;
326 bool hashPtreq (const void *const a, const void *const b)
328 return (a == b)? true: false;
332 /* http://www.cse.yorku.ca/~oz/hash.html */
333 static unsigned long
334 djb2(const unsigned char *str)
336 unsigned long hash = 5381;
337 int c;
339 while ((c = *str++))
340 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
342 return hash;
345 static unsigned long
346 casedjb2(const unsigned char *str)
348 unsigned long hash = 5381;
349 int c;
351 while ((c = *str++))
353 if (('a' <= c) && (c <= 'z'))
354 c += ('A' - 'a');
355 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
358 return hash;
362 unsigned int hashCstrhash (const void *const x)
364 const char *const s = x;
365 return (unsigned int)djb2((const unsigned char *)s);
368 bool hashCstreq (const void * const a, const void *const b)
370 return !!(strcmp (a, b) == 0);
373 unsigned int hashInthash (const void *const x)
375 union tmp {
376 unsigned int u;
377 int i;
378 } x0;
380 x0.u = 0;
381 x0.i = *(int *)x;
382 return x0.u;
385 bool hashInteq (const void *const a, const void *const b)
387 int ai = *(int *)a;
388 int bi = *(int *)b;
390 return !!(ai == bi);
394 unsigned int hashCstrcasehash (const void *const x)
396 const char *const s = x;
397 return (unsigned int)casedjb2((const unsigned char *)s);
400 bool hashCstrcaseeq (const void *const a, const void *const b)
402 return !!(strcasecmp (a, b) == 0);