Files
my-os-project2/kernel/hshtb.h

85 lines
2.3 KiB
C

#ifndef HSHTB_H_
#define HSHTB_H_
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "hal/hal.h"
#include "util/util.h"
#define HSHTB_FNV32_OFF 0x811c9dc5u
#define HSHTB_FNV32_PRIME 0x01000193u
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 ^= p[i];
h *= HSHTB_FNV32_PRIME;
}
return h;
}
enum {
HSHTB_EMPTY = 0,
HSHTB_TAKEN = 1,
HSHTB_TOMB = 2,
};
#define HSHTB_ALLOC(tb, keyfield, k, out) \
do { \
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)[__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; \
} \
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, keyfield, k, out) \
do { \
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 ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \
break; \
} \
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_