This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Because I don't know if I'm going to switch to dynamic arrays or something tomorrow, and I don't want all the code using my code to have to be changed.
It's lightweight, doesn't need macros, and is typesafe in user land.
It's missing ways of going backwards or peeking ahead, but you can do those in userland (see \Ref{Buffering}). I don't believe it's possible to layer them between the user and the provider in C in a typesafe way.
[ You can provide peek(..., iter, offset) if you want... ]
(these are in iter_demo.c).
void simple_example() { iter i={0,0}; char *s; while (( s=get_next_string_in_sequence(&i) )) { printf("s is 's'
", s); } }
More complex usage, with iteration being abandoned in the middle:
void medium_example() { iter i={0,0}; char *s; while (( s=get_next_string_in_sequence(&i) )) { if (!strcmp(s, "special terminate value")) { iter_reset(&i); / * free any resources * / break; } printf("s is 's'
", s); } }
What do you do if you want to peer ahead in the sequence? You have to keep that state yourself.
There are two examples in iter_demo.c.
There's probably a way to factor this better, but I'm not sure how.
If your internal structure is an array or a linked list, where the iterator can just be a pointer, then just user iter.state as that pointer. Something like this:
void get_next_string_in_sequence(iter *i) { static char **strings = { "john", "jacob", "jingleheimer", 0 }; char *result; result = strings[i->state++]; if (!result) i->state = 0; return result; }
If your internal structure is something where you need more than a single pointer to traverse it, such as a tree structure with only downward links, then you'll need to allocate that traversal-management structure when called with i->state == 0, and set i->reset to a function which frees the structure and sets the state to 0. Before you return 0 on the last call, you should call that reset function yourself.
Definition in file iter.h.
|
Value: if ((i)->state) { \ if ((i)->reset) (*((i)->reset))(i); \ } else { \ (i)->state = 0; \ } (Otherwise some implementations will hold onto resources.) |
|
Declare as "iter" each iterator you want to use, in the caller's memory. Be sure to initialize it to {0,0} like: iter x = {0,0}; |