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.
-
return_type (*iterator_function)(struct_type *it)
-
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 andnext_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'srange
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 (*iterator_function)(counter *it)
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}