Packets: Implement additional SENF_PARSER_VARIANT options (keys, accessors)
[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         typedef boost::mpl::vector< BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_TYPES(types)) >         \
126             BOOST_PP_CAT(name, _parsers);                                                         \
127         typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_GETAUX(chooser), _t)::value_type              \
128             BOOST_PP_CAT(name,_chooser_value_type);                                               \
129         BOOST_PP_IF( SENF_PARSER_VARIANT_NEEDTRANSFORM(types),                                    \
130                      SENF_PARSER_VARIANT_MAKETRANSFORM,                                           \
131                      SENF_PARSER_VARIANT_NOTRANSFORM )(name,                                      \
132                                                        types)                                     \
133         typedef senf::detail::VariantParserTraits< BOOST_PP_CAT(name, _parsers),                  \
134                                                    BOOST_PP_CAT(name, _transform) >               \
135             BOOST_PP_CAT(name, _traits);                                                          \
136         SENF_PARSER_COLLECTION_I(                                                                 \
137             access, name, chooser, BOOST_PP_CAT(name, _traits) );                                 \
138         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_ACCESSOR, name, types)
139
140 #   define SENF_PARSER_VARIANT_MAKETRANSFORM(name, types)                                         \
141         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUE, name, types)                        \
142         template <BOOST_PP_CAT(name, _chooser_value_type) (*KeyFn)()>                             \
143         struct BOOST_PP_CAT(name, _key_value_template)                                            \
144             : public senf::detail::VariantKey<BOOST_PP_CAT(name, _chooser_value_type), KeyFn> {}; \
145         typedef senf::detail::VariantKeyTransform<                                                \
146             BOOST_PP_CAT(name,_chooser_value_type),                                               \
147             boost::mpl::vector<                                                                   \
148                 BOOST_PP_SEQ_ENUM(SENF_PARSER_VARIANT_KEYVALUES(name, types))                     \
149             > > BOOST_PP_CAT(name, _transform);
150
151 #   define SENF_PARSER_VARIANT_KEYVALUE(r, name, i, elem)                                         \
152         static BOOST_PP_CAT(name, _chooser_value_type)                                            \
153             BOOST_PP_CAT(BOOST_PP_CAT(name, _key_),i)()                                           \
154                 { return SENF_PARSER_VARIANT_GETKEY(elem, i); }
155
156 #   define SENF_PARSER_VARIANT_NOTRANSFORM(name, types)                                           \
157         typedef void BOOST_PP_CAT(name, _transform);
158
159 #   define SENF_PARSER_VARIANT_KEYVALUES(name, types)                                             \
160         BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
161
162 #   define SENF_PARSER_VARIANT_KEYVALUES_(r, name, i, elem)                                       \
163         (BOOST_PP_CAT(name,_key_value_template)<                                                  \
164              & BOOST_PP_CAT(BOOST_PP_CAT(name, _key_), i) >)
165
166 #   define SENF_PARSER_VARIANT_ACCESSOR(r, name, i, elem)                                         \
167         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(elem),                                             \
168                      SENF_PARSER_VARIANT_MAKEACCESSOR,                                            \
169                      SENF_PARSER_VARIANT_NOACCESSOR )(name, i, elem)
170
171 #   define SENF_PARSER_VARIANT_NOACCESSOR(name, i, elem)
172 #   define SENF_PARSER_VARIANT_MAKEACCESSOR(name, i, elem)                                        \
173         BOOST_PP_IF( SENF_PARSER_VARIANT_HASVALUE(elem),                                          \
174                      SENF_PARSER_VARIANT_MAKEVACCESSOR,                                           \
175                      SENF_PARSER_VARIANT_MAKENVACCESSOR )(name, i, elem)
176
177 #   define SENF_PARSER_VARIANT_MAKEVACCESSOR(name, i, elem)                                       \
178         SENF_PARSER_VARIANT_GETTYPE(elem) SENF_PARSER_VARIANT_GETID(elem)()                       \
179         { return name().get<i>(); }                                                               \
180         void BOOST_PP_CAT(init_, SENF_PARSER_VARIANT_GETID(elem))()                               \
181         { name().init<i>(); }                                                                     \
182         bool BOOST_PP_CAT(has_, SENF_PARSER_VARIANT_GETID(elem))()                                \
183         { return name().variant() == i; }
184
185 #   define SENF_PARSER_VARIANT_MAKENVACCESSOR(name, i, elem)                                      \
186         void SENF_PARSER_VARIANT_GETID(elem)()                                                    \
187         { name().init<i>(); }
188
189 #   define SENF_PARSER_VARIANT_KEY_GOBBLE__key(key, type)
190 #   define SENF_PARSER_VARIANT_KEY_GETKEY__key(key, type) key
191 #   define SENF_PARSER_VARIANT_KEY_GETTYPE__key(key, type) type
192
193 #   define SENF_PARSER_VARIANT_ID_GOBBLE__id(id, value)
194 #   define SENF_PARSER_VARIANT_ID_GETID__id(id, value) id
195 #   define SENF_PARSER_VARIANT_ID_GETVALUE__id(id, value) value
196
197 #   define SENF_PARSER_VARIANT_ID_GOBBLE__novalue(id, value)
198 #   define SENF_PARSER_VARIANT_ID_GETID__novalue(id, value) id
199 #   define SENF_PARSER_VARIANT_ID_GETVALUE__novalue(id, value) value
200
201 #   define SENF_PARSER_VARIANT_HASVALUE_GOBBLE__id(id, value)
202
203 #   define SENF_PARSER_VARIANT_HASKEY(x)                                                          \
204         SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
205
206 #   define SENF_PARSER_VARIANT_HASKEY_(x)                                                         \
207         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
208
209 #   define SENF_PARSER_VARIANT_GETKEY(x, default)                                                 \
210         SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
211
212 #   define SENF_PARSER_VARIANT_GETKEY_(x, default)                                                \
213         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
214                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETKEY__, x),                           \
215                      default )
216
217 #   define SENF_PARSER_VARIANT_HASID(x)                                                           \
218         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
219
220 #   define SENF_PARSER_VARIANT_GETID(x)                                                           \
221         BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
222
223 #   define SENF_PARSER_VARIANT_GETVALUE(x)                                                        \
224         BOOST_PP_IF( SENF_PARSER_VARIANT_HASID(x),                                                \
225                      BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETVALUE__, x),                          \
226                      x )
227
228 #   define SENF_PARSER_VARIANT_HASVALUE(x)                                                        \
229         BOOST_PP_IS_EMPTY( SENF_CAT_RECURS3(SENF_PARSER_VARIANT_HASVALUE_GOBBLE__, x) )
230
231 #   define SENF_PARSER_VARIANT_GETTYPE(x)                                                         \
232         SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
233
234 #   define SENF_PARSER_VARIANT_GETTYPE_(x)                                                        \
235         BOOST_PP_IF( SENF_PARSER_VARIANT_HASKEY_(x),                                              \
236                      BOOST_PP_CAT(SENF_PARSER_VARIANT_KEY_GETTYPE__, x),                          \
237                      x )
238
239 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM(types)                                               \
240         BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
241
242 #   define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem)                                     \
243         BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
244
245 #   define SENF_PARSER_VARIANT_TYPES(types)                                                       \
246         BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
247
248 #   define SENF_PARSER_VARIANT_TYPES_(r, _, elem)                                                 \
249         (SENF_PARSER_VARIANT_GETTYPE(elem))
250
251 #endif
252
253 }}
254
255 ///////////////////////////////ih.e////////////////////////////////////////
256 #endif
257
258 \f
259 // Local Variables:
260 // mode: c++
261 // fill-column: 100
262 // comment-column: 40
263 // c-file-style: "senf"
264 // indent-tabs-mode: nil
265 // ispell-local-dictionary: "american"
266 // compile-command: "scons -u test"
267 // End: