added qse_rbt_cbsert()

This commit is contained in:
2010-10-31 06:49:18 +00:00
parent d58631e70b
commit 1c82886941
9 changed files with 601 additions and 134 deletions

View File

@ -1,5 +1,5 @@
/*
* $Id: htb.c 365 2010-10-29 13:54:36Z hyunghwan.chung $
* $Id: htb.c 366 2010-10-30 12:49:18Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@ -23,16 +23,18 @@
QSE_IMPLEMENT_COMMON_FUNCTIONS (htb)
#define htb_t qse_htb_t
#define pair_t qse_htb_pair_t
#define copier_t qse_htb_copier_t
#define freeer_t qse_htb_freeer_t
#define hasher_t qse_htb_hasher_t
#define comper_t qse_htb_comper_t
#define keeper_t qse_htb_keeper_t
#define sizer_t qse_htb_sizer_t
#define walker_t qse_htb_walker_t
#define cbserter_t qse_htb_cbserter_t
#define htb_t qse_htb_t
#define pair_t qse_htb_pair_t
#define copier_t qse_htb_copier_t
#define freeer_t qse_htb_freeer_t
#define hasher_t qse_htb_hasher_t
#define comper_t qse_htb_comper_t
#define keeper_t qse_htb_keeper_t
#define sizer_t qse_htb_sizer_t
#define walker_t qse_htb_walker_t
#define cbserter_t qse_htb_cbserter_t
#define mancbs_t qse_htb_mancbs_t
#define mancbs_kind_t qse_htb_mancbs_kind_t
#define KPTR(p) QSE_HTB_KPTR(p)
#define KLEN(p) QSE_HTB_KLEN(p)
@ -153,7 +155,7 @@ static QSE_INLINE pair_t* change_pair_val (
{
if (ovlen == vlen)
{
QSE_MEMCPY (VPTR(pair), vptr, VTOB(htb,vlen));
if (vptr) QSE_MEMCPY (VPTR(pair), vptr, VTOB(htb,vlen));
}
else
{
@ -185,7 +187,7 @@ static QSE_INLINE pair_t* change_pair_val (
return pair;
}
static qse_htb_mancbs_t mancbs[] =
static mancbs_t mancbs[] =
{
{
{
@ -248,7 +250,7 @@ static qse_htb_mancbs_t mancbs[] =
}
};
const qse_htb_mancbs_t* qse_htb_mancbs (qse_htb_mancbs_kind_t kind)
const mancbs_t* qse_htb_mancbs (mancbs_kind_t kind)
{
return &mancbs[kind];
};
@ -330,12 +332,12 @@ void qse_htb_fini (htb_t* htb)
QSE_MMGR_FREE (htb->mmgr, htb->bucket);
}
const qse_htb_mancbs_t* qse_htb_getmancbs (htb_t* htb)
const mancbs_t* qse_htb_getmancbs (htb_t* htb)
{
return htb->mancbs;
}
void qse_htb_setmancbs (htb_t* htb, const qse_htb_mancbs_t* mancbs)
void qse_htb_setmancbs (htb_t* htb, const mancbs_t* mancbs)
{
QSE_ASSERT (mancbs != QSE_NULL);
htb->mancbs = mancbs;

View File

@ -23,14 +23,17 @@
QSE_IMPLEMENT_COMMON_FUNCTIONS (rbt)
#define rbt_t qse_rbt_t
#define pair_t qse_rbt_pair_t
#define id_t qse_rbt_id_t
#define copier_t qse_rbt_copier_t
#define freeer_t qse_rbt_freeer_t
#define comper_t qse_rbt_comper_t
#define keeper_t qse_rbt_keeper_t
#define walker_t qse_rbt_walker_t
#define rbt_t qse_rbt_t
#define pair_t qse_rbt_pair_t
#define id_t qse_rbt_id_t
#define copier_t qse_rbt_copier_t
#define freeer_t qse_rbt_freeer_t
#define comper_t qse_rbt_comper_t
#define keeper_t qse_rbt_keeper_t
#define walker_t qse_rbt_walker_t
#define cbserter_t qse_rbt_cbserter_t
#define mancbs_t qse_rbt_mancbs_t
#define mancbs_kind_t qse_rbt_mancbs_kind_t
#define KPTR(p) QSE_RBT_KPTR(p)
#define KLEN(p) QSE_RBT_KLEN(p)
@ -134,7 +137,7 @@ QSE_INLINE void qse_rbt_freepair (rbt_t* rbt, pair_t* pair)
QSE_MMGR_FREE (rbt->mmgr, pair);
}
static qse_rbt_mancbs_t mancbs[] =
static mancbs_t mancbs[] =
{
{
{
@ -189,7 +192,7 @@ static qse_rbt_mancbs_t mancbs[] =
}
};
const qse_rbt_mancbs_t* qse_rbt_mancbs (qse_rbt_mancbs_kind_t kind)
const mancbs_t* qse_rbt_mancbs (mancbs_kind_t kind)
{
return &mancbs[kind];
};
@ -257,12 +260,12 @@ void qse_rbt_fini (rbt_t* rbt)
qse_rbt_clear (rbt);
}
const qse_rbt_mancbs_t* qse_rbt_getmancbs (rbt_t* rbt)
const mancbs_t* qse_rbt_getmancbs (rbt_t* rbt)
{
return rbt->mancbs;
}
void qse_rbt_setmancbs (rbt_t* rbt, const qse_rbt_mancbs_t* mancbs)
void qse_rbt_setmancbs (rbt_t* rbt, const mancbs_t* mancbs)
{
QSE_ASSERT (mancbs != QSE_NULL);
rbt->mancbs = mancbs;
@ -450,7 +453,7 @@ static pair_t* change_pair_val (
{
if (ovlen == vlen)
{
QSE_MEMCPY (VPTR(pair), vptr, VTOB(rbt,vlen));
if (vptr) QSE_MEMCPY (VPTR(pair), vptr, VTOB(rbt,vlen));
}
else
{
@ -597,6 +600,101 @@ pair_t* qse_rbt_update (
return insert (rbt, kptr, klen, vptr, vlen, UPDATE);
}
pair_t* qse_rbt_cbsert (
rbt_t* rbt, void* kptr, size_t klen, cbserter_t cbserter, void* ctx)
{
pair_t* xcur = rbt->root;
pair_t* xpar = QSE_NULL;
pair_t* xnew;
while (!IS_NIL(rbt,xcur))
{
int n = rbt->mancbs->comper (rbt, kptr, klen, xcur->kptr, xcur->klen);
if (n == 0)
{
/* back up the contents of the current pair
* in case it is reallocated */
pair_t tmp = *xcur;
/* call the callback function to manipulate the pair */
xnew = cbserter (rbt, xcur, kptr, klen, ctx);
if (xnew == QSE_NULL)
{
/* error returned by the callback function */
return QSE_NULL;
}
if (xnew != xcur)
{
/* the current pair has been reallocated, which implicitly
* means the previous contents were wiped out. so the contents
* backed up will be used for restoration/migration */
xnew->color = tmp.color;
xnew->left = tmp.left;
xnew->right = tmp.right;
xnew->parent = tmp.parent;
if (tmp.parent)
{
if (tmp.parent->left == xcur)
{
tmp.parent->left = xnew;
}
else
{
QSE_ASSERT (tmp.parent->right == xcur);
tmp.parent->right = xnew;
}
}
if (!IS_NIL(rbt,tmp.left)) tmp.left->parent = xnew;
if (!IS_NIL(rbt,tmp.right)) tmp.right->parent = xnew;
if (xcur == rbt->root) rbt->root = xnew;
}
return xnew;
}
xpar = xcur;
if (n > 0) xcur = xcur->right;
else /* if (n < 0) */ xcur = xcur->left;
}
xnew = cbserter (rbt, QSE_NULL, kptr, klen, ctx);
if (xnew == QSE_NULL) return QSE_NULL;
if (xpar == QSE_NULL)
{
/* the tree contains no pair */
QSE_ASSERT (rbt->root == &rbt->nil);
rbt->root = xnew;
}
else
{
/* perform normal binary insert */
int n = rbt->mancbs->comper (rbt, kptr, klen, xpar->kptr, xpar->klen);
if (n > 0)
{
QSE_ASSERT (xpar->right == &rbt->nil);
xpar->right = xnew;
}
else
{
QSE_ASSERT (xpar->left == &rbt->nil);
xpar->left = xnew;
}
xnew->parent = xpar;
adjust (rbt, xnew);
}
rbt->root->color = QSE_RBT_BLACK;
return xnew;
}
static void adjust_for_delete (rbt_t* rbt, pair_t* pair, pair_t* par)
{
while (pair != rbt->root && pair->color == QSE_RBT_BLACK)