diff --git a/core/btree.c b/core/btree.c index 2664ed3..56dea8c 100644 --- a/core/btree.c +++ b/core/btree.c @@ -77,6 +77,12 @@ #define HEIGHT(x) ((x) ? (x)->b_height : 0) +struct b_btree_iterator_p { + size_t i, depth; + b_btree_node *node; + b_btree *_b; +}; + static inline void update_height(struct b_btree_node *x) { x->b_height = MAX(HEIGHT(x->b_left), HEIGHT((x->b_right))) + 1; @@ -413,8 +419,7 @@ void b_btree_insert_fixup(struct b_btree *tree, struct b_btree_node *node) @param node the node to delete. */ static struct b_btree_node *remove_node_with_no_children( - struct b_btree *tree, - struct b_btree_node *node) + struct b_btree *tree, struct b_btree_node *node) { struct b_btree_node *w = node->b_parent; struct b_btree_node *p = node->b_parent; @@ -447,8 +452,7 @@ static struct b_btree_node *remove_node_with_no_children( @param node the node to delete. */ static struct b_btree_node *replace_node_with_one_subtree( - struct b_btree *tree, - struct b_btree_node *node) + struct b_btree *tree, struct b_btree_node *node) { struct b_btree_node *p = node->b_parent; struct b_btree_node *z = NULL; @@ -497,8 +501,7 @@ static struct b_btree_node *replace_node_with_one_subtree( @param z the node to delete. */ static struct b_btree_node *replace_node_with_two_subtrees( - struct b_btree *tree, - struct b_btree_node *z) + struct b_btree *tree, struct b_btree_node *z) { /* x will replace z */ struct b_btree_node *x = z->b_left; @@ -733,45 +736,49 @@ b_btree_node *b_btree_prev(const struct b_btree_node *node) return prev_node(node, &d); } -static bool btree_iterator_next(struct b_iterator *it) +b_iterator *b_btree_begin(struct b_btree *tree) { - return b_btree_iterator_next((struct b_btree_iterator *)it); -} + b_iterator *it_obj = b_object_create(B_TYPE_BTREE_ITERATOR); + if (!it_obj) { + return NULL; + } -static b_status btree_iterator_erase(struct b_iterator *it) -{ - return b_btree_iterator_erase((struct b_btree_iterator *)it); -} - -static bool btree_iterator_is_valid(const struct b_iterator *it) -{ - return b_btree_iterator_is_valid((struct b_btree_iterator *)it); -} - -static const b_iterator_ops btree_iterator_ops = { - .it_next = btree_iterator_next, - .it_erase = btree_iterator_erase, - .it_close = NULL, - .it_is_valid = btree_iterator_is_valid, -}; - -int b_btree_iterator_begin( - const struct b_btree *tree, - struct b_btree_iterator *it) -{ + struct b_btree_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_BTREE_ITERATOR); int depth = 0; it->_b = (struct b_btree *)tree; it->i = 0; it->node = first_node(tree, &depth); it->depth = depth; - it->_base.it_ops = &btree_iterator_ops; - return 0; + return it_obj; } -bool b_btree_iterator_next(struct b_btree_iterator *it) +const b_iterator *b_btree_cbegin(const struct b_btree *tree) { + b_iterator *it_obj = b_object_create(B_TYPE_BTREE_ITERATOR); + if (!it_obj) { + return NULL; + } + + struct b_btree_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_BTREE_ITERATOR); + int depth = 0; + + it->_b = (struct b_btree *)tree; + it->i = 0; + it->node = first_node(tree, &depth); + it->depth = depth; + + return it_obj; +} + +static enum b_status iterator_move_next(const b_iterator *obj) +{ + struct b_btree_iterator_p *it + = b_object_get_private(obj, B_TYPE_BTREE_ITERATOR); + int depth_diff = 0; struct b_btree_node *next = next_node(it->node, &depth_diff); @@ -788,8 +795,11 @@ bool b_btree_iterator_next(struct b_btree_iterator *it) return true; } -b_status b_btree_iterator_erase(struct b_btree_iterator *it) +static enum b_status iterator_erase(b_iterator *obj) { + struct b_btree_iterator_p *it + = b_object_get_private(obj, B_TYPE_BTREE_ITERATOR); + if (!it->node) { return B_ERR_OUT_OF_BOUNDS; } @@ -815,7 +825,41 @@ b_status b_btree_iterator_erase(struct b_btree_iterator *it) return B_SUCCESS; } -bool b_btree_iterator_is_valid(const struct b_btree_iterator *it) +static b_iterator_value iterator_get_value(b_iterator *obj) { - return it->node != NULL; + struct b_btree_iterator_p *it + = b_object_get_private(obj, B_TYPE_BTREE_ITERATOR); + + return B_ITERATOR_VALUE_PTR(it->node); } + +static const b_iterator_value iterator_get_cvalue(const b_iterator *obj) +{ + struct b_btree_iterator_p *it + = b_object_get_private(obj, B_TYPE_BTREE_ITERATOR); + + return B_ITERATOR_VALUE_CPTR(it->node); +} + +/*** CLASS DEFINITION *********************************************************/ + +// ---- b_btree_iterator DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_btree_iterator) + B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) + B_INTERFACE_ENTRY(to_string) = NULL; + B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) + + B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR) + B_INTERFACE_ENTRY(it_move_next) = iterator_move_next; + B_INTERFACE_ENTRY(it_erase) = iterator_erase; + B_INTERFACE_ENTRY(it_get_value) = iterator_get_value; + B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue; + B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR) +B_TYPE_CLASS_DEFINITION_END(b_btree_iterator) + +B_TYPE_DEFINITION_BEGIN(b_btree_iterator) + B_TYPE_ID(0x432779d7, 0xc03a, 0x48ea, 0xae8f, 0x12c666c767ae); + B_TYPE_EXTENDS(B_TYPE_ITERATOR); + B_TYPE_CLASS(b_btree_iterator_class); + B_TYPE_INSTANCE_PRIVATE(struct b_btree_iterator_p); +B_TYPE_DEFINITION_END(b_btree_iterator) diff --git a/core/include/blue/core/btree.h b/core/include/blue/core/btree.h index f526e07..b5cf925 100644 --- a/core/include/blue/core/btree.h +++ b/core/include/blue/core/btree.h @@ -2,19 +2,21 @@ #define BLUELIB_CORE_BTREE_H_ #include +#include #include #include #include #include -#define B_BTREE_INIT \ - { \ - 0 \ - } +B_DECLS_BEGIN; -#ifdef __cplusplus -extern "C" { -#endif +#define B_BTREE_INIT {0} +#define B_TYPE_BTREE_ITERATOR (b_btree_iterator_get_type()) + +B_DECLARE_TYPE(b_btree_iterator); + +B_TYPE_CLASS_DECLARATION_BEGIN(b_btree_iterator) +B_TYPE_CLASS_DECLARATION_END(b_btree_iterator) /* defines a simple node insertion function. this function assumes that your nodes have simple integer keys that can be @@ -24,18 +26,18 @@ extern "C" { if you have a tree node type like this: struct my_tree_node { - int key; - b_btree_node base; + int key; + b_btree_node base; } You would use the following call to generate an insert function for a tree with this node type: BTREE_DEFINE_SIMPLE_INSERT( - struct my_tree_node, - base, - key, - my_tree_node_insert); + struct my_tree_node, + base, + key, + my_tree_node_insert); Which would emit a function defined like: @@ -102,8 +104,8 @@ extern "C" { if you have a tree node type like this: struct my_tree_node { - complex_key_t key; - b_btree_node base; + complex_key_t key; + b_btree_node base; } You would need to define a comparator function or macro with the following @@ -191,8 +193,8 @@ extern "C" { if you have a tree node type like this: struct my_tree_node { - int key; - b_btree_node base; + int key; + b_btree_node base; } You would use the following call to generate a search function for a tree @@ -257,12 +259,7 @@ typedef struct b_btree { b_btree_node *b_root; } b_btree; -typedef struct b_btree_iterator { - b_iterator _base; - size_t i, depth; - b_btree_node *node; - b_btree *_b; -} b_btree_iterator; +BLUE_API b_type b_btree_iterator_get_type(void); /* re-balance a binary tree after an insertion operation. @@ -350,10 +347,8 @@ static inline unsigned short b_btree_height(b_btree_node *node) return node->b_height; } -BLUE_API int b_btree_iterator_begin(const b_btree *tree, b_btree_iterator *it); -BLUE_API bool b_btree_iterator_next(b_btree_iterator *it); -BLUE_API b_status b_btree_iterator_erase(b_btree_iterator *it); -BLUE_API bool b_btree_iterator_is_valid(const b_btree_iterator *it); +BLUE_API b_iterator *b_btree_begin(b_btree *tree); +BLUE_API const b_iterator *b_btree_cbegin(const b_btree *tree); #ifdef __cplusplus }