Packets: Add 'Translator' argument to Parse_Variant_Direct
g0dil [Thu, 22 Nov 2007 16:42:31 +0000 (16:42 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@526 270642c3-0616-0410-b53a-bc976706d245

Packets/ParseVariant.hh
Packets/ParseVariant.ih
Packets/ParseVariant.test.cc

index 9deb622..0c33791 100644 (file)
@@ -151,10 +151,11 @@ namespace senf {
         \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;
     };
 
@@ -210,8 +211,12 @@ namespace senf {
         \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)
         
@@ -219,8 +224,61 @@ namespace senf {
         \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)
 
 }
 
index 0e33da0..1166077 100644 (file)
@@ -56,7 +56,7 @@ namespace detail {
 #   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;
@@ -72,20 +72,27 @@ namespace detail {
         }
         
         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) )
index e795e49..41935d5 100644 (file)
@@ -38,7 +38,7 @@
 BOOST_AUTO_UNIT_TEST(parseVariant)
 {
     typedef senf::Parse_Array<10, senf::Parse_UInt8> Array10;
-    typedef senf::Parse_Variant_Direct< senf::Parse_UInt8, 1, 
+    typedef senf::Parse_Variant_Direct< senf::Parse_UInt8, 1, senf::detail::Parse_Variant_IdentityTranslator,
         senf::VoidPacketParser,
         Array10, 
         senf:: Parse_UInt32