X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fhash.h;h=11d132a49f9bb3f49cd1facbee72b56f586dda49;hb=ac2a1722b71e98010324ed46235e96bfa6e672f5;hp=c26e7acd66ee95e7980f89f73f88f0e443a1e744;hpb=6b6a025488f289f749498a7e6cc1994be19f53e8;p=tinc diff --git a/src/hash.h b/src/hash.h index c26e7acd..11d132a4 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,3 +1,6 @@ +#ifndef TINC_HASH_H +#define TINC_HASH_H + /* hash.h -- header file for hash.c Copyright (C) 2012 Guus Sliepen @@ -17,25 +20,66 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_HASH_H__ -#define __TINC_HASH_H__ -typedef struct hash_t { - size_t n; - size_t size; - char *keys; - const void **values; -} hash_t; +/* Map 32 bits int onto 0..n-1, without throwing away too many bits if n is 2^8 or 2^16 */ + +uint32_t modulo(uint32_t hash, size_t n); + +#define HASH_SEARCH_ITERATIONS 4 -extern hash_t *hash_alloc(size_t n, size_t size) __attribute__ ((__malloc__)); -extern void hash_free(hash_t *); +#define hash_insert(t, ...) hash_insert_ ## t (__VA_ARGS__) +#define hash_delete(t, ...) hash_delete_ ## t (__VA_ARGS__) +#define hash_search(t, ...) hash_search_ ## t (__VA_ARGS__) +#define hash_clear(t, n) hash_clear_ ## t ((n)) -extern void hash_insert(hash_t *, const void *key, const void *value); +#define hash_define(t, n) \ + typedef struct hash_ ## t { \ + t keys[n]; \ + const void *values[n]; \ + } hash_ ## t; \ + static uint32_t inline hash_modulo_ ## t(uint32_t hash) { \ + return hash & (n - 1); \ + } \ + void hash_insert_ ## t (hash_ ##t *hash, const t *key, const void *value) { \ + uint32_t i = hash_modulo_ ## t(hash_function_ ## t(key)); \ + for(uint8_t f=0; f< (HASH_SEARCH_ITERATIONS - 1); f++){ \ + if(hash->values[i] == NULL || !memcmp(key, &hash->keys[i], sizeof(t))) { \ + memcpy(&hash->keys[i], key, sizeof(t)); \ + hash->values[i] = value; \ + return; \ + } \ + if(++i == n) i = 0; \ + } \ + /* We always pick the last slot. It's unfair. But thats life */ \ + memcpy(&hash->keys[i], key, sizeof(t)); \ + hash->values[i] = value; \ + } \ + void *hash_search_ ## t (const hash_ ##t *hash, const t *key) { \ + uint32_t i = hash_modulo_ ## t(hash_function_ ## t(key)); \ + for(uint8_t f=0; fkeys[i], sizeof(t))) { \ + return (void *)hash->values[i]; \ + } \ + if(++i == n) i = 0; \ + } \ + return NULL; \ + } \ + void hash_delete_ ## t (hash_ ##t *hash, const t *key) { \ + uint32_t i = hash_modulo_ ## t(hash_function_ ## t(key)); \ + for(uint8_t f=0; fkeys[i], sizeof(t))) { \ + hash->values[i] = NULL; \ + return; \ + } \ + if(++i == n) i = 0; \ + } \ + } \ + void hash_clear_ ## t(hash_ ##t *hash) { \ + memset(hash->values, 0, n * sizeof(*hash->values)); \ + memset(hash->keys, 0, n * sizeof(*hash->keys)); \ + } -extern void *hash_search(const hash_t *, const void *key); -extern void *hash_search_or_insert(hash_t *, const void *key, const void *value); -extern void hash_clear(hash_t *); -extern void hash_resize(hash_t *, size_t n); +#define hash_new(t, name) static hash_ ## t name -#endif /* __TINC_HASH_H__ */ +#endif