Utils/Termlib: Extend the completion API
[senf.git] / Packets / ParseHelpers.ih
index d936097..a4d1cd9 100644 (file)
 #
 # // Custom includes
 # include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/if.hpp>
+# include <boost/preprocessor/expand.hpp>
+# include <boost/preprocessor/facilities/is_empty.hpp>
+# include <boost/preprocessor/punctuation/comma.hpp>
 # include "../Utils/mpl.hh"
 #
 # ////////////////////////////////ih.p///////////////////////////////////////
 # // SENF_PARSER_I_FIELD_OFS_*
 #
 # define SENF_PARSER_I_FIELD_OFS_var(name, type, access)                                          \
+    protected:                                                                                    \
         size_type BOOST_PP_CAT(name,_offset)() const {                                            \
             return field_offset_(static_cast<senf::mpl::rv<BOOST_PP_CAT(name,_index)-1>*>(0));    \
         }                                                                                         \
-        static size_type const BOOST_PP_CAT(name, _init_bytes) = SENF_MPL_SLOT_GET(init_bytes);
+        static size_type const BOOST_PP_CAT(name, _init_bytes) =                                  \
+            SENF_MPL_SLOT_GET(init_bytes);                                                        \
+    private:
 #
 # define SENF_PARSER_I_FIELD_OFS_fix(name, type, access)                                          \
-        static size_type const BOOST_PP_CAT(name, _offset) = SENF_MPL_SLOT_GET(offset);
+    protected:                                                                                    \
+        static size_type const BOOST_PP_CAT(name, _offset) =                                      \
+            SENF_MPL_SLOT_GET(offset);                                                            \
+    private:
 #
 # ////////////////////////////////////////
 # // SENF_PARSER_I_ADVANCE_OFS_*
             return BOOST_PP_CAT(name, _next_offset)();                                            \
         }                                                                                         \
         SENF_MPL_SLOT_SET(init_bytes, BOOST_PP_CAT(name,_next_init_bytes));                       \
+    protected:                                                                                    \
         static size_type const BOOST_PP_CAT(name, _group) = SENF_MPL_SLOT_GET(group) + isvar;     \
+    private:                                                                                      \
         SENF_MPL_SLOT_SET(group, BOOST_PP_CAT(name, _group));                                     \
     access:
 #
 # // SENF_PARSER_I_FIELD_VAL_*
 #
 # define SENF_PARSER_I_FIELD_VAL_rw(name, type, access)                                           \
-    private:                                                                                      \
+    protected:                                                                                    \
         BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const {                                    \
             return parse<type>( SENF_PARSER_OFFSET(name) );                                       \
         }                                                                                         \
         }
 #
 # define SENF_PARSER_I_FIELD_VAL_ro(name, type, access)                                           \
-    private:                                                                                      \
+    protected:                                                                                    \
         BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const {                                    \
             return parse<type>( SENF_PARSER_OFFSET(name) );                                       \
         }                                                                                         \
             return field_offset_(static_cast<senf::mpl::rv<BOOST_PP_CAT(name,_index)-1>*>(0))     \
                 - SENF_MPL_SLOT_GET(bitfield_size);                                               \
         }                                                                                         \
-        static size_type const BOOST_PP_CAT(name, _init_bytes) = SENF_MPL_SLOT_GET(init_bytes)    \
-            - SENF_MPL_SLOT_GET(bitfield_size);
+        static size_type const BOOST_PP_CAT(name, _init_bytes) =                                  \
+            SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size);
 #
 # define SENF_PARSER_I_BITFIELD_OFS_fix(name, type, access)                                       \
-        static size_type const BOOST_PP_CAT(name, _offset) = SENF_MPL_SLOT_GET(offset)            \
-            - SENF_MPL_SLOT_GET(bitfield_size);
+        static size_type const BOOST_PP_CAT(name, _offset) =                                      \
+            SENF_MPL_SLOT_GET(offset) - SENF_MPL_SLOT_GET(bitfield_size);
 #
 # ////////////////////////////////////////
 # // SENF_PARSER_I_BITFIELD_RESET
 # define SENF_PARSER_SKIP_BITS_fix(bits) SENF_PARSER_I_SKIP_BITS(bits, fix)
 #
 # define SENF_PARSER_I_SKIP_BITS(bits, ofstype)                                                   \
-      SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + bits)
+      private:                                                                                    \
+          SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + bits);                                  \
+      public:
 #
 # ///////////////////////////////////////////////////////////////////////////
 # // SENF_PARSER_GOTO_*
 # ///////////////////////////////////////////////////////////////////////////
 # // SENF_PARSER_COLLECTION_I
 #
-  namespace senf { namespace detail { namespace auxtag { struct none {}; } } }
+# ifndef DOXYGEN
+#
+  namespace senf { namespace detail { namespace auxtag {
+      struct none {}; } } }
+  namespace senf { namespace detail { namespace auxtag {
+      struct bytes {}; } } }
+  namespace senf { namespace detail { namespace auxtag {
+      template <class Transform, class Tag>
+      struct transform {}; } } }
+  namespace senf { namespace detail { namespace auxtag {
+      struct packetSize {}; } } }
+#
+# endif
 #
+# // Each tag is implemented by defining the following macros. If the Tag is <name>(<args>):
+# //   SENF_PARSER_COLLECTION_TAG_GOBBLE__<name>(<args>)
+# //       gobble the tag, that is expand to nothing
+# //   SENF_PARSER_COLLECTION_TAG__<name>(<args>)
+# //       return an intermediate tag. This tag will be used with the next macro to get the aux tag
+# //       this indirection is needed since the tag may include templates with more than one
+# //       argument which cannot be passed through macros ... Ugh ...
+# //   SENF_PARSER_COLLECTION_TAG_EXPAND__<tag>(<tag args>)
+# //       expand to the real tag type
+# //   SENF_PARSER_COLLECTION_TAG_GETAUX__<name>(<args>)
+# //       return the real aux field. More specifically, this is the aux argument to the aux expand
+# //       macro
+# //   SENF_PARSER_COLLECTION_TAG_AUXTYPE__<name>(<args>)
+# //       return an identifier selecting the aux type macro to use. If the expansion of this macro
+# //       is <auxtag>, the macro will be called SENF_PARSER_COLLECTION_TAG_AUXDEF__<auxtag>
+# //   SENF_PARSER_COLLECTION_TAG_AUXDEF__<auxtag>(<name>,<auxarg>)
+# //       this command must declare the typedef <fieldname>_aux_type to the base aux policy
+#
+# define SENF_PARSER_COLLECTION_TAG_GOBBLE__bytes(x)
+# define SENF_PARSER_COLLECTION_TAG__bytes(x) bytes()
+# define SENF_PARSER_COLLECTION_TAG_EXPAND__bytes() senf::detail::auxtag::bytes
+# define SENF_PARSER_COLLECTION_TAG_GETAUX__bytes(x) x
+# define SENF_PARSER_COLLECTION_TAG_AUXTYPE__bytes(x) auxField
+#
+# define SENF_PARSER_COLLECTION_TAG_GOBBLE__transform(x,y)
+# define SENF_PARSER_COLLECTION_TAG__transform(x,y) \
+      transform(x, SENF_PARSER_COLLECTION_TAG_RECURS1(y))
+# define SENF_PARSER_COLLECTION_TAG_EXPAND__transform(x,y)                                        \
+      senf::detail::auxtag::transform<                                                            \
+          x,                                                                                      \
+          SENF_CAT_RECURS1(SENF_PARSER_COLLECTION_TAG_EXPAND__, y)>
+# define SENF_PARSER_COLLECTION_TAG_GETAUX__transform(x,y) \
+      SENF_PARSER_COLLECTION_TAG_GETAUX_RECURS1(y)
+# define SENF_PARSER_COLLECTION_TAG_AUXTYPE__transform(x,y) \
+      SENF_PARSER_COLLECTION_TAG_AUXTYPE_RECURS1(y)
+#
+# define SENF_PARSER_COLLECTION_TAG_GOBBLE__packetSize()
+# define SENF_PARSER_COLLECTION_TAG__packetSize() packetSize()
+# define SENF_PARSER_COLLECTION_TAG_EXPAND__packetSize() senf::detail::auxtag::bytes
+# define SENF_PARSER_COLLECTION_TAG_GETAUX__packetSize() _
+# define SENF_PARSER_COLLECTION_TAG_AUXTYPE__packetSize() packetSize
+#
+# // No recursive call so we need some more of theese ... ARGH !!!
+# define SENF_CAT_RECURS1(a, b) SENF_CAT_RECURS1_I(a,b)
+# define SENF_CAT_RECURS1_I(a, b) a ## b
+# define SENF_CAT_RECURS2(a, b) SENF_CAT_RECURS2_I(a,b)
+# define SENF_CAT_RECURS2_I(a, b) a ## b
+# define SENF_CAT_RECURS3(a, b) SENF_CAT_RECURS3_I(a,b)
+# define SENF_CAT_RECURS3_I(a, b) a ## b
+#
+# define SENF_PARSER_COLLECTION_TAG_EXPAND__none() senf::detail::auxtag::none
+#
+# define SENF_PARSER_COLLECTION_TAG_RECURS1(aux)                                                  \
+      BOOST_PP_IF(                                                                                \
+          SENF_PARSER_COLLECTION_HAS_KEYWORD(aux),                                                \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG__, aux),                                        \
+          none() )
+#
+# define SENF_PARSER_COLLECTION_TAG_GETAUX_RECURS1(aux)                                           \
+      BOOST_PP_IF(                                                                                \
+          SENF_PARSER_COLLECTION_HAS_KEYWORD(aux),                                                \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_GETAUX__, aux),                                 \
+          aux)
+#
+# define SENF_PARSER_COLLECTION_TAG_AUXTYPE_RECURS1(aux)                                          \
+      BOOST_PP_IF(                                                                                \
+          SENF_PARSER_COLLECTION_HAS_KEYWORD(aux),                                                \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_AUXTYPE__, aux),                                \
+          auxField)
+#
+# define SENF_PARSER_COLLECTION_HAS_KEYWORD(x)                                                    \
+      BOOST_PP_IS_EMPTY( SENF_CAT_RECURS1(SENF_PARSER_COLLECTION_TAG_GOBBLE__, x) )
+#
+# define SENF_PARSER_COLLECTION_GETAUX(aux)                                                       \
+      BOOST_PP_IF( SENF_PARSER_COLLECTION_HAS_KEYWORD(aux),                                       \
+                   SENF_CAT_RECURS2(SENF_PARSER_COLLECTION_TAG_GETAUX__, aux),                    \
+                   aux )
+
 # define SENF_PARSER_COLLECTION_I(access, name, aux, traits)                                      \
+      BOOST_PP_EXPAND(                                                                            \
+          SENF_PARSER_COLLECTION_II                                                               \
+              BOOST_PP_IF(                                                                        \
+                  SENF_PARSER_COLLECTION_HAS_KEYWORD(aux),                                        \
+                  ( access,                                                                       \
+                    name,                                                                         \
+                    SENF_CAT_RECURS2(SENF_PARSER_COLLECTION_TAG_AUXTYPE__, aux),                  \
+                    SENF_CAT_RECURS2(SENF_PARSER_COLLECTION_TAG_GETAUX__, aux),                   \
+                    SENF_CAT_RECURS2(SENF_PARSER_COLLECTION_TAG__, aux),                          \
+                    traits ),                                                                     \
+                  ( access,                                                                       \
+                    name,                                                                         \
+                    auxField,                                                                     \
+                    aux,                                                                          \
+                    none(),                                                                       \
+                    traits ) ))
+#
+# define SENF_PARSER_COLLECTION_II(access, name, auxtype, aux, tag, traits)                       \
       private:                                                                                    \
-          BOOST_PP_CAT(SENF_PARSER_COLLECTION_AUXTYPE_, SENF_PARSER_TYPE)(name, aux)              \
-          typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_AUX_I_, SENF_PARSER_TYPE)(name, aux)        \
-              BOOST_PP_CAT(name,_aux_policy);                                                     \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_AUXDEF__, auxtype)(name, aux)                   \
           typedef traits::parser<                                                                 \
               BOOST_PP_CAT(name,_aux_policy),                                                     \
-              senf::detail::auxtag::none                                                          \
+              BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_EXPAND__, tag)                              \
               >::type BOOST_PP_CAT(name, _collection_t);                                          \
       access:                                                                                     \
           SENF_PARSER_FIELD_SETUP_I( name,                                                        \
                                      SENF_PARSER_TYPE,                                            \
                                      rw,                                                          \
                                      access )                                                     \
-          BOOST_PP_CAT(SENF_PARSER_COLLECTION_VAL_, SENF_PARSER_TYPE)(name, aux, access)          \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_VAL__, auxtype)(name, aux, access)              \
       public:
 #
+# define SENF_PARSER_COLLECTION_TAG_AUXDEF__auxField(name, aux)                                   \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_AUXTYPE_, SENF_PARSER_TYPE)(name, aux)              \
+          typedef BOOST_PP_CAT(SENF_PARSER_COLLECTION_AUX_I_, SENF_PARSER_TYPE)(name, aux)        \
+              BOOST_PP_CAT(name,_aux_policy);
+#
 # define SENF_PARSER_COLLECTION_AUXTYPE_var(name, aux)                                            \
       static bool const BOOST_PP_CAT(name, _aux_fixed) =                                          \
           (SENF_MPL_SLOT_GET(group) - BOOST_PP_CAT(aux, _group) == 0);
 #
 # define SENF_PARSER_COLLECTION_AUXTYPE_fix(name, aux)
 #
+# ifndef DOXYGEN
+#
   namespace senf { namespace detail {
       template <class Parser> struct DynamicAuxParserPolicy;
       template <class Parser, unsigned offset> struct FixedAuxParserPolicy;
       template <class Parser, unsigned fixedOffset, bool fixedDelta>
-      struct ParserAuxPolicySelect 
+      struct ParserAuxPolicySelect
       { typedef senf::detail::DynamicAuxParserPolicy<Parser> type; };
       template <class Parser, unsigned fixedOffset>
-      struct ParserAuxPolicySelect<Parser, fixedOffset, true> 
+      struct ParserAuxPolicySelect<Parser, fixedOffset, true>
       { typedef senf::detail::FixedAuxParserPolicy<Parser, fixedOffset> type; };
   }};
 #
+# endif
+#
 # define SENF_PARSER_COLLECTION_AUX_I_var(name, aux)                                              \
       senf::detail::ParserAuxPolicySelect< BOOST_PP_CAT(aux, _t),                                 \
                                            SENF_PARSER_CURRENT_FIXED_OFFSET()                     \
                                           SENF_PARSER_CURRENT_FIXED_OFFSET()                      \
                                               - SENF_PARSER_FIXED_OFFSET(aux) >
 #
-# define SENF_PARSER_COLLECTION_VAL_var(name,aux,access)                                           \
-      private:                                                                                     \
-          template <class T> T BOOST_PP_CAT(name, _dispatch)(boost::true_type) const               \
-          { return parse<T>( SENF_PARSER_OFFSET(name) ); }                                         \
-          template <class T> T BOOST_PP_CAT(name, _dispatch)(boost::false_type) const              \
-          { return parse<T>( BOOST_PP_CAT(name, _aux_policy)(aux()), SENF_PARSER_OFFSET(name) ); } \
-          BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const                                     \
-          { return BOOST_PP_CAT(name, _dispatch) <BOOST_PP_CAT(name, _t)>(                         \
-                  boost::integral_constant<bool, BOOST_PP_CAT(name, _aux_fixed)>()); }             \
-      access:                                                                                      \
-          BOOST_PP_CAT(name, _t) name() const                                                      \
+# define SENF_PARSER_COLLECTION_TAG_AUXDEF__packetSize(name, aux)                                 \
+          typedef senf::detail::PacketSizeAuxParserPolicy BOOST_PP_CAT(name, _aux_policy);
+#
+# define SENF_PARSER_COLLECTION_TAG_VAL__auxField(name, aux, access)                              \
+          BOOST_PP_CAT(SENF_PARSER_COLLECTION_VAL_, SENF_PARSER_TYPE)(name, aux, access)
+#
+# define SENF_PARSER_COLLECTION_VAL_var(name,aux,access)                                          \
+      private:                                                                                    \
+          template <class T> T BOOST_PP_CAT(name, _dispatch)(boost::true_type) const              \
+          { return parse<T>( SENF_PARSER_OFFSET(name) ); }                                        \
+          template <class T> T BOOST_PP_CAT(name, _dispatch)(boost::false_type) const             \
+          { return parse<T>( BOOST_PP_CAT(aux,_)(), SENF_PARSER_OFFSET(name) ); }                 \
+          BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const                                    \
+          { return BOOST_PP_CAT(name, _dispatch) <BOOST_PP_CAT(name, _t)>(                        \
+                  boost::integral_constant<bool, BOOST_PP_CAT(name, _aux_fixed)>()); }            \
+      access:                                                                                     \
+          BOOST_PP_CAT(name, _t) name() const                                                     \
           { return BOOST_PP_CAT(name, _)(); }
 #
 # define SENF_PARSER_COLLECTION_VAL_fix(name,aux,access)                                          \
           BOOST_PP_CAT(name, _t) name() const                                                     \
           { return BOOST_PP_CAT(name, _)(); }
 #
+# define SENF_PARSER_COLLECTION_TAG_VAL__packetSize(name, aux, access)                            \
+      private:                                                                                    \
+          BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const                                    \
+          { return parse<BOOST_PP_CAT(name, _t)>( SENF_PARSER_OFFSET(name) ); }                   \
+      access:                                                                                     \
+          BOOST_PP_CAT(name, _t) name() const                                                     \
+          { return BOOST_PP_CAT(name, _)(); }
+#
 # ////////////////////////////////ih.e///////////////////////////////////////
 # endif
 #