src/ucx/cx/iterator.h

changeset 438
22eca559aded
parent 415
d938228c382e
child 490
d218607f5a7e
--- 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

mercurial