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} * {License}
*/ */
@ -11,26 +11,71 @@
#include <ase/macros.h> #include <ase/macros.h>
typedef struct ase_map_t ase_map_t; 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 void* kptr;
{ ase_size_t klen;
ase_char_t* ptr;
ase_size_t len;
} key;
void* val; void* vptr;
ase_size_t vlen;
/* used internally */ /* 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 struct ase_map_t
{ {
/* map owner. passed to freeval and sameval as the first argument */ ase_mmgr_t* mmgr;
void* owner;
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 size;
ase_size_t capa; ase_size_t capa;
@ -38,94 +83,95 @@ struct ase_map_t
unsigned int factor; unsigned int factor;
ase_size_t threshold; ase_size_t threshold;
ase_pair_t** buck; ase_map_pair_t** buck;
/*
void (*freeval) (void* owner,void* val); void (*freeval) (void* owner,void* val);
void (*sameval) (void* owner,void* val); */
void (*sameval) (void* owner, void* vptr, ase_size_t vlen);
/* 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;*/
}; };
#define ASE_PAIR_KEYPTR(p) ((p)->key.ptr) #define ASE_MAP_COPIER_INLINE ase_map_copyinline
#define ASE_PAIR_KEYLEN(p) ((p)->key.len)
#define ASE_PAIR_VAL(p) ((p)->val) #define ASE_MAP_KPTR(p) ((p)->kptr)
#define ASE_PAIR_LNK(p) ((p)->next) #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /*
* Creates a hashed map with a dynamic array bucket and a list of values linked * 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 ( ase_map_t* ase_map_open (
void* owner, ase_size_t capa, unsigned int factor, void* owner, ase_size_t capa, unsigned int factor,
void(*freeval)(void*,void*), void(*sameval)(void*,void*), void(*freeval)(void*,void*), void(*sameval)(void*,void*),
ase_mmgr_t* mmgr); ase_mmgr_t* mmgr);
*/
ase_map_t* ase_map_open (
ase_mmgr_t* mmgr,
ase_size_t ext,
void (*init) (ase_map_t*)
);
/** /* destroy a map */
* Destroys a hashed map
*/
void ase_map_close (ase_map_t* map); void ase_map_close (ase_map_t* map);
/* clear a map */
void ase_map_clear (ase_map_t* 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_size_t ase_map_getsize (ase_map_t* map);
ase_pair_t* ase_map_get ( ase_map_pair_t* ase_map_get (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen); ase_map_t* map,
const void* kptr,
ase_size_t klen
);
ase_pair_t* ase_map_put ( ase_map_pair_t* ase_map_put (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, ase_map_t* map,
void* val); const void* kptr,
ase_size_t klen,
void* vptr,
ase_size_t vlen
);
int ase_map_putx ( int ase_map_putx (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, ase_map_t* map,
void* val, ase_pair_t** px); 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_pair_t* ase_map_set (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, ase_map_t* map,
void* val); void* kptr,
ase_size_t klen,
ase_pair_t* ase_map_getpair ( void* vptr,
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, ase_size_t vlen
void** val); );
ase_pair_t* ase_map_setpair (ase_map_t* map, ase_pair_t* pair, void* val);
int ase_map_remove ( 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);
/** /* get the pointer to the first pair in the map. */
* Gets the pointer to the first pair in the map. ase_map_pair_t* ase_map_getfirstpair (ase_map_t* map, ase_size_t* buckno);
* @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 next pair in the map. */
* Gets the pointer to the next pair in the map. ase_map_pair_t* ase_map_getnextpair (
* @param map [in] ase_map_t* map, ase_map_pair_t* pair, ase_size_t* buckno);
* @param pair [in]
* @param buckno [in out] void* ase_map_copyinline (ase_map_t* map, void* dptr, ase_size_t dlen);
*/
ase_pair_t* ase_map_getnextpair (
ase_map_t* map, ase_pair_t* pair, ase_size_t* buckno);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -7,12 +7,6 @@
#include <ase/cmn/dll.h> #include <ase/cmn/dll.h>
#include "mem.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_dll_t* ase_dll_open (
ase_mmgr_t* mmgr, ase_size_t extension, ase_mmgr_t* mmgr, ase_size_t extension,
void (*initializer) (ase_dll_t*)) void (*initializer) (ase_dll_t*))
@ -43,7 +37,7 @@ ase_dll_t* ase_dll_open (
void ase_dll_close (ase_dll_t* dll) void ase_dll_close (ase_dll_t* dll)
{ {
ase_dll_clear (dll); ase_dll_clear (dll);
ASE_FREE (dll->mmgr, dll); ASE_MMGR_FREE (dll->mmgr, dll);
} }
void ase_dll_clear (ase_dll_t* 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) 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; if (n == ASE_NULL) return ASE_NULL;
n->dptr = dptr; n->dptr = dptr;
} }
else if (dll->copier == ASE_DLL_COPIER_INLINE) 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; if (n == ASE_NULL) return ASE_NULL;
ASE_MEMCPY (n + 1, dptr, dlen); 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 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; if (n == ASE_NULL) return ASE_NULL;
n->dptr = dll->copier (dll, dptr, dlen); n->dptr = dll->copier (dll, dptr, dlen);
if (n->dptr == ASE_NULL)
{
ASE_MMGR_FREE (dll->mmgr, n);
return ASE_NULL;
}
} }
n->dlen = dlen; n->dlen = dlen;
@ -211,7 +210,7 @@ void ase_dll_delete (ase_dll_t* dll, ase_dll_node_t* pos)
} }
/* free the node */ /* free the node */
ASE_FREE (dll->mmgr, pos); ASE_MMGR_FREE (dll->mmgr, pos);
/* decrement the number of elements */ /* decrement the number of elements */
dll->size--; dll->size--;
@ -237,3 +236,10 @@ void ase_dll_walk (ase_dll_t* dll, ase_dll_walker_t walker, void* arg)
n = n->next; 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} * {License}
*/ */
#include <ase/cmn/map.h> #include <ase/cmn/map.h>
#include <ase/cmn/str.h>
#include "mem.h" #include "mem.h"
static ase_size_t hashkey (const ase_char_t* keyptr, ase_size_t keylen); #define map_t ase_map_t
static int rehash (ase_map_t* map); #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) \ #define KPTR(p) ASE_MAP_KPTR(p)
do { \ #define KLEN(p) ASE_MAP_KLEN(p)
if ((map)->freeval != ASE_NULL) \ #define VPTR(p) ASE_MAP_VPTR(p)
(map)->freeval ((map)->owner, ASE_PAIR_VAL(pair)); \ #define VLEN(p) ASE_MAP_VLEN(p)
ASE_FREE ((map)->mmgr, pair); \
} while (0)
/* #define size_t ase_size_t
#define RECYCLE_PAIR(map,pair) \ #define byte_t ase_byte_t
do { \ #define mmgr_t ase_mmgr_t
if ((map)->freeval != ASE_NULL) \
(map)->freeval ((map)->owner, ASE_PAIR_VAL(pair)); \
(pair)->next = (map)->fp; \
(map)->fp = (pair); \
} while (0)
*/
ase_map_t* ase_map_open ( static int reorganize (map_t* map);
void* owner, ase_size_t capa, unsigned int factor,
void(*freeval)(void*,void*), void(*sameval)(void*,void*), static size_t hash_key (map_t* map, const void* kptr, size_t klen)
ase_mmgr_t* mmgr)
{ {
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"); while (p < bound)
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)
{ {
ASE_FREE (mmgr, map); n = n * 31 + *p++;
return ASE_NULL; p++;
} }
map->owner = owner; return n;
map->capa = capa; }
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;
}
}
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->size = 0;
map->freeval = freeval; map->capa = 0;
map->sameval = sameval; map->factor = 70;
while (capa > 0) map->buck[--capa] = ASE_NULL;
map->factor = factor; map->hasher = hash_key;
map->threshold = ((ase_size_t)map->factor) * map->capa / 100; map->comper = comp_key;
if (init) init (map);
/*map->fp = ASE_NULL;*/
return map; 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_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
ASE_FREE (map->mmgr, map->buck); "The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
ASE_FREE (map->mmgr, map); 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_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
ase_pair_t* pair, * next; "The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
map->copier[id] = copier;
}
/* freeer_t ase_map_getfreeer (map_t* map, int id)
while (map->fp != ASE_NULL) {
{ ASE_ASSERTX (id == ASE_MAP_KEY || id == ASE_MAP_VAL,
next = ASE_PAIR_LNK(map->fp); "The ID should be either ASE_MAP_KEY or ASE_MAP_VAL");
ASE_FREE (map->mmgr, map->fp); return map->freeer[id];
map->fp = next; }
}
*/ 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++) for (i = 0; i < map->capa; i++)
{ {
@ -90,8 +297,8 @@ void ase_map_clear (ase_map_t* map)
while (pair != ASE_NULL) while (pair != ASE_NULL)
{ {
next = ASE_PAIR_LNK(pair); next = ASE_MAP_NEXT(pair);
FREE_PAIR (map, pair); free_pair (map, pair);
map->size--; map->size--;
pair = next; 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; return map->size;
} }
ase_pair_t* ase_map_get ( pair_t* ase_map_get (
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; pair_t* pair;
ase_size_t hc; size_t hc;
hc = hashkey(keyptr,keylen) % map->capa; hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc]; pair = map->buck[hc];
while (pair != ASE_NULL) while (pair != ASE_NULL)
{ {
if (ase_strxncmp ( if (map->comper (map,
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair), KPTR(pair), KLEN(pair),
keyptr, keylen) == 0) return pair; kptr, klen) == 0) return pair;
pair = ASE_PAIR_LNK(pair); pair = ASE_MAP_NEXT(pair);
} }
return ASE_NULL; return ASE_NULL;
} }
ase_pair_t* ase_map_put ( pair_t* ase_map_put (map_t* map,
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, void* val) void* kptr, size_t klen, void* vptr, size_t vlen)
{ {
int n; 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; if (n < 0) return ASE_NULL;
return px; return px;
} }
int ase_map_putx ( int ase_map_putx (
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, map_t* map, void* kptr, size_t klen,
void* val, ase_pair_t** px) void* vptr, size_t vlen, pair_t** px)
{ {
ase_pair_t* pair, * fp, * fp2; pair_t* pair, * p, * prev = ASE_NULL, * next;
ase_size_t hc; size_t hc;
hc = hashkey(keyptr,keylen) % map->capa; hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc]; pair = map->buck[hc];
while (pair != ASE_NULL) while (pair != ASE_NULL)
{ {
if (ase_strxncmp ( next = ASE_MAP_NEXT(pair);
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);
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 */ return 0; /* value changed for the existing key */
} }
pair = ASE_PAIR_LNK(pair);
prev = pair;
pair = next;
} }
if (map->threshold > 0 && if (map->threshold > 0 &&
map->size >= map->threshold) 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); ASE_ASSERT (pair == ASE_NULL);
/* #if 0
fp = map->fp; fp2 = ASE_NULL; pair = (pair_t*) ASE_MMGR_ALLOC (map->mmgr,
while (fp != ASE_NULL) ASE_SIZEOF(pair_t) + ((klen+1)*ASE_SIZEOF(*kptr)));
{
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 (pair == ASE_NULL) return -1; /* error */
/*}*/
/* duplicate the key if it is new */ /* duplicate the key if it is new */
ASE_PAIR_KEYPTR(pair) = (ase_char_t*)(pair + 1); KPTR(pair) = (void*)(pair + 1);
ase_strncpy (ASE_PAIR_KEYPTR(pair), keyptr, keylen); ase_strncpy (KPTR(pair), kptr, klen);
ASE_PAIR_KEYLEN(pair) = keylen; KLEN(pair) = klen;
ASE_PAIR_VAL(pair) = val; VPTR(pair) = vptr;
ASE_PAIR_LNK(pair) = map->buck[hc]; 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->buck[hc] = pair;
map->size++; map->size++;
@ -213,111 +416,83 @@ int ase_map_putx (
return 1; /* new key added */ return 1; /* new key added */
} }
ase_pair_t* ase_map_set ( pair_t* ase_map_set (map_t* map,
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, void* kptr, size_t klen, void* vptr, size_t vlen)
void* val)
{ {
ase_pair_t* pair; pair_t* pair;
ase_size_t hc; size_t hc;
hc = hashkey(keyptr,keylen) % map->capa; hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc]; pair = map->buck[hc];
while (pair != ASE_NULL) while (pair != ASE_NULL)
{ {
if (ase_strxncmp ( if (map->comper (map,
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair), KPTR(pair), KLEN(pair),
keyptr, keylen) == 0) 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; return ASE_NULL;
} }
ase_pair_t* ase_map_getpair ( #if 0
ase_map_t* map, const ase_char_t* keyptr, ase_size_t keylen, pair_t* ase_map_getpair (
void** val) 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; if (pair == ASE_NULL) return ASE_NULL;
*val = ASE_PAIR_VAL(pair); if (val) *val = VPTR(pair);
if (vptr) *vptr = VLEN(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;
}
return pair; return pair;
} }
#endif
int ase_map_remove ( 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; pair_t* pair, * prev;
ase_size_t hc; size_t hc;
hc = hashkey(keyptr,keylen) % map->capa; hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->buck[hc]; pair = map->buck[hc];
prev = ASE_NULL; prev = ASE_NULL;
while (pair != ASE_NULL) while (pair != ASE_NULL)
{ {
if (ase_strxncmp ( if (map->comper (map,
ASE_PAIR_KEYPTR(pair), ASE_PAIR_KEYLEN(pair), KPTR(pair), KLEN(pair),
keyptr, keylen) == 0) kptr, klen) == 0)
{ {
if (prev == ASE_NULL) if (prev == ASE_NULL)
map->buck[hc] = ASE_PAIR_LNK(pair); map->buck[hc] = ASE_MAP_NEXT(pair);
else ASE_PAIR_LNK(prev) = ASE_PAIR_LNK(pair); else ASE_MAP_NEXT(prev) = ASE_MAP_NEXT(pair);
/*RECYCLE_PAIR (map, pair);*/
FREE_PAIR (map, pair);
free_pair (map, pair);
map->size--; map->size--;
return 0; return 0;
} }
prev = pair; prev = pair;
pair = ASE_PAIR_LNK(pair); pair = ASE_MAP_NEXT(pair);
} }
return -1; 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; size_t i;
ase_pair_t* pair, * next; pair_t* pair, * next;
for (i = 0; i < map->capa; i++) 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) while (pair != ASE_NULL)
{ {
next = ASE_PAIR_LNK(pair); next = ASE_MAP_NEXT(pair);
if (walker(pair,arg) == -1) return -1; /* TODO: ASE_MAP_WALK_STOP ASE_MAP_WALK_FORWARD */
if (walker(map, pair, arg) == -1) return -1;
pair = next; pair = next;
} }
} }
@ -334,10 +510,10 @@ int ase_map_walk (ase_map_t* map, int (*walker) (ase_pair_t*,void*), void* arg)
return 0; 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; size_t i;
ase_pair_t* pair; pair_t* pair;
for (i = 0; i < map->capa; i++) 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; return ASE_NULL;
} }
ase_pair_t* ase_map_getnextpair ( pair_t* ase_map_getnextpair (
ase_map_t* map, ase_pair_t* pair, ase_size_t* buckno) map_t* map, pair_t* pair, size_t* buckno)
{ {
ase_size_t i; size_t i;
ase_pair_t* next; pair_t* next;
next = ASE_PAIR_LNK(pair); next = ASE_MAP_NEXT(pair);
if (next != ASE_NULL) if (next != ASE_NULL)
{ {
/* no change in bucket number */ /* no change in bucket number */
@ -378,34 +554,20 @@ ase_pair_t* ase_map_getnextpair (
return ASE_NULL; return ASE_NULL;
} }
static int reorganize (map_t* map)
static ase_size_t hashkey (const ase_char_t* keyptr, ase_size_t keylen)
{ {
ase_size_t n = 0, i; size_t i, hc, new_capa;
const ase_char_t* end = keyptr + keylen; pair_t** new_buck;
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;
/* 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_capa = (map->capa >= 65536)? (map->capa + 65536): (map->capa << 1);
new_buck = (ase_pair_t**) ASE_MALLOC ( new_buck = (pair_t**) ASE_MMGR_ALLOC (
map->mmgr, ASE_SIZEOF(ase_pair_t*) * new_capa); map->mmgr, ASE_SIZEOF(pair_t*) * new_capa);
if (new_buck == ASE_NULL) if (new_buck == ASE_NULL)
{ {
/* once rehash fails, the rehashing is disabled */ /* once reogranization fails, reogranization is disabled */
map->threshold = 0; map->threshold = 0;
return -1; return -1;
} }
@ -414,27 +576,33 @@ static int rehash (ase_map_t* map)
for (i = 0; i < map->capa; i++) for (i = 0; i < map->capa; i++)
{ {
ase_pair_t* pair = map->buck[i]; pair_t* pair = map->buck[i];
while (pair != ASE_NULL) while (pair != ASE_NULL)
{ {
ase_pair_t* next = ASE_PAIR_LNK(pair); pair_t* next = ASE_MAP_NEXT(pair);
hc = hashkey( hc = map->hasher (map,
ASE_PAIR_KEYPTR(pair), KPTR(pair),
ASE_PAIR_KEYLEN(pair)) % new_capa; KLEN(pair)) % new_capa;
ASE_PAIR_LNK(pair) = new_buck[hc]; ASE_MAP_NEXT(pair) = new_buck[hc];
new_buck[hc] = pair; new_buck[hc] = pair;
pair = next; pair = next;
} }
} }
ASE_FREE (map->mmgr, map->buck); ASE_MMGR_FREE (map->mmgr, map->buck);
map->buck = new_buck; map->buck = new_buck;
map->capa = new_capa; 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; 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 <ase/cmn/sll.h>
#include "mem.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_sll_t* ase_sll_open (
ase_mmgr_t* mmgr, ase_size_t extension, ase_mmgr_t* mmgr, ase_size_t extension,
void (*initializer) (ase_sll_t*)) void (*initializer) (ase_sll_t*))
@ -43,7 +37,7 @@ ase_sll_t* ase_sll_open (
void ase_sll_close (ase_sll_t* sll) void ase_sll_close (ase_sll_t* sll)
{ {
ase_sll_clear (sll); ase_sll_clear (sll);
ASE_FREE (sll->mmgr, sll); ASE_MMGR_FREE (sll->mmgr, sll);
} }
void ase_sll_clear (ase_sll_t* 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) 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; if (n == ASE_NULL) return ASE_NULL;
n->dptr = dptr; n->dptr = dptr;
} }
else if (sll->copier == ASE_SLL_COPIER_INLINE) 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; if (n == ASE_NULL) return ASE_NULL;
ASE_MEMCPY (n + 1, dptr, dlen); 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 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; if (n == ASE_NULL) return ASE_NULL;
n->dptr = sll->copier (sll, dptr, dlen); n->dptr = sll->copier (sll, dptr, dlen);
if (n->dptr == ASE_NULL)
{
ASE_MMGR_FREE (sll->mmgr, n);
return ASE_NULL;
}
} }
n->dlen = dlen; n->dlen = dlen;
@ -210,7 +209,7 @@ void ase_sll_delete (ase_sll_t* sll, ase_sll_node_t* pos)
} }
/* free the node */ /* free the node */
ASE_FREE (sll->mmgr, pos); ASE_MMGR_FREE (sll->mmgr, pos);
/* decrement the number of elements */ /* decrement the number of elements */
sll->size--; sll->size--;
@ -236,3 +235,9 @@ void ase_sll_walk (ase_sll_t* sll, ase_sll_walker_t walker, void* arg)
n = n->next; 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;
}