201 lines
4.5 KiB
C
201 lines
4.5 KiB
C
|
|
#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;
|
|
}
|