2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
15 \brief VariantParser internal header */
17 #ifndef IH_SENF_Packets_VariantParser_
18 #define IH_SENF_Packets_VariantParser_ 1
21 #include "PacketParser.hh"
22 #include <boost/preprocessor/cat.hpp>
23 #include <boost/preprocessor/seq/enum.hpp>
24 #include <boost/preprocessor/seq/fold_left.hpp>
25 #include <boost/preprocessor/seq/for_each.hpp>
26 #include <boost/preprocessor/logical/or.hpp>
27 #include <boost/preprocessor/seq/for_each_i.hpp>
28 #include <boost/preprocessor/logical/not.hpp>
29 #include <boost/preprocessor/expr_if.hpp>
31 //-/////////////////////////////////////////////////////////////////////////////////////////////////
38 template <class Variant, unsigned N>
40 static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
43 template <class Variant>
44 struct VariantBytes<Variant,0> {
45 static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
48 template <class Transform, class AuxPolicy, class AuxTag>
49 struct VariantParserPolicy;
51 template <class AuxPolicy, class AuxTag>
52 struct VariantParserPolicy<void, AuxPolicy, AuxTag>
55 template <class Transform, class AuxPolicy, class AuxTag>
56 struct VariantParserPolicy
57 : public VariantParserPolicy< void,
58 TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
61 template <class AuxPolicy>
62 struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
64 typedef AuxPolicy type;
67 template <class AuxPolicy, class Transform>
68 struct VariantParserPolicy<void,
70 senf::detail::auxtag::transform<Transform,
71 senf::detail::auxtag::none> >
73 typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
76 template <class Parsers, class Transform>
77 struct VariantParserTraits
79 template <class AuxPolicy, class AuxTag>
81 typedef senf::VariantParser<
82 typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
87 template <class T, class Keys>
88 struct VariantKeyTransform
90 typedef unsigned value_type;
92 static unsigned get(input_type v);
93 static input_type set(unsigned v);
96 template <class In, class Out, class Keys, unsigned N>
97 struct VariantKeyTransformCheck
100 static In set(Out v);
103 template <class In, class Out, class Keys>
104 struct VariantKeyTransformCheck<In, Out, Keys, 0>
106 static Out get(In v);
107 static In set(Out v);
110 # define SENF_PARSER_VARIANT_I(access, name, chooser, types) \
111 SENF_PARSER_REQUIRE_VAR(variant) \
113 typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) > \
114 BOOST_PP_CAT(name, _parsers); \
116 typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type \
117 BOOST_PP_CAT(name,_chooser_value_type); \
118 BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types), \
119 SENF_PARSER_VARIANT_MAKETRANSFORM, \
120 SENF_PARSER_VARIANT_NOTRANSFORM )(name, \
122 typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers), \
123 BOOST_PP_CAT(name, _transform) > \
124 BOOST_PP_CAT(name, _traits); \
126 SENF_PARSER_COLLECTION_I( \
127 BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), protected, access), \
128 name, chooser, BOOST_PP_CAT(name, _traits) ); \
130 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types) \
133 # define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types) \
134 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types) \
135 template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()> \
136 struct BOOST_PP_CAT(name, _key_value_template) { \
137 static BOOST_PP_CAT(name, _chooser_value_type) key() { return (*KeyFn)(); } \
139 template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()> \
140 friend struct BOOST_PP_CAT(name, _key_value_template); \
141 typedef senf::detail::VariantKeyTransform< \
142 BOOST_PP_CAT(name,_chooser_value_type), \
143 boost::mpl::vector< \
144 BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types)) \
145 > > BOOST_PP_CAT(name, _transform);
147 # define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem) \
148 static BOOST_PP_CAT(name, _chooser_value_type) \
149 BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)() \
150 { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
152 # define SENF_PARSER_VARIANT_NOTRANSFORM(name, types) \
153 typedef void BOOST_PP_CAT(name, _transform);
155 # define SENF_PARSER_VARIANT_KEYVALUES(name, types) \
156 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
158 # define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem) \
159 (BOOST_PP_CAT(name,_key_value_template)< \
160 & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
162 # define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem) \
163 BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem), \
164 SENF_PARSER_VARIANT_MAKEACCESSOR, \
165 SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
167 # define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
168 # define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem) \
169 SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, SENF_PARSER_VARIANT_GETID(elem)) \
170 SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, SENF_PARSER_VARIANT_GETHASID(elem)) \
171 SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, SENF_PARSER_VARIANT_GETINITID(elem))
173 # define SENF_PARSER_VARIANT_IFNOTNA(id, x) \
174 BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
176 # define SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, id) \
177 SENF_PARSER_VARIANT_IFNOTNA( id, \
178 typedef SENF_PARSER_VARIANT_GETTYPE(elem) \
179 BOOST_PP_CAT(id, _t); \
180 BOOST_PP_CAT(id, _t) id() const \
181 { return name().get<i>(); } \
184 # define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id) \
185 SENF_PARSER_VARIANT_IFNOTNA( id, \
187 { return name().variant() == i; } \
190 # define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id) \
191 SENF_PARSER_VARIANT_IFNOTNA( id, \
193 { name().init<i>(); } \
196 # define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
197 # define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
198 # define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
200 # define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
201 # define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
202 # define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
203 # define SENF_PARSER_VARIANT_ID_GETHASID__id(id, value) SENF_CAT_RECURS3(has_, id)
204 # define SENF_PARSER_VARIANT_ID_GETINITID__id(id, value) SENF_CAT_RECURS3(init_, id)
206 # define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
207 # define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) na
208 # define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
209 # define SENF_PARSER_VARIANT_ID_GETHASID__novalue(id, value) na
210 # define SENF_PARSER_VARIANT_ID_GETINITID__novalue(id, value) id
212 # define SENF_PARSER_VARIANT_ID_GOBBLE__ids(id, hasid, initid, value)
213 # define SENF_PARSER_VARIANT_ID_GETID__ids(id, hasid, initid, value) id
214 # define SENF_PARSER_VARIANT_ID_GETVALUE__ids(id, hasid, initid, value) value
215 # define SENF_PARSER_VARIANT_ID_GETHASID__ids(id, hasid, initid, value) hasid
216 # define SENF_PARSER_VARIANT_ID_GETINITID__ids(id, hasid, initid, value) initid
218 # define SENF_PARSER_VARIANT_NA_GOBBLE__na
220 # define SENF_PARSER_VARIANT_NA(x) \
221 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
223 # define SENF_PARSER_VARIANT_HASKEY(x) \
224 SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
226 # define SENF_PARSER_VARIANT_HASKEY_(x) \
227 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
229 # define SENF_PARSER_VARIANT_GETKEY(x, default) \
230 SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
232 # define SENF_PARSER_VARIANT_GETKEY_(x, default) \
233 BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x), \
234 BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x), \
237 # define SENF_PARSER_VARIANT_HASID(x) \
238 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
240 # define SENF_PARSER_VARIANT_GETID(x) \
241 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
243 # define SENF_PARSER_VARIANT_GETHASID(x) \
244 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
246 # define SENF_PARSER_VARIANT_GETINITID(x) \
247 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
249 # define SENF_PARSER_VARIANT_GETVALUE(x) \
250 BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x), \
251 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x), \
254 # define SENF_PARSER_VARIANT_GETTYPE(x) \
255 SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
257 # define SENF_PARSER_VARIANT_GETTYPE_(x) \
258 BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x), \
259 BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x), \
262 # define SENF_PARSER_VARIANT_NEEDTRANSFORM(types) \
263 BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
265 # define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem) \
266 BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
268 # define SENF_PARSER_VARIANT_NEEDACCESSORS(types) \
269 BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
271 # define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem) \
272 BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
274 # define SENF_PARSER_VARIANT_TYPES(types) \
275 BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
277 # define SENF_PARSER_VARIANT_TYPES_(r, _, elem) \
278 (SENF_PARSER_VARIANT_GETTYPE(elem))
284 //-/////////////////////////////////////////////////////////////////////////////////////////////////
291 // comment-column: 40
292 // c-file-style: "senf"
293 // indent-tabs-mode: nil
294 // ispell-local-dictionary: "american"
295 // compile-command: "scons -u test"