fd68088358e3a693c73d102af0f2324a6dbb7c24
[senf.git] / senf / Packets / VariantParser.ih
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief VariantParser internal header */
25
26 #ifndef IH_SENF_Packets_VariantParser_
27 #define IH_SENF_Packets_VariantParser_ 1
28
29 // Custom includes
30 #include "PacketParser.hh"
31 #include <boost/preprocessor/cat.hpp>
32 #include <boost/preprocessor/seq/enum.hpp>
33 #include <boost/preprocessor/seq/fold_left.hpp>
34 #include <boost/preprocessor/seq/for_each.hpp>
35 #include <boost/preprocessor/logical/or.hpp>
36 #include <boost/preprocessor/seq/for_each_i.hpp>
37 #include <boost/preprocessor/logical/not.hpp>
38 #include <boost/preprocessor/expr_if.hpp>
39
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41
42 namespace senf {
43 namespace detail {
44
45 #ifndef DOXYGEN
46
47     template <class Variant, unsigned N>
48     struct VariantBytes {
49         static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
50     };
51
52     template <class Variant>
53     struct VariantBytes<Variant,0> {
54         static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
55     };
56
57     template <class Transform, class AuxPolicy, class AuxTag>
58     struct VariantParserPolicy;
59
60     template <class AuxPolicy, class AuxTag>
61     struct VariantParserPolicy<void, AuxPolicy, AuxTag>
62     {};
63
64     template <class Transform, class AuxPolicy, class AuxTag>
65     struct VariantParserPolicy
66         : public VariantParserPolicy< void,
67                                       TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
68     {};
69
70     template <class AuxPolicy>
71     struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
72     {
73         typedef AuxPolicy type;
74     };
75
76     template <class AuxPolicy, class Transform>
77     struct VariantParserPolicy<void,
78                                AuxPolicy,
79                                senf::detail::auxtag::transform<Transform,
80                                                                senf::detail::auxtag::none> >
81     {
82         typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
83     };
84
85     template <class Parsers, class Transform>
86     struct VariantParserTraits
87     {
88         template <class AuxPolicy, class AuxTag>
89         struct parser {
90             typedef senf::VariantParser<
91                 typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
92                 Parsers> type;
93         };
94     };
95
96     template <class T, T (*KeyFn)()>
97     struct VariantKey
98     {
99         static T key() { return (*KeyFn)(); }
100     };
101
102     template <class T, class Keys>
103     struct VariantKeyTransform
104     {
105         typedef unsigned value_type;
106         typedef T input_type;
107         static unsigned get(input_type v);
108         static input_type set(unsigned v);
109     };
110
111     template <class In, class Out, class Keys, unsigned N>
112     struct VariantKeyTransformCheck
113     {
114         static Out get(In v);
115         static In set(Out v);
116     };
117
118     template <class In, class Out, class Keys>
119     struct VariantKeyTransformCheck<In, Out, Keys, 0>
120     {
121         static Out get(In v);
122         static In set(Out v);
123     };
124
125 #   define SENF_PARSER_VARIANT_I(access, name, chooser, types)                                    \
126         SENF_PARSER_REQUIRE_VAR(variant)                                                          \
127     protected:                                                                                    \
128         typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) >         \
129             BOOST_PP_CAT(name, _parsers);                                                         \
130     private:                                                                                      \
131         typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type              \
132             BOOST_PP_CAT(name,_chooser_value_type);                                               \
133         BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types),                                    \
134                      SENF_PARSER_VARIANT_MAKETRANSFORM,                                           \
135                      SENF_PARSER_VARIANT_NOTRANSFORM )(name,                                      \
136                                                        types)                                     \
137         typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers),                  \
138                                                    BOOST_PP_CAT(name, _transform) >               \
139             BOOST_PP_CAT(name, _traits);                                                          \
140     public:                                                                                       \
141         SENF_PARSER_COLLECTION_I(                                                                 \
142             BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), protected, access),           \
143             name, chooser, BOOST_PP_CAT(name, _traits) );                                         \
144     access:                                                                                       \
145         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types)                        \
146     public:
147
148 #   define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types)                                         \
149         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types)                        \
150         template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()>                             \
151         struct BOOST_PP_CAT(name, _key_value_template)                                            \
152             : public senf::detail::VariantKey<BOOST_PP_CAT(name, _chooser_value_type), KeyFn> {}; \
153         template <class T, T (*K)()> friend class senf::detail::VariantKey;                       \
154         typedef senf::detail::VariantKeyTransform<                                                \
155             BOOST_PP_CAT(name,_chooser_value_type),                                               \
156             boost::mpl::vector<                                                                   \
157                 BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types))                     \
158             > > BOOST_PP_CAT(name, _transform);
159
160 #   define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem)                                         \
161         static BOOST_PP_CAT(name, _chooser_value_type)                                            \
162             BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)()                                           \
163                 { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
164
165 #   define SENF_PARSER_VARIANT_NOTRANSFORM(name, types)                                           \
166         typedef void BOOST_PP_CAT(name, _transform);
167
168 #   define SENF_PARSER_VARIANT_KEYVALUES(name, types)                                             \
169         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
170
171 #   define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem)                                       \
172         (BOOST_PP_CAT(name,_key_value_template)<                                                  \
173              & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
174
175 #   define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem)                                         \
176         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem),                                             \
177                      SENF_PARSER_VARIANT_MAKEACCESSOR,                                            \
178                      SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
179
180 #   define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
181 #   define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem)                                        \
182         SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, SENF_PARSER_VARIANT_GETID(elem))    \
183         SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, SENF_PARSER_VARIANT_GETHASID(elem))   \
184         SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, SENF_PARSER_VARIANT_GETINITID(elem))
185
186 #   define SENF_PARSER_VARIANT_IFNOTNA(id, x)                                                     \
187         BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
188
189 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, id)                              \
190         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
191             typedef SENF_PARSER_VARIANT_GETTYPE(elem)                                             \
192                 BOOST_PP_CAT(id, _t);                                                             \
193             BOOST_PP_CAT(id, _t) id() const                                                       \
194                 { return name().get<i>(); }                                                       \
195         )
196
197 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id)                                \
198         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
199             bool id() const                                                                       \
200                 { return name().variant() == i; }                                                 \
201         )
202
203 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id)                               \
204         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
205             void id() const                                                                       \
206             { name().init<i>(); }                                                                 \
207         )
208
209 #   define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
210 #   define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
211 #   define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
212
213 #   define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
214 #   define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
215 #   define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
216 #   define SENF_PARSER_VARIANT_ID_GETHASID__id(id, value) SENF_CAT_RECURS3(has_, id)
217 #   define SENF_PARSER_VARIANT_ID_GETINITID__id(id, value) SENF_CAT_RECURS3(init_, id)
218
219 #   define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
220 #   define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) na
221 #   define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
222 #   define SENF_PARSER_VARIANT_ID_GETHASID__novalue(id, value) na
223 #   define SENF_PARSER_VARIANT_ID_GETINITID__novalue(id, value) id
224
225 #   define SENF_PARSER_VARIANT_ID_GOBBLE__ids(id, hasid, initid, value)
226 #   define SENF_PARSER_VARIANT_ID_GETID__ids(id, hasid, initid, value) id
227 #   define SENF_PARSER_VARIANT_ID_GETVALUE__ids(id, hasid, initid, value) value
228 #   define SENF_PARSER_VARIANT_ID_GETHASID__ids(id, hasid, initid, value) hasid
229 #   define SENF_PARSER_VARIANT_ID_GETINITID__ids(id, hasid, initid, value) initid
230
231 #   define SENF_PARSER_VARIANT_NA_GOBBLE__na
232
233 #   define SENF_PARSER_VARIANT_NA(x)                                                              \
234         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
235
236 #   define SENF_PARSER_VARIANT_HASKEY(x)                                                          \
237         SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
238
239 #   define SENF_PARSER_VARIANT_HASKEY_(x)                                                         \
240         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
241
242 #   define SENF_PARSER_VARIANT_GETKEY(x, default)                                                 \
243         SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
244
245 #   define SENF_PARSER_VARIANT_GETKEY_(x, default)                                                \
246         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
247                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x),                           \
248                      default )
249
250 #   define SENF_PARSER_VARIANT_HASID(x)                                                           \
251         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
252
253 #   define SENF_PARSER_VARIANT_GETID(x)                                                           \
254         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
255
256 #   define SENF_PARSER_VARIANT_GETHASID(x)                                                        \
257         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
258
259 #   define SENF_PARSER_VARIANT_GETINITID(x)                                                       \
260         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
261
262 #   define SENF_PARSER_VARIANT_GETVALUE(x)                                                        \
263         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x),                                                \
264                      BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x),                          \
265                      x )
266
267 #   define SENF_PARSER_VARIANT_GETTYPE(x)                                                         \
268         SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
269
270 #   define SENF_PARSER_VARIANT_GETTYPE_(x)                                                        \
271         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
272                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x),                          \
273                      x )
274
275 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM(types)                                               \
276         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
277
278 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem)                                     \
279         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
280
281 #   define SENF_PARSER_VARIANT_NEEDACCESSORS(types)                                               \
282         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
283
284 #   define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem)                                     \
285         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
286
287 #   define SENF_PARSER_VARIANT_TYPES(types)                                                       \
288         BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
289
290 #   define SENF_PARSER_VARIANT_TYPES_(r, _, elem)                                                 \
291         (SENF_PARSER_VARIANT_GETTYPE(elem))
292
293 #endif
294
295 }}
296
297 //-/////////////////////////////////////////////////////////////////////////////////////////////////
298 #endif
299
300 \f
301 // Local Variables:
302 // mode: c++
303 // fill-column: 100
304 // comment-column: 40
305 // c-file-style: "senf"
306 // indent-tabs-mode: nil
307 // ispell-local-dictionary: "american"
308 // compile-command: "scons -u test"
309 // End: