#include "logfsos.h" #include "logfs.h" #include "local.h" typedef struct MapNode MapNode; struct MapNode { MapNode *next; uchar e[1]; // entry goes here, inline }; struct Map { int size; int (*hash)(void *key, int size); int (*compare)(void *entry, void *key); int (*allocsize)(void *key); void (*free)(void *entry); MapNode *head[1]; }; char * logfsmapnew(int size, int (*hash)(void *key, int size), int (*compare)(void *entry, void *key), int (*allocsize)(void *key), void (*free)(void *), Map **mapp) { Map *p; *mapp = p = logfsrealloc(nil, sizeof(Map) + (size - 1) * sizeof(MapNode *)); if(p == nil) return Enomem; p->size = size; p->hash = hash; p->compare = compare; p->allocsize = allocsize; p->free = free; return nil; } void logfsmapfree(FidMap **mp) { FidMap *m; int i; m = *mp; if(m == nil) return; for(i = 0; i < m->size; i++) { MapNode *n, *next; n = m->head[i]; while(n) { next = n->next; if(m->free) (*m->free)(n->e); logfsfreemem(n); n = next; } } logfsfreemem(m); *mp = nil; } static char * find(FidMap *m, void *key, int create, void **ep) { MapNode *n; int i; i = (*m->hash)(key, m->size); n = m->head[i]; while(n && !(*m->compare)(n->e, key)) n = n->next; if(n) { if(create) { *ep = nil; return nil; } *ep = n->e; return nil; } if(!create) { *ep = nil; return nil; } n = logfsrealloc(nil, (*m->allocsize)(key) + sizeof(MapNode *)); if(n == nil) { *ep = nil; return Enomem; } n->next = m->head[i]; m->head[i] = n; *ep = n->e; return nil; } void * logfsmapfindentry(Map *m, void *key) { void *rv; find(m, key, 0, &rv); return rv; } char * logfsmapnewentry(Map *m, void *key, void **entryp) { return find(m, key, 1, entryp); } int logfsmapdeleteentry(Map *m, void *key) { MapNode **np, *n; np = &m->head[(*m->hash)(key, m->size)]; while((n = *np) && !(*m->compare)(n->e, key)) np = &n->next; if(n) { *np = n->next; if(m->free) (*m->free)(n->e); logfsfreemem(n); return 1; } return 0; // not there } int logfsmapwalk(Map *m, int (*func)(void *magic, void *), void *magic) { int x; MapNode *n; for(x = 0; x < m->size; x++) for(n = m->head[x]; n; n = n->next) { int rv = (*func)(magic, n->e); if(rv <= 0) return rv; } return 1; }