iterator.h

View source code here on GitHub!

Includes

IteratorHead(return_type, struct_type)

This macro allows a struct to implement my Iterator API, which is heavily inspired by Python. You should put it at the top of a struct like so:

struct counter {
    IteratorHead(uintmax_t, counter);
    uintmax_t idx;
    uintmax_t stop;
    intmax_t step;
};

It imparts the following internal properties.

return_type (*iterator_function)(struct_type *it)

The function to advance the iterator and return the next element.

bool exhausted : 1

An indicator that tells you if the iterator is exhausted.

bool started : 1

An indicator that tells you if the interator has moved at all.

bool phase : 1

An indicator that flips every time the iterator moves.

IterationHead(it)

This macro implements the base functionality of all Iterator functions. It must be at the top of all iteration functions, with the iterator passed as an argument.

IteratorInitHead(it, advance)

This macro implements the library-managed portion of iterator construction. The first argument should be the uninitialized iterator, and the second argument should be a pointer to its iteration function.

next(state)
next_p(state)

These macros implement the iteration operation. The only difference between them is that next takes in a struct and next_p takes a pointer. Both yield return_type.

type counter

This is an example implementation of the Iterator API used in this project. You can construct it using any of the factory functions found below, and it is generally used much like Python's range object.

uintmax_t (*iterator_function)(counter *it)

The function to advance the iterator and return the next element.

bool exhausted : 1

An indicator that tells you if the iterator is exhausted.

bool started : 1

An indicator that tells you if the interator has moved at all.

bool phase : 1

An indicator that flips every time the iterator moves.

uintmax_t idx

The current position of the counter.

uintmax_t stop

The point before which the counter will stop (as in range).

intmax_t step

The amount by which the counter will move in each iteration (as in range).

uintmax_t iterate_counter(counter *i)
counter counter3(uintmax_t start, uintmax_t stop, intmax_t step)
counter counter2(uintmax_t start, uintmax_t stop)
counter counter1(uintmax_t stop)
  1#pragma once
  2
  3#include <stdbool.h>
  4#include <stdint.h>
  5#include "macros.h"
  6
  7#define IteratorHead(return_type, struct_type) \
  8    return_type (*iterator_function)(struct_type *it); \
  9    bool exhausted : 1; \
 10    bool started : 1; \
 11    bool phase : 1
 12    /**
 13     * The base struct for all iterators in this project
 14     * @return_type: The type that your iterator will yield
 15     * @struct_type: The type that your iterator state is stored in
 16     *
 17     * @iterator_function: The function to advance the iterator and return the next element
 18     * @exhausted: An indicator that tells you if the iterator is exhausted
 19     * @started: An indicator that tells you if the interator has moved at all
 20     * @phase: An indicator that flips every time the iterator moves
 21     *
 22     * See counter for an example implementation
 23     */
 24
 25#define IterationHead(it) \
 26    it->started = 1; \
 27    it->phase = !(it->phase)
 28    /**
 29     * The base macro for all iteration functions in this project
 30     * @it: The pointer to the iterator you are advancing
 31     *
 32     * See counter for an example implementation
 33     */
 34
 35#define IteratorInitHead(it, advance) \
 36    it.iterator_function = &advance; \
 37    it.started = 0; \
 38    it.phase = 0; \
 39    it.exhausted = 0
 40    /**
 41     * The base macro for all iterator initialization functions in this project
 42     * @it: The iterator you are initializing
 43     * @advance: The function this iterator uses to advance
 44     *
 45     * See counter for an example implementation
 46     */
 47
 48#define next(state) (*(state.iterator_function))(&state)
 49    /**
 50     * The macro to advance generic iterators
 51     * @state: The iterator you wish to advance
 52     *
 53     * See counter for an example implementation
 54     */
 55
 56#define next_p(state) (*(state->iterator_function))(state)
 57    /**
 58     * The macro to advance generic iterator pointers
 59     * @state: The pointer to the iterator you wish to advance
 60     *
 61     * See counter for an example implementation
 62     */
 63
 64typedef struct counter counter;
 65struct counter {
 66    /**
 67     * The reference struct for all iterators in this project
 68     * @iterator_function: The function to advance the iterator and return the next element
 69     * @exhausted: An indicator that tells you if the iterator is exhausted
 70     * @started: An indicator that tells you if the interator has moved at all
 71     * @phase: An indicator that flips every time the iterator moves
 72     * @idx: The current position of the counter
 73     * @stop: The point where the counter is exhausted
 74     * @step: The amount to step by each time you iterate the counter
 75     *
 76     * See IteratorHead
 77     */
 78    IteratorHead(uintmax_t, counter);
 79    uintmax_t idx;
 80    uintmax_t stop;
 81    intmax_t step;
 82};
 83
 84uintmax_t iterate_counter(counter *i);
 85inline uintmax_t iterate_counter(counter *i) {
 86    /**
 87     * The function to advance a counter
 88     * @i the counter you want to advance
 89     *
 90     * Returns the next number in the iteration
 91     */
 92    IterationHead(i);
 93    uintmax_t ret = i->idx;
 94    intmax_t step = i->step;
 95    i->idx += step;
 96    if ((step > 0 && i->idx >= i->stop) || (step < 0 && i->idx <= i->stop))
 97        i->exhausted = 1;
 98    return ret;
 99}
100
101counter counter3(uintmax_t start, uintmax_t stop, intmax_t step);
102inline counter counter3(uintmax_t start, uintmax_t stop, intmax_t step) {
103    /**
104     * The base constructor for the counter iterator
105     * @start: The beginning position of the counter
106     * @stop: The point where the counter is exhausted
107     * @step: The amount to step by each time you iterate the counter
108     *
109     * See counter
110     */
111    counter ret;
112    IteratorInitHead(ret, iterate_counter);
113    ret.idx = start;
114    ret.stop = stop;
115    ret.step = step;
116    return ret;
117}
118
119counter counter2(uintmax_t start, uintmax_t stop);
120inline counter counter2(uintmax_t start, uintmax_t stop) {
121    /**
122     * The simpler constructor for the counter iterator
123     * @start: The beginning position of the counter
124     * @stop: The point where the counter is exhausted
125     *
126     * See counter
127     */
128    return counter3(start, stop, 1);
129}
130
131counter counter1(uintmax_t stop);
132inline counter counter1(uintmax_t stop) {
133    /**
134     * The simplest constructor for the counter iterator
135     * @stop: The point where the counter is exhausted
136     *
137     * See counter
138     */
139    return counter2(0, stop);
140}

Tags: c-iterator