4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief VariantParser internal header */
26 #ifndef IH_VariantParser_
27 #define IH_VariantParser_ 1
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>
38 ///////////////////////////////ih.p////////////////////////////////////////
45 template <class Variant, unsigned N>
47 static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
50 template <class Variant>
51 struct VariantBytes<Variant,0> {
52 static PacketParserBase::size_type bytes(Variant const & v, unsigned n);
55 template <class Transform, class AuxPolicy, class AuxTag>
56 struct VariantParserPolicy;
58 template <class AuxPolicy, class AuxTag>
59 struct VariantParserPolicy<void, AuxPolicy, AuxTag>
62 template <class Transform, class AuxPolicy, class AuxTag>
63 struct VariantParserPolicy
64 : public VariantParserPolicy< void,
65 TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
68 template <class AuxPolicy>
69 struct VariantParserPolicy<void, AuxPolicy, senf::detail::auxtag::none>
71 typedef AuxPolicy type;
74 template <class AuxPolicy, class Transform>
75 struct VariantParserPolicy<void,
77 senf::detail::auxtag::transform<Transform,
78 senf::detail::auxtag::none> >
80 typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
83 template <class Parsers, class Transform>
84 struct VariantParserTraits
86 template <class AuxPolicy, class AuxTag>
88 typedef senf::VariantParser<
89 typename VariantParserPolicy<Transform, AuxPolicy, AuxTag>::type,
94 template <class T, T (*KeyFn)()>
97 static T key() { return (*KeyFn)(); }
100 template <class T, class Keys>
101 struct VariantKeyTransform
103 typedef unsigned value_type;
104 typedef T input_type;
105 static unsigned get(input_type v);
106 static input_type set(unsigned v);
109 template <class In, class Out, class Keys, unsigned N>
110 struct VariantKeyTransformCheck
112 static Out get(In v);
113 static In set(Out v);
116 template <class In, class Out, class Keys>
117 struct VariantKeyTransformCheck<In, Out, Keys, 0>
119 static Out get(In v);
120 static In set(Out v);
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, \
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)
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);
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); }
156 # define SENF_PARSER_VARIANT_NOTRANSFORM(name, types) \
157 typedef void BOOST_PP_CAT(name, _transform);
159 # define SENF_PARSER_VARIANT_KEYVALUES(name, types) \
160 BOOST_PP_SEQ_FOR_EACH_I(SENF_PARSER_VARIANT_KEYVALUES_, name, types)
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) >)
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)
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)
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; }
185 # define SENF_PARSER_VARIANT_MAKENVACCESSOR(name, i, elem) \
186 void SENF_PARSER_VARIANT_GETID(elem)() \
187 { name().init<i>(); }
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
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
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
201 # define SENF_PARSER_VARIANT_HASVALUE_GOBBLE__id(id, value)
203 # define SENF_PARSER_VARIANT_HASKEY(x) \
204 SENF_PARSER_VARIANT_HASKEY_( SENF_PARSER_VARIANT_GETVALUE(x) )
206 # define SENF_PARSER_VARIANT_HASKEY_(x) \
207 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_VARIANT_KEY_GOBBLE__, x) )
209 # define SENF_PARSER_VARIANT_GETKEY(x, default) \
210 SENF_PARSER_VARIANT_GETKEY_( SENF_PARSER_VARIANT_GETVALUE(x), default )
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), \
217 # define SENF_PARSER_VARIANT_HASID(x) \
218 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS2(SENF_PARSER_VARIANT_ID_GOBBLE__, x) )
220 # define SENF_PARSER_VARIANT_GETID(x) \
221 BOOST_PP_CAT(SENF_PARSER_VARIANT_ID_GETID__, x)
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), \
228 # define SENF_PARSER_VARIANT_HASVALUE(x) \
229 BOOST_PP_IS_EMPTY( SENF_CAT_RECURS3(SENF_PARSER_VARIANT_HASVALUE_GOBBLE__, x) )
231 # define SENF_PARSER_VARIANT_GETTYPE(x) \
232 SENF_PARSER_VARIANT_GETTYPE_( SENF_PARSER_VARIANT_GETVALUE(x) )
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), \
239 # define SENF_PARSER_VARIANT_NEEDTRANSFORM(types) \
240 BOOST_PP_SEQ_FOLD_LEFT(SENF_PARSER_VARIANT_NEEDTRANSFORM_, 0, types)
242 # define SENF_PARSER_VARIANT_NEEDTRANSFORM_(s, state, elem) \
243 BOOST_PP_OR(state, SENF_PARSER_VARIANT_HASKEY(elem))
245 # define SENF_PARSER_VARIANT_TYPES(types) \
246 BOOST_PP_SEQ_FOR_EACH(SENF_PARSER_VARIANT_TYPES_, _, types)
248 # define SENF_PARSER_VARIANT_TYPES_(r, _, elem) \
249 (SENF_PARSER_VARIANT_GETTYPE(elem))
255 ///////////////////////////////ih.e////////////////////////////////////////
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"