diff -r 16e2a3391e88 -r d4baf4dd55c3 src/cx/iterator.h --- a/src/cx/iterator.h Thu May 23 18:21:36 2024 +0200 +++ b/src/cx/iterator.h Thu May 23 19:29:14 2024 +0200 @@ -38,68 +38,64 @@ #include "common.h" +#define CX_ITERATOR_BASE \ + /** \ + * True iff the iterator points to valid data. \ + */ \ + __attribute__ ((__nonnull__)) \ + bool (*valid)(void const *); \ + /** \ + * Returns a pointer to the current element. \ + * \ + * When valid returns false, the behavior of this function is undefined. \ + */ \ + __attribute__ ((__nonnull__)) \ + void *(*current)(void const *); \ + /** \ + * Original implementation in case the function needs to be wrapped. \ + */ \ + __attribute__ ((__nonnull__)) \ + void *(*current_impl)(void const *); \ + /** \ + * Advances the iterator. \ + * \ + * When valid returns false, the behavior of this function is undefined. \ + */ \ + __attribute__ ((__nonnull__)) \ + void (*next)(void *); \ + /** \ + * Indicates whether this iterator may remove elements. \ + */ \ + bool mutating; \ + /** \ + * Internal flag for removing the current element when advancing. \ + */ \ + bool remove; + /** - * The base of mutating and non-mutating iterators. + * Internal iterator struct - use CxIterator. */ -struct cx_iterator_base_s { - /** - * True iff the iterator points to valid data. - */ - __attribute__ ((__nonnull__)) - bool (*valid)(void const *); +struct cx_iterator_s { + CX_ITERATOR_BASE /** - * Returns a pointer to the current element. - * - * When valid returns false, the behavior of this function is undefined. - */ - __attribute__ ((__nonnull__)) - void *(*current)(void const *); - - /** - * Original implementation in case the function needs to be wrapped. - */ - __attribute__ ((__nonnull__)) - void *(*current_impl)(void const *); - - /** - * Advances the iterator. - * - * When valid returns false, the behavior of this function is undefined. - */ - __attribute__ ((__nonnull__)) - void (*next)(void *); - - /** - * Indicates whether this iterator may remove elements. - */ - 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. + * Handle for the current element. */ void *elem_handle; /** * Handle for the source collection, if any. */ - void *src_handle; + union { + /** + * Access for mutating iterators. + */ + void *m; + /** + * Access for normal iterators. + */ + void const *c; + } src_handle; /** * Field for storing a key-value pair. @@ -141,91 +137,15 @@ }; /** - * Mutating iterator value type. + * Iterator 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; - - /** - * 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. - */ - 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; - - /** - * The size of an individual element. - */ - size_t elem_size; - - /** - * May contain the total number of elements, if known. - * Shall be set to \c SIZE_MAX when the total number is unknown during iteration. - */ - size_t elem_count; -}; - -/** - * Iterator value type. * An iterator points to a certain element in a (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 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 makes this iterator invalid (regardless of what cxIteratorValid() returns). - * - * @see CxMutIterator + * any concurrent mutation of the collection other than by this iterator makes this iterator invalid + * and it must not be used anymore. */ typedef struct cx_iterator_s CxIterator; @@ -237,7 +157,7 @@ * @param iter the iterator * @return true iff the iterator points to valid data */ -#define cxIteratorValid(iter) (iter).base.valid(&(iter)) +#define cxIteratorValid(iter) (iter).valid(&(iter)) /** * Returns a pointer to the current element. @@ -247,21 +167,21 @@ * @param iter the iterator * @return a pointer to the current element */ -#define cxIteratorCurrent(iter) (iter).base.current(&iter) +#define cxIteratorCurrent(iter) (iter).current(&iter) /** * Advances the iterator to the next element. * * @param iter the iterator */ -#define cxIteratorNext(iter) (iter).base.next(&iter) +#define cxIteratorNext(iter) (iter).next(&iter) /** * Flags the current element for removal, if this iterator is mutating. * * @param iter the iterator */ -#define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating +#define cxIteratorFlagRemoval(iter) (iter).remove |= (iter).mutating /** * Loops over an iterator. @@ -316,7 +236,7 @@ * @return an iterator for the specified array */ __attribute__((__warn_unused_result__)) -CxMutIterator cxMutIterator( +CxIterator cxMutIterator( void *array, size_t elem_size, size_t elem_count,