Fri, 23 May 2025 12:44:24 +0200
make test-compile depend on both static and shared
the shared lib is not needed for the tests,
but when run with coverage, gcov will be confused
when outdated line information is available from
a previous shared build
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file iterator.h * @brief Interface for iterator implementations. * @author Mike Becker * @author Olaf Wintermann * @copyright 2-Clause BSD License */ #ifndef UCX_ITERATOR_H #define UCX_ITERATOR_H #include "common.h" #ifdef __cplusplus extern "C" { #endif /** * Common data for all iterators. */ struct cx_iterator_base_s { /** * True if the iterator points to valid data. */ bool (*valid)(const void *); /** * Returns a pointer to the current element. * * When valid returns false, the behavior of this function is undefined. */ void *(*current)(const void *); /** * Original implementation in case the function needs to be wrapped. */ void *(*current_impl)(const void *); /** * Advances the iterator. * * When valid returns false, the behavior of this function is undefined. */ void (*next)(void *); /** * Indicates whether this iterator may remove elements. */ bool mutating; /** * Internal flag for removing the current element when advancing. */ bool remove; }; /** * Convenience type definition for the base structure of an iterator. * @see #CX_ITERATOR_BASE */ typedef struct cx_iterator_base_s CxIteratorBase; /** * Declares base attributes for an iterator. * Must be the first member of an iterator structure. */ #define CX_ITERATOR_BASE struct cx_iterator_base_s base /** * Internal iterator struct - use CxIterator. */ struct cx_iterator_s { /** * Inherited common data for all iterators. */ CX_ITERATOR_BASE; /** * Handle for the current element. */ void *elem_handle; /** * Handle for the source collection, if any. */ union { /** * Access for mutating iterators. */ void *m; /** * Access for normal iterators. */ const void *c; } src_handle; /** * If the iterator is position-aware, contains the index of the element in the underlying collection. * Otherwise, this field is usually uninitialized. */ size_t index; /** * The size of an individual element. */ size_t elem_size; /** * May contain the total number of elements, if known. * Shall be set to @c SIZE_MAX when the total number is unknown during iteration. */ size_t elem_count; }; /** * Iterator type. * * An iterator points to a certain element in a (possibly unbounded) chain of elements. * Iterators that are based on collections (which have a defined "first" element), are supposed * to be "position-aware", which means that they keep track of the current index within the collection. * * @note Objects that are pointed to by an iterator are always mutable through that iterator. However, * any concurrent mutation of the collection other than by this iterator makes this iterator invalid, * and it must not be used anymore. */ typedef struct cx_iterator_s CxIterator; /** * Checks if the iterator points to valid data. * * @param iter the iterator * @retval true if the iterator points to valid data * @retval false if the iterator already moved past the end */ #define cxIteratorValid(iter) (iter).base.valid(&(iter)) /** * Returns a pointer to the current element. * * The behavior is undefined if this iterator is invalid. * * @param iter the iterator * @return a pointer to the current element * @see cxIteratorValid() */ #define cxIteratorCurrent(iter) (iter).base.current(&iter) /** * Advances the iterator to the next element. * * @param iter the iterator */ #define cxIteratorNext(iter) (iter).base.next(&iter) /** * Flags the current element for removal, if this iterator is mutating. * * Does nothing for non-mutating iterators. * * @param iter the iterator */ #define cxIteratorFlagRemoval(iter) (iter).base.remove |= (iter).base.mutating /** * Obtains a reference to an arbitrary iterator. * * This is useful for APIs that expect some iterator as an argument. * * @param iter the iterator * @return (@c struct @c cx_iterator_base_s*) a pointer to the iterator */ #define cxIteratorRef(iter) &((iter).base) /** * Loops over an iterator. * * @param type the type of the elements * @param elem the name of the iteration variable * @param iter the iterator */ #define cx_foreach(type, elem, iter) \ for (type elem; cxIteratorValid(iter) && (elem = (type)cxIteratorCurrent(iter)) != NULL ; cxIteratorNext(iter)) /** * Creates an iterator for the specified plain array. * * The @p array can be @c NULL in which case the iterator will be immediately * initialized such that #cxIteratorValid() returns @c false. * * This iterator yields the addresses of the array elements. * If you want to iterator over an array of pointers, you can * use cxIteratorPtr() to create an iterator which directly * yields the stored pointers. * * @param array a pointer to the array (can be @c NULL) * @param elem_size the size of one array element * @param elem_count the number of elements in the array * @return an iterator for the specified array * @see cxIteratorPtr() */ cx_attr_nodiscard cx_attr_export CxIterator cxIterator( const void *array, size_t elem_size, size_t elem_count ); /** * Creates a mutating iterator for the specified plain array. * * While the iterator is in use, the array may only be altered by removing * elements through #cxIteratorFlagRemoval(). Every other change to the array * will bring this iterator to an undefined state. * * When @p remove_keeps_order is set to @c false, removing an element will only * move the last element to the position of the removed element, instead of * moving all subsequent elements by one. Usually, when the order of elements is * not important, this parameter should be set to @c false. * * The @p array can be @c NULL in which case the iterator will be immediately * initialized such that #cxIteratorValid() returns @c false. * * * @param array a pointer to the array (can be @c NULL) * @param elem_size the size of one array element * @param elem_count the number of elements in the array * @param remove_keeps_order @c true if the order of elements must be preserved * when removing an element * @return an iterator for the specified array */ cx_attr_nodiscard cx_attr_export CxIterator cxMutIterator( void *array, size_t elem_size, size_t elem_count, bool remove_keeps_order ); /** * Creates an iterator for the specified plain pointer array. * * This iterator assumes that every element in the array is a pointer * and yields exactly those pointers during iteration (while in contrast * an iterator created with cxIterator() would return the addresses * of those pointers within the array). * * @param array a pointer to the array (can be @c NULL) * @param elem_count the number of elements in the array * @return an iterator for the specified array * @see cxIterator() */ cx_attr_nodiscard cx_attr_export CxIterator cxIteratorPtr( const void *array, size_t elem_count ); /** * Creates a mutating iterator for the specified plain pointer array. * * This is the mutating variant of cxIteratorPtr(). See also * cxMutIterator(). * * @param array a pointer to the array (can be @c NULL) * @param elem_count the number of elements in the array * @param remove_keeps_order @c true if the order of elements must be preserved * when removing an element * @return an iterator for the specified array * @see cxMutIterator() * @see cxIteratorPtr() */ cx_attr_nodiscard cx_attr_export CxIterator cxMutIteratorPtr( void *array, size_t elem_count, bool remove_keeps_order ); #ifdef __cplusplus } // extern "C" #endif #endif // UCX_ITERATOR_H