1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 /** 29 * \file iterator.h 30 * \brief Interface for iterator implementations. 31 * \author Mike Becker 32 * \author Olaf Wintermann 33 * \version 3.0 34 * \copyright 2-Clause BSD License 35 */ 36 37 #ifndefUCX_ITERATOR_H 38 #defineUCX_ITERATOR_H 39 40 #include"common.h" 41 42 /** 43 * The base of mutating and non-mutating iterators. 44 */ 45 struct cx_iterator_base_s {
46 /** 47 * True iff the iterator points to valid data. 48 */ 49 __attribute__ ((__nonnull__))
50 bool (*valid)(voidconst *);
51 52 /** 53 * Returns a pointer to the current element. 54 * 55 * When valid returns false, the behavior of this function is undefined. 56 */ 57 __attribute__ ((__nonnull__))
58 void *(*current)(voidconst *);
59 60 /** 61 * Original implementation in case the function needs to be wrapped. 62 */ 63 __attribute__ ((__nonnull__))
64 void *(*current_impl)(voidconst *);
65 66 /** 67 * Advances the iterator. 68 * 69 * When valid returns false, the behavior of this function is undefined. 70 */ 71 __attribute__ ((__nonnull__))
72 void (*next)(void *);
73 74 /** 75 * Flag current element for removal, if possible. 76 * 77 * When valid returns false, the behavior of this function is undefined. 78 */ 79 __attribute__ ((__nonnull__))
80 bool (*flag_removal)(void *);
81 82 /** 83 * Indicates whether this iterator may remove elements. 84 */ 85 bool mutating;
86 87 /** 88 * Internal flag for removing the current element when advancing. 89 */ 90 bool remove;
91 };
92 93 /** 94 * Internal iterator struct - use CxMutIterator. 95 */ 96 struct cx_mut_iterator_s {
97 98 /** 99 * The base properties of this iterator.100 */101 struct cx_iterator_base_s base;
102 103 /**104 * Handle for the current element, if required.105 */106 void *elem_handle;
107 108 /**109 * Handle for the source collection, if any.110 */111 void *src_handle;
112 113 /**114 * Field for storing a key-value pair.115 * May be used by iterators that iterate over k/v-collections.116 */117 struct {
118 /**119 * A pointer to the key.120 */121 voidconst *key;
122 /**123 * A pointer to the value.124 */125 void *value;
126 } kv_data;
127 128 /**129 * Field for storing a slot number.130 * May be used by iterators that iterate over multi-bucket collections.131 */132 size_t slot;
133 134 /**135 * If the iterator is position-aware, contains the index of the element in the underlying collection.136 * Otherwise, this field is usually uninitialized.137 */138 size_t index;
139 };
140 141 /**142 * Mutating iterator value type.143 *144 * An iterator points to a certain element in an (possibly unbounded) chain of elements.145 * Iterators that are based on collections (which have a defined "first" element), are supposed146 * to be "position-aware", which means that they keep track of the current index within the collection.147 *148 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the149 * iterator is based on a collection and the underlying collection is mutated by other means than this iterator150 * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns)151 * and MUST be re-obtained from the collection.152 *153 * @see CxIterator154 */155 typedefstruct cx_mut_iterator_s CxMutIterator;
156 157 /**158 * Internal iterator struct - use CxIterator.159 */160 struct cx_iterator_s {
161 162 /**163 * The base properties of this iterator.164 */165 struct cx_iterator_base_s base;
166 167 /**168 * Handle for the current element, if required.169 */170 void *elem_handle;
171 172 /**173 * Handle for the source collection, if any.174 */175 voidconst *src_handle;
176 177 /**178 * Field for storing a key-value pair.179 * May be used by iterators that iterate over k/v-collections.180 */181 struct {
182 /**183 * A pointer to the key.184 */185 voidconst *key;
186 /**187 * A pointer to the value.188 */189 void *value;
190 } kv_data;
191 192 /**193 * Field for storing a slot number.194 * May be used by iterators that iterate over multi-bucket collections.195 */196 size_t slot;
197 198 /**199 * If the iterator is position-aware, contains the index of the element in the underlying collection.200 * Otherwise, this field is usually uninitialized.201 */202 size_t index;
203 };
204 205 /**206 * Iterator value type.207 * An iterator points to a certain element in a (possibly unbounded) chain of elements.208 * Iterators that are based on collections (which have a defined "first" element), are supposed209 * to be "position-aware", which means that they keep track of the current index within the collection.210 *211 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However,212 * this iterator cannot mutate the collection itself (add or remove elements) and any mutation of the213 * collection by other means makes this iterator invalid (regardless of what cxIteratorValid() returns).214 *215 * @see CxMutIterator216 */217 typedefstruct cx_iterator_s CxIterator;
218 219 /**220 * Checks if the iterator points to valid data.221 *222 * This is especially false for past-the-end iterators.223 *224 * @param iter the iterator225 * @return true iff the iterator points to valid data226 */227 #define cxIteratorValid(iter) (iter).base.valid(&(iter))
228 229 /**230 * Returns a pointer to the current element.231 *232 * The behavior is undefined if this iterator is invalid.233 *234 * @param iter the iterator235 * @return a pointer to the current element236 */237 #define cxIteratorCurrent(iter) (iter).base.current(&iter)
238 239 /**240 * Advances the iterator to the next element.241 *242 * @param iter the iterator243 */244 #define cxIteratorNext(iter) (iter).base.next(&iter)
245 246 /**247 * Flags the current element for removal.248 *249 * @param iter the iterator250 * @return false if this iterator cannot remove the element251 */252 #define cxIteratorFlagRemoval(iter) (iter).base.flag_removal(&iter)
253 254 /**255 * Loops over an iterator.256 * @param type the type of the elements257 * @param elem the name of the iteration variable258 * @param iter the iterator259 */260 #define cx_foreach(type, elem, iter) \
261 for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter))
262 263 #endif// UCX_ITERATOR_H264