X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FVariantParser.hh;h=8516a9f1e7e82e484efbdcf73c2ca1b8e280c401;hb=96bb4084fc4493a7a2686d02a895bce1160d61d6;hp=25b143f242861593d6e7fced424b89c6216d6c25;hpb=380525e28d9a2a2758dedcb4875b5c3755303344;p=senf.git diff --git a/Packets/VariantParser.hh b/Packets/VariantParser.hh index 25b143f..8516a9f 100644 --- a/Packets/VariantParser.hh +++ b/Packets/VariantParser.hh @@ -62,7 +62,7 @@ namespace senf { \code typedef senf::VariantParser< MyAuxPolicy, - senf::VoidPacketParser, TypeAParser, TypeBParser> MyVariantParser; + 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 @@ -123,15 +123,11 @@ namespace senf { \post variant() == \a N */ }; - /** \brief Define DirectVariantParser field + /** \brief Define VariantParser 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. - \code struct SomeParser : public PacketParserBase { @@ -139,22 +135,11 @@ namespace senf { SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser ); SENF_PARSER_PRIVATE_VARIANT( content, 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>(); } + (novalue( disable, senf::VoidPacketParser )) + ( id( uint8, senf::UInt8Parser )) + ( id( uint16, senf::UInt16Parser )) + ( id( uint24, senf::UInt24Parser )) + ( id( uint32, senf::UInt32Parser )) ); SENF_PARSER_FINALIZE(SomeParser); }; @@ -163,9 +148,79 @@ namespace senf { 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. + 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: + + + + + + + + + + +
\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 for this + type
\c novalue(\a name, \a type)This is like \c id but only provides an + initializer called \a name and no accessor
\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.
+ + It is customary, to hide the variant parser (by defining it private) and provide + more conveniently named accessors. In above example, these accessors are automatically + generated using the id's given. The exact members defined are: + + + + + + + + + +
\a name \c _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 \a value keys 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 MyTransform + { + 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) ); + \endcode + \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 @@ -179,7 +234,7 @@ namespace senf { # define SENF_PARSER_VARIANT(name, chooser, types) \ SENF_PARSER_VARIANT_I(public, name, chooser, types) - /** \brief Define DirectVariantParser field (private) + /** \brief Define private VariantParser field \see \ref SENF_PARSER_VARIANT() \hideinitializer @@ -187,37 +242,6 @@ namespace senf { */ # define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \ SENF_PARSER_VARIANT_I(private, name, chooser, 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. - - \see \ref SENF_PARSER_VARIANT() - \hideinitializer - \ingroup packetparsermacros - */ - - } ///////////////////////////////hh.e////////////////////////////////////////