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 * \copyright 2-Clause BSD License 34 */ 35 36 #ifndefUCX_ITERATOR_H 37 #defineUCX_ITERATOR_H 38 39 #include"common.h" 40 41 struct cx_iterator_base_s {
42 /** 43 * True iff the iterator points to valid data. 44 */ 45 __attribute__ ((__nonnull__))
46 bool (*valid)(constvoid *);
47 48 /** 49 * Returns a pointer to the current element. 50 * 51 * When valid returns false, the behavior of this function is undefined. 52 */ 53 __attribute__ ((__nonnull__))
54 void *(*current)(constvoid *);
55 56 /** 57 * Original implementation in case the function needs to be wrapped. 58 */ 59 __attribute__ ((__nonnull__))
60 void *(*current_impl)(constvoid *);
61 62 /** 63 * Advances the iterator. 64 * 65 * When valid returns false, the behavior of this function is undefined. 66 */ 67 __attribute__ ((__nonnull__))
68 void (*next)(void *);
69 /** 70 * Indicates whether this iterator may remove elements. 71 */ 72 bool mutating;
73 /** 74 * Internal flag for removing the current element when advancing. 75 */ 76 bool remove;
77 };
78 79 /** 80 * Declares base attributes for an iterator. 81 * Must be the first member of an iterator structure. 82 */ 83 #defineCX_ITERATOR_BASEstruct cx_iterator_base_s base
84 85 /** 86 * Internal iterator struct - use CxIterator. 87 */ 88 struct cx_iterator_s {
89 CX_ITERATOR_BASE;
90 91 /** 92 * Handle for the current element. 93 */ 94 void *elem_handle;
95 96 /** 97 * Handle for the source collection, if any. 98 */ 99 union {
100 /**101 * Access for mutating iterators.102 */103 void *m;
104 /**105 * Access for normal iterators.106 */107 constvoid *c;
108 } src_handle;
109 110 /**111 * Field for storing a key-value pair.112 * May be used by iterators that iterate over k/v-collections.113 */114 struct {
115 /**116 * A pointer to the key.117 */118 constvoid *key;
119 /**120 * A pointer to the value.121 */122 void *value;
123 } kv_data;
124 125 /**126 * Field for storing a slot number.127 * May be used by iterators that iterate over multi-bucket collections.128 */129 size_t slot;
130 131 /**132 * If the iterator is position-aware, contains the index of the element in the underlying collection.133 * Otherwise, this field is usually uninitialized.134 */135 size_t index;
136 137 /**138 * The size of an individual element.139 */140 size_t elem_size;
141 142 /**143 * May contain the total number of elements, if known.144 * Shall be set to \c SIZE_MAX when the total number is unknown during iteration.145 */146 size_t elem_count;
147 };
148 149 /**150 * Iterator type.151 *152 * An iterator points to a certain element in a (possibly unbounded) chain of elements.153 * Iterators that are based on collections (which have a defined "first" element), are supposed154 * to be "position-aware", which means that they keep track of the current index within the collection.155 *156 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However,157 * any concurrent mutation of the collection other than by this iterator makes this iterator invalid158 * and it must not be used anymore.159 */160 typedefstruct cx_iterator_s CxIterator;
161 162 /**163 * Checks if the iterator points to valid data.164 *165 * This is especially false for past-the-end iterators.166 *167 * @param iter the iterator168 * @return true iff the iterator points to valid data169 */170 #define cxIteratorValid(iter) (iter).base.valid(&(iter))
171 172 /**173 * Returns a pointer to the current element.174 *175 * The behavior is undefined if this iterator is invalid.176 *177 * @param iter the iterator178 * @return a pointer to the current element179 */180 #define cxIteratorCurrent(iter) (iter).base.current(&iter)
181 182 /**183 * Advances the iterator to the next element.184 *185 * @param iter the iterator186 */187 #define cxIteratorNext(iter) (iter).base.next(&iter)
188 189 /**190 * Flags the current element for removal, if this iterator is mutating.191 *192 * @param iter the iterator193 */194 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating
195 196 /**197 * Obtains a reference to an arbitrary iterator.198 *199 * This is useful for APIs that expect some iterator as an argument.200 *201 * @param iter the iterator202 */203 #define cxIteratorRef(iter) &((iter).base)
204 205 /**206 * Loops over an iterator.207 * @param type the type of the elements208 * @param elem the name of the iteration variable209 * @param iter the iterator210 */211 #define cx_foreach(type, elem, iter) \
212 for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter))
213 214 215 /**216 * Creates an iterator for the specified plain array.217 *218 * The \p array can be \c NULL in which case the iterator will be immediately219 * initialized such that #cxIteratorValid() returns \c false.220 *221 *222 * @param array a pointer to the array (can be \c NULL)223 * @param elem_size the size of one array element224 * @param elem_count the number of elements in the array225 * @return an iterator for the specified array226 */227 __attribute__((__warn_unused_result__))
228 CxIterator cxIterator(
229 constvoid *array,
230 size_t elem_size,
231 size_t elem_count
232 );
233 234 /**235 * Creates a mutating iterator for the specified plain array.236 *237 * While the iterator is in use, the array may only be altered by removing238 * elements through #cxIteratorFlagRemoval(). Every other change to the array239 * will bring this iterator to an undefined state.240 *241 * When \p remove_keeps_order is set to \c false, removing an element will only242 * move the last element to the position of the removed element, instead of243 * moving all subsequent elements by one. Usually, when the order of elements is244 * not important, this parameter should be set to \c false.245 *246 * The \p array can be \c NULL in which case the iterator will be immediately247 * initialized such that #cxIteratorValid() returns \c false.248 *249 *250 * @param array a pointer to the array (can be \c NULL)251 * @param elem_size the size of one array element252 * @param elem_count the number of elements in the array253 * @param remove_keeps_order \c true if the order of elements must be preserved254 * when removing an element255 * @return an iterator for the specified array256 */257 __attribute__((__warn_unused_result__))
258 CxIterator cxMutIterator(
259 void *array,
260 size_t elem_size,
261 size_t elem_count,
262 bool remove_keeps_order
263 );
264 265 #endif// UCX_ITERATOR_H266