wmii/lib/libstuff/map.c

132 lines
2.1 KiB
C
Raw Normal View History

2007-04-20 23:25:29 +04:00
/* Written by Kris Maglione */
/* Public domain */
#include <assert.h>
2010-05-22 06:52:47 +04:00
#include <string.h>
#include <stuff/util.h>
2007-04-20 23:25:29 +04:00
/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */
2008-05-31 04:04:02 +04:00
struct MapEnt {
ulong hash;
const char* key;
void* val;
MapEnt* next;
};
2007-04-20 23:25:29 +04:00
MapEnt *NM;
/* By Dan Bernstein. Public domain. */
static ulong
hash(const char *str) {
ulong h;
h = 5381;
while (*str != '\0') {
h += h << 5; /* h *= 33 */
h ^= *str++;
}
return h;
}
static void
insert(Map *m, MapEnt **e, ulong val, const char *key) {
2007-04-20 23:25:29 +04:00
MapEnt *te;
m->nmemb++;
2007-04-20 23:25:29 +04:00
te = emallocz(sizeof *te);
te->hash = val;
te->key = key;
te->next = *e;
*e = te;
}
static MapEnt**
map_getp(Map *map, ulong val, int create) {
2007-04-20 23:25:29 +04:00
MapEnt **e;
e = &map->bucket[val%map->nhash];
for(; *e; e = &(*e)->next)
if((*e)->hash >= val) break;
if(*e == nil || (*e)->hash != val) {
if(create)
insert(map, e, val, nil);
2007-04-20 23:25:29 +04:00
else
e = &NM;
}
return e;
}
static MapEnt**
hash_getp(Map *map, const char *str, int create) {
2007-04-20 23:25:29 +04:00
MapEnt **e;
ulong h;
int cmp;
h = hash(str);
e = map_getp(map, h, create);
2007-04-20 23:25:29 +04:00
if(*e && (*e)->key == nil)
2010-06-02 04:09:25 +04:00
(*e)->key = estrdup(str);
2007-04-20 23:25:29 +04:00
else {
2007-07-03 13:13:01 +04:00
SET(cmp);
2007-04-20 23:25:29 +04:00
for(; *e; e = &(*e)->next)
if((*e)->hash > h || (cmp = strcmp((*e)->key, str)) >= 0)
break;
if(*e == nil || (*e)->hash > h || cmp > 0)
if(create)
2010-06-02 04:09:25 +04:00
insert(map, e, h, estrdup(str));
2007-04-20 23:25:29 +04:00
}
return e;
}
2008-05-31 04:04:02 +04:00
void**
map_get(Map *map, ulong val, bool create) {
MapEnt *e;
2007-04-20 23:25:29 +04:00
2008-05-31 04:04:02 +04:00
e = *map_getp(map, val, create);
return e ? &e->val : nil;
2007-04-20 23:25:29 +04:00
}
2008-05-31 04:04:02 +04:00
void**
hash_get(Map *map, const char *str, bool create) {
MapEnt *e;
2007-04-20 23:25:29 +04:00
2008-05-31 04:04:02 +04:00
e = *hash_getp(map, str, create);
return e ? &e->val : nil;
2007-04-20 23:25:29 +04:00
}
void*
map_rm(Map *map, ulong val) {
2007-04-20 23:25:29 +04:00
MapEnt **e, *te;
void *ret;
ret = nil;
e = map_getp(map, val, 0);
2007-04-20 23:25:29 +04:00
if(*e) {
te = *e;
ret = te->val;
*e = te->next;
assert(map->nmemb-- > 0);
2007-04-20 23:25:29 +04:00
free(te);
}
return ret;
}
void*
hash_rm(Map *map, const char *str) {
2007-04-20 23:25:29 +04:00
MapEnt **e, *te;
void *ret;
ret = nil;
e = hash_getp(map, str, 0);
2007-04-20 23:25:29 +04:00
if(*e) {
te = *e;
ret = te->val;
*e = te->next;
assert(map->nmemb-- > 0);
2010-06-02 04:09:25 +04:00
free((void*)(uintptr_t)te->key);
2007-04-20 23:25:29 +04:00
free(te);
}
return ret;
}
2008-05-31 04:04:02 +04:00