#ifndef UCX_TREE_H
#define UCX_TREE_H
#include "common.h"
#include "collection.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct cx_tree_iterator_s {
CX_ITERATOR_BASE;
bool skip;
bool visit_on_exit;
bool exiting;
ptrdiff_t loc_children;
ptrdiff_t loc_next;
size_t counter;
void *node;
void *node_next;
void **stack;
size_t stack_capacity;
union {
size_t stack_size;
size_t depth;
};
} CxTreeIterator;
struct cx_tree_visitor_queue_s {
void *node;
size_t depth;
struct cx_tree_visitor_queue_s *next;
};
typedef struct cx_tree_visitor_s {
CX_ITERATOR_BASE;
bool skip;
ptrdiff_t loc_children;
ptrdiff_t loc_next;
size_t counter;
void *node;
size_t depth;
struct cx_tree_visitor_queue_s *queue_next;
struct cx_tree_visitor_queue_s *queue_last;
} CxTreeVisitor;
__attribute__((__nonnull__))
static inline
void cxTreeIteratorDispose(CxTreeIterator *iter) {
free(iter->stack);
iter->stack =
NULL;
}
__attribute__((__nonnull__))
static inline
void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
struct cx_tree_visitor_queue_s *q = visitor->queue_next;
while (q !=
NULL) {
struct cx_tree_visitor_queue_s *next = q->next;
free(q);
q = next;
}
}
#define cxTreeIteratorContinue(iterator) (iterator).skip = true;
continue
#define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor)
__attribute__((__nonnull__))
void cx_tree_link(
void *restrict parent,
void *restrict node,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
__attribute__((__nonnull__))
void cx_tree_unlink(
void *node,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
typedef int (*cx_tree_search_data_func)(
const void *node,
const void *data);
typedef int (*cx_tree_search_func)(
const void *node,
const void *new_node);
__attribute__((__nonnull__))
int cx_tree_search_data(
const void *root,
const void *data,
cx_tree_search_data_func sfunc,
void **result,
ptrdiff_t loc_children,
ptrdiff_t loc_next
);
__attribute__((__nonnull__))
int cx_tree_search(
const void *root,
const void *node,
cx_tree_search_func sfunc,
void **result,
ptrdiff_t loc_children,
ptrdiff_t loc_next
);
CxTreeIterator cx_tree_iterator(
void *root,
bool visit_on_exit,
ptrdiff_t loc_children,
ptrdiff_t loc_next
);
CxTreeVisitor cx_tree_visitor(
void *root,
ptrdiff_t loc_children,
ptrdiff_t loc_next
);
typedef void *(*cx_tree_node_create_func)(
const void *,
void *);
extern unsigned int cx_tree_add_look_around_depth;
__attribute__((__nonnull__(
1,
3,
4,
6,
7)))
size_t cx_tree_add_iter(
struct cx_iterator_base_s *iter,
size_t num,
cx_tree_search_func sfunc,
cx_tree_node_create_func cfunc,
void *cdata,
void **failed,
void *root,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
__attribute__((__nonnull__(
1,
4,
5,
7,
8)))
size_t cx_tree_add_array(
const void *src,
size_t num,
size_t elem_size,
cx_tree_search_func sfunc,
cx_tree_node_create_func cfunc,
void *cdata,
void **failed,
void *root,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
__attribute__((__nonnull__(
1,
2,
3,
5,
6)))
int cx_tree_add(
const void *src,
cx_tree_search_func sfunc,
cx_tree_node_create_func cfunc,
void *cdata,
void **cnode,
void *root,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
typedef struct cx_tree_class_s cx_tree_class;
struct cx_tree_node_base_s {
struct cx_tree_node_base_s *parent;
struct cx_tree_node_base_s *children;
struct cx_tree_node_base_s *last_child;
struct cx_tree_node_base_s *prev;
struct cx_tree_node_base_s *next;
};
struct cx_tree_s {
const cx_tree_class *cl;
const CxAllocator *allocator;
void *root;
cx_tree_node_create_func node_create;
cx_destructor_func simple_destructor;
cx_destructor_func2 advanced_destructor;
void *destructor_data;
cx_tree_search_func search;
cx_tree_search_data_func search_data;
size_t size;
ptrdiff_t loc_parent;
ptrdiff_t loc_children;
ptrdiff_t loc_last_child;
ptrdiff_t loc_prev;
ptrdiff_t loc_next;
};
#define CX_TREE_NODE_BASE(type) \
type *parent; \
type *children;\
type *last_child;\
type *prev;\
type *next
#define cx_tree_node_base_layout \
offsetof(
struct cx_tree_node_base_s, parent),\
offsetof(
struct cx_tree_node_base_s, children),\
offsetof(
struct cx_tree_node_base_s, last_child),\
offsetof(
struct cx_tree_node_base_s, prev), \
offsetof(
struct cx_tree_node_base_s, next)
#define cx_tree_node_layout(tree) \
(tree)->loc_parent,\
(tree)->loc_children,\
(tree)->loc_last_child,\
(tree)->loc_prev, \
(tree)->loc_next
struct cx_tree_class_s {
void (*destructor)(
struct cx_tree_s *);
int (*insert_element)(
struct cx_tree_s *tree,
const void *data
);
size_t (*insert_many)(
struct cx_tree_s *tree,
struct cx_iterator_base_s *iter,
size_t n
);
void *(*find)(
struct cx_tree_s *tree,
const void *subtree,
const void *data
);
CxTreeIterator (*iterator)(
struct cx_tree_s *tree,
bool visit_on_exit
);
CxTreeVisitor (*visitor)(
struct cx_tree_s *tree);
};
typedef struct cx_tree_s CxTree;
__attribute__((__nonnull__, __warn_unused_result__))
CxTree *cxTreeCreate(
const CxAllocator *allocator,
cx_tree_node_create_func create_func,
cx_tree_search_func search_func,
cx_tree_search_data_func search_data_func,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
__attribute__((__nonnull__, __warn_unused_result__))
static inline CxTree *cxTreeCreateSimple(
const CxAllocator *allocator,
cx_tree_node_create_func create_func,
cx_tree_search_func search_func,
cx_tree_search_data_func search_data_func
) {
return cxTreeCreate(
allocator,
create_func,
search_func,
search_data_func,
cx_tree_node_base_layout
);
}
__attribute__((__nonnull__, __warn_unused_result__))
CxTree *cxTreeCreateWrapped(
const CxAllocator *allocator,
void *root,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next
);
__attribute__((__nonnull__))
static inline
void cxTreeDestroy(CxTree *tree) {
tree->cl->destructor(tree);
}
__attribute__((__nonnull__))
static inline
int cxTreeInsert(
CxTree *tree,
const void *data
) {
return tree->cl->insert_element(tree, data);
}
__attribute__((__nonnull__))
static inline
size_t cxTreeInsertIter(
CxTree *tree,
struct cx_iterator_base_s *iter,
size_t n
) {
return tree->cl->insert_many(tree, iter, n);
}
__attribute__((__nonnull__))
static inline
size_t cxTreeInsertArray(
CxTree *tree,
const void *data,
size_t elem_size,
size_t n
) {
if (n ==
0)
return 0;
if (n ==
1)
return 0 == cxTreeInsert(tree, data) ?
1 :
0;
CxIterator iter = cxIterator(data, elem_size, n);
return cxTreeInsertIter(tree, cxIteratorRef(iter), n);
}
__attribute__((__nonnull__))
static inline
void *cxTreeFind(
CxTree *tree,
const void *data
) {
return tree->cl->find(tree, tree->root, data);
}
__attribute__((__nonnull__))
static inline
void *cxTreeFindInSubtree(
CxTree *tree,
const void *data,
void *subtree_root
) {
return tree->cl->find(tree, subtree_root, data);
}
__attribute__((__nonnull__))
size_t cxTreeSubtreeSize(CxTree *tree,
void *subtree_root);
__attribute__((__nonnull__))
size_t cxTreeSubtreeDepth(CxTree *tree,
void *subtree_root);
__attribute__((__nonnull__))
size_t cxTreeDepth(CxTree *tree);
__attribute__((__nonnull__, __warn_unused_result__))
static inline CxTreeIterator cxTreeIterator(
CxTree *tree,
bool visit_on_exit
) {
return tree->cl->iterator(tree, visit_on_exit);
}
__attribute__((__nonnull__, __warn_unused_result__))
static inline CxTreeVisitor cxTreeVisitor(CxTree *tree) {
return tree->cl->visitor(tree);
}
__attribute__((__nonnull__))
static inline
void cxTreeAddChildNode(
CxTree *tree,
void *parent,
void *child) {
cx_tree_link(parent, child, cx_tree_node_layout(tree));
tree->size++;
}
__attribute__((__nonnull__))
int cxTreeAddChild(
CxTree *tree,
void *parent,
const void *data
);
typedef void (*cx_tree_relink_func)(
void *node,
const void *old_parent,
const void *new_parent
);
__attribute__((__nonnull__(
1,
2)))
int cxTreeRemove(
CxTree *tree,
void *node,
cx_tree_relink_func relink_func
);
__attribute__((__nonnull__))
void cxTreeRemoveSubtree(CxTree *tree,
void *node);
#ifdef __cplusplus
}
#endif
#endif