Packets: Adjust SENF_PARSER_VARIANT implementation for better public/private support
[senf.git] / 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_VariantParser_
27 #define IH_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 ///////////////////////////////ih.p////////////////////////////////////////
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     private:                                                                                      \
128         typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) >         \
129             BOOST_PP_CAT(name, _parsers);                                                         \
130         typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type              \
131             BOOST_PP_CAT(name,_chooser_value_type);                                               \
132         BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types),                                    \
133                      SENF_PARSER_VARIANT_MAKETRANSFORM,                                           \
134                      SENF_PARSER_VARIANT_NOTRANSFORM )(name,                                      \
135                                                        types)                                     \
136         typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers),                  \
137                                                    BOOST_PP_CAT(name, _transform) >               \
138             BOOST_PP_CAT(name, _traits);                                                          \
139     public:                                                                                       \
140         SENF_PARSER_COLLECTION_I(                                                                 \
141             BOOST_PP_IIF( SENF_PARSER_VARIANT_NEEDACCESSORS(types), private, access),             \
142             name, chooser, BOOST_PP_CAT(name, _traits) );                                         \
143     access:                                                                                       \
144         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types)                        \
145     public:
146
147 #   define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types)                                         \
148         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types)                        \
149         template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()>                             \
150         struct BOOST_PP_CAT(name, _key_value_template)                                            \
151             : public senf::detail::VariantKey<BOOST_PP_CAT(name, _chooser_value_type), KeyFn> {}; \
152         template <class T, T (*K)()> friend class senf::detail::VariantKey;                   \
153         typedef senf::detail::VariantKeyTransform<                                                \
154             BOOST_PP_CAT(name,_chooser_value_type),                                               \
155             boost::mpl::vector<                                                                   \
156                 BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types))                     \
157             > > BOOST_PP_CAT(name, _transform);
158
159 #   define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem)                                         \
160         static BOOST_PP_CAT(name, _chooser_value_type)                                            \
161             BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)()                                           \
162                 { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
163
164 #   define SENF_PARSER_VARIANT_NOTRANSFORM(name, types)                                           \
165         typedef void BOOST_PP_CAT(name, _transform);
166
167 #   define SENF_PARSER_VARIANT_KEYVALUES(name, types)                                             \
168         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
169
170 #   define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem)                                       \
171         (BOOST_PP_CAT(name,_key_value_template)<                                                  \
172              & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
173
174 #   define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem)                                         \
175         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem),                                             \
176                      SENF_PARSER_VARIANT_MAKEACCESSOR,                                            \
177                      SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
178
179 #   define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
180 #   define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem)                                        \
181         SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, SENF_PARSER_VARIANT_GETID(elem))    \
182         SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, SENF_PARSER_VARIANT_GETHASID(elem))   \
183         SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, SENF_PARSER_VARIANT_GETINITID(elem))
184
185 #   define SENF_PARSER_VARIANT_IFNOTNA(id, x)                                                     \
186         BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
187     
188 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, id)                              \
189         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
190             typedef SENF_PARSER_VARIANT_GETTYPE(elem)                                             \
191                 BOOST_PP_CAT(id, _t);                                                             \
192             BOOST_PP_CAT(id, _t) id() const                                                       \
193                 { return name().get<i>(); }                                                       \
194         )
195                                      
196 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id)                                \
197         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
198             bool id() const                                                                       \
199                 { return name().variant() == i; }                                                 \
200         )
201
202 #   define SENF_PARSER_VARIANT_MAKEACCESSOR_INIT(name, i, elem, id)                               \
203         SENF_PARSER_VARIANT_IFNOTNA( id,                                                          \
204             void id() const                                                                       \
205             { name().init<i>(); }                                                                 \
206         )
207
208 #   define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
209 #   define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
210 #   define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
211
212 #   define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
213 #   define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
214 #   define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
215 #   define SENF_PARSER_VARIANT_ID_GETHASID__id(id, value) SENF_CAT_RECURS3(has_, id)
216 #   define SENF_PARSER_VARIANT_ID_GETINITID__id(id, value) SENF_CAT_RECURS3(init_, id)
217
218 #   define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
219 #   define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) na
220 #   define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
221 #   define SENF_PARSER_VARIANT_ID_GETHASID__novalue(id, value) na
222 #   define SENF_PARSER_VARIANT_ID_GETINITID__novalue(id, value) id
223
224 #   define SENF_PARSER_VARIANT_ID_GOBBLE__ids(id, hasid, initid, value)
225 #   define SENF_PARSER_VARIANT_ID_GETID__ids(id, hasid, initid, value) id
226 #   define SENF_PARSER_VARIANT_ID_GETVALUE__ids(id, hasid, initid, value) value
227 #   define SENF_PARSER_VARIANT_ID_GETHASID__ids(id, hasid, initid, value) hasid
228 #   define SENF_PARSER_VARIANT_ID_GETINITID__ids(id, hasid, initid, value) initid
229
230 #   define SENF_PARSER_VARIANT_NA_GOBBLE__na
231
232 #   define SENF_PARSER_VARIANT_NA(x)                                                              \
233         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_NA_GOBBLE__, x) )
234
235 #   define SENF_PARSER_VARIANT_HASKEY(x)                                                          \
236         SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
237
238 #   define SENF_PARSER_VARIANT_HASKEY_(x)                                                         \
239         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
240
241 #   define SENF_PARSER_VARIANT_GETKEY(x, default)                                                 \
242         SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
243
244 #   define SENF_PARSER_VARIANT_GETKEY_(x, default)                                                \
245         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
246                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x),                           \
247                      default )
248
249 #   define SENF_PARSER_VARIANT_HASID(x)                                                           \
250         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
251
252 #   define SENF_PARSER_VARIANT_GETID(x)                                                           \
253         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
254
255 #   define SENF_PARSER_VARIANT_GETHASID(x)                                                        \
256         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETHASID__, x)
257
258 #   define SENF_PARSER_VARIANT_GETINITID(x)                                                       \
259         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETINITID__, x)
260
261 #   define SENF_PARSER_VARIANT_GETVALUE(x)                                                        \
262         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x),                                                \
263                      BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x),                          \
264                      x )
265
266 #   define SENF_PARSER_VARIANT_GETTYPE(x)                                                         \
267         SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
268
269 #   define SENF_PARSER_VARIANT_GETTYPE_(x)                                                        \
270         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
271                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x),                          \
272                      x )
273
274 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM(types)                                               \
275         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
276
277 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem)                                     \
278         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
279
280 #   define SENF_PARSER_VARIANT_NEEDACCESSORS(types)                                               \
281         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDACCESSORS_, 0, types)
282
283 #   define SENF_PARSER_VARIANT_NEEDACCESSORS_(s, state, elem)                                     \
284         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASID(elem))
285
286 #   define SENF_PARSER_VARIANT_TYPES(types)                                                       \
287         BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
288
289 #   define SENF_PARSER_VARIANT_TYPES_(r, _, elem)                                                 \
290         (SENF_PARSER_VARIANT_GETTYPE(elem))
291
292 #endif
293
294 }}
295
296 ///////////////////////////////ih.e////////////////////////////////////////
297 #endif
298
299 \f
300 // Local Variables:
301 // mode: c++
302 // fill-column: 100
303 // comment-column: 40
304 // c-file-style: "senf"
305 // indent-tabs-mode: nil
306 // ispell-local-dictionary: "american"
307 // compile-command: "scons -u test"
308 // End: