// $Id$
//
-// Copyright (C) 2007
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer NETwork research (NET)
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
#include "PacketParser.hh"
//#include "VariantParser.mpp"
-#include "VariantParser.ih"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
packet change depending on some condition.
\code
typedef senf::VariantParser<
- MyVariantPolicy,
- senf::VoidPacketParser, TypeAParser, TypeBParser> MyVariantParser;
+ MyAuxPolicy,
+ senf::mpl::vector<senf::VoidPacketParser, TypeAParser, TypeBParser> > MyVariantParser;
\endcode
This typedef defines a variant parser choosing one of three sub
parsers. senf::VoidPacketParser is an empty parser, it effectively makes this parser
initialized to the first sub-parser.
\see
- ExampleVariantPolicy on how to implement the \a VariantPolicy \n
+ ExampleAuxPolicy on how to implement the \a AuxPolicy \n
\ref SENF_PARSER_VARIANT() on how to integrate the parser into another parser
\ingroup parsecollection
*/
- template <class VariantPolicy, SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
+ template <class AuxPolicy, class Parsers>
class VariantParser
- : public PacketParserBase, private VariantPolicy
+ : public PacketParserBase, private AuxPolicy
{
- typedef boost::mpl::vector< SENF_PARSE_VARIANT_TPL_ARGS(P) > parsers;
+ typedef Parsers parsers;
public:
///\name Parser interface
///\{
VariantParser(data_iterator i, state_type s);
- VariantParser(VariantPolicy policy, data_iterator i, state_type s);
+ VariantParser(AuxPolicy policy, data_iterator i, state_type s);
size_type bytes() const;
void init();
- static const size_type init_bytes =
- senf::init_bytes<P0>::value + VariantPolicy::init_bytes;
+ static const size_type init_bytes = senf::init_bytes<
+ typename boost::mpl::at<parsers, boost::mpl::int_<0> >::type>::value
+ + AuxPolicy::aux_bytes;
///\}
///////////////////////////////////////////////////////////////////////////
\post variant() == \a N */
};
- /** \brief Variant with direct, fixed distance type field
-
- This struct is a template typedef defining a senf::Parser_Variant instantiation. It defines
- a variant parser which interprets the value returned by some other parser directly as index
- into the list of sub parsers (the numeric template argument to senf::VariantParser::get()
- and senf::Parser_Variant::init()).
+ /** \brief Define VariantParser field
+ This macro is a special helper to define a senf::VariantParser type field.
\code
- // Define a variant choosing between FooParser and BarParser depending on the directly
- // preceding 1-byte 8bit uint value
- typedef senf::DirectVariantParser< senf::UInt8Parser, 1u,
- FooParser, BarParser >::parser MyVariant;
- \endcode
+ struct SomeParser : public PacketParserBase
+ {
+ # include SENF_PARSER()
+
+ SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
+ SENF_PARSER_VARIANT( content, type,
+ (novalue( disable, senf::VoidPacketParser ))
+ ( id( uint8value, senf::UInt8Parser ))
+ ( id( uint16value, senf::UInt16Parser ))
+ ( id( uint24value, senf::UInt24Parser ))
+ ( id( uint32value, senf::UInt32Parser )) );
- \a ChooserType defines the type of the field used to choose the sub parser. This must be a
- fixed-size value parser. \a Distance gives the \e fixed distance of this field \e before the
- currently defined field.
+ SENF_PARSER_FINALIZE(SomeParser);
+ };
+ \endcode
+
+ The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
+ type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
- It is best to define a field of this type using \ref SENF_PARSER_VARIANT() or \ref
- SENF_PARSER_PRIVATE_VARIANT().
+ \warning Realize, that the \a chooser field is controlled by the variant parser. This field
+ should therefore be declared either read-only or private and must be changed only via
+ the variant parser.
- \param[in] ChooserType type of chooser field (a value parser)
- \param[in] Distance fixed distance of the chooser field before the current field
- \param[in] P any number of sub parsers
+ The \a types parameter specifies the types of sub-objects supported by this variant
+ parser. This parameter is a (Boost.Preprocessor style) sequence
+ <pre>(\a type) (\a type) ...</pre>
+ of parser types with additional optional information:
- \see senf::Parser_Variant
- \ingroup parsecollection
- */
- template <class ChooserType, unsigned Distance, class Translator,
- SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
- struct DirectVariantParser
- {
- typedef VariantParser< detail::DirectVariantParser<ChooserType, Distance, Translator>,
- SENF_PARSE_VARIANT_TPL_ARGS(P) > parser;
- };
+ <table class="senf fixedcolumn">
+ <tr><td>\a type</td><td>Do not provide accessor and use the 0-based type index as
+ key.</td></tr>
- /** \brief Define DirectVariantParser field
+ <tr><td>\c id(\a name, \a type)</td><td>Automatically create an accessor \a name, a test
+ function <tt>has_</tt>\a name and a function to switch to this type <tt>init_</tt>\a name
+ for this type. Identical to \c ids(\a name, <tt>has_</tt>\a name, <tt>init_</tt>\a name, \a
+ type)</td></tr>
- This macro is a special helper to define a senf::DirectVariantParser type field. This is a
- variant field which chooses the sub-type by directly taking the value of some other field.
+ <tr><td>\c novalue(\a name, \a type)</td><td>This is like \c id but only provides an
+ initializer called \a name and no accessor. Identical to \c ids(\c na, \c na, \a name, \a
+ type)</td></tr>
- \warning
- This is a dynamically sized parser. Nevertheless, the chooser field \e must have a
- \e fixed distance to this field, the \a chooser must be a fixed-size value parser.
+ <tr><td>\c ids(\a accessorId, \a testId, \a initId, \a type)</td><td>This is again like \c
+ id but the names of the accessor, test function and init function are given
+ explicitly. Setting any of the id's to \c na will disable that function.</td></tr>
+
+ <tr><td>\c key(\a value, \a type)</td><td>Use \a value to identity this type. The type is
+ selected, when the \a chooser is equal to \a value</td></tr>
+
+ <tr><td>\c id(\a name, \c key(\a value, \a type))<br/>\c novalue(\a name, \c key(\a value,
+ \a type))</td><td>The options may be nested in this way.</td></tr>
+ </table>
+
+ Whenever an id is specified for any type, the variant itself will automatically be made
+ private so the only access to the variant from the outside is via the accessors.
+
+ The functions defined by specifying an id are:
+
+ <table class="senf fixedcolumn">
+ <tr><td><em>name</em><tt>_t</tt></td><td>The type for this specific variant value if not \c
+ novalue.</td></tr>
+
+ <tr><td><em>name</em><tt>_t</tt> <em>name</em>()</td><td>Return the variant value at this id
+ if not \c novalue.</td></tr>
+
+ <tr><td><tt>void</tt> <tt>init_</tt><em>name</em>()</td><td>Set the variant to have a value
+ of this type. If the field is \c novalue, the \c init_ prefix is omitted.</td></tr>
+
+ <tr><td><tt>bool</tt> <tt>has_</tt><em>name</em>()</td><td>Return \c true, if the variant
+ currently holds this kind of value, \c false otherwise. Only if not \c novalue.</td></tr>
+ </table>
+
+ If \c key specs are given, they designate the value to expect in the \a chooser field to
+ select a specific variant type. If the \a chooser value does not match any key, the variant
+ will be initialized to the \e first type.
+
+ Further additional tags are supported which modify the way, the \a chooser field is
+ interpreted:
+
+ <table class="senf fixedcolumn">
+ <tr><td>\c transform(\a transform, \a chooser)</td><td>The \a transform is applied to the \a
+ chooser value, the value is not used directly</td>
+ </table>
+
+ The optional \a transform is a class with the following layout
\code
- struct SomeParser : public PacketParserBase
+ struct MyTransform
{
- # include SENF_PARSER()
-
- SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
- SENF_PARSER_PRIVATE_VARIANT( content, type,
+ typedef ... value_type;
+ static value_type get(other_type v);
+ static other_type set(value_type v);
+ };
+ \endcode \c other_type is the \a chooser ::\c value_type whereas the \c value_type typedef
+ is the arbitrary return type of the transform.
+
+ The tags are applied to the \a chooser parameter:
+ \code
+ SENF_PARSER_VARIANT ( content, transform(MyTransform, type),
(senf::VoidPacketParser)
(senf::UInt8Parser)
(senf::UInt16Parser)
(senf::UInt24Parser)
(senf::UInt32Parser) );
-
- senf::UInt8Parser uint8() const { return content().get<1>(); }
- senf::UInt16Parser uint16() const { return content().get<2>(); }
- senf::UInt24Parser uint24() const { return content().get<3>(); }
- senf::UInt32Parser uint32() const { return content().get<4>(); }
-
- void disable() const { content().init<0>(); }
- void set_uint8() const { content().init<1>(); }
- void set_uint16() const { content().init<2>(); }
- void set_uint24) const { content().init<3>(); }
- void set_uint23() const { content().init<4>(); }
-
- SENF_PARSER_FINALIZE(SomeParser);
- };
\endcode
-
- The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
- type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
-
- It is customary, to hide the variant parser (by defining it private) and provide more
- conveniently named accessors.
-
+
\param[in] name name of the field
\param[in] chooser name of the field choosing the variant to use
\param[in] types a Boost.Preprocessor style sequence of sub-parser types
\see
- senf::VariantParser \n
+ senf::VariantParser for the VariantParser API\n
\ref SENF_PARSER_PRIVATE_VARIANT()
\hideinitializer
\ingroup packetparsermacros
*/
-# define SENF_PARSER_VARIANT(name, chooser, types) \
- SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, \
- name, \
- chooser, \
- senf::detail::VariantParser_IdentityTranslator, \
- types)
-
- /** \brief Define DirectVariantParser field (private)
-
- \see \ref SENF_PARSER_VARIANT()
- \hideinitializer
- \ingroup packetparsermacros
- */
-# define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
- SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, \
- name, \
- chooser, \
- senf::detail::VariantParser_IdentityTranslator, \
- types)
-
- /** \brief Define DirectVariantParser field with translator
-
- This is like \ref SENF_PARSER_VARIANT(), however it allows to specify a \a translator
- argument which translates between \a chooser values and type indices:
- \code
- struct SomeTranslator {
- static unsigned fromChooser(chooser_field_t::value_type value) {
- switch (value) {
- case 1 : return 0 ;
- case 5 : return 1 ;
- default : return 2 ;
- }
- }
- static chooser_field_t::value_type toChooser(unsigned value) {
- static chooser_field_t::value_type table[] const = { 1, 5, 0 };
- return table[value];
- }
- };
- \endcode
- The \a translator class must have two publicly accessible static members, \c fromChooser and
- \c toChooser. \c fromChooser takes the value as returned by the \a chooser field and must
- return the corresponding class index whereas \c toChooser takes the class index and must
- return the value to write into the \a chooser field.
+# define SENF_PARSER_VARIANT(name, chooser, types) \
+ SENF_PARSER_VARIANT_I(public, name, chooser, types)
- \see \ref SENF_PARSER_VARIANT()
- \hideinitializer
- \ingroup packetparsermacros
- */
-# define SENF_PARSER_VARIANT_TRANS(name, chooser, translator, types) \
- SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, \
- name, \
- chooser, \
- translator, \
- types)
-
- /** \brief Define DirectVariantParser field with translator (private)
+ /** \brief Define private VariantParser field
- \see \ref SENF_PARSER_VARIANT_TRANS()
+ \see \ref SENF_PARSER_VARIANT()
\hideinitializer
\ingroup packetparsermacros
*/
-# define SENF_PARSER_PRIVATE_VARIANT_TRANS(name, chooser, types) \
- SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, \
- name, \
- chooser, \
- translator, \
- types)
-
+# define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
+ SENF_PARSER_VARIANT_I(private, name, chooser, types)
}
///////////////////////////////hh.e////////////////////////////////////////