generic_iterators  1.0.0
Demonstration of implementing and using type safe generic iterators in pure, standard C
iterator.h File Reference

Utilities to define and implement an Iterable. More...

Go to the source code of this file.

Macros

#define CONCAT_(A, B)   A##B
 
#define CONCAT(A, B)   CONCAT_(A, B)
 
#define Iterator(T)   T##Iterator
 Convenience macro to get the type of the Iterator (typeclass) with given element type. More...
 
#define Iterable(T)   T##Iterable
 Convenience macro to get the type of the Iterable (typeclass instance) with given element type. More...
 
#define DefineIteratorOf(T)
 Define an Iterator typeclass and its Iterable instance for given element type. More...
 
#define impl_iterator(IterType, ElmntType, Name, next_f)
 Define a function to turn given IterType into an Iterable(ElmntType). More...
 

Detailed Description

Utilities to define and implement an Iterable.

Macro Definition Documentation

◆ DefineIteratorOf

#define DefineIteratorOf (   T)
Value:
typedef typeclass(Maybe(T) (*const next)(void* self)) Iterator(T); \
#define Iterator(T)
Convenience macro to get the type of the Iterator (typeclass) with given element type.
Definition: iterator.h:31
#define Iterable(T)
Convenience macro to get the type of the Iterable (typeclass instance) with given element type.
Definition: iterator.h:48
#define Maybe(T)
Convenience macro to get the type of the Maybe defined with a certain type.
Definition: maybe.h:40
#define typeclass(funcs)
Define a typeclass with the given functions.
Definition: typeclass.h:23
#define typeclass_instance(Typeclass)
Define a typeclass instance for the given typeclass.
Definition: typeclass.h:43

Define an Iterator typeclass and its Iterable instance for given element type.

Example

DefineIteratorOf(int); // Defines an Iterator(int) typeclass as well as its instance
#define DefineIteratorOf(T)
Define an Iterator typeclass and its Iterable instance for given element type.
Definition: iterator.h:65
Parameters
TThe type of value the Iterator instance will yield. Must be alphanumeric.
Note
If T is a pointer, it needs to be typedef-ed into a type that does not contain the *. Only alphanumerics.
A Maybe(T) for the given T must also exist.

◆ impl_iterator

#define impl_iterator (   IterType,
  ElmntType,
  Name,
  next_f 
)
Value:
static inline Maybe(ElmntType) CONCAT(next_f, __)(void* self) \
{ \
Maybe(ElmntType) (*const next_)(IterType self) = (next_f); \
(void)next_; \
return (next_f)(self); \
} \
Iterable(ElmntType) Name(IterType x) \
{ \
static Iterator(ElmntType) const tc = {.next = (CONCAT(next_f, __))}; \
return (Iterable(ElmntType)){.tc = &tc, .self = x}; \
}

Define a function to turn given IterType into an Iterable(ElmntType).

Implement the Iterator typeclass for a type. Essentially defining a wrapper function that returns the Iterable.

The defined function takes in a value of IterType and wraps it in an Iterable - which can be passed around to generic functions working on an iterable.

The term "generic" is used here in the context of the input. As in, the function taking a generic iterable, does not care about what type is backing up the iterable; but, does care about what element type the iterator yields.

Example

// Example of implementing an infinite iterator representing the fibonacci sequence
#include <stdint.h>
typedef struct fibonacci
{
uint32_t curr;
uint32_t next;
} Fibonacci;
DefineMaybe(uint32_t)
DefineIteratorOf(uint32_t);
static Maybe(uint32_t) fibnxt(Fibonacci* self)
{
uint32_t new_nxt = self->curr + self->next;
self->curr = self->next;
self->next = new_nxt;
return Just(new_nxt, uint32_t);
}
// Define a function named `prep_fib_itr`, which takes in a `Fibonacci*` and returns an `Iterable(int)`
// The returned iterable is an infinite fibonacci sequence
impl_iterator(Fibonacci*, uint32_t, prep_fib_itr, fibnxt)
#define impl_iterator(IterType, ElmntType, Name, next_f)
Define a function to turn given IterType into an Iterable(ElmntType).
Definition: iterator.h:123
#define DefineMaybe(T)
Define a Maybe<T> type.
Definition: maybe.h:57
#define Just(v, T)
Wrap a Just value into a Maybe(T).
Definition: maybe.h:91
Parameters
IterTypeThe semantic type (C type) this impl is for, must be a pointer type.
ElmntTypeThe type of value the Iterator instance will yield.
NameName to define the function as.
next_fFunction pointer that serves as the next implementation for IterType. This function must have the signature of Maybe(ElmntType) (*)(IterType self) - i.e, should take IterType and return a value of the corresponding element type wrapped in a Maybe - Nothing value indicates end of iteration.
Note
If ElmntType is a pointer, it needs to be typedef-ed into a type that does not contain the *. Only alphanumerics.
A Maybe(T) for the given ElmntType must exist.
This should not be delimited by a semicolon.

◆ Iterable

#define Iterable (   T)    T##Iterable

Convenience macro to get the type of the Iterable (typeclass instance) with given element type.

Example

Iterable(int) i; // Declares a variable of type Iterable(Int) (the typeclass instance)
Parameters
TThe type of value the Iterable will yield. Must be the same type name passed to DefineIteratorOf(T).
Note
If T is a pointer, it needs to be typedef-ed into a type that does not contain the *. Only alphanumerics.

◆ Iterator

#define Iterator (   T)    T##Iterator

Convenience macro to get the type of the Iterator (typeclass) with given element type.

Example

Iterator(int) i; // Declares a variable of type Iterator(int) (a typeclass)
Parameters
TThe type of value the Iterator instance will yield. Must be the same type name passed to DefineIteratorOf(T).
Note
If T is a pointer, it needs to be typedef-ed into a type that does not contain the *. Only alphanumerics.