summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2014-10-24 08:56:39 +0000
committerkr.angelov <kr.angelov@gmail.com>2014-10-24 08:56:39 +0000
commitdc62e52636795fe802296cef2ddffbb60af38085 (patch)
tree72fa0348550ce62029ea51437bc9b74edbf6b8a7 /src/runtime/c/gu
parent550c74794129890397e98a14560cd072f21a78b8 (diff)
simplify gu/map
Diffstat (limited to 'src/runtime/c/gu')
-rw-r--r--src/runtime/c/gu/map.c118
-rw-r--r--src/runtime/c/gu/map.h2
2 files changed, 39 insertions, 81 deletions
diff --git a/src/runtime/c/gu/map.c b/src/runtime/c/gu/map.c
index d6b8a0c72..87758b110 100644
--- a/src/runtime/c/gu/map.c
+++ b/src/runtime/c/gu/map.c
@@ -5,13 +5,6 @@
#include <gu/prime.h>
#include <gu/string.h>
-typedef enum {
- GU_MAP_GENERIC,
- GU_MAP_ADDR,
- GU_MAP_WORD,
- GU_MAP_STRING
-} GuMapKind;
-
typedef struct GuMapData GuMapData;
struct GuMapData {
@@ -23,7 +16,6 @@ struct GuMapData {
};
struct GuMap {
- GuMapKind kind;
GuHasher* hasher;
size_t key_size;
size_t value_size;
@@ -61,17 +53,16 @@ gu_map_entry_is_free(GuMap* map, GuMapData* data, size_t idx)
{
if (idx == data->zero_idx) {
return false;
- } else if (map->kind == GU_MAP_ADDR) {
+ } else if (map->hasher == gu_addr_hasher) {
const void* key = ((const void**)data->keys)[idx];
return key == NULL;
- } else if (map->kind == GU_MAP_WORD) {
+ } else if (map->hasher == gu_word_hasher) {
GuWord key = ((GuWord*)data->keys)[idx];
return key == 0;
- } else if (map->kind == GU_MAP_STRING) {
+ } else if (map->hasher == gu_string_hasher) {
GuString key = ((GuString*)data->keys)[idx];
return key == NULL;
}
- gu_assert(map->kind == GU_MAP_GENERIC);
const void* key = &data->keys[idx * map->key_size];
return gu_map_buf_is_zero(key, map->key_size);
}
@@ -80,30 +71,7 @@ static bool
gu_map_lookup(GuMap* map, const void* key, size_t* idx_out)
{
size_t n = map->data.n_entries;
- switch (map->kind) {
- case GU_MAP_GENERIC: {
- GuHasher* hasher = map->hasher;
- GuEquality* eq = (GuEquality*) hasher;
- GuHash hash = hasher->hash(hasher, key);
- size_t idx = hash % n;
- size_t offset = (hash % (n - 2)) + 1;
- size_t key_size = map->key_size;
- while (true) {
- void* entry_key = &map->data.keys[idx * key_size];
- if (gu_map_buf_is_zero(entry_key, key_size) &&
- map->data.zero_idx != idx) {
- *idx_out = idx;
- return false;
- } else if (eq->is_equal(eq, key, entry_key)) {
- *idx_out = idx;
- return true;
- }
- idx = (idx + offset) % n;
- }
- gu_impossible();
- break;
- }
- case GU_MAP_ADDR: {
+ if (map->hasher == gu_addr_hasher) {
GuHash hash = (GuHash) key;
size_t idx = hash % n;
size_t offset = (hash % (n - 2)) + 1;
@@ -119,10 +87,7 @@ gu_map_lookup(GuMap* map, const void* key, size_t* idx_out)
}
idx = (idx + offset) % n;
}
- gu_impossible();
- break;
- }
- case GU_MAP_WORD: {
+ } else if (map->hasher == gu_word_hasher) {
GuWord w = *(const GuWord*)key;
GuHash hash = (GuHash) w;
size_t idx = hash % n;
@@ -138,10 +103,7 @@ gu_map_lookup(GuMap* map, const void* key, size_t* idx_out)
}
idx = (idx + offset) % n;
}
- gu_impossible();
- break;
- }
- case GU_MAP_STRING: {
+ } else if (map->hasher == gu_string_hasher) {
GuHasher* hasher = map->hasher;
GuEquality* eq = (GuEquality*) hasher;
GuHash hash = hasher->hash(hasher, key);
@@ -159,12 +121,27 @@ gu_map_lookup(GuMap* map, const void* key, size_t* idx_out)
}
idx = (idx + offset) % n;
}
- gu_impossible();
- break;
- }
- default:
- gu_impossible();
+ } else {
+ GuHasher* hasher = map->hasher;
+ GuEquality* eq = (GuEquality*) hasher;
+ GuHash hash = hasher->hash(hasher, key);
+ size_t idx = hash % n;
+ size_t offset = (hash % (n - 2)) + 1;
+ size_t key_size = map->key_size;
+ while (true) {
+ void* entry_key = &map->data.keys[idx * key_size];
+ if (gu_map_buf_is_zero(entry_key, key_size) &&
+ map->data.zero_idx != idx) {
+ *idx_out = idx;
+ return false;
+ } else if (eq->is_equal(eq, key, entry_key)) {
+ *idx_out = idx;
+ return true;
+ }
+ idx = (idx + offset) % n;
+ }
}
+
gu_impossible();
return false;
}
@@ -194,23 +171,16 @@ gu_map_resize(GuMap* map)
GU_MIN(key_alloc / key_size,
value_alloc / value_size)
: key_alloc / key_size);
- switch (map->kind) {
- case GU_MAP_GENERIC:
- case GU_MAP_WORD:
- memset(data->keys, 0, key_alloc);
- break;
- case GU_MAP_ADDR:
+ if (map->hasher == gu_addr_hasher) {
for (size_t i = 0; i < data->n_entries; i++) {
((const void**)data->keys)[i] = NULL;
}
- break;
- case GU_MAP_STRING:
+ } else if (map->hasher == gu_string_hasher) {
for (size_t i = 0; i < data->n_entries; i++) {
((GuString*)data->keys)[i] = NULL;
}
- break;
- default:
- gu_impossible();
+ } else {
+ memset(data->keys, 0, key_alloc);
}
gu_assert(data->n_entries > data->n_occupied);
@@ -223,9 +193,9 @@ gu_map_resize(GuMap* map)
continue;
}
void* old_key = &old_data.keys[i * key_size];
- if (map->kind == GU_MAP_ADDR) {
+ if (map->hasher == gu_addr_hasher) {
old_key = *(void**)old_key;
- } else if (map->kind == GU_MAP_STRING) {
+ } else if (map->hasher == gu_string_hasher) {
old_key = (void*) *(GuString*)old_key;
}
void* old_value = &old_data.values[i * value_size];
@@ -298,9 +268,9 @@ gu_map_insert(GuMap* map, const void* key)
found = gu_map_lookup(map, key, &idx);
gu_assert(!found);
}
- if (map->kind == GU_MAP_ADDR) {
+ if (map->hasher == gu_addr_hasher) {
((const void**)map->data.keys)[idx] = key;
- } else if (map->kind == GU_MAP_STRING) {
+ } else if (map->hasher == gu_string_hasher) {
((GuString*)map->data.keys)[idx] = key;
} else {
memcpy(&map->data.keys[idx * map->key_size],
@@ -328,9 +298,9 @@ gu_map_iter(GuMap* map, GuMapItor* itor, GuExn* err)
}
const void* key = &map->data.keys[i * map->key_size];
void* value = &map->data.values[i * map->value_size];
- if (map->kind == GU_MAP_ADDR) {
+ if (map->hasher == gu_addr_hasher) {
key = *(const void* const*) key;
- } else if (map->kind == GU_MAP_STRING) {
+ } else if (map->hasher == gu_string_hasher) {
key = *(GuString*) key;
}
itor->fn(itor, key, value, err);
@@ -357,9 +327,9 @@ gu_map_enum_next(GuEnum* self, void* to, GuPool* pool)
}
en->x.key = &en->ht->data.keys[i * en->ht->key_size];
en->x.value = &en->ht->data.values[i * en->ht->value_size];
- if (en->ht->kind == GU_MAP_ADDR) {
+ if (en->ht->hasher == gu_addr_hasher) {
en->x.key = *(const void* const*) en->x.key;
- } else if (en->ht->kind == GU_MAP_STRING) {
+ } else if (en->ht->hasher == gu_string_hasher) {
en->x.key = *(GuString*) en->x.key;
}
@@ -400,17 +370,6 @@ gu_make_map(size_t key_size, GuHasher* hasher,
size_t value_size, const void* default_value,
GuPool* pool)
{
- GuMapKind kind =
- ((!hasher || hasher == gu_addr_hasher)
- ? GU_MAP_ADDR
- : (hasher == gu_string_hasher)
- ? GU_MAP_STRING
- : (key_size == sizeof(GuWord) && hasher == gu_word_hasher)
- ? GU_MAP_WORD
- : GU_MAP_GENERIC);
- if (kind == GU_MAP_ADDR || kind == GU_MAP_STRING) {
- key_size = sizeof(GuWord);
- }
GuMapData data = {
.n_occupied = 0,
.n_entries = 0,
@@ -425,7 +384,6 @@ gu_make_map(size_t key_size, GuHasher* hasher,
map->key_size = key_size;
map->value_size = value_size;
map->fin.fn = gu_map_finalize;
- map->kind = kind;
gu_pool_finally(pool, &map->fin);
gu_map_resize(map);
return map;
diff --git a/src/runtime/c/gu/map.h b/src/runtime/c/gu/map.h
index 813a99372..a1234e99b 100644
--- a/src/runtime/c/gu/map.h
+++ b/src/runtime/c/gu/map.h
@@ -27,7 +27,7 @@ gu_make_map(size_t key_size, GuHasher* hasher,
(gu_make_map(sizeof(K), (HASHER), 0, NULL, (POOL)))
#define gu_new_addr_map(K, V, DV, POOL) \
- (gu_make_map(0, NULL, sizeof(V), (DV), (POOL)))
+ (gu_make_map(sizeof(K), gu_addr_hasher, sizeof(V), (DV), (POOL)))
size_t
gu_map_count(GuMap* map);