X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FVariantParser.hh;h=17b0ca414445dfeaebcbb89ead5bde5424f04799;hb=c45c112ae88196ea8da9c5a9efb0e167196744d2;hp=042e46e7bafde75de2ed73e276478a42b6f2833b;hpb=f73fa16ed5abdce272ac77f8b8b9ef2b9922c266;p=senf.git diff --git a/Packets/VariantParser.hh b/Packets/VariantParser.hh index 042e46e..17b0ca4 100644 --- a/Packets/VariantParser.hh +++ b/Packets/VariantParser.hh @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institute for Open Communication Systems (FOKUS) -// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -23,10 +23,10 @@ /** \file \brief VariantParser public header */ -#ifndef HH_VariantParser_ -#define HH_VariantParser_ 1 +#ifndef HH_SENF_Packets_VariantParser_ +#define HH_SENF_Packets_VariantParser_ 1 -#ifndef HH_Packets_ +#ifndef HH_SENF_Packets_Packets_ #error "Don't include 'VariantParser.hh' directly, include 'Packets.hh'" #endif @@ -39,7 +39,6 @@ #include "PacketParser.hh" //#include "VariantParser.mpp" -#include "VariantParser.ih" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { @@ -62,8 +61,8 @@ namespace senf { packet change depending on some condition. \code typedef senf::VariantParser< - MyVariantPolicy, - senf::VoidPacketParser, TypeAParser, TypeBParser> MyVariantParser; + MyAuxPolicy, + senf::mpl::vector > 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 @@ -73,28 +72,29 @@ namespace senf { 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 + template 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::value + VariantPolicy::init_bytes; + static const size_type init_bytes = senf::init_bytes< + typename boost::mpl::at >::type>::value + + AuxPolicy::aux_bytes; ///\} /////////////////////////////////////////////////////////////////////////// @@ -123,169 +123,142 @@ namespace senf { \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 +
(\a type) (\a type) ...
+ of parser types with additional optional information: - \see senf::Parser_Variant - \ingroup parsecollection - */ - template - struct DirectVariantParser - { - typedef VariantParser< detail::DirectVariantParser, - SENF_PARSE_VARIANT_TPL_ARGS(P) > parser; - }; + + - /** \brief Define DirectVariantParser field + - 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. + - \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. + + + + + +
\a typeDo not provide accessor and use the 0-based type index as + key.
\c id(\a name, \a type)Automatically create an accessor \a name, a test + function has_\a name and a function to switch to this type init_\a name + for this type. Identical to \c ids(\a name, has_\a name, init_\a name, \a + type)
\c novalue(\a name, \a type)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)
\c ids(\a accessorId, \a testId, \a initId, \a type)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.
\c key(\a value, \a type)Use \a value to identity this type. The type is + selected, when the \a chooser is equal to \a value
\c id(\a name, \c key(\a value, \a type))
\c novalue(\a name, \c key(\a value, + \a type))
The options may be nested in this way.
+ + 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: + + + + + + + + + +
name_tThe type for this specific variant value if not \c + novalue.
name_t name()Return the variant value at this id + if not \c novalue.
void init_name()Set the variant to have a value + of this type. If the field is \c novalue, the \c init_ prefix is omitted.
bool has_name()Return \c true, if the variant + currently holds this kind of value, \c false otherwise. Only if not \c novalue.
+ + 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: + + + +
\c transform(\a transform, \a chooser)The \a transform is applied to the \a + chooser value, the value is not used directly
+ + 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//////////////////////////////////////// #endif -#if !defined(HH_Packets__decls_) && !defined(HH_VariantParser_i_) -#define HH_VariantParser_i_ +#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_VariantParser_i_) +#define HH_SENF_Packets_VariantParser_i_ //#include "VariantParser.cci" #include "VariantParser.ct" #include "VariantParser.cti"