Ranges module

Cnx Ranges provides a "struct template" enabling a lazy, collection-agnostic way to view, filter, modify, and reference a collection's elements.

Ranges is one of the Cnx features that relies most heavily on GNU C extensions (currently), in particular, __auto_type and statement expressions. It would benefit the most from C2x standardization of auto and lambdas.

Requires:

  1. A Cnx compatible collection.
  2. CnxRange(T) has been fully instantiated for the type contained in your collection (<C2nxt/Range.h> has been included and in scope with RANGE_T defined to the type and and RANGE_DECL defined to TRUE, and it has been included in exactly one translation unit in your binary with RANGE_T defined to the type and RANGE_IMPL defined to true).

A Cnx compatible collection provides:

  1. A vtable pointer member variable m_vtable which contains function pointers to the collection's associated functions.
  2. Some category of Cnx compatible iterators (eg: CnxForwardIterator(Ref(T))).
  3. Functions to return begin and end iterators, named begin and end, respectively, in m_vtable. They should take the signature

    YourIteratorCategory(Ref(T)) (*const begin)(YourCollectionType* restrict self);
    YourIteratorCategory(Ref(T)) (*const end)(YourCollectionType* restrict self);
    

    If these are met, your collection can be used with CnxRange(T) and its abstractions.

Example usage of CnxRange(T):

#include <Cnx/Def.h>

#define VECTOR_INCLUDE_DEFAULT_INSTANTIATIONS TRUE
#include <Cnx/Vector.h>
#undef VECTOR_INCLUDE_DEFAULT_INSTANTIATIONS

#define RANGE_INCLUDE_DEFAULT_INSTANTIATIONS TRUE
#include <Cnx/Range.h>
#undef RANGE_INCLUDE_DEFAULT_INSTANTIATIONS

#include <Cnx/IO.h>

// example function to pass to cnx_transform, multiplies all elements by 3
void transform(u32* restrict elem) {
    (*elem) *= 3;
}

// example function to pass to cnx_filter, hides odd elements from view
bool filter(const u32* restrict elem) {
    return *elem % 2 == 0;
}

// example function to pass to cnx_accumulate, sums all elements
u32 accumulate(const u32* restrict current, const u32* restrict elem) {
    return (*current) + (*elem);
}

void example(void) {
    let_mut cnx_vector_scoped(u32) vec = cnx_vector_new(u32);
    ranged_for(i, 0U, 10U) {
        cnx_vector_push_back(vec, i);
    }

    let_mut range = cnx_range_from(u32, vec);

    // prints the elements of `range` (thus the elements of `vec`),
    // with a newline after each element
    // you'll see 0 thru 9
    foreach(elem, range) {
        println("{}", elem);
    }

    // transform the elements with `transform`
    // then filter them out of the view of the created range `range2` `with `filter`
    let_mut range2 = cnx_range_transform_then_filter(range, transform, filter);
    // print the elements in `range2`
    //(thus the elements of `vec` `range2` still sees after `filter`),
    // followed by a newline
    // you'll see multiples of 6 from 0 thru 24
    foreach(elem, range2) {
        println("{}", elem);
    }

    // copy the elements viewed by range (thus the elements in `vec`)
    // into a new vector `vec2`
    let_mut cnx_vector_scoped(u32) vec2 = cnx_range_collect(u32, range);
    // print the elements of `vec`
    // you'll see multiples of 3 from 0 thru 27
    foreach(elem, vec) {
        println("{}", elem);
    }
    // print the elements of `vec2`
    // you'll see multiples of 3 from 0 thru 27,
    //the same output as for `vec`
    foreach(elem, vec2) {
        println("{}", elem);
    }

    // "accumulates" (in this case, sums), the elements in `vec2`
    let acc = cnx_accumulate(u32, vec2, accumulate)
    // prints the accumulation followed by a newline, you'll see 135
    println("{}", acc);
}

// The total output you'll see from above is:
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 0
// 6
// 12
// 18
// 24
// 0
// 3
// 6
// 9
// 12
// 15
// 18
// 21
// 24
// 27
// 0
// 3
// 6
// 9
// 12
// 15
// 18
// 21
// 24
// 27
// 135

Defines

#define CnxRange(T)
Macro alias for an instantiation of CnxRange(T) for the type T
#define CnxRangeFilter(T)
Macro alias for filter function compatible with a CnxRange(T) instantiation.
#define CnxRangeTransform(T)
Macro alias for transform function compatible with a CnxRange(T) instantiation.
#define CnxRangeAccumulator(T)
Macro alias for accumulator function compatible with a CnxRange(T) instantiation.
#define cnx_range_from_iterators_filtered(T, begin, end, filter)
Creates a filtered CnxRange(T)
#define cnx_range_from_iterators(T, begin, end)
Creates a CnxRange(T)
#define cnx_range_from_filtered(T, collection, filter)
Creates a filtered CnxRange(T)
#define cnx_range_from(T, collection)
Creates a CnxRange(T)
#define cnx_range_begin(self)
Returns at the beginning of the CnxRange(T)
#define cnx_range_end(self)
Returns at the end of the CnxRange(T)
#define cnx_range_filter_iterators(T, begin, end, filter)
Creates a filtered CnxRange(T)
#define cnx_range_filter(T, collection, filter)
Creates a filtered CnxRange(T)
#define cnx_range_take_first_from_iterators(T, n, begin, end)
Creates a CnxRange(T) over the first n elements in the iteration.
#define cnx_range_take_first(T, n, collection)
Creates a CnxRange(T) over the first n elements in the collection.
#define cnx_range_collect(T, range)
Collects the elements viewed by the range into a new CnxVector(T)
#define cnx_range_transform(range, transform_function)
Transforms the elements viewed by the CnxRange(T)
#define cnx_transform(T, collection, transform_function)
Transforms the elements in the collection.
#define cnx_range_transform_then_filter(range, transform_function, filter_function)
Transforms the elements viewed by the CnxRange(T), then filters the range.
#define cnx_transform_then_filter(T, collection, transform_function, filter_function)
Transforms the elements in the collection, then returns a filtered CnxRange(T) over the collection.
#define cnx_range_accumulate(range, accumulation_function)
"Accumulates" the elements viewed by the CnxRange(T)
#define cnx_accumulate(T, collection, accumulation_function)
"Accumulates" the elements in the collection

Define documentation

#define CnxRange(T)

Macro alias for an instantiation of CnxRange(T) for the type T

Parameters
T - The type held by the collection CnxRange(T) will abstract over

Used for creating and referencing a typedef for a specific CnxRange(T) instantiation

#define CnxRangeFilter(T)

Macro alias for filter function compatible with a CnxRange(T) instantiation.

Parameters
T - The type held by the collection CnxRange(T) will abstract over

Used for creating and referencing a typedef for a filter function compatible with a specific CnxRange(T) instantiation. A CnxRangeFilter(T) must take the signature:

bool (*filter)(const T* restrict elem);

#define CnxRangeTransform(T)

Macro alias for transform function compatible with a CnxRange(T) instantiation.

Parameters
T - The type held by the collection CnxRange(T) will abstract over

Used for creating and referencing a typedef for a filter function compatible with a specific CnxRange(T) instantiation. A CnxRangeTransform(T) must take the signature:

void (*transform)(T* restrict elem);

#define CnxRangeAccumulator(T)

Macro alias for accumulator function compatible with a CnxRange(T) instantiation.

Parameters
T - The type held by the collection CnxRange(T) will abstract over

Used for creating and referencing a typedef for a filter function compatible with a specific CnxRange(T) instantiation. A CnxRangeAccumulator(T) must take the signature:

T (*accumulator)(const T* current_value, const T* elem);

#define cnx_range_from_iterators_filtered(T, begin, end, filter)

Creates a filtered CnxRange(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
begin - The begin iterator for the collection
end - The end iterator for the collection
filter - The CnxRangeFilter(T) to filter the range with
Returns a CnxRange(T) over the given iteration, filtered with filter

Creates a CnxRange(T) from the given iterators, filtered with the CnxRangeFilter(T), filter

#define cnx_range_from_iterators(T, begin, end)

Creates a CnxRange(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
begin - The begin iterator for the collection
end - The end iterator for the collection
Returns a CnxRange(T) over the given iteration

Creates a CnxRange(T) from the given iterators

#define cnx_range_from_filtered(T, collection, filter)

Creates a filtered CnxRange(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
collection - The collection to abstract into a range
filter - The CnxRangeFilter(T) to filter the range with
Returns a CnxRange(T) over the given collection, filtered with filter

Creates a CnxRange(T) from the given collection, filtered with the CnxRangeFilter(T), filter

#define cnx_range_from(T, collection)

Creates a CnxRange(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
collection - The collection to abstract into a range
Returns a CnxRange(T) over the given collection

Creates a CnxRange(T) from the given collection

#define cnx_range_begin(self)

Returns at the beginning of the CnxRange(T)

Parameters
self - The CnxRange(T) to get an iterator into
Returns a CnxForwardIterator(Ref(T)) at the beginning of the range

Returns a CnxForwardIterator(Ref(T)) into the given CnxRange(T), at the beginning of the iteration

#define cnx_range_end(self)

Returns at the end of the CnxRange(T)

Parameters
self - The CnxRange(T) to get an iterator into
Returns a CnxForwardIterator(Ref(T)) at the end of the range

Returns a CnxForwardIterator(Ref(T)) into the given CnxRange(T), at the end of the iteration

#define cnx_range_filter_iterators(T, begin, end, filter)

Creates a filtered CnxRange(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
begin - The begin iterator for the collection
end - The end iterator for the collection
filter - The CnxRangeFilter(T) to filter the range with
Returns a CnxRange(T) over the given iteration, filtered with filter

Creates a CnxRange(T) from the given iterators, filtered with the CnxRangeFilter(T), filter

#define cnx_range_filter(T, collection, filter)

Creates a filtered CnxRange(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
collection - The collection to abstract into a range
filter - The CnxRangeFilter(T) to filter the range with
Returns a CnxRange(T) over the given collection, filtered with filter

Creates a CnxRange(T) from the given collection, filtered with the CnxRangeFilter(T), filter

#define cnx_range_take_first_from_iterators(T, n, begin, end)

Creates a CnxRange(T) over the first n elements in the iteration.

Parameters
T - The type held by the collection CnxRange(T) will abstract over
n - The number of elements in the iteration to view as the range
begin - The begin iterator for the collection
end - The end iterator for the collection
Returns a CnxRange(T) over the first n elements of the iteration

Creates a CnxRange(T) beginning at begin and ending at begin + n

#define cnx_range_take_first(T, n, collection)

Creates a CnxRange(T) over the first n elements in the collection.

Parameters
T - The type held by the collection CnxRange(T) will abstract over
n - The number of elements in the iteration to view as the range
collection - The collection to abstract into a range
Returns a CnxRange(T) over the first n elements of the iteration

Creates a CnxRange(T) beginning at the beginning of the collection and ending at begin + n

#define cnx_range_collect(T, range)

Collects the elements viewed by the range into a new CnxVector(T)

Parameters
T - The type held by the collection CnxRange(T) will abstract over
range - The CnxRange(T) to collect
Returns a CnxVector(T) containing the elements viewed by range

Creates a new CnxVector(T) and copies the elements viewed by range into it

Requirements

  • Requires that the CnxVector(T) template has been instantiated for T and the instantiation is in scope

#define cnx_range_transform(range, transform_function)

Transforms the elements viewed by the CnxRange(T)

Parameters
range - The CnxRange(T) to transform
transform_function - The CnxRangeTransform(T) to transform elements with
Returns The given range, after applying the transformation

Transforms the elements viewed by the range in place with the CnxRangeTransform(T) function, transform_function

#define cnx_transform(T, collection, transform_function)

Transforms the elements in the collection.

Parameters
T - The type held by the collection CnxRange(T) will abstract over
collection - The collection to abstract into a range
transform_function - The CnxRangeTransform(T) to transform elements with
Returns The given range, after applying the transformation

Transforms the elements in the collection in place with the CnxRangeTransform(T) function, transform_function, and returns a CnxRange(T) viewing the collection

#define cnx_range_transform_then_filter(range, transform_function, filter_function)

Transforms the elements viewed by the CnxRange(T), then filters the range.

Parameters
range - The CnxRange(T) to transform and filter
transform_function - The CnxRangeTransform(T) to transform elements with
filter_function - The CnxRangeFilter(T) to filter the range with
Returns The given range, after applying the transformation, filtered

Transforms the elements viewed by the range in place with the CnxRangeTransform(T) function, transform_function, then filters the range with the CnxRangeFilter(T), filter_function

#define cnx_transform_then_filter(T, collection, transform_function, filter_function)

Transforms the elements in the collection, then returns a filtered CnxRange(T) over the collection.

Parameters
T - The type held by the collection CnxRange(T) will abstract over
collection - The collection to abstract into a range
transform_function - The CnxRangeTransform(T) to transform elements with
filter_function - The CnxRangeFilter(T) to filter the range with
Returns The given range, after applying the transformation, filtered

Transforms the elements viewed in the collection in place with the CnxRangeTransform(T) function, transform_function, then returns a range over the collection filtered with the CnxRangeFilter(T), filter_function

#define cnx_range_accumulate(range, accumulation_function)

"Accumulates" the elements viewed by the CnxRange(T)

Parameters
range - The CnxRange(T) to accumulate the elements of
accumulation_function - The CnxRangeAccumulator(T) to accumulate elements with
Returns The resulting accumulation

"Accumulates" the elements viewed by the given CnxRange(T) with the CnxRangeAccumulator(T), accumulation_function, returning the result

#define cnx_accumulate(T, collection, accumulation_function)

"Accumulates" the elements in the collection

Parameters
T - The type held by the collection CnxRange(T) will abstract over
collection - The collection to accumulate
accumulation_function - The CnxRangeAccumulator(T) to accumulate elements with
Returns The resulting accumulation

"Accumulates" the elements in the given collection with the CnxRangeAccumulator(T), accumulation_function, returning the result