added qse_rbt_cbsert()
This commit is contained in:
@ -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;
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user