4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief VariantParser internal header */
31 #ifndef IH_SENF_Packets_VariantParser_
32 #define IH_SENF_Packets_VariantParser_ 1
35 #include "PacketParser.hh"
36 #include <boost/preprocessor/cat.hpp>
37 #include <boost/preprocessor/seq/enum.hpp>
38 #include <boost/preprocessor/seq/fold_left.hpp>
39 #include <boost/preprocessor/seq/for_each.hpp>
40 #include <boost/preprocessor/logical/or.hpp>
41 #include <boost/preprocessor/seq/for_each_i.hpp>
42 #include <boost/preprocessor/logical/not.hpp>
43 #include <boost/preprocessor/expr_if.hpp>
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
52 template <class Variant, unsigned N>
54 static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
57 template <class Variant>
58 struct VariantBytes<Variant,0> {
59 static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
62 template <class Transform, class AuxPolicy, class AuxTag>
63 struct VariantParserPolicy;
65 template <class AuxPolicy, class AuxTag>
66 struct VariantParserPolicy<void, AuxPolicy, AuxTag>
69 template <class Transform, class AuxPolicy, class AuxTag>
70 struct VariantParserPolicy
71 : public VariantParserPolicy< void,
72 TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
75 template <class AuxPolicy>
76 struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
78 typedef AuxPolicy type;
81 template <class AuxPolicy, class Transform>
82 struct VariantParserPolicy<void,
84 senf::detail::auxtag::transform<Transform,
85 senf::detail::auxtag::none> >
87 typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
90 template <class Parsers, class Transform>
91 struct VariantParserTraits
93 template <class AuxPolicy, class AuxTag>
95 typedef senf::VariantParser<
96 typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
101 template <class T, T (*KeyFn)()>
104 static T key() { return (*KeyFn)(); }
107 template <class T, class Keys>
108 struct VariantKeyTransform
110 typedef unsigned value_type;
111 typedef T input_type;
112 static unsigned get(input_type v);
113 static input_type set(unsigned v);
116 template <class In, class Out, class Keys, unsigned N>
117 struct VariantKeyTransformCheck
119 static Out get(In v);
120 static In set(Out v);
123 template <class In, class Out, class Keys>
124 struct VariantKeyTransformCheck<In, Out, Keys, 0>
126 static Out get(In v);
127 static In set(Out v);
130 # define SENF_PARSER_VARIANT_I(access, name, chooser, types) \
131 SENF_PARSER_REQUIRE_VAR(variant) \
133 typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) > \
134 BOOST_PP_CAT(name, _parsers); \
136 typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type \
137 BOOST_PP_CAT(name,_chooser_value_type); \
138 BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types), \
139 SENF_PARSER_VARIANT_MAKETRANSFORM, \
140 SENF_PARSER_VARIANT_NOTRANSFORM )(name, \
142 typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers), \
143 BOOST_PP_CAT(name, _transform) > \
144 BOOST_PP_CAT(name, _traits); \
146 SENF_PARSER_COLLECTION_I( \
147 BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), protected, access), \
148 name, chooser, BOOST_PP_CAT(name, _traits) ); \
150 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types) \
153 # define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types) \
154 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types) \
155 template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()> \
156 struct BOOST_PP_CAT(name, _key_value_template) \
157 : public senf::detail::VariantKey<BOOST_PP_CAT(name, _chooser_value_type), KeyFn> {}; \
158 template <class T, T (*K)()> friend struct senf::detail::VariantKey; \
159 typedef senf::detail::VariantKeyTransform< \
160 BOOST_PP_CAT(name,_chooser_value_type), \
161 boost::mpl::vector< \
162 BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types)) \
163 > > BOOST_PP_CAT(name, _transform);
165 # define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem) \
166 static BOOST_PP_CAT(name, _chooser_value_type) \
167 BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)() \
168 { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
170 # define SENF_PARSER_VARIANT_NOTRANSFORM(name, types) \
171 typedef void BOOST_PP_CAT(name, _transform);
173 # define SENF_PARSER_VARIANT_KEYVALUES(name, types) \
174 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
176 # define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem) \
177 (BOOST_PP_CAT(name,_key_value_template)< \
178 & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
180 # define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem) \
181 BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem), \
182 SENF_PARSER_VARIANT_MAKEACCESSOR, \
183 SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
185 # define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
186 # define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem) \
187 SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, SENF_PARSER_VARIANT_GETID(elem)) \
188 SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, SENF_PARSER_VARIANT_GETHASID(elem)) \
189 SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, SENF_PARSER_VARIANT_GETINITID(elem))
191 # define SENF_PARSER_VARIANT_IFNOTNA(id, x) \
192 BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
194 # define SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, id) \
195 SENF_PARSER_VARIANT_IFNOTNA( id, \
196 typedef SENF_PARSER_VARIANT_GETTYPE(elem) \
197 BOOST_PP_CAT(id, _t); \
198 BOOST_PP_CAT(id, _t) id() const \
199 { return name().get<i>(); } \
202 # define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id) \
203 SENF_PARSER_VARIANT_IFNOTNA( id, \
205 { return name().variant() == i; } \
208 # define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id) \
209 SENF_PARSER_VARIANT_IFNOTNA( id, \
211 { name().init<i>(); } \
214 # define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
215 # define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
216 # define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
218 # define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
219 # define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
220 # define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
221 # define SENF_PARSER_VARIANT_ID_GETHASID__id(id, value) SENF_CAT_RECURS3(has_, id)
222 # define SENF_PARSER_VARIANT_ID_GETINITID__id(id, value) SENF_CAT_RECURS3(init_, id)
224 # define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
225 # define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) na
226 # define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
227 # define SENF_PARSER_VARIANT_ID_GETHASID__novalue(id, value) na
228 # define SENF_PARSER_VARIANT_ID_GETINITID__novalue(id, value) id
230 # define SENF_PARSER_VARIANT_ID_GOBBLE__ids(id, hasid, initid, value)
231 # define SENF_PARSER_VARIANT_ID_GETID__ids(id, hasid, initid, value) id
232 # define SENF_PARSER_VARIANT_ID_GETVALUE__ids(id, hasid, initid, value) value
233 # define SENF_PARSER_VARIANT_ID_GETHASID__ids(id, hasid, initid, value) hasid
234 # define SENF_PARSER_VARIANT_ID_GETINITID__ids(id, hasid, initid, value) initid
236 # define SENF_PARSER_VARIANT_NA_GOBBLE__na
238 # define SENF_PARSER_VARIANT_NA(x) \
239 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
241 # define SENF_PARSER_VARIANT_HASKEY(x) \
242 SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
244 # define SENF_PARSER_VARIANT_HASKEY_(x) \
245 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
247 # define SENF_PARSER_VARIANT_GETKEY(x, default) \
248 SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
250 # define SENF_PARSER_VARIANT_GETKEY_(x, default) \
251 BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x), \
252 BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x), \
255 # define SENF_PARSER_VARIANT_HASID(x) \
256 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
258 # define SENF_PARSER_VARIANT_GETID(x) \
259 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
261 # define SENF_PARSER_VARIANT_GETHASID(x) \
262 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
264 # define SENF_PARSER_VARIANT_GETINITID(x) \
265 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
267 # define SENF_PARSER_VARIANT_GETVALUE(x) \
268 BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x), \
269 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x), \
272 # define SENF_PARSER_VARIANT_GETTYPE(x) \
273 SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
275 # define SENF_PARSER_VARIANT_GETTYPE_(x) \
276 BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x), \
277 BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x), \
280 # define SENF_PARSER_VARIANT_NEEDTRANSFORM(types) \
281 BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
283 # define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem) \
284 BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
286 # define SENF_PARSER_VARIANT_NEEDACCESSORS(types) \
287 BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
289 # define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem) \
290 BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
292 # define SENF_PARSER_VARIANT_TYPES(types) \
293 BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
295 # define SENF_PARSER_VARIANT_TYPES_(r, _, elem) \
296 (SENF_PARSER_VARIANT_GETTYPE(elem))
302 //-/////////////////////////////////////////////////////////////////////////////////////////////////
309 // comment-column: 40
310 // c-file-style: "senf"
311 // indent-tabs-mode: nil
312 // ispell-local-dictionary: "american"
313 // compile-command: "scons -u test"