Skip to content

Instantly share code, notes, and snippets.

@qexat
Created June 26, 2024 19:25
Show Gist options
  • Save qexat/a97863c12333967a9f944deb5e12da69 to your computer and use it in GitHub Desktop.
Save qexat/a97863c12333967a9f944deb5e12da69 to your computer and use it in GitHub Desktop.
basic generic iterators in C
#include <stdio.h>
#include <stdlib.h>
#define ITERATOR_IMPL(T, state_t) \
struct \
{ \
T (*__next__)(state_t *); \
}
#define ITERATOR_STATE(T) \
struct iterator_state_##T \
{ \
bool finished; \
T data; \
}
#define ITERATOR(T) \
struct iterator_##T \
{ \
ITERATOR_STATE(T) state; \
ITERATOR_IMPL(T, ITERATOR_STATE(T)) impl; \
}
#define ITERATOR_NEW(T, init, next) \
{ \
(ITERATOR_STATE(T)){ \
false, \
(init), \
}, \
{ \
(next) \
} \
}
#define NEXT(iterator) \
({ \
if ((iterator).state.finished) \
{ \
fprintf(stderr, "Error: iterator is finished\n"); \
exit(1); \
} \
(iterator).impl.__next__(&(iterator).state); \
})
#define STOP_ITERATION(iterator) (iterator).state.finished
#define YIELD(value) return (value)
#define ITERATOR_RETURN(state_p) (state_p)->finished = true
int foo(ITERATOR_STATE(int) * state)
{
if (state->finished)
{
return -1;
}
int value = state->data;
state->data++;
if (state->data > 9)
{
ITERATOR_RETURN(state);
}
YIELD(value);
}
int main()
{
ITERATOR(int) x = ITERATOR_NEW(int, 0, foo);
while (!STOP_ITERATION(x))
{
printf("%d\n", NEXT(x));
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment