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 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 ///////////////////////////////hh.p////////////////////////////////////////
46 # ifndef SENF_LIMIT_PARSE_VARIANT
47 /** \brief Maximum number of senf::VariantParser sub-parsers.
49 This number defines the maximum number of parser arguments senf::VariantParser takes.
51 # define SENF_LIMIT_PARSE_VARIANT 6
54 /** \brief Variant parser
56 This is not really a collection parser (it does not provide a collection
57 interface). However, it is not a composite parser or value parser either.
59 A variant parser will parse any number of sub-parsers discriminated by an arbitrary, policy
60 defined condition. This is the parser to use, if the type and/or number of fields of a
61 packet change depending on some condition.
63 typedef senf::VariantParser<
65 senf::mpl::vector<senf::VoidPacketParser, TypeAParser, TypeBParser> > MyVariantParser;
67 This typedef defines a variant parser choosing one of three sub
68 parsers. senf::VoidPacketParser is an empty parser, it effectively makes this parser
71 When creating a new packet containing a variant parser, the variant parser will always be
72 initialized to the first sub-parser.
75 ExampleAuxPolicy on how to implement the \a AuxPolicy \n
76 \ref SENF_PARSER_VARIANT() on how to integrate the parser into another parser
77 \ingroup parsecollection
79 template <class AuxPolicy, class Parsers>
81 : public PacketParserBase, private AuxPolicy
83 typedef Parsers parsers;
86 ///\name Parser interface
89 VariantParser(data_iterator i, state_type s);
90 VariantParser(AuxPolicy policy, data_iterator i, state_type s);
92 size_type bytes() const;
95 static const size_type init_bytes = senf::init_bytes<
96 typename boost::mpl::at<parsers, boost::mpl::int_<0> >::type>::value
97 + AuxPolicy::aux_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 Define VariantParser field
128 This macro is a special helper to define a senf::VariantParser type field.
130 struct SomeParser : public PacketParserBase
132 # include SENF_PARSER()
134 SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
135 SENF_PARSER_VARIANT( content, type,
136 (novalue( disable, senf::VoidPacketParser ))
137 ( id( uint8, senf::UInt8Parser ))
138 ( id( uint16, senf::UInt16Parser ))
139 ( id( uint24, senf::UInt24Parser ))
140 ( id( uint32, senf::UInt32Parser )) );
142 SENF_PARSER_FINALIZE(SomeParser);
146 The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
147 type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
149 The \a types parameter specifies the types of sub-objects supported by this variant
150 parser. This parameter is a (Boost.Preprocessor style) sequence
151 <pre>(\a type) (\a type) ...</pre>
152 of parser types with additional optional information:
154 <table class="senf fixedcolumn">
155 <tr><td>\a type</td><td>Do not provide accessor and use the 0-based type index as
158 <tr><td>\c id(\a name, \a type)</td><td>Automatically create an accessor \a name, a test
159 function <tt>has_</tt>\a name and a function to switch to this type <tt>init_</tt>\a name
160 for this type. Identical to \c ids(\a name, <tt>has_</tt>\a name, <tt>init_</tt>\a name, \a
163 <tr><td>\c novalue(\a name, \a type)</td><td>This is like \c id but only provides an
164 initializer called \a name and no accessor. Identical to \c ids(\c na, \c na, \a name, \a
167 <tr><td>\c ids(\a accessorId, \a testId, \a initId, \a type)</td><td>This is again like \c
168 id but the names of the accessor, test function and init function are given
169 explicitly. Setting any of the id's to \c na will disable that function.</td></tr>
171 <tr><td>\c key(\a value, \a type)</td><td>Use \a value to identity this type. The type is
172 selected, when the \a chooser is equal to \a value</td></tr>
174 <tr><td>\c id(\a name, \c key(\a value, \a type))<br/>\c novalue(\a name, \c key(\a value,
175 \a type))</td><td>The options may be nested in this way.</td></tr>
178 Whenever an id is specified for any type, the variant itself will automatically be made
179 private so the only access to the variant from the outside is via the accessors.
181 The functions defined by specifying an id are:
183 <table class="senf fixedcolumn">
184 <tr><td><em>name</em><tt>_t</tt></td><td>The type for this specific variant value if not \c
187 <tr><td><em>name</em><tt>_t</tt> <em>name</em>()</td><td>Return the variant value at this id
188 if not \c novalue.</td></tr>
190 <tr><td><tt>void</tt> <tt>init_</tt><em>name</em>()</td><td>Set the variant to have a value
191 of this type. If the field is \c novalue, the \c init_ prefix is omitted.</td></tr>
193 <tr><td><tt>bool</tt> <tt>has_</tt><em>name</em>()</td><td>Return \c true, if the variant
194 currently holds this kind of value, \c false otherwise. Only if not \c novalue.</td></tr>
197 If \c key specs are given, they designate the value to expect in the \a chooser field to
198 select a specific variant type. If the \a chooser value does not match any key, the variant
199 will be initialized to the \e first type.
201 Further additional tags are supported which modify the way, the \a chooser field is
204 <table class="senf fixedcolumn">
205 <tr><td>\c transform(\a transform, \a chooser)</td><td>The \a transform is applied to the \a
206 chooser value, the value is not used directly</td>
209 The optional \a transform is a class with the following layout
214 typedef ... value_type;
215 static value_type get(other_type v);
216 static other_type set(value_type v);
218 \endcode \c other_type is the \a chooser ::\c value_type whereas the \c value_type typedef
219 is the arbitrary return type of the transform.
221 The tags are applied to the \a chooser parameter:
223 SENF_PARSER_VARIANT ( content, transform(MyTransform, type),
224 (senf::VoidPacketParser)
228 (senf::UInt32Parser) );
231 \param[in] name name of the field
232 \param[in] chooser name of the field choosing the variant to use
233 \param[in] types a Boost.Preprocessor style sequence of sub-parser types
236 senf::VariantParser for the VariantParser API\n
237 \ref SENF_PARSER_PRIVATE_VARIANT()
239 \ingroup packetparsermacros
241 # define SENF_PARSER_VARIANT(name, chooser, types) \
242 SENF_PARSER_VARIANT_I(public, name, chooser, types)
244 /** \brief Define private VariantParser field
246 \see \ref SENF_PARSER_VARIANT()
248 \ingroup packetparsermacros
250 # define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
251 SENF_PARSER_VARIANT_I(private, name, chooser, types)
254 ///////////////////////////////hh.e////////////////////////////////////////
256 #if !defined(HH_Packets__decls_) && !defined(HH_VariantParser_i_)
257 #define HH_VariantParser_i_
258 //#include "VariantParser.cci"
259 #include "VariantParser.ct"
260 #include "VariantParser.cti"
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"