4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer NETwork research (NET)
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 public header */
26 #ifndef HH_VariantParser_
27 #define HH_VariantParser_ 1
30 #error "Don't include 'VariantParser.hh' directly, include 'Packets.hh'"
34 #include <boost/mpl/vector.hpp>
35 #include <boost/mpl/at.hpp>
36 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
37 #include <boost/preprocessor/repetition/enum_params.hpp>
38 #include <boost/preprocessor/seq/for_each.hpp>
39 #include "PacketParser.hh"
41 //#include "VariantParser.mpp"
42 #include "VariantParser.ih"
43 ///////////////////////////////hh.p////////////////////////////////////////
47 # ifndef SENF_LIMIT_PARSE_VARIANT
48 /** \brief Maximum number of senf::VariantParser sub-parsers.
50 This number defines the maximum number of parser arguments senf::VariantParser takes.
52 # define SENF_LIMIT_PARSE_VARIANT 6
55 /** \brief Variant parser
57 This is not really a collection parser (it does not provide a collection
58 interface). However, it is not a composite parser or value parser either.
60 A variant parser will parse any number of sub-parsers discriminated by an arbitrary, policy
61 defined condition. This is the parser to use, if the type and/or number of fields of a
62 packet change depending on some condition.
64 typedef senf::VariantParser<
66 senf::VoidPacketParser, TypeAParser, TypeBParser> MyVariantParser;
68 This typedef defines a variant parser choosing one of three sub
69 parsers. senf::VoidPacketParser is an empty parser, it effectively makes this parser
72 When creating a new packet containing a variant parser, the variant parser will always be
73 initialized to the first sub-parser.
76 ExampleVariantPolicy on how to implement the \a VariantPolicy \n
77 \ref SENF_PARSER_VARIANT() on how to integrate the parser into another parser
78 \ingroup parsecollection
80 template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
82 : public PacketParserBase, private VariantPolicy
84 typedef boost::mpl::vector< SENF_PARSE_VARIANT_TPL_ARGS(P) > parsers;
87 ///\name Parser interface
90 VariantParser(data_iterator i, state_type s);
91 VariantParser(VariantPolicy policy, data_iterator i, state_type s);
93 size_type bytes() const;
96 static const size_type init_bytes =
97 senf::init_bytes<P0>::value + VariantPolicy::init_bytes;
100 ///////////////////////////////////////////////////////////////////////////
102 unsigned variant() const; ///< Get current variant
103 /**< Get the currently selected variant index. The returned
104 number directly indexes the list of sub parsers.
105 \returns Index of currently selected variant. Integer
106 in the range from 0 to (number-of-sub-parsers - 1)
109 template <unsigned N>
110 typename boost::mpl::at< parsers, boost::mpl::int_<N> >::type get() const;
111 ///< Access sub-parser
112 /**< This call will return the sub-parser at index \a
113 N. This call will fail, if the currently active
114 variant() is not \a N.
115 \pre variant() == \a N
116 \returns sub-parser at index \a N */
118 template <unsigned N>
119 void init(); ///< Re-initialize field
120 /**< This will reinitialize the field to the variant
121 sub-parser at index \a N changing the currently
123 \post variant() == \a N */
126 /** \brief Variant with direct, fixed distance type field
128 This struct is a template typedef defining a senf::Parser_Variant instantiation. It defines
129 a variant parser which interprets the value returned by some other parser directly as index
130 into the list of sub parsers (the numeric template argument to senf::VariantParser::get()
131 and senf::Parser_Variant::init()).
134 // Define a variant choosing between FooParser and BarParser depending on the directly
135 // preceding 1-byte 8bit uint value
136 typedef senf::DirectVariantParser< senf::UInt8Parser, 1u,
137 FooParser, BarParser >::parser MyVariant;
140 \a ChooserType defines the type of the field used to choose the sub parser. This must be a
141 fixed-size value parser. \a Distance gives the \e fixed distance of this field \e before the
142 currently defined field.
144 It is best to define a field of this type using \ref SENF_PARSER_VARIANT() or \ref
145 SENF_PARSER_PRIVATE_VARIANT().
147 \param[in] ChooserType type of chooser field (a value parser)
148 \param[in] Distance fixed distance of the chooser field before the current field
149 \param[in] P any number of sub parsers
151 \see senf::Parser_Variant
152 \ingroup parsecollection
154 template <class ChooserType, unsigned Distance, class Translator,
155 SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
156 struct DirectVariantParser
158 typedef VariantParser< detail::DirectVariantParser<ChooserType, Distance, Translator>,
159 SENF_PARSE_VARIANT_TPL_ARGS(P) > parser;
162 /** \brief Define DirectVariantParser field
164 This macro is a special helper to define a senf::DirectVariantParser type field. This is a
165 variant field which chooses the sub-type by directly taking the value of some other field.
168 This is a dynamically sized parser. Nevertheless, the chooser field \e must have a
169 \e fixed distance to this field, the \a chooser must be a fixed-size value parser.
172 struct SomeParser : public PacketParserBase
174 # include SENF_PARSER()
176 SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
177 SENF_PARSER_PRIVATE_VARIANT( content, type,
178 (senf::VoidPacketParser)
182 (senf::UInt32Parser) );
184 senf::UInt8Parser uint8() const { return content().get<1>(); }
185 senf::UInt16Parser uint16() const { return content().get<2>(); }
186 senf::UInt24Parser uint24() const { return content().get<3>(); }
187 senf::UInt32Parser uint32() const { return content().get<4>(); }
189 void disable() const { content().init<0>(); }
190 void set_uint8() const { content().init<1>(); }
191 void set_uint16() const { content().init<2>(); }
192 void set_uint24) const { content().init<3>(); }
193 void set_uint23() const { content().init<4>(); }
195 SENF_PARSER_FINALIZE(SomeParser);
199 The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
200 type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
202 It is customary, to hide the variant parser (by defining it private) and provide more
203 conveniently named accessors.
205 \param[in] name name of the field
206 \param[in] chooser name of the field choosing the variant to use
207 \param[in] types a Boost.Preprocessor style sequence of sub-parser types
210 senf::VariantParser \n
211 \ref SENF_PARSER_PRIVATE_VARIANT()
213 \ingroup packetparsermacros
215 # define SENF_PARSER_VARIANT(name, chooser, types) \
216 SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, \
219 senf::detail::VariantParser_IdentityTranslator, \
222 /** \brief Define DirectVariantParser field (private)
224 \see \ref SENF_PARSER_VARIANT()
226 \ingroup packetparsermacros
228 # define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
229 SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, \
232 senf::detail::VariantParser_IdentityTranslator, \
235 /** \brief Define DirectVariantParser field with translator
237 This is like \ref SENF_PARSER_VARIANT(), however it allows to specify a \a translator
238 argument which translates between \a chooser values and type indices:
240 struct SomeTranslator {
241 static unsigned fromChooser(chooser_field_t::value_type value) {
248 static chooser_field_t::value_type toChooser(unsigned value) {
249 static chooser_field_t::value_type table[] const = { 1, 5, 0 };
254 The \a translator class must have two publicly accessible static members, \c fromChooser and
255 \c toChooser. \c fromChooser takes the value as returned by the \a chooser field and must
256 return the corresponding class index whereas \c toChooser takes the class index and must
257 return the value to write into the \a chooser field.
259 \see \ref SENF_PARSER_VARIANT()
261 \ingroup packetparsermacros
263 # define SENF_PARSER_VARIANT_TRANS(name, chooser, translator, types) \
264 SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, \
270 /** \brief Define DirectVariantParser field with translator (private)
272 \see \ref SENF_PARSER_VARIANT_TRANS()
274 \ingroup packetparsermacros
276 # define SENF_PARSER_PRIVATE_VARIANT_TRANS(name, chooser, types) \
277 SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, \
285 ///////////////////////////////hh.e////////////////////////////////////////
287 #if !defined(HH_Packets__decls_) && !defined(HH_VariantParser_i_)
288 #define HH_VariantParser_i_
289 //#include "VariantParser.cci"
290 #include "VariantParser.ct"
291 #include "VariantParser.cti"
298 // comment-column: 40
299 // c-file-style: "senf"
300 // indent-tabs-mode: nil
301 // ispell-local-dictionary: "american"
302 // compile-command: "scons -u test"