This commit is contained in:
parent
7fb73210b8
commit
b6d38c892a
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
VLEN(n) = vlen;
|
||||||
map->capa = capa;
|
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 (pair == ASE_NULL) return -1; /* error */
|
||||||
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 */
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/* 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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user