--- a/src/ucx/cx/iterator.h Sun Nov 20 12:43:44 2022 +0100 +++ b/src/ucx/cx/iterator.h Sat Nov 26 17:07:08 2022 +0100 @@ -40,26 +40,53 @@ #include "common.h" /** - * Internal iterator struct - use CxIterator. + * The base of mutating and non-mutating iterators. */ -struct cx_iterator_s { +struct cx_iterator_base_s { /** * True iff the iterator points to valid data. */ __attribute__ ((__nonnull__)) - bool (*valid)(struct cx_iterator_s const *); + bool (*valid)(void const *); /** * Returns a pointer to the current element. */ __attribute__ ((__nonnull__)) - void *(*current)(struct cx_iterator_s const *); + void *(*current)(void const *); /** * Advances the iterator. */ __attribute__ ((__nonnull__)) - void (*next)(struct cx_iterator_s *); + void (*next)(void *); + + /** + * Flag current element for removal, if possible. + */ + __attribute__ ((__nonnull__)) + bool (*flag_removal)(void *); + + /** + * Indicates whether this iterator is muting. + */ + bool mutating; + + /** + * Internal flag for removing the current element when advancing. + */ + bool remove; +}; + +/** + * Internal iterator struct - use CxMutIterator. + */ +struct cx_mut_iterator_s { + + /** + * The base properties of this iterator. + */ + struct cx_iterator_base_s base; /** * Handle for the current element, if required. @@ -79,7 +106,7 @@ /** * A pointer to the key. */ - void *key; + void const *key; /** * A pointer to the value. */ @@ -97,13 +124,70 @@ * Otherwise, this field is usually uninitialized. */ size_t index; +}; + +/** + * Mutating iterator value type. + * + * An iterator points to a certain element in an (possibly unbounded) chain of elements. + * Iterators that are based on collections (which have a defined "first" element), are supposed + * to be "position-aware", which means that they keep track of the current index within the collection. + * + * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the + * iterator is based on a collection and the underlying collection is mutated by other means than this iterator + * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns) + * and MUST be re-obtained from the collection. + * + * @see CxIterator + */ +typedef struct cx_mut_iterator_s CxMutIterator; + +/** + * Internal iterator struct - use CxIterator. + */ +struct cx_iterator_s { + + /** + * The base properties of this iterator. + */ + struct cx_iterator_base_s base; /** - * Users may set this to true, if the current element shall be removed from the underlying collection - * when the iterator advances. - * Has no effect on iterators that are not based on a collection. + * Handle for the current element, if required. + */ + void *elem_handle; + + /** + * Handle for the source collection, if any. + */ + void const *src_handle; + + /** + * Field for storing a key-value pair. + * May be used by iterators that iterate over k/v-collections. */ - bool remove; + struct { + /** + * A pointer to the key. + */ + void const *key; + /** + * A pointer to the value. + */ + void *value; + } kv_data; + + /** + * Field for storing a slot number. + * May be used by iterators that iterate over multi-bucket collections. + */ + size_t slot; + + /** + * If the iterator is position-aware, contains the index of the element in the underlying collection. + * Otherwise, this field is usually uninitialized. + */ + size_t index; }; /** @@ -112,10 +196,11 @@ * Iterators that are based on collections (which have a defined "first" element), are supposed * to be "position-aware", which means that they keep track of the current index within the collection. * - * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the - * iterator is based on a collection and the underlying collection is mutated (elements added or removed), - * the iterator becomes invalid (regardless of what cxIteratorValid() returns) and MUST be re-obtained - * from the collection. + * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, + * this iterator cannot mutate the collection itself (add or remove elements) and any mutation of the + * collection by other means make this iterator invalid (regardless of what cxIteratorValid() returns). + * + * @see CxMutIterator */ typedef struct cx_iterator_s CxIterator; @@ -124,36 +209,35 @@ * * This is especially false for past-the-end iterators. * - * @param iter a pointer to the iterator + * @param iter the iterator * @return true iff the iterator points to valid data */ -__attribute__ ((__nonnull__)) -static inline bool cxIteratorValid(CxIterator const *iter) { - return iter->valid(iter); -} +#define cxIteratorValid(iter) (iter).base.valid(&(iter)) /** * Returns a pointer to the current element. * * The behavior is undefined if this iterator is invalid. * - * @param iter a pointer to the iterator + * @param iter the iterator * @return a pointer to the current element */ -__attribute__ ((__nonnull__)) -static inline void *cxIteratorCurrent(CxIterator const *iter) { - return iter->current(iter); -} +#define cxIteratorCurrent(iter) (iter).base.current(&iter) /** * Advances the iterator to the next element. * - * @param iter a pointer to the iterator + * @param iter the iterator */ -__attribute__ ((__nonnull__)) -static inline void cxIteratorNext(CxIterator *iter) { - iter->next(iter); -} +#define cxIteratorNext(iter) (iter).base.next(&iter) + +/** + * Flags the current element for removal. + * + * @param iter the iterator + * @return false if this iterator cannot remove the element + */ +#define cxIteratorFlagRemoval(iter) (iter).base.flag_removal(&iter) /** * Loops over an iterator. @@ -162,6 +246,6 @@ * @param iter the iterator */ #define cx_foreach(type, elem, iter) \ -for (type elem; cxIteratorValid(&iter) && (elem = (type)cxIteratorCurrent(&iter)) != NULL ; cxIteratorNext(&iter)) // NOLINT(bugprone-macro-parentheses) +for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter)) -#endif /* UCX_ITERATOR_H */ +#endif // UCX_ITERATOR_H