fa8acdc6dd43aaf8882621c3bef72f927818cd05
[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
38 ///////////////////////////////ih.p////////////////////////////////////////
39
40 namespace senf {
41 namespace detail {
42
43 #ifndef DOXYGEN
44
45     template <class Variant, unsigned N>
46     struct VariantBytes {
47         static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
48     };
49
50     template <class Variant>
51     struct VariantBytes<Variant,0> {
52         static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
53     };
54
55     template <class Transform, class AuxPolicy, class AuxTag>
56     struct VariantParserPolicy;
57
58     template <class AuxPolicy, class AuxTag>
59     struct VariantParserPolicy<void, AuxPolicy, AuxTag>
60     {};
61
62     template <class Transform, class AuxPolicy, class AuxTag>
63     struct VariantParserPolicy
64         : public VariantParserPolicy< void, 
65                                       TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
66     {};
67
68     template <class AuxPolicy>
69     struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
70     {
71         typedef AuxPolicy type;
72     };
73
74     template <class AuxPolicy, class Transform>
75     struct VariantParserPolicy<void,
76                                AuxPolicy, 
77                                senf::detail::auxtag::transform<Transform, 
78                                                                senf::detail::auxtag::none> >
79     {
80         typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
81     };
82
83     template <class Parsers, class Transform>
84     struct VariantParserTraits
85     {
86         template <class AuxPolicy, class AuxTag>
87         struct parser {
88             typedef senf::VariantParser<
89                 typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
90                 Parsers> type;
91         };
92     };
93
94     template <class T, T (*KeyFn)()> 
95     struct VariantKey 
96     {
97         static T key() { return (*KeyFn)(); }
98     };
99
100     template <class T, class Keys>
101     struct VariantKeyTransform
102     {
103         typedef unsigned value_type;
104         typedef T input_type;
105         static unsigned get(input_type v);
106         static input_type set(unsigned v);
107     };
108
109     template <class In, class Out, class Keys, unsigned N>
110     struct VariantKeyTransformCheck
111     {
112         static Out get(In v);
113         static In set(Out v);
114     };
115
116     template <class In, class Out, class Keys>
117     struct VariantKeyTransformCheck<In, Out, Keys, 0>
118     {
119         static Out get(In v);
120         static In set(Out v);
121     };
122     
123 #   define SENF_PARSER_VARIANT_I(access, name, chooser, types)                                    \
124         SENF_PARSER_REQUIRE_VAR(variant)                                                          \
125     private:                                                                                      \
126         typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) >         \
127             BOOST_PP_CAT(name, _parsers);                                                         \
128         typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type              \
129             BOOST_PP_CAT(name,_chooser_value_type);                                               \
130         BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types),                                    \
131                      SENF_PARSER_VARIANT_MAKETRANSFORM,                                           \
132                      SENF_PARSER_VARIANT_NOTRANSFORM )(name,                                      \
133                                                        types)                                     \
134         typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers),                  \
135                                                    BOOST_PP_CAT(name, _transform) >               \
136             BOOST_PP_CAT(name, _traits);                                                          \
137     public:                                                                                       \
138         SENF_PARSER_COLLECTION_I(                                                                 \
139             access, name, chooser, BOOST_PP_CAT(name, _traits) );                                 \
140         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types)
141
142 #   define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types)                                         \
143         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types)                        \
144         template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()>                             \
145         struct BOOST_PP_CAT(name, _key_value_template)                                            \
146             : public senf::detail::VariantKey<BOOST_PP_CAT(name, _chooser_value_type), KeyFn> {}; \
147         template <class T, T (*K)()> friend class senf::detail::VariantKey;                   \
148         typedef senf::detail::VariantKeyTransform<                                                \
149             BOOST_PP_CAT(name,_chooser_value_type),                                               \
150             boost::mpl::vector<                                                                   \
151                 BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types))                     \
152             > > BOOST_PP_CAT(name, _transform);
153
154 #   define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem)                                         \
155         static BOOST_PP_CAT(name, _chooser_value_type)                                            \
156             BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)()                                           \
157                 { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
158
159 #   define SENF_PARSER_VARIANT_NOTRANSFORM(name, types)                                           \
160         typedef void BOOST_PP_CAT(name, _transform);
161
162 #   define SENF_PARSER_VARIANT_KEYVALUES(name, types)                                             \
163         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
164
165 #   define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem)                                       \
166         (BOOST_PP_CAT(name,_key_value_template)<                                                  \
167              & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
168
169 #   define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem)                                         \
170         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem),                                             \
171                      SENF_PARSER_VARIANT_MAKEACCESSOR,                                            \
172                      SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
173
174 #   define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
175 #   define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem)                                        \
176         BOOST_PP_IF( SENF_PARSER_VARIANT_HASVALUE(elem),                                          \
177                      SENF_PARSER_VARIANT_MAKEVACCESSOR,                                           \
178                      SENF_PARSER_VARIANT_MAKENVACCESSOR )(name, i, elem)
179
180 #   define SENF_PARSER_VARIANT_MAKEVACCESSOR(name, i, elem)                                       \
181         typedef SENF_PARSER_VARIANT_GETTYPE(elem)                                                 \
182             BOOST_PP_CAT(SENF_PARSER_VARIANT_GETID(elem), _t);                                    \
183         SENF_PARSER_VARIANT_GETTYPE(elem) SENF_PARSER_VARIANT_GETID(elem)() const                 \
184         { return name().get<i>(); }                                                               \
185         void BOOST_PP_CAT(init_, SENF_PARSER_VARIANT_GETID(elem))() const                         \
186         { name().init<i>(); }                                                                     \
187         bool BOOST_PP_CAT(has_, SENF_PARSER_VARIANT_GETID(elem))() const                          \
188         { return name().variant() == i; }
189
190 #   define SENF_PARSER_VARIANT_MAKENVACCESSOR(name, i, elem)                                      \
191         void SENF_PARSER_VARIANT_GETID(elem)() const                                              \
192         { name().init<i>(); }
193
194 #   define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
195 #   define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
196 #   define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
197
198 #   define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
199 #   define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
200 #   define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
201
202 #   define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
203 #   define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) id
204 #   define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
205
206 #   define SENF_PARSER_VARIANT_HASVALUE_GOBBLE__id(id, value)
207
208 #   define SENF_PARSER_VARIANT_HASKEY(x)                                                          \
209         SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
210
211 #   define SENF_PARSER_VARIANT_HASKEY_(x)                                                         \
212         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
213
214 #   define SENF_PARSER_VARIANT_GETKEY(x, default)                                                 \
215         SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
216
217 #   define SENF_PARSER_VARIANT_GETKEY_(x, default)                                                \
218         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
219                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x),                           \
220                      default )
221
222 #   define SENF_PARSER_VARIANT_HASID(x)                                                           \
223         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
224
225 #   define SENF_PARSER_VARIANT_GETID(x)                                                           \
226         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
227
228 #   define SENF_PARSER_VARIANT_GETVALUE(x)                                                        \
229         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x),                                                \
230                      BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x),                          \
231                      x )
232
233 #   define SENF_PARSER_VARIANT_HASVALUE(x)                                                        \
234         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS3(SENF_PARSER_VARIANT_HASVALUE_GOBBLE__, x) )
235
236 #   define SENF_PARSER_VARIANT_GETTYPE(x)                                                         \
237         SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
238
239 #   define SENF_PARSER_VARIANT_GETTYPE_(x)                                                        \
240         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
241                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x),                          \
242                      x )
243
244 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM(types)                                               \
245         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
246
247 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem)                                     \
248         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
249
250 #   define SENF_PARSER_VARIANT_TYPES(types)                                                       \
251         BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
252
253 #   define SENF_PARSER_VARIANT_TYPES_(r, _, elem)                                                 \
254         (SENF_PARSER_VARIANT_GETTYPE(elem))
255
256 #endif
257
258 }}
259
260 ///////////////////////////////ih.e////////////////////////////////////////
261 #endif
262
263 \f
264 // Local Variables:
265 // mode: c++
266 // fill-column: 100
267 // comment-column: 40
268 // c-file-style: "senf"
269 // indent-tabs-mode: nil
270 // ispell-local-dictionary: "american"
271 // compile-command: "scons -u test"
272 // End: