|
Simple data structures / objects in plain C Snapshot
|
a tree. tree. Each node has variable number of child nodes, the node is embeddable (like ring list). This tree is especially suited for parse trees. More...
Classes | |
| struct | tagTREENODE |
Defines | |
| #define | TREE_FOREACH_CHILD(current, node) |
| #define | TREE_FOREACH_CHILD_REVERSE(current, node) |
| #define | TREE_FOREACH_PREORDER(current, tree) |
| #define | TREE_FOREACH_PREORDER_END |
| #define | TREE_FOREACH_POSTORDER(current, tree) |
| #define | TREE_FOREACH_POSTORDER_END |
Typedefs | |
| typedef struct tagTREENODE | TREENODE |
| typedef int(* | TREE_VISITOR )(TREENODE *entry, void *context) |
| typedef void(* | TREE_VISITOR_V )(TREENODE *entry, void *context) |
| typedef int(* | TREE_VISITOR_EXT_V )(TREENODE *entry, TREE_VISIT_EVENT visit, void *context) |
Enumerations | |
| enum | TREE_INSERT_MODE { TREE_INSERT_FIRST, TREE_INSERT_LAST } |
| enum | TREE_VISIT_EVENT { TREE_PREORDER, TREE_POSTORDER } |
Functions | |
| M_INLINE void | TREE_init_root (TREENODE *tree) |
| M_INLINE TREENODE * | TREE_parent (TREENODE *node) |
| M_INLINE TREENODE * | TREE_left_sibling (TREENODE *node) |
| M_INLINE TREENODE * | TREE_right_sibling (TREENODE *node) |
| M_INLINE TREENODE * | TREE_leftmost_sibling (TREENODE *node) |
| M_INLINE TREENODE * | TREE_rightmost_sibling (TREENODE *node) |
| M_INLINE TREENODE * | TREE_first_child (TREENODE *node) |
| M_INLINE TREENODE * | TREE_last_child (TREENODE *node) |
| M_INLINE int | TREE_insert_right_sibling (TREENODE *current, TREENODE *newnode, int node_is_leaf) |
| M_INLINE int | TREE_insert_left_sibling (TREENODE *current, TREENODE *newnode, int node_is_leaf) |
| M_INLINE void | TREE_insert_child (TREENODE *parent, TREENODE *newnode, TREE_INSERT_MODE mode, int node_is_leaf) |
| M_INLINE void | TREE_merge_childs (TREENODE *parent, TREE_INSERT_MODE mode, TREENODE *newnode) |
| M_INLINE TREENODE * | TREE_unlink_node (TREENODE *node) |
| M_INLINE size_t | TREE_count_child_nodes (TREENODE *current) |
| M_INLINE TREENODE * | TREE_preorder_next (TREENODE *current) |
| M_INLINE void | TREE_foreach_child (TREENODE *lst, TREE_VISITOR_V eval, void *context) |
| iterate over all elements of a list of child nodes, callback is invoked for either element of the list. list is traversed from first element to the last element. | |
| M_INLINE void | TREE_foreach_child_reverse (TREENODE *lst, TREE_VISITOR_V eval, void *context) |
| M_INLINE TREENODE * | TREE_findif_child (TREENODE *tree, TREE_VISITOR eval, void *context, int32_t *retval) |
| find an element within the list of child nodes. callback is invoked for each element of the list, in forward direction from first element to last element; when the callback returns non zero value the iteration stops as we have found what we searched for. | |
| M_INLINE TREENODE * | TREE_findif_child_reverse (TREENODE *tree, TREE_VISITOR eval, void *context, int32_t *retval) |
| M_INLINE TREENODE * | TREE_postorder_next (TREENODE *current, TREENODE *prev) |
| M_INLINE void | TREE_foreach_preorder (TREENODE *node, TREE_VISITOR_V visit, void *context) |
| M_INLINE TREENODE * | TREE_find_preorder (TREENODE *node, TREE_VISITOR visit, void *context) |
| M_INLINE void | TREE_foreach_postorder (TREENODE *node, TREE_VISITOR_V visit, void *context) |
| M_INLINE TREENODE * | TREE_find_postorder (TREENODE *node, TREE_VISITOR visit, void *context) |
| M_INLINE int | TREE_check_tree (TREENODE *root) |
| check tree for consistency errors | |
a tree. tree. Each node has variable number of child nodes, the node is embeddable (like ring list). This tree is especially suited for parse trees.
| #define TREE_FOREACH_CHILD | ( | current, | |
| node | |||
| ) |
for((current) = TREE_first_child(node); \ (current); \ (current) = TREE_right_sibling(current))
| #define TREE_FOREACH_CHILD_REVERSE | ( | current, | |
| node | |||
| ) |
for((current) = TREE_last_child(node); \ (current); \ (current) = TREE_left_sibling(current))
| #define TREE_FOREACH_POSTORDER | ( | current, | |
| tree | |||
| ) |
{\
TREENODE *TREE_nextnode##next,*TREE_nextnode##prev;\
TREE_nextnode##prev = 0; \
current = TREE_postorder_next((tree),TREE_nextnode##prev);\
if (current)\
for( TREE_nextnode##next = TREE_postorder_next(current,TREE_nextnode##prev);\
(current) && current != (tree); \
TREE_nextnode##prev = (current), \
(current) = TREE_nextnode##next, \
TREE_nextnode##next = TREE_postorder_next(current,TREE_nextnode##prev)) {
| #define TREE_FOREACH_PREORDER | ( | current, | |
| tree | |||
| ) |
{\
TREENODE *TREE_nextnode##next;\
current = TREE_preorder_next((tree));\
if (current)\
for( TREE_nextnode##next = TREE_preorder_next(current);\
(current) && current != (tree); \
(current) = TREE_nextnode##next, TREE_nextnode##next = TREE_preorder_next(current)) {
| typedef int(* TREE_VISITOR)(TREENODE *entry, void *context) |
| typedef int(* TREE_VISITOR_EXT_V)(TREENODE *entry, TREE_VISIT_EVENT visit, void *context) |
| typedef void(* TREE_VISITOR_V)(TREENODE *entry, void *context) |
| typedef struct tagTREENODE TREENODE |
| enum TREE_INSERT_MODE |
| enum TREE_VISIT_EVENT |
| M_INLINE int TREE_check_tree | ( | TREENODE * | root | ) |
check tree for consistency errors
Definition at line 715 of file tree.h.
{
TREENODE *firstch = root->nextlevel_first;
#ifdef TREE_NEXTLEVEL_LAST
TREENODE *lastch = root->nextlevel_last;
#endif
#ifndef TREE_NEXTLEVEL_LEFT
TREENODE *slow,*fast, *next;
#endif
if (!firstch
#ifdef TREE_NEXTLEVEL_LAST
|| !lastch
#endif
) {
#ifdef TREE_NEXTLEVEL_LAST
if (firstch || lastch) {
return 0;
}
#endif
return 1;
}
if (firstch->parent != root) {
return 0;
}
#ifdef TREE_NEXTLEVEL_LEFT
for(;;firstch = firstch->right) {
TREENODE *next;
if (!firstch) {
return 0;
}
if (!TREE_check_tree(firstch)) {
return 0;
}
next = firstch->right;
if (!next) {
#ifdef TREE_NEXTLEVEL_LAST
if (lastch != firstch) {
return 0;
}
#endif
break;
}
if (next->left != firstch) {
return 0;
}
}
#else
slow=fast=firstch;
while(1) {
if (!TREE_check_tree(slow)) {
return 0;
}
next = fast->right;
if (!next) {
break;
}
fast = next;
if (fast == slow) {
return 0;
}
next = fast->right;
if (!next) {
break;
}
fast = next;
if (fast == slow) {
return 0;
}
slow = slow->right;
}
#ifdef TREE_NEXTLEVEL_LAST
if (lastch != fast) {
return 0;
}
#endif
#endif
return 1;
}
| M_INLINE size_t TREE_count_child_nodes | ( | TREENODE * | current | ) |
Definition at line 385 of file tree.h.
{
size_t ret = 0;
TREENODE *c;
TREE_FOREACH_CHILD(c,current) {
ret++;
}
return ret;
}
| M_INLINE TREENODE* TREE_find_postorder | ( | TREENODE * | node, |
| TREE_VISITOR | visit, | ||
| void * | context | ||
| ) |
Definition at line 695 of file tree.h.
{
TREENODE *current;
TREE_FOREACH_POSTORDER(current,node)
if (visit(node,context)) {
return current;
}
TREE_FOREACH_POSTORDER_END
return 0;
}
| M_INLINE TREENODE* TREE_find_preorder | ( | TREENODE * | node, |
| TREE_VISITOR | visit, | ||
| void * | context | ||
| ) |
Definition at line 643 of file tree.h.
{
TREENODE *current;
TREE_FOREACH_PREORDER(current,node)
if (visit(node,context)) {
return current;
}
TREE_FOREACH_POSTORDER_END
return 0;
}
| M_INLINE TREENODE* TREE_findif_child | ( | TREENODE * | tree, |
| TREE_VISITOR | eval, | ||
| void * | context, | ||
| int32_t * | retval | ||
| ) |
find an element within the list of child nodes. callback is invoked for each element of the list, in forward direction from first element to last element; when the callback returns non zero value the iteration stops as we have found what we searched for.
| tree | (in) node in a tree (parent of enumerated childs). |
| eval | (in) callback that is called to visit each set (or cleared) bit. |
| context | (in) pointer that is passed as context on each invocation of callback. |
| retval | (out) optional - the first non zero value returned by eval callback, if NULL then ignored. |
Definition at line 499 of file tree.h.
{
int ret;
TREENODE *cur;
if (retval) {
*retval = 0;
}
if (!eval) {
return 0;
}
TREE_FOREACH_CHILD( cur, tree) {
ret = eval( cur, context );
if (ret) {
if (retval) {
*retval = ret;
}
return cur;
}
}
return 0;
}
| M_INLINE TREENODE* TREE_findif_child_reverse | ( | TREENODE * | tree, |
| TREE_VISITOR | eval, | ||
| void * | context, | ||
| int32_t * | retval | ||
| ) |
Definition at line 526 of file tree.h.
{
int ret;
TREENODE *cur;
if (retval) {
*retval = 0;
}
if (!eval) {
return 0;
}
TREE_FOREACH_CHILD_REVERSE( cur, tree) {
ret = eval( cur, context );
if (ret) {
if (retval) {
*retval = ret;
}
return cur;
}
}
return 0;
}
Definition at line 105 of file tree.h.
{
return node->nextlevel_first;
}
| M_INLINE void TREE_foreach_child | ( | TREENODE * | lst, |
| TREE_VISITOR_V | eval, | ||
| void * | context | ||
| ) |
iterate over all elements of a list of child nodes, callback is invoked for either element of the list. list is traversed from first element to the last element.
| lst | (in) node in a tree (parent of enumerated childs). |
| eval | (in) callback that is called to visit each set (or cleared) bit. |
| context | (in) pointer that is passed as context on each invocation of callback. |
| save_from_del | (in) if non zero then callback can remove the current link from the list (a bit slower); if null then not; if zero then can't remove the current link from the list. |
Definition at line 458 of file tree.h.
{
TREENODE *cur;
if (!eval) {
return;
}
TREE_FOREACH_CHILD( cur, lst) {
eval( cur, context );
}
}
| M_INLINE void TREE_foreach_child_reverse | ( | TREENODE * | lst, |
| TREE_VISITOR_V | eval, | ||
| void * | context | ||
| ) |
Definition at line 474 of file tree.h.
{
TREENODE *cur;
if (!eval) {
return;
}
TREE_FOREACH_CHILD_REVERSE( cur,lst) {
eval( cur, context );
}
}
| M_INLINE void TREE_foreach_postorder | ( | TREENODE * | node, |
| TREE_VISITOR_V | visit, | ||
| void * | context | ||
| ) |
Definition at line 668 of file tree.h.
{
TREENODE *current;
TREE_FOREACH_POSTORDER(current,node)
visit(node,context);
TREE_FOREACH_POSTORDER_END
}
| M_INLINE void TREE_foreach_preorder | ( | TREENODE * | node, |
| TREE_VISITOR_V | visit, | ||
| void * | context | ||
| ) |
Definition at line 634 of file tree.h.
{
TREENODE *current;
TREE_FOREACH_PREORDER(current,node)
visit(node,context);
TREE_FOREACH_POSTORDER_END
}
| M_INLINE void TREE_init_root | ( | TREENODE * | tree | ) |
Definition at line 37 of file tree.h.
{
tree->right = tree->parent = tree->nextlevel_first = 0;
#ifdef TREE_NEXTLEVEL_LEFT
tree->left = 0;
#endif
#ifdef TREE_NEXTLEVEL_LAST
tree->nextlevel_last = 0;
#endif
}
| M_INLINE void TREE_insert_child | ( | TREENODE * | parent, |
| TREENODE * | newnode, | ||
| TREE_INSERT_MODE | mode, | ||
| int | node_is_leaf | ||
| ) |
Definition at line 196 of file tree.h.
{
/* init new node */
if (node_is_leaf) {
newnode->nextlevel_first = 0;
#ifdef TREE_NEXTLEVEL_LAST
newnode->nextlevel_last = 0;
#endif
}
newnode->parent = parent;
newnode->right = 0;
#ifdef TREE_NEXTLEVEL_LEFT
newnode->left = 0;
#endif
if (!parent->nextlevel_first) {
/* insert as first child */
//newnode->nextlevel_first = parent->nextlevel_first;
parent->nextlevel_first = newnode;
#ifdef TREE_NEXTLEVEL_LAST
//newnode->nextlevel_last = parent->nextlevel_last;
parent->nextlevel_last = newnode;
#endif
} else {
/* insert as sibling */
switch(mode) {
case TREE_INSERT_FIRST: {
TREE_insert_left_sibling(parent->nextlevel_first,newnode, 0);
}
break;
case TREE_INSERT_LAST:
#ifdef TREE_NEXTLEVEL_LAST
TREE_insert_right_sibling( parent->nextlevel_last,newnode, 0);
#else
TREE_insert_right_sibling( TREE_rightmost_sibling(parent->nextlevel_first), newnode, 0);
#endif
break;
}
}
}
Definition at line 157 of file tree.h.
{
TREENODE *parent = current->parent;
if (!parent) {
return -1;
}
if (node_is_leaf) {
TREE_init_root(newnode);
}
if (parent->nextlevel_first == current) {
parent->nextlevel_first = newnode;
}
newnode->parent = parent;
#ifdef TREE_NEXTLEVEL_LEFT
if (current->left) {
current->left->right = newnode;
}
#endif
newnode->right = current;
#ifdef TREE_NEXTLEVEL_LEFT
newnode->left = current->left;
current->left = newnode;
#endif
return 0;
}
Definition at line 123 of file tree.h.
{
TREENODE *parent = current->parent;
if (!parent) {
return -1;
}
if (node_is_leaf) {
TREE_init_root(newnode);
}
#ifdef TREE_NEXTLEVEL_LAST
if (parent->nextlevel_last == current) {
parent->nextlevel_last = newnode;
}
#endif
newnode->parent = parent;
#ifdef TREE_NEXTLEVEL_LEFT
newnode->left = current;
if (current->right) {
current->right->left = newnode;
}
#endif
newnode->right = current->right;
current->right = newnode;
return 0;
}
Definition at line 110 of file tree.h.
{
#ifdef TREE_NEXTLEVEL_LAST
return node->nextlevel_last;
#else
return TREE_rightmost_sibling(node->nextlevel_first);
#endif
}
| M_INLINE void TREE_merge_childs | ( | TREENODE * | parent, |
| TREE_INSERT_MODE | mode, | ||
| TREENODE * | newnode | ||
| ) |
Definition at line 244 of file tree.h.
{
TREENODE *ch;
switch(mode) {
case TREE_INSERT_LAST:
ch = TREE_first_child(newnode);
if (!ch) {
return;
}
while(ch) {
TREE_insert_child(parent, ch, TREE_INSERT_LAST, 0 );
ch = TREE_right_sibling(ch);
}
break;
case TREE_INSERT_FIRST:
ch = TREE_last_child(newnode);
if (!ch) {
return;
}
while(ch) {
TREE_insert_child(parent, ch, TREE_INSERT_FIRST, 0 );
ch = TREE_left_sibling(ch);
}
break;
}
}
Definition at line 578 of file tree.h.
{
if (current->nextlevel_first && (!prev || current->parent == prev)) {
next_level:
do {
current = current->nextlevel_first;
}
while(current->nextlevel_first);
} else {
if (current->right) {
current = current->right;
if (current->nextlevel_first) {
goto next_level;
}
} else {
if (current->parent) {
current = current->parent;
}
}
}
return current;
}
Definition at line 403 of file tree.h.
{
if (current->nextlevel_first) {
current = current->nextlevel_first;
} else {
if (current->right) {
current = current->right;
} else {
while(current->parent) {
current = current->parent;
if (current->right) {
current = current->right;
break;
}
}
}
}
return current;
}
Definition at line 277 of file tree.h.
{
TREENODE *tmp,*tmp_next, *tmp_last;
if (!node->parent) {
return 0;
}
/* wrong */
tmp = node->parent;
if (tmp && tmp->nextlevel_first == node) {
if (!node->nextlevel_first) {
tmp->nextlevel_first = node->right;
goto sdel;
}
tmp->nextlevel_first = node->nextlevel_first;
tmp_next = tmp->nextlevel_first;
tmp_last = TREE_rightmost_sibling(tmp_next);
tmp_last->right = node->right;
#ifdef TREE_NEXTLEVEL_LEFT
if (node->right) {
node->right->left = tmp_last;
}
#endif
do {
tmp_next->parent = tmp;
if (tmp_next == tmp_last) {
break;
}
tmp_next = tmp_next->right;
} while(tmp_next);
return node;
}
#ifdef TREE_NEXTLEVEL_LAST
if (tmp && tmp->nextlevel_last == node) {
if (!node->nextlevel_last) {
tmp->nextlevel_last = TREE_left_sibling(node);
goto sdel;
}
tmp->nextlevel_last = node->nextlevel_last;
tmp_next = tmp->nextlevel_last;
tmp_last = TREE_leftmost_sibling(tmp_next);
#ifdef TREE_NEXTLEVEL_LEFT
tmp_last->left = node->left;
#endif
TREE_left_sibling(node)->right = tmp_last;
do {
tmp_last->parent = tmp;
if (tmp_next == tmp_last) {
break;
}
tmp_last = tmp_last->right;
} while(tmp_last);
return node;
}
#endif
sdel:
#ifdef TREE_NEXTLEVEL_LEFT
tmp = node->right;
if (tmp) {
tmp->left = node->left;
}
#endif
tmp = TREE_left_sibling(node);
if (tmp) {
tmp->right = node->right;
}
return node;
}
1.7.4