25#define XXH_STATIC_LINKING_ONLY
28#define hashsize(n) ((apr_size_t)1<<(n))
29#define hashmask(n) (hashsize(n)-1)
31static const void *str_get_key(
const void *opaque)
36static apr_size_t str_get_key_len(
const void *opaque)
38 const char *str = opaque;
42static int str_key_cmp(
const void *opaque1,
const void *opaque2, apr_size_t len)
44 const char *str1 = opaque1;
45 const char *str2 = opaque2;
47 return memcmp(str1, str2, len);
50static apr_uint32_t str_hash(
register const void *opaque,
register apr_size_t len)
53 return XXH32(opaque, len, 0x1337cafe);
68 apr_size_t *filling_table;
97 return napr_hash_make(pool, nel, ffactor, str_get_key, str_get_key_len, str_key_cmp, str_hash);
107 if (NULL == (result = apr_pcalloc(pool,
sizeof(
struct napr_hash_t)))) {
112 while (hashsize(result->power) < nel)
115 result->size = hashsize(result->power);
116 result->mask = hashmask(result->power);
117 result->ffactor = ffactor;
118 result->get_key = get_key;
119 result->get_key_len = get_key_len;
120 result->key_cmp = key_cmp;
124 if (APR_SUCCESS != (status = apr_pool_create(&(result->own_pool), pool))) {
126 DEBUG_ERR(
"error calling apr_pool_create: %s", apr_strerror(status, errbuf, 128));
132 if (NULL == (result->table = apr_pcalloc(result->own_pool, result->size *
sizeof(
void **)))) {
137 if (NULL == (result->filling_table = apr_pcalloc(result->own_pool, result->size *
sizeof(apr_size_t)))) {
145extern void *
napr_hash_search(napr_hash_t *hash,
const void *key, apr_size_t key_len, apr_uint32_t *hash_value)
147 apr_uint32_t key_hash;
148 apr_size_t i, nel, bucket;
150 key_hash = hash->hash(key, key_len);
152 if (NULL != hash_value)
153 *hash_value = key_hash;
155 bucket = key_hash & hash->mask;
156 if (0 != (nel = hash->filling_table[bucket])) {
157 for (i = 0; i < nel; i++) {
159 if (key_len == hash->get_key_len(hash->table[bucket][i]))
160 if (0 == (hash->key_cmp(key, hash->get_key(hash->table[bucket][i]), key_len)))
161 return hash->table[bucket][i];
168static inline apr_status_t napr_hash_rebuild(napr_hash_t *hash)
176 napr_hash_make(hash->pool, hashsize(hash->power + 1), hash->ffactor, hash->get_key, hash->get_key_len,
177 hash->key_cmp, hash->hash))) {
178 DEBUG_ERR(
"error calling napr_hash_init");
182 for (i = 0; i < hash->size; i++) {
183 for (j = 0; j < hash->filling_table[i]; j++) {
191 hash->hash(hash->get_key(hash->table[i][j]), hash->get_key_len(hash->table[i][j]))))) {
193 DEBUG_ERR(
"error calling napr_hash_set: %s", apr_strerror(status, errbuf, 128));
198 hash->table = tmp->table;
199 hash->filling_table = tmp->filling_table;
200 hash->nel = tmp->nel;
201 hash->size = tmp->size;
202 hash->mask = tmp->mask;
203 hash->power = tmp->power;
204 apr_pool_destroy(hash->own_pool);
205 hash->own_pool = tmp->own_pool;
212 apr_size_t nel, bucket, i, key_len;
215 bucket = hash_value & hash->mask;
216 key = hash->get_key(data);
217 key_len = hash->get_key_len(data);
218 if (0 != (nel = hash->filling_table[bucket])) {
219 for (i = 0; i < nel; i++) {
221 if (key_len == hash->get_key_len(hash->table[bucket][i]))
222 if (0 == (hash->key_cmp(key, hash->get_key(hash->table[bucket][i]), key_len))) {
225 hash->table[bucket][i] = hash->table[bucket][nel - 1];
226 hash->table[bucket][nel - 1] = NULL;
229 hash->table[bucket][i] = NULL;
231 hash->filling_table[bucket]--;
238 DEBUG_DBG(
"try to remove something that is not here");
242extern apr_status_t
napr_hash_set(napr_hash_t *hash,
void *data, apr_uint32_t hash_value)
244 apr_size_t nel, bucket;
247 bucket = hash_value & hash->mask;
249 if ((0 == (nel = hash->filling_table[bucket])) && (NULL == hash->table[bucket])) {
250 hash->table[bucket] = (
void **) apr_pcalloc(hash->own_pool, hash->ffactor *
sizeof(
void *));
253 hash->table[bucket][nel] = data;
254 hash->filling_table[bucket]++;
257 if (hash->ffactor <= hash->filling_table[bucket]) {
265 if (APR_SUCCESS != (status = napr_hash_rebuild(hash))) {
267 DEBUG_ERR(
"error calling napr_hash_rebuild: %s", apr_strerror(status, errbuf, 128));
277 return thehash->pool;
284 hash_index->hash = hash;
285 hash_index->bucket = 0;
286 hash_index->element = 0;
288 if (hash->filling_table[0] > 0)
296 if ((0 != index->hash->filling_table[index->bucket])
297 && (index->element < (index->hash->filling_table[index->bucket] - 1))) {
303 for (index->bucket += 1; index->bucket < index->hash->size; index->bucket++) {
304 if (0 != index->hash->filling_table[index->bucket])
307 if (index->bucket < index->hash->size)
314void napr_hash_this(napr_hash_index_t *hi,
const void **key, apr_size_t *klen,
void **val)
317 *key = hi->hash->get_key(hi->hash->table[hi->bucket][hi->element]);
319 *klen = hi->hash->get_key_len(hi->hash->table[hi->bucket][hi->element]);
321 *val = hi->hash->table[hi->bucket][hi->element];
UTIL debug output macros.
#define DEBUG_DBG(str, arg...)
Display error message at the level debug.
#define DEBUG_ERR(str, arg...)
Display error message at the level error.
XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32(const void *input, size_t length, XXH32_hash_t seed)
Calculates the 32-bit hash of input using xxHash32.
apr_pool_t * napr_hash_pool_get(const napr_hash_t *thehash)
Get a pointer to the pool from which the hash table was allocated.
napr_hash_index_t * napr_hash_first(apr_pool_t *pool, napr_hash_t *hash)
Start iterating over the entries in a hash table.
void napr_hash_this(napr_hash_index_t *hi, const void **key, apr_size_t *klen, void **val)
Get the current entry's details from the iteration state.
napr_hash_t * napr_hash_str_make(apr_pool_t *pool, apr_size_t nel, apr_size_t ffactor)
Create a hash table optimized for storing C strings as keys.
apr_status_t napr_hash_set(napr_hash_t *hash, void *data, apr_uint32_t hash_value)
Inserts or updates an item in the hash table.
void * napr_hash_search(napr_hash_t *hash, const void *key, apr_size_t key_len, apr_uint32_t *hash_value)
Searches the hash table for an item.
napr_hash_index_t * napr_hash_next(napr_hash_index_t *index)
Continue iterating over the entries in a hash table.
void napr_hash_remove(napr_hash_t *hash, void *data, apr_uint32_t hash_value)
Removes an item from the hash table.
napr_hash_t * napr_hash_make(apr_pool_t *pool, apr_size_t nel, apr_size_t ffactor, get_key_callback_fn_t get_key, get_key_len_callback_fn_t get_key_len, key_cmp_callback_fn_t key_cmp, hash_callback_fn_t hash)
Create a hash table with custom key handling and hashing functions.
A high-performance hash table implementation built on APR.
int() key_cmp_callback_fn_t(const void *, const void *, apr_size_t)
Callback function to compare two keys.
struct napr_hash_index_t napr_hash_index_t
Opaque hash table iterator structure.
apr_uint32_t() hash_callback_fn_t(register const void *, register apr_size_t)
Callback function to compute the hash value of a key.
apr_size_t() get_key_len_callback_fn_t(const void *)
Callback function to get the length of a key.
const void *() get_key_callback_fn_t(const void *)
Callback function to extract the key from a stored data item.
struct napr_hash_t napr_hash_t
Opaque hash table structure.