added qse_rbt_cbsert()
This commit is contained in:
parent
d58631e70b
commit
1c82886941
@ -271,7 +271,7 @@ void* qse_fma_alloc (
|
||||
* the @a size requested is not greater than the fixed block size of the memory
|
||||
* allocator @a fma, it allocates a block of the fixed size; If the block
|
||||
* @a blk is not #QSE_NULL and the @a size requested is not greater than the
|
||||
* fixed block size of the memory allocator @a fma, it returns the block @blk.
|
||||
* fixed block size of the memory allocator @a fma, it returns the block @a blk.
|
||||
*
|
||||
* @return block pointer on success, #QSE_NULL on failure
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: htb.h 365 2010-10-29 13:54:36Z hyunghwan.chung $
|
||||
* $Id: htb.h 366 2010-10-30 12:49:18Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
@ -25,8 +25,44 @@
|
||||
#include <qse/macros.h>
|
||||
|
||||
/**@file
|
||||
* A hash table maintains buckets for key/value pairs with the same key hash
|
||||
* chained under the same bucket.
|
||||
* This file provides a hash table encapsulated in the #qse_htb_t type that
|
||||
* maintains buckets for key/value pairs with the same key hash chained under
|
||||
* the same bucket. Its interface is very close to #qse_rbt_t.
|
||||
*
|
||||
* This sample code adds a series of keys and values and print them
|
||||
* in the randome order.
|
||||
* @code
|
||||
* #include <qse/cmn/htb.h>
|
||||
* #include <qse/cmn/mem.h>
|
||||
* #include <qse/cmn/stdio.h>
|
||||
*
|
||||
* static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
||||
* {
|
||||
* qse_printf (QSE_T("key = %d, value = %d\n"),
|
||||
* *(int*)QSE_HTB_KPTR(pair), *(int*)QSE_HTB_VPTR(pair));
|
||||
* return QSE_HTB_WALK_FORWARD;
|
||||
* }
|
||||
*
|
||||
* int main ()
|
||||
* {
|
||||
* qse_htb_t* s1;
|
||||
* int i;
|
||||
*
|
||||
* s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 30, 75, 1, 1); // error handling skipped
|
||||
* qse_htb_setmancbs (s1, qse_htb_mancbs(QSE_HTB_MANCBS_INLINE_COPIERS));
|
||||
*
|
||||
* for (i = 0; i < 20; i++)
|
||||
* {
|
||||
* int x = i * 20;
|
||||
* qse_htb_insert (s1, &i, QSE_SIZEOF(i), &x, QSE_SIZEOF(x)); // eror handling skipped
|
||||
* }
|
||||
*
|
||||
* qse_htb_walk (s1, walk, QSE_NULL);
|
||||
*
|
||||
* qse_htb_close (s1);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
typedef struct qse_htb_t qse_htb_t;
|
||||
@ -132,6 +168,25 @@ typedef qse_htb_walk_t (*qse_htb_walker_t) (
|
||||
void* ctx /**< pointer to user-defined data */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_htb_cbserter_t type defines a callback function for qse_htb_cbsert().
|
||||
* The qse_htb_cbserter() function calls it to allocate a new pair for the
|
||||
* key pointed to by @a kptr of the length @a klen and the callback context
|
||||
* @a ctx. The second parameter @a pair is passed the pointer to the existing
|
||||
* pair for the key or #QSE_NULL in case of no existing key. The callback
|
||||
* must return a pointer to a new or a reallocated pair. When reallocating the
|
||||
* existing pair, this callback must destroy the existing pair and return the
|
||||
* newly reallocated pair. It must return #QSE_NULL for failure.
|
||||
*/
|
||||
typedef qse_htb_pair_t* (*qse_htb_cbserter_t) (
|
||||
qse_htb_t* htb, /**< hash table */
|
||||
qse_htb_pair_t* pair, /**< pair pointer */
|
||||
void* kptr, /**< key pointer */
|
||||
qse_size_t klen, /**< key length */
|
||||
void* ctx /**< callback context */
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The qse_htb_pair_t type defines hash table pair. A pair is composed of a key
|
||||
* and a value. It maintains pointers to the beginning of a key and a value
|
||||
@ -161,11 +216,19 @@ struct qse_htb_mancbs_t
|
||||
qse_htb_hasher_t hasher; /**< key hasher */
|
||||
};
|
||||
|
||||
/**
|
||||
* The qse_htb_mancbs_kind_t type defines the type of predefined
|
||||
* callback set for pair manipulation.
|
||||
*/
|
||||
enum qse_htb_mancbs_kind_t
|
||||
{
|
||||
/** store the key and the value pointer */
|
||||
QSE_HTB_MANCBS_DEFAULT,
|
||||
/** copy both key and value into the pair */
|
||||
QSE_HTB_MANCBS_INLINE_COPIERS,
|
||||
/** copy the key into the pair but store the value pointer */
|
||||
QSE_HTB_MANCBS_INLINE_KEY_COPIER,
|
||||
/** copy the value into the pair but store the key pointer */
|
||||
QSE_HTB_MANCBS_INLINE_VALUE_COPIER
|
||||
};
|
||||
|
||||
@ -190,7 +253,17 @@ struct qse_htb_t
|
||||
qse_htb_pair_t** bucket;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The QSE_HTB_COPIER_SIMPLE macros defines a copier that remembers the
|
||||
* pointer and length of data in a pair.
|
||||
**/
|
||||
#define QSE_HTB_COPIER_SIMPLE ((qse_htb_copier_t)1)
|
||||
|
||||
/**
|
||||
* The QSE_HTB_COPIER_INLINE macros defines a copier that copies data into
|
||||
* a pair.
|
||||
**/
|
||||
#define QSE_HTB_COPIER_INLINE ((qse_htb_copier_t)2)
|
||||
|
||||
#define QSE_HTB_COPIER_DEFAULT (QSE_HTB_COPIER_SIMPLE)
|
||||
@ -227,6 +300,10 @@ extern "C" {
|
||||
|
||||
QSE_DEFINE_COMMON_FUNCTIONS (htb)
|
||||
|
||||
/**
|
||||
* The qse_htb_mancbs() functions returns a predefined callback set for
|
||||
* pair manipulation.
|
||||
*/
|
||||
const qse_htb_mancbs_t* qse_htb_mancbs (
|
||||
qse_htb_mancbs_kind_t kind
|
||||
);
|
||||
@ -380,24 +457,6 @@ qse_htb_pair_t* qse_htb_update (
|
||||
qse_size_t vlen /**< value length */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_htb_cbserter_t type defines a callback function for qse_htb_cbsert().
|
||||
* The qse_htb_cbserter() function calls it to allocate a new pair for the
|
||||
* key pointed to by @a kptr of the length @a klen and the callback context
|
||||
* @a ctx. The second parameter @a pair is passed the pointer to the existing
|
||||
* pair for the key or #QSE_NULL in case of no existing key. The callback
|
||||
* must return a pointer to a new or a reallocated pair. When reallocating the
|
||||
* existing pair, this callback must destroy the existing pair and return the
|
||||
* newly reallocated pair. It must return #QSE_NULL for failure.
|
||||
*/
|
||||
typedef qse_htb_pair_t* (*qse_htb_cbserter_t) (
|
||||
qse_htb_t* htb, /**< hash table */
|
||||
qse_htb_pair_t* pair, /**< pair pointer */
|
||||
void* kptr, /**< key pointer */
|
||||
qse_size_t klen, /**< key length */
|
||||
void* ctx /**< callback context */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_htb_cbsert() function inserts a key/value pair by delegating pair
|
||||
* allocation to a callback function. Depending on the callback function,
|
||||
@ -407,82 +466,82 @@ typedef qse_htb_pair_t* (*qse_htb_cbserter_t) (
|
||||
* existing value delimited by a comma if the key is found.
|
||||
*
|
||||
* @code
|
||||
* qse_htb_walk_t print_map_pair (qse_htb_t* map, qse_htb_pair_t* pair, void* ctx)
|
||||
* {
|
||||
* qse_printf (QSE_T("%.*s[%d] => %.*s[%d]\n"),
|
||||
* (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_KLEN(pair),
|
||||
* (int)QSE_HTB_VLEN(pair), QSE_HTB_VPTR(pair), (int)QSE_HTB_VLEN(pair));
|
||||
* return QSE_HTB_WALK_FORWARD;
|
||||
* }
|
||||
* qse_htb_walk_t print_map_pair (qse_htb_t* map, qse_htb_pair_t* pair, void* ctx)
|
||||
* {
|
||||
* qse_printf (QSE_T("%.*s[%d] => %.*s[%d]\n"),
|
||||
* (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_KLEN(pair),
|
||||
* (int)QSE_HTB_VLEN(pair), QSE_HTB_VPTR(pair), (int)QSE_HTB_VLEN(pair));
|
||||
* return QSE_HTB_WALK_FORWARD;
|
||||
* }
|
||||
*
|
||||
* qse_htb_pair_t* cbserter (
|
||||
* qse_htb_t* htb, qse_htb_pair_t* pair,
|
||||
* void* kptr, qse_size_t klen, void* ctx)
|
||||
* {
|
||||
* qse_xstr_t* v = (qse_xstr_t*)ctx;
|
||||
* if (pair == QSE_NULL)
|
||||
* {
|
||||
* // no existing key for the key
|
||||
* return qse_htb_allocpair (htb, kptr, klen, v->ptr, v->len);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // a pair with the key exists.
|
||||
* // in this sample, i will append the new value to the old value
|
||||
* // separated by a comma
|
||||
* qse_htb_pair_t* new_pair;
|
||||
* qse_char_t comma = QSE_T(',');
|
||||
* qse_byte_t* vptr;
|
||||
* qse_htb_pair_t* cbserter (
|
||||
* qse_htb_t* htb, qse_htb_pair_t* pair,
|
||||
* void* kptr, qse_size_t klen, void* ctx)
|
||||
* {
|
||||
* qse_xstr_t* v = (qse_xstr_t*)ctx;
|
||||
* if (pair == QSE_NULL)
|
||||
* {
|
||||
* // no existing key for the key
|
||||
* return qse_htb_allocpair (htb, kptr, klen, v->ptr, v->len);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // a pair with the key exists.
|
||||
* // in this sample, i will append the new value to the old value
|
||||
* // separated by a comma
|
||||
* qse_htb_pair_t* new_pair;
|
||||
* qse_char_t comma = QSE_T(',');
|
||||
* qse_byte_t* vptr;
|
||||
*
|
||||
* // allocate a new pair, but without filling the actual value.
|
||||
* // note vptr is given QSE_NULL for that purpose
|
||||
* new_pair = qse_htb_allocpair (
|
||||
* htb, kptr, klen, QSE_NULL, pair->vlen + 1 + v->len);
|
||||
* if (new_pair == QSE_NULL) return QSE_NULL;
|
||||
* // allocate a new pair, but without filling the actual value.
|
||||
* // note vptr is given QSE_NULL for that purpose
|
||||
* new_pair = qse_htb_allocpair (
|
||||
* htb, kptr, klen, QSE_NULL, pair->vlen + 1 + v->len);
|
||||
* if (new_pair == QSE_NULL) return QSE_NULL;
|
||||
*
|
||||
* // fill in the value space
|
||||
* vptr = new_pair->vptr;
|
||||
* qse_memcpy (vptr, pair->vptr, pair->vlen*QSE_SIZEOF(qse_char_t));
|
||||
* vptr += pair->vlen*QSE_SIZEOF(qse_char_t);
|
||||
* qse_memcpy (vptr, &comma, QSE_SIZEOF(qse_char_t));
|
||||
* vptr += QSE_SIZEOF(qse_char_t);
|
||||
* qse_memcpy (vptr, v->ptr, v->len*QSE_SIZEOF(qse_char_t));
|
||||
* // fill in the value space
|
||||
* vptr = new_pair->vptr;
|
||||
* qse_memcpy (vptr, pair->vptr, pair->vlen*QSE_SIZEOF(qse_char_t));
|
||||
* vptr += pair->vlen*QSE_SIZEOF(qse_char_t);
|
||||
* qse_memcpy (vptr, &comma, QSE_SIZEOF(qse_char_t));
|
||||
* vptr += QSE_SIZEOF(qse_char_t);
|
||||
* qse_memcpy (vptr, v->ptr, v->len*QSE_SIZEOF(qse_char_t));
|
||||
*
|
||||
* // this callback requires the old pair to be destroyed
|
||||
* qse_htb_freepair (htb, pair);
|
||||
* // this callback requires the old pair to be destroyed
|
||||
* qse_htb_freepair (htb, pair);
|
||||
*
|
||||
* // return the new pair
|
||||
* return new_pair;
|
||||
* }
|
||||
* }
|
||||
* // return the new pair
|
||||
* return new_pair;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* int main ()
|
||||
* {
|
||||
* qse_htb_t* s1;
|
||||
* int i;
|
||||
* qse_char_t* keys[] = { QSE_T("one"), QSE_T("two"), QSE_T("three") };
|
||||
* qse_char_t* vals[] = { QSE_T("1"), QSE_T("2"), QSE_T("3"), QSE_T("4"), QSE_T("5") };
|
||||
* int main ()
|
||||
* {
|
||||
* qse_htb_t* s1;
|
||||
* int i;
|
||||
* qse_char_t* keys[] = { QSE_T("one"), QSE_T("two"), QSE_T("three") };
|
||||
* qse_char_t* vals[] = { QSE_T("1"), QSE_T("2"), QSE_T("3"), QSE_T("4"), QSE_T("5") };
|
||||
*
|
||||
* s1 = qse_htb_open (
|
||||
* QSE_MMGR_GETDFL(), 0, 10, 70,
|
||||
* QSE_SIZEOF(qse_char_t), QSE_SIZEOF(qse_char_t)
|
||||
* ); // note error check is skipped
|
||||
* qse_htb_setmancbs (s1, &mancbs1);
|
||||
* s1 = qse_htb_open (
|
||||
* QSE_MMGR_GETDFL(), 0, 10, 70,
|
||||
* QSE_SIZEOF(qse_char_t), QSE_SIZEOF(qse_char_t)
|
||||
* ); // note error check is skipped
|
||||
* qse_htb_setmancbs (s1, &mancbs1);
|
||||
*
|
||||
* for (i = 0; i < QSE_COUNTOF(vals); i++)
|
||||
* {
|
||||
* qse_xstr_t ctx;
|
||||
* ctx.ptr = vals[i]; ctx.len = qse_strlen(vals[i]);
|
||||
* qse_htb_cbsert (s1,
|
||||
* keys[i%QSE_COUNTOF(keys)], qse_strlen(keys[i%QSE_COUNTOF(keys)]),
|
||||
* cbserter, &ctx
|
||||
* ); // note error check is skipped
|
||||
* }
|
||||
* qse_htb_walk (s1, print_map_pair, QSE_NULL);
|
||||
* for (i = 0; i < QSE_COUNTOF(vals); i++)
|
||||
* {
|
||||
* qse_xstr_t ctx;
|
||||
* ctx.ptr = vals[i]; ctx.len = qse_strlen(vals[i]);
|
||||
* qse_htb_cbsert (s1,
|
||||
* keys[i%QSE_COUNTOF(keys)], qse_strlen(keys[i%QSE_COUNTOF(keys)]),
|
||||
* cbserter, &ctx
|
||||
* ); // note error check is skipped
|
||||
* }
|
||||
* qse_htb_walk (s1, print_map_pair, QSE_NULL);
|
||||
*
|
||||
* qse_htb_close (s1);
|
||||
* return 0;
|
||||
* }
|
||||
* qse_htb_close (s1);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
qse_htb_pair_t* qse_htb_cbsert (
|
||||
|
@ -47,6 +47,7 @@
|
||||
# define qse_map_ensert(map,kptr,klen,vptr,vlen) qse_htb_ensert(map,kptr,klen,vptr,vlen)
|
||||
# define qse_map_insert(map,kptr,klen,vptr,vlen) qse_htb_insert(map,kptr,klen,vptr,vlen)
|
||||
# define qse_map_update(map,kptr,klen,vptr,vlen) qse_htb_update(map,kptr,klen,vptr,vlen)
|
||||
# define qse_map_cbsert(map,kptr,klen,cb,ctx) qse_htb_cbsert(map,kptr,klen,cb,ctx)
|
||||
# define qse_map_delete(map,kptr,klen) qse_htb_delete(map,kptr,klen)
|
||||
# define qse_map_clear(map) qse_htb_clear(map)
|
||||
# define qse_map_walk(map,walker,ctx) qse_htb_walk(map,walker,ctx)
|
||||
@ -59,6 +60,8 @@
|
||||
# define qse_map_t qse_htb_t
|
||||
# define qse_map_pair_t qse_htb_pair_t
|
||||
# define qse_map_mancbs_t qse_htb_mancbs_t
|
||||
# define qse_map_cbserter_t qse_htb_cbserter_t
|
||||
# define qse_map_walker_t qse_htb_walker_t
|
||||
# define QSE_MAP_COPIER_SIMPLE QSE_HTB_COPIER_SIMPLE
|
||||
# define QSE_MAP_COPIER_INLINE QSE_HTB_COPIER_INLINE
|
||||
# define QSE_MAP_COPIER_DEFAULT QSE_HTB_COPIER_DEFAULT
|
||||
@ -100,6 +103,7 @@
|
||||
# define qse_map_ensert(map,kptr,klen,vptr,vlen) qse_rbt_ensert(map,kptr,klen,vptr,vlen)
|
||||
# define qse_map_insert(map,kptr,klen,vptr,vlen) qse_rbt_insert(map,kptr,klen,vptr,vlen)
|
||||
# define qse_map_update(map,kptr,klen,vptr,vlen) qse_rbt_update(map,kptr,klen,vptr,vlen)
|
||||
# define qse_map_cbsert(map,kptr,klen,cb,ctx) qse_rbt_cbsert(map,kptr,klen,cb,ctx)
|
||||
# define qse_map_delete(map,kptr,klen) qse_rbt_delete(map,kptr,klen)
|
||||
# define qse_map_clear(map) qse_rbt_clear(map)
|
||||
# define qse_map_walk(map,walker,ctx) qse_rbt_walk(map,walker,ctx)
|
||||
@ -112,6 +116,8 @@
|
||||
# define qse_map_t qse_rbt_t
|
||||
# define qse_map_pair_t qse_rbt_pair_t
|
||||
# define qse_map_mancbs_t qse_rbt_mancbs_t
|
||||
# define qse_map_cbserter_t qse_rbt_cbserter_t
|
||||
# define qse_map_walker_t qse_rbt_walker_t
|
||||
# define QSE_MAP_COPIER_SIMPLE QSE_RBT_COPIER_SIMPLE
|
||||
# define QSE_MAP_COPIER_INLINE QSE_RBT_COPIER_INLINE
|
||||
# define QSE_MAP_COPIER_DEFAULT QSE_RBT_COPIER_DEFAULT
|
||||
|
@ -25,7 +25,44 @@
|
||||
#include <qse/macros.h>
|
||||
|
||||
/**@file
|
||||
* A red-black tree is a self-balancing binary search tree.
|
||||
* This file provides a red-black tree encapsulated in the #qse_rbt_t type that
|
||||
* implements a self-balancing binary search tree.Its interface is very close
|
||||
* to #qse_htb_t.
|
||||
*
|
||||
* This sample code adds a series of keys and values and print them
|
||||
* in descending key order.
|
||||
* @code
|
||||
* #include <qse/cmn/rbt.h>
|
||||
* #include <qse/cmn/mem.h>
|
||||
* #include <qse/cmn/stdio.h>
|
||||
*
|
||||
* static qse_rbt_walk_t walk (qse_rbt_t* rbt, qse_rbt_pair_t* pair, void* ctx)
|
||||
* {
|
||||
* qse_printf (QSE_T("key = %d, value = %d\n"),
|
||||
* *(int*)QSE_RBT_KPTR(pair), *(int*)QSE_RBT_VPTR(pair));
|
||||
* return QSE_RBT_WALK_FORWARD;
|
||||
* }
|
||||
*
|
||||
* int main ()
|
||||
* {
|
||||
* qse_rbt_t* s1;
|
||||
* int i;
|
||||
*
|
||||
* s1 = qse_rbt_open (QSE_MMGR_GETDFL(), 0, 1, 1); // error handling skipped
|
||||
* qse_rbt_setmancbs (s1, qse_rbt_mancbs(QSE_RBT_MANCBS_INLINE_COPIERS));
|
||||
*
|
||||
* for (i = 0; i < 20; i++)
|
||||
* {
|
||||
* int x = i * 20;
|
||||
* qse_rbt_insert (s1, &i, QSE_SIZEOF(i), &x, QSE_SIZEOF(x)); // eror handling skipped
|
||||
* }
|
||||
*
|
||||
* qse_rbt_rwalk (s1, walk, QSE_NULL);
|
||||
*
|
||||
* qse_rbt_close (s1);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
typedef struct qse_rbt_t qse_rbt_t;
|
||||
@ -102,11 +139,29 @@ typedef void (*qse_rbt_keeper_t) (
|
||||
* The qse_rbt_walker_t defines a pair visitor.
|
||||
*/
|
||||
typedef qse_rbt_walk_t (*qse_rbt_walker_t) (
|
||||
qse_rbt_t* rbt, /**< rbt */
|
||||
qse_rbt_t* rbt, /**< red-black tree */
|
||||
qse_rbt_pair_t* pair, /**< pointer to a key/value pair */
|
||||
void* ctx /**< pointer to user-defined data */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_cbserter_t type defines a callback function for qse_rbt_cbsert().
|
||||
* The qse_rbt_cbserter() function calls it to allocate a new pair for the
|
||||
* key pointed to by @a kptr of the length @a klen and the callback context
|
||||
* @a ctx. The second parameter @a pair is passed the pointer to the existing
|
||||
* pair for the key or #QSE_NULL in case of no existing key. The callback
|
||||
* must return a pointer to a new or a reallocated pair. When reallocating the
|
||||
* existing pair, this callback must destroy the existing pair and return the
|
||||
* newly reallocated pair. It must return #QSE_NULL for failure.
|
||||
*/
|
||||
typedef qse_rbt_pair_t* (*qse_rbt_cbserter_t) (
|
||||
qse_rbt_t* rbt, /**< red-black tree */
|
||||
qse_rbt_pair_t* pair, /**< pair pointer */
|
||||
void* kptr, /**< key pointer */
|
||||
qse_size_t klen, /**< key length */
|
||||
void* ctx /**< callback context */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_pair_t type defines red-black tree pair. A pair is composed
|
||||
* of a key and a value. It maintains pointers to the beginning of a key and
|
||||
@ -132,6 +187,10 @@ struct qse_rbt_pair_t
|
||||
|
||||
typedef struct qse_rbt_mancbs_t qse_rbt_mancbs_t;
|
||||
|
||||
/**
|
||||
* The qse_rbt_mancbs_t type defines callback function sets for key/value
|
||||
* pair manipulation.
|
||||
*/
|
||||
struct qse_rbt_mancbs_t
|
||||
{
|
||||
qse_rbt_copier_t copier[2]; /**< key and value copier */
|
||||
@ -140,11 +199,19 @@ struct qse_rbt_mancbs_t
|
||||
qse_rbt_keeper_t keeper; /**< value keeper */
|
||||
};
|
||||
|
||||
/**
|
||||
* The qse_rbt_mancbs_kind_t type defines the type of predefined
|
||||
* callback set for pair manipulation.
|
||||
*/
|
||||
enum qse_rbt_mancbs_kind_t
|
||||
{
|
||||
/** store the key and the value pointer */
|
||||
QSE_RBT_MANCBS_DEFAULT,
|
||||
/** copy both key and value into the pair */
|
||||
QSE_RBT_MANCBS_INLINE_COPIERS,
|
||||
/** copy the key into the pair but store the value pointer */
|
||||
QSE_RBT_MANCBS_INLINE_KEY_COPIER,
|
||||
/** copy the value into the pair but store the key pointer */
|
||||
QSE_RBT_MANCBS_INLINE_VALUE_COPIER
|
||||
};
|
||||
|
||||
@ -203,6 +270,10 @@ extern "C" {
|
||||
|
||||
QSE_DEFINE_COMMON_FUNCTIONS (rbt)
|
||||
|
||||
/**
|
||||
* The qse_rbt_mancbs() functions returns a predefined callback set for
|
||||
* pair manipulation.
|
||||
*/
|
||||
const qse_rbt_mancbs_t* qse_rbt_mancbs (
|
||||
qse_rbt_mancbs_kind_t kind
|
||||
);
|
||||
@ -251,7 +322,7 @@ const qse_rbt_mancbs_t* qse_rbt_getmancbs (
|
||||
|
||||
/**
|
||||
* The qse_rbt_setmancbs() function sets internal manipulation callback
|
||||
* functions for data construction, destruction, resizing, hashing, etc.
|
||||
* functions for data construction, destruction, comparison, etc.
|
||||
*/
|
||||
void qse_rbt_setmancbs (
|
||||
qse_rbt_t* rbt, /**< red-black tree */
|
||||
@ -335,6 +406,101 @@ qse_rbt_pair_t* qse_rbt_update (
|
||||
qse_size_t vlen /**< value length */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_cbsert() function inserts a key/value pair by delegating pair
|
||||
* allocation to a callback function. Depending on the callback function,
|
||||
* it may behave like qse_rbt_insert(), qse_rbt_upsert(), qse_rbt_update(),
|
||||
* qse_rbt_ensert(), or totally differently. The sample code below inserts
|
||||
* a new pair if the key is not found and appends the new value to the
|
||||
* existing value delimited by a comma if the key is found.
|
||||
*
|
||||
* @code
|
||||
* qse_rbt_walk_t print_map_pair (qse_rbt_t* map, qse_rbt_pair_t* pair, void* ctx)
|
||||
* {
|
||||
* qse_printf (QSE_T("%.*s[%d] => %.*s[%d]\n"),
|
||||
* (int)QSE_RBT_KLEN(pair), QSE_RBT_KPTR(pair), (int)QSE_RBT_KLEN(pair),
|
||||
* (int)QSE_RBT_VLEN(pair), QSE_RBT_VPTR(pair), (int)QSE_RBT_VLEN(pair));
|
||||
* return QSE_RBT_WALK_FORWARD;
|
||||
* }
|
||||
*
|
||||
* qse_rbt_pair_t* cbserter (
|
||||
* qse_rbt_t* rbt, qse_rbt_pair_t* pair,
|
||||
* void* kptr, qse_size_t klen, void* ctx)
|
||||
* {
|
||||
* qse_xstr_t* v = (qse_xstr_t*)ctx;
|
||||
* if (pair == QSE_NULL)
|
||||
* {
|
||||
* // no existing key for the key
|
||||
* return qse_rbt_allocpair (rbt, kptr, klen, v->ptr, v->len);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // a pair with the key exists.
|
||||
* // in this sample, i will append the new value to the old value
|
||||
* // separated by a comma
|
||||
* qse_rbt_pair_t* new_pair;
|
||||
* qse_char_t comma = QSE_T(',');
|
||||
* qse_byte_t* vptr;
|
||||
*
|
||||
* // allocate a new pair, but without filling the actual value.
|
||||
* // note vptr is given QSE_NULL for that purpose
|
||||
* new_pair = qse_rbt_allocpair (
|
||||
* rbt, kptr, klen, QSE_NULL, pair->vlen + 1 + v->len);
|
||||
* if (new_pair == QSE_NULL) return QSE_NULL;
|
||||
*
|
||||
* // fill in the value space
|
||||
* vptr = new_pair->vptr;
|
||||
* qse_memcpy (vptr, pair->vptr, pair->vlen*QSE_SIZEOF(qse_char_t));
|
||||
* vptr += pair->vlen*QSE_SIZEOF(qse_char_t);
|
||||
* qse_memcpy (vptr, &comma, QSE_SIZEOF(qse_char_t));
|
||||
* vptr += QSE_SIZEOF(qse_char_t);
|
||||
* qse_memcpy (vptr, v->ptr, v->len*QSE_SIZEOF(qse_char_t));
|
||||
*
|
||||
* // this callback requires the old pair to be destroyed
|
||||
* qse_rbt_freepair (rbt, pair);
|
||||
*
|
||||
* // return the new pair
|
||||
* return new_pair;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* int main ()
|
||||
* {
|
||||
* qse_rbt_t* s1;
|
||||
* int i;
|
||||
* qse_char_t* keys[] = { QSE_T("one"), QSE_T("two"), QSE_T("three") };
|
||||
* qse_char_t* vals[] = { QSE_T("1"), QSE_T("2"), QSE_T("3"), QSE_T("4"), QSE_T("5") };
|
||||
*
|
||||
* s1 = qse_rbt_open (
|
||||
* QSE_MMGR_GETDFL(), 0,
|
||||
* QSE_SIZEOF(qse_char_t), QSE_SIZEOF(qse_char_t)
|
||||
* ); // note error check is skipped
|
||||
* qse_rbt_setmancbs (s1, &mancbs1);
|
||||
*
|
||||
* for (i = 0; i < QSE_COUNTOF(vals); i++)
|
||||
* {
|
||||
* qse_xstr_t ctx;
|
||||
* ctx.ptr = vals[i]; ctx.len = qse_strlen(vals[i]);
|
||||
* qse_rbt_cbsert (s1,
|
||||
* keys[i%QSE_COUNTOF(keys)], qse_strlen(keys[i%QSE_COUNTOF(keys)]),
|
||||
* cbserter, &ctx
|
||||
* ); // note error check is skipped
|
||||
* }
|
||||
* qse_rbt_walk (s1, print_map_pair, QSE_NULL);
|
||||
*
|
||||
* qse_rbt_close (s1);
|
||||
* return 0;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
qse_rbt_pair_t* qse_rbt_cbsert (
|
||||
qse_rbt_t* rbt, /**< red-black tree */
|
||||
void* kptr, /**< key pointer */
|
||||
qse_size_t klen, /**< key length */
|
||||
qse_rbt_cbserter_t cbserter, /**< callback function */
|
||||
void* ctx /**< callback context */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_delete() function deletes a pair with a matching key
|
||||
* @return 0 on success, -1 on failure
|
||||
@ -372,6 +538,39 @@ void qse_rbt_rwalk (
|
||||
void* ctx /**< pointer to user-specific data */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_allocpair() function allocates a pair for a key and a value
|
||||
* given. But it does not chain the pair allocated into the red-black tree @a rbt.
|
||||
* Use this function at your own risk.
|
||||
*
|
||||
* Take note of he following special behavior when the copier is
|
||||
* #QSE_RBT_COPIER_INLINE.
|
||||
* - If @a kptr is #QSE_NULL, the key space of the size @a klen is reserved but
|
||||
* not propagated with any data.
|
||||
* - If @a vptr is #QSE_NULL, the value space of the size @a vlen is reserved
|
||||
* but not propagated with any data.
|
||||
*/
|
||||
qse_rbt_pair_t* qse_rbt_allocpair (
|
||||
qse_rbt_t* rbt,
|
||||
void* kptr,
|
||||
qse_size_t klen,
|
||||
void* vptr,
|
||||
qse_size_t vlen
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_freepair() function destroys a pair. But it does not detach
|
||||
* the pair destroyed from the red-black tree @a rbt. Use this function at your
|
||||
* own risk.
|
||||
*/
|
||||
void qse_rbt_freepair (
|
||||
qse_rbt_t* rbt,
|
||||
qse_rbt_pair_t* pair
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_rbt_dflcomp() function defines the default key comparator.
|
||||
*/
|
||||
int qse_rbt_dflcomp (
|
||||
qse_rbt_t* rbt,
|
||||
const void* kptr1,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: str.h 356 2010-09-07 12:29:25Z hyunghwan.chung $
|
||||
* $Id: str.h 366 2010-10-30 12:49:18Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
@ -229,7 +229,7 @@ qse_size_t qse_strfcpy (
|
||||
|
||||
/**
|
||||
* The qse_strfncpy() function formats a string by position.
|
||||
* It differs from qse_strfcpy() in that @str is an array of the
|
||||
* It differs from qse_strfcpy() in that @a str is an array of the
|
||||
* #qse_cstr_t type.
|
||||
* @sa qse_strfcpy, qse_strxfcpy, qse_strxfncpy
|
||||
*/
|
||||
|
@ -140,7 +140,7 @@ void qse_xma_close (
|
||||
* The qse_xma_init() initializes a memory allocator. If you have the qse_xma_t
|
||||
* structure statically declared or already allocated, you may pass the pointer
|
||||
* to this function instead of calling qse_xma_open(). It obtains a memory zone
|
||||
* of @a zonesize bytes with the memory manager @mmgr. Unlike qse_xma_open(),
|
||||
* of @a zonesize bytes with the memory manager @a mmgr. Unlike qse_xma_open(),
|
||||
* it does not accept the extension size, thus not creating an extention area.
|
||||
* @return @a xma on success, #QSE_NULL on failure
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -109,17 +109,120 @@ static int test2 ()
|
||||
|
||||
qse_printf (QSE_T("-------------------\n"));
|
||||
qse_rbt_upsert (s1, QSE_T("hello"), 5, QSE_T("dr. gorilla"), 11);
|
||||
qse_rbt_upsert (s1, QSE_T("thinkpad"), 8, QSE_T("x61 rocks"), 9);
|
||||
qse_rbt_upsert (s1, QSE_T("thinkpad"), 8, QSE_T("x61 rocks on"), 13);
|
||||
qse_rbt_ensert (s1, QSE_T("vista"), 5, QSE_T("microsoft"), 9);
|
||||
qse_rbt_update (s1, QSE_T("world"), 5, QSE_T("baseball classic"), 16);
|
||||
qse_rbt_rwalk (s1, walk2, QSE_NULL);
|
||||
|
||||
qse_rbt_close (s1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qse_rbt_walk_t print_map_pair (qse_rbt_t* map, qse_rbt_pair_t* pair, void* arg)
|
||||
{
|
||||
qse_printf (QSE_T("%.*s[%d] => %.*s[%d]\n"),
|
||||
(int)QSE_RBT_KLEN(pair), QSE_RBT_KPTR(pair), (int)QSE_RBT_KLEN(pair),
|
||||
(int)QSE_RBT_VLEN(pair), QSE_RBT_VPTR(pair), (int)QSE_RBT_VLEN(pair));
|
||||
|
||||
return QSE_RBT_WALK_FORWARD;
|
||||
}
|
||||
|
||||
static qse_rbt_pair_t* test5_cbserter (
|
||||
qse_rbt_t* rbt, qse_rbt_pair_t* pair,
|
||||
void* kptr, qse_size_t klen, void* ctx)
|
||||
{
|
||||
qse_xstr_t* v = (qse_xstr_t*)ctx;
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
/* no existing key for the key */
|
||||
return qse_rbt_allocpair (rbt, kptr, klen, v->ptr, v->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* a pair with the key exists.
|
||||
* in this sample, i will append the new value to the old value
|
||||
* separated by a comma */
|
||||
|
||||
qse_rbt_pair_t* new_pair;
|
||||
qse_char_t comma = QSE_T(',');
|
||||
qse_byte_t* vptr;
|
||||
|
||||
/* allocate a new pair, but without filling the actual value.
|
||||
* note vptr is given QSE_NULL for that purpose */
|
||||
new_pair = qse_rbt_allocpair (
|
||||
rbt, kptr, klen, QSE_NULL, pair->vlen + 1 + v->len);
|
||||
if (new_pair == QSE_NULL) return QSE_NULL;
|
||||
|
||||
/* fill in the value space */
|
||||
vptr = new_pair->vptr;
|
||||
qse_memcpy (vptr, pair->vptr, pair->vlen*QSE_SIZEOF(qse_char_t));
|
||||
vptr += pair->vlen*QSE_SIZEOF(qse_char_t);
|
||||
qse_memcpy (vptr, &comma, QSE_SIZEOF(qse_char_t));
|
||||
vptr += QSE_SIZEOF(qse_char_t);
|
||||
qse_memcpy (vptr, v->ptr, v->len*QSE_SIZEOF(qse_char_t));
|
||||
|
||||
/* this callback requires the old pair to be destroyed */
|
||||
qse_rbt_freepair (rbt, pair);
|
||||
|
||||
/* return the new pair */
|
||||
return new_pair;
|
||||
}
|
||||
}
|
||||
|
||||
static int test5 ()
|
||||
{
|
||||
qse_rbt_t* s1;
|
||||
int i;
|
||||
|
||||
qse_char_t* keys[] =
|
||||
{
|
||||
QSE_T("one"), QSE_T("two"), QSE_T("three")
|
||||
};
|
||||
qse_char_t* vals[] =
|
||||
{
|
||||
QSE_T("1"), QSE_T("2"), QSE_T("3"), QSE_T("4"), QSE_T("5"),
|
||||
};
|
||||
|
||||
s1 = qse_rbt_open (QSE_MMGR_GETDFL(), 0,
|
||||
QSE_SIZEOF(qse_char_t), QSE_SIZEOF(qse_char_t));
|
||||
if (s1 == QSE_NULL)
|
||||
{
|
||||
qse_printf (QSE_T("cannot open a hash table\n"));
|
||||
return -1;
|
||||
}
|
||||
qse_rbt_setmancbs (s1, qse_rbt_mancbs(QSE_RBT_MANCBS_INLINE_COPIERS));
|
||||
|
||||
for (i = 0; i < QSE_COUNTOF(vals); i++)
|
||||
{
|
||||
qse_xstr_t ctx;
|
||||
|
||||
qse_printf (QSE_T("setting a key [%s] and a value [%s]: "), keys[i%QSE_COUNTOF(keys)], vals[i]);
|
||||
|
||||
ctx.ptr = vals[i];
|
||||
ctx.len = qse_strlen(vals[i]);
|
||||
if (qse_rbt_cbsert (s1,
|
||||
keys[i%QSE_COUNTOF(keys)],
|
||||
qse_strlen(keys[i%QSE_COUNTOF(keys)]),
|
||||
test5_cbserter, &ctx) == QSE_NULL)
|
||||
{
|
||||
qse_printf (QSE_T("[FAILED]\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_printf (QSE_T("[OK]\n"));
|
||||
}
|
||||
}
|
||||
qse_rbt_walk (s1, print_map_pair, QSE_NULL);
|
||||
|
||||
|
||||
qse_rbt_close (s1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
R (test1);
|
||||
R (test2);
|
||||
R (test5);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user