switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Packets / VariantParser.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
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.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief VariantParser public header */
30
31 #ifndef HH_SENF_Packets_VariantParser_
32 #define HH_SENF_Packets_VariantParser_ 1
33
34 #ifndef HH_SENF_Packets_Packets_
35 #error "Don't include 'VariantParser.hh' directly, include 'Packets.hh'"
36 #endif
37
38 // Custom includes
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"
45
46 //#include "VariantParser.mpp"
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48
49 namespace senf {
50
51 #   ifndef SENF_LIMIT_PARSE_VARIANT
52         /** \brief Maximum number of senf::VariantParser sub-parsers.
53
54             This number defines the maximum number of parser arguments senf::VariantParser takes.
55          */
56 #       define SENF_LIMIT_PARSE_VARIANT 6
57 #   endif
58
59     /** \brief Variant parser
60
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.
63
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.
67         \code
68         typedef senf::VariantParser<
69             MyAuxPolicy,
70             senf::mpl::vector<senf::VoidPacketParser, TypeAParser, TypeBParser> > MyVariantParser;
71         \endcode
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
74         optional.
75
76         When creating a new packet containing a variant parser, the variant parser will always be
77         initialized to the first sub-parser.
78
79         \see
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
83      */
84     template <class AuxPolicy, class Parsers>
85     class VariantParser
86         : public PacketParserBase, private AuxPolicy
87     {
88         typedef Parsers parsers;
89
90     public:
91         ///\name Parser interface
92         //\{
93
94         VariantParser(data_iterator i, state_type s);
95         VariantParser(AuxPolicy policy, data_iterator i, state_type s);
96
97         size_type bytes() const;
98         void init();
99
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;
103
104         //\}
105         //-////////////////////////////////////////////////////////////////////////
106
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)
112                                           */
113
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 */
122
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
127                                              selected variant.
128                                              \post variant() == \a N */
129     };
130
131     /** \brief Define VariantParser field
132
133         This macro is a special helper to define a senf::VariantParser type field.
134         \code
135         struct SomeParser : public PacketParserBase
136         {
137         #   include SENF_PARSER()
138
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     )) );
146
147             SENF_PARSER_FINALIZE(SomeParser);
148         };
149         \endcode
150
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.
153
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
156             the variant parser.
157
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:
162
163         <table class="senf fixedcolumn">
164         <tr><td>\a type</td><td>Do not provide accessor and use the 0-based type index as
165         key.</td></tr>
166
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
170         type)</td></tr>
171
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
174         type)</td></tr>
175
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>
179
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>
182
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>
185         </table>
186
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.
189
190         The functions defined by specifying an id are:
191
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
194         novalue.</td></tr>
195
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>
198
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>
201
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>
204         </table>
205
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.
209
210         Further additional tags are supported which modify the way, the \a chooser field is
211         interpreted:
212
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>
216         </table>
217
218         The optional \a transform is a class with the following layout
219
220         \code
221         struct MyTransform
222         {
223             typedef ... value_type;
224             static value_type get(other_type v);
225             static other_type set(value_type v);
226         };
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.
229
230         The tags are applied to the \a chooser parameter:
231         \code
232         SENF_PARSER_VARIANT ( content, transform(MyTransform, type),
233                                             (senf::VoidPacketParser)
234                                             (senf::UInt8Parser)
235                                             (senf::UInt16Parser)
236                                             (senf::UInt24Parser)
237                                             (senf::UInt32Parser) );
238         \endcode
239
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
243
244         \see
245             senf::VariantParser for the VariantParser API\n
246             \ref SENF_PARSER_PRIVATE_VARIANT()
247         \hideinitializer
248         \ingroup packetparsermacros
249      */
250 #   define SENF_PARSER_VARIANT(name, chooser, types) \
251         SENF_PARSER_VARIANT_I(public, name, chooser, types)
252
253     /** \brief Define private VariantParser field
254
255         \see \ref SENF_PARSER_VARIANT()
256         \hideinitializer
257         \ingroup packetparsermacros
258      */
259 #   define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
260         SENF_PARSER_VARIANT_I(protected, name, chooser, types)
261 }
262
263 //-/////////////////////////////////////////////////////////////////////////////////////////////////
264 #endif
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"
270 #endif
271
272 \f
273 // Local Variables:
274 // mode: c++
275 // fill-column: 100
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"
281 // End: