Browse Source

[ht.h] Adding key list

Vinicius Teshima 1 năm trước cách đây
mục cha
commit
8633e86327
1 tập tin đã thay đổi với 37 bổ sung25 xóa
  1. 37 25
      src/ht.h

+ 37 - 25
src/ht.h

@@ -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 {								\