This commit is contained in:
hyung-hwan 2008-08-23 09:23:09 +00:00
parent 7fb73210b8
commit b6d38c892a
4 changed files with 536 additions and 311 deletions

View File

@ -1,5 +1,5 @@
/*
* $Id: map.h 223 2008-06-26 06:44:41Z baconevi $
* $Id: map.h 344 2008-08-22 15:23:09Z baconevi $
*
* {License}
*/
@ -11,26 +11,71 @@
#include <ase/macros.h>
typedef struct ase_map_t ase_map_t;
typedef struct ase_pair_t ase_pair_t;
typedef struct ase_map_pair_t ase_map_pair_t;
struct ase_pair_t
/* data copier */
typedef void* (*ase_map_copier_t) (
ase_map_t* map,
void* dptr,
ase_size_t dlen
);
/* data freeer */
typedef void (*ase_map_freeer_t) (
ase_map_t* map,
void* dptr,
ase_size_t dlen
);
/* key hasher */
typedef ase_size_t (*ase_map_hasher_t) (
ase_map_t* map /* a map */,
const void* kptr /* the pointer to a key */,
ase_size_t klen /* the length of a key in bytes */
);
/* key comparater */
typedef int (*ase_map_comper_t) (
ase_map_t* map /* a map */,
const void* kptr1 /* the pointer to a key */,
ase_size_t klen1 /* the length of a key in bytes */,
const void* kptr2 /* the pointer to a key */,
ase_size_t klen2 /* the length of a key in bytes */
);
/* pair visitor */
typedef int (*ase_map_walker_t) (
ase_map_t* map,
ase_map_pair_t* pair,
void* arg
);
struct ase_map_pair_t
{
struct
{
ase_char_t* ptr;
ase_size_t len;
} key;
void* kptr;
ase_size_t klen;
void* val;
void* vptr;
ase_size_t vlen;
/* used internally */
ase_pair_t* next;
ase_map_pair_t* next;
};
enum ase_map_id_t
{
ASE_MAP_KEY = 0,
ASE_MAP_VAL = 1
};
struct ase_map_t
{
/* map owner. passed to freeval and sameval as the first argument */
void* owner;
ase_mmgr_t* mmgr;
ase_map_copier_t copier[2];
ase_map_freeer_t freeer[2];
ase_map_hasher_t hasher;
ase_map_comper_t comper;
ase_size_t size;
ase_size_t capa;
@ -38,94 +83,95 @@ struct ase_map_t
unsigned int factor;
ase_size_t threshold;
ase_pair_t** buck;
ase_map_pair_t** buck;
/*
void (*freeval) (void* owner,void* val);
void (*sameval) (void* owner,void* val);
/* the mmgr pointed at by mmgr should be valid
* while the map is alive as the contents are
* not replicated */
ase_mmgr_t* mmgr;
/* list of free pairs */
/*ase_pair_t* fp;*/
*/
void (*sameval) (void* owner, void* vptr, ase_size_t vlen);
};
#define ASE_PAIR_KEYPTR(p) ((p)->key.ptr)
#define ASE_PAIR_KEYLEN(p) ((p)->key.len)
#define ASE_PAIR_VAL(p) ((p)->val)
#define ASE_PAIR_LNK(p) ((p)->next)
#define ASE_MAP_COPIER_INLINE ase_map_copyinline
#define ASE_MAP_KPTR(p) ((p)->kptr)
#define ASE_MAP_KLEN(p) ((p)->klen)
#define ASE_MAP_VPTR(p) ((p)->vptr)
#define ASE_MAP_VLEN(p) ((p)->vlen)
#define ASE_MAP_NEXT(p) ((p)->next)
#ifdef __cplusplus
extern "C" {
#endif
/**
/*
* Creates a hashed map with a dynamic array bucket and a list of values linked
*
* @param owner [in]
* @param capa [in]
* @param factor [in]
* @param freeval [in]
* @param sameval [in]
* @param mmgr [in]
*/
/*
ase_map_t* ase_map_open (
void* owner, ase_size_t capa, unsigned int factor,
void(*freeval)(void*,void*), void(*sameval)(void*,void*),
ase_mmgr_t* mmgr);
*/
ase_map_t* ase_map_open (
ase_mmgr_t* mmgr,
ase_size_t ext,
void (*init) (ase_map_t*)
);
/**
* Destroys a hashed map
*/
/* destroy a map */
void ase_map_close (ase_map_t* map);
/* clear a map */
void ase_map_clear (ase_map_t* map);
/* get the number of key/value pairs in a map
ase_size_t ase_map_getsize (ase_map_t* map);
ase_pair_t* ase_map_get (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen);
ase_map_pair_t* ase_map_get (
ase_map_t* map,
const void* kptr,
ase_size_t klen
);
ase_pair_t* ase_map_put (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void* val);
ase_map_pair_t* ase_map_put (
ase_map_t* map,
const void* kptr,
ase_size_t klen,
void* vptr,
ase_size_t vlen
);
int ase_map_putx (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void* val, ase_pair_t** px);
ase_map_t* map,
void* kptr,
ase_size_t klen,
void* vptr,
ase_size_t vlen,
ase_map_pair_t** px
);
ase_pair_t* ase_map_set (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void* val);
ase_pair_t* ase_map_getpair (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void** val);
ase_pair_t* ase_map_setpair (ase_map_t* map, ase_pair_t* pair, void* val);
ase_map_pair_t* ase_map_set (
ase_map_t* map,
void* kptr,
ase_size_t klen,
void* vptr,
ase_size_t vlen
);
int ase_map_remove (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen);
ase_map_t* map, const void* kptr, ase_size_t klen);
int ase_map_walk (ase_map_t* map, int (*walker)(ase_pair_t*,void*), void* arg);
/* traverse a map */
int ase_map_walk (ase_map_t* map, ase_map_walker_t walker, void* arg);
/**
* Gets the pointer to the first pair in the map.
* @param map [in]
* @param buckno [out]
*/
ase_pair_t* ase_map_getfirstpair (ase_map_t* map, ase_size_t* buckno);
/* get the pointer to the first pair in the map. */
ase_map_pair_t* ase_map_getfirstpair (ase_map_t* map, ase_size_t* buckno);
/**
* Gets the pointer to the next pair in the map.
* @param map [in]
* @param pair [in]
* @param buckno [in out]
*/
ase_pair_t* ase_map_getnextpair (
ase_map_t* map, ase_pair_t* pair, ase_size_t* buckno);
/* get the pointer to the next pair in the map. */
ase_map_pair_t* ase_map_getnextpair (
ase_map_t* map, ase_map_pair_t* pair, ase_size_t* buckno);
void* ase_map_copyinline (ase_map_t* map, void* dptr, ase_size_t dlen);
#ifdef __cplusplus
}

View File

@ -7,12 +7,6 @@
#include <ase/cmn/dll.h>
#include "mem.h"
void* ase_dll_copyinline (ase_dll_t* dll, void* dptr, ase_size_t dlen)
{
/* this is a dummy copier */
return ASE_NULL;
}
ase_dll_t* ase_dll_open (
ase_mmgr_t* mmgr, ase_size_t extension,
void (*initializer) (ase_dll_t*))
@ -43,7 +37,7 @@ ase_dll_t* ase_dll_open (
void ase_dll_close (ase_dll_t* dll)
{
ase_dll_clear (dll);
ASE_FREE (dll->mmgr, dll);
ASE_MMGR_FREE (dll->mmgr, dll);
}
void ase_dll_clear (ase_dll_t* dll)
@ -108,13 +102,13 @@ static ase_dll_node_t* alloc_node (ase_dll_t* dll, void* dptr, ase_size_t dlen)
if (dll->copier == ASE_NULL)
{
n = ASE_MALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t));
n = ASE_MMGR_ALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t));
if (n == ASE_NULL) return ASE_NULL;
n->dptr = dptr;
}
else if (dll->copier == ASE_DLL_COPIER_INLINE)
{
n = ASE_MALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t) + dlen);
n = ASE_MMGR_ALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t) + dlen);
if (n == ASE_NULL) return ASE_NULL;
ASE_MEMCPY (n + 1, dptr, dlen);
@ -122,9 +116,14 @@ static ase_dll_node_t* alloc_node (ase_dll_t* dll, void* dptr, ase_size_t dlen)
}
else
{
n = ASE_MALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t));
n = ASE_MMGR_ALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t));
if (n == ASE_NULL) return ASE_NULL;
n->dptr = dll->copier (dll, dptr, dlen);
if (n->dptr == ASE_NULL)
{
ASE_MMGR_FREE (dll->mmgr, n);
return ASE_NULL;
}
}
n->dlen = dlen;
@ -211,7 +210,7 @@ void ase_dll_delete (ase_dll_t* dll, ase_dll_node_t* pos)
}
/* free the node */
ASE_FREE (dll->mmgr, pos);
ASE_MMGR_FREE (dll->mmgr, pos);
/* decrement the number of elements */
dll->size--;
@ -237,3 +236,10 @@ void ase_dll_walk (ase_dll_t* dll, ase_dll_walker_t walker, void* arg)
n = n->next;
}
}
void* ase_dll_copyinline (ase_dll_t* dll, void* dptr, ase_size_t dlen)
{
/* this is a dummy copier */
return ASE_NULL;
}

View File

@ -1,88 +1,295 @@
/*
* $Id: map.c 332 2008-08-18 11:21:48Z baconevi $
* $Id: map.c 344 2008-08-22 15:23:09Z baconevi $
*
* {License}
*/
#include <ase/cmn/map.h>
#include <ase/cmn/str.h>
#include "mem.h"
static ase_size_t hashkey (const ase_char_t* keyptr, ase_size_t keylen);
static int rehash (ase_map_t* map);
#define map_t ase_map_t
#define pair_t ase_map_pair_t
#define copier_t ase_map_copier_t
#define freeer_t ase_map_freeer_t
#define hasher_t ase_map_hasher_t
#define comper_t ase_map_comper_t
#define walker_t ase_map_walker_t
#define FREE_PAIR(map,pair) \
do { \
if ((map)->freeval != ASE_NULL) \
(map)->freeval ((map)->owner, ASE_PAIR_VAL(pair)); \
ASE_FREE ((map)->mmgr, pair); \
} while (0)
#define KPTR(p) ASE_MAP_KPTR(p)
#define KLEN(p) ASE_MAP_KLEN(p)
#define VPTR(p) ASE_MAP_VPTR(p)
#define VLEN(p) ASE_MAP_VLEN(p)
/*
#define RECYCLE_PAIR(map,pair) \
do { \
if ((map)->freeval != ASE_NULL) \
(map)->freeval ((map)->owner, ASE_PAIR_VAL(pair)); \
(pair)->next = (map)->fp; \
(map)->fp = (pair); \
} while (0)
*/
#define size_t ase_size_t
#define byte_t ase_byte_t
#define mmgr_t ase_mmgr_t
ase_map_t* ase_map_open (
void* owner, ase_size_t capa, unsigned int factor,
void(*freeval)(void*,void*), void(*sameval)(void*,void*),
ase_mmgr_t* mmgr)
static int reorganize (map_t* map);
static size_t hash_key (map_t* map, const void* kptr, size_t klen)
{
ase_map_t* map;
size_t n = 0;
const byte_t* p = (const byte_t*)kptr;
const byte_t* bound = p + klen;
ASE_ASSERTX (capa > 0, "the initial capacity should be greater than 0");
map = (ase_map_t*) ASE_MALLOC (mmgr, ASE_SIZEOF(ase_map_t));
if (map == ASE_NULL) return ASE_NULL;
map->mmgr = mmgr;
map->buck = (ase_pair_t**)
ASE_MALLOC (mmgr, ASE_SIZEOF(ase_pair_t*)*capa);
if (map->buck == ASE_NULL)
while (p < bound)
{
ASE_FREE (mmgr, map);
return ASE_NULL;
n = n * 31 + *p++;
p++;
}
return n;
}
static int comp_key (map_t* map,
const void* kptr1, size_t klen1,
const void* kptr2, size_t klen2)
{
if (klen1 == klen2) return ASE_MEMCMP (kptr1, kptr2, klen1);
/* when the length are different it indicate that they are
* just different */
return 1;
}
static pair_t* alloc_pair (map_t* map,
void* kptr, size_t klen, void* vptr, size_t vlen)
{
pair_t* n;
copier_t kcop = map->copier[ASE_MAP_KEY];
copier_t vcop = map->copier[ASE_MAP_VAL];
size_t as = ASE_SIZEOF(pair_t);
if (kcop == ASE_MAP_COPIER_INLINE) as += klen;
if (vcop == ASE_MAP_COPIER_INLINE) as += vlen;
n = ASE_MMGR_ALLOC (map->mmgr, as);
if (n == ASE_NULL) return ASE_NULL;
ASE_MAP_NEXT(n) = ASE_NULL;
KLEN(n) = klen;
if (kcop == ASE_NULL)
{
KPTR(n) = kptr;
}
else if (kcop == ASE_MAP_COPIER_INLINE)
{
KPTR(n) = n + 1;
ASE_MEMCPY (KPTR(n), kptr, klen);
}
else
{
n->kptr = kcop (map, kptr, klen);
if (n->kptr == ASE_NULL)
{
ASE_MMGR_FREE (map->mmgr, n);
return ASE_NULL;
}
}
map->owner = owner;
map->capa = capa;
VLEN(n) = vlen;
if (vcop == ASE_NULL)
{
VPTR(n) = vptr;
}
else if (vcop == ASE_MAP_COPIER_INLINE)
{
VPTR(n) = n + 1;
ASE_MEMCPY (VPTR(n), vptr, vlen);
}
else
{
n->vptr = vcop (map, vptr, vlen);
if (n->vptr != ASE_NULL)
{
if (map->freeer[ASE_MAP_KEY] != ASE_NULL)
map->freeer[ASE_MAP_KEY] (map, n->kptr, n->klen);
ASE_MMGR_FREE (map->mmgr, n);
return ASE_NULL;
}
}
return n;
}
static void free_pair (map_t* map, pair_t* pair)
{
if (map->freeer[ASE_MAP_KEY] != ASE_NULL)
map->freeer[ASE_MAP_KEY] (map, KPTR(pair), KLEN(pair));
if (map->freeer[ASE_MAP_VAL] != ASE_NULL)
map->freeer[ASE_MAP_VAL] (map, VPTR(pair), VLEN(pair));
ASE_MMGR_FREE (map->mmgr, pair);
}
static pair_t* change_pair_val (
map_t* map, pair_t* pair, void* vptr, size_t vlen)
{
/* use this function with care */
if (VPTR(pair) == vptr)
{
/* if the old value and the new value are the same,
* it just calls the handler for this condition.
* No value replacement occurs. */
if (map->sameval != ASE_NULL)
{
map->sameval (map, vptr, vlen);
}
}
else
{
copier_t vcop = map->copier[ASE_MAP_VAL];
void* ovptr = VPTR(pair);
size_t ovlen = VLEN(pair);
/* place the new value according to the copier */
if (vcop == ASE_NULL)
{
VPTR(pair) = vptr;
VLEN(pair) = vlen;
}
else if (vcop == ASE_MAP_COPIER_INLINE)
{
if (ovlen == vlen)
{
ASE_MEMCPY (VPTR(pair), vptr, vlen);
}
else
{
/* need to reconstruct the pair */
pair_t* p = alloc_pair (map,
KPTR(pair), KLEN(pair),
vptr, vlen);
if (p == ASE_NULL) return ASE_NULL;
free_pair (map, pair);
return p;
}
}
else
{
void* nvptr = vcop (map, vptr, vlen);
if (nvptr == ASE_NULL) return ASE_NULL;
VPTR(pair) = nvptr;
VLEN(pair) = vlen;
}
/* free up the old value */
if (map->freeer[ASE_MAP_VAL] != ASE_NULL)
{
map->freeer[ASE_MAP_VAL] (map, ovptr, ovlen);
}
}
return pair;
}
map_t* ase_map_open (mmgr_t* mmgr, size_t ext, void (*init) (map_t*))
{
map_t* map;
if (mmgr == ASE_NULL)
{
mmgr = ASE_MMGR_GETDFL();
ASE_ASSERTX (mmgr != ASE_NULL,
"Set the memory manager with ASE_MMGR_SETDFL()");
if (mmgr == ASE_NULL) return ASE_NULL;
}
map = ASE_MMGR_ALLOC (mmgr, ASE_SIZEOF(map_t) + ext);
if (map == ASE_NULL) return ASE_NULL;
ASE_MEMSET (map, 0, ASE_SIZEOF(map_t) + ext);
map->mmgr = mmgr;
map->size = 0;
map->freeval = freeval;
map->sameval = sameval;
while (capa > 0) map->buck[--capa] = ASE_NULL;
map->capa = 0;
map->factor = 70;
map->factor = factor;
map->threshold = ((ase_size_t)map->factor) * map->capa / 100;
map->hasher = hash_key;
map->comper = comp_key;
if (init) init (map);
/*map->fp = ASE_NULL;*/
return map;
}
void ase_map_close (ase_map_t* map)
copier_t ase_map_getcopier (map_t* map, int id)
{
ase_map_clear (map);
ASE_FREE (map->mmgr, map->buck);
ASE_FREE (map->mmgr, map);
ASE_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
"The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
return map->copier[id];
}
void ase_map_clear (ase_map_t* map)
void ase_map_setcopier (map_t* map, int id, copier_t copier)
{
ase_size_t i;
ase_pair_t* pair, * next;
ASE_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
"The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
map->copier[id] = copier;
}
/*
while (map->fp != ASE_NULL)
{
next = ASE_PAIR_LNK(map->fp);
ASE_FREE (map->mmgr, map->fp);
map->fp = next;
}
*/
freeer_t ase_map_getfreeer (map_t* map, int id)
{
ASE_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
"The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
return map->freeer[id];
}
void ase_map_setfreeer (map_t* map, int id, freeer_t freeer)
{
ASE_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
"The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
map->freeer[id] = freeer;
}
hasher_t ase_map_gethasher (map_t* map)
{
return map->hasher;
}
void ase_map_sethasher (map_t* map, hasher_t hasher)
{
map->hasher = hasher;
}
comper_t ase_map_getcomper (map_t* map)
{
return map->comper;
}
void ase_map_setcomper (map_t* map, comper_t comper)
{
map->comper = comper;
}
void* ase_map_getextension (map_t* map)
{
return map + 1;
}
mmgr_t* ase_map_getmmgr (map_t* map)
{
return map->mmgr;
}
void ase_map_setmmgr (map_t* map, mmgr_t* mmgr)
{
map->mmgr = mmgr;
}
void ase_map_close (map_t* map)
{
ase_map_clear (map);
ASE_MMGR_FREE (map->mmgr, map->buck);
ASE_MMGR_FREE (map->mmgr, map);
}
void ase_map_clear (map_t* map)
{
size_t i;
pair_t* pair, * next;
for (i = 0; i < map->capa; i++)
{
@ -90,8 +297,8 @@ void ase_map_clear (ase_map_t* map)
while (pair != ASE_NULL)
{
next = ASE_PAIR_LNK(pair);
FREE_PAIR (map, pair);
next = ASE_MAP_NEXT(pair);
free_pair (map, pair);
map->size--;
pair = next;
}
@ -100,112 +307,108 @@ void ase_map_clear (ase_map_t* map)
}
}
ase_size_t ase_map_getsize (ase_map_t* map)
size_t ase_map_getsize (map_t* map)
{
return map->size;
}
ase_pair_t* ase_map_get (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen)
pair_t* ase_map_get (
map_t* map, const void* kptr, size_t klen)
{
ase_pair_t* pair;
ase_size_t hc;
pair_t* pair;
size_t hc;
hc = hashkey(keyptr,keylen) % map->capa;
hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc];
while (pair != ASE_NULL)
{
if (ase_strxncmp (
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair),
keyptr, keylen) == 0) return pair;
if (map->comper (map,
KPTR(pair), KLEN(pair),
kptr, klen) == 0) return pair;
pair = ASE_PAIR_LNK(pair);
pair = ASE_MAP_NEXT(pair);
}
return ASE_NULL;
}
ase_pair_t* ase_map_put (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, void* val)
pair_t* ase_map_put (map_t* map,
void* kptr, size_t klen, void* vptr, size_t vlen)
{
int n;
ase_pair_t* px;
pair_t* px;
n = ase_map_putx (map, keyptr, keylen, val, &px);
n = ase_map_putx (map, kptr, klen, vptr, vlen, &px);
if (n < 0) return ASE_NULL;
return px;
}
int ase_map_putx (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void* val, ase_pair_t** px)
map_t* map, void* kptr, size_t klen,
void* vptr, size_t vlen, pair_t** px)
{
ase_pair_t* pair, * fp, * fp2;
ase_size_t hc;
pair_t* pair, * p, * prev = ASE_NULL, * next;
size_t hc;
hc = hashkey(keyptr,keylen) % map->capa;
hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc];
while (pair != ASE_NULL)
{
if (ase_strxncmp (
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair),
keyptr, keylen) == 0)
{
if (px != ASE_NULL)
*px = ase_map_setpair (map, pair, val);
else
ase_map_setpair (map, pair, val);
next = ASE_MAP_NEXT(pair);
if (map->comper (map,
KPTR(pair), KLEN(pair),
kptr, klen) == 0)
{
p = change_pair_val (map, pair, vptr, vlen);
if (p == ASE_NULL) return -1; /* change error */
if (p != pair)
{
/* the pair has been reallocated. relink it */
if (prev == ASE_NULL) map->buck[hc] = p;
else ASE_MAP_NEXT(prev) = p;
ASE_MAP_NEXT(p) = next;
}
if (px != ASE_NULL) *px = p;
return 0; /* value changed for the existing key */
}
pair = ASE_PAIR_LNK(pair);
prev = pair;
pair = next;
}
if (map->threshold > 0 &&
map->size >= map->threshold)
{
if (rehash(map) == 0) /* ignore the rehash error */
if (reorganize(map) == 0) /* ignore the error */
{
hc = hashkey(keyptr,keylen) % map->capa;
hc = map->hasher(map,kptr,klen) % map->capa;
}
}
ASE_ASSERT (pair == ASE_NULL);
/*
fp = map->fp; fp2 = ASE_NULL;
while (fp != ASE_NULL)
{
if (fp->key.len == keylen)
{
pair = fp;
if (fp2 == ASE_NULL) map->fp = fp->next;
else fp2->next = fp->next;
break;
}
fp2 = fp;
fp = fp->next;
}
if (pair == ASE_NULL)
{
*/
pair = (ase_pair_t*) ASE_MALLOC (map->mmgr,
ASE_SIZEOF(ase_pair_t) + ((keylen+1)*ASE_SIZEOF(*keyptr)));
if (pair == ASE_NULL) return -1; /* error */
/*}*/
#if 0
pair = (pair_t*) ASE_MMGR_ALLOC (map->mmgr,
ASE_SIZEOF(pair_t) + ((klen+1)*ASE_SIZEOF(*kptr)));
if (pair == ASE_NULL) return -1; /* error */
/* duplicate the key if it is new */
ASE_PAIR_KEYPTR(pair) = (ase_char_t*)(pair + 1);
ase_strncpy (ASE_PAIR_KEYPTR(pair), keyptr, keylen);
KPTR(pair) = (void*)(pair + 1);
ase_strncpy (KPTR(pair), kptr, klen);
ASE_PAIR_KEYLEN(pair) = keylen;
ASE_PAIR_VAL(pair) = val;
ASE_PAIR_LNK(pair) = map->buck[hc];
KLEN(pair) = klen;
VPTR(pair) = vptr;
VLEN(pair) = vlen;
#endif
pair = alloc_pair (map, kptr, klen, vptr, vlen);
if (pair == ASE_NULL) return -1; /* error */
ASE_MAP_NEXT(pair) = map->buck[hc];
map->buck[hc] = pair;
map->size++;
@ -213,111 +416,83 @@ int ase_map_putx (
return 1; /* new key added */
}
ase_pair_t* ase_map_set (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void* val)
pair_t* ase_map_set (map_t* map,
void* kptr, size_t klen, void* vptr, size_t vlen)
{
ase_pair_t* pair;
ase_size_t hc;
pair_t* pair;
size_t hc;
hc = hashkey(keyptr,keylen) % map->capa;
hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc];
while (pair != ASE_NULL)
{
if (ase_strxncmp (
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair),
keyptr, keylen) == 0)
if (map->comper (map,
KPTR(pair), KLEN(pair),
kptr, klen) == 0)
{
return ase_map_setpair (map, pair, val);
/*TODO: this is wrong... change code .... same way as putx... */
return change_pair_val (map, pair, vptr, vlen);
}
pair = ASE_PAIR_LNK(pair);
pair = ASE_MAP_NEXT(pair);
}
return ASE_NULL;
}
ase_pair_t* ase_map_getpair (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen,
void** val)
#if 0
pair_t* ase_map_getpair (
map_t* map, const void* kptr, size_t klen,
void** val, size_t* vptr)
{
ase_pair_t* pair;
pair_t* pair;
pair = ase_map_get (map, keyptr, keylen);
pair = ase_map_get (map, kptr, klen);
if (pair == ASE_NULL) return ASE_NULL;
*val = ASE_PAIR_VAL(pair);
return pair;
}
ase_pair_t* ase_map_setpair (ase_map_t* map, ase_pair_t* pair, void* val)
{
/* use this function with care */
if (ASE_PAIR_VAL(pair) == val)
{
/* if the old value and the new value are the same,
* it just calls the handler for this condition.
* No value replacement occurs. */
if (map->sameval != ASE_NULL)
{
map->sameval (map->owner, val);
}
}
else
{
/* frees the old value */
if (map->freeval != ASE_NULL)
{
map->freeval (map->owner, ASE_PAIR_VAL(pair));
}
/* the new value takes the place */
ASE_PAIR_VAL(pair) = val;
}
if (val) *val = VPTR(pair);
if (vptr) *vptr = VLEN(pair);
return pair;
}
#endif
int ase_map_remove (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen)
map_t* map, const void* kptr, size_t klen)
{
ase_pair_t* pair, * prev;
ase_size_t hc;
pair_t* pair, * prev;
size_t hc;
hc = hashkey(keyptr,keylen) % map->capa;
hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc];
prev = ASE_NULL;
while (pair != ASE_NULL)
{
if (ase_strxncmp (
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair),
keyptr, keylen) == 0)
if (map->comper (map,
KPTR(pair), KLEN(pair),
kptr, klen) == 0)
{
if (prev == ASE_NULL)
map->buck[hc] = ASE_PAIR_LNK(pair);
else ASE_PAIR_LNK(prev) = ASE_PAIR_LNK(pair);
/*RECYCLE_PAIR (map, pair);*/
FREE_PAIR (map, pair);
map->buck[hc] = ASE_MAP_NEXT(pair);
else ASE_MAP_NEXT(prev) = ASE_MAP_NEXT(pair);
free_pair (map, pair);
map->size--;
return 0;
}
prev = pair;
pair = ASE_PAIR_LNK(pair);
pair = ASE_MAP_NEXT(pair);
}
return -1;
}
int ase_map_walk (ase_map_t* map, int (*walker) (ase_pair_t*,void*), void* arg)
int ase_map_walk (map_t* map, walker_t walker, void* arg)
{
ase_size_t i;
ase_pair_t* pair, * next;
size_t i;
pair_t* pair, * next;
for (i = 0; i < map->capa; i++)
{
@ -325,8 +500,9 @@ int ase_map_walk (ase_map_t* map, int (*walker) (ase_pair_t*,void*), void* arg)
while (pair != ASE_NULL)
{
next = ASE_PAIR_LNK(pair);
if (walker(pair,arg) == -1) return -1;
next = ASE_MAP_NEXT(pair);
/* TODO: ASE_MAP_WALK_STOP ASE_MAP_WALK_FORWARD */
if (walker(map, pair, arg) == -1) return -1;
pair = next;
}
}
@ -334,10 +510,10 @@ int ase_map_walk (ase_map_t* map, int (*walker) (ase_pair_t*,void*), void* arg)
return 0;
}
ase_pair_t* ase_map_getfirstpair (ase_map_t* map, ase_size_t* buckno)
pair_t* ase_map_getfirstpair (map_t* map, size_t* buckno)
{
ase_size_t i;
ase_pair_t* pair;
size_t i;
pair_t* pair;
for (i = 0; i < map->capa; i++)
{
@ -352,13 +528,13 @@ ase_pair_t* ase_map_getfirstpair (ase_map_t* map, ase_size_t* buckno)
return ASE_NULL;
}
ase_pair_t* ase_map_getnextpair (
ase_map_t* map, ase_pair_t* pair, ase_size_t* buckno)
pair_t* ase_map_getnextpair (
map_t* map, pair_t* pair, size_t* buckno)
{
ase_size_t i;
ase_pair_t* next;
size_t i;
pair_t* next;
next = ASE_PAIR_LNK(pair);
next = ASE_MAP_NEXT(pair);
if (next != ASE_NULL)
{
/* no change in bucket number */
@ -378,34 +554,20 @@ ase_pair_t* ase_map_getnextpair (
return ASE_NULL;
}
static ase_size_t hashkey (const ase_char_t* keyptr, ase_size_t keylen)
static int reorganize (map_t* map)
{
ase_size_t n = 0, i;
const ase_char_t* end = keyptr + keylen;
while (keyptr < end)
{
ase_byte_t* bp = (ase_byte_t*)keyptr;
for (i = 0; i < ASE_SIZEOF(*keyptr); i++) n = n * 31 + *bp++;
keyptr++;
}
return n;
}
static int rehash (ase_map_t* map)
{
ase_size_t i, hc, new_capa;
ase_pair_t** new_buck;
size_t i, hc, new_capa;
pair_t** new_buck;
/* the bucket is doubled until it grows up to 65536 slots.
* once it has reached it, it grows by 65536 slots */
new_capa = (map->capa >= 65536)? (map->capa + 65536): (map->capa << 1);
new_buck = (ase_pair_t**) ASE_MALLOC (
map->mmgr, ASE_SIZEOF(ase_pair_t*) * new_capa);
new_buck = (pair_t**) ASE_MMGR_ALLOC (
map->mmgr, ASE_SIZEOF(pair_t*) * new_capa);
if (new_buck == ASE_NULL)
{
/* once rehash fails, the rehashing is disabled */
/* once reogranization fails, reogranization is disabled */
map->threshold = 0;
return -1;
}
@ -414,27 +576,33 @@ static int rehash (ase_map_t* map)
for (i = 0; i < map->capa; i++)
{
ase_pair_t* pair = map->buck[i];
pair_t* pair = map->buck[i];
while (pair != ASE_NULL)
{
ase_pair_t* next = ASE_PAIR_LNK(pair);
pair_t* next = ASE_MAP_NEXT(pair);
hc = hashkey(
ASE_PAIR_KEYPTR(pair),
ASE_PAIR_KEYLEN(pair)) % new_capa;
hc = map->hasher (map,
KPTR(pair),
KLEN(pair)) % new_capa;
ASE_PAIR_LNK(pair) = new_buck[hc];
ASE_MAP_NEXT(pair) = new_buck[hc];
new_buck[hc] = pair;
pair = next;
}
}
ASE_FREE (map->mmgr, map->buck);
ASE_MMGR_FREE (map->mmgr, map->buck);
map->buck = new_buck;
map->capa = new_capa;
map->threshold = ((ase_size_t)map->factor) * map->capa / 100;
map->threshold = ((size_t)map->factor) * map->capa / 100;
return 0;
}
void* ase_map_copyinline (map_t* map, void* dptr, size_t dlen)
{
/* this is a dummy copier */
return ASE_NULL;
}

View File

@ -7,12 +7,6 @@
#include <ase/cmn/sll.h>
#include "mem.h"
void* ase_sll_copyinline (ase_sll_t* sll, void* dptr, ase_size_t dlen)
{
/* this is a dummy copier */
return ASE_NULL;
}
ase_sll_t* ase_sll_open (
ase_mmgr_t* mmgr, ase_size_t extension,
void (*initializer) (ase_sll_t*))
@ -43,7 +37,7 @@ ase_sll_t* ase_sll_open (
void ase_sll_close (ase_sll_t* sll)
{
ase_sll_clear (sll);
ASE_FREE (sll->mmgr, sll);
ASE_MMGR_FREE (sll->mmgr, sll);
}
void ase_sll_clear (ase_sll_t* sll)
@ -108,13 +102,13 @@ static ase_sll_node_t* alloc_node (ase_sll_t* sll, void* dptr, ase_size_t dlen)
if (sll->copier == ASE_NULL)
{
n = ASE_MALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t));
n = ASE_MMGR_ALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t));
if (n == ASE_NULL) return ASE_NULL;
n->dptr = dptr;
}
else if (sll->copier == ASE_SLL_COPIER_INLINE)
{
n = ASE_MALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t) + dlen);
n = ASE_MMGR_ALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t) + dlen);
if (n == ASE_NULL) return ASE_NULL;
ASE_MEMCPY (n + 1, dptr, dlen);
@ -122,9 +116,14 @@ static ase_sll_node_t* alloc_node (ase_sll_t* sll, void* dptr, ase_size_t dlen)
}
else
{
n = ASE_MALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t));
n = ASE_MMGR_ALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t));
if (n == ASE_NULL) return ASE_NULL;
n->dptr = sll->copier (sll, dptr, dlen);
if (n->dptr == ASE_NULL)
{
ASE_MMGR_FREE (sll->mmgr, n);
return ASE_NULL;
}
}
n->dlen = dlen;
@ -210,7 +209,7 @@ void ase_sll_delete (ase_sll_t* sll, ase_sll_node_t* pos)
}
/* free the node */
ASE_FREE (sll->mmgr, pos);
ASE_MMGR_FREE (sll->mmgr, pos);
/* decrement the number of elements */
sll->size--;
@ -236,3 +235,9 @@ void ase_sll_walk (ase_sll_t* sll, ase_sll_walker_t walker, void* arg)
n = n->next;
}
}
void* ase_sll_copyinline (ase_sll_t* sll, void* dptr, ase_size_t dlen)
{
/* this is a dummy copier */
return ASE_NULL;
}