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)(voidconst *);
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)(voidconst *);
55 56 /** 57 * Original implementation in case the function needs to be wrapped. 58 */ 59 __attribute__ ((__nonnull__))
60 void *(*current_impl)(voidconst *);
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 */ 82 #defineCX_ITERATOR_BASEstruct cx_iterator_base_s base
83 84 /** 85 * Internal iterator struct - use CxIterator. 86 */ 87 struct cx_iterator_s {
88 CX_ITERATOR_BASE;
89 90 /** 91 * Handle for the current element. 92 */ 93 void *elem_handle;
94 95 /** 96 * Handle for the source collection, if any. 97 */ 98 union {
99 /**100 * Access for mutating iterators.101 */102 void *m;
103 /**104 * Access for normal iterators.105 */106 voidconst *c;
107 } src_handle;
108 109 /**110 * Field for storing a key-value pair.111 * May be used by iterators that iterate over k/v-collections.112 */113 struct {
114 /**115 * A pointer to the key.116 */117 voidconst *key;
118 /**119 * A pointer to the value.120 */121 void *value;
122 } kv_data;
123 124 /**125 * Field for storing a slot number.126 * May be used by iterators that iterate over multi-bucket collections.127 */128 size_t slot;
129 130 /**131 * If the iterator is position-aware, contains the index of the element in the underlying collection.132 * Otherwise, this field is usually uninitialized.133 */134 size_t index;
135 136 /**137 * The size of an individual element.138 */139 size_t elem_size;
140 141 /**142 * May contain the total number of elements, if known.143 * Shall be set to \c SIZE_MAX when the total number is unknown during iteration.144 */145 size_t elem_count;
146 };
147 148 /**149 * Iterator type.150 *151 * An iterator points to a certain element in a (possibly unbounded) chain of elements.152 * Iterators that are based on collections (which have a defined "first" element), are supposed153 * to be "position-aware", which means that they keep track of the current index within the collection.154 *155 * @note Objects that are pointed to by an iterator are always mutable through that iterator. However,156 * any concurrent mutation of the collection other than by this iterator makes this iterator invalid157 * and it must not be used anymore.158 */159 typedefstruct cx_iterator_s CxIterator;
160 161 /**162 * Checks if the iterator points to valid data.163 *164 * This is especially false for past-the-end iterators.165 *166 * @param iter the iterator167 * @return true iff the iterator points to valid data168 */169 #define cxIteratorValid(iter) (iter).base.valid(&(iter))
170 171 /**172 * Returns a pointer to the current element.173 *174 * The behavior is undefined if this iterator is invalid.175 *176 * @param iter the iterator177 * @return a pointer to the current element178 */179 #define cxIteratorCurrent(iter) (iter).base.current(&iter)
180 181 /**182 * Advances the iterator to the next element.183 *184 * @param iter the iterator185 */186 #define cxIteratorNext(iter) (iter).base.next(&iter)
187 188 /**189 * Flags the current element for removal, if this iterator is mutating.190 *191 * @param iter the iterator192 */193 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating
194 195 /**196 * Loops over an iterator.197 * @param type the type of the elements198 * @param elem the name of the iteration variable199 * @param iter the iterator200 */201 #define cx_foreach(type, elem, iter) \
202 for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter))
203 204 205 /**206 * Creates an iterator for the specified plain array.207 *208 * The \p array can be \c NULL in which case the iterator will be immediately209 * initialized such that #cxIteratorValid() returns \c false.210 *211 *212 * @param array a pointer to the array (can be \c NULL)213 * @param elem_size the size of one array element214 * @param elem_count the number of elements in the array215 * @return an iterator for the specified array216 */217 __attribute__((__warn_unused_result__))
218 CxIterator cxIterator(
219 voidconst *array,
220 size_t elem_size,
221 size_t elem_count
222 );
223 224 /**225 * Creates a mutating iterator for the specified plain array.226 *227 * While the iterator is in use, the array may only be altered by removing228 * elements through #cxIteratorFlagRemoval(). Every other change to the array229 * will bring this iterator to an undefined state.230 *231 * When \p remove_keeps_order is set to \c false, removing an element will only232 * move the last element to the position of the removed element, instead of233 * moving all subsequent elements by one. Usually, when the order of elements is234 * not important, this parameter should be set to \c false.235 *236 * The \p array can be \c NULL in which case the iterator will be immediately237 * initialized such that #cxIteratorValid() returns \c false.238 *239 *240 * @param array a pointer to the array (can be \c NULL)241 * @param elem_size the size of one array element242 * @param elem_count the number of elements in the array243 * @param remove_keeps_order \c true if the order of elements must be preserved244 * when removing an element245 * @return an iterator for the specified array246 */247 __attribute__((__warn_unused_result__))
248 CxIterator cxMutIterator(
249 void *array,
250 size_t elem_size,
251 size_t elem_count,
252 bool remove_keeps_order
253 );
254 255 #endif// UCX_ITERATOR_H256