src/cx/iterator.h

Thu, 23 May 2024 22:06:32 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 23 May 2024 22:06:32 +0200
changeset 857
4d12e34bb130
parent 854
fe0d69d72bcd
child 858
d9ad7904c4c2
permissions
-rw-r--r--

add missing convenience functions

     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  */
    36 #ifndef UCX_ITERATOR_H
    37 #define UCX_ITERATOR_H
    39 #include "common.h"
    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 *);
    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 *);
    56     /**
    57      * Original implementation in case the function needs to be wrapped.
    58      */
    59     __attribute__ ((__nonnull__))
    60     void *(*current_impl)(void const *);
    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 };
    79 /**
    80  * Declares base attributes for an iterator.
    81  */
    82 #define CX_ITERATOR_BASE struct cx_iterator_base_s base
    84 /**
    85  * Internal iterator struct - use CxIterator.
    86  */
    87 struct cx_iterator_s {
    88     CX_ITERATOR_BASE;
    90     /**
    91      * Handle for the current element.
    92      */
    93     void *elem_handle;
    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;
   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;
   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;
   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;
   136     /**
   137      * The size of an individual element.
   138      */
   139     size_t elem_size;
   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 };
   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;
   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))
   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)
   181 /**
   182  * Advances the iterator to the next element.
   183  *
   184  * @param iter the iterator
   185  */
   186 #define cxIteratorNext(iter) (iter).base.next(&iter)
   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
   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))
   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 );
   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 );
   255 #endif // UCX_ITERATOR_H

mercurial