02b65a5e86d69c51f72d590153472914dd9faed5
[senf.git] / senf / Packets / VariantParser.hh
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 public header */
25
26 #ifndef HH_SENF_Packets_VariantParser_
27 #define HH_SENF_Packets_VariantParser_ 1
28
29 #ifndef HH_SENF_Packets_Packets_
30 #error "Don't include 'VariantParser.hh' directly, include 'Packets.hh'"
31 #endif
32
33 // Custom includes
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"
40
41 //#include "VariantParser.mpp"
42 ///////////////////////////////hh.p////////////////////////////////////////
43
44 namespace senf {
45
46 #   ifndef SENF_LIMIT_PARSE_VARIANT
47         /** \brief Maximum number of senf::VariantParser sub-parsers.
48
49             This number defines the maximum number of parser arguments senf::VariantParser takes.
50          */
51 #       define SENF_LIMIT_PARSE_VARIANT 6
52 #   endif
53
54     /** \brief Variant parser
55
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.
58
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.
62         \code
63         typedef senf::VariantParser<
64             MyAuxPolicy,
65             senf::mpl::vector<senf::VoidPacketParser, TypeAParser, TypeBParser> > MyVariantParser;
66         \endcode
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
69         optional.
70
71         When creating a new packet containing a variant parser, the variant parser will always be
72         initialized to the first sub-parser.
73
74         \see
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
78      */
79     template <class AuxPolicy, class Parsers>
80     class VariantParser
81         : public PacketParserBase, private AuxPolicy
82     {
83         typedef Parsers parsers;
84
85     public:
86         ///\name Parser interface
87         ///\{
88
89         VariantParser(data_iterator i, state_type s);
90         VariantParser(AuxPolicy policy, data_iterator i, state_type s);
91
92         size_type bytes() const;
93         void init();
94
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;
98
99         ///\}
100         ///////////////////////////////////////////////////////////////////////////
101
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)
107                                           */
108
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 */
117
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
122                                              selected variant.
123                                              \post variant() == \a N */
124     };
125
126     /** \brief Define VariantParser field
127
128         This macro is a special helper to define a senf::VariantParser type field.
129         \code
130         struct SomeParser : public PacketParserBase
131         {
132         #   include SENF_PARSER()
133
134             SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
135             SENF_PARSER_VARIANT( content, type,
136                                     (novalue( disable,      senf::VoidPacketParser ))
137                                     (     id( uint8value,   senf::UInt8Parser      ))
138                                     (     id( uint16value,  senf::UInt16Parser     ))
139                                     (     id( uint24value,  senf::UInt24Parser     ))
140                                     (     id( uint32value,  senf::UInt32Parser     )) );
141
142             SENF_PARSER_FINALIZE(SomeParser);
143         };
144         \endcode
145
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.
148
149         \warning Realize, that the \a chooser field is controlled by the variant parser. This field
150             should therefore be declared either read-only or private and must be changed only via
151             the variant parser.
152
153         The \a types parameter specifies the types of sub-objects supported by this variant
154         parser. This parameter is a (Boost.Preprocessor style) sequence
155         <pre>(\a type) (\a type) ...</pre>
156         of parser types with additional optional information:
157
158         <table class="senf fixedcolumn">
159         <tr><td>\a type</td><td>Do not provide accessor and use the 0-based type index as
160         key.</td></tr>
161
162         <tr><td>\c id(\a name, \a type)</td><td>Automatically create an accessor \a name, a test
163         function <tt>has_</tt>\a name and a function to switch to this type <tt>init_</tt>\a name
164         for this type. Identical to \c ids(\a name, <tt>has_</tt>\a name, <tt>init_</tt>\a name, \a
165         type)</td></tr>
166
167         <tr><td>\c novalue(\a name, \a type)</td><td>This is like \c id but only provides an
168         initializer called \a name and no accessor. Identical to \c ids(\c na, \c na, \a name, \a
169         type)</td></tr>
170
171         <tr><td>\c ids(\a accessorId, \a testId, \a initId, \a type)</td><td>This is again like \c
172         id but the names of the accessor, test function and init function are given
173         explicitly. Setting any of the id's to \c na will disable that function.</td></tr>
174
175         <tr><td>\c key(\a value, \a type)</td><td>Use \a value to identity this type. The type is
176         selected, when the \a chooser is equal to \a value</td></tr>
177
178         <tr><td>\c id(\a name, \c key(\a value, \a type))<br/>\c novalue(\a name, \c key(\a value,
179         \a type))</td><td>The options may be nested in this way.</td></tr>
180         </table>
181
182         Whenever an id is specified for any type, the variant itself will automatically be made
183         private so the only access to the variant from the outside is via the accessors.
184
185         The functions defined by specifying an id are:
186
187         <table class="senf fixedcolumn">
188         <tr><td><em>name</em><tt>_t</tt></td><td>The type for this specific variant value if not \c
189         novalue.</td></tr>
190
191         <tr><td><em>name</em><tt>_t</tt> <em>name</em>()</td><td>Return the variant value at this id
192         if not \c novalue.</td></tr>
193
194         <tr><td><tt>void</tt> <tt>init_</tt><em>name</em>()</td><td>Set the variant to have a value
195         of this type. If the field is \c novalue, the \c init_ prefix is omitted.</td></tr>
196
197         <tr><td><tt>bool</tt> <tt>has_</tt><em>name</em>()</td><td>Return \c true, if the variant
198         currently holds this kind of value, \c false otherwise. Only if not \c novalue.</td></tr>
199         </table>
200
201         If \c key specs are given, they designate the value to expect in the \a chooser field to
202         select a specific variant type. If the \a chooser value does not match any key, the variant
203         will be initialized to the \e first type.
204
205         Further additional tags are supported which modify the way, the \a chooser field is
206         interpreted:
207
208         <table class="senf fixedcolumn">
209         <tr><td>\c transform(\a transform, \a chooser)</td><td>The \a transform is applied to the \a
210         chooser value, the value is not used directly</td>
211         </table>
212
213         The optional \a transform is a class with the following layout
214
215         \code
216         struct MyTransform
217         {
218             typedef ... value_type;
219             static value_type get(other_type v);
220             static other_type set(value_type v);
221         };
222         \endcode \c other_type is the \a chooser ::\c value_type whereas the \c value_type typedef
223         is the arbitrary return type of the transform.
224
225         The tags are applied to the \a chooser parameter:
226         \code
227         SENF_PARSER_VARIANT ( content, transform(MyTransform, type),
228                                             (senf::VoidPacketParser)
229                                             (senf::UInt8Parser)
230                                             (senf::UInt16Parser)
231                                             (senf::UInt24Parser)
232                                             (senf::UInt32Parser) );
233         \endcode
234
235         \param[in] name name of the field
236         \param[in] chooser name of the field choosing the variant to use
237         \param[in] types a Boost.Preprocessor style sequence of sub-parser types
238
239         \see
240             senf::VariantParser for the VariantParser API\n
241             \ref SENF_PARSER_PRIVATE_VARIANT()
242         \hideinitializer
243         \ingroup packetparsermacros
244      */
245 #   define SENF_PARSER_VARIANT(name, chooser, types) \
246         SENF_PARSER_VARIANT_I(public, name, chooser, types)
247
248     /** \brief Define private VariantParser field
249
250         \see \ref SENF_PARSER_VARIANT()
251         \hideinitializer
252         \ingroup packetparsermacros
253      */
254 #   define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
255         SENF_PARSER_VARIANT_I(protected, name, chooser, types)
256 }
257
258 ///////////////////////////////hh.e////////////////////////////////////////
259 #endif
260 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_VariantParser_i_)
261 #define HH_SENF_Packets_VariantParser_i_
262 //#include "VariantParser.cci"
263 #include "VariantParser.ct"
264 #include "VariantParser.cti"
265 #endif
266
267 \f
268 // Local Variables:
269 // mode: c++
270 // fill-column: 100
271 // comment-column: 40
272 // c-file-style: "senf"
273 // indent-tabs-mode: nil
274 // ispell-local-dictionary: "american"
275 // compile-command: "scons -u test"
276 // End: