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 * \version 3.0 34 * \copyright 2-Clause BSD License 35 */ 36 37 #ifndef UCX_ITERATOR_H 38 #define UCX_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)(void const *); 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)(void const *); 59 60 /** 61 * Original implementation in case the function needs to be wrapped. 62 */ 63 __attribute__ ((__nonnull__)) 64 void *(*current_impl)(void const *); 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 void const *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 supposed 146 * 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 the 149 * iterator is based on a collection and the underlying collection is mutated by other means than this iterator 150 * (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 CxIterator 154 */ 155 typedef struct 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 void const *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 void const *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 supposed 209 * 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 the 213 * collection by other means makes this iterator invalid (regardless of what cxIteratorValid() returns). 214 * 215 * @see CxMutIterator 216 */ 217 typedef struct 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 iterator 225 * @return true iff the iterator points to valid data 226 */ 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 iterator 235 * @return a pointer to the current element 236 */ 237 #define cxIteratorCurrent(iter) (iter).base.current(&iter) 238 239 /** 240 * Advances the iterator to the next element. 241 * 242 * @param iter the iterator 243 */ 244 #define cxIteratorNext(iter) (iter).base.next(&iter) 245 246 /** 247 * Flags the current element for removal. 248 * 249 * @param iter the iterator 250 * @return false if this iterator cannot remove the element 251 */ 252 #define cxIteratorFlagRemoval(iter) (iter).base.flag_removal(&iter) 253 254 /** 255 * Loops over an iterator. 256 * @param type the type of the elements 257 * @param elem the name of the iteration variable 258 * @param iter the iterator 259 */ 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_H 264