Add more functions for TREE
This commit is contained in:
1 parent
c12d0a3f23
commit
96a0639a8a
1 file changed
+58
-2
@@ -61,7 +61,6 @@
|
|||||||
# define M_TR33_NODE_CONTRACT(node, tree) do { \
|
# define M_TR33_NODE_CONTRACT(node, tree) do { \
|
||||||
M_ASSERT( (tree)->size > 0); \
|
M_ASSERT( (tree)->size > 0); \
|
||||||
M_ASSERT( (node)->parent != M_TR33_NO_NODE); \
|
M_ASSERT( (node)->parent != M_TR33_NO_NODE); \
|
||||||
M_ASSERT( (node) >= &(tree)->tab[0] && (node) < &(tree)->tab[(tree)->capacity] ); \
|
|
||||||
M_ASSERT( (node)->parent == M_TR33_ROOT_NODE || (node)->parent >= 0); \
|
M_ASSERT( (node)->parent == M_TR33_ROOT_NODE || (node)->parent >= 0); \
|
||||||
M_ASSERT( (node)->parent != M_TR33_ROOT_NODE || (node) == &(tree)->tab[(tree)->root_index] ); \
|
M_ASSERT( (node)->parent != M_TR33_ROOT_NODE || (node) == &(tree)->tab[(tree)->root_index] ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -70,6 +69,7 @@
|
|||||||
M_ASSERT( (tree)->size >= 0 && (tree)->size <= (tree)->capacity); \
|
M_ASSERT( (tree)->size >= 0 && (tree)->size <= (tree)->capacity); \
|
||||||
M_ASSERT( (tree)->capacity >= 0 ); \
|
M_ASSERT( (tree)->capacity >= 0 ); \
|
||||||
M_ASSERT( (tree)->capacity == 0 || (tree)->tab != NULL); \
|
M_ASSERT( (tree)->capacity == 0 || (tree)->tab != NULL); \
|
||||||
|
M_ASSERT( (tree)->allow_realloc == 1 || (tree)->allow_realloc == 32 ); \
|
||||||
M_ASSERT( (tree)->free_index >= M_TR33_NO_NODE && (tree)->free_index < (tree)->capacity); \
|
M_ASSERT( (tree)->free_index >= M_TR33_NO_NODE && (tree)->free_index < (tree)->capacity); \
|
||||||
M_ASSERT( (tree)->root_index >= M_TR33_NO_NODE && (tree)->root_index < (tree)->capacity); \
|
M_ASSERT( (tree)->root_index >= M_TR33_NO_NODE && (tree)->root_index < (tree)->capacity); \
|
||||||
M_ASSERT( (tree)->free_index < 0 || (tree)->tab[(tree)->free_index].parent == M_TR33_NO_NODE); \
|
M_ASSERT( (tree)->free_index < 0 || (tree)->tab[(tree)->free_index].parent == M_TR33_NO_NODE); \
|
||||||
@@ -81,6 +81,7 @@
|
|||||||
M_TR33_CONTRACT( (it).tree); \
|
M_TR33_CONTRACT( (it).tree); \
|
||||||
M_ASSERT(valid == false || (it).index >= 0); \
|
M_ASSERT(valid == false || (it).index >= 0); \
|
||||||
if ((it).index >= 0) { \
|
if ((it).index >= 0) { \
|
||||||
|
M_ASSERT( (it).index < (it).tree->capacity); \
|
||||||
M_TR33_NODE_CONTRACT(&(it).tree->tab[(it).index], (it).tree); \
|
M_TR33_NODE_CONTRACT(&(it).tree->tab[(it).index], (it).tree); \
|
||||||
/* All child of this node have the parent field correctly set */ \
|
/* All child of this node have the parent field correctly set */ \
|
||||||
m_tr33_index_t itj = (it).tree->tab[(it).index].child; \
|
m_tr33_index_t itj = (it).tree->tab[(it).index].child; \
|
||||||
@@ -158,6 +159,7 @@ typedef int32_t m_tr33_index_t;
|
|||||||
+ capacity is the allocated size of the array 'tab' \
|
+ capacity is the allocated size of the array 'tab' \
|
||||||
+ root_index is the index of the "first" root in the tree. \
|
+ root_index is the index of the "first" root in the tree. \
|
||||||
+ free_index is the list of free nodes in the array 'tab'. \
|
+ free_index is the list of free nodes in the array 'tab'. \
|
||||||
|
+ allow_realloc is a bool encoded as true=1 and false=32 \
|
||||||
+ tab is a pointer to the allocated nodes. \
|
+ tab is a pointer to the allocated nodes. \
|
||||||
*/ \
|
*/ \
|
||||||
typedef struct M_C(name, _s) { \
|
typedef struct M_C(name, _s) { \
|
||||||
@@ -165,6 +167,7 @@ typedef int32_t m_tr33_index_t;
|
|||||||
m_tr33_index_t capacity; \
|
m_tr33_index_t capacity; \
|
||||||
m_tr33_index_t root_index; \
|
m_tr33_index_t root_index; \
|
||||||
m_tr33_index_t free_index; \
|
m_tr33_index_t free_index; \
|
||||||
|
unsigned allow_realloc; \
|
||||||
M_C(name, _node_ct) *tab; \
|
M_C(name, _node_ct) *tab; \
|
||||||
} tree_t[1]; \
|
} tree_t[1]; \
|
||||||
\
|
\
|
||||||
@@ -189,6 +192,7 @@ typedef int32_t m_tr33_index_t;
|
|||||||
tree->capacity = 0; \
|
tree->capacity = 0; \
|
||||||
tree->root_index = M_TR33_NO_NODE; \
|
tree->root_index = M_TR33_NO_NODE; \
|
||||||
tree->free_index = M_TR33_NO_NODE; \
|
tree->free_index = M_TR33_NO_NODE; \
|
||||||
|
tree->allow_realloc = true; \
|
||||||
tree->tab = NULL; \
|
tree->tab = NULL; \
|
||||||
M_TR33_CONTRACT(tree); \
|
M_TR33_CONTRACT(tree); \
|
||||||
} \
|
} \
|
||||||
@@ -234,12 +238,54 @@ typedef int32_t m_tr33_index_t;
|
|||||||
return M_ASSIGN_CAST(size_t, tree->size); \
|
return M_ASSIGN_CAST(size_t, tree->size); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
static inline void \
|
||||||
|
M_C(name, _reserve)(tree_t tree, size_t alloc) { \
|
||||||
|
M_TR33_CONTRACT(tree); \
|
||||||
|
/* Nothing to do if the request is lower than the current capacity. */ \
|
||||||
|
if (alloc <= tree->capacity) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
/* Realloc the array */ \
|
||||||
|
if (M_UNLIKELY (alloc >= INT32_MAX)) { \
|
||||||
|
M_MEMORY_FULL(sizeof (struct M_C(name, _node_s)) * alloc); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
struct M_C(name, _node_s) *ptr = \
|
||||||
|
M_CALL_REALLOC(oplist, struct M_C(name, _node_s), tree->tab, alloc); \
|
||||||
|
if (M_UNLIKELY (ptr == NULL) ) { \
|
||||||
|
M_MEMORY_FULL(sizeof (struct M_C(name, _node_s)) * alloc); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
/* Construct the list of free node in the extra allocated pool */ \
|
||||||
|
for(size_t i = tree->size ; i < alloc; i++) { \
|
||||||
|
ptr[i].parent = M_TR33_NO_NODE; \
|
||||||
|
ptr[i].left = M_TR33_NO_NODE; \
|
||||||
|
ptr[i].right = M_TR33_NO_NODE; \
|
||||||
|
ptr[i].child = i + 1; \
|
||||||
|
} \
|
||||||
|
/* The last node has no child in the free node list */ \
|
||||||
|
ptr[alloc-1].child = M_TR33_NO_NODE; \
|
||||||
|
/* Save the free list state in the tree */ \
|
||||||
|
tree->tab = ptr; \
|
||||||
|
tree->capacity = alloc; \
|
||||||
|
M_TR33_CONTRACT(tree); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline void \
|
||||||
|
M_C(name, _lock)(tree_t tree, bool lock) { \
|
||||||
|
M_TR33_CONTRACT(tree); \
|
||||||
|
tree->allow_realloc = lock ? 32 : 1; \
|
||||||
|
M_TR33_CONTRACT(tree); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
static inline m_tr33_index_t \
|
static inline m_tr33_index_t \
|
||||||
M_C3(m_tr33_, name, _alloc_node)(tree_t tree) { \
|
M_C3(m_tr33_, name, _alloc_node)(tree_t tree) { \
|
||||||
m_tr33_index_t ret = tree->free_index; \
|
m_tr33_index_t ret = tree->free_index; \
|
||||||
if (M_UNLIKELY(ret < 0)) { \
|
if (M_UNLIKELY(ret < 0)) { \
|
||||||
/* No more enough space: realloc the array */ \
|
/* No more enough space: realloc the array */ \
|
||||||
const size_t alloc = M_CALL_INC_ALLOC(oplist, tree->size); \
|
size_t alloc = M_CALL_INC_ALLOC(oplist, tree->size); \
|
||||||
|
/* Take into account if realloc is allowed */ \
|
||||||
|
alloc <<= tree->allow_realloc; \
|
||||||
if (M_UNLIKELY (alloc >= INT32_MAX)) { \
|
if (M_UNLIKELY (alloc >= INT32_MAX)) { \
|
||||||
M_MEMORY_FULL(sizeof (struct M_C(name, _node_s)) * alloc); \
|
M_MEMORY_FULL(sizeof (struct M_C(name, _node_s)) * alloc); \
|
||||||
return M_TR33_NO_NODE; \
|
return M_TR33_NO_NODE; \
|
||||||
@@ -309,6 +355,16 @@ typedef int32_t m_tr33_index_t;
|
|||||||
return it; \
|
return it; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
static inline it_t \
|
||||||
|
M_C(name, _it_end)(tree_t tree) { \
|
||||||
|
M_TR33_CONTRACT(tree); \
|
||||||
|
it_t it; \
|
||||||
|
it.tree = tree; \
|
||||||
|
it.index = M_TR33_NO_NODE; \
|
||||||
|
M_TR33_IT_CONTRACT(it, false); \
|
||||||
|
return it; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
static inline bool \
|
static inline bool \
|
||||||
M_C(name, _end_p)(it_t it) { \
|
M_C(name, _end_p)(it_t it) { \
|
||||||
M_TR33_IT_CONTRACT(it, false); \
|
M_TR33_IT_CONTRACT(it, false); \
|
||||||
|
|||||||
Reference in new issue
Block a user