diff --git a/src/hash.c b/src/hash.c index fa2053f..173d79b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1,17 +1,23 @@ +#include #include +#include #include "types.h" #include "hash.h" #include "config.h" -int init_hashmap(HashMap *map){ - map->curr_len = 64; - map->buffer = malloc(sizeof(MapItem)*64); - map->bit_free = malloc(64/32); - map->load_factor = 0; +int heap_hashmap(HashMap *map, i32 size){ + if(size < 32) + return 1; + map->curr_len = size; + map->buffer = malloc(sizeof(MapItem)*size); + map->bit_free = malloc(sizeof(u32)*size/32); if(!map->buffer || !map->bit_free) return 1; + + memset(map->bit_free, 0, sizeof(u32)*size/32); + return 0; } @@ -36,3 +42,77 @@ u32 hash(i32 max, char *str){ #endif return hsh; } + +i32 get_bit(u32 *bitmap, i32 pos){ + return (bitmap[pos/32] >> (pos%32)) & 1; +} + +void set_bit(u32 *bitmap, i32 pos){ + bitmap[pos/32] |= (1<<(pos%32)); +} + +u32 hashmap_insert(HashMap *map, char *str){ + #if DEBUG > 0 + float load_factor = (float)(map->item_n+1)/(float)(map->curr_len); + printf("%f\n", load_factor); + #if DEBUG == 1 + assert(load_factor < 0.95); + #else + assert(load_factor < 0.8); + #endif + #endif + + if(map->item_n+1 >= map->curr_len) + return HASH_NULL; + u32 hsh = hash(map->curr_len, str); + char *match = hashmap_get(map, hsh); + if(match){ + if(!strncmp(match, str, 32)) + return hsh; + } + + if(!map->bit_free[hsh/32]){ + map->buffer[hsh].hash = hsh; + strncpy(map->buffer[hsh].str, str, 32); + set_bit(map->bit_free, hsh); + map->item_n++; + return hsh; + } + + u32 pos = hsh; + i32 can; + do { + can = !get_bit(map->bit_free, pos); + pos++; + } while(pos < map->curr_len && !can); + pos--; + + #if DEBUG == 2 + assert(can); + #endif + + if(can){ + map->buffer[pos].hash = hsh; + strncpy(map->buffer[hsh].str, str, 32); + set_bit(map->bit_free, hsh); + map->item_n++; + return hsh; + } + + return HASH_NULL; +} + +char *hashmap_get(HashMap *map, u32 hash){ + u32 pos = hash; + i32 can; + do { + u32 c_hash = map->buffer[pos].hash; + can = c_hash == hash; + pos++; + } while(!can && pos < map->curr_len); + + if(can) + return map->buffer[pos-1].str; + else + return NULL; +} diff --git a/src/hash.h b/src/hash.h index 292f1dd..fc592ac 100644 --- a/src/hash.h +++ b/src/hash.h @@ -7,6 +7,8 @@ #define HASH_NULL 0xFFFFFF +#define LOAD_EXTEND fix(0.7) + typedef struct { u32 hash; // Hashs are internally 24bit for bytecode ops @@ -19,13 +21,18 @@ typedef struct { MapItem *buffer; u32 *bit_free; // Bit map to track usage u32 curr_len; - fixed_t load_factor; + u32 item_n; } HashMap; -int init_hashmap(HashMap *map); +int heap_hashmap(HashMap *map, i32 size); void free_hashmap(HashMap *map); // Max is max value of hash u32 hash(i32 max, char *str); + +// Returns hash - if error returns HASH_NULL +u32 hashmap_insert(HashMap *map, char *str); + +char *hashmap_get(HashMap *map, u32 hash); diff --git a/src/main.c b/src/main.c index 7ae1fc6..2434651 100644 --- a/src/main.c +++ b/src/main.c @@ -9,20 +9,32 @@ int main(){ HashMap map; - if(init_hashmap(&map)){ + if(heap_hashmap(&map, 32)){ printf("Failed to alloc hashmap"); return 1; } - char *string = "Je mange du fromage"; - char *str2 = "69420"; - char *str3 = "a"; - char *str4 = "func_init_foo_thing"; + char *strings[] = { + "Je mange fromage", + "Les chausettes de l'archiducess", + "sont elles seches, archiseches", + "Now, for something completly dif", + "ferent.", + "Nobody expects the spanish inqui", + "sition !", + "Il est 4H du matin", + "very-long-and-verbose-function", + "Mais punaise de flute" + }; - printf("%d %d %d %d\n", hash(128, string), hash(128,str2), hash(128,str3), - hash(128,str4)); + int hashs[10]; - free_hashmap(&map); + for(int i = 0; i < 10; i++) + hashs[i] = hashmap_insert(&map, strings[i]); + for(int i = 0; i < 10; i++) + printf("%d : %s\n", hashs[i], hashmap_get(&map, hashs[i])); + + free_hashmap(&map); return 0; }