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