f7361e4e537c9134f97648a8d4f713c6affadd47
[senf.git] / senf / Packets / VariantParser.ih
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
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.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief VariantParser internal header */
30
31 #ifndef IH_SENF_Packets_VariantParser_
32 #define IH_SENF_Packets_VariantParser_ 1
33
34 // Custom includes
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>
44
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46
47 namespace senf {
48 namespace detail {
49
50 #ifndef DOXYGEN
51
52     template <class Variant, unsigned N>
53     struct VariantBytes {
54         static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
55     };
56
57     template <class Variant>
58     struct VariantBytes<Variant,0> {
59         static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
60     };
61
62     template <class Transform, class AuxPolicy, class AuxTag>
63     struct VariantParserPolicy;
64
65     template <class AuxPolicy, class AuxTag>
66     struct VariantParserPolicy<void, AuxPolicy, AuxTag>
67     {};
68
69     template <class Transform, class AuxPolicy, class AuxTag>
70     struct VariantParserPolicy
71         : public VariantParserPolicy< void,
72                                       TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
73     {};
74
75     template <class AuxPolicy>
76     struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
77     {
78         typedef AuxPolicy type;
79     };
80
81     template <class AuxPolicy, class Transform>
82     struct VariantParserPolicy<void,
83                                AuxPolicy,
84                                senf::detail::auxtag::transform<Transform,
85                                                                senf::detail::auxtag::none> >
86     {
87         typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
88     };
89
90     template <class Parsers, class Transform>
91     struct VariantParserTraits
92     {
93         template <class AuxPolicy, class AuxTag>
94         struct parser {
95             typedef senf::VariantParser<
96                 typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
97                 Parsers> type;
98         };
99     };
100
101     template <class T, T (*KeyFn)()>
102     struct VariantKey
103     {
104         static T key() { return (*KeyFn)(); }
105     };
106
107     template <class T, class Keys>
108     struct VariantKeyTransform
109     {
110         typedef unsigned value_type;
111         typedef T input_type;
112         static unsigned get(input_type v);
113         static input_type set(unsigned v);
114     };
115
116     template <class In, class Out, class Keys, unsigned N>
117     struct VariantKeyTransformCheck
118     {
119         static Out get(In v);
120         static In set(Out v);
121     };
122
123     template <class In, class Out, class Keys>
124     struct VariantKeyTransformCheck<In, Out, Keys, 0>
125     {
126         static Out get(In v);
127         static In set(Out v);
128     };
129
130 #   define SENF_PARSER_VARIANT_I(access, name, chooser, types)                                    \
131         SENF_PARSER_REQUIRE_VAR(variant)                                                          \
132     protected:                                                                                    \
133         typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) >         \
134             BOOST_PP_CAT(name, _parsers);                                                         \
135     private:                                                                                      \
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,                                      \
141                                                        types)                                     \
142         typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers),                  \
143                                                    BOOST_PP_CAT(name, _transform) >               \
144             BOOST_PP_CAT(name, _traits);                                                          \
145     public:                                                                                       \
146         SENF_PARSER_COLLECTION_I(                                                                 \
147             BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), protected, access),           \
148             name, chooser, BOOST_PP_CAT(name, _traits) );                                         \
149     access:                                                                                       \
150         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types)                        \
151     public:
152
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 class 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);
164
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); }
169
170 #   define SENF_PARSER_VARIANT_NOTRANSFORM(name, types)                                           \
171         typedef void BOOST_PP_CAT(name, _transform);
172
173 #   define SENF_PARSER_VARIANT_KEYVALUES(name, types)                                             \
174         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
175
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) >)
179
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)
184
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))
190
191 #   define SENF_PARSER_VARIANT_IFNOTNA(id, x)                                                     \
192         BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
193
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>(); }                                                       \
200         )
201
202 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id)                                \
203         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
204             bool id() const                                                                       \
205                 { return name().variant() == i; }                                                 \
206         )
207
208 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id)                               \
209         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
210             void id() const                                                                       \
211             { name().init<i>(); }                                                                 \
212         )
213
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
217
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)
223
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
229
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
235
236 #   define SENF_PARSER_VARIANT_NA_GOBBLE__na
237
238 #   define SENF_PARSER_VARIANT_NA(x)                                                              \
239         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
240
241 #   define SENF_PARSER_VARIANT_HASKEY(x)                                                          \
242         SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
243
244 #   define SENF_PARSER_VARIANT_HASKEY_(x)                                                         \
245         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
246
247 #   define SENF_PARSER_VARIANT_GETKEY(x, default)                                                 \
248         SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
249
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),                           \
253                      default )
254
255 #   define SENF_PARSER_VARIANT_HASID(x)                                                           \
256         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
257
258 #   define SENF_PARSER_VARIANT_GETID(x)                                                           \
259         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
260
261 #   define SENF_PARSER_VARIANT_GETHASID(x)                                                        \
262         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
263
264 #   define SENF_PARSER_VARIANT_GETINITID(x)                                                       \
265         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
266
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),                          \
270                      x )
271
272 #   define SENF_PARSER_VARIANT_GETTYPE(x)                                                         \
273         SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
274
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),                          \
278                      x )
279
280 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM(types)                                               \
281         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
282
283 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem)                                     \
284         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
285
286 #   define SENF_PARSER_VARIANT_NEEDACCESSORS(types)                                               \
287         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
288
289 #   define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem)                                     \
290         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
291
292 #   define SENF_PARSER_VARIANT_TYPES(types)                                                       \
293         BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
294
295 #   define SENF_PARSER_VARIANT_TYPES_(r, _, elem)                                                 \
296         (SENF_PARSER_VARIANT_GETTYPE(elem))
297
298 #endif
299
300 }}
301
302 //-/////////////////////////////////////////////////////////////////////////////////////////////////
303 #endif
304
305 \f
306 // Local Variables:
307 // mode: c++
308 // fill-column: 100
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"
314 // End: