Iterators module

Cnx defines its own set of iterator SizedTrait templates that allow for simple, collection-agnostic processing of a collection of elements in a way similar to C++ or Rust.

Iterators provide a uniform interface for accessing the elements of a collection in contained order. They act as reference-wrappers for the element associated with their current position, providing reference-like semantics for accessing values, and because of this are designed to work with pointer-to-T (typedefed as Ref(T) or ConstRef(T)) as their generic parameter as opposed to T.

Cnx defines four categories of iterators, each with different requirements and functionality.

  1. Forward Iterators (CnxForwardIterator(T)) provide forward-only (increment-only) access to the elements in an iteration. This is provided through the associated next function.
  2. Reverse Iterators (CnxReverseIterator(T)) provide reverse-on (decrement-only) access to the elements in an iteration. This is provided through the associated next function.
  3. Bidirectional Iterators (CnxBidirectionalIterator(T)) provide forward and reverse access to the elements in an iteration. This is provided through the associated next and previous functions.
  4. Random Access Iterators (CnxRandomAccessIterator(T)) provide bidirectional and random (indexed) access to the elements in an iteration. This is provided through the associated next, previous, and at functions.

All iterators also provide access to the current value through current and equality comparison through equals.

Using iterators are very simple.

let_mut str = cnx_string_from("this is a string");
// We can use them by hand like so:
let_mut begin = cnx_string_begin(str);
let end = cnx_string_end(str);
// for each `char` in `str`, do something
for(let_mut character = cnx_iterator_current(begin);
    !cnx_iterator_equals(begin, end);
    character = cnx_iterator_next(begin)) {
    // do something with character
}

// or we can use `foreach(element, collection)` to wrap most of that for us:
// for each `char` in `str`, do something
foreach(character, str) {
    // do something with character
}

foreach(element, collection) accesses elements by value, but there are also versions to access by pointer-to-const and pointer as well:

foreach_ref(character, str) {
    // character is `const char*`
}
foreach_ref_mut(character, str) {
    // character is `char*`
}

Most Cnx collections will require const and non-const iterators for their associated type to be instantiated prior to their own instantiation. This is very simple, to provide instantiations of iterators for a collection of type T, just:

typedef T* Ref(T);
typedef const T* ConstRef(T);
DeclCnxIterators(Ref(T));
DeclCnxIterators(ConstRef(T));

The above will instantiate iterators of all four categories for the type T, but you could also only instantiate forward iterators or reverse iterators, depending on the collection you intend to use. When unsure, instantiating all is the simplest solution.

To provide Cnx iterators for your own collections, the process is a little more involved. First, you'll need a concrete type to back your iterator (it will implement the desired iterator Traits). By design, these should contain, exactly, an isize index, m_index, and a pointer to associated collection, in exactly that order. If you deviate from this size, you will cause undefined behavior and should get a compiler error. If you deviate from this layout, you'll break other abstractions built on top of iterators, like CnxRange(T), for your type.

For example, the pseudo-code for the concrete type for CnxVector(T)'s non-const iterator is:

typedef CnxVector(T)Iterator {
    CnxVector(T)* m_vector;
    isize m_index;
} CnxVector(T)Iterator;

On top of that, you'll need a factory function for your concrete type of the signature:

ConcreteIterator (*const collection_iterator_new)(const CollectionType* restrict collection);

and the functions for the specific iterator category you intend to provide. None of these need be part of your public API, they can remain implementation details. You'll then need to instantiate a declaration and implementation for an into_iter function. For example, for CnxForwardIterator(T), this would be:

// in "YourCollection.h"
DeclIntoCnxForwardIterator(YourCollection, T, YourDesiredIntoIterFuncName);
// in "YourCollection.c"
ImplIntoCnxForwardIterator(YourCollection,
                           T,
                           YourDesiredIntoIterFuncName,
                           YourConcreteIteratorTypeFactoryFunction,
                           YourIteratorNextFunction,
                           YourIteratorCurrentFunction,
                           YourIteratorEqualsFunction);

From here, you can wrap the into_iter function to provide iterators initialized to specific points in the iteration. For more detailed examples of providing each iterator category, see the documentation for the specific category in question. For a reference implementation of how to provide iterators for a user-defined collection, consider viewing the implementations for CnxString, CnxVector(T), or CnxArray(T)

Defines

#define CNX_ITERATOR_CONCRETE_TYPE_SIZE
The maximum compatible size of a concrete type implementing a Cnx iterator trait.
#define CnxForwardIterator(T)
Macro alias for CnxForwardIterator of type T
#define DeclCnxForwardIterator(T)
Instantiates CnxForwardIterator(T) for the type T
#define DeclIntoCnxForwardIterator(CollectionType, T, IntoIterFuncName)
Instantiates an into_iter function declaration.
#define ImplIntoCnxForwardIterator(CollectionType, T, IntoIterFuncName, CreateFunction, NextFunction, CurrentFunction, EqualsFunction)
Instantiates an into_iter function definition.
#define CnxReverseIterator(T)
Macro alias for CnxReverseIterator of type T
#define DeclCnxReverseIterator(T)
Instantiates CnxReverseIterator(T) for the type T
#define DeclIntoCnxReverseIterator(CollectionType, T, IntoIterFuncName)
Instantiates an into_iter function declaration.
#define ImplIntoCnxReverseIterator(CollectionType, T, IntoIterFuncName, CreateFunction, NextFunction, CurrentFunction, EqualsFunction)
Instantiates an into_iter function definition.
#define CnxBidirectionalIterator(T)
Macro alias for CnxBidirectionalIterator of type T
#define DeclCnxBidirectionalIterator(T)
Instantiates CnxBidirectionalIterator(T) for the type T
#define DeclIntoCnxBidirectionalIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName)
Instantiates an into_iter function declaration and iterator conversion function declarations.
#define ImplIntoCnxBidirectionalIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName, CreateFunction, NextFunction, PreviousFunction, CurrentFunction, EqualsFunction)
Instantiates an into_iter function definition and iterator conversion function definitions.
#define CnxRandomAccessIterator(T)
Macro alias for CnxRandomAccessIterator of type T
#define DeclCnxRandomAccessIterator(T)
Instantiates CnxRandomAccessIterator(T) for the type T
#define DeclIntoCnxRandomAccessIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName)
Instantiates an into_iter function declaration and iterator conversion function declarations.
#define ImplIntoCnxRandomAccessIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName, CreateFunction, NextFunction, PreviousFunction, AtFunction, CurrentFunction, EqualsFunction)
Instantiates an into_iter function definition and iterator conversion function definitions.
#define cnx_iterator_next(iterator)
Advances the iterator to the next element.
#define cnx_iterator_previous(iterator)
Decrements the iterator to the previous element.
#define cnx_iterator_at(iterator, index)
Returns a reference to the element at the given index in the iteration.
#define cnx_iterator_current(iterator)
Returns a reference to the element associated with the current position of the iterator.
#define cnx_iterator_equals(lhs, rhs)
Returns whether the given iterators are equal.
#define cnx_iterator_into_forward_iterator(iterator)
Converts the given CnxBidirectionalIterator(T) or CnxRandomAccessIterator(T) into a CnxForwardIterator(T)
#define cnx_iterator_into_reverse_iterator(iterator)
Converts the given CnxBidirectionalIterator(T) or CnxRandomAccessIterator(T) into a CnxReverseIterator(T)
#define cnx_iterator_into_bidirectional_iterator(iterator)
Converts the given CnxRandomAccessIterator(T) into a CnxBidirectionalIterator(T)
#define foreach(element, collection)
Loops over each element in the iteration of the given collection.
#define foreach_ref(element, collection)
Loops over each element in the iteration of the given collection.
#define foreach_ref_mut(element, collection)
Loops over each element in the iteration of the given collection.
#define DeclCnxIterators(T)
Instantiates each iterator category for the type T.

Define documentation

#define CNX_ITERATOR_CONCRETE_TYPE_SIZE

The maximum compatible size of a concrete type implementing a Cnx iterator trait.

Cnx iterators are designed to have a maximum concrete size, as they are SizedTraits, and to be compatible a concrete type can't exceed this (doing so would be UB and should cause a compiler error or warning).

#define CnxForwardIterator(T)

Macro alias for CnxForwardIterator of type T

Parameters
T - The reference type the iterator represents

Used for creating and referencing a typedef for a specific forward iterator instantiation.

#define DeclCnxForwardIterator(T)

Instantiates CnxForwardIterator(T) for the type T

Parameters
T - The reference type the iterator represents

Instantiates the necessary declarations and definitions for CnxForwardIterator(T), enabling its use elsewhere.

#define DeclIntoCnxForwardIterator(CollectionType, T, IntoIterFuncName)

Instantiates an into_iter function declaration.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function

Instantiates the declaration of an into_iter function, associated with the collection type CollectionType, returning a CnxForwardIterator(T) associated with the collection.

#define ImplIntoCnxForwardIterator(CollectionType, T, IntoIterFuncName, CreateFunction, NextFunction, CurrentFunction, EqualsFunction)

Instantiates an into_iter function definition.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function
CreateFunction - The factory function for the concrete type that will implement CnxForwardIterator(T) for your collection.
NextFunction - The function advancing the iterator
CurrentFunction - The function returning the element currently associated with the iterator
EqualsFunction - The function determining if two iterators are equal

Instantiates the definition of an into_iter function, associated with the collection type CollectionType, returning a CnxForwardIterator(T) associated with the collection. Requires that the following are already declared and/or defined:

  1. CreateFunction - A factory function returning the concrete type backing the collection's iterators of the signature:

    ConcreteType (*const CreateFunction)(const Collection* restrict self);
    
  2. NextFunction - Advances the iterator to the next element in the iteration and returns the element. Takes the signature:

    T (*const NextFunction)(CnxForwardIterator(T)* restrict self);
    
  3. CurrentFunction - Returns the element associated with the current position of the iterator. Takes the signature:

    T (*const CurrentFunction)(const CnxForwardIterator(T)* restrict self);
    
  4. EqualsFunction - Determines if two given iterators are equal. Takes the signature:

     bool (*const EqualsFunction)(const CnxForwardIterator(T)* restrict self,
                                  const CnxForwardIterator(T)* restrict rhs);
    

    Since iterators are a Trait object, your internal implementations can cast the self pointer to a pointer to the concrete type and operate on it as required. Example:

bool (*const EqualsFunction)(const CnxForwardIterator(T)* restrict self,
                             const CnxForwardIterator(T)* restrict rhs) {
    let _self = static_cast(const ConcreteType*)(self->m_self);
    let _rhs = static_cast(const ConcreteType*)(rhs->m_self);
    return _self->m_collection_ptr == _rhs->m_collection_ptr
           && _self->m_index == _rhs->m_index;
}

#define CnxReverseIterator(T)

Macro alias for CnxReverseIterator of type T

Parameters
T - The reference type the iterator represents

Used for creating and referencing a typedef for a specific reverse iterator instantiation.

#define DeclCnxReverseIterator(T)

Instantiates CnxReverseIterator(T) for the type T

Parameters
T - The reference type the iterator represents

Instantiates the necessary declarations and definitions for CnxReverseIterator(T), enabling its use elsewhere.

#define DeclIntoCnxReverseIterator(CollectionType, T, IntoIterFuncName)

Instantiates an into_iter function declaration.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function

Instantiates the declaration of an into_iter function, associated with the collection type CollectionType, returning a CnxReverseIterator(T) associated with the collection.

#define ImplIntoCnxReverseIterator(CollectionType, T, IntoIterFuncName, CreateFunction, NextFunction, CurrentFunction, EqualsFunction)

Instantiates an into_iter function definition.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function
CreateFunction - The factory function for the concrete type that will implement CnxReverseIterator(T) for your collection.
NextFunction - The function advancing the iterator
CurrentFunction - The function returning the element currently associated with the iterator
EqualsFunction - The function determining if two iterators are equal

Instantiates the definition of an into_iter function, associated with the collection type CollectionType, returning a CnxReverseIterator(T) associated with the collection. Requires that the following are already declared and/or defined:

  1. CreateFunction - A factory function returning the concrete type backing the collection's iterators of the signature:

    ConcreteType (*const CreateFunction)(const Collection* restrict self);
    
  2. NextFunction - Advances the iterator to the next element in the iteration and returns the element. Takes the signature:

    T (*const NextFunction)(CnxReverseIterator(T)* restrict self);
    
  3. CurrentFunction - Returns the element associated with the current position of the iterator. Takes the signature:

    T (*const CurrentFunction)(const CnxReverseIterator(T)* restrict self);
    
  4. EqualsFunction - Determines if two given iterators are equal. Takes the signature:

     bool (*const EqualsFunction)(const CnxReverseIterator(T)* restrict self,
                                  const CnxReverseIterator(T)* restrict rhs);
    

    Since iterators are a Trait object, your internal implementations can cast the self pointer to a pointer to the concrete type and operate on it as required. Example:

bool (*const EqualsFunction)(const CnxReverseIterator(T)* restrict self,
                             const CnxReverseIterator(T)* restrict rhs) {
    let _self = static_cast(const ConcreteType*)(self->m_self);
    let _rhs = static_cast(const ConcreteType*)(rhs->m_self);
    return _self->m_collection_ptr == _rhs->m_collection_ptr
           && _self->m_index == _rhs->m_index;
}

#define CnxBidirectionalIterator(T)

Macro alias for CnxBidirectionalIterator of type T

Parameters
T - The reference type the iterator represents

Used for creating and referencing a typedef for a specific bidirectional iterator instantiation.

#define DeclCnxBidirectionalIterator(T)

Instantiates CnxBidirectionalIterator(T) for the type T

Parameters
T - The reference type the iterator represents

Instantiates the necessary declarations and definitions for CnxBidirectionalIterator(T), enabling its use elsewhere.

#define DeclIntoCnxBidirectionalIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName)

Instantiates an into_iter function declaration and iterator conversion function declarations.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function
IteratorConversionName - The root name for the conversion functions

Instantiates the declaration of an into_iter function, associated with the collection type CollectionType, returning a CnxBidirectionalIterator(T) associated with the collection. Also Instantiates the declarations for conversion functions from CnxBidirectionalIterator(T) to its subcategories CnxForwardIterator(T) and CnxReverseIterator(T).

#define ImplIntoCnxBidirectionalIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName, CreateFunction, NextFunction, PreviousFunction, CurrentFunction, EqualsFunction)

Instantiates an into_iter function definition and iterator conversion function definitions.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function
IteratorConversionName - The root name for the conversion functions
CreateFunction - The factory function for the concrete type that will implement CnxBidirectionalIterator(T) for your collection.
NextFunction - The function advancing the iterator
PreviousFunction - The function decrementing the iterator
CurrentFunction - The function returning the element currently associated with the iterator
EqualsFunction - The function determining if two iterators are equal

Instantiates the definition of an into_iter function, associated with the collection type CollectionType, returning a CnxBidirectionalIterator(T) associated with the collection. Also Instantiates the definitions for conversion functions from CnxBidirectionalIterator(T) to its subcategories CnxForwardIterator(T) and CnxReverseIterator(T). Requires that the following are already declared and/or defined:

  1. CreateFunction - A factory function returning the concrete type backing the collection's iterators of the signature:

    ConcreteType (*const CreateFunction)(const Collection* restrict self);
    
  2. NextFunction - Advances the iterator to the next element in the iteration and returns the element. Takes the signature:

    T (*const NextFunction)(CnxBidirectionalIterator(T)* restrict self);
    
  3. PreviousFunction - Decrements the iterator to the previous element in the iteration and returns the element. Takes the signature:

    T (*const PreviousFunction)(CnxBidirectionalIterator(T)* restrict self);
    
  4. CurrentFunction - Returns the element associated with the current position of the iterator. Takes the signature:

    T (*const CurrentFunction)(const CnxBidirectionalIterator(T)* restrict self);
    
  5. EqualsFunction - Determines if two given iterators are equal. Takes the signature:

     bool (*const EqualsFunction)(const CnxBidirectionalIterator(T)* restrict self,
                                  const CnxBidirectionalIterator(T)* restrict rhs);
    

    Since iterators are a Trait object, your internal implementations can cast the self pointer to a pointer to the concrete type and operate on it as required. Example:

bool (*const EqualsFunction)(const CnxBidirectionalIterator(T)* restrict self,
                             const CnxBidirectionalIterator(T)* restrict rhs) {
    let _self = static_cast(const ConcreteType*)(self->m_self);
    let _rhs = static_cast(const ConcreteType*)(rhs->m_self);
    return _self->m_collection_ptr == _rhs->m_collection_ptr
           && _self->m_index == _rhs->m_index;
}

#define CnxRandomAccessIterator(T)

Macro alias for CnxRandomAccessIterator of type T

Parameters
T - The reference type the iterator represents

Used for creating and referencing a typedef for a specific random access iterator instantiation.

#define DeclCnxRandomAccessIterator(T)

Instantiates CnxRandomAccessIterator(T) for the type T

Parameters
T - The reference type the iterator represents

Instantiates the necessary declarations and definitions for CnxRandomAccessIterator(T), enabling its use elsewhere.

#define DeclIntoCnxRandomAccessIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName)

Instantiates an into_iter function declaration and iterator conversion function declarations.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function
IteratorConversionName - The root name for the conversion functions

Instantiates the declaration of an into_iter function, associated with the collection type CollectionType, returning a CnxRandomAccessIterator(T) associated with the collection. Also Instantiates the declarations for conversion functions from CnxRandomAccessIterator(T) to its subcategories CnxForwardIterator(T), CnxReverseIterator(T), and CnxBidirectionalIterator(T).

#define ImplIntoCnxRandomAccessIterator(CollectionType, T, IntoIterFuncName, IteratorConversionName, CreateFunction, NextFunction, PreviousFunction, AtFunction, CurrentFunction, EqualsFunction)

Instantiates an into_iter function definition and iterator conversion function definitions.

Parameters
CollectionType - The type of the collection to have an into_iter function instantiated for
T - The reference type the iterator represents
IntoIterFuncName - The name for the into_iter function
IteratorConversionName - The root name for the conversion functions
CreateFunction - The factory function for the concrete type that will implement CnxRandomAccessIterator(T) for your collection.
NextFunction - The function advancing the iterator
PreviousFunction - The function decrementing the iterator
AtFunction - The function returning the element associated with the given index into the iteration
CurrentFunction - The function returning the element currently associated with the iterator
EqualsFunction - The function determining if two iterators are equal

Instantiates the definition of an into_iter function, associated with the collection type CollectionType, returning a CnxRandomAccessIterator(T) associated with the collection. Also Instantiates the definitions for conversion functions from CnxRandomAccessIterator(T) to its subcategories CnxForwardIterator(T), CnxReverseIterator(T), and CnxBidirectionalIterator(T). Requires that the following are already declared and/or defined:

  1. CreateFunction - A factory function returning the concrete type backing the collection's iterators of the signature:

    ConcreteType (*const CreateFunction)(const Collection* restrict self);
    
  2. NextFunction - Advances the iterator to the next element in the iteration and returns the element. Takes the signature:

    T (*const NextFunction)(CnxRandomAccessIterator(T)* restrict self);
    
  3. PreviousFunction - Decrements the iterator to the previous element in the iteration and returns the element. Takes the signature:

    T (*const PreviousFunction)(CnxRandomAccessIterator(T)* restrict self);
    
  4. AtFunction - Returns the element in the iteration associated with the given index. Takes the signature:

    T (*const AtFunction)(CnxRandomAccessIterator(T)* restrict self, usize index);
    
  5. CurrentFunction - Returns the element associated with the current position of the iterator. Takes the signature:

    T (*const CurrentFunction)(const CnxRandomAccessIterator(T)* restrict self);
    
  6. EqualsFunction - Determines if two given iterators are equal. Takes the signature:

     bool (*const EqualsFunction)(const CnxRandomAccessIterator(T)* restrict self,
                                  const CnxRandomAccessIterator(T)* restrict rhs);
    

    Since iterators are a Trait object, your internal implementations can cast the self pointer to a pointer to the concrete type and operate on it as required. Example:

bool (*const EqualsFunction)(const CnxRandomAccessIterator(T)* restrict self,
                             const CnxRandomAccessIterator(T)* restrict rhs) {
    let _self = static_cast(const ConcreteType*)(self->m_self);
    let _rhs = static_cast(const ConcreteType*)(rhs->m_self);
    return _self->m_collection_ptr == _rhs->m_collection_ptr
           && _self->m_index == _rhs->m_index;
}

#define cnx_iterator_next(iterator)

Advances the iterator to the next element.

Parameters
iterator - The iterator to advance
Returns a reference to the next element in the iteration

Advances the iterator to the next element and returns a reference to that element.

#define cnx_iterator_previous(iterator)

Decrements the iterator to the previous element.

Parameters
iterator - The iterator to decrement
Returns a reference to the previous element in the iteration

Decrements the iterator to the previous element and returns a reference to that element.

#define cnx_iterator_at(iterator, index)

Returns a reference to the element at the given index in the iteration.

Parameters
iterator - The iterator to get an element from
index - The index in the iteration of the desired element
Returns a reference to the element at the given index

#define cnx_iterator_current(iterator)

Returns a reference to the element associated with the current position of the iterator.

Parameters
iterator - The iterator to get the currently associated element from
Returns a reference to the element associated with the current position of the iterator

#define cnx_iterator_equals(lhs, rhs)

Returns whether the given iterators are equal.

Parameters
lhs - The LHS iterator of the equality comparison
rhs - The RHS iterator of the equality comparison
Returns whether the iterators are equal

#define cnx_iterator_into_forward_iterator(iterator)

Converts the given CnxBidirectionalIterator(T) or CnxRandomAccessIterator(T) into a CnxForwardIterator(T)

Parameters
iterator - The iterator to convert
Returns iterator as a CnxForwardIterator(T)

#define cnx_iterator_into_reverse_iterator(iterator)

Converts the given CnxBidirectionalIterator(T) or CnxRandomAccessIterator(T) into a CnxReverseIterator(T)

Parameters
iterator - The iterator to convert
Returns iterator as a CnxReverseIterator(T)

#define cnx_iterator_into_bidirectional_iterator(iterator)

Converts the given CnxRandomAccessIterator(T) into a CnxBidirectionalIterator(T)

Parameters
iterator - The iterator to convert
Returns iterator as a CnxBidirectionalIterator(T)

#define foreach(element, collection)

Loops over each element in the iteration of the given collection.

Parameters
element - The name to use to reference the current element in the iteration
collection - The collection to iterate over

This category of foreach loop iterates by value (element will be a copy)

#define foreach_ref(element, collection)

Loops over each element in the iteration of the given collection.

Parameters
element - The name to use to reference the current element in the iteration
collection - The collection to iterate over

This category of foreach loop iterates by const pointer (element will be a pointer to const)

#define foreach_ref_mut(element, collection)

Loops over each element in the iteration of the given collection.

Parameters
element - The name to use to reference the current element in the iteration
collection - The collection to iterate over

This category of foreach loop iterates by pointer (element will be a pointer)

#define DeclCnxIterators(T)

Instantiates each iterator category for the type T.

Parameters
T - The reference type the iterator represents

Instantiates the necessary declarations and definitions for each Cnx iterator category, enabling their use elsewhere.