added qse_htb_cbsert().
exported qse_htb_allocpair() and qse_htb_freepair()
This commit is contained in:
parent
81f314d676
commit
2265531c97
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: htb.h 363 2010-10-27 12:54:37Z hyunghwan.chung $
|
* $Id: htb.h 364 2010-10-28 13:09:53Z hyunghwan.chung $
|
||||||
*
|
*
|
||||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
This file is part of QSE.
|
This file is part of QSE.
|
||||||
@ -56,6 +56,9 @@ typedef enum qse_htb_id_t qse_htb_id_t;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_htb_copier_t type defines a pair contruction callback.
|
* The qse_htb_copier_t type defines a pair contruction callback.
|
||||||
|
* A special copier #QSE_HTB_COPIER_INLINE is provided. This copier enables
|
||||||
|
* you to copy the data inline to the internal node. No freeer is invoked
|
||||||
|
* when the node is freeed.
|
||||||
*/
|
*/
|
||||||
typedef void* (*qse_htb_copier_t) (
|
typedef void* (*qse_htb_copier_t) (
|
||||||
qse_htb_t* htb /* hash table */,
|
qse_htb_t* htb /* hash table */,
|
||||||
@ -65,6 +68,7 @@ typedef void* (*qse_htb_copier_t) (
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_htb_freeer_t defines a key/value destruction callback
|
* The qse_htb_freeer_t defines a key/value destruction callback
|
||||||
|
* The freeer is called when a node containing the element is destroyed.
|
||||||
*/
|
*/
|
||||||
typedef void (*qse_htb_freeer_t) (
|
typedef void (*qse_htb_freeer_t) (
|
||||||
qse_htb_t* htb, /**< hash table */
|
qse_htb_t* htb, /**< hash table */
|
||||||
@ -108,8 +112,8 @@ typedef void (*qse_htb_keeper_t) (
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_htb_sizer_t type defines a bucket size claculator that is called
|
* The qse_htb_sizer_t type defines a bucket size claculator that is called
|
||||||
* when hash table should resize the bucket. The current bucket size +1 is passed
|
* when hash table should resize the bucket. The current bucket size + 1 is
|
||||||
* as the hint.
|
* passed as the hint.
|
||||||
*/
|
*/
|
||||||
typedef qse_size_t (*qse_htb_sizer_t) (
|
typedef qse_size_t (*qse_htb_sizer_t) (
|
||||||
qse_htb_t* htb, /**< htb */
|
qse_htb_t* htb, /**< htb */
|
||||||
@ -163,15 +167,6 @@ struct qse_htb_t
|
|||||||
|
|
||||||
const qse_htb_mancbs_t* mancbs;
|
const qse_htb_mancbs_t* mancbs;
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_htb_copier_t copier[2];
|
|
||||||
qse_htb_freeer_t freeer[2];
|
|
||||||
qse_htb_hasher_t hasher; /**< key hasher */
|
|
||||||
qse_htb_comper_t comper; /**< key comparator */
|
|
||||||
qse_htb_keeper_t keeper; /**< value keeper */
|
|
||||||
qse_htb_sizer_t sizer; /**< bucket capacity recalculator */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
qse_byte_t scale[2]; /**< length scale */
|
qse_byte_t scale[2]; /**< length scale */
|
||||||
qse_byte_t factor; /**< load factor in percentage */
|
qse_byte_t factor; /**< load factor in percentage */
|
||||||
|
|
||||||
@ -313,87 +308,6 @@ void qse_htb_setmancbs (
|
|||||||
const qse_htb_mancbs_t* mancbs
|
const qse_htb_mancbs_t* mancbs
|
||||||
);
|
);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/**
|
|
||||||
* The qse_htb_getcopier() function gets a data copier.
|
|
||||||
*/
|
|
||||||
qse_htb_copier_t qse_htb_getcopier (
|
|
||||||
qse_htb_t* htb, /**< hash table */
|
|
||||||
qse_htb_id_t id /**< QSE_HTB_KEY or QSE_HTB_VAL */
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The qse_htb_setcopier() function specifies how to clone an element.
|
|
||||||
* A special copier QSE_HTB_COPIER_INLINE is provided. This copier enables
|
|
||||||
* you to copy the data inline to the internal node. No freeer is invoked
|
|
||||||
* when the node is freeed.
|
|
||||||
*
|
|
||||||
* You may set the copier to QSE_NULL to perform no special operation
|
|
||||||
* when the data pointer is rememebered.
|
|
||||||
*/
|
|
||||||
void qse_htb_setcopier (
|
|
||||||
qse_htb_t* htb, /**< hash table */
|
|
||||||
qse_htb_id_t id, /**< QSE_HTB_KEY or QSE_HTB_VAL */
|
|
||||||
qse_htb_copier_t copier /**< element copier */
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The qse_htb_getfreeer() function returns a custom element destroyer.
|
|
||||||
*/
|
|
||||||
qse_htb_freeer_t qse_htb_getfreeer (
|
|
||||||
qse_htb_t* htb, /**< hash table */
|
|
||||||
qse_htb_id_t id /**< QSE_HTB_KEY or QSE_HTB_VAL */
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The qse_htb_setfreeer() function specifies how to destroy an element.
|
|
||||||
* The @a freeer is called when a node containing the element is destroyed.
|
|
||||||
*/
|
|
||||||
void qse_htb_setfreeer (
|
|
||||||
qse_htb_t* htb, /**< hash table */
|
|
||||||
qse_htb_id_t id, /**< QSE_HTB_KEY or QSE_HTB_VAL */
|
|
||||||
qse_htb_freeer_t freeer /**< an element freeer */
|
|
||||||
);
|
|
||||||
|
|
||||||
qse_htb_hasher_t qse_htb_gethasher (
|
|
||||||
qse_htb_t* htb
|
|
||||||
);
|
|
||||||
|
|
||||||
void qse_htb_sethasher (
|
|
||||||
qse_htb_t* htb,
|
|
||||||
qse_htb_hasher_t hasher
|
|
||||||
);
|
|
||||||
|
|
||||||
qse_htb_comper_t qse_htb_getcomper (
|
|
||||||
qse_htb_t* htb
|
|
||||||
);
|
|
||||||
|
|
||||||
void qse_htb_setcomper (
|
|
||||||
qse_htb_t* htb,
|
|
||||||
qse_htb_comper_t comper
|
|
||||||
);
|
|
||||||
|
|
||||||
qse_htb_keeper_t qse_htb_getkeeper (
|
|
||||||
qse_htb_t* htb
|
|
||||||
);
|
|
||||||
|
|
||||||
void qse_htb_setkeeper (
|
|
||||||
qse_htb_t* htb,
|
|
||||||
qse_htb_keeper_t keeper
|
|
||||||
);
|
|
||||||
|
|
||||||
qse_htb_sizer_t qse_htb_getsizer (
|
|
||||||
qse_htb_t* htb
|
|
||||||
);
|
|
||||||
|
|
||||||
/* the sizer function is passed hash table object and htb->capa + 1 */
|
|
||||||
void qse_htb_setsizer (
|
|
||||||
qse_htb_t* htb,
|
|
||||||
qse_htb_sizer_t sizer
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_htb_search() function searches a hash table to find a pair with a
|
* The qse_htb_search() function searches a hash table to find a pair with a
|
||||||
* matching key. It returns the pointer to the pair found. If it fails
|
* matching key. It returns the pointer to the pair found. If it fails
|
||||||
@ -464,6 +378,22 @@ qse_htb_pair_t* qse_htb_update (
|
|||||||
qse_size_t vlen /**< the length of the value */
|
qse_size_t vlen /**< the length of the value */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
typedef qse_htb_pair_t* (*qse_htb_cbserter_t) (
|
||||||
|
qse_htb_t* htb,
|
||||||
|
qse_htb_pair_t* pair,
|
||||||
|
void* kptr,
|
||||||
|
qse_size_t klen,
|
||||||
|
void* ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_htb_pair_t* qse_htb_cbsert (
|
||||||
|
qse_htb_t* htb,
|
||||||
|
void* kptr,
|
||||||
|
qse_size_t klen,
|
||||||
|
qse_htb_cbserter_t cbserter,
|
||||||
|
void* ctx
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_htb_delete() function deletes a pair with a matching key
|
* The qse_htb_delete() function deletes a pair with a matching key
|
||||||
* @return 0 on success, -1 on failure
|
* @return 0 on success, -1 on failure
|
||||||
@ -509,6 +439,28 @@ qse_htb_pair_t* qse_htb_getnextpair (
|
|||||||
qse_size_t* buckno /**< bucket number */
|
qse_size_t* buckno /**< bucket number */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htb_allocpair() function allocates a pair for a key and a value
|
||||||
|
* given. But it does not chain the pair allocated into the hash table @a htb.
|
||||||
|
* Use this function at your own risk.
|
||||||
|
*/
|
||||||
|
qse_htb_pair_t* qse_htb_allocpair (
|
||||||
|
qse_htb_t* htb,
|
||||||
|
void* kptr,
|
||||||
|
qse_size_t klen,
|
||||||
|
void* vptr,
|
||||||
|
qse_size_t vlen
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htb_freepair() function destroys a pair. But it does not detach
|
||||||
|
* the pair destroyed from the hash table @a htb. Use this function at your
|
||||||
|
* own risk.
|
||||||
|
*/
|
||||||
|
void qse_htb_freepair (
|
||||||
|
qse_htb_t* htb,
|
||||||
|
qse_htb_pair_t* pair
|
||||||
|
);
|
||||||
|
|
||||||
qse_size_t qse_htb_dflhash (
|
qse_size_t qse_htb_dflhash (
|
||||||
qse_htb_t* htb,
|
qse_htb_t* htb,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: htb.c 363 2010-10-27 12:54:37Z hyunghwan.chung $
|
* $Id: htb.c 364 2010-10-28 13:09:53Z hyunghwan.chung $
|
||||||
*
|
*
|
||||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||||
This file is part of QSE.
|
This file is part of QSE.
|
||||||
@ -23,15 +23,16 @@
|
|||||||
|
|
||||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (htb)
|
QSE_IMPLEMENT_COMMON_FUNCTIONS (htb)
|
||||||
|
|
||||||
#define htb_t qse_htb_t
|
#define htb_t qse_htb_t
|
||||||
#define pair_t qse_htb_pair_t
|
#define pair_t qse_htb_pair_t
|
||||||
#define copier_t qse_htb_copier_t
|
#define copier_t qse_htb_copier_t
|
||||||
#define freeer_t qse_htb_freeer_t
|
#define freeer_t qse_htb_freeer_t
|
||||||
#define hasher_t qse_htb_hasher_t
|
#define hasher_t qse_htb_hasher_t
|
||||||
#define comper_t qse_htb_comper_t
|
#define comper_t qse_htb_comper_t
|
||||||
#define keeper_t qse_htb_keeper_t
|
#define keeper_t qse_htb_keeper_t
|
||||||
#define sizer_t qse_htb_sizer_t
|
#define sizer_t qse_htb_sizer_t
|
||||||
#define walker_t qse_htb_walker_t
|
#define walker_t qse_htb_walker_t
|
||||||
|
#define cbserter_t qse_htb_cbserter_t
|
||||||
|
|
||||||
#define KPTR(p) QSE_HTB_KPTR(p)
|
#define KPTR(p) QSE_HTB_KPTR(p)
|
||||||
#define KLEN(p) QSE_HTB_KLEN(p)
|
#define KLEN(p) QSE_HTB_KLEN(p)
|
||||||
@ -47,14 +48,8 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (htb)
|
|||||||
#define KTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_KEY])
|
#define KTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_KEY])
|
||||||
#define VTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_VAL])
|
#define VTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_VAL])
|
||||||
|
|
||||||
#define UPSERT 1
|
QSE_INLINE pair_t* qse_htb_allocpair (
|
||||||
#define UPDATE 2
|
htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen)
|
||||||
#define ENSERT 3
|
|
||||||
#define INSERT 4
|
|
||||||
|
|
||||||
|
|
||||||
static pair_t* alloc_pair (htb_t* htb,
|
|
||||||
void* kptr, size_t klen, void* vptr, size_t vlen)
|
|
||||||
{
|
{
|
||||||
pair_t* n;
|
pair_t* n;
|
||||||
copier_t kcop = htb->mancbs->copier[QSE_HTB_KEY];
|
copier_t kcop = htb->mancbs->copier[QSE_HTB_KEY];
|
||||||
@ -116,7 +111,7 @@ static pair_t* alloc_pair (htb_t* htb,
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_pair (htb_t* htb, pair_t* pair)
|
QSE_INLINE void qse_htb_freepair (htb_t* htb, pair_t* pair)
|
||||||
{
|
{
|
||||||
if (htb->mancbs->freeer[QSE_HTB_KEY] != QSE_NULL)
|
if (htb->mancbs->freeer[QSE_HTB_KEY] != QSE_NULL)
|
||||||
htb->mancbs->freeer[QSE_HTB_KEY] (htb, KPTR(pair), KLEN(pair));
|
htb->mancbs->freeer[QSE_HTB_KEY] (htb, KPTR(pair), KLEN(pair));
|
||||||
@ -125,7 +120,7 @@ static void free_pair (htb_t* htb, pair_t* pair)
|
|||||||
QSE_MMGR_FREE (htb->mmgr, pair);
|
QSE_MMGR_FREE (htb->mmgr, pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pair_t* change_pair_val (
|
static QSE_INLINE pair_t* change_pair_val (
|
||||||
htb_t* htb, pair_t* pair, void* vptr, size_t vlen)
|
htb_t* htb, pair_t* pair, void* vptr, size_t vlen)
|
||||||
{
|
{
|
||||||
if (VPTR(pair) == vptr && VLEN(pair) == vlen)
|
if (VPTR(pair) == vptr && VLEN(pair) == vlen)
|
||||||
@ -159,11 +154,11 @@ static pair_t* change_pair_val (
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* need to reconstruct the pair */
|
/* need to reconstruct the pair */
|
||||||
pair_t* p = alloc_pair (htb,
|
pair_t* p = qse_htb_allocpair (htb,
|
||||||
KPTR(pair), KLEN(pair),
|
KPTR(pair), KLEN(pair),
|
||||||
vptr, vlen);
|
vptr, vlen);
|
||||||
if (p == QSE_NULL) return QSE_NULL;
|
if (p == QSE_NULL) return QSE_NULL;
|
||||||
free_pair (htb, pair);
|
qse_htb_freepair (htb, pair);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,79 +327,6 @@ void qse_htb_setmancbs (htb_t* htb, const qse_htb_mancbs_t* mancbs)
|
|||||||
htb->mancbs = mancbs;
|
htb->mancbs = mancbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
copier_t qse_htb_getcopier (htb_t* htb, qse_htb_id_t id)
|
|
||||||
{
|
|
||||||
QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL,
|
|
||||||
"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL");
|
|
||||||
return htb->copier[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_htb_setcopier (htb_t* htb, qse_htb_id_t id, copier_t copier)
|
|
||||||
{
|
|
||||||
QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL,
|
|
||||||
"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL");
|
|
||||||
if (copier == QSE_NULL) copier = QSE_HTB_COPIER_SIMPLE;
|
|
||||||
htb->copier[id] = copier;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeer_t qse_htb_getfreeer (htb_t* htb, qse_htb_id_t id)
|
|
||||||
{
|
|
||||||
QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL,
|
|
||||||
"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL");
|
|
||||||
return htb->freeer[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_htb_setfreeer (htb_t* htb, qse_htb_id_t id, freeer_t freeer)
|
|
||||||
{
|
|
||||||
QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL,
|
|
||||||
"The ID should be either QSE_HTB_KEY or QSE_HTB_VAL");
|
|
||||||
htb->freeer[id] = freeer;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasher_t qse_htb_gethasher (htb_t* htb)
|
|
||||||
{
|
|
||||||
return htb->hasher;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_htb_sethasher (htb_t* htb, hasher_t hasher)
|
|
||||||
{
|
|
||||||
if (hasher == QSE_NULL) hasher = hash_key;
|
|
||||||
htb->hasher = hasher;
|
|
||||||
}
|
|
||||||
|
|
||||||
comper_t qse_htb_getcomper (htb_t* htb)
|
|
||||||
{
|
|
||||||
return htb->comper;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_htb_setcomper (htb_t* htb, comper_t comper)
|
|
||||||
{
|
|
||||||
if (comper == QSE_NULL) comper = comp_key;
|
|
||||||
htb->comper = comper;
|
|
||||||
}
|
|
||||||
|
|
||||||
keeper_t qse_htb_getkeeper (htb_t* htb)
|
|
||||||
{
|
|
||||||
return htb->keeper;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_htb_setkeeper (htb_t* htb, keeper_t keeper)
|
|
||||||
{
|
|
||||||
htb->keeper = keeper;
|
|
||||||
}
|
|
||||||
|
|
||||||
sizer_t qse_htb_getsizer (htb_t* htb)
|
|
||||||
{
|
|
||||||
return htb->sizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qse_htb_setsizer (htb_t* htb, sizer_t sizer)
|
|
||||||
{
|
|
||||||
htb->sizer = sizer;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t qse_htb_getsize (htb_t* htb)
|
size_t qse_htb_getsize (htb_t* htb)
|
||||||
{
|
{
|
||||||
return htb->size;
|
return htb->size;
|
||||||
@ -498,6 +420,12 @@ static QSE_INLINE_ALWAYS int reorganize (htb_t* htb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* insert options */
|
||||||
|
#define UPSERT 1
|
||||||
|
#define UPDATE 2
|
||||||
|
#define ENSERT 3
|
||||||
|
#define INSERT 4
|
||||||
|
|
||||||
static pair_t* insert (
|
static pair_t* insert (
|
||||||
htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen, int opt)
|
htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen, int opt)
|
||||||
{
|
{
|
||||||
@ -522,17 +450,18 @@ static pair_t* insert (
|
|||||||
p = change_pair_val (htb, pair, vptr, vlen);
|
p = change_pair_val (htb, pair, vptr, vlen);
|
||||||
if (p == QSE_NULL)
|
if (p == QSE_NULL)
|
||||||
{
|
{
|
||||||
/* error in change the value */
|
/* error in changing the value */
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
if (p != pair)
|
if (p != pair)
|
||||||
{
|
{
|
||||||
/* pair reallocated.
|
/* old pair destroyed. new pair reallocated.
|
||||||
* relink it */
|
* relink to include the new pair but to drop
|
||||||
|
* the old pair. */
|
||||||
if (prev == QSE_NULL)
|
if (prev == QSE_NULL)
|
||||||
htb->bucket[hc] = p;
|
htb->bucket[hc] = p;
|
||||||
else NEXT(prev) = p;
|
else NEXT(prev) = p;
|
||||||
NEXT(p) = next;
|
NEXT(p) = next;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
@ -554,7 +483,9 @@ static pair_t* insert (
|
|||||||
|
|
||||||
if (htb->threshold > 0 && htb->size >= htb->threshold)
|
if (htb->threshold > 0 && htb->size >= htb->threshold)
|
||||||
{
|
{
|
||||||
if (reorganize(htb) == 0) /* ignore the error */
|
/* ingore reorganization error as it simply means
|
||||||
|
* more bucket collision and performance penalty. */
|
||||||
|
if (reorganize(htb) == 0)
|
||||||
{
|
{
|
||||||
hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa;
|
hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa;
|
||||||
}
|
}
|
||||||
@ -562,7 +493,7 @@ static pair_t* insert (
|
|||||||
|
|
||||||
QSE_ASSERT (pair == QSE_NULL);
|
QSE_ASSERT (pair == QSE_NULL);
|
||||||
|
|
||||||
pair = alloc_pair (htb, kptr, klen, vptr, vlen);
|
pair = qse_htb_allocpair (htb, kptr, klen, vptr, vlen);
|
||||||
if (pair == QSE_NULL) return QSE_NULL; /* error */
|
if (pair == QSE_NULL) return QSE_NULL; /* error */
|
||||||
|
|
||||||
NEXT(pair) = htb->bucket[hc];
|
NEXT(pair) = htb->bucket[hc];
|
||||||
@ -597,6 +528,68 @@ pair_t* qse_htb_update (
|
|||||||
return insert (htb, kptr, klen, vptr, vlen, UPDATE);
|
return insert (htb, kptr, klen, vptr, vlen, UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pair_t* qse_htb_cbsert (
|
||||||
|
htb_t* htb, void* kptr, size_t klen, cbserter_t cbserter, void* ctx)
|
||||||
|
{
|
||||||
|
pair_t* pair, * p, * prev, * next;
|
||||||
|
size_t hc;
|
||||||
|
|
||||||
|
hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa;
|
||||||
|
pair = htb->bucket[hc];
|
||||||
|
prev = QSE_NULL;
|
||||||
|
|
||||||
|
while (pair != QSE_NULL)
|
||||||
|
{
|
||||||
|
next = NEXT(pair);
|
||||||
|
|
||||||
|
if (htb->mancbs->comper (htb, KPTR(pair), KLEN(pair), kptr, klen) == 0)
|
||||||
|
{
|
||||||
|
/* found a pair with a matching key */
|
||||||
|
p = cbserter (htb, pair, kptr, klen, ctx);
|
||||||
|
if (p == QSE_NULL)
|
||||||
|
{
|
||||||
|
/* error returned by the callback function */
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
if (p != pair)
|
||||||
|
{
|
||||||
|
/* old pair destroyed. new pair reallocated.
|
||||||
|
* relink to include the new pair but to drop
|
||||||
|
* the old pair. */
|
||||||
|
if (prev == QSE_NULL)
|
||||||
|
htb->bucket[hc] = p;
|
||||||
|
else NEXT(prev) = p;
|
||||||
|
NEXT(p) = next;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = pair;
|
||||||
|
pair = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htb->threshold > 0 && htb->size >= htb->threshold)
|
||||||
|
{
|
||||||
|
/* ingore reorganization error as it simply means
|
||||||
|
* more bucket collision and performance penalty. */
|
||||||
|
if (reorganize(htb) == 0)
|
||||||
|
{
|
||||||
|
hc = htb->mancbs->hasher(htb,kptr,klen) % htb->capa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_ASSERT (pair == QSE_NULL);
|
||||||
|
|
||||||
|
pair = cbserter (htb, QSE_NULL, kptr, klen, ctx);
|
||||||
|
if (pair == QSE_NULL) return QSE_NULL; /* error */
|
||||||
|
|
||||||
|
NEXT(pair) = htb->bucket[hc];
|
||||||
|
htb->bucket[hc] = pair;
|
||||||
|
htb->size++;
|
||||||
|
|
||||||
|
return pair; /* new key added */
|
||||||
|
}
|
||||||
|
|
||||||
int qse_htb_delete (htb_t* htb, const void* kptr, size_t klen)
|
int qse_htb_delete (htb_t* htb, const void* kptr, size_t klen)
|
||||||
{
|
{
|
||||||
pair_t* pair, * prev;
|
pair_t* pair, * prev;
|
||||||
@ -614,7 +607,7 @@ int qse_htb_delete (htb_t* htb, const void* kptr, size_t klen)
|
|||||||
htb->bucket[hc] = NEXT(pair);
|
htb->bucket[hc] = NEXT(pair);
|
||||||
else NEXT(prev) = NEXT(pair);
|
else NEXT(prev) = NEXT(pair);
|
||||||
|
|
||||||
free_pair (htb, pair);
|
qse_htb_freepair (htb, pair);
|
||||||
htb->size--;
|
htb->size--;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -639,7 +632,7 @@ void qse_htb_clear (htb_t* htb)
|
|||||||
while (pair != QSE_NULL)
|
while (pair != QSE_NULL)
|
||||||
{
|
{
|
||||||
next = NEXT(pair);
|
next = NEXT(pair);
|
||||||
free_pair (htb, pair);
|
qse_htb_freepair (htb, pair);
|
||||||
htb->size--;
|
htb->size--;
|
||||||
pair = next;
|
pair = next;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,23 @@
|
|||||||
if (f() == -1) return -1; \
|
if (f() == -1) return -1; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
static qse_htb_mancbs_t mancbs1 =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
QSE_HTB_COPIER_INLINE,
|
||||||
|
QSE_HTB_COPIER_INLINE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
QSE_HTB_FREEER_DEFAULT,
|
||||||
|
QSE_HTB_FREEER_DEFAULT
|
||||||
|
},
|
||||||
|
QSE_HTB_HASHER_DEFAULT,
|
||||||
|
QSE_HTB_COMPER_DEFAULT,
|
||||||
|
QSE_HTB_KEEPER_DEFAULT,
|
||||||
|
QSE_HTB_SIZER_DEFAULT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static int test1_build (qse_htb_t* s1)
|
static int test1_build (qse_htb_t* s1)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -109,15 +126,13 @@ static int test1 ()
|
|||||||
{
|
{
|
||||||
qse_htb_t* s1;
|
qse_htb_t* s1;
|
||||||
|
|
||||||
s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 5, 70);
|
s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 5, 70, 1, 1);
|
||||||
if (s1 == QSE_NULL)
|
if (s1 == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("cannot open a map\n"));
|
qse_printf (QSE_T("cannot open a map\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
qse_htb_setmancbs (s1, &mancbs1);
|
||||||
qse_htb_setcopier (s1, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE);
|
|
||||||
qse_htb_setcopier (s1, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE);
|
|
||||||
|
|
||||||
if (test1_build(s1) == -1)
|
if (test1_build(s1) == -1)
|
||||||
{
|
{
|
||||||
@ -154,17 +169,22 @@ static int test2 ()
|
|||||||
QSE_T("in a given directory")
|
QSE_T("in a given directory")
|
||||||
};
|
};
|
||||||
|
|
||||||
s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 1, 70);
|
qse_char_t* vals[] =
|
||||||
|
{
|
||||||
|
QSE_T("what the hell is this"),
|
||||||
|
QSE_T("oh my goddess"),
|
||||||
|
QSE_T("hello mr monkey"),
|
||||||
|
QSE_T("is this good?")
|
||||||
|
};
|
||||||
|
|
||||||
|
s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 1, 70,
|
||||||
|
QSE_SIZEOF(qse_char_t), QSE_SIZEOF(qse_char_t));
|
||||||
if (s1 == QSE_NULL)
|
if (s1 == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("cannot open a map\n"));
|
qse_printf (QSE_T("cannot open a map\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
qse_htb_setmancbs (s1, &mancbs1);
|
||||||
qse_htb_setscale (s1, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t));
|
|
||||||
qse_htb_setscale (s1, QSE_HTB_VAL, QSE_SIZEOF(qse_char_t));
|
|
||||||
qse_htb_setcopier (s1, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE);
|
|
||||||
qse_htb_setcopier (s1, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE);
|
|
||||||
|
|
||||||
for (i = 0; i < QSE_COUNTOF(keys); i++)
|
for (i = 0; i < QSE_COUNTOF(keys); i++)
|
||||||
{
|
{
|
||||||
@ -185,10 +205,28 @@ static int test2 ()
|
|||||||
|
|
||||||
qse_htb_walk (s1, print_map_pair, QSE_NULL);
|
qse_htb_walk (s1, print_map_pair, QSE_NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < QSE_COUNTOF(keys); i++)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("updating a key [%s] and a value [%s]: "), keys[i], vals[i]);
|
||||||
|
if (qse_htb_update (s1,
|
||||||
|
keys[i], qse_strlen(keys[i]),
|
||||||
|
vals[i], qse_strlen(vals[i])) == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("[FAILED]\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("[OK]\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qse_htb_walk (s1, print_map_pair, QSE_NULL);
|
||||||
|
|
||||||
|
|
||||||
qse_htb_close (s1);
|
qse_htb_close (s1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int comp_key (qse_htb_t* map,
|
static int comp_key (qse_htb_t* map,
|
||||||
const void* kptr1, qse_size_t klen1,
|
const void* kptr1, qse_size_t klen1,
|
||||||
const void* kptr2, qse_size_t klen2)
|
const void* kptr2, qse_size_t klen2)
|
||||||
@ -296,12 +334,15 @@ static int test4 ()
|
|||||||
qse_htb_close (s1);
|
qse_htb_close (s1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
R (test1);
|
R (test1);
|
||||||
R (test2);
|
R (test2);
|
||||||
|
#if 0
|
||||||
R (test3);
|
R (test3);
|
||||||
R (test4);
|
R (test4);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user