VariantParser.ih
Go to the documentation of this file.
1 //
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
6 //
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
11 //
12 
13 
14 /** \file
15  \brief VariantParser internal header */
16 
17 #ifndef IH_SENF_Packets_VariantParser_
18 #define IH_SENF_Packets_VariantParser_ 1
19 
20 // Custom includes
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>
30 
31 //-/////////////////////////////////////////////////////////////////////////////////////////////////
32 
33 namespace senf {
34 namespace detail {
35 
36 #ifndef DOXYGEN
37 
38  template <class Variant, unsigned N>
39  struct VariantBytes {
40  static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
41  };
42 
43  template <class Variant>
44  struct VariantBytes<Variant,0> {
45  static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
46  };
47 
48  template <class Transform, class AuxPolicy, class AuxTag>
49  struct VariantParserPolicy;
50 
51  template <class AuxPolicy, class AuxTag>
52  struct VariantParserPolicy<void, AuxPolicy, AuxTag>
53  {};
54 
55  template <class Transform, class AuxPolicy, class AuxTag>
56  struct VariantParserPolicy
57  : public VariantParserPolicy< void,
58  TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
59  {};
60 
61  template <class AuxPolicy>
62  struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
63  {
64  typedef AuxPolicy type;
65  };
66 
67  template <class AuxPolicy, class Transform>
68  struct VariantParserPolicy<void,
69  AuxPolicy,
70  senf::detail::auxtag::transform<Transform,
71  senf::detail::auxtag::none> >
72  {
73  typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
74  };
75 
76  template <class Parsers, class Transform>
77  struct VariantParserTraits
78  {
79  template <class AuxPolicy, class AuxTag>
80  struct parser {
81  typedef senf::VariantParser<
82  typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
83  Parsers> type;
84  };
85  };
86 
87  template <class T, class Keys>
88  struct VariantKeyTransform
89  {
90  typedef unsigned value_type;
91  typedef T input_type;
92  static unsigned get(input_type v);
93  static input_type set(unsigned v);
94  };
95 
96  template <class In, class Out, class Keys, unsigned N>
97  struct VariantKeyTransformCheck
98  {
99  static Out get(In v);
100  static In set(Out v);
101  };
102 
103  template <class In, class Out, class Keys>
104  struct VariantKeyTransformCheck<In, Out, Keys, 0>
105  {
106  static Out get(In v);
107  static In set(Out v);
108  };
109 
110 # define SENF_PARSER_VARIANT_I(access, name, chooser, types) \
111  SENF_PARSER_REQUIRE_VAR(variant) \
112  protected: \
113  typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) > \
114  BOOST_PP_CAT(name, _parsers); \
115  private: \
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, \
121  types) \
122  typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers), \
123  BOOST_PP_CAT(name, _transform) > \
124  BOOST_PP_CAT(name, _traits); \
125  public: \
126  SENF_PARSER_COLLECTION_I( \
127  BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), protected, access), \
128  name, chooser, BOOST_PP_CAT(name, _traits) ); \
129  access: \
130  BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types) \
131  public:
132 
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)(); } \
138  }; \
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);
146 
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); }
151 
152 # define SENF_PARSER_VARIANT_NOTRANSFORM(name, types) \
153  typedef void BOOST_PP_CAT(name, _transform);
154 
155 # define SENF_PARSER_VARIANT_KEYVALUES(name, types) \
156  BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
157 
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) >)
161 
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)
166 
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))
172 
173 # define SENF_PARSER_VARIANT_IFNOTNA(id, x) \
174  BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
175 
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>(); } \
182  )
183 
184 # define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id) \
185  SENF_PARSER_VARIANT_IFNOTNA( id, \
186  bool id() const \
187  { return name().variant() == i; } \
188  )
189 
190 # define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id) \
191  SENF_PARSER_VARIANT_IFNOTNA( id, \
192  void id() const \
193  { name().init<i>(); } \
194  )
195 
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
199 
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)
205 
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
211 
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
217 
218 # define SENF_PARSER_VARIANT_NA_GOBBLE__na
219 
220 # define SENF_PARSER_VARIANT_NA(x) \
221  BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
222 
223 # define SENF_PARSER_VARIANT_HASKEY(x) \
224  SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
225 
226 # define SENF_PARSER_VARIANT_HASKEY_(x) \
227  BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
228 
229 # define SENF_PARSER_VARIANT_GETKEY(x, default) \
230  SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
231 
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), \
235  default )
236 
237 # define SENF_PARSER_VARIANT_HASID(x) \
238  BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
239 
240 # define SENF_PARSER_VARIANT_GETID(x) \
241  BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
242 
243 # define SENF_PARSER_VARIANT_GETHASID(x) \
244  BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
245 
246 # define SENF_PARSER_VARIANT_GETINITID(x) \
247  BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
248 
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), \
252  x )
253 
254 # define SENF_PARSER_VARIANT_GETTYPE(x) \
255  SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
256 
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), \
260  x )
261 
262 # define SENF_PARSER_VARIANT_NEEDTRANSFORM(types) \
263  BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
264 
265 # define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem) \
266  BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
267 
268 # define SENF_PARSER_VARIANT_NEEDACCESSORS(types) \
269  BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
270 
271 # define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem) \
272  BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
273 
274 # define SENF_PARSER_VARIANT_TYPES(types) \
275  BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
276 
277 # define SENF_PARSER_VARIANT_TYPES_(r, _, elem) \
278  (SENF_PARSER_VARIANT_GETTYPE(elem))
279 
280 #endif
281 
282 }}
283 
284 //-/////////////////////////////////////////////////////////////////////////////////////////////////
285 #endif
286 
287 
288 // Local Variables:
289 // mode: c++
290 // fill-column: 100
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"
296 // End: