|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Borrowed from libkmod - interface to kernel module operations
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Copyright (C) 2011-2013 ProFUSION embedded systems
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
80a84b |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
80a84b |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
80a84b |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
80a84b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
80a84b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
80a84b |
* Lesser General Public License for more details.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
80a84b |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#include <errno.h>
|
|
Packit Service |
80a84b |
#include <inttypes.h>
|
|
Packit Service |
80a84b |
#include <stdlib.h>
|
|
Packit Service |
80a84b |
#include <string.h>
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#include "hash.h"
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* endianess and alignments */
|
|
Packit Service |
80a84b |
/* taken from kmod shared/util.h */
|
|
Packit Service |
80a84b |
/* ************************************************************************ */
|
|
Packit Service |
80a84b |
#define get_unaligned(ptr) \
|
|
Packit Service |
80a84b |
({ \
|
|
Packit Service |
80a84b |
struct __attribute__((packed)) { \
|
|
Packit Service |
80a84b |
typeof(*(ptr)) __v; \
|
|
Packit Service |
80a84b |
} *__p = (typeof(__p)) (ptr); \
|
|
Packit Service |
80a84b |
__p->__v; \
|
|
Packit Service |
80a84b |
})
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#define put_unaligned(val, ptr) \
|
|
Packit Service |
80a84b |
do { \
|
|
Packit Service |
80a84b |
struct __attribute__((packed)) { \
|
|
Packit Service |
80a84b |
typeof(*(ptr)) __v; \
|
|
Packit Service |
80a84b |
} *__p = (typeof(__p)) (ptr); \
|
|
Packit Service |
80a84b |
__p->__v = (val); \
|
|
Packit Service |
80a84b |
} while (0)
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static inline unsigned int ALIGN_POWER2(unsigned int u)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static inline size_t min(size_t a, size_t b)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return a < b ? a : b;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
struct hash_entry {
|
|
Packit Service |
80a84b |
const char *key;
|
|
Packit Service |
80a84b |
size_t keylen;
|
|
Packit Service |
80a84b |
const void *value;
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
struct hash_bucket {
|
|
Packit Service |
80a84b |
struct hash_entry *entries;
|
|
Packit Service |
80a84b |
unsigned int used;
|
|
Packit Service |
80a84b |
unsigned int total;
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
struct hash {
|
|
Packit Service |
80a84b |
unsigned int count;
|
|
Packit Service |
80a84b |
unsigned int step;
|
|
Packit Service |
80a84b |
unsigned int n_buckets;
|
|
Packit Service |
80a84b |
void (*free_value)(void *value);
|
|
Packit Service |
80a84b |
struct hash_bucket buckets[];
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static inline int hash_key_cmp(const char *key1, size_t size1,
|
|
Packit Service |
80a84b |
const char *key2, size_t size2)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int rc;
|
|
Packit Service |
80a84b |
size_t size;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
size = min(size1, size2);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
rc = memcmp(key1, key2, size);
|
|
Packit Service |
80a84b |
if (rc != 0)
|
|
Packit Service |
80a84b |
return rc;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return (int)(size1 - size2);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
struct hash *hash_new(unsigned int n_buckets,
|
|
Packit Service |
80a84b |
void (*free_value)(void *value))
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
struct hash *hash;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
n_buckets = ALIGN_POWER2(n_buckets);
|
|
Packit Service |
80a84b |
hash = calloc(1, sizeof(struct hash) +
|
|
Packit Service |
80a84b |
n_buckets * sizeof(struct hash_bucket));
|
|
Packit Service |
80a84b |
if (hash == NULL)
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
hash->n_buckets = n_buckets;
|
|
Packit Service |
80a84b |
hash->free_value = free_value;
|
|
Packit Service |
80a84b |
hash->step = n_buckets / 32;
|
|
Packit Service |
80a84b |
if (hash->step == 0)
|
|
Packit Service |
80a84b |
hash->step = 4;
|
|
Packit Service |
80a84b |
else if (hash->step > 64)
|
|
Packit Service |
80a84b |
hash->step = 64;
|
|
Packit Service |
80a84b |
return hash;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void hash_free(struct hash *hash)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
struct hash_bucket *bucket, *bucket_end;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (hash == NULL)
|
|
Packit Service |
80a84b |
return;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
bucket = hash->buckets;
|
|
Packit Service |
80a84b |
bucket_end = bucket + hash->n_buckets;
|
|
Packit Service |
80a84b |
for (; bucket < bucket_end; bucket++) {
|
|
Packit Service |
80a84b |
if (hash->free_value) {
|
|
Packit Service |
80a84b |
struct hash_entry *entry, *entry_end;
|
|
Packit Service |
80a84b |
entry = bucket->entries;
|
|
Packit Service |
80a84b |
entry_end = entry + bucket->used;
|
|
Packit Service |
80a84b |
for (; entry < entry_end; entry++)
|
|
Packit Service |
80a84b |
hash->free_value((void *)entry->value);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
free(bucket->entries);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
free(hash);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static inline unsigned int hash_superfast(const char *key, unsigned int len)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
/* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
|
|
Packit Service |
80a84b |
* used by WebCore (http://webkit.org/blog/8/hashtables-part-2/)
|
|
Packit Service |
80a84b |
* EFL's eina and possible others.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
unsigned int tmp, hash = len, rem = len & 3;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
len /= 4;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Main loop */
|
|
Packit Service |
80a84b |
for (; len > 0; len--) {
|
|
Packit Service |
80a84b |
hash += get_unaligned((uint16_t *) key);
|
|
Packit Service |
80a84b |
tmp = (get_unaligned((uint16_t *)(key + 2)) << 11) ^ hash;
|
|
Packit Service |
80a84b |
hash = (hash << 16) ^ tmp;
|
|
Packit Service |
80a84b |
key += 4;
|
|
Packit Service |
80a84b |
hash += hash >> 11;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Handle end cases */
|
|
Packit Service |
80a84b |
switch (rem) {
|
|
Packit Service |
80a84b |
case 3:
|
|
Packit Service |
80a84b |
hash += get_unaligned((uint16_t *) key);
|
|
Packit Service |
80a84b |
hash ^= hash << 16;
|
|
Packit Service |
80a84b |
hash ^= key[2] << 18;
|
|
Packit Service |
80a84b |
hash += hash >> 11;
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
case 2:
|
|
Packit Service |
80a84b |
hash += get_unaligned((uint16_t *) key);
|
|
Packit Service |
80a84b |
hash ^= hash << 11;
|
|
Packit Service |
80a84b |
hash += hash >> 17;
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
case 1:
|
|
Packit Service |
80a84b |
hash += *key;
|
|
Packit Service |
80a84b |
hash ^= hash << 10;
|
|
Packit Service |
80a84b |
hash += hash >> 1;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Force "avalanching" of final 127 bits */
|
|
Packit Service |
80a84b |
hash ^= hash << 3;
|
|
Packit Service |
80a84b |
hash += hash >> 5;
|
|
Packit Service |
80a84b |
hash ^= hash << 4;
|
|
Packit Service |
80a84b |
hash += hash >> 17;
|
|
Packit Service |
80a84b |
hash ^= hash << 25;
|
|
Packit Service |
80a84b |
hash += hash >> 6;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return hash;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* add or replace key in hash map.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* none of key or value are copied, just references are remembered as is,
|
|
Packit Service |
80a84b |
* make sure they are live while pair exists in hash!
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
int hash_add_bin(struct hash *hash,
|
|
Packit Service |
80a84b |
const char *key, size_t keylen, const void *value)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
unsigned int hashval = hash_superfast(key, keylen);
|
|
Packit Service |
80a84b |
unsigned int pos = hashval & (hash->n_buckets - 1);
|
|
Packit Service |
80a84b |
struct hash_bucket *bucket = hash->buckets + pos;
|
|
Packit Service |
80a84b |
struct hash_entry *entry, *entry_end;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (bucket->used + 1 >= bucket->total) {
|
|
Packit Service |
80a84b |
unsigned new_total = bucket->total + hash->step;
|
|
Packit Service |
80a84b |
size_t size = new_total * sizeof(struct hash_entry);
|
|
Packit Service |
80a84b |
struct hash_entry *tmp = realloc(bucket->entries, size);
|
|
Packit Service |
80a84b |
if (tmp == NULL)
|
|
Packit Service |
80a84b |
return -errno;
|
|
Packit Service |
80a84b |
bucket->entries = tmp;
|
|
Packit Service |
80a84b |
bucket->total = new_total;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
entry = bucket->entries;
|
|
Packit Service |
80a84b |
entry_end = entry + bucket->used;
|
|
Packit Service |
80a84b |
for (; entry < entry_end; entry++) {
|
|
Packit Service |
80a84b |
int c = hash_key_cmp(key, keylen, entry->key, entry->keylen);
|
|
Packit Service |
80a84b |
if (c == 0) {
|
|
Packit Service |
80a84b |
if (hash->free_value)
|
|
Packit Service |
80a84b |
hash->free_value((void *)entry->value);
|
|
Packit Service |
80a84b |
entry->key = key;
|
|
Packit Service |
80a84b |
entry->keylen = keylen;
|
|
Packit Service |
80a84b |
entry->value = value;
|
|
Packit Service |
80a84b |
return 0;
|
|
Packit Service |
80a84b |
} else if (c < 0) {
|
|
Packit Service |
80a84b |
memmove(entry + 1, entry,
|
|
Packit Service |
80a84b |
(entry_end - entry) * sizeof(struct hash_entry));
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
entry->key = key;
|
|
Packit Service |
80a84b |
entry->keylen = keylen;
|
|
Packit Service |
80a84b |
entry->value = value;
|
|
Packit Service |
80a84b |
bucket->used++;
|
|
Packit Service |
80a84b |
hash->count++;
|
|
Packit Service |
80a84b |
return 0;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* similar to hash_add(), but fails if key already exists */
|
|
Packit Service |
80a84b |
int hash_add_unique_bin(struct hash *hash,
|
|
Packit Service |
80a84b |
const char *key, size_t keylen, const void *value)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
unsigned int hashval = hash_superfast(key, keylen);
|
|
Packit Service |
80a84b |
unsigned int pos = hashval & (hash->n_buckets - 1);
|
|
Packit Service |
80a84b |
struct hash_bucket *bucket = hash->buckets + pos;
|
|
Packit Service |
80a84b |
struct hash_entry *entry, *entry_end;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (bucket->used + 1 >= bucket->total) {
|
|
Packit Service |
80a84b |
unsigned new_total = bucket->total + hash->step;
|
|
Packit Service |
80a84b |
size_t size = new_total * sizeof(struct hash_entry);
|
|
Packit Service |
80a84b |
struct hash_entry *tmp = realloc(bucket->entries, size);
|
|
Packit Service |
80a84b |
if (tmp == NULL)
|
|
Packit Service |
80a84b |
return -errno;
|
|
Packit Service |
80a84b |
bucket->entries = tmp;
|
|
Packit Service |
80a84b |
bucket->total = new_total;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
entry = bucket->entries;
|
|
Packit Service |
80a84b |
entry_end = entry + bucket->used;
|
|
Packit Service |
80a84b |
for (; entry < entry_end; entry++) {
|
|
Packit Service |
80a84b |
int c = hash_key_cmp(key, keylen, entry->key, entry->keylen);
|
|
Packit Service |
80a84b |
if (c == 0)
|
|
Packit Service |
80a84b |
return -EEXIST;
|
|
Packit Service |
80a84b |
else if (c < 0) {
|
|
Packit Service |
80a84b |
memmove(entry + 1, entry,
|
|
Packit Service |
80a84b |
(entry_end - entry) * sizeof(struct hash_entry));
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
entry->key = key;
|
|
Packit Service |
80a84b |
entry->keylen = keylen;
|
|
Packit Service |
80a84b |
entry->value = value;
|
|
Packit Service |
80a84b |
bucket->used++;
|
|
Packit Service |
80a84b |
hash->count++;
|
|
Packit Service |
80a84b |
return 0;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static int hash_entry_cmp(const void *pa, const void *pb)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
const struct hash_entry *a = pa;
|
|
Packit Service |
80a84b |
const struct hash_entry *b = pb;
|
|
Packit Service |
80a84b |
return hash_key_cmp(a->key, a->keylen, b->key, b->keylen);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void *hash_find_bin(const struct hash *hash, const char *key, size_t keylen)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
unsigned int hashval = hash_superfast(key, keylen);
|
|
Packit Service |
80a84b |
unsigned int pos = hashval & (hash->n_buckets - 1);
|
|
Packit Service |
80a84b |
const struct hash_bucket *bucket = hash->buckets + pos;
|
|
Packit Service |
80a84b |
const struct hash_entry se = {
|
|
Packit Service |
80a84b |
.key = key,
|
|
Packit Service |
80a84b |
.keylen = keylen,
|
|
Packit Service |
80a84b |
.value = NULL
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
const struct hash_entry *entry = bsearch(
|
|
Packit Service |
80a84b |
&se, bucket->entries, bucket->used,
|
|
Packit Service |
80a84b |
sizeof(struct hash_entry), hash_entry_cmp);
|
|
Packit Service |
80a84b |
if (entry == NULL)
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
return (void *)entry->value;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
int hash_del_bin(struct hash *hash, const char *key, size_t keylen)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
unsigned int hashval = hash_superfast(key, keylen);
|
|
Packit Service |
80a84b |
unsigned int pos = hashval & (hash->n_buckets - 1);
|
|
Packit Service |
80a84b |
unsigned int steps_used, steps_total;
|
|
Packit Service |
80a84b |
struct hash_bucket *bucket = hash->buckets + pos;
|
|
Packit Service |
80a84b |
struct hash_entry *entry, *entry_end;
|
|
Packit Service |
80a84b |
const struct hash_entry se = {
|
|
Packit Service |
80a84b |
.key = key,
|
|
Packit Service |
80a84b |
.keylen = keylen,
|
|
Packit Service |
80a84b |
.value = NULL
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
entry = bsearch(&se, bucket->entries, bucket->used,
|
|
Packit Service |
80a84b |
sizeof(struct hash_entry), hash_entry_cmp);
|
|
Packit Service |
80a84b |
if (entry == NULL)
|
|
Packit Service |
80a84b |
return -ENOENT;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (hash->free_value)
|
|
Packit Service |
80a84b |
hash->free_value((void *)entry->value);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
entry_end = bucket->entries + bucket->used;
|
|
Packit Service |
80a84b |
memmove(entry, entry + 1,
|
|
Packit Service |
80a84b |
(entry_end - entry) * sizeof(struct hash_entry));
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
bucket->used--;
|
|
Packit Service |
80a84b |
hash->count--;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
steps_used = bucket->used / hash->step;
|
|
Packit Service |
80a84b |
steps_total = bucket->total / hash->step;
|
|
Packit Service |
80a84b |
if (steps_used + 1 < steps_total) {
|
|
Packit Service |
80a84b |
size_t size = (steps_used + 1) *
|
|
Packit Service |
80a84b |
hash->step * sizeof(struct hash_entry);
|
|
Packit Service |
80a84b |
struct hash_entry *tmp = realloc(bucket->entries, size);
|
|
Packit Service |
80a84b |
if (tmp) {
|
|
Packit Service |
80a84b |
bucket->entries = tmp;
|
|
Packit Service |
80a84b |
bucket->total = (steps_used + 1) * hash->step;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return 0;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
unsigned int hash_get_count(const struct hash *hash)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return hash->count;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void hash_iter_init(const struct hash *hash, struct hash_iter *iter)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
iter->hash = hash;
|
|
Packit Service |
80a84b |
iter->bucket = 0;
|
|
Packit Service |
80a84b |
iter->entry = -1;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
bool hash_iter_next_bin(struct hash_iter *iter, const char **key,
|
|
Packit Service |
80a84b |
size_t *keylen,
|
|
Packit Service |
80a84b |
const void **value)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
const struct hash_bucket *b = iter->hash->buckets + iter->bucket;
|
|
Packit Service |
80a84b |
const struct hash_entry *e;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
iter->entry++;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (iter->entry >= b->used) {
|
|
Packit Service |
80a84b |
iter->entry = 0;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
for (iter->bucket++; iter->bucket < iter->hash->n_buckets;
|
|
Packit Service |
80a84b |
iter->bucket++) {
|
|
Packit Service |
80a84b |
b = iter->hash->buckets + iter->bucket;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (b->used > 0)
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (iter->bucket >= iter->hash->n_buckets)
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
e = b->entries + iter->entry;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (value != NULL)
|
|
Packit Service |
80a84b |
*value = e->value;
|
|
Packit Service |
80a84b |
if (key != NULL)
|
|
Packit Service |
80a84b |
*key = e->key;
|
|
Packit Service |
80a84b |
if (keylen != NULL)
|
|
Packit Service |
80a84b |
*keylen = e->keylen;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
}
|