Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/map.h

202 lines
4.5 KiB
C
Raw Permalink Normal View History

2025-09-02 14:43:36 +02:00
#define HASHM_BUCKETS 2
uint map_f_inthash(void *ptr) {
uint hash = (uint)((ulong)ptr);
return ((hash << 8) & 0xf000) | ((hash >> 8) & 0x0fff); // (hash >> 24) | ((hash >> 8) & 0x0000ff00) | ((hash << 8) & 0x00ff0000) | (hash << 24);
}
byte map_f_inteq(void *ptr1, void *ptr2) {
return ptr1 == ptr2;
}
uint map_f_strhash(void *str) {
int pos = 0;
uint hash = 0;
uint c;
while(c = (uint)(((char*)str)[pos++])) {
hash = 31 * hash + c;
}
return hash;
}
byte map_f_streq(void *str1, void *str2) {
return strcmp((char*)str1, (char*)str2) == 0;
}
void map_init(map_t *map, map_hashfunc *hash, map_eqfunc *eq, uint load, byte cat) {
map->hash_func = hash;
map->eq_func = eq;
map->elems = NULL;
map->load = load;
map->cat = cat;
map->stored = 0;
}
/*
void **map_talloc(void ***ptr, byte offset) {
void **list = *ptr;
if(list == NULL) {
*ptr = list = mem_alloc(sizeof(void **) * 256);
memset(list, 0, sizeof(void **) * 256);
}
return list[offset];
}
*/
byte map_put(map_t *map, void *key, void *elem) {
uint hash = map->hash_func(key);
uint offset;
uint size;
void ***ptr = &map->elems;
void **list = *ptr;
void **elems;
uint stored;
for(int z = HASHM_BUCKETS - 1; z >= 0; z--) {
offset = (hash >> (z << 3)) & 0xff;
// list = *ptr;
if(list == NULL) {
*ptr = list = mem_alloc(sizeof(void **) * 256, map->cat);
memset(list, 0, sizeof(void **) * 256);
}
ptr = (void***)&list[offset];
list = list[offset];
}
if(list == NULL) {
*ptr = list = mem_alloc(sizeof(void *) * map->load * 2 + sizeof(uint) * 2, map->cat);
memset(list, 0, sizeof(void *) * map->load * 2 + sizeof(uint) * 2);
((uint*)list)[0] = size = map->load;
stored = 0;
}
else {
size = ((uint*)list)[0];
stored = ((uint*)list)[1];
}
elems = (void**)(((uint*)list) + 2);
for(uint z = 0; z < size; z++) {
if((elems[z*2] != NULL) && map->eq_func(key, elems[z*2])) {
elems[z*2+0] = key;
elems[z*2+1] = elem;
return 0;
}
}
if(stored == size) {
*ptr = list = mem_realloc(list, sizeof(void *) * (size+(map->load)) * 2 + sizeof(uint) * 2, map->cat);
elems = (void**)(((uint*)list) + 2);
memset(&elems[size*2], 0, sizeof(void *) * map->load * 2); // + sizeof(uint) * 2);
((uint*)list)[0] = size += map->load;
}
for(uint z = 0; z < size; z++) {
if(elems[z*2] == NULL) {
elems[z*2+0] = key;
elems[z*2+1] = elem;
break;
}
}
((uint*)list)[1] = stored + 1;
map->stored += 1;
return 1;
}
void *map_get(map_t *map, void *key) {
uint hash = map->hash_func(key);
uint offset;
uint size;
void **list = map->elems;
void **elems;
for(int z = HASHM_BUCKETS - 1; z >= 0; z--) {
if(list == NULL) {
return NULL;
}
offset = (hash >> (z << 3)) & 0xff;
list = list[offset];
}
if(list == NULL) {
return NULL;
}
size = ((uint*)list)[0];
elems = (void**)(((uint*)list) + 2);
for(uint z = 0; z < size; z++) {
if((elems[z*2] != NULL) && map->eq_func(key, elems[z*2+0])) {
return elems[z*2+1];
}
}
return NULL;
}
void *map_remove(map_t *map, void *key) {
uint hash = map->hash_func(key);
uint offset;
uint size;
uint stored;
void **lists[HASHM_BUCKETS];
void **list = map->elems;
void **elems;
void *elem;
int s;
for(int z = HASHM_BUCKETS - 1; z >= 0; z--) {
if(list == NULL) {
return NULL;
}
offset = (hash >> (z << 3)) & 0xff;
lists[z] = list;
list = list[offset];
}
size = ((uint*)list)[0];
stored = ((uint*)list)[1];
elems = (void**)(((uint*)list) + 2);
for(uint z = 0; z < size; z++) {
if((elems[z*2] != NULL) && map->eq_func(key, elems[z*2+0])) {
elem = elems[z*2+1];
elems[z*2+0] = elems[z*2+1] = NULL;
((uint*)list)[1] = stored -= 1;
// logd("t", "s %d", stored);
if(stored == 0) {
mem_free(list);
for(int n = 0; n < HASHM_BUCKETS; n++) {
// if(lists[n] == NULL) {
// break;
// }
lists[n][(hash >> (n << 3)) & 0xff] = NULL;
for(s = 0; s < 256; s++) {
if(lists[n][s] != NULL) {
break;
}
}
if(s == 256) {
mem_free(lists[n]);
if(n == HASHM_BUCKETS - 1) {
map->elems = NULL;
}
else {
lists[n+1][(hash >> ((n+1) << 3)) & 0xff] = NULL;
}
}
else {
break;
}
}
}
map->stored -= 1;
return elem;
}
}
return NULL;
}
void map_rclear(void **list, int depth) {
for(int z = 0; z < 256 && depth < HASHM_BUCKETS; z++) {
if(list[z] != NULL) {
map_rclear(list[z], depth+1);
}
}
mem_free(list);
}
void map_clear(map_t *map) {
map->stored = 0;
if(map->elems)
map_rclear(map->elems, 0);
map->elems = NULL;
}