This commit is contained in:
attilavs2 2025-03-04 22:28:32 +01:00
parent 5f8cf91f8d
commit ea076227ef
3 changed files with 114 additions and 15 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);