UNIXworkcode

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 #ifndef UCX_ITERATOR_H 37 #define UCX_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)(void const *); 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)(void const *); 55 56 /** 57 * Original implementation in case the function needs to be wrapped. 58 */ 59 __attribute__ ((__nonnull__)) 60 void *(*current_impl)(void const *); 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 #define CX_ITERATOR_BASE struct 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 void const *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 void const *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 supposed 153 * 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 invalid 157 * and it must not be used anymore. 158 */ 159 typedef struct 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 iterator 167 * @return true iff the iterator points to valid data 168 */ 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 iterator 177 * @return a pointer to the current element 178 */ 179 #define cxIteratorCurrent(iter) (iter).base.current(&iter) 180 181 /** 182 * Advances the iterator to the next element. 183 * 184 * @param iter the iterator 185 */ 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 iterator 192 */ 193 #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating 194 195 /** 196 * Loops over an iterator. 197 * @param type the type of the elements 198 * @param elem the name of the iteration variable 199 * @param iter the iterator 200 */ 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 immediately 209 * 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 element 214 * @param elem_count the number of elements in the array 215 * @return an iterator for the specified array 216 */ 217 __attribute__((__warn_unused_result__)) 218 CxIterator cxIterator( 219 void const *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 removing 228 * elements through #cxIteratorFlagRemoval(). Every other change to the array 229 * will bring this iterator to an undefined state. 230 * 231 * When \p remove_keeps_order is set to \c false, removing an element will only 232 * move the last element to the position of the removed element, instead of 233 * moving all subsequent elements by one. Usually, when the order of elements is 234 * 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 immediately 237 * 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 element 242 * @param elem_count the number of elements in the array 243 * @param remove_keeps_order \c true if the order of elements must be preserved 244 * when removing an element 245 * @return an iterator for the specified array 246 */ 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_H 256