diff --git a/ds/include/blue/ds/list.h b/ds/include/blue/ds/list.h index 8ed73a8..9678e6c 100644 --- a/ds/include/blue/ds/list.h +++ b/ds/include/blue/ds/list.h @@ -1,37 +1,30 @@ #ifndef BLUE_DS_LIST_H_ #define BLUE_DS_LIST_H_ +#include #include #include B_DECLS_BEGIN; -#define B_TYPE_LIST (b_list_get_type()) +#define B_TYPE_LIST (b_list_get_type()) +#define B_TYPE_LIST_ITERATOR (b_list_iterator_get_type()) struct b_list_p; B_DECLARE_TYPE(b_list); +B_DECLARE_TYPE(b_list_iterator); B_TYPE_CLASS_DECLARATION_BEGIN(b_list) B_TYPE_CLASS_DECLARATION_END(b_list) +B_TYPE_CLASS_DECLARATION_BEGIN(b_list_iterator) +B_TYPE_CLASS_DECLARATION_END(b_list_iterator) + typedef struct b_list_entry b_list_entry; -#define b_list_foreach(it, q) \ - for (int z__b_unique_name() = b_list_iterator_begin(q, it); \ - (it)->entry != NULL; b_list_iterator_next(it)) - -typedef struct b_list_iterator { - b_queue_iterator _base; - const b_list *_q; - const struct b_list_p *_q_p; - - size_t i; - void *item; - b_list_entry *entry; -} b_list_iterator; - BLUE_API b_type b_list_get_type(void); +BLUE_API b_type b_list_iterator_get_type(void); B_TYPE_DEFAULT_CONSTRUCTOR(b_list, B_TYPE_LIST); @@ -60,13 +53,11 @@ BLUE_API b_status b_list_delete_item(b_list *q, void *ptr); BLUE_API b_status b_list_delete_entry(b_list *q, b_list_entry *entry); BLUE_API void b_list_delete_all(b_list *q); -BLUE_API int b_list_iterator_begin(const b_list *q, b_list_iterator *it); -BLUE_API bool b_list_iterator_next(b_list_iterator *it); -BLUE_API b_status b_list_iterator_erase(b_list_iterator *it); -BLUE_API bool b_list_iterator_is_valid(const b_list_iterator *it); - BLUE_API void *b_list_entry_value(const b_list_entry *entry); +BLUE_API b_iterator *b_list_begin(b_list *q); +BLUE_API b_iterator *b_list_cbegin(const b_list *q); + B_DECLS_END; #endif diff --git a/ds/list.c b/ds/list.c index c875e65..ec50682 100644 --- a/ds/list.c +++ b/ds/list.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -14,6 +16,16 @@ struct b_list_p { size_t l_len; }; +struct b_list_iterator_p { + b_list *_q; + struct b_list_p *_q_p; + struct b_queue_entry *_q_entry; + + size_t i; + void *item; + b_list_entry *entry; +}; + /*** PRIVATE FUNCTIONS ********************************************************/ static bool list_empty(struct b_list_p *q) @@ -184,14 +196,16 @@ static void *list_pop_back(struct b_list_p *q) static struct b_list_entry *find_item(struct b_list_p *list, void *item) { - struct b_queue_iterator it; - b_queue_foreach (&it, &list->l_queue) { - struct b_list_entry *entry - = b_unbox(struct b_list_entry, it.entry, e_entry); + struct b_queue_entry *entry = b_queue_first(&list->l_queue); + while (entry) { + struct b_list_entry *list_entry + = b_unbox(struct b_list_entry, entry, e_entry); - if (entry->e_data == item) { - return entry; + if (list_entry->e_data == item) { + return list_entry; } + + entry = b_queue_next(entry); } return NULL; @@ -224,15 +238,14 @@ static b_status list_delete_entry(struct b_list_p *q, struct b_list_entry *entry static void list_delete_all(struct b_list_p *q) { - struct b_queue_iterator it; - b_queue_iterator_begin(&q->l_queue, &it); + struct b_queue_entry *entry = b_queue_first(&q->l_queue); + while (entry) { + struct b_list_entry *list_entry + = b_unbox(struct b_list_entry, entry, e_entry); + struct b_queue_entry *next = b_queue_next(entry); - while (b_queue_iterator_is_valid(&it)) { - struct b_list_entry *entry - = b_unbox(struct b_list_entry, it.entry, e_entry); - b_queue_iterator_erase(&it); - - free(entry); + free(list_entry); + entry = next; } q->l_len = 0; @@ -347,6 +360,11 @@ void b_list_delete_all(b_list *q) B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_delete_all, q); } +void *b_list_entry_value(const struct b_list_entry *entry) +{ + return entry ? entry->e_data : NULL; +} + /*** VIRTUAL FUNCTIONS ********************************************************/ static void list_init(b_object *obj, void *priv) @@ -360,32 +378,20 @@ static void list_fini(b_object *obj, void *priv) list_delete_all(list); } -/*** CLASS DEFINITION *********************************************************/ - -B_TYPE_CLASS_DEFINITION_BEGIN(b_list) - 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_DEFINITION_END(b_list) - -B_TYPE_DEFINITION_BEGIN(b_list) - B_TYPE_ID(0x8730e66f, 0x0fd9, 0x4773, 0x9bbd, 0x6428f6e495eb); - B_TYPE_CLASS(b_list_class); - B_TYPE_INSTANCE_PRIVATE(struct b_list_p); - B_TYPE_INSTANCE_INIT(list_init); - B_TYPE_INSTANCE_FINI(list_fini); -B_TYPE_DEFINITION_END(b_list) - /*** ITERATOR FUNCTIONS *******************************************************/ -int b_list_iterator_begin(const b_list *q, struct b_list_iterator *it) +static b_iterator *iterable_begin(b_list *q) { + b_list_iterator *it_obj = b_object_create(B_TYPE_LIST_ITERATOR); + struct b_list_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_LIST_ITERATOR); + it->_q = q; it->_q_p = b_object_get_private(q, B_TYPE_LIST); - b_queue_iterator_begin(&it->_q_p->l_queue, &it->_base); + it->_q_entry = b_queue_first(&it->_q_p->l_queue); it->i = 0; - it->entry = b_unbox(struct b_list_entry, it->_base.entry, e_entry); + it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry); if (it->entry) { it->item = it->entry->e_data; } @@ -393,17 +399,45 @@ int b_list_iterator_begin(const b_list *q, struct b_list_iterator *it) return 0; } -bool b_list_iterator_next(struct b_list_iterator *it) +static const b_iterator *iterable_cbegin(const b_list *q) { - bool ok = b_queue_iterator_next(&it->_base); - if (!ok) { + b_list_iterator *it_obj = b_object_create(B_TYPE_LIST_ITERATOR); + struct b_list_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_LIST_ITERATOR); + + it->_q = (b_list *)q; + it->_q_p = b_object_get_private(q, B_TYPE_LIST); + it->_q_entry = b_queue_first(&it->_q_p->l_queue); + + it->i = 0; + it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry); + if (it->entry) { + it->item = it->entry->e_data; + } + + return 0; +} + +static enum b_status iterator_move_next(const b_iterator *obj) +{ + struct b_list_iterator_p *it + = b_object_get_private(obj, B_TYPE_LIST_ITERATOR); + + if (!it->_q_entry) { it->entry = NULL; it->item = NULL; - return false; + return B_ERR_NO_DATA; + } + + it->_q_entry = b_queue_next(it->_q_entry); + if (!it->_q_entry) { + it->entry = NULL; + it->item = NULL; + return B_ERR_NO_DATA; } it->i++; - it->entry = b_unbox(struct b_list_entry, it->_base.entry, e_entry); + it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry); if (it->entry) { it->item = it->entry->e_data; } @@ -411,16 +445,22 @@ bool b_list_iterator_next(struct b_list_iterator *it) return it->entry != NULL; } -b_status b_list_iterator_erase(struct b_list_iterator *it) +static enum b_status iterator_erase(b_iterator *obj) { - if (!it->entry) { + struct b_list_iterator_p *it + = b_object_get_private(obj, B_TYPE_LIST_ITERATOR); + + if (!it->entry || !it->_q_entry) { return B_ERR_OUT_OF_BOUNDS; } - b_queue_iterator_erase(&it->_base); + struct b_queue_entry *next = b_queue_next(it->_q_entry); + + b_queue_delete(&it->_q_p->l_queue, it->_q_entry); free(it->entry); - it->entry = b_unbox(struct b_list_entry, it->_base.entry, e_entry); + it->_q_entry = next; + it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry); if (it->entry) { it->item = it->entry->e_data; } @@ -428,12 +468,62 @@ b_status b_list_iterator_erase(struct b_list_iterator *it) return B_SUCCESS; } -bool b_list_iterator_is_valid(const struct b_list_iterator *it) +static b_iterator_value iterator_get_value(b_iterator *obj) { - return it->entry != NULL; + struct b_list_iterator_p *it + = b_object_get_private(obj, B_TYPE_LIST_ITERATOR); + + return B_ITERATOR_VALUE_PTR(it->item); } -void *b_list_entry_value(const struct b_list_entry *entry) +static const b_iterator_value iterator_get_cvalue(const b_iterator *obj) { - return entry ? entry->e_data : NULL; + struct b_list_iterator_p *it + = b_object_get_private(obj, B_TYPE_LIST_ITERATOR); + + return B_ITERATOR_VALUE_CPTR(it->item); } + +/*** CLASS DEFINITION *********************************************************/ + +// ---- b_list DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_list) + 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_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_list) + +B_TYPE_DEFINITION_BEGIN(b_list) + B_TYPE_ID(0x8730e66f, 0x0fd9, 0x4773, 0x9bbd, 0x6428f6e495eb); + B_TYPE_CLASS(b_list_class); + B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE); + B_TYPE_INSTANCE_PRIVATE(struct b_list_p); + B_TYPE_INSTANCE_INIT(list_init); + B_TYPE_INSTANCE_FINI(list_fini); +B_TYPE_DEFINITION_END(b_list) + +// ---- b_list_iterator DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_list_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_list_iterator) + +B_TYPE_DEFINITION_BEGIN(b_list_iterator) + B_TYPE_ID(0xd9658456, 0xdd80, 0x419a, 0xb23a, 0xb513013e6431); + B_TYPE_EXTENDS(B_TYPE_ITERATOR); + B_TYPE_CLASS(b_list_iterator_class); + B_TYPE_INSTANCE_PRIVATE(struct b_list_iterator_p); +B_TYPE_DEFINITION_END(b_list_iterator)