Packets: Change Parse_VectorN sizer to to allow explicitly specifying the size field...
g0dil [Thu, 22 Nov 2007 15:39:50 +0000 (15:39 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@525 270642c3-0616-0410-b53a-bc976706d245

Packets/ParseHelpers.hh
Packets/ParseHelpers.ih
Packets/ParseListB.test.cc
Packets/ParseListN.test.cc
Packets/ParseVec.cti
Packets/ParseVec.hh
Packets/ParseVec.ih
Packets/ParseVec.test.cc

index c3e2ab4..a5d761e 100644 (file)
 
     \hideinitializer
  */
-#define SENF_PARSER_INIT()       void init(int)
+#define SENF_PARSER_INIT()       void init(int) const
 
 #ifdef DOXYGEN
 
index b55c9a4..38595ed 100644 (file)
@@ -41,7 +41,7 @@
         SENF_MPL_SLOT_DEF_ZERO(offset);                                                           \
         SENF_MPL_SLOT_DEF_ZERO(bit);                                                              \
         SENF_MPL_SLOT_DEF_ZERO(bitfield_size);                                                    \
-        void init_chain(senf::mpl::rv<0>*) {}                                                     \
+        void init_chain(senf::mpl::rv<0>*) const {}                                               \
     public:
 #
 # define SENF_PARSER_INITIALIZE_var()                                                             \
@@ -50,7 +50,7 @@
         SENF_MPL_SLOT_DEF_ZERO(init_bytes);                                                       \
         SENF_MPL_SLOT_DEF_ZERO(bit);                                                              \
         SENF_MPL_SLOT_DEF_ZERO(bitfield_size);                                                    \
-        void init_chain(senf::mpl::rv<0>*) {}                                                     \
+        void init_chain(senf::mpl::rv<0>*) const {}                                               \
         size_type field_offset_(senf::mpl::rv<0>*) const { return 0; }                            \
     public:
 #
@@ -65,7 +65,7 @@
         size_type field_offset_(senf::mpl::rv<1>*) const {                                        \
             return senf::bytes( *static_cast<name const*>(this) );                                \
         }                                                                                         \
-        void init_chain(senf::mpl::rv<1>*) {                                                      \
+        void init_chain(senf::mpl::rv<1>*) const {                                                \
             name::init();                                                                         \
         }                                                                                         \
     public:
@@ -75,7 +75,7 @@
     private:                                                                                      \
         SENF_MPL_SLOT_SET(offset, name::fixed_bytes);                                             \
         SENF_MPL_SLOT_SET(index, 1);                                                              \
-        void init_chain(senf::mpl::rv<1>*) {                                                      \
+        void init_chain(senf::mpl::rv<1>*) const {                                                \
             name::init();                                                                         \
         }                                                                                         \
     public:
 #
 # define SENF_PARSER_I_FIELD_INIT_rw(name, type, access)                                                  \
     private:                                                                                      \
-        void init_chain(senf::mpl::rv<BOOST_PP_CAT(name,_index)>*) {                              \
+        void init_chain(senf::mpl::rv<BOOST_PP_CAT(name,_index)>*) const {                        \
             init_chain(static_cast<senf::mpl::rv<BOOST_PP_CAT(name,_index)-1>*>(0));              \
             name().init();                                                                        \
         }                                                                                         \
 #
 # define SENF_PARSER_I_FIELD_INIT_ro(name, type, access)                                                  \
     private:                                                                                      \
-        void init_chain(senf::mpl::rv<BOOST_PP_CAT(name,_index)>*) {                              \
+        void init_chain(senf::mpl::rv<BOOST_PP_CAT(name,_index)>*) const {                        \
             init_chain(static_cast<senf::mpl::rv<BOOST_PP_CAT(name,_index)-1>*>(0));              \
         }                                                                                         \
     access:
     static size_type const fixed_bytes = SENF_MPL_SLOT_GET(offset);
 #
 # define SENF_PARSER_FINALIZE_GENERIC(name)                                                       \
-         void defaultInit() {                                                                     \
+         void defaultInit() const {                                                               \
              init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)>*>(0));                \
          }                                                                                        \
          name(data_iterator i, state_type s) : parser_base_type(i,s) {}                           \
     private:                                                                                      \
-         template <class T> void init(T) { defaultInit(); }                                       \
+ template <class T> void init(T) const { defaultInit(); }                                 \
     public:                                                                                       \
-         void init() { init(0); }
+         void init() const { init(0); }
 #
 # ////////////////////////////////ih.e///////////////////////////////////////
 # endif
index a3d5fc1..464717a 100644 (file)
@@ -37,7 +37,16 @@ namespace {
     struct VoidPacket : public senf::PacketTypeBase
     {};
 
-    typedef senf::Parse_VectorN<senf::Parse_UInt16,senf::Parse_UInt8>::parser ParseVec;
+    struct ParseVec : public senf::PacketParserBase
+    {
+#       include SENF_PARSER()
+
+        SENF_PARSER_PRIVATE_FIELD( size, senf::Parse_UInt8 );
+        SENF_PARSER_VEC_N( vec, size, senf::Parse_UInt16 );
+
+        SENF_PARSER_FINALIZE(ParseVec);
+    };
+
     typedef senf::Parse_ListB<ParseVec,senf::Parse_UInt16>::parser ParseList;
 }
 
@@ -80,8 +89,8 @@ BOOST_AUTO_UNIT_TEST(parseListB_container)
         BOOST_CHECK_EQUAL( c.size(), 1u );
         BOOST_CHECK_EQUAL( c.bytes(), 3u );
 
-        BOOST_CHECK_EQUAL( c.front().size(), 0u );
-        c.front().push_back(0x1234u);
+        BOOST_CHECK_EQUAL( c.front().vec().size(), 0u );
+        c.front().vec().push_back(0x1234u);
         BOOST_CHECK_EQUAL( c.bytes(), 5u );
 
         {
@@ -90,7 +99,7 @@ BOOST_AUTO_UNIT_TEST(parseListB_container)
             ParseList::container c2 (ParseList(pi2->data().begin(),&pi2->data()));
             c2.push_back_space();
             {
-                ParseVec::container c2v (c2.front());
+                ParseVec::vec_t::container c2v (c2.front().vec());
                 c2v.push_back(0x2345u);
                 c2v.push_back(0x3456u);
             }
@@ -101,33 +110,33 @@ BOOST_AUTO_UNIT_TEST(parseListB_container)
             c.insert(c.end(),c2.back());
             BOOST_CHECK_EQUAL( c.size(), 2u );
             BOOST_CHECK_EQUAL( c.bytes(), 10u );
-            BOOST_CHECK_EQUAL( c.back()[0], 0x2345u );
+            BOOST_CHECK_EQUAL( c.back().vec()[0], 0x2345u );
             BOOST_CHECK_EQUAL( c.back().bytes(), c2.back().bytes() );
 
-            c2.back()[0] << 0x1357u;
+            c2.back().vec()[0] << 0x1357u;
             c.insert(boost::next(c.begin()), 2u, c2.back());
             BOOST_CHECK_EQUAL( c.size(), 4u );
             BOOST_CHECK_EQUAL( c.bytes(), 20u );
-            BOOST_CHECK_EQUAL( (*boost::next(c.begin()))[0], 0x1357u ); 
-            BOOST_CHECK_EQUAL( (*boost::next(c.begin(),2))[0], 0x1357u );
+            BOOST_CHECK_EQUAL( (*boost::next(c.begin())).vec()[0], 0x1357u ); 
+            BOOST_CHECK_EQUAL( (*boost::next(c.begin(),2)).vec()[0], 0x1357u );
 
-            c2.back()[0] << 0x2468u;
+            c2.back().vec()[0] << 0x2468u;
             c.insert(c.begin(),c2.begin(),c2.end());
             BOOST_CHECK_EQUAL( c.size(), 5u );
             BOOST_CHECK_EQUAL( c.bytes(), 25u );
-            BOOST_CHECK_EQUAL( c.front()[0], 0x2468u );
+            BOOST_CHECK_EQUAL( c.front().vec()[0], 0x2468u );
 
             c.erase(c.begin(),2);
             BOOST_CHECK_EQUAL( c.size(), 3u );
             BOOST_CHECK_EQUAL( c.bytes(), 17u );
-            BOOST_CHECK_EQUAL( c.front()[0],0x1357u );
-            BOOST_CHECK_EQUAL( c.back()[0], 0x2345u );
+            BOOST_CHECK_EQUAL( c.front().vec()[0],0x1357u );
+            BOOST_CHECK_EQUAL( c.back().vec()[0], 0x2345u );
             
             c.erase((boost::next(c.begin(),2)),c.end());
             BOOST_CHECK_EQUAL( c.size(), 2u );
             BOOST_CHECK_EQUAL( c.bytes(), 12u );
-            BOOST_CHECK_EQUAL( c.front()[0],0x1357u );
-            BOOST_CHECK_EQUAL( c.back()[0], 0x1357u );
+            BOOST_CHECK_EQUAL( c.front().vec()[0],0x1357u );
+            BOOST_CHECK_EQUAL( c.back().vec()[0], 0x1357u );
 
             c.clear();
             BOOST_CHECK_EQUAL( c.size(), 0u );
index 1e8c56f..7decaa3 100644 (file)
@@ -37,12 +37,21 @@ namespace {
     struct VoidPacket_Type : public senf::PacketTypeBase
     {};
     typedef senf::ConcretePacket<VoidPacket_Type> VoidPacket;
+
+    struct MyVec : public senf::PacketParserBase
+    {
+#       include SENF_PARSER()
+
+        SENF_PARSER_PRIVATE_FIELD( size, senf::Parse_UInt8 );
+        SENF_PARSER_VEC_N( vec, size, senf::Parse_UInt16 );
+
+        SENF_PARSER_FINALIZE(MyVec);
+    };
 }
 
 BOOST_AUTO_UNIT_TEST(parseListN)
 {
-    typedef senf::Parse_VectorN<senf::Parse_UInt16,senf::Parse_UInt8>::parser ParseVec;
-    typedef senf::Parse_ListN<ParseVec,senf::Parse_UInt16>::parser ParseList;
+    typedef senf::Parse_ListN<MyVec,senf::Parse_UInt16>::parser ParseList;
     
     VoidPacket vp (VoidPacket::create(ParseList::init_bytes));
 
@@ -62,35 +71,35 @@ BOOST_AUTO_UNIT_TEST(parseListN)
         BOOST_CHECK_EQUAL( p.bytes(), 3u );
         BOOST_CHECK_EQUAL( p.size(), 1u );
         BOOST_CHECK_EQUAL( p.front().bytes(), 1u );
-        BOOST_CHECK_EQUAL( p.front().size(), 0u );
+        BOOST_CHECK_EQUAL( p.front().vec().size(), 0u );
         BOOST_CHECK_EQUAL( vp.data()[1], 0x01u );
 
-        p.front().push_back(0x1234u);
-        BOOST_CHECK_EQUAL( p.front().size(), 1u );
+        p.front().vec().push_back(0x1234u);
+        BOOST_CHECK_EQUAL( p.front().vec().size(), 1u );
         BOOST_CHECK_EQUAL( p.front().bytes(), 3u );
-        BOOST_CHECK_EQUAL( p.front()[0], 0x1234u );
+        BOOST_CHECK_EQUAL( p.front().vec()[0], 0x1234u );
         BOOST_CHECK_EQUAL( p.size(), 1u );
         BOOST_CHECK_EQUAL( p.bytes(), 5u );
 
-        p.front().push_back(0x2345u);
-        BOOST_CHECK_EQUAL( p.front().back(), 0x2345u );
+        p.front().vec().push_back(0x2345u);
+        BOOST_CHECK_EQUAL( p.front().vec().back(), 0x2345u );
         BOOST_CHECK_EQUAL( p.bytes(), 7u );
 
         p.push_back_space();
         BOOST_CHECK_EQUAL( p.size(), 2u );
         BOOST_CHECK_EQUAL( p.bytes(), 8u );
         
-        p.back().push_front(0x0123u);
-        BOOST_CHECK_EQUAL( p.front().size(), 2u );
-        BOOST_CHECK_EQUAL( p.back().size(), 1u );
+        p.back().vec().push_front(0x0123u);
+        BOOST_CHECK_EQUAL( p.front().vec().size(), 2u );
+        BOOST_CHECK_EQUAL( p.back().vec().size(), 1u );
 
         p.push_front_space(2u);
         BOOST_CHECK_EQUAL( p.size(), 4u );
-        BOOST_CHECK_EQUAL( p.front().size(), 0u);
+        BOOST_CHECK_EQUAL( p.front().vec().size(), 0u);
         
         p.resize(3u);
         BOOST_CHECK_EQUAL( p.size(), 3u );
-        BOOST_CHECK_EQUAL( p.back()[0], 0x1234u );
+        BOOST_CHECK_EQUAL( p.back().vec()[0], 0x1234u );
         BOOST_CHECK_EQUAL( p.bytes(), 9u );
 
 #       undef p
@@ -99,8 +108,7 @@ BOOST_AUTO_UNIT_TEST(parseListN)
 
 BOOST_AUTO_UNIT_TEST(parseListN_container)
 {
-    typedef senf::Parse_VectorN<senf::Parse_UInt16,senf::Parse_UInt8>::parser ParseVec;
-    typedef senf::Parse_ListN<ParseVec,senf::Parse_UInt16>::parser ParseList;
+    typedef senf::Parse_ListN<MyVec,senf::Parse_UInt16>::parser ParseList;
     
     VoidPacket vp (VoidPacket::create(ParseList::init_bytes));
 
index 14ac2d6..962ded0 100644 (file)
@@ -165,40 +165,42 @@ prefix_ void senf::Parse_Vector<ElementParser,Sizer>::resize(size_type n, Value
 ///////////////////////////////////////////////////////////////////////////
 // senf::SimpleSizeParser<SizeParser,offset>
 
-template <class SizeParser>
-prefix_ typename senf::detail::Parse_VectorN_Sizer<SizeParser>::size_type
-senf::detail::Parse_VectorN_Sizer<SizeParser>::size(iterator i, state_type s)
+template <class SizeParser, unsigned Distance>
+prefix_ typename senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::size_type
+senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::size(iterator i, state_type s)
     const
 {
-    return SizeParser(i,s).value();
+    return SizeParser(boost::prior(i, Distance), s).value();
 }
 
-template <class SizeParser>
-prefix_ void senf::detail::Parse_VectorN_Sizer<SizeParser>::size(iterator i, state_type s,
-                                                              size_type v)
+template <class SizeParser, unsigned Distance>
+prefix_ void senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::size(iterator i,
+                                                                          state_type s,
+                                                                          size_type v)
     const
 {
-    SizeParser(i,s).value(v);
+    SizeParser(boost::prior(i, Distance), s).value(v);
 }
 
-template <class SizeParser>
-prefix_ typename senf::detail::Parse_VectorN_Sizer<SizeParser>::iterator
-senf::detail::Parse_VectorN_Sizer<SizeParser>::begin(iterator i, state_type s)
+template <class SizeParser, unsigned Distance>
+prefix_ typename senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::iterator
+senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::begin(iterator i, state_type s)
     const
 {
-    return boost::next(i,SizeParser::fixed_bytes);
+    return i;
 }
 
-template <class SizeParser>
-prefix_ typename senf::detail::Parse_VectorN_Sizer<SizeParser>::size_type
-senf::detail::Parse_VectorN_Sizer<SizeParser>::bytes(iterator i, state_type s)
+template <class SizeParser, unsigned Distance>
+prefix_ typename senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::size_type
+senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::bytes(iterator i, state_type s)
     const
 {
-    return SizeParser::fixed_bytes;
+    return 0;
 }
 
-template <class SizeParser>
-prefix_ void senf::detail::Parse_VectorN_Sizer<SizeParser>::init(iterator i, state_type s)
+template <class SizeParser, unsigned Distance>
+prefix_ void senf::detail::Parse_VectorN_Sizer<SizeParser,Distance>::init(iterator i,
+                                                                          state_type s)
     const
 {}
 
index beb953f..5d8d180 100644 (file)
@@ -35,6 +35,7 @@
 #include "ParseArray.hh" // for Parse_Array_iterator
 
 //#include "ParseVec.mpp"
+#include "ParseVec.ih"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
@@ -111,8 +112,6 @@ namespace senf {
         friend class Parse_Vector_Container<ElementParser,Sizer>;
     };
 
-    namespace detail { template <class SizeParser> class Parse_VectorN_Sizer; }
-
     /** \brief Vector with prefix sizing
         
         This is a 'template typedef'. It defines a vector with a <em>directly preceding</em> size
@@ -130,28 +129,42 @@ namespace senf {
         \see Parse_Vector
         \ingroup parsecollection
      */
-    template <class ElementParser, class SizeParser>
+    template <class ElementParser, class SizeParser, unsigned Distance>
     struct Parse_VectorN
     {
         typedef Parse_Vector< ElementParser,
-                              detail::Parse_VectorN_Sizer<SizeParser> > parser;
+                              detail::Parse_VectorN_Sizer<SizeParser, Distance> > parser;
     };
 
     /** \brief Define Parse_VectorN field
         
         This macro is a special helper to define a senf::Parse_VectorN type field, a vector of
-        elements of type \a elt_type (a parser) directly preceded by a numeric size field of type \a
-        size_type (another parser).
+        elements of type \a elt_type (a parser) which size is given by the \a size field.
+
+        \code
+        // The size field should be declared private (size is accessible via the vector)
+        SENF_PARSER_PRIVATE_FIELD ( vec_size_, senf::Parse_UInt16 );
+        // Define the vector, here it has 32bit unsigned integer elements
+        SENF_PARSER_VEC_N         ( vec,       _vec_size, senf::Parse_UInt32 );
+        \endcode
         
         \param[in] name field name
+        \param[in] size name of field giving the vector size
         \param[in] elt_type vector element type
-        \param[in] size_type size type
         \hideinitializer
         \ingroup packetparsermacros
      */
-#   define SENF_PARSER_VEC_N(name, elt_type, size_type)                                           \
-        typedef senf::Parse_VectorN<elt_type, size_type>::parser BOOST_PP_CAT(name, _vec_t);      \
-        SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _vec_t) )
+#   define SENF_PARSER_VEC_N(name, size, elt_type)                                                \
+        SENF_PARSER_VEC_N_I(SENF_PARSER_FIELD, name, size, elt_type)
+
+    /** \brief Define Parse_VectorN field
+
+        \see \ref SENF_PARSER_VEC_N()
+        \hideinitializer
+        \ingroup packetparsermacros
+     */
+#   define SENF_PARSER_PRIVATE_VEC_N(name, size, elt_type)                                        \
+        SENF_PARSER_VEC_N_I(SENF_PARSER_PRIVATE_FIELD, name, size, elt_type)
 
     /** \brief Parse_Vector container wrapper
 
index 339b8f4..2937351 100644 (file)
@@ -37,14 +37,14 @@ namespace detail {
 
         This is the sizer policy used by Parse_VectorN
      */
-    template <class SizeParser>
+    template <class SizeParser, unsigned Distance>
     struct Parse_VectorN_Sizer
     {
         typedef PacketParserBase::size_type size_type;
         typedef PacketParserBase::data_iterator iterator;
         typedef PacketParserBase::state_type state_type;
 
-        static const size_type init_bytes = SizeParser::fixed_bytes;
+        static const size_type init_bytes = 0;
 
         size_type  size  (iterator i, state_type s) const;
         void       size  (iterator i, state_type s, size_type v) const;
@@ -53,6 +53,14 @@ namespace detail {
         void       init  (iterator i, state_type s) const;
     };
 
+#   define SENF_PARSER_VEC_N_I(field, name, size, elt_type)                                       \
+        typedef senf::Parse_VectorN< elt_type,                                                    \
+                                     BOOST_PP_CAT(size, _t),                                      \
+                                     SENF_PARSER_CURRENT_FIXED_OFFSET()                           \
+                                         - SENF_PARSER_FIXED_OFFSET(size)                         \
+            >::parser BOOST_PP_CAT(name, _vec_t);                                                 \
+        field( name, BOOST_PP_CAT(name, _vec_t) )
+
 }}
 
 ///////////////////////////////ih.e////////////////////////////////////////
index daa30d1..74e028f 100644 (file)
@@ -48,20 +48,20 @@ BOOST_AUTO_UNIT_TEST(parseVec)
     senf::PacketInterpreterBase::ptr p (senf::PacketInterpreter<VoidPacket>::create(data));
     typedef senf::Parse_Vector<
         senf::Parse_UInt16,
-        senf::detail::Parse_VectorN_Sizer<senf::Parse_UInt8>
+        senf::detail::Parse_VectorN_Sizer<senf::Parse_UInt8, 1u>
         > Parse_UInt16Vec;
 
     {
-        Parse_UInt16Vec v (p->data().begin(), &p->data());
+        Parse_UInt16Vec v (boost::next(p->data().begin(), 1), &p->data());
         
         BOOST_CHECK_EQUAL( v[0], 0x1011 );
         BOOST_CHECK_EQUAL( v[2], 0x1415 );
         BOOST_CHECK_EQUAL( v.size(), 3u );
-        BOOST_CHECK_EQUAL( v.bytes(), 7u );
+        BOOST_CHECK_EQUAL( v.bytes(), 6u );
         BOOST_CHECK( ! v.empty() );
         p->data()[0] = 0x06;
         BOOST_CHECK_EQUAL( v.size(), 6u );
-        BOOST_CHECK_EQUAL( v.bytes(), 13u );
+        BOOST_CHECK_EQUAL( v.bytes(), 12u );
         
         Parse_UInt16Vec::iterator b (v.begin());
         Parse_UInt16Vec::iterator e (v.end());
@@ -75,7 +75,7 @@ BOOST_AUTO_UNIT_TEST(parseVec)
     // we don't need to check them again below ...
 
     {
-#       define v Parse_UInt16Vec(p->data().begin(),&p->data())
+#       define v Parse_UInt16Vec(boost::next(p->data().begin(),1),&p->data())
 
         v.push_back(0xf0f1u,2);
         BOOST_CHECK_EQUAL( v.size(), 8u );
@@ -123,9 +123,9 @@ BOOST_AUTO_UNIT_TEST(parseVec_wrapper)
     senf::PacketInterpreterBase::ptr p (senf::PacketInterpreter<VoidPacket>::create(data));
     typedef senf::Parse_Vector<
         senf::Parse_UInt16,
-        senf::detail::Parse_VectorN_Sizer<senf::Parse_UInt8>
+        senf::detail::Parse_VectorN_Sizer<senf::Parse_UInt8, 1u>
         > Parse_UInt16Vec;
-    Parse_UInt16Vec v (p->data().begin(), &p->data());
+    Parse_UInt16Vec v (boost::next(p->data().begin(),1), &p->data());
     Parse_UInt16Vec::container w (v);
 
     BOOST_CHECK_EQUAL( w[0], 0x1011 );