From bae95909ca99dd819e0e12f8b2ef4ea7c65c9f1e Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 29 Oct 2025 14:35:07 +0000 Subject: [PATCH] ds: dict: update iterator interface --- ds/dict.c | 262 ++++++++++++++++++++++++++------------ ds/include/blue/ds/dict.h | 29 ++--- 2 files changed, 192 insertions(+), 99 deletions(-) diff --git a/ds/dict.c b/ds/dict.c index 9a49165..59d7603 100644 --- a/ds/dict.c +++ b/ds/dict.c @@ -26,6 +26,16 @@ struct b_dict_p { b_btree d_buckets; }; +struct b_dict_iterator_p { + size_t i; + b_dict_item item; + + b_dict *_d; + struct b_dict_p *_d_p; + b_btree_node *_cbn; + b_queue_entry *_cqe; +}; + /*** MISC FUNCTIONS ***********************************************************/ static B_BTREE_DEFINE_SIMPLE_GET( @@ -132,14 +142,16 @@ static b_object *dict_at(const struct b_dict_p *dict, const char *key) return NULL; } - b_queue_iterator it; - b_queue_foreach (&it, &bucket->bk_items) { + struct b_queue_entry *entry = b_queue_first(&bucket->bk_items); + while (entry) { struct b_dict_bucket_item *item - = b_unbox(struct b_dict_bucket_item, it.entry, bi_entry); + = b_unbox(struct b_dict_bucket_item, entry, bi_entry); if (!strcmp(b_string_ptr(item->bi_str), key)) { return item->bi_value; } + + entry = b_queue_next(entry); } return NULL; @@ -153,14 +165,16 @@ static b_object *dict_at_sk(const struct b_dict_p *dict, const b_string *key) return NULL; } - b_queue_iterator it; - b_queue_foreach (&it, &bucket->bk_items) { + struct b_queue_entry *entry = b_queue_first(&bucket->bk_items); + while (entry) { struct b_dict_bucket_item *item - = b_unbox(struct b_dict_bucket_item, it.entry, bi_entry); + = b_unbox(struct b_dict_bucket_item, entry, bi_entry); if (b_string_compare(item->bi_str, key)) { return item->bi_value; } + + entry = b_queue_next(entry); } return NULL; @@ -199,6 +213,7 @@ static bool dict_has_skey(const struct b_dict_p *dict, const b_string *key) static size_t dict_get_size(const struct b_dict_p *dict) { size_t count = 0; +#if 0 b_btree_iterator it1; b_queue_iterator it2; @@ -210,6 +225,7 @@ static size_t dict_get_size(const struct b_dict_p *dict) count++; } } +#endif return count; } @@ -298,6 +314,7 @@ static b_status delete_item( /*** PUBLIC FUNCTIONS *********************************************************/ +#if 0 b_dict *b_dict_create_with_items(const b_dict_item *items) { b_dict *dict = b_dict_create(); @@ -313,6 +330,8 @@ b_dict *b_dict_create_with_items(const b_dict_item *items) return dict; } +#endif + b_status b_dict_put(b_dict *dict, const char *key, b_object *value) { B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put, dict, key, value); @@ -375,6 +394,7 @@ static void dict_fini(b_object *obj, void *priv) { struct b_dict_p *dict = priv; +#if 0 b_btree_iterator tree_it; b_btree_iterator_begin(&dict->d_buckets, &tree_it); while (b_btree_iterator_is_valid(&tree_it)) { @@ -405,6 +425,7 @@ static void dict_fini(b_object *obj, void *priv) free(bucket); } +#endif } static void dict_to_string(const b_object *obj, b_stream *out) @@ -421,6 +442,7 @@ static void dict_to_string(const b_object *obj, b_stream *out) b_stream_push_indent(out, 1); size_t len = dict_get_size(dict); +#if 0 b_dict_iterator it; b_dict_foreach(&it, (b_dict *)obj) { @@ -445,138 +467,163 @@ static void dict_to_string(const b_object *obj, b_stream *out) b_stream_write_char(out, '\n'); } +#endif b_stream_pop_indent(out); b_stream_write_char(out, '}'); } -/*** CLASS DEFINITION *********************************************************/ - -B_TYPE_CLASS_DEFINITION_BEGIN(b_dict) - B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) - B_INTERFACE_ENTRY(to_string) = dict_to_string; - B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) -B_TYPE_CLASS_DEFINITION_END(b_dict) - -B_TYPE_DEFINITION_BEGIN(b_dict) - B_TYPE_ID(0xd2af61d9, 0xd0be, 0x4960, 0xbe3f, 0x509749814c10); - B_TYPE_CLASS(b_dict_class); - B_TYPE_INSTANCE_PRIVATE(struct b_dict_p); - B_TYPE_INSTANCE_INIT(dict_init); - B_TYPE_INSTANCE_FINI(dict_fini); -B_TYPE_DEFINITION_END(b_dict) - /*** ITERATOR FUNCTIONS *******************************************************/ -static bool dict_iterator_next(struct b_iterator *it) +static b_iterator *iterable_begin(b_dict *dict) { - return b_dict_iterator_next((struct b_dict_iterator *)it); -} + b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR); + if (!it_obj) { + return NULL; + } -static b_status dict_iterator_erase(struct b_iterator *it) -{ - return b_dict_iterator_erase((struct b_dict_iterator *)it); -} - -static bool dict_iterator_is_valid(const struct b_iterator *it) -{ - return b_dict_iterator_is_valid((struct b_dict_iterator *)it); -} - -static struct b_iterator_ops it_ops = { - .it_next = dict_iterator_next, - .it_close = NULL, - .it_erase = dict_iterator_erase, - .it_is_valid = dict_iterator_is_valid, -}; - -int b_dict_iterator_begin(b_dict *dict, b_dict_iterator *it) -{ - it->_base.it_ops = &it_ops; + struct b_dict_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR); it->i = 0; it->_d = dict; it->_d_p = b_object_get_private(dict, B_TYPE_DICT); if (dict_is_empty(it->_d_p)) { - it->key = NULL; - it->value = NULL; - return -1; + it->item.key = NULL; + it->item.value = NULL; + return it_obj; } b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets); struct b_dict_bucket *first_bucket = b_unbox(struct b_dict_bucket, first_node, bk_node); if (!first_bucket) { - it->key = NULL; - it->value = NULL; - return -1; + it->item.key = NULL; + it->item.value = NULL; + return it_obj; } b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items); struct b_dict_bucket_item *first_item = b_unbox(struct b_dict_bucket_item, first_entry, bi_entry); if (!first_item) { - it->key = NULL; - it->value = NULL; - return -1; + it->item.key = NULL; + it->item.value = NULL; + return it_obj; } - it->key = first_item->bi_str; - it->value = first_item->bi_value; + it->item.key = first_item->bi_str; + it->item.value = first_item->bi_value; it->_d = dict; it->_cbn = first_node; it->_cqe = first_entry; - return 0; + return it_obj; } -bool b_dict_iterator_next(b_dict_iterator *it) +static const b_iterator *iterable_cbegin(const b_dict *dict) { + b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR); + if (!it_obj) { + return NULL; + } + + struct b_dict_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR); + + it->i = 0; + it->_d = (b_dict *)dict; + it->_d_p = b_object_get_private(dict, B_TYPE_DICT); + + if (dict_is_empty(it->_d_p)) { + it->item.key = NULL; + it->item.value = NULL; + b_iterator_set_status(it_obj, B_ERR_NO_DATA); + return it_obj; + } + + b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets); + struct b_dict_bucket *first_bucket + = b_unbox(struct b_dict_bucket, first_node, bk_node); + if (!first_bucket) { + it->item.key = NULL; + it->item.value = NULL; + b_iterator_set_status(it_obj, B_ERR_NO_DATA); + return it_obj; + } + + b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items); + struct b_dict_bucket_item *first_item + = b_unbox(struct b_dict_bucket_item, first_entry, bi_entry); + if (!first_item) { + it->item.key = NULL; + it->item.value = NULL; + b_iterator_set_status(it_obj, B_ERR_NO_DATA); + return it_obj; + } + + it->item.key = first_item->bi_str; + it->item.value = first_item->bi_value; + + it->_cbn = first_node; + it->_cqe = first_entry; + + return it_obj; +} + +static enum b_status iterator_move_next(const b_iterator *obj) +{ + struct b_dict_iterator_p *it + = b_object_get_private(obj, B_TYPE_DICT_ITERATOR); + struct b_btree_node *next_node; struct b_queue_entry *next_entry; if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) { - it->key = NULL; - it->value = NULL; - return -1; + it->item.key = NULL; + it->item.value = NULL; + return B_ERR_NO_DATA; } struct b_dict_bucket_item *next_item = b_unbox(struct b_dict_bucket_item, next_entry, bi_entry); if (!next_item) { - it->key = NULL; - it->value = NULL; - return -1; + it->item.key = NULL; + it->item.value = NULL; + return B_ERR_NO_DATA; } it->i++; - it->key = next_item->bi_str; - it->value = next_item->bi_value; + it->item.key = next_item->bi_str; + it->item.value = next_item->bi_value; it->_cbn = next_node; it->_cqe = next_entry; - return 0; + return B_SUCCESS; } -b_status b_dict_iterator_erase(struct b_dict_iterator *it) +static enum b_status iterator_erase(b_iterator *obj) { - if ((it->key || it->value) && !(it->_cbn && it->_cqe)) { + struct b_dict_iterator_p *it + = b_object_get_private(obj, B_TYPE_DICT_ITERATOR); + + if ((it->item.key || it->item.value) && !(it->_cbn && it->_cqe)) { return B_ERR_BAD_STATE; } - if (!it->key || !it->_cqe) { - return B_ERR_OUT_OF_BOUNDS; + if (!it->item.key || !it->_cqe) { + return B_ERR_NO_DATA; } struct b_btree_node *next_node; struct b_queue_entry *next_entry; if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) { - it->key = NULL; - it->value = NULL; - return false; + it->item.key = NULL; + it->item.value = NULL; + return B_ERR_NO_DATA; } struct b_dict_bucket *cur_bucket @@ -593,14 +640,14 @@ b_status b_dict_iterator_erase(struct b_dict_iterator *it) } if (next_item) { - it->key = next_item->bi_str; - it->value = next_item->bi_value; + it->item.key = next_item->bi_str; + it->item.value = next_item->bi_value; it->_cbn = next_node; it->_cqe = next_entry; } else { - it->key = NULL; - it->value = NULL; + it->item.key = NULL; + it->item.value = NULL; it->_cbn = NULL; it->_cqe = NULL; @@ -609,7 +656,62 @@ b_status b_dict_iterator_erase(struct b_dict_iterator *it) return B_SUCCESS; } -bool b_dict_iterator_is_valid(const struct b_dict_iterator *it) +static b_iterator_value iterator_get_value(b_iterator *obj) { - return it->key != NULL; + struct b_dict_iterator_p *it + = b_object_get_private(obj, B_TYPE_DICT_ITERATOR); + + return B_ITERATOR_VALUE_PTR(&it->item); } + +static const b_iterator_value iterator_get_cvalue(const b_iterator *obj) +{ + struct b_dict_iterator_p *it + = b_object_get_private(obj, B_TYPE_DICT_ITERATOR); + + return B_ITERATOR_VALUE_CPTR(&it->item); +} + +/*** CLASS DEFINITION *********************************************************/ + +// ---- b_dict DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_dict) + B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) + B_INTERFACE_ENTRY(to_string) = dict_to_string; + B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) + + B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE) + B_INTERFACE_ENTRY(it_begin) = iterable_begin; + B_INTERFACE_ENTRY(it_cbegin) = iterable_cbegin; + B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE) +B_TYPE_CLASS_DEFINITION_END(b_dict) + +B_TYPE_DEFINITION_BEGIN(b_dict) + B_TYPE_ID(0xd2af61d9, 0xd0be, 0x4960, 0xbe3f, 0x509749814c10); + B_TYPE_CLASS(b_dict_class); + B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE); + B_TYPE_INSTANCE_PRIVATE(struct b_dict_p); + B_TYPE_INSTANCE_INIT(dict_init); + B_TYPE_INSTANCE_FINI(dict_fini); +B_TYPE_DEFINITION_END(b_dict) + +// ---- b_dict_iterator DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_dict_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_dict_iterator) + +B_TYPE_DEFINITION_BEGIN(b_dict_iterator) + B_TYPE_ID(0x9ea96701, 0x1713, 0x4a3e, 0xbf63, 0xdc856b456f3b); + B_TYPE_EXTENDS(B_TYPE_ITERATOR); + B_TYPE_CLASS(b_dict_iterator_class); + B_TYPE_INSTANCE_PRIVATE(struct b_dict_iterator_p); +B_TYPE_DEFINITION_END(b_dict_iterator) diff --git a/ds/include/blue/ds/dict.h b/ds/include/blue/ds/dict.h index 8cd75d9..e3430c7 100644 --- a/ds/include/blue/ds/dict.h +++ b/ds/include/blue/ds/dict.h @@ -10,15 +10,20 @@ B_DECLS_BEGIN; -#define B_TYPE_DICT (b_dict_get_type()) +#define B_TYPE_DICT (b_dict_get_type()) +#define B_TYPE_DICT_ITERATOR (b_dict_iterator_get_type()) struct b_dict_p; B_DECLARE_TYPE(b_dict); +B_DECLARE_TYPE(b_dict_iterator); B_TYPE_CLASS_DECLARATION_BEGIN(b_dict) B_TYPE_CLASS_DECLARATION_END(b_dict) +B_TYPE_CLASS_DECLARATION_BEGIN(b_dict_iterator) +B_TYPE_CLASS_DECLARATION_END(b_dict_iterator) + #define B_DICT_ITEM(k, v) {.key = (k), .value = (v)} #define B_DICT_ITEM_END {.key = NULL, .value = NULL} @@ -26,28 +31,19 @@ B_TYPE_CLASS_DECLARATION_END(b_dict) for (int z__b_unique_name() = b_dict_iterator_begin(dict, it); \ (it)->key != NULL; b_dict_iterator_next(it)) -typedef struct b_dict_iterator { - b_iterator _base; - size_t i; - const b_string *key; - b_object *value; - - b_dict *_d; - struct b_dict_p *_d_p; - b_btree_node *_cbn; - b_queue_entry *_cqe; -} b_dict_iterator; - typedef struct b_dict_item { - const char *key; + const b_string *key; b_object *value; } b_dict_item; BLUE_API b_type b_dict_get_type(void); +BLUE_API b_type b_dict_iterator_get_type(void); B_TYPE_DEFAULT_CONSTRUCTOR(b_dict, B_TYPE_DICT); +#if 0 BLUE_API b_dict *b_dict_create_with_items(const b_dict_item *items); +#endif BLUE_API b_status b_dict_put(b_dict *dict, const char *key, b_object *value); BLUE_API b_status b_dict_put_sk(b_dict *dict, const b_string *key, b_object *value); @@ -61,11 +57,6 @@ BLUE_API bool b_dict_has_skey(const b_dict *dict, const b_string *key); BLUE_API size_t b_dict_get_size(const b_dict *dict); BLUE_API bool b_dict_is_empty(const b_dict *dict); -BLUE_API int b_dict_iterator_begin(b_dict *dict, b_dict_iterator *it); -BLUE_API bool b_dict_iterator_next(b_dict_iterator *it); -BLUE_API b_status b_dict_iterator_erase(b_dict_iterator *it); -BLUE_API bool b_dict_iterator_is_valid(const b_dict_iterator *it); - B_DECLS_END; #endif