Remove rbtree_prefix from Red Black Tree.

(See commit on shared-pointer).

Rename rbntree_name_it_t into name_it_t.

Update tests, documentation, bench in accordance.
This commit is contained in:
Patrick Pelissier committed 2017-07-26 22:56:25 +02:00
1 parent 8f33273d7e
commit 7d2848e16a
5 files changed
+235 -226

No files matched your search

+44 -40
View File
@@ -1453,7 +1453,7 @@ for this function to be defined.
#### RBTREE\_DEF(name, type[, oplist])
Define the binary ordered tree 'rbtree\_##name##\_t' and its associated methods as "static inline" functions.
Define the binary ordered tree 'name##\_t' and its associated methods as "static inline" functions.
A binary tree is a tree data structure in which each node has at most two children, which are referred to as the left child and the right child.
In this kind of tree, all elements of the tree are totally ordered.
The current implementation is [RED-BLACK TREE](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree).
@@ -1467,13 +1467,13 @@ pushed item already exist in the container. The default behavior
will overwrite the recorded value with the new one.
It shall be done once per type and per compilation unit.
It also define the iterator rbtree\_it\_##name##\_t and its associated methods as "static inline" functions.
It also define the iterator name##\_it\_t and its associated methods as "static inline" functions.
The object oplist is expected to have the following operators (INIT, INIT_SET, SET, CMP and CLEAR), otherwise default operators are used. If there is no given oplist, the default operators are also used. The created methods will use the operators to init, set and clear the contained object.
Example:
RBTREE_DEF(uint, unsigned int)
RBTREE_DEF(rbtree_uint, unsigned int)
void f(unsigned int num) {
rbtree_uint_t tree;
rbtree_uint_init(tree);
@@ -1482,161 +1482,165 @@ Example:
rbtree_uint_clear(tree);
}
#### RBTREE\_OPLIST(name [, oplist])
Return the oplist of the Red-Black defined by calling RBTREE\_DEF with name & oplist.
#### Created methods
The following methods are automatically and properly created by the previous macros.
In the following methods, name stands for the name given to the macro which is used to identify the type.
##### rbtree\_name\_t
##### name\_t
Type of the Red Black Tree of 'type'.
##### rbtree\_it\_name\_t
##### name\it_\_t
Type of an iterator over this Red Black Tree.
##### void rbtree\_name\_init(rbtree\_name\_t rbtree)
##### void name\_init(name\_t rbtree)
Initialize the Red Black Tree 'rbtree' to be empty.
##### void rbtree\_name\_clear(rbtree\_name\_t rbtree)
##### void name\_clear(name\_t rbtree)
Clear the Red Black Tree 'rbtree'.
##### void rbtree\_name\_init\_set(rbtree\_name\_t rbtree, const rbtree\_name\_t ref)
##### void name\_init\_set(name\_t rbtree, const name\_t ref)
Initialize the Red Black Tree 'rbtree' to be the same as 'ref'.
##### void rbtree\_name\_set(rbtree\_name\_t rbtree, const rbtree\_name\_t ref)
##### void name\_set(name\_t rbtree, const name\_t ref)
Set the Red Black Tree 'rbtree' to be the same as 'ref'.
##### void rbtree\_name\_init\_move(rbtree\_name\_t rbtree, rbtree\_name\_t ref)
##### void name\_init\_move(name\_t rbtree, name\_t ref)
Initialize the Red Black Tree 'rbtree' by stealing as resource as possible
from 'ref' and clear 'ref'.
##### void rbtree\_name\_move(rbtree\_name\_t rbtree, rbtree\_name\_t ref)
##### void name\_move(name\_t rbtree, name\_t ref)
Set the Red Black Tree 'rbtree' by stealing as resource as possible
from 'ref' and clear 'ref'.
##### void rbtree\_name\_clean(rbtree\_name\_t rbtree)
##### void name\_clean(name\_t rbtree)
Clean the Red Black Tree 'rbtree'. 'rbtree' remains initialized but empty.
##### size\_t rbtree\_name\_size(const rbtree\_name\_t rbtree)
##### size\_t name\_size(const name\_t rbtree)
Return the number of elements of the Red Black Tree.
##### void rbtree\_name\_push(rbtree\_name\_t rbtree, const type data)
##### void name\_push(name\_t rbtree, const type data)
Push 'data' into the Red Black Tree 'rbtree' at its ordered place
while keeping the tree balanced.
##### void rbtree\_name\_pop(type *dest, rbtree\_name\_t rbtree, const type data)
##### void name\_pop(type *dest, name\_t rbtree, const type data)
Pop 'data' from the Red Black Tree 'rbtree'
and save the poped value into 'dest' if the pointer is not null
while keeping the tree balanced.
Do nothing if 'data' is no present in the Red Black Tree.
##### type * rbtree\_name\_min(const rbtree\_name\_t rbtree)
##### const type * rbtree\_name\_cmin(const rbtree\_name\_t rbtree)
##### type * name\_min(const name\_t rbtree)
##### const type * name\_cmin(const name\_t rbtree)
Return a pointer to the minimum element of the tree
or NULL if there is no element.
##### type * rbtree\_name\_max(const rbtree\_name\_t rbtree)
##### const type * rbtree\_name\_cmax(const rbtree\_name\_t rbtree)
##### type * name\_max(const name\_t rbtree)
##### const type * name\_cmax(const name\_t rbtree)
Return a pointer to the maximum element of the tree
or NULL if there is no element.
##### type * rbtree\_name\_get(const rbtree\_name\_t rbtree, const type *data)
##### const type * rbtree\_name\_cget(const rbtree\_name\_t rbtree, const type *data)
##### type * name\_get(const name\_t rbtree, const type *data)
##### const type * name\_cget(const name\_t rbtree, const type *data)
Return a pointer to the element of the tree 'rbtree' which is equal to 'data',
or NULL if there is no match.
##### void rbtree\_name\_swap(rbtree\_name\_t rbtree1, rbtree\_name\_t rbtree2)
##### void name\_swap(name\_t rbtree1, name\_t rbtree2)
Swap both trees.
##### bool rbtree\_name\_empty\_p(const rbtree\_name\_t rbtree)
##### bool name\_empty\_p(const name\_t rbtree)
Return true if the tree is empty, false otherwise.
##### void rbtree\_name\_it(rbtree\_it\_name\_t it, rbtree\_name\_t rbtree)
##### void name\_it(name\it_\_t it, name\_t rbtree)
Set the iterator 'it' to the first element of 'rbtree'.
##### void rbtree\_name\_it\_set(rbtree\_it\_name\_t it, const rbtree\_it\_name\_t ref)
##### void name\_it\_set(name\it_\_t it, const name\it_\_t ref)
Set the iterator 'it' to the same element than 'ref'.
##### void rbtree\_name\_it\_last(rbtree\_it\_name\_t it, rbtree\_name\_t rbtree)
##### void name\_it\_last(name\it_\_t it, name\_t rbtree)
Set the iterator 'it' to the last element of 'rbtree'.
##### void rbtree\_name\_it\_end(rbtree\_it\_name\_t it, rbtree\_name\_t rbtree)
##### void name\_it\_end(name\it_\_t it, name\_t rbtree)
Set the iterator 'it' to no element of 'rbtree'.
##### void rbtree\_name\_it\_from(rbtree\_it\_name\_t it, const rbtree\_name\_t rbtree, const type data)
##### void name\_it\_from(name\it_\_t it, const name\_t rbtree, const type data)
Set the iterator 'it' to the greatest element of 'rbtree'
lower of equal than 'data' or the first element is there is none.
##### bool rbtree\_name\_end\_p(const rbtree\_it\_name\_t it)
##### bool name\_end\_p(const name\it_\_t it)
Return true if 'it' references no longer a valid element.
##### bool rbtree\_name\_last\_p(const rbtree\_it\_name\_t it)
##### bool name\_last\_p(const name\it_\_t it)
Return true if 'it' references the last element or is no longer valid.
##### bool rbtree\_name\_to\_p(const rbtree\_it\_name\_t it, const type data)
##### bool name\_to\_p(const name\it_\_t it, const type data)
Return true if 'it' references an element which is greater or equal than 'data'.
##### void rbtree\_name\_next(rbtree\_it\_name\_t it)
##### void name\_next(name\it_\_t it)
Update the iterator 'it' to the next element.
##### void rbtree\_name\_previous(rbtree\_it\_name\_t it)
##### void name\_previous(name\it_\_t it)
Update the iterator 'it' to the previous element.
##### type *rbtree\_name\_ref(rbtree\_it\_name\_t it)
##### const type *rbtree\_name\_ref(rbtree\_it\_name\_t it)
##### type *name\_ref(name\it_\_t it)
##### const type *name\_ref(name\it_\_t it)
Return a pointer to the element pointer by the iterator 'it'.
This pointer remains valid until the Red Black Tree is modified by another method.
##### void rbtree\_name\_get\_str(string\_t str, const rbtree\_name\_t rbtree, bool append)
##### void name\_get\_str(string\_t str, const name\_t rbtree, bool append)
Generate a string representation of the rbtree 'rbtree' and set 'str' to this representation
(if 'append' is false) or append 'str' with this representation (if 'append' is true).
This method is only defined if the type of the element defines a GET\_STR method itself.
##### void rbtree\_name\_out\_str(FILE *file, const rbtree\_name\_t rbtree)
##### void name\_out\_str(FILE *file, const name\_t rbtree)
Generate a string representation of the rbtree 'rbtree' and outputs it into the FILE 'file'.
This method is only defined if the type of the element defines a OUT\_STR method itself.
##### void rbtree\_name\_in\_str(FILE *file, const rbtree\_name\_t rbtree)
##### void name\_in\_str(FILE *file, const name\_t rbtree)
Read from the file 'file' a string representation of a rbtree and set 'rbtree' to this representation.
This method is only defined if the type of the element defines a IN\_STR method itself.
##### bool rbtree\_name\_equal\_p(const rbtree\_name\_t rbtree1, const rbtree\_name\_t rbtree2)
##### bool name\_equal\_p(const name\_t rbtree1, const name\_t rbtree2)
Return true if both rbtrees 'rbtree1' and 'rbtree2' are equal.
This method is only defined if the type of the element defines a EQUAL method itself.
##### size\_t rbtree\_name\_hash\_p(const rbtree\_name\_t rbtree)
##### size\_t name\_hash\_p(const name\_t rbtree)
Return the hash of the tree.
This method is only defined if the type of the element defines a HASH method itself.
+3 -3
View File
@@ -69,9 +69,9 @@ static void test_list (size_t n)
/********************************************************************************************/
#ifdef USE_MEMPOOL
RBTREE_DEF(ulong, unsigned long, (MEMPOOL( rbtree_mpool), MEMPOOL_LINKAGE(static)))
RBTREE_DEF(rbtree_ulong, unsigned long, (MEMPOOL( rbtree_mpool), MEMPOOL_LINKAGE(static)))
#else
RBTREE_DEF(ulong, unsigned long)
RBTREE_DEF(rbtree_ulong, unsigned long)
#endif
static void test_rbtree(size_t n)
@@ -79,7 +79,7 @@ static void test_rbtree(size_t n)
#ifdef USE_MEMPOOL
mempool_rbtree_ulong_init(rbtree_mpool);
#endif
M_LET(tree, RBTREE_OPLIST(ulong)) {
M_LET(tree, RBTREE_OPLIST(rbtree_ulong)) {
for (size_t i = 0; i < n; i++) {
rbtree_ulong_push(tree, rand_get());
}
+1 -1
View File
@@ -127,7 +127,7 @@ void my_type_rand(my_type_t x)
#define MY_TYPE_OPLIST (TYPE(my_type_t), INIT(my_type_init), CLEAR(my_type_clear), INIT_SET(my_type_init_set), SET(my_type_set), INIT_MOVE(my_type_init_move), CMP(my_type_cmp), HASH(my_type_hash), OUT_STR(my_type_out_str), IN_STR(my_type_in_str))
// Let's define a Red Black Tree over this structure
RBTREE_DEF(my_type, my_type_t, MY_TYPE_OPLIST)
RBTREE_DEF(rbtree_my_type, my_type_t, MY_TYPE_OPLIST)
int main(int argc, const char *argv[])
{
+183 -178
View File
@@ -38,9 +38,9 @@
#define RBTREE_DEF(name, ...) \
M_IF_NARGS_EQ1(__VA_ARGS__) \
(RBTREEI_DEF2(name, __VA_ARGS__, M_DEFAULT_OPLIST, \
M_C3(rbtree_, name, _t), struct M_C3(rbtree_node_, name, _s), M_C3(rbtree_it_, name, _t)), \
M_C(name, _t), struct M_C(name, _node_s), M_C(name, _it_t)), \
RBTREEI_DEF2(name, __VA_ARGS__ , \
M_C3(rbtree_, name, _t), struct M_C3(rbtree_node_, name, _s), M_C3(rbtree_it_, name, _t)))
M_C(name, _t), struct M_C(name, _node_s), M_C(name, _it_t)))
/* Define the oplist of a rbtree of type.
USAGE: RBTREE_OPLIST(name [, oplist_of_the_type]) */
@@ -53,36 +53,36 @@
/********************************** INTERNAL ************************************/
#define RBTREEI_OPLIST(name, oplist) \
(INIT(M_C3(rbtree_, name, _init)), \
INIT_SET(M_C3(rbtree_, name, _init_set)), \
SET(M_C3(rbtree_, name, _set)), \
CLEAR(M_C3(rbtree_, name, _clear)), \
INIT_MOVE(M_C3(rbtree_, name, _init_move)), \
MOVE(M_C3(rbtree_, name, _move)), \
SWAP(M_C3(rbtree_, name, _swap)), \
TYPE(M_C3(rbtree_,name,_t)), \
SUBTYPE(M_C3(rbtree_type_,name,_t)), \
IT_TYPE(M_C3(rbtree_it_,name,_t)), \
IT_FIRST(M_C3(rbtree_,name,_it)), \
IT_SET(M_C3(rbtree_,name,_it_set)), \
IT_LAST(M_C3(rbtree_,name,_it_last)), \
IT_END(M_C3(rbtree_,name,_it_end)), \
IT_END_P(M_C3(rbtree_,name,_end_p)), \
IT_LAST_P(M_C3(rbtree_,name,_last_p)), \
IT_EQUAL_P(M_C3(rbtree_,name,_it_equal_p)), \
IT_NEXT(M_C3(rbtree_,name,_next)), \
IT_REF(M_C3(rbtree_,name,_ref)), \
IT_CREF(M_C3(rbtree_,name,_cref)), \
CLEAN(M_C3(rbtree_,name,_clean)), \
PUSH(M_C3(rbtree_,name,_push)), \
POP(M_C3(rbtree_,name,_pop)) \
GET_MIN(M_C3(rbtree_,name,_min)), \
GET_MAX(M_C3(rbtree_,name,_max)), \
M_IF_METHOD(GET_STR, oplist)(GET_STR(M_C3(rbtree_, name, _get_str)),), \
M_IF_METHOD(OUT_STR, oplist)(OUT_STR(M_C3(rbtree_, name, _out_str)),), \
M_IF_METHOD(IN_STR, oplist)(IN_STR(M_C3(rbtree_, name, _in_str)),), \
M_IF_METHOD(EQUAL, oplist)(EQUAL(M_C3(rbtree_, name, _equal_p)),), \
M_IF_METHOD(HASH, oplist)(HASH(M_C3(rbtree_, name, _hash)),) \
(INIT(M_C(name, _init)), \
INIT_SET(M_C(name, _init_set)), \
SET(M_C(name, _set)), \
CLEAR(M_C(name, _clear)), \
INIT_MOVE(M_C(name, _init_move)), \
MOVE(M_C(name, _move)), \
SWAP(M_C(name, _swap)), \
TYPE(M_C(name,_t)), \
SUBTYPE(M_C(name, _type_t)), \
IT_TYPE(M_C(name, _it_t)), \
IT_FIRST(M_C(name,_it)), \
IT_SET(M_C(name,_it_set)), \
IT_LAST(M_C(name,_it_last)), \
IT_END(M_C(name,_it_end)), \
IT_END_P(M_C(name,_end_p)), \
IT_LAST_P(M_C(name,_last_p)), \
IT_EQUAL_P(M_C(name,_it_equal_p)), \
IT_NEXT(M_C(name,_next)), \
IT_REF(M_C(name,_ref)), \
IT_CREF(M_C(name,_cref)), \
CLEAN(M_C(name,_clean)), \
PUSH(M_C(name,_push)), \
POP(M_C(name,_pop)) \
GET_MIN(M_C(name,_min)), \
GET_MAX(M_C(name,_max)), \
M_IF_METHOD(GET_STR, oplist)(GET_STR(M_C(name, _get_str)),), \
M_IF_METHOD(OUT_STR, oplist)(OUT_STR(M_C(name, _out_str)),), \
M_IF_METHOD(IN_STR, oplist)(IN_STR(M_C(name, _in_str)),), \
M_IF_METHOD(EQUAL, oplist)(EQUAL(M_C(name, _equal_p)),), \
M_IF_METHOD(HASH, oplist)(HASH(M_C(name, _hash)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
@@ -107,18 +107,20 @@ typedef enum {
} rbtreei_color_e;
// General contact of a tree
#define RBTREEI_CONTRACT(tree) \
assert ((tree) != NULL); \
assert ((tree)->node == NULL || RBTREEI_IS_BLACK((tree)->node)); \
assert ((tree)->size != 0 || (tree)->node == NULL); \
#define RBTREEI_CONTRACT(tree) do { \
assert ((tree) != NULL); \
assert ((tree)->node == NULL || RBTREEI_IS_BLACK((tree)->node)); \
assert ((tree)->size != 0 || (tree)->node == NULL); \
} while (0)
// Contract of a node (doesn't check for equal depth in black)
#define RBTREEI_CONTRACT_NODE(node) \
assert((node) != NULL); \
assert(RBTREEI_IS_BLACK(node) || RBTREEI_IS_RED(node)); \
assert(RBTREEI_IS_BLACK(node) \
|| (((node)->child[0] == NULL || RBTREEI_IS_BLACK(node->child[0])) \
&& ((node)->child[1] == NULL || RBTREEI_IS_BLACK(node->child[1]))))
#define RBTREEI_CONTRACT_NODE(node) do { \
assert((node) != NULL); \
assert(RBTREEI_IS_BLACK(node) || RBTREEI_IS_RED(node)); \
assert(RBTREEI_IS_BLACK(node) \
|| (((node)->child[0] == NULL || RBTREEI_IS_BLACK(node->child[0])) \
&& ((node)->child[1] == NULL || RBTREEI_IS_BLACK(node->child[1])))); \
} while (0)
#define RBTREEI_DEF2(name, type, oplist, tree_t, node_t, tree_it_t) \
\
@@ -128,42 +130,44 @@ typedef enum {
rbtreei_color_e color; \
}; \
\
typedef struct M_C3(rbtree_, name, _s) { \
typedef struct M_C(name, _s) { \
size_t size; \
node_t *node; \
} tree_t[1]; \
\
typedef struct { \
\
typedef struct M_C(name, _it_s) { \
node_t *stack[RBTREEI_MAX_STACK]; \
char which[RBTREEI_MAX_STACK]; \
unsigned int cpt; \
} tree_it_t[1]; \
\
typedef type M_C3(rbtree_type_, name, _t); \
typedef type M_C(name, _type_t); \
\
M_IF_METHOD(MEMPOOL, oplist)( \
MEMPOOL_DEF(M_C(mempool_rbtree_,name), node_t) \
M_GET_MEMPOOL_LINKAGE oplist M_C3(mempool_rbtree_, name, _t) M_GET_MEMPOOL oplist; \
static inline node_t *M_C3(rbtreei_,name,_new)(void) { \
return M_C3(mempool_rbtree_, name, _alloc)(M_GET_MEMPOOL oplist); \
MEMPOOL_DEF(M_C(name, _mempool_rbtree), node_t) \
M_GET_MEMPOOL_LINKAGE oplist M_C(name, mempool_rbtree_t) M_GET_MEMPOOL oplist; \
static inline node_t *M_C(name,_int_new)(void) { \
return M_C(name, _mempool_rbtree_alloc)(M_GET_MEMPOOL oplist); \
} \
static inline void M_C3(rbtreei_,name,_del)(node_t *ptr) { \
M_C3(mempool_rbtree_, name, _free)(M_GET_MEMPOOL oplist, ptr); \
static inline void M_C(name,_int_del)(node_t *ptr) { \
M_C(name, mempool_rbtree_free)(M_GET_MEMPOOL oplist, ptr); \
} \
RBTREEI_DEF3(name, type, oplist, tree_t, node_t, tree_it_t) \
\
, /* No mempool allocation */ \
static inline node_t *M_C3(rbtreei_,name,_new)(void) { \
\
static inline node_t *M_C(name,_int_new)(void) { \
return M_GET_NEW oplist (node_t); \
} \
static inline void M_C3(rbtreei_,name,_del)(node_t *ptr) { \
static inline void M_C(name,_int_del)(node_t *ptr) { \
M_GET_DEL oplist (ptr); \
} \
RBTREEI_DEF3(name, type, oplist, tree_t, node_t, tree_it_t) )
#define RBTREEI_DEF3(name, type, oplist, tree_t, node_t, tree_it_t) \
\
\
static inline void \
M_C3(rbtree_, name, _init)(tree_t tree) \
M_C(name, _init)(tree_t tree) \
{ \
assert (tree != NULL); \
tree->size = 0; \
@@ -172,7 +176,7 @@ typedef enum {
} \
\
static inline void \
M_C3(rbtree_, name, _clean)(tree_t tree) \
M_C(name, _clean)(tree_t tree) \
{ \
RBTREEI_CONTRACT(tree); \
node_t *stack[RBTREEI_MAX_STACK]; \
@@ -198,7 +202,7 @@ typedef enum {
} \
assert (n == stack[cpt - 1]); \
M_GET_CLEAR oplist (n->data); \
M_C3(rbtreei_,name,_del) (n); \
M_C(name,_int_del) (n); \
assert((stack[cpt-1] = NULL) == NULL); \
cpt--; \
} \
@@ -207,13 +211,13 @@ typedef enum {
} \
\
static inline void \
M_C3(rbtree_, name, _clear)(tree_t tree) \
M_C(name, _clear)(tree_t tree) \
{ \
M_C3(rbtree_, name, _clean)(tree); \
M_C(name, _clean)(tree); \
} \
\
static inline void \
M_C3(rbtree_, name, _push)(tree_t tree, type const data) \
M_C(name, _push)(tree_t tree, type const data) \
{ \
RBTREEI_CONTRACT(tree); \
node_t *tab[RBTREEI_MAX_STACK]; \
@@ -222,7 +226,7 @@ typedef enum {
node_t *n = tree->node; \
/* If nothing, create new node */ \
if (n == NULL) { \
n = M_C3(rbtreei_,name,_new)(); \
n = M_C(name,_int_new)(); \
if (M_UNLIKELY (n == NULL)) { \
M_MEMORY_FULL(sizeof (node_t)); \
return; \
@@ -261,7 +265,7 @@ typedef enum {
return; \
} \
/* Create new */ \
n = M_C3(rbtreei_,name,_new)(); \
n = M_C(name,_int_new)(); \
if (M_UNLIKELY (n == NULL) ) { \
M_MEMORY_FULL (sizeof (node_t)); \
return; \
@@ -352,14 +356,14 @@ typedef enum {
} \
\
static inline size_t \
M_C3(rbtree_, name, _size)(const tree_t tree) \
M_C(name, _size)(const tree_t tree) \
{ \
RBTREEI_CONTRACT (tree); \
return tree->size; \
} \
\
static inline void \
M_C3(rbtreei_, name, _it)(tree_it_t it, const tree_t tree, int child) \
M_C(name, _int_it)(tree_it_t it, const tree_t tree, int child) \
{ \
RBTREEI_CONTRACT (tree); \
assert (it != NULL); \
@@ -380,40 +384,41 @@ typedef enum {
} \
\
static inline void \
M_C3(rbtree_, name, _it)(tree_it_t it, const tree_t tree) \
M_C(name, _it)(tree_it_t it, const tree_t tree) \
{ \
M_C3(rbtreei_, name, _it)(it, tree, 0); \
M_C(name, _int_it)(it, tree, 0); \
} \
\
static inline void \
M_C3(rbtree_, name, _it_last)(tree_it_t it, const tree_t tree) \
M_C(name, _it_last)(tree_it_t it, const tree_t tree) \
{ \
M_C3(rbtreei_, name, _it)(it, tree, 1); \
M_C(name,_int_it)(it, tree, 1); \
} \
\
static inline void \
M_C3(rbtree_, name, _it_end)(tree_it_t it, const tree_t tree) \
M_C(name, _it_end)(tree_it_t it, const tree_t tree) \
{ \
assert (it != NULL && tree != NULL); \
RBTREEI_CONTRACT (tree); \
assert (it != NULL); \
it->cpt = 0; \
} \
\
static inline void \
M_C3(rbtree_, name, _it_set)(tree_it_t it, const tree_it_t ref) \
M_C(name, _it_set)(tree_it_t it, const tree_it_t ref) \
{ \
assert (it != NULL && ref != NULL); \
*it = *ref; \
} \
\
static inline bool \
M_C3(rbtree_, name, _end_p)(const tree_it_t it) \
M_C(name, _end_p)(const tree_it_t it) \
{ \
assert (it != NULL); \
return it->cpt == 0; \
} \
\
static inline void \
M_C3(rbtreei_, name, _next)(tree_it_t it, int child) \
M_C(name, _int_next)(tree_it_t it, int child) \
{ \
assert (it != NULL); \
assert (child == 0 || child == 1); \
@@ -444,19 +449,19 @@ typedef enum {
} \
\
static inline void \
M_C3(rbtree_, name, _next)(tree_it_t it) \
M_C(name, _next)(tree_it_t it) \
{ \
M_C3(rbtreei_, name, _next)(it, 0); \
M_C(name, _int_next)(it, 0); \
} \
\
static inline void \
M_C3(rbtree_, name, _previous)(tree_it_t it) \
M_C(name, _previous)(tree_it_t it) \
{ \
M_C3(rbtreei_, name, _next)(it, 1); \
M_C(name, _int_next)(it, 1); \
} \
\
static inline type * \
M_C3(rbtree_, name, _ref)(const tree_it_t it) \
M_C(name, _ref)(const tree_it_t it) \
{ \
assert(it != NULL && it->cpt > 0); \
/* NOTE: partially unsafe if the user modify the order of the el */ \
@@ -464,14 +469,14 @@ typedef enum {
} \
\
static inline const type * \
M_C3(rbtree_, name, _cref)(const tree_it_t it) \
M_C(name, _cref)(const tree_it_t it) \
{ \
return M_CONST_CAST(type, M_C3(rbtree_, name, _ref)(it)); \
return M_CONST_CAST(type, M_C(name, _ref)(it)); \
} \
\
static inline bool \
M_C3(rbtree_, name, _it_equal_p)(const tree_it_t it1, \
const tree_it_t it2) \
M_C(name, _it_equal_p)(const tree_it_t it1, \
const tree_it_t it2) \
{ \
return it1->cpt == it2->cpt \
&& it1->stack[it1->cpt-1] == it2->stack[it2->cpt-1]; \
@@ -479,8 +484,8 @@ typedef enum {
\
\
static inline void \
M_C3(rbtree_, name, _it_from)(tree_it_t it, \
const tree_t tree, type const data) \
M_C(name, _it_from)(tree_it_t it, \
const tree_t tree, type const data) \
{ \
RBTREEI_CONTRACT (tree); \
assert (it != NULL); \
@@ -501,7 +506,7 @@ typedef enum {
} \
\
static inline bool \
M_C3(rbtree_, name, _it_to_p)(tree_it_t it, type const data) \
M_C(name, _it_to_p)(tree_it_t it, type const data) \
{ \
assert (it != NULL); \
if (it->cpt == 0) return true; \
@@ -512,7 +517,7 @@ typedef enum {
} \
\
static inline type * \
M_C3(rbtree_, name, _min)(const tree_t tree) \
M_C(name, _min)(const tree_t tree) \
{ \
RBTREEI_CONTRACT (tree); \
node_t *n = tree->node; \
@@ -523,9 +528,9 @@ typedef enum {
} \
return &n->data; \
} \
\
\
static inline type * \
M_C3(rbtree_, name, _max)(const tree_t tree) \
M_C(name, _max)(const tree_t tree) \
{ \
RBTREEI_CONTRACT (tree); \
node_t *n = tree->node; \
@@ -536,21 +541,21 @@ typedef enum {
} \
return &n->data; \
} \
\
\
static inline const type * \
M_C3(rbtree_, name, _cmin)(const tree_t tree) \
M_C(name, _cmin)(const tree_t tree) \
{ \
return M_CONST_CAST(type, M_C3(rbtree_, name, _min)(tree)); \
return M_CONST_CAST(type, M_C(name, _min)(tree)); \
} \
\
\
static inline const type * \
M_C3(rbtree_, name, _cmax)(const tree_t tree) \
M_C(name, _cmax)(const tree_t tree) \
{ \
return M_CONST_CAST(type, M_C3(rbtree_, name, _max)(tree)); \
return M_CONST_CAST(type, M_C(name, _max)(tree)); \
} \
\
\
static inline type * \
M_C3(rbtree_, name, _get)(const tree_t tree, type const data) \
M_C(name, _get)(const tree_t tree, type const data) \
{ \
RBTREEI_CONTRACT (tree); \
node_t *n = tree->node; \
@@ -569,49 +574,49 @@ typedef enum {
} \
\
static inline const type * \
M_C3(rbtree_, name, _cget)(const tree_t tree, type const data) \
M_C(name, _cget)(const tree_t tree, type const data) \
{ \
return M_CONST_CAST(type, M_C3(rbtree_, name, _get)(tree, data)); \
return M_CONST_CAST(type, M_C(name, _get)(tree, data)); \
} \
\
\
static inline node_t * \
M_C3(rbtreei_,name,_copyn)(const node_t *o) \
M_C(name, _int_copyn)(const node_t *o) \
{ \
if (o == NULL) return NULL; \
node_t *n = M_C3(rbtreei_,name,_new)(); \
node_t *n = M_C(name,_int_new)(); \
if (M_UNLIKELY (n == NULL) ) { \
M_MEMORY_FULL (sizeof (node_t)); \
return NULL; \
} \
M_GET_INIT_SET oplist (n->data, o->data); \
n->child[0] = M_C3(rbtreei_,name,_copyn)(o->child[0]); \
n->child[1] = M_C3(rbtreei_,name,_copyn)(o->child[1]); \
n->child[0] = M_C(name, _int_copyn)(o->child[0]); \
n->child[1] = M_C(name, _int_copyn)(o->child[1]); \
RBTREEI_COPY_COLOR (n, o); \
return n; \
} \
\
\
static inline void \
M_C3(rbtree_, name, _init_set)(tree_t tree, const tree_t ref) \
M_C(name, _init_set)(tree_t tree, const tree_t ref) \
{ \
RBTREEI_CONTRACT (ref); \
assert (tree != NULL && tree != ref); \
tree->size = ref->size; \
tree->node = M_C3(rbtreei_,name,_copyn)(ref->node); \
tree->node = M_C(name, _int_copyn)(ref->node); \
RBTREEI_CONTRACT (tree); \
} \
\
static inline void \
M_C3(rbtree_, name, _set)(tree_t tree, const tree_t ref) \
M_C(name, _set)(tree_t tree, const tree_t ref) \
{ \
RBTREEI_CONTRACT (tree); \
RBTREEI_CONTRACT (ref); \
if (tree == ref) return; \
M_C3(rbtree_,name,_clear)(tree); \
M_C3(rbtree_,name,_init_set)(tree, ref); \
M_C(name,_clear)(tree); \
M_C(name,_init_set)(tree, ref); \
} \
\
static inline void \
M_C3(rbtree_, name, _init_move)(tree_t tree, tree_t ref) \
M_C(name, _init_move)(tree_t tree, tree_t ref) \
{ \
RBTREEI_CONTRACT (ref); \
assert (tree != NULL && tree != ref); \
@@ -623,18 +628,18 @@ typedef enum {
} \
\
static inline void \
M_C3(rbtree_, name, _move)(tree_t tree, tree_t ref) \
M_C(name, _move)(tree_t tree, tree_t ref) \
{ \
RBTREEI_CONTRACT (tree); \
RBTREEI_CONTRACT (ref); \
assert (tree != ref); \
M_C3(rbtree_,name,_clear)(tree); \
M_C3(rbtree_,name,_init_move)(tree, ref); \
M_C(name,_clear)(tree); \
M_C(name,_init_move)(tree, ref); \
RBTREEI_CONTRACT (tree); \
} \
\
\
static inline void \
M_C3(rbtree_, name, _swap)(tree_t tree1, tree_t tree2) \
M_C(name, _swap)(tree_t tree1, tree_t tree2) \
{ \
RBTREEI_CONTRACT (tree1); \
RBTREEI_CONTRACT (tree2); \
@@ -649,26 +654,26 @@ typedef enum {
} \
\
static inline bool \
M_C3(rbtree_, name, _empty_p)(const tree_t tree) \
M_C(name, _empty_p)(const tree_t tree) \
{ \
RBTREEI_CONTRACT (tree); \
return tree->size == 0; \
} \
\
static inline rbtreei_color_e \
M_C3(rbtreei_, name, _get_color)(const node_t *n) \
M_C(name, _int_get_color)(const node_t *n) \
{ \
return (n == NULL) ? RBTREE_BLACK : n->color; \
} \
\
static inline void \
M_C3(rbtreei_, name, _set_color)(node_t *n, rbtreei_color_e c) \
M_C(name, _int_set_color)(node_t *n, rbtreei_color_e c) \
{ \
if (n != NULL) n->color = c; \
} \
\
static inline node_t * \
M_C3(rbtreei_, name, _rotate)(node_t *pp, node_t *ppp, const bool right) \
M_C(name, _int_rotate)(node_t *pp, node_t *ppp, const bool right) \
{ \
assert (pp != NULL && ppp != NULL); \
bool left = !right; \
@@ -684,16 +689,16 @@ typedef enum {
\
M_IF_DEBUG( \
static size_t \
M_C3(rbtreei_,name,_depth)(const node_t *n) \
M_C(name, _int_depth)(const node_t *n) \
{ \
if (n == NULL) return 1; \
return RBTREEI_IS_BLACK (n) \
+ M_C3(rbtreei_,name,_depth)(n->child[0]); \
+ M_C(name, _int_depth)(n->child[0]); \
} \
) \
\
static inline bool \
M_C3(rbtree_, name, _pop)(type *data_ptr, tree_t tree, type const key) \
M_C(name, _pop)(type *data_ptr, tree_t tree, type const key) \
{ \
RBTREEI_CONTRACT (tree); \
node_t *tab[RBTREEI_MAX_STACK]; \
@@ -706,8 +711,8 @@ typedef enum {
tab[cpt] = n; \
while (n != NULL) { \
RBTREEI_CONTRACT_NODE (n); \
assert(M_C3(rbtreei_,name,_depth)(n->child[0]) \
== M_C3(rbtreei_,name,_depth)(n->child[1])); \
assert(M_C(name, _int_depth)(n->child[0]) \
== M_C(name, _int_depth)(n->child[1])); \
int cmp = M_GET_CMP oplist (n->data, key); \
if (cmp == 0) { \
break; \
@@ -737,8 +742,8 @@ typedef enum {
while (v != NULL) { \
/* Always left node */ \
RBTREEI_CONTRACT_NODE (v); \
assert(M_C3(rbtreei_,name,_depth)(v->child[0]) \
== M_C3(rbtreei_,name,_depth)(v->child[1])); \
assert(M_C(name, _int_depth)(v->child[0]) \
== M_C(name, _int_depth)(v->child[1])); \
which[cpt++] = 0; \
v = v->child[0]; \
assert (cpt < RBTREEI_MAX_STACK); \
@@ -773,7 +778,7 @@ typedef enum {
\
/* Rebalance from child to root */ \
if (v_color == RBTREE_BLACK \
&& M_C3(rbtreei_,name,_get_color)(u) == RBTREE_BLACK) { \
&& M_C(name, _int_get_color)(u) == RBTREE_BLACK) { \
/* tab[0] is NULL, tab[1] is root, u is double black */ \
node_t *p = u, *s; \
while (cpt >= 2) { \
@@ -782,8 +787,8 @@ typedef enum {
assert (p != NULL && u == p->child[nbChild]); \
s = p->child[!nbChild]; \
/* if sibling is red, perform a rotation to move sibling up */ \
if (M_C3(rbtreei_,name,_get_color)(s) == RBTREE_RED) { \
p = M_C3(rbtreei_,name,_rotate) (p, tab[cpt-1], !nbChild); \
if (M_C(name, _int_get_color)(s) == RBTREE_RED) { \
p = M_C(name, _int_rotate) (p, tab[cpt-1], !nbChild); \
RBTREEI_SET_BLACK(p); /* was sibling */ \
tab[cpt] = p; \
which[cpt++] = nbChild; \
@@ -791,20 +796,20 @@ typedef enum {
assert (p != NULL); \
RBTREEI_SET_RED(p); \
s = p->child[!nbChild]; \
assert (M_C3(rbtreei_,name,_get_color)(s) == RBTREE_BLACK); \
assert (M_C(name, _int_get_color)(s) == RBTREE_BLACK); \
} \
assert (p != NULL && u == p->child[nbChild]); \
/* if both childreen of s are black */ \
/* perform recoloring and recur on parent if black */ \
if (s != NULL \
&& M_C3(rbtreei_,name,_get_color)(s->child[0])== RBTREE_BLACK \
&& M_C3(rbtreei_,name,_get_color)(s->child[1])== RBTREE_BLACK) { \
assert(M_C3(rbtreei_,name,_depth)(s->child[0]) == M_C3(rbtreei_,name,_depth)(s->child[1])); \
&& M_C(name, _int_get_color)(s->child[0])== RBTREE_BLACK \
&& M_C(name, _int_get_color)(s->child[1])== RBTREE_BLACK) { \
assert(M_C(name, _int_depth)(s->child[0]) == M_C(name, _int_depth)(s->child[1])); \
RBTREEI_SET_RED(s); \
if (RBTREEI_IS_RED(p)) { \
RBTREEI_SET_BLACK(p); \
RBTREEI_CONTRACT_NODE(p); \
assert(M_C3(rbtreei_,name,_depth)(p->child[0]) == M_C3(rbtreei_,name,_depth)(p->child[1])); \
assert(M_C(name, _int_depth)(p->child[0]) == M_C(name, _int_depth)(p->child[1])); \
break; \
} \
u = p; \
@@ -812,44 +817,44 @@ typedef enum {
assert (s != NULL); \
/* at least one child of 's' is red */ \
/* perform rotation(s) */ \
bool childIsRight = M_C3(rbtreei_,name,_get_color)(s->child[1])== RBTREE_RED; \
bool childIsRight = M_C(name, _int_get_color)(s->child[1])== RBTREE_RED; \
rbtreei_color_e p_color = p->color; \
if (childIsRight != nbChild) { \
/* left-left or right-right case */ \
p = M_C3(rbtreei_,name,_rotate) (p, tab[cpt-1], childIsRight); \
p = M_C(name, _int_rotate) (p, tab[cpt-1], childIsRight); \
} else { \
s = M_C3(rbtreei_,name,_rotate) (s, p, childIsRight); \
p = M_C3(rbtreei_,name,_rotate) (p, tab[cpt-1], !nbChild); \
s = M_C(name, _int_rotate) (s, p, childIsRight); \
p = M_C(name, _int_rotate) (p, tab[cpt-1], !nbChild); \
} \
p->color = p_color; \
assert(p->child[0] != NULL && p->child[1] != NULL); \
RBTREEI_SET_BLACK(p->child[0]); \
RBTREEI_SET_BLACK(p->child[1]); \
RBTREEI_CONTRACT_NODE(p); \
assert(M_C3(rbtreei_,name,_depth)(p->child[0]) == M_C3(rbtreei_,name,_depth)(p->child[1])); \
assert(M_C(name, _int_depth)(p->child[0]) == M_C(name, _int_depth)(p->child[1])); \
break; \
} \
} /* while */ \
if (cpt == 1 /* root has been reached? */ ) { \
M_C3(rbtreei_,name,_set_color)(p, RBTREE_BLACK); \
M_C(name, _int_set_color)(p, RBTREE_BLACK); \
assert (tree->node == p); \
} \
} else { \
M_C3(rbtreei_,name,_set_color)(u, RBTREE_BLACK); \
M_C(name, _int_set_color)(u, RBTREE_BLACK); \
} \
assert (tree->node == NULL || RBTREEI_IS_BLACK(tree->node)); \
/* delete it */ \
if (data_ptr != NULL) \
M_GET_SET oplist (*data_ptr, n->data); \
M_GET_CLEAR oplist (n->data); \
M_C3(rbtreei_,name,_del) (n); \
M_C(name,_int_del) (n); \
tree->size --; \
RBTREEI_CONTRACT (tree); \
return true; \
} \
\
M_IF_METHOD(EQUAL, oplist)( \
static inline bool M_C3(rbtree_,name,_equal_p)(const tree_t t1, const tree_t t2) { \
static inline bool M_C(name,_equal_p)(const tree_t t1, const tree_t t2) { \
RBTREEI_CONTRACT(t1); \
RBTREEI_CONTRACT(t2); \
if (t1->size != t2->size) return false; \
@@ -859,40 +864,40 @@ typedef enum {
structuraly different but functionnaly equal (you get this by \
constructing the tree in a different way). We have to \
compare the ordered value within the tree. */ \
M_C3(rbtree_, name, _it)(it1, t1); \
M_C3(rbtree_, name, _it)(it2, t2); \
while (!M_C3(rbtree_, name, _end_p)(it1) \
&& !M_C3(rbtree_, name, _end_p)(it2)) { \
const type *ref1 = M_C3(rbtree_, name, _cref)(it1); \
const type *ref2 = M_C3(rbtree_, name, _cref)(it2); \
M_C(name, _it)(it1, t1); \
M_C(name, _it)(it2, t2); \
while (!M_C(name, _end_p)(it1) \
&& !M_C(name, _end_p)(it2)) { \
const type *ref1 = M_C(name, _cref)(it1); \
const type *ref2 = M_C(name, _cref)(it2); \
if (M_GET_EQUAL oplist (*ref1, *ref2) == false) \
return false; \
M_C3(rbtree_, name, _next)(it1); \
M_C3(rbtree_, name, _next)(it2); \
M_C(name, _next)(it1); \
M_C(name, _next)(it2); \
} \
return M_C3(rbtree_, name, _end_p)(it1) \
&& M_C3(rbtree_, name, _end_p)(it2); \
return M_C(name, _end_p)(it1) \
&& M_C(name, _end_p)(it2); \
} \
, /* NO EQUAL METHOD */ ) \
\
\
M_IF_METHOD(HASH, oplist)( \
static inline size_t M_C3(rbtree_,name,_hash)(const tree_t t1) { \
static inline size_t M_C(name,_hash)(const tree_t t1) { \
RBTREEI_CONTRACT(t1); \
M_HASH_DECL(hash); \
/* NOTE: We can't compute the hash directly for the same reason \
than for EQUAL operator. */ \
tree_it_t it1; \
M_C3(rbtree_, name, _it)(it1, t1); \
while (!M_C3(rbtree_, name, _end_p)(it1)) { \
const type *ref1 = M_C3(rbtree_, name, _cref)(it1); \
M_C(name, _it)(it1, t1); \
while (!M_C(name, _end_p)(it1)) { \
const type *ref1 = M_C(name, _cref)(it1); \
M_HASH_UP(hash, M_GET_HASH oplist (*ref1)); \
} \
return hash; \
} \
, /* NO HASH METHOD */ ) \
\
\
M_IF_METHOD(GET_STR, oplist)( \
static inline void M_C3(rbtree_,name,_get_str)(string_t str, \
static inline void M_C(name, _get_str)(string_t str, \
const tree_t t1, bool append) { \
RBTREEI_CONTRACT(t1); \
assert(str != NULL); \
@@ -900,48 +905,48 @@ typedef enum {
/* NOTE: The print is really naive, and not really efficient */ \
bool commaToPrint = false; \
tree_it_t it1; \
M_C3(rbtree_, name, _it)(it1, t1); \
while (!M_C3(rbtree_, name, _end_p)(it1)) { \
M_C(name, _it)(it1, t1); \
while (!M_C(name, _end_p)(it1)) { \
if (commaToPrint) \
string_push_back (str, M_GET_SEPARATOR oplist); \
commaToPrint = true; \
const type *ref1 = M_C3(rbtree_, name, _cref)(it1); \
const type *ref1 = M_C(name, _cref)(it1); \
M_GET_GET_STR oplist(str, *ref1, true); \
M_C3(rbtree_, name, _next)(it1); \
M_C(name, _next)(it1); \
} \
string_push_back (str, ']'); \
} \
, /* NO GET_STR */ ) \
\
\
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_C3(rbtree_, name, _out_str)(FILE *file, tree_t rbtree) \
M_C(name, _out_str)(FILE *file, tree_t rbtree) \
{ \
RBTREEI_CONTRACT(rbtree); \
assert (file != NULL); \
fprintf (file, "["); \
fputc ('[', file); \
tree_it_t it; \
bool commaToPrint = false; \
for (M_C3(rbtree_, name, _it)(it, rbtree) ; \
!M_C3(rbtree_, name, _end_p)(it); \
M_C3(rbtree_, name, _next)(it)){ \
for (M_C(name, _it)(it, rbtree) ; \
!M_C(name, _end_p)(it); \
M_C(name, _next)(it)){ \
if (commaToPrint) \
fputc (M_GET_SEPARATOR oplist, file); \
commaToPrint = true; \
const type *item = M_C3(rbtree_, name, _cref)(it); \
const type *item = M_C(name, _cref)(it); \
M_GET_OUT_STR oplist (file, *item); \
} \
fprintf (file, "]"); \
fputc (']', file); \
} \
, /* no out_str */ ) \
\
M_IF_METHOD(IN_STR, oplist)( \
static inline bool \
M_C3(rbtree_, name, _in_str)(tree_t rbtree, FILE *file) \
M_C(name, _in_str)(tree_t rbtree, FILE *file) \
{ \
RBTREEI_CONTRACT(rbtree); \
assert (file != NULL); \
M_C3(rbtree_, name,_clean)(rbtree); \
M_C(name,_clean)(rbtree); \
char c = fgetc(file); \
if (c != '[') return false; \
c = fgetc(file); \
@@ -953,13 +958,13 @@ typedef enum {
bool b = M_GET_IN_STR oplist (item, file); \
c = fgetc(file); \
if (!b) break; \
M_C3(rbtree_, name, _push)(rbtree, item); \
M_C(name, _push)(rbtree, item); \
} while (c == M_GET_SEPARATOR oplist && !feof(file) && !ferror(file)); \
M_GET_CLEAR oplist (item); \
return c == ']'; \
} \
, /* no in_str */ ) \
\
\
// TODO: specialized _sort shall do nothing, but shall check the requested order. How ?
+4 -4
View File
@@ -42,12 +42,12 @@ static void uint_get_str(string_t str, unsigned int u, bool append)
#include "coverage.h"
START_COVERAGE
RBTREE_DEF(uint, unsigned int, M_OPEXTEND(M_DEFAULT_OPLIST, IN_STR(uint_in_str M_IPTR), OUT_STR(uint_out_str), GET_STR(uint_get_str)) )
RBTREE_DEF(float, float)
RBTREE_DEF(rbtree_uint, unsigned int, M_OPEXTEND(M_DEFAULT_OPLIST, IN_STR(uint_in_str M_IPTR), OUT_STR(uint_out_str), GET_STR(uint_get_str)) )
RBTREE_DEF(rbtree_float, float)
END_COVERAGE
#define UINT_OPLIST RBTREE_OPLIST(uint)
#define FLOAT_OP RBTREE_OPLIST(float)
#define UINT_OPLIST RBTREE_OPLIST(rbtree_uint)
#define FLOAT_OP RBTREE_OPLIST(rbtree_float)
static void test_uint(void)
{