diff --git a/core/include/blue/core/iterator.h b/core/include/blue/core/iterator.h index 8114a37..16ce7a8 100644 --- a/core/include/blue/core/iterator.h +++ b/core/include/blue/core/iterator.h @@ -1,26 +1,63 @@ -#ifndef BLUELIB_CORE_ITERATOR_H_ -#define BLUELIB_CORE_ITERATOR_H_ +#ifndef BLUE_CORE_ITERATOR_H_ +#define BLUE_CORE_ITERATOR_H_ -#include +#include #include +#include #include -struct b_iterator; +B_DECLS_BEGIN; -typedef struct b_iterator_ops { - b_status (*it_close)(struct b_iterator *); - bool (*it_next)(struct b_iterator *); - b_status (*it_erase)(struct b_iterator *); - bool (*it_is_valid)(const struct b_iterator *); -} b_iterator_ops; +#define b_foreach(type, var, iterator) \ + for (type var = (type)b_iterator_value(iterator).v_int; var != NULL; \ + b_iterator_next(iterator), \ + var = (type)b_iterator_value(iterator).v_int) -typedef struct b_iterator { - const b_iterator_ops *it_ops; -} b_iterator; +#define B_ITERATOR_VALUE_INT(v) ((b_iterator_value) {.v_int = (v)}) +#define B_ITERATOR_VALUE_PTR(v) ((b_iterator_value) {.v_ptr = (v)}) +#define B_ITERATOR_VALUE_CPTR(v) ((const b_iterator_value) {.v_cptr = (v)}) +#define B_ITERATOR_VALUE_NULL ((b_iterator_value) {}) +#define B_ITERATOR_VALUE_IS_NULL(v) ((v)->v_ptr == NULL) -BLUE_API b_status b_iterator_close(b_iterator *it); -BLUE_API bool b_iterator_next(b_iterator *it); +#define B_TYPE_ITERATOR (b_iterator_get_type()) +#define B_TYPE_ITERABLE (b_iterable_get_type()) + +typedef union b_iterator_value { + uintptr_t v_int; + void *v_ptr; + const void *v_cptr; +} b_iterator_value; + +B_DECLARE_TYPE(b_iterator); +B_DECLARE_TYPE(b_iterable); + +B_TYPE_CLASS_DECLARATION_BEGIN(b_iterator) + b_status (*it_move_next)(const b_iterator *); + b_status (*it_erase)(b_iterator *); + b_iterator_value (*it_get_value)(b_iterator *); + const b_iterator_value (*it_get_cvalue)(const b_iterator *); +B_TYPE_CLASS_DECLARATION_END(b_iterator) + +B_TYPE_CLASS_DECLARATION_BEGIN(b_iterable) + b_iterator *(*it_begin)(b_iterable *); + const b_iterator *(*it_cbegin)(const b_iterable *); +B_TYPE_CLASS_DECLARATION_END(b_iterable) + +BLUE_API b_type b_iterator_get_type(void); +BLUE_API b_type b_iterable_get_type(void); + +BLUE_API b_iterator *b_iterator_begin(b_iterable *it); +BLUE_API const b_iterator *b_iterator_cbegin(const b_iterable *it); + +BLUE_API b_status b_iterator_get_status(const b_iterator *it); +BLUE_API b_status b_iterator_set_status(const b_iterator *it, b_status status); + +BLUE_API b_status b_iterator_next(const b_iterator *it); +BLUE_API b_iterator_value b_iterator_get_value(b_iterator *it); +BLUE_API const b_iterator_value b_iterator_get_cvalue(const b_iterator *it); BLUE_API b_status b_iterator_erase(b_iterator *it); -BLUE_API bool b_iterator_is_valid(const b_iterator *it); +BLUE_API b_status b_iterator_is_valid(const b_iterator *it); + +B_DECLS_END; #endif diff --git a/core/iterator.c b/core/iterator.c index c1f9b5e..a365a7c 100644 --- a/core/iterator.c +++ b/core/iterator.c @@ -1,37 +1,97 @@ #include -b_status b_iterator_cleanup(struct b_iterator *it) -{ - if (it->it_ops && it->it_ops->it_close) { - return it->it_ops->it_close(it); - } +/*** PRIVATE DATA *************************************************************/ +struct b_iterator_p { + enum b_status it_status; +}; + +/*** PRIVATE FUNCTIONS ********************************************************/ + +static enum b_status iterator_get_status(const struct b_iterator_p *it) +{ + return it->it_status; +} + +static enum b_status iterator_set_status(struct b_iterator_p *it, b_status status) +{ + it->it_status = status; return B_SUCCESS; } -bool b_iterator_next(struct b_iterator *it) -{ - if (it->it_ops && it->it_ops->it_next) { - return it->it_ops->it_next(it); - } +/*** PUBLIC FUNCTIONS *********************************************************/ - return false; +b_iterator *b_iterator_begin(b_iterable *it) +{ + B_CLASS_DISPATCH_VIRTUAL_0(b_iterable, B_TYPE_ITERABLE, NULL, it_begin, it); } -b_status b_iterator_erase(struct b_iterator *it) +const b_iterator *b_iterator_cbegin(const b_iterable *it) { - if (it->it_ops && it->it_ops->it_erase) { - return it->it_ops->it_erase(it); - } - - return B_ERR_NOT_SUPPORTED; + B_CLASS_DISPATCH_VIRTUAL_0(b_iterable, B_TYPE_ITERABLE, NULL, it_cbegin, it); } -bool b_iterator_is_valid(const struct b_iterator *it) +enum b_status b_iterator_get_status(const b_iterator *it) { - if (it->it_ops && it->it_ops->it_is_valid) { - return it->it_ops->it_is_valid(it); - } - - return false; + B_CLASS_DISPATCH_STATIC_0(B_TYPE_ITERATOR, iterator_get_status, it); } + +enum b_status b_iterator_set_status(const b_iterator *it, b_status status) +{ + B_CLASS_DISPATCH_STATIC(B_TYPE_ITERATOR, iterator_set_status, it, status); +} + +b_status b_iterator_move_next(b_iterator *it) +{ + B_CLASS_DISPATCH_VIRTUAL_0( + b_iterator, B_TYPE_ITERATOR, B_ERR_NOT_SUPPORTED, it_move_next, it); +} + +b_iterator_value b_iterator_get_value(b_iterator *it) +{ + B_CLASS_DISPATCH_VIRTUAL_0( + b_iterator, B_TYPE_ITERATOR, B_ITERATOR_VALUE_NULL, + it_get_value, it); +} + +const b_iterator_value b_iterator_get_cvalue(const b_iterator *it) +{ + B_CLASS_DISPATCH_VIRTUAL_0( + b_iterator, B_TYPE_ITERATOR, B_ITERATOR_VALUE_NULL, + it_get_cvalue, it); +} + +b_status b_iterator_erase(b_iterator *it) +{ + B_CLASS_DISPATCH_VIRTUAL_0( + b_iterator, B_TYPE_ITERATOR, B_ERR_NOT_SUPPORTED, it_erase, it); +} + +/*** CLASS DEFINITION *********************************************************/ + +// ---- b_iterator DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_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_DEFINITION_END(b_iterator) + +B_TYPE_DEFINITION_BEGIN(b_iterator) + B_TYPE_FLAGS(B_TYPE_F_ABSTRACT); + B_TYPE_ID(0xfd40b67f, 0x7087, 0x40a9, 0x8fd8, 0x8ae27bd58c9e); + B_TYPE_CLASS(b_iterator_class); + B_TYPE_INSTANCE_PRIVATE(struct b_iterator_p); +B_TYPE_DEFINITION_END(b_iterator) + +// ---- b_iterable DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_iterable) + 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_iterable) + +B_TYPE_DEFINITION_BEGIN(b_iterable) + B_TYPE_FLAGS(B_TYPE_F_ABSTRACT); + B_TYPE_ID(0x4bbabf2d, 0xfc5d, 0x40cc, 0x89fc, 0x164085e47f73); + B_TYPE_CLASS(b_iterable_class); +B_TYPE_DEFINITION_END(b_iterable)