#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_(&iter, )`, * with `iter` being of the `tio_iter_t *` type. * Get the next element through `tio_next_(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)); TIO_EXTERN(void) tio_end OF((tio_iter_t *tio__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 */