1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#ifndef LIBTIO_ITER_H
# define LIBTIO_ITER_H 20180710
# include "cdefs.h"
TIO_BEGIN_NAMESPACE
/* A few things in libtio work using iterators. This is the centralized
* iterator interface. */
struct tio_iter;
typedef struct tio_iter tio_iter_t;
struct tio_iter_functions;
typedef struct tio_iter_functions tio_iter_functions_t;
/* ---
* Define something.
* --- */
/* The way this is done:
*
* When `tio_next()` is called, if there was a previous element,
* the `tio_nextfree_t` callback, if not NULL, will be called to free
* it, then in all cases, the `tio_next_t` callback will be called to
* get the next element. If the `tio_next_t` callback returns
* `tio_error_iter`, all following calls to `tio_next()` with this
* iterator won't call the callbacks and directly return the same error.
*
* When `tio_end()` is called, the `tio_end_t` callback, if not NULL,
* will be called. */
typedef TIO_HOOK_TYPE(int) tio_next_t
OF((void *tio__cookie, void **tio__ptr));
typedef TIO_HOOK_TYPE(void) tio_nextfree_t
OF((void *tio__cookie, void *tio__ptr));
typedef TIO_HOOK_TYPE(void) tio_end_t
OF((void *tio__cookie));
struct tio_iter_functions {
tio_next_t *tio_iter_functions_next;
tio_nextfree_t *tio_iter_functions_nextfree;
tio_end_t *tio_iter_functions_end;
};
/* ---
* Functions.
* --- */
TIO_BEGIN_DECLS
/* Start an iterator with `tio_iter_<whatever>(&iter, <other data>)`,
* with `iter` being of the `tio_iter_t *` type.
* Get the next element through `tio_next_<whatever>(iter, &ptr)`,
* which is usually a macro or function defined as
* `tio_next(iter, (void **)(PTRP))`.
* Then end the iterator using `tio_end(iter)`.
*
* Beware: any time you use `tio_next()` or `tio_end()`, the previous
* element might be free'd or re-used, so if you are interested in what is
* in it, copy the data before using one of the previous functions. */
TIO_EXTERN(int) tio_iter
OF((tio_iter_t **tio__iterp, void *tio__cookie,
tio_iter_functions_t const *tio__funcs));
TIO_EXTERN(int) tio_next
OF((tio_iter_t *tio__iter, void **tio__ptr));
# define tio_end(ITER) tio_free(ITER)
/* You can make a “super iterator” that makes an iterator out of two
* iterators! It will empty the first one, then the second one.
* It will also take care of closing them. */
TIO_EXTERN(int) tio_combine_iterators
OF((tio_iter_t **tio__iterp,
tio_iter_t *tio__first,
tio_iter_t *tio__second));
TIO_END_DECLS
TIO_END_NAMESPACE
#endif /* LIBTIO_ITER_H */
|