From d8abd54b8922192a886e2c0c8be2f74b66cd4adb Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 29 Oct 2025 14:34:38 +0000 Subject: [PATCH] ds: array: update iterator interface --- ds/array.c | 156 +++++++++++++++++++++++++------------ ds/include/blue/ds/array.h | 80 ++----------------- 2 files changed, 114 insertions(+), 122 deletions(-) diff --git a/ds/array.c b/ds/array.c index 754ed08..2dc9b8c 100644 --- a/ds/array.c +++ b/ds/array.c @@ -15,6 +15,16 @@ struct b_array_p { b_object **ar_data; }; +struct b_array_iterator_p { + b_array *_a; + struct b_array_p *_a_p; + + /** The index of the current value */ + size_t i; + /** The current value */ + b_object *value; +}; + /*** PRIVATE FUNCTIONS ********************************************************/ static b_status resize_array(struct b_array_p *array, size_t new_capacity) @@ -347,52 +357,16 @@ static void array_to_string(const b_object *obj, b_stream *out) b_stream_write_char(out, ']'); } -/*** CLASS DEFINITION *********************************************************/ - -B_TYPE_CLASS_DEFINITION_BEGIN(b_array) - B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) - B_INTERFACE_ENTRY(to_string) = array_to_string; - B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) -B_TYPE_CLASS_DEFINITION_END(b_array) - -B_TYPE_DEFINITION_BEGIN(b_array) - B_TYPE_ID(0xe3c46da1, 0x5f37, 0x4e44, 0xb53b, 0xff5a6200191b); - B_TYPE_CLASS(b_array_class); - B_TYPE_INSTANCE_PRIVATE(struct b_array_p); - B_TYPE_INSTANCE_INIT(array_init); - B_TYPE_INSTANCE_FINI(array_fini); -B_TYPE_DEFINITION_END(b_array) - /*** ITERATOR FUNCTIONS *******************************************************/ -static bool array_iterator_next(struct b_iterator *it) +static b_iterator *iterable_begin(b_object *obj) { - return b_array_iterator_next((struct b_array_iterator *)it); -} - -static b_status array_iterator_erase(struct b_iterator *it) -{ - return b_array_iterator_erase((struct b_array_iterator *)it); -} - -static bool array_iterator_is_valid(const struct b_iterator *it) -{ - return b_array_iterator_is_valid((const struct b_array_iterator *)it); -} - -static b_iterator_ops it_ops = { - .it_next = array_iterator_next, - .it_close = NULL, - .it_erase = array_iterator_erase, - .it_is_valid = array_iterator_is_valid, -}; - -int b_array_iterator_begin(b_array *array, struct b_array_iterator *it) -{ - it->_a = array; - it->_a_p = b_object_get_private(array, B_TYPE_ARRAY); + b_array_iterator *it_obj = b_object_create(B_TYPE_ARRAY_ITERATOR); + struct b_array_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_ARRAY_ITERATOR); + it->_a = obj; + it->_a_p = b_object_get_private(obj, B_TYPE_ARRAY); it->i = 0; - it->_base.it_ops = &it_ops; if (it->_a_p->ar_len > 0) { it->value = it->_a_p->ar_data[0]; @@ -400,11 +374,31 @@ int b_array_iterator_begin(b_array *array, struct b_array_iterator *it) it->value = NULL; } - return 0; + return it_obj; } -bool b_array_iterator_next(struct b_array_iterator *it) +static const b_iterator *iterable_cbegin(const b_object *obj) { + b_array_iterator *it_obj = b_object_create(B_TYPE_ARRAY_ITERATOR); + struct b_array_iterator_p *it + = b_object_get_private(it_obj, B_TYPE_ARRAY_ITERATOR); + it->_a = (b_array *)obj; + it->_a_p = b_object_get_private(obj, B_TYPE_ARRAY); + it->i = 0; + + if (it->_a_p->ar_len > 0) { + it->value = it->_a_p->ar_data[0]; + } else { + it->value = NULL; + } + + return it_obj; +} + +static enum b_status iterator_move_next(const b_iterator *obj) +{ + struct b_array_iterator_p *it + = b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR); struct b_array_p *array = it->_a_p; if (it->value == NULL || it->i >= array->ar_len) { @@ -419,12 +413,15 @@ bool b_array_iterator_next(struct b_array_iterator *it) it->value = array->ar_data[it->i]; } - return it->value != NULL; + return (it->value != NULL) ? B_SUCCESS : B_ERR_NO_DATA; } -b_status b_array_iterator_erase(struct b_array_iterator *it) +static enum b_status iterator_erase(b_iterator *obj) { + struct b_array_iterator_p *it + = b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR); struct b_array_p *array = it->_a_p; + if (it->i >= array->ar_len) { return B_ERR_OUT_OF_BOUNDS; } @@ -444,9 +441,28 @@ b_status b_array_iterator_erase(struct b_array_iterator *it) return B_SUCCESS; } -bool b_array_iterator_is_valid(const struct b_array_iterator *it) +static b_iterator_value iterator_get_value(b_iterator *obj) { + struct b_array_iterator_p *it + = b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR); + + return B_ITERATOR_VALUE_PTR(it->value); +} + +static const b_iterator_value iterator_get_cvalue(const b_iterator *obj) +{ + struct b_array_iterator_p *it + = b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR); + + return B_ITERATOR_VALUE_CPTR(it->value); +} + +static enum b_status iterator_is_valid(const b_iterator *obj) +{ + struct b_array_iterator_p *it + = b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR); struct b_array_p *array = it->_a_p; + if (it->i >= array->ar_len) { return false; } @@ -455,5 +471,49 @@ bool b_array_iterator_is_valid(const struct b_array_iterator *it) return false; } - return it->value != NULL; + return (it->value != NULL) ? B_SUCCESS : B_ERR_NO_DATA; } + +/*** CLASS DEFINITION *********************************************************/ + +// ---- b_array DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_array) + B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) + B_INTERFACE_ENTRY(to_string) = array_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_array) + +B_TYPE_DEFINITION_BEGIN(b_array) + B_TYPE_ID(0xe3c46da1, 0x5f37, 0x4e44, 0xb53b, 0xff5a6200191b); + B_TYPE_CLASS(b_array_class); + B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE); + B_TYPE_INSTANCE_PRIVATE(struct b_array_p); + B_TYPE_INSTANCE_INIT(array_init); + B_TYPE_INSTANCE_FINI(array_fini); +B_TYPE_DEFINITION_END(b_array) + +// ---- b_array_iterator DEFINITION +B_TYPE_CLASS_DEFINITION_BEGIN(b_array_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_array_iterator) + +B_TYPE_DEFINITION_BEGIN(b_array_iterator) + B_TYPE_ID(0xe5e9e8b8, 0x14cb, 0x4192, 0x8138, 0xf45238a2ae73); + B_TYPE_EXTENDS(B_TYPE_ITERATOR); + B_TYPE_CLASS(b_array_iterator_class); + B_TYPE_INSTANCE_PRIVATE(struct b_array_iterator_p); +B_TYPE_DEFINITION_END(b_array_iterator) diff --git a/ds/include/blue/ds/array.h b/ds/include/blue/ds/array.h index 8ab76f7..6ab6cd0 100644 --- a/ds/include/blue/ds/array.h +++ b/ds/include/blue/ds/array.h @@ -16,50 +16,22 @@ B_DECLS_BEGIN; -#define B_TYPE_ARRAY (b_array_get_type()) +#define B_TYPE_ARRAY (b_array_get_type()) +#define B_TYPE_ARRAY_ITERATOR (b_array_iterator_get_type()) struct b_array_p; B_DECLARE_TYPE(b_array); +B_DECLARE_TYPE(b_array_iterator); B_TYPE_CLASS_DECLARATION_BEGIN(b_array) B_TYPE_CLASS_DECLARATION_END(b_array) -/** - * Iterate through each object in an b_array. - * - * This should be used for read-only iterations only. Adding or removing objects - * while iterating though an array using b_array_foreach is NOT supported. - * - * @param it A pointer to an b_array_iterator. This iterator will contain the - * current object reference for the current loop iteration. - * @param array A pointer to the b_array to iterate over. - */ -#define b_array_foreach(it, array) \ - for (int z__b_unique_name() = b_array_iterator_begin(array, it); \ - (it)->value != NULL; b_array_iterator_next(it)) - -/** - * Iterator for traversing the contents of an b_array. - * - * The iterator provides the current b_object `value`, as well - * as the index `i` of that value within the array. - * - * Any members whose names begin with _ (underscore) are reserved - * and should not be accessed. - */ -typedef struct b_array_iterator { - b_iterator _base; - b_array *_a; - struct b_array_p *_a_p; - - /** The index of the current value */ - size_t i; - /** The current value */ - b_object *value; -} b_array_iterator; +B_TYPE_CLASS_DECLARATION_BEGIN(b_array_iterator) +B_TYPE_CLASS_DECLARATION_END(b_array_iterator) BLUE_API b_type b_array_get_type(void); +BLUE_API b_type b_array_iterator_get_type(void); B_TYPE_DEFAULT_CONSTRUCTOR(b_array, B_TYPE_ARRAY); @@ -241,46 +213,6 @@ BLUE_API size_t b_array_size(const b_array *array); */ BLUE_API size_t b_array_capacity(const b_array *array); -/** - * Initialise an b_array_iterator to pointer to the first object in an b_array. - * If the b_array is empty, then `it` will be an invalid iterator. - * - * @param array - * @param it - * @return Always returns 0. - */ -BLUE_API int b_array_iterator_begin(b_array *array, b_array_iterator *it); - -/** - * Advances an b_array_iterator to pointer to the next object in an b_array. - * @param it The iterator to advance. - * @return True if the iterator contains a valid reference to an object, or - * False if the iterator has gone past the end of the array. - */ -BLUE_API bool b_array_iterator_next(b_array_iterator *it); - -/** - * Removes the object pointed to by an b_array_iterator from its container - * b_array, and advances the iterator to the next object in the b_array. - * - * The reference count of the removed object will be decremented. - * - * @param it The iterator whose object should be removed. - * @return B_SUCCESS if the object was removed, or a status code describing the error that occurred. - */ -BLUE_API b_status b_array_iterator_erase(b_array_iterator *it); - -/** - * Checks whether or not an iterator contains a valid reference to an object. - * An iterator will become invalid if it has moved past the end of the b_array - * it was iterating across, or if b_array_iterator_erase() was called on an - * iterator pointing to the last object in an b_array. - * - * @param it The iterator to check. - * @return True if the iterator is valid. False otherwise. - */ -BLUE_API bool b_array_iterator_is_valid(const b_array_iterator *it); - B_DECLS_END; #endif