libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

map.c (2329B)


      1 /* Written by Kris Maglione */
      2 /* Public domain */
      3 #include <stdlib.h>
      4 #include "ixp_local.h"
      5 
      6 /* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g  x/^([^a-zA-Z]|static|$)/-+d  s/ (\*map|val|*str)//g */
      7 
      8 struct MapEnt {
      9 	ulong		hash;
     10 	const char*	key;
     11 	void*		val;
     12 	MapEnt*		next;
     13 };
     14 
     15 MapEnt *NM;
     16 
     17 static void
     18 insert(MapEnt **e, ulong val, const char *key) {
     19 	MapEnt *te;
     20 	
     21 	te = emallocz(sizeof *te);
     22 	te->hash = val;
     23 	te->key = key;
     24 	te->next = *e;
     25 	*e = te;
     26 }
     27 
     28 static MapEnt**
     29 map_getp(IxpMap *map, ulong val, bool create, bool *exists) {
     30 	MapEnt **e;
     31 
     32 	e = &map->bucket[val%map->nhash];
     33 	for(; *e; e = &(*e)->next)
     34 		if((*e)->hash >= val) break;
     35 	if(exists)
     36 		*exists = *e && (*e)->hash == val;
     37 
     38 	if(*e == nil || (*e)->hash != val) {
     39 		if(create)
     40 			insert(e, val, nil);
     41 		else
     42 			e = &NM;
     43 	}
     44 	return e;
     45 }
     46 
     47 void
     48 ixp_mapfree(IxpMap *map, void (*destroy)(void*)) {
     49 	int i;
     50 	MapEnt *e;
     51 
     52 	thread->wlock(&map->lock);
     53 	for(i=0; i < map->nhash; i++)
     54 		while((e = map->bucket[i])) {
     55 			map->bucket[i] = e->next;
     56 			if(destroy)
     57 				destroy(e->val);
     58 			free(e);
     59 		}
     60 	thread->wunlock(&map->lock);
     61 	thread->rwdestroy(&map->lock);
     62 }
     63 
     64 void
     65 ixp_mapexec(IxpMap *map, void (*run)(void*, void*), void *context) {
     66 	int i;
     67 	MapEnt *e;
     68 
     69 	thread->rlock(&map->lock);
     70 	for(i=0; i < map->nhash; i++)
     71 		for(e=map->bucket[i]; e; e=e->next)
     72 			run(context, e->val);
     73 	thread->runlock(&map->lock);
     74 }
     75 
     76 void
     77 ixp_mapinit(IxpMap *map, MapEnt **buckets, int nbuckets) {
     78 
     79 	map->bucket = buckets;
     80 	map->nhash = nbuckets;
     81 
     82 	thread->initrwlock(&map->lock);
     83 }
     84 
     85 bool
     86 ixp_mapinsert(IxpMap *map, ulong key, void *val, bool overwrite) {
     87 	MapEnt *e;
     88 	bool existed, res;
     89 	
     90 	res = true;
     91 	thread->wlock(&map->lock);
     92 	e = *map_getp(map, key, true, &existed);
     93 	if(existed && !overwrite)
     94 		res = false;
     95 	else
     96 		e->val = val;
     97 	thread->wunlock(&map->lock);
     98 	return res;
     99 }
    100 
    101 void*
    102 ixp_mapget(IxpMap *map, ulong val) {
    103 	MapEnt *e;
    104 	void *res;
    105 	
    106 	thread->rlock(&map->lock);
    107 	e = *map_getp(map, val, false, nil);
    108 	res = e ? e->val : nil;
    109 	thread->runlock(&map->lock);
    110 	return res;
    111 }
    112 
    113 void*
    114 ixp_maprm(IxpMap *map, ulong val) {
    115 	MapEnt **e, *te;
    116 	void *ret;
    117 	
    118 	ret = nil;
    119 	thread->wlock(&map->lock);
    120 	e = map_getp(map, val, false, nil);
    121 	if(*e) {
    122 		te = *e;
    123 		ret = te->val;
    124 		*e = te->next;
    125 		thread->wunlock(&map->lock);
    126 		free(te);
    127 	}
    128 	else
    129 		thread->wunlock(&map->lock);
    130 	return ret;
    131 }
    132