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 <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
int init_hashmap(HashMap *map){
|
int heap_hashmap(HashMap *map, i32 size){
|
||||||
map->curr_len = 64;
|
if(size < 32)
|
||||||
map->buffer = malloc(sizeof(MapItem)*64);
|
return 1;
|
||||||
map->bit_free = malloc(64/32);
|
map->curr_len = size;
|
||||||
map->load_factor = 0;
|
map->buffer = malloc(sizeof(MapItem)*size);
|
||||||
|
map->bit_free = malloc(sizeof(u32)*size/32);
|
||||||
|
|
||||||
if(!map->buffer || !map->bit_free)
|
if(!map->buffer || !map->bit_free)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
memset(map->bit_free, 0, sizeof(u32)*size/32);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,3 +42,77 @@ u32 hash(i32 max, char *str){
|
||||||
#endif
|
#endif
|
||||||
return hsh;
|
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 HASH_NULL 0xFFFFFF
|
||||||
|
|
||||||
|
#define LOAD_EXTEND fix(0.7)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
u32 hash; // Hashs are internally 24bit for bytecode ops
|
u32 hash; // Hashs are internally 24bit for bytecode ops
|
||||||
|
@ -19,13 +21,18 @@ typedef struct {
|
||||||
MapItem *buffer;
|
MapItem *buffer;
|
||||||
u32 *bit_free; // Bit map to track usage
|
u32 *bit_free; // Bit map to track usage
|
||||||
u32 curr_len;
|
u32 curr_len;
|
||||||
fixed_t load_factor;
|
u32 item_n;
|
||||||
|
|
||||||
} HashMap;
|
} HashMap;
|
||||||
|
|
||||||
int init_hashmap(HashMap *map);
|
int heap_hashmap(HashMap *map, i32 size);
|
||||||
|
|
||||||
void free_hashmap(HashMap *map);
|
void free_hashmap(HashMap *map);
|
||||||
|
|
||||||
// Max is max value of hash
|
// Max is max value of hash
|
||||||
u32 hash(i32 max, char *str);
|
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(){
|
int main(){
|
||||||
HashMap map;
|
HashMap map;
|
||||||
if(init_hashmap(&map)){
|
if(heap_hashmap(&map, 32)){
|
||||||
printf("Failed to alloc hashmap");
|
printf("Failed to alloc hashmap");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *string = "Je mange du fromage";
|
char *strings[] = {
|
||||||
char *str2 = "69420";
|
"Je mange fromage",
|
||||||
char *str3 = "a";
|
"Les chausettes de l'archiducess",
|
||||||
char *str4 = "func_init_foo_thing";
|
"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),
|
int hashs[10];
|
||||||
hash(128,str4));
|
|
||||||
|
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);
|
free_hashmap(&map);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue