4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief VariantParser public header */
31 #ifndef HH_SENF_Packets_VariantParser_
32 #define HH_SENF_Packets_VariantParser_ 1
34 #ifndef HH_SENF_Packets_Packets_
35 #error "Don't include 'VariantParser.hh' directly, include 'Packets.hh'"
39 #include <boost/mpl/vector.hpp>
40 #include <boost/mpl/at.hpp>
41 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
42 #include <boost/preprocessor/repetition/enum_params.hpp>
43 #include <boost/preprocessor/seq/for_each.hpp>
44 #include "PacketParser.hh"
46 //#include "VariantParser.mpp"
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
51 # ifndef SENF_LIMIT_PARSE_VARIANT
52 /** \brief Maximum number of senf::VariantParser sub-parsers.
54 This number defines the maximum number of parser arguments senf::VariantParser takes.
56 # define SENF_LIMIT_PARSE_VARIANT 6
59 /** \brief Variant parser
61 This is not really a collection parser (it does not provide a collection
62 interface). However, it is not a composite parser or value parser either.
64 A variant parser will parse any number of sub-parsers discriminated by an arbitrary, policy
65 defined condition. This is the parser to use, if the type and/or number of fields of a
66 packet change depending on some condition.
68 typedef senf::VariantParser<
70 senf::mpl::vector<senf::VoidPacketParser, TypeAParser, TypeBParser> > MyVariantParser;
72 This typedef defines a variant parser choosing one of three sub
73 parsers. senf::VoidPacketParser is an empty parser, it effectively makes this parser
76 When creating a new packet containing a variant parser, the variant parser will always be
77 initialized to the first sub-parser.
80 ExampleAuxPolicy on how to implement the \a AuxPolicy \n
81 \ref SENF_PARSER_VARIANT() on how to integrate the parser into another parser
82 \ingroup parsecollection
84 template <class AuxPolicy, class Parsers>
86 : public PacketParserBase, private AuxPolicy
88 typedef Parsers parsers;
91 ///\name Parser interface
94 VariantParser(data_iterator i, state_type s);
95 VariantParser(AuxPolicy policy, data_iterator i, state_type s);
97 size_type bytes() const;
100 static const size_type init_bytes = senf::init_bytes<
101 typename boost::mpl::at<parsers, boost::mpl::int_<0> >::type>::value
102 + AuxPolicy::aux_bytes;
105 //-////////////////////////////////////////////////////////////////////////
107 unsigned variant() const; ///< Get current variant
108 /**< Get the currently selected variant index. The returned
109 number directly indexes the list of sub parsers.
110 \returns Index of currently selected variant. Integer
111 in the range from 0 to (number-of-sub-parsers - 1)
114 template <unsigned N>
115 typename boost::mpl::at< parsers, boost::mpl::int_<N> >::type get() const;
116 ///< Access sub-parser
117 /**< This call will return the sub-parser at index \a
118 N. This call will fail, if the currently active
119 variant() is not \a N.
120 \pre variant() == \a N
121 \returns sub-parser at index \a N */
123 template <unsigned N>
124 void init(); ///< Re-initialize field
125 /**< This will reinitialize the field to the variant
126 sub-parser at index \a N changing the currently
128 \post variant() == \a N */
131 /** \brief Define VariantParser field
133 This macro is a special helper to define a senf::VariantParser type field.
135 struct SomeParser : public PacketParserBase
137 # include SENF_PARSER()
139 SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
140 SENF_PARSER_VARIANT( content, type,
141 (novalue( disable, senf::VoidPacketParser ))
142 ( id( uint8value, senf::UInt8Parser ))
143 ( id( uint16value, senf::UInt16Parser ))
144 ( id( uint24value, senf::UInt24Parser ))
145 ( id( uint32value, senf::UInt32Parser )) );
147 SENF_PARSER_FINALIZE(SomeParser);
151 The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
152 type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
154 \warning Realize, that the \a chooser field is controlled by the variant parser. This field
155 should therefore be declared either read-only or private and must be changed only via
158 The \a types parameter specifies the types of sub-objects supported by this variant
159 parser. This parameter is a (Boost.Preprocessor style) sequence
160 <pre>(\a type) (\a type) ...</pre>
161 of parser types with additional optional information:
163 <table class="senf fixedcolumn">
164 <tr><td>\a type</td><td>Do not provide accessor and use the 0-based type index as
167 <tr><td>\c id(\a name, \a type)</td><td>Automatically create an accessor \a name, a test
168 function <tt>has_</tt>\a name and a function to switch to this type <tt>init_</tt>\a name
169 for this type. Identical to \c ids(\a name, <tt>has_</tt>\a name, <tt>init_</tt>\a name, \a
172 <tr><td>\c novalue(\a name, \a type)</td><td>This is like \c id but only provides an
173 initializer called \a name and no accessor. Identical to \c ids(\c na, \c na, \a name, \a
176 <tr><td>\c ids(\a accessorId, \a testId, \a initId, \a type)</td><td>This is again like \c
177 id but the names of the accessor, test function and init function are given
178 explicitly. Setting any of the id's to \c na will disable that function.</td></tr>
180 <tr><td>\c key(\a value, \a type)</td><td>Use \a value to identity this type. The type is
181 selected, when the \a chooser is equal to \a value</td></tr>
183 <tr><td>\c id(\a name, \c key(\a value, \a type))<br/>\c novalue(\a name, \c key(\a value,
184 \a type))</td><td>The options may be nested in this way.</td></tr>
187 Whenever an id is specified for any type, the variant itself will automatically be made
188 private so the only access to the variant from the outside is via the accessors.
190 The functions defined by specifying an id are:
192 <table class="senf fixedcolumn">
193 <tr><td><em>name</em><tt>_t</tt></td><td>The type for this specific variant value if not \c
196 <tr><td><em>name</em><tt>_t</tt> <em>name</em>()</td><td>Return the variant value at this id
197 if not \c novalue.</td></tr>
199 <tr><td><tt>void</tt> <tt>init_</tt><em>name</em>()</td><td>Set the variant to have a value
200 of this type. If the field is \c novalue, the \c init_ prefix is omitted.</td></tr>
202 <tr><td><tt>bool</tt> <tt>has_</tt><em>name</em>()</td><td>Return \c true, if the variant
203 currently holds this kind of value, \c false otherwise. Only if not \c novalue.</td></tr>
206 If \c key specs are given, they designate the value to expect in the \a chooser field to
207 select a specific variant type. If the \a chooser value does not match any key, the variant
208 will be initialized to the \e first type.
210 Further additional tags are supported which modify the way, the \a chooser field is
213 <table class="senf fixedcolumn">
214 <tr><td>\c transform(\a transform, \a chooser)</td><td>The \a transform is applied to the \a
215 chooser value, the value is not used directly</td>
218 The optional \a transform is a class with the following layout
223 typedef ... value_type;
224 static value_type get(other_type v);
225 static other_type set(value_type v);
227 \endcode \c other_type is the \a chooser ::\c value_type whereas the \c value_type typedef
228 is the arbitrary return type of the transform.
230 The tags are applied to the \a chooser parameter:
232 SENF_PARSER_VARIANT ( content, transform(MyTransform, type),
233 (senf::VoidPacketParser)
237 (senf::UInt32Parser) );
240 \param[in] name name of the field
241 \param[in] chooser name of the field choosing the variant to use
242 \param[in] types a Boost.Preprocessor style sequence of sub-parser types
245 senf::VariantParser for the VariantParser API\n
246 \ref SENF_PARSER_PRIVATE_VARIANT()
248 \ingroup packetparsermacros
250 # define SENF_PARSER_VARIANT(name, chooser, types) \
251 SENF_PARSER_VARIANT_I(public, name, chooser, types)
253 /** \brief Define private VariantParser field
255 \see \ref SENF_PARSER_VARIANT()
257 \ingroup packetparsermacros
259 # define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
260 SENF_PARSER_VARIANT_I(protected, name, chooser, types)
263 //-/////////////////////////////////////////////////////////////////////////////////////////////////
265 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_VariantParser_i_)
266 #define HH_SENF_Packets_VariantParser_i_
267 //#include "VariantParser.cci"
268 #include "VariantParser.ct"
269 #include "VariantParser.cti"
276 // comment-column: 40
277 // c-file-style: "senf"
278 // indent-tabs-mode: nil
279 // ispell-local-dictionary: "american"
280 // compile-command: "scons -u test"