Browse Source

Removing old map.h and adding new ht.h

Vinicius Teshima 1 năm trước cách đây
mục cha
commit
eeedce7b10
2 tập tin đã thay đổi với 201 bổ sung149 xóa
  1. 201 0
      include/toolbox/ht.h
  2. 0 149
      include/toolbox/map.h

+ 201 - 0
include/toolbox/ht.h

@@ -0,0 +1,201 @@
+#ifndef HT_H
+#define HT_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "da.h"
+
+#ifndef typeof
+#define typeof __typeof__
+#endif
+
+#define CONCAT(a, b) CONCAT_INNER(a, b)
+#define CONCAT_INNER(a, b) a ## b
+#define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
+
+typedef uint64_t (*ht_hash_func)(const char *, size_t);
+
+uint64_t ht_default_hash(const char *str, size_t str_size);
+
+#define HT_DEF_STRUCT(type, name)			\
+	struct name##_item {				\
+		struct {				\
+			const char *data;		\
+			size_t size;			\
+		} key_str;				\
+		uint64_t key;				\
+		type data;				\
+		void *next;				\
+	};						\
+	struct name {					\
+		struct name##_item *items;		\
+		size_t size;				\
+		size_t cap;				\
+		DA_DEF_STRUCT_ITEM(uint64_t, keys);	\
+		ht_hash_func hash;			\
+		size_t collisions;			\
+	}
+
+#define HT_DEF_STRUCT_ITEM(type, name)			\
+	struct {					\
+		struct {				\
+			uint64_t key;			\
+			type data;			\
+			void *next;			\
+		} *items;				\
+		size_t size;				\
+		size_t cap;				\
+		ht_hash_func hash;			\
+	} name
+
+
+#define HT_CREATE(ht, init_cap)					\
+	do {								\
+		(ht).cap = (init_cap);					\
+		(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)					\
+	do{								\
+		void *_t = NULL;					\
+		for ( i = 0; i < (ht).cap; ++i ) {			\
+			typeof(*(ht).items) *_hi = &(ht).items[i];	\
+			while( _hi->next != NULL ) {			\
+				_t = _hi;				\
+				_hi = _hi->next;			\
+				free(_t);				\
+			}						\
+		}							\
+		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, _i, _j, _k)				\
+	do {								\
+		typeof((ht)) _ht = {0};				\
+		HT_CREATE(_ht, (ht).cap*2);				\
+		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;			\
+			}						\
+			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;					\
+		}							\
+		HT_DESTROY(ht);					\
+		(ht) = _ht;						\
+	} while(0)
+
+#define HT_INC_CAP(ht)						\
+	_HT_INC_CAP(ht, UNIQUE_NAME(_ht), UNIQUE_NAME(_it),	\
+		    UNIQUE_NAME(_i), UNIQUE_NAME(_j), UNIQUE_NAME(_k))
+
+#include <stdio.h>
+#define _HT_SET(ht, _key, _key_size, val, _k, _it, _i)			\
+	do {								\
+		if ( (ht).size + 1 >= (ht).cap ) { \
+			HT_INC_CAP(ht);				\
+		}							\
+		uint64_t _k = (ht).hash((_key), (_key_size));		\
+		typeof(*(ht).items) *_it = &(ht).items[_k % (ht).cap];	\
+		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;						\
+		_it->data = val;					\
+		_it->next = NULL;					\
+		++(ht).size;						\
+	} while(0)
+
+#define HT_SET(ht, key, key_size, val)					\
+	_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 {								\
+		uint64_t _k = (ht).hash((_key), (_key_size));		\
+		typeof(*(ht).items) *_it = &(ht).items[_k % (ht).cap];	\
+		(ret) = _it->data;					\
+	} while(0)
+
+#define HT_GET(ht, key, key_size, ret)					\
+	_HT_GET(ht, key, key_size, ret, UNIQUE_NAME(_k), UNIQUE_NAME(_it))
+
+#if defined(HT_IMP) || defined(IMP)
+
+uint64_t
+ht_default_hash(const char *str, size_t str_size)
+{
+	uint64_t k = (uint64_t)((char)str[0]) << 56;
+	k |= (((uint64_t) (str[1 * (str_size > 1)])) << 48);
+	k |= (((uint64_t) (str[2 * (str_size > 2)])) << 40);
+	k |= (((uint64_t) (str[3 * (str_size > 3)])) << 32);
+	k |= (((uint64_t) (str[(str_size-4) * (str_size >= 4)])) <<  24);
+	k |= (((uint64_t) (str[(str_size-3) * (str_size >= 3)])) <<  16);
+	k |= (((uint64_t) (str[(str_size-2) * (str_size >= 2)])) <<  8);
+	k |= (((uint64_t) (str[(str_size-1) * (str_size >= 1)])) <<  0);
+	return k + ((uint64_t)str[4 * (str_size > 4)] * 31)
+		 + ((uint64_t)str[(str_size-5) * (str_size >= 5)] * 13)
+		+ ((uint64_t)str[str_size/2] * 41);
+	/* static uint8_t _primes_list[] = { */
+	/* 	3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, */
+	/* 	61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, */
+	/* 	131, 137, 139, 149, 151, 157, 163, 167, 173 */
+	/* }; */
+	/* static uint8_t _primes_list_size = 8; */
+	/* uint64_t max = UINT64_MAX >> 1; */
+	/* uint64_t ret = 1; */
+	/* uint8_t p = 0; */
+	/* size_t i = 0; */
+	/* uint8_t b = 0; */
+
+	/* for ( i = 0; i < str_size; ++i ) { */
+	/* 	b = (uint8_t)str[i]; */
+	/* 	p = _primes_list[(i + b) & _primes_list_size]; */
+	/* 	ret = (ret * (b * p)) % max; */
+	/* } */
+
+	/* return ret; */
+}
+
+
+#endif /* defined(HT_IMP) || defined(IMP) */
+
+#undef CONCAT
+#undef CONCAT_INNER
+#undef UNIQUE_NAME
+
+#endif

+ 0 - 149
include/toolbox/map.h

@@ -1,149 +0,0 @@
-#ifndef MAP_H
-#define MAP_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifndef MAP_MAX_SIZE
-#define MAP_MAX_SIZE 5000
-#endif /* MAP_MAX_SIZE */
-
-struct map_item {
-	void *data;
-	size_t size;
-	const uint64_t hkey;
-	struct map_item *hit;
-};
-
-struct map {
-	/* uint64_t *hkeys; */
-	struct map_item *items;
-	size_t size;
-};
-
-struct map* map_create();
-
-__attribute__((access (read_write, 1), access (read_only, 2),
-	       access (read_only, 3), nonnull))
-void map_add(struct map *__restrict__ map, const char *__restrict__ key,
-	     void *__restrict__ data, size_t size);
-
-__attribute__((access (read_write, 1), access (read_only, 3), nonnull))
-void map_add_h(struct map *__restrict__ map, uint64_t hkey,
-	       void *__restrict__ data, size_t size);
-
-__attribute__((access (read_only, 1), access (read_only, 2), nonnull))
-void* map_get(struct map const *__restrict__ map, const char *__restrict__ key);
-__attribute__((access (read_only, 1), nonnull))
-void* map_get_h(struct map const *__restrict__ map, uint64_t hkey);
-
-__attribute__((access (read_only, 1), access (read_only, 2), nonnull))
-struct map_item* map_get_item(struct map const *__restrict__ map,
-			      const char *__restrict__ key);
-
-__attribute__((access (read_only, 1), nonnull))
-struct map_item* map_get_item_h(struct map const *__restrict__ map,
-				uint64_t hkey);
-
-__attribute__((access (read_write, 1), nonnull))
-void map_destroy(struct map *map);
-
-#define MAP_IMP
-#if defined(MAP_IMP) || defined(IMPLEMENTATIONS)
-
-#define HASH_IMP
-#include "./hash.h"
-#undef HASH_IMP
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-struct map* map_create() {
-	/* NOTE: Should probraly do something more here */
-	struct map *ret = calloc(1, sizeof(struct map));
-	if ( ret == NULL ) {
-		fprintf(stderr, "[ERROR] Failed to calloc: map_create\n");
-		exit(EXIT_FAILURE);
-	}
-	ret->items = calloc(MAP_MAX_SIZE, sizeof(struct map_item));
-	if ( ret->items == NULL ) {
-		fprintf(stderr, "[ERROR] Failed to calloc: map_create\n");
-		exit(EXIT_FAILURE);
-	}
-	return ret;
-}
-
-void map_add(struct map *__restrict__ map, const char *__restrict__ key,
-	     void *__restrict__ data, size_t size) {
-	map_add_h(map, hash(key, strlen(key)), data, size);
-}
-
-void map_add_h(struct map *__restrict__ map, uint64_t hkey,
-	       void *__restrict__ data, size_t size) {
-	struct map_item *pitem = &map->items[hkey % MAP_MAX_SIZE];
-
-	while ( pitem->data != NULL ) {
-		if ( pitem->hit == NULL ) {
-			pitem->hit = calloc(1, sizeof(struct map_item));
-			if ( pitem->hit == NULL ) {
-				fprintf(stderr, "[ERROR] Failed to calloc: map_add\n");
-				exit(EXIT_FAILURE);
-			}
-		}
-		pitem = pitem->hit;
-	}
-
-	pitem->data = calloc(1, size);
-	if ( pitem->data == NULL ) {
-		fprintf(stderr, "[ERROR] Failed to calloc: map_add\n");
-		exit(EXIT_FAILURE);
-	}
-
-	pitem->size = size;
-	memcpy(pitem->data, data, size);
-
-	/* const kkkkkk */
-	*(uint64_t*) &pitem->hkey = hkey;
-}
-
-void* map_get(struct map const *__restrict__ map,
-	      const char *__restrict__ key) {
-	return map_get_h(map, hash(key, strlen(key)));
-}
-void* map_get_h(struct map const *__restrict__ map, uint64_t hkey) {
-	struct map_item *pitem = map_get_item_h(map, hkey);
-	if ( pitem == NULL ) {
-		return NULL;
-	}
-
-	return pitem->data;
-}
-
-struct map_item* map_get_item(struct map const *__restrict__ map,
-			      const char *__restrict__ key) {
-	return map_get_item_h(map, hash(key, strlen(key)));
-}
-
-struct map_item* map_get_item_h(struct map const *__restrict__ map,
-				uint64_t hkey) {
-	struct map_item *pitem = &map->items[hkey % MAP_MAX_SIZE];
-
-	while ( pitem->hkey != hkey) {
-		if ( pitem->hit == NULL ) {
-			return NULL;
-		}
-
-		pitem = pitem->hit;
-	}
-
-	return pitem;
-}
-
-void map_destroy(struct map *map) {
-	(void) map;
-}
-
-#endif /* MAP_IMP || IMPLEMENTATIONS */
-
-#endif /* MAP_H */