ref: 3866717cbb020199d58171c1c0cdd7382a74ee82
dir: /liblogfs/map.c/
#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;
}