1.1 --- a/src/cx/iterator.h Thu May 23 18:21:36 2024 +0200 1.2 +++ b/src/cx/iterator.h Thu May 23 19:29:14 2024 +0200 1.3 @@ -38,68 +38,64 @@ 1.4 1.5 #include "common.h" 1.6 1.7 +#define CX_ITERATOR_BASE \ 1.8 + /** \ 1.9 + * True iff the iterator points to valid data. \ 1.10 + */ \ 1.11 + __attribute__ ((__nonnull__)) \ 1.12 + bool (*valid)(void const *); \ 1.13 + /** \ 1.14 + * Returns a pointer to the current element. \ 1.15 + * \ 1.16 + * When valid returns false, the behavior of this function is undefined. \ 1.17 + */ \ 1.18 + __attribute__ ((__nonnull__)) \ 1.19 + void *(*current)(void const *); \ 1.20 + /** \ 1.21 + * Original implementation in case the function needs to be wrapped. \ 1.22 + */ \ 1.23 + __attribute__ ((__nonnull__)) \ 1.24 + void *(*current_impl)(void const *); \ 1.25 + /** \ 1.26 + * Advances the iterator. \ 1.27 + * \ 1.28 + * When valid returns false, the behavior of this function is undefined. \ 1.29 + */ \ 1.30 + __attribute__ ((__nonnull__)) \ 1.31 + void (*next)(void *); \ 1.32 + /** \ 1.33 + * Indicates whether this iterator may remove elements. \ 1.34 + */ \ 1.35 + bool mutating; \ 1.36 + /** \ 1.37 + * Internal flag for removing the current element when advancing. \ 1.38 + */ \ 1.39 + bool remove; 1.40 + 1.41 /** 1.42 - * The base of mutating and non-mutating iterators. 1.43 + * Internal iterator struct - use CxIterator. 1.44 */ 1.45 -struct cx_iterator_base_s { 1.46 - /** 1.47 - * True iff the iterator points to valid data. 1.48 - */ 1.49 - __attribute__ ((__nonnull__)) 1.50 - bool (*valid)(void const *); 1.51 +struct cx_iterator_s { 1.52 + CX_ITERATOR_BASE 1.53 1.54 /** 1.55 - * Returns a pointer to the current element. 1.56 - * 1.57 - * When valid returns false, the behavior of this function is undefined. 1.58 - */ 1.59 - __attribute__ ((__nonnull__)) 1.60 - void *(*current)(void const *); 1.61 - 1.62 - /** 1.63 - * Original implementation in case the function needs to be wrapped. 1.64 - */ 1.65 - __attribute__ ((__nonnull__)) 1.66 - void *(*current_impl)(void const *); 1.67 - 1.68 - /** 1.69 - * Advances the iterator. 1.70 - * 1.71 - * When valid returns false, the behavior of this function is undefined. 1.72 - */ 1.73 - __attribute__ ((__nonnull__)) 1.74 - void (*next)(void *); 1.75 - 1.76 - /** 1.77 - * Indicates whether this iterator may remove elements. 1.78 - */ 1.79 - bool mutating; 1.80 - 1.81 - /** 1.82 - * Internal flag for removing the current element when advancing. 1.83 - */ 1.84 - bool remove; 1.85 -}; 1.86 - 1.87 -/** 1.88 - * Internal iterator struct - use CxMutIterator. 1.89 - */ 1.90 -struct cx_mut_iterator_s { 1.91 - 1.92 - /** 1.93 - * The base properties of this iterator. 1.94 - */ 1.95 - struct cx_iterator_base_s base; 1.96 - 1.97 - /** 1.98 - * Handle for the current element, if required. 1.99 + * Handle for the current element. 1.100 */ 1.101 void *elem_handle; 1.102 1.103 /** 1.104 * Handle for the source collection, if any. 1.105 */ 1.106 - void *src_handle; 1.107 + union { 1.108 + /** 1.109 + * Access for mutating iterators. 1.110 + */ 1.111 + void *m; 1.112 + /** 1.113 + * Access for normal iterators. 1.114 + */ 1.115 + void const *c; 1.116 + } src_handle; 1.117 1.118 /** 1.119 * Field for storing a key-value pair. 1.120 @@ -141,91 +137,15 @@ 1.121 }; 1.122 1.123 /** 1.124 - * Mutating iterator value type. 1.125 + * Iterator type. 1.126 * 1.127 - * An iterator points to a certain element in an (possibly unbounded) chain of elements. 1.128 - * Iterators that are based on collections (which have a defined "first" element), are supposed 1.129 - * to be "position-aware", which means that they keep track of the current index within the collection. 1.130 - * 1.131 - * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the 1.132 - * iterator is based on a collection and the underlying collection is mutated by other means than this iterator 1.133 - * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns) 1.134 - * and MUST be re-obtained from the collection. 1.135 - * 1.136 - * @see CxIterator 1.137 - */ 1.138 -typedef struct cx_mut_iterator_s CxMutIterator; 1.139 - 1.140 -/** 1.141 - * Internal iterator struct - use CxIterator. 1.142 - */ 1.143 -struct cx_iterator_s { 1.144 - 1.145 - /** 1.146 - * The base properties of this iterator. 1.147 - */ 1.148 - struct cx_iterator_base_s base; 1.149 - 1.150 - /** 1.151 - * Handle for the current element, if required. 1.152 - */ 1.153 - void *elem_handle; 1.154 - 1.155 - /** 1.156 - * Handle for the source collection, if any. 1.157 - */ 1.158 - void const *src_handle; 1.159 - 1.160 - /** 1.161 - * Field for storing a key-value pair. 1.162 - * May be used by iterators that iterate over k/v-collections. 1.163 - */ 1.164 - struct { 1.165 - /** 1.166 - * A pointer to the key. 1.167 - */ 1.168 - void const *key; 1.169 - /** 1.170 - * A pointer to the value. 1.171 - */ 1.172 - void *value; 1.173 - } kv_data; 1.174 - 1.175 - /** 1.176 - * Field for storing a slot number. 1.177 - * May be used by iterators that iterate over multi-bucket collections. 1.178 - */ 1.179 - size_t slot; 1.180 - 1.181 - /** 1.182 - * If the iterator is position-aware, contains the index of the element in the underlying collection. 1.183 - * Otherwise, this field is usually uninitialized. 1.184 - */ 1.185 - size_t index; 1.186 - 1.187 - /** 1.188 - * The size of an individual element. 1.189 - */ 1.190 - size_t elem_size; 1.191 - 1.192 - /** 1.193 - * May contain the total number of elements, if known. 1.194 - * Shall be set to \c SIZE_MAX when the total number is unknown during iteration. 1.195 - */ 1.196 - size_t elem_count; 1.197 -}; 1.198 - 1.199 -/** 1.200 - * Iterator value type. 1.201 * An iterator points to a certain element in a (possibly unbounded) chain of elements. 1.202 * Iterators that are based on collections (which have a defined "first" element), are supposed 1.203 * to be "position-aware", which means that they keep track of the current index within the collection. 1.204 * 1.205 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, 1.206 - * this iterator cannot mutate the collection itself (add or remove elements) and any mutation of the 1.207 - * collection by other means makes this iterator invalid (regardless of what cxIteratorValid() returns). 1.208 - * 1.209 - * @see CxMutIterator 1.210 + * any concurrent mutation of the collection other than by this iterator makes this iterator invalid 1.211 + * and it must not be used anymore. 1.212 */ 1.213 typedef struct cx_iterator_s CxIterator; 1.214 1.215 @@ -237,7 +157,7 @@ 1.216 * @param iter the iterator 1.217 * @return true iff the iterator points to valid data 1.218 */ 1.219 -#define cxIteratorValid(iter) (iter).base.valid(&(iter)) 1.220 +#define cxIteratorValid(iter) (iter).valid(&(iter)) 1.221 1.222 /** 1.223 * Returns a pointer to the current element. 1.224 @@ -247,21 +167,21 @@ 1.225 * @param iter the iterator 1.226 * @return a pointer to the current element 1.227 */ 1.228 -#define cxIteratorCurrent(iter) (iter).base.current(&iter) 1.229 +#define cxIteratorCurrent(iter) (iter).current(&iter) 1.230 1.231 /** 1.232 * Advances the iterator to the next element. 1.233 * 1.234 * @param iter the iterator 1.235 */ 1.236 -#define cxIteratorNext(iter) (iter).base.next(&iter) 1.237 +#define cxIteratorNext(iter) (iter).next(&iter) 1.238 1.239 /** 1.240 * Flags the current element for removal, if this iterator is mutating. 1.241 * 1.242 * @param iter the iterator 1.243 */ 1.244 -#define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating 1.245 +#define cxIteratorFlagRemoval(iter) (iter).remove |= (iter).mutating 1.246 1.247 /** 1.248 * Loops over an iterator. 1.249 @@ -316,7 +236,7 @@ 1.250 * @return an iterator for the specified array 1.251 */ 1.252 __attribute__((__warn_unused_result__)) 1.253 -CxMutIterator cxMutIterator( 1.254 +CxIterator cxMutIterator( 1.255 void *array, 1.256 size_t elem_size, 1.257 size_t elem_count,