|
|
@@ -6,6 +6,8 @@
|
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
|
|
|
|
+#include "da.h"
|
|
|
+
|
|
|
#ifndef typeof
|
|
|
#define typeof __typeof__
|
|
|
#endif
|
|
|
@@ -32,6 +34,7 @@ uint64_t ht_default_hash(const char *str, size_t str_size);
|
|
|
struct name##_item *items; \
|
|
|
size_t size; \
|
|
|
size_t cap; \
|
|
|
+ DA_DEF_STRUCT_ITEM(uint64_t, keys); \
|
|
|
ht_hash_func hash; \
|
|
|
size_t collisions; \
|
|
|
}
|
|
|
@@ -55,6 +58,7 @@ uint64_t ht_default_hash(const char *str, size_t str_size);
|
|
|
(ht).size = 0; \
|
|
|
(ht).items = calloc((ht).cap, sizeof(*(ht).items)); \
|
|
|
(ht).hash = ht_default_hash; \
|
|
|
+ DA_CREATE((ht).keys); \
|
|
|
} while(0)
|
|
|
|
|
|
#define _HT_DESTROY(ht, _t, _hi) \
|
|
|
@@ -69,64 +73,71 @@ uint64_t ht_default_hash(const char *str, size_t str_size);
|
|
|
} \
|
|
|
} \
|
|
|
free((ht).items); \
|
|
|
+ free((ht).keys.items); \
|
|
|
} while(0)
|
|
|
|
|
|
#define HT_DESTROY(ht) \
|
|
|
_HT_DESTROY(ht, UNIQUE_NAME(_t), UNIQUE_NAME(_hi))
|
|
|
|
|
|
|
|
|
-#define _HT_INC_CAP(ht, _ht, _it) \
|
|
|
+#define _HT_INC_CAP(ht, _ht, _it, _i, _j, _k) \
|
|
|
do { \
|
|
|
typeof((ht)) _ht = {0}; \
|
|
|
HT_CREATE(_ht, (ht).cap*2); \
|
|
|
- for ( i = 0; i < (ht).cap; ++i ) { \
|
|
|
- typeof(*(ht).items) _hi = (ht).items[i]; \
|
|
|
- typeof(*(_ht).items) *_it = &_ht.items[_hi.key \
|
|
|
- % _ht.cap]; \
|
|
|
- if ( _it->key != 0 && _it->key != _hi.key ) { \
|
|
|
- while( _it->next != NULL ) { \
|
|
|
- _it = _it->next; \
|
|
|
- } \
|
|
|
- _it->next = malloc(sizeof(*(_ht).items)); \
|
|
|
- _it = _it->next; \
|
|
|
- ++(ht).collisions; \
|
|
|
+ for ( size_t _i = 0; _i < (ht).keys.size; ++_i ) { \
|
|
|
+ uint64_t _k = (ht).keys.items[_i]; \
|
|
|
+ typeof(*(ht).items) _hi = (ht).items[_k % (ht).cap]; \
|
|
|
+ uint64_t _j = 0; \
|
|
|
+ while( _hi.key != _k) { \
|
|
|
+ _hi = (ht).items[(_k + ++_j) % (ht).cap]; \
|
|
|
+ } \
|
|
|
+ typeof(*_ht.items) *_it = &_ht.items[_hi.key \
|
|
|
+ % _ht.cap]; \
|
|
|
+ _j = _hi.key; \
|
|
|
+ while ( _it->key != 0 && _it->key != _hi.key ) { \
|
|
|
+ _it = &_ht.items[(++_j) % _ht.cap]; \
|
|
|
+ ++_ht.collisions; \
|
|
|
} \
|
|
|
if ( _it->key == _hi.key ) { \
|
|
|
+ printf("\n[ERROR] Unreachable\n"); \
|
|
|
+ exit(0);\
|
|
|
_it->data = _hi.data; \
|
|
|
- break; \
|
|
|
+ continue; \
|
|
|
} \
|
|
|
+ DA_APPEND(_ht.keys, _hi.key); \
|
|
|
_it->key_str.data = _hi.key_str.data; \
|
|
|
_it->key_str.size = _hi.key_str.size; \
|
|
|
_it->key = _hi.key; \
|
|
|
_it->data = _hi.data; \
|
|
|
_it->next = NULL; \
|
|
|
- ++(_ht).size; \
|
|
|
- _it->next = _hi.next; \
|
|
|
+ ++_ht.size; \
|
|
|
} \
|
|
|
HT_DESTROY(ht); \
|
|
|
(ht) = _ht; \
|
|
|
} while(0)
|
|
|
|
|
|
-#define HT_INC_CAP(ht) \
|
|
|
- _HT_INC_CAP(ht, UNIQUE_NAME(_ht), UNIQUE_NAME(_it))
|
|
|
+#define HT_INC_CAP(ht) \
|
|
|
+ _HT_INC_CAP(ht, UNIQUE_NAME(_ht), UNIQUE_NAME(_it), \
|
|
|
+ UNIQUE_NAME(_i), UNIQUE_NAME(_j), UNIQUE_NAME(_k))
|
|
|
|
|
|
|
|
|
-#define _HT_SET(ht, _key, _key_size, val, _k, _it) \
|
|
|
+#define _HT_SET(ht, _key, _key_size, val, _k, _it, _i) \
|
|
|
do { \
|
|
|
+ if ( (ht).size + 1 >= (ht).cap ) { \
|
|
|
+ break; \
|
|
|
+ } \
|
|
|
uint64_t _k = (ht).hash((_key), (_key_size)); \
|
|
|
typeof(*(ht).items) *_it = &(ht).items[_k % (ht).cap]; \
|
|
|
- if ( _it->key != 0 && _it->key != _k ) { \
|
|
|
- while( _it->next != NULL ) { \
|
|
|
- _it = _it->next; \
|
|
|
- } \
|
|
|
- _it->next = malloc(sizeof(*(ht).items)); \
|
|
|
- _it = _it->next; \
|
|
|
+ uint64_t _i = _k; \
|
|
|
+ while ( _it->key != 0 && _it->key != _k ) { \
|
|
|
+ _it = &(ht).items[(++_i) % (ht).cap]; \
|
|
|
++(ht).collisions; \
|
|
|
} \
|
|
|
if ( _it->key == _k ) { \
|
|
|
_it->data = val; \
|
|
|
break; \
|
|
|
} \
|
|
|
+ DA_APPEND((ht).keys, _k); \
|
|
|
_it->key_str.data = _key; \
|
|
|
_it->key_str.size = _key_size; \
|
|
|
_it->key = _k; \
|
|
|
@@ -136,7 +147,8 @@ uint64_t ht_default_hash(const char *str, size_t str_size);
|
|
|
} while(0)
|
|
|
|
|
|
#define HT_SET(ht, key, key_size, val) \
|
|
|
- _HT_SET(ht, key, key_size, val, UNIQUE_NAME(_k), UNIQUE_NAME(_it))
|
|
|
+ _HT_SET(ht, key, key_size, val, \
|
|
|
+ UNIQUE_NAME(_k), UNIQUE_NAME(_it), UNIQUE_NAME(_i))
|
|
|
|
|
|
#define _HT_GET(ht, _key, _key_size, ret, _k, _it) \
|
|
|
do { \
|