X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FVariantParser.hh;h=17b0ca414445dfeaebcbb89ead5bde5424f04799;hb=c45c112ae88196ea8da9c5a9efb0e167196744d2;hp=25b143f242861593d6e7fced424b89c6216d6c25;hpb=380525e28d9a2a2758dedcb4875b5c3755303344;p=senf.git diff --git a/Packets/VariantParser.hh b/Packets/VariantParser.hh index 25b143f..17b0ca4 100644 --- a/Packets/VariantParser.hh +++ b/Packets/VariantParser.hh @@ -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 @@ -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,55 +123,121 @@ namespace senf { \post variant() == \a N */ }; - /** \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. + /** \brief Define VariantParser field + This macro is a special helper to define a senf::VariantParser type field. \code struct SomeParser : public PacketParserBase { # include SENF_PARSER() 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>(); } + 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 )) ); SENF_PARSER_FINALIZE(SomeParser); }; - \endcode - + \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. + \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. + + 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, 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 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 \see - senf::VariantParser \n + senf::VariantParser for the VariantParser API\n \ref SENF_PARSER_PRIVATE_VARIANT() \hideinitializer \ingroup packetparsermacros @@ -179,7 +245,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,43 +253,12 @@ 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//////////////////////////////////////// #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"