a
This commit is contained in:
parent
5f8cf91f8d
commit
ea076227ef
3 changed files with 114 additions and 15 deletions
90
src/hash.c
90
src/hash.c
|
@ -1,17 +1,23 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
11
src/hash.h
11
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);
|
||||
|
|
26
src/main.c
26
src/main.c
|
@ -9,18 +9,30 @@
|
|||
|
||||
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];
|
||||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue