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.
21 #define xCalloc(n,Type) (Type *)calloc((size_t)(n), sizeof (Type))
24 #define xMalloc(n,Type) (Type *)malloc((size_t)(n) * sizeof (Type))
27 #define eFree(x) free(x)
34 typedef struct sHashEntry hentry
;
44 hashTableHashFunc hashfn
;
45 hashTableEqualFunc equalfn
;
46 hashTableDeleteFunc keyfreefn
;
47 hashTableDeleteFunc valfreefn
;
48 void *valForNotUnknownKey
;
49 hashTableDeleteFunc valForNotUnknownKeyfreefn
;
53 const void *const target_key
;
54 hashTableForeachFunc user_proc
;
56 hashTableEqualFunc equalfn
;
59 static hentry
* entry_new (void *key
, void *value
, hentry
* next
)
61 hentry
* entry
= xMalloc (1, hentry
);
70 static void entry_reset (hentry
* entry
,
73 hashTableDeleteFunc keyfreefn
,
74 hashTableDeleteFunc valfreefn
)
77 keyfreefn (entry
->key
);
79 valfreefn (entry
->value
);
81 entry
->value
= newval
;
84 static hentry
* entry_destroy (hentry
* entry
,
85 hashTableDeleteFunc keyfreefn
,
86 hashTableDeleteFunc valfreefn
)
90 entry_reset (entry
, NULL
, NULL
, keyfreefn
, valfreefn
);
97 static void entry_reclaim (hentry
* entry
,
98 hashTableDeleteFunc keyfreefn
,
99 hashTableDeleteFunc valfreefn
)
102 entry
= entry_destroy (entry
, keyfreefn
, valfreefn
);
105 static void *entry_find (hentry
* entry
, const void* const key
, hashTableEqualFunc equalfn
,
106 void *valForNotUnknownKey
)
110 if (equalfn( key
, entry
->key
))
114 return valForNotUnknownKey
;
117 static bool entry_delete (hentry
**entry
, const void *key
, hashTableEqualFunc equalfn
,
118 hashTableDeleteFunc keyfreefn
, hashTableDeleteFunc valfreefn
)
122 if (equalfn (key
, (*entry
)->key
))
124 *entry
= entry_destroy (*entry
, keyfreefn
, valfreefn
);
127 entry
= &((*entry
)->next
);
132 static bool entry_update (hentry
*entry
, void *key
, void *value
, hashTableEqualFunc equalfn
,
133 hashTableDeleteFunc keyfreefn
, hashTableDeleteFunc valfreefn
)
137 if (equalfn (key
, entry
->key
))
139 entry_reset (entry
, key
, value
, keyfreefn
, valfreefn
);
147 static bool entry_foreach (hentry
*entry
, hashTableForeachFunc proc
, void *user_data
)
151 if (!proc (entry
->key
, entry
->value
, user_data
))
158 extern hashTable
*hashTableNew (unsigned int size
,
159 hashTableHashFunc hashfn
,
160 hashTableEqualFunc equalfn
,
161 hashTableDeleteFunc keyfreefn
,
162 hashTableDeleteFunc valfreefn
)
166 htable
= xMalloc (1, hashTable
);
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
;
180 extern void hashTableSetValueForUnknownKey (hashTable
*htable
,
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
)
196 hashTableClear (htable
);
198 if (htable
->valForNotUnknownKeyfreefn
)
199 htable
->valForNotUnknownKeyfreefn (htable
->valForNotUnknownKey
);
200 eFree (htable
->table
);
204 extern void hashTableClear (hashTable
*htable
)
210 for (i
= 0; i
< htable
->size
; i
++)
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
)
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
)
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
)
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
)
249 i
= htable
->hashfn (key
) % htable
->size
;
250 bool r
= entry_update(htable
->table
[i
], key
, value
,
251 htable
->equalfn
, htable
->keyfreefn
, htable
->valfreefn
);
253 htable
->table
[i
] = entry_new(key
, value
, htable
->table
[i
]);
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
)
266 for (i
= 0; i
< htable
->size
; i
++)
267 if (!entry_foreach(htable
->table
[i
], proc
, user_data
))
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
))
284 extern bool hashTableForeachItemOnChain (hashTable
*htable
, const void *key
, hashTableForeachFunc proc
, void *user_data
)
287 struct chainTracker chain_tracker
= {
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
))
300 static bool count (const void *const key CTAGS_ATTR_UNUSED
, void *value CTAGS_ATTR_UNUSED
, void *data
)
307 extern unsigned int hashTableCountItem (hashTable
*htable
)
310 hashTableForeachItem (htable
, count
, &c
);
314 unsigned int hashPtrhash (const void * const x
)
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 */
334 djb2(const unsigned char *str
)
336 unsigned long hash
= 5381;
340 hash
= ((hash
<< 5) + hash
) + c
; /* hash * 33 + c */
346 casedjb2(const unsigned char *str
)
348 unsigned long hash
= 5381;
353 if (('a' <= c
) && (c
<= 'z'))
355 hash
= ((hash
<< 5) + hash
) + c
; /* hash * 33 + c */
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
)
385 bool hashInteq (const void *const a
, const void *const b
)
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);