1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifndef CCAN_GENERATOR_H
3 #define CCAN_GENERATOR_H
7 #error Generators require typeof
10 #if !HAVE_STATEMENT_EXPR
11 #error Generators require statement expressions
18 #include <ccan/cppmagic/cppmagic.h>
19 #include <ccan/compiler/compiler.h>
20 #include <ccan/coroutine/coroutine.h>
22 #if !COROUTINE_AVAILABLE
23 #error Generators require coroutines
27 * Internals - included just for the use of inlines and macros
31 struct coroutine_state gen;
32 struct coroutine_state caller;
37 static inline struct generator_ *generator_state_(const void *ret)
39 return (struct generator_ *)ret - 1;
42 static inline void *generator_argp_(const void *ret)
44 return generator_state_(ret)->base;
47 struct generator_incomplete_;
49 #define generator_rtype_(gen_) \
50 typeof((*(gen_))((struct generator_incomplete_ *)NULL))
52 void *generator_new_(void (*fn)(void *), size_t retsize);
53 void generator_free_(void *ret, size_t retsize);
60 * generator_t - type for an in-progress generator
61 * @rtype: type of values the generator yield
63 #define generator_t(rtype_) \
64 typeof(rtype_ (*)(struct generator_incomplete_ *))
67 * generator_declare - declare (but don't define) a generator function
68 * @name: name for the generator
69 * @rtype: return type for the generator
71 * Declares (as an extern) a generator function named @name, which
72 * will yield return values of type @rtype.
75 * generator_declare(count_to_3, int);
77 #define generator_declare(name_, rtype_, ...) \
78 generator_t(rtype_) name_(generator_parms_outer_(__VA_ARGS__))
81 * generator_def - define a generator function
82 * @name: name for the generator
83 * @rtype: return type for the generator
85 * Define a generator function named @name yielding return values of
86 * type @rtype. The generator_def() line is followed immediately by a
87 * block containing the generator's code.
90 * generator_def(count_to_3, int)
97 #define generator_parm_(t_, n_) t_ n_
98 #define generator_parms_(...) \
99 CPPMAGIC_2MAP(generator_parm_, __VA_ARGS__)
100 #define generator_parms_inner_(...) \
101 CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
102 (, generator_parms_(__VA_ARGS__))()
103 #define generator_parms_outer_(...) \
104 CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
105 (generator_parms_(__VA_ARGS__))(void)
106 #define generator_argfield_(t_, n_) t_ n_;
107 #define generator_argstruct_(...) \
109 CPPMAGIC_JOIN(, CPPMAGIC_2MAP(generator_argfield_, \
112 #define generator_arg_unpack_(t_, n_) args->n_
113 #define generator_args_unpack_(...) \
114 CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \
115 (, CPPMAGIC_2MAP(generator_arg_unpack_, __VA_ARGS__))()
116 #define generator_arg_pack_(t_, n_) args->n_ = n_
117 #define generator_args_pack_(...) \
118 CPPMAGIC_JOIN(;, CPPMAGIC_2MAP(generator_arg_pack_, __VA_ARGS__))
119 #define generator_def_(name_, rtype_, storage_, ...) \
120 static void name_##_generator_(rtype_ *ret_ \
121 generator_parms_inner_(__VA_ARGS__)); \
122 static void name_##_generator__(void *ret) \
124 struct generator_ *gen; \
125 UNNEEDED generator_argstruct_(__VA_ARGS__) *args; \
126 gen = generator_state_(ret); \
127 args = generator_argp_(ret); \
128 name_##_generator_(ret generator_args_unpack_(__VA_ARGS__)); \
129 gen->complete = true; \
130 coroutine_jump(&gen->caller); \
133 storage_ generator_t(rtype_) \
134 name_(generator_parms_outer_(__VA_ARGS__)) \
136 generator_t(rtype_) gen = generator_new_(name_##_generator__, \
138 UNNEEDED generator_argstruct_(__VA_ARGS__) *args = \
139 generator_argp_(gen); \
140 generator_args_pack_(__VA_ARGS__); \
143 static void name_##_generator_(rtype_ *ret_ \
144 generator_parms_inner_(__VA_ARGS__))
145 #define generator_def(name_, rtype_, ...) \
146 generator_def_(name_, rtype_, , __VA_ARGS__)
149 * generator_def_static - define a private / local generator function
150 * @name: name for the generator
151 * @rtype: return type for the generator
153 * As generator_def, but the resulting generator function will be
154 * local to this module.
156 #define generator_def_static(name_, rtype_, ...) \
157 generator_def_(name_, rtype_, static, __VA_ARGS__)
160 * generator_yield - yield (return) a value from a generator
161 * @val: value to yield
163 * Invoke only from within a generator. Yield the given value to the
164 * caller. This will stop execution of the generator code until the
165 * caller next invokes generator_next(), at which point it will
166 * continue from the generator_yield statement.
168 #define generator_yield(val_) \
170 struct generator_ *gen_ = generator_state_(ret_); \
172 coroutine_switch(&gen_->gen, &gen_->caller); \
176 * generator_next - get next value from a generator
177 * @gen: a generator state variable
179 * Returns a pointer to a (correctly typed) buffer containing the next
180 * value yielded by @gen, or NULL if @gen is finished. The buffer
181 * contents is only valid until the next time @gen is called or
184 static inline void *generator_next_(void *ret_)
186 struct generator_ *gen = generator_state_(ret_);
191 coroutine_switch(&gen->caller, &gen->gen);
193 return gen->complete ? NULL : ret_;
195 #define generator_next(gen_) \
196 ((generator_rtype_(gen_) *)generator_next_(gen_))
199 * generator_next_val - store next value from a generator
200 * @val: a variable of type suitable to store the generator's return
202 * @gen: a generator state variable
204 * Returns 'true' if @gen yielded a new value, false if @gen is
205 * complete. If a new value was yielded, it is stored in @val.
207 #define generator_next_val(val_, gen_) \
209 generator_rtype_(gen_) *ret; \
210 ret = generator_next(gen_); \
216 #define generator_free(gen_) \
217 generator_free_((generator_rtype_(gen_) *)(gen_), \
218 sizeof(generator_rtype_(gen_)))
220 #endif /* CCAN_GENERATOR_H */