\see senf::Parser_Variant
\ingroup parsecollection
*/
- template <class ChooserType, unsigned Distance, SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
+ template <class ChooserType, unsigned Distance, class Translator,
+ SENF_PARSE_VARIANT_TPL_ARGS_DFL(class P)>
struct Parse_Variant_Direct
{
- typedef Parse_Variant< detail::Parse_Variant_Direct<ChooserType, Distance>,
+ typedef Parse_Variant< detail::Parse_Variant_Direct<ChooserType, Distance, Translator>,
SENF_PARSE_VARIANT_TPL_ARGS(P) > parser;
};
\hideinitializer
\ingroup packetparsermacros
*/
-# define SENF_PARSER_VARIANT(name, chooser, types) \
- SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, name, chooser, types)
+# define SENF_PARSER_VARIANT(name, chooser, types) \
+ SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, \
+ name, \
+ chooser, \
+ senf::detail::Parse_Variant_IdentityTranslator, \
+ types)
/** \brief Define Parse_Variant_Direct field (private)
\hideinitializer
\ingroup packetparsermacros
*/
-# define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
- SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, name, chooser, types)
+# define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types) \
+ SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, \
+ name, \
+ chooser, \
+ senf::detail::Parse_Variant_IdentityTranslator, \
+ types)
+
+ /** \brief Define Parse_Variant_Direct 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 foChooser(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
+ */
+# define SENF_PARSER_VARIANT_TRANS(name, chooser, translator, types) \
+ SENF_PARSER_VARIANT_I(SENF_PARSER_FIELD, \
+ name, \
+ chooser, \
+ translator, \
+ types)
+
+ /** \brief Define Parse_Variant_Direct field with translator (private)
+
+ \see \ref SENF_PARSER_VARIANT_TRANS()
+ \hideinitializer
+ \ingroup packetparsermacros
+ */
+# define SENF_PARSER_PRIVATE_VARIANT_TRANS(name, chooser, types) \
+ SENF_PARSER_VARIANT_I(SENF_PARSER_PRIVATE_FIELD, \
+ name, \
+ chooser, \
+ translator, \
+ types)
}
# endif
/** \brief Internal: Variant Policy used by senf::Parse_Variant_Direct */
- template <class ChooserType, unsigned Distance>
+ template <class ChooserType, unsigned Distance, class Translator>
struct Parse_Variant_Direct
{
typedef PacketParserBase::data_iterator data_iterator;
}
unsigned variant(data_iterator i, state_type s) const {
- return chooser(i,s).value();
+ return Translator::fromChooser(chooser(i,s).value());
}
void variant(unsigned v, data_iterator i, state_type s) {
- chooser(i,s).value(v);
+ chooser(i,s).value(Translator::toChooser(v));
}
};
+ /** \brief Internal: Identity chooser translator */
+ struct Parse_Variant_IdentityTranslator {
+ static unsigned fromChooser(unsigned value) { return value; }
+ static unsigned toChooser(unsigned value) { return value; }
+ };
+
# define SENF_PARSER_VARIANT_(r, data, elem) ,elem
-# define SENF_PARSER_VARIANT_I(field, name, chooser, types) \
+# define SENF_PARSER_VARIANT_I(field, name, chooser, translator, types) \
typedef senf::Parse_Variant_Direct< \
BOOST_PP_CAT(chooser, _t), \
- SENF_PARSER_CURRENT_FIXED_OFFSET() - SENF_PARSER_FIXED_OFFSET(chooser) \
+ SENF_PARSER_CURRENT_FIXED_OFFSET() - SENF_PARSER_FIXED_OFFSET(chooser), \
+ translator \
BOOST_PP_SEQ_FOR_EACH( SENF_PARSER_VARIANT_, _, types ) \
>::parser BOOST_PP_CAT(name, _variant_t); \
field( name, BOOST_PP_CAT(name, _variant_t) )