Rewrite the kernel hashtable struct
This commit is contained in:
@ -4,47 +4,81 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/hal.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#define HSHTB_FNV32_BASE 0x811c9dc5
|
||||
#define HSHTB_FNV32_OFF 0x811c9dc5u
|
||||
#define HSHTB_FNV32_PRIME 0x01000193u
|
||||
|
||||
static inline uint32_t hshtb_fnv32(char *s, size_t len) {
|
||||
uint32_t h = HSHTB_FNV32_BASE;
|
||||
static inline uint32_t hshtb_fnv32(const void *data, size_t len) {
|
||||
const unsigned char *p = (const unsigned char *)data;
|
||||
uint32_t h = HSHTB_FNV32_OFF;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
h ^= s[i];
|
||||
h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
|
||||
h ^= p[i];
|
||||
h *= HSHTB_FNV32_PRIME;
|
||||
}
|
||||
return h >> 8;
|
||||
return h;
|
||||
}
|
||||
|
||||
#define HSHTB_ALLOC(tb, name, k, keyname, out) \
|
||||
enum {
|
||||
HSHTB_EMPTY = 0,
|
||||
HSHTB_TAKEN = 1,
|
||||
HSHTB_TOMB = 2,
|
||||
};
|
||||
|
||||
#define HSHTB_ALLOC(tb, keyfield, k, out) \
|
||||
do { \
|
||||
size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \
|
||||
size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \
|
||||
size_t i = idx; \
|
||||
size_t __len = sizeof((tb)) / sizeof((tb)[0]); \
|
||||
uint32_t __h = hshtb_fnv32((k), strlen((k))); \
|
||||
size_t __idx = __h % __len; \
|
||||
size_t __start = __idx; \
|
||||
typeof(&(tb)[0]) __tomb = NULL; \
|
||||
do { \
|
||||
if (!(tb)->name[i].taken) { \
|
||||
(out) = &((tb)->name[i]); \
|
||||
hal_memset((out), 0, sizeof(*(out))); \
|
||||
(out)->taken = true; \
|
||||
hal_memcpy((out)->keyname, k, hal_strlen(k)); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
|
||||
typeof(&(tb)[0]) __slot = __tomb ? __tomb : &(tb)[__idx]; \
|
||||
hal_memset(__slot, 0, sizeof(*__slot)); \
|
||||
__slot->_hshtbstate = HSHTB_TAKEN; \
|
||||
hal_memcpy(__slot->keyfield, (k), MIN(sizeof(__slot->keyfield) - 1, hal_strlen((k)))); \
|
||||
(out) = __slot; \
|
||||
break; \
|
||||
} \
|
||||
i = (i + 1) % len; \
|
||||
} while(i != idx); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \
|
||||
(out) = &(tb)[__idx]; \
|
||||
break; \
|
||||
} \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_TOMB && !__tomb) { \
|
||||
__tomb = &(tb)[__idx]; \
|
||||
} \
|
||||
__idx = (__idx + 1) % __len; \
|
||||
} while(__idx != __start); \
|
||||
} while(0)
|
||||
|
||||
#define HSHTB_GET(tb, name, k, keyname, out) \
|
||||
#define HSHTB_GET(tb, keyfield, k, out) \
|
||||
do { \
|
||||
size_t len = sizeof((tb)->name) / sizeof((tb)->name[0]); \
|
||||
size_t idx = hshtb_fnv32(k, hal_strlen(k)) % len; \
|
||||
size_t i = idx; \
|
||||
size_t __len = sizeof((tb)) / sizeof((tb)[0]); \
|
||||
uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \
|
||||
size_t __idx = __h % __len; \
|
||||
size_t __start = __idx; \
|
||||
(out) = NULL; \
|
||||
do { \
|
||||
if (hal_memcmp((tb)->name[i].keyname, k, hal_strlen(k)) == 0) { \
|
||||
(out) = &((tb)->name[i]); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
|
||||
break; \
|
||||
} \
|
||||
i = (i + 1) % len; \
|
||||
} while(i != idx); \
|
||||
if ((tb)[__idx]._hshtbstate == HSHTB_TAKEN && hal_strcmp((tb)[__idx].keyfield, (k)) == 0) { \
|
||||
(out) = &(tb)[__idx]; \
|
||||
break; \
|
||||
} \
|
||||
__idx = (__idx + 1) % __len; \
|
||||
} while(__idx != __start); \
|
||||
} while(0)
|
||||
|
||||
#define HSHTB_DELETE(tb, keyfield, k) \
|
||||
do { \
|
||||
typeof(&(tb)[0]) __e; \
|
||||
HSHTB_GET((tb), (keyfield), (k), __e); \
|
||||
if (__e) { \
|
||||
__e->state = HSHTB_TOMB; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif // HSHTB_H_
|
||||
|
Reference in New Issue
Block a user