Packets: Implement packet size aux parser policy and packetSize() collection macro...
g0dil [Fri, 23 Jan 2009 09:47:07 +0000 (09:47 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1074 270642c3-0616-0410-b53a-bc976706d245

Packets/AuxParser.cci [new file with mode: 0644]
Packets/AuxParser.hh
Packets/AuxParser.test.cc [new file with mode: 0644]
Packets/ListBParser.test.cc
Packets/ListParser.hh
Packets/ParseHelpers.ih
Packets/VectorParser.hh
Packets/VectorParser.test.cc

diff --git a/Packets/AuxParser.cci b/Packets/AuxParser.cci
new file mode 100644 (file)
index 0000000..b354214
--- /dev/null
@@ -0,0 +1,70 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief AuxParser inline non-template implementation */
+
+//#include "AuxParser.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::PacketSizeAuxParserPolicy
+
+prefix_ senf::PacketParserBase::size_type
+senf::detail::PacketSizeAuxParserPolicy::aux(PacketParserBase::data_iterator i,
+                                             PacketParserBase::state_type s)
+    const
+{
+    return std::distance(i, s->end());
+}
+
+prefix_ void senf::detail::PacketSizeAuxParserPolicy::aux(unsigned v,
+                                                          PacketParserBase::data_iterator i,
+                                                          PacketParserBase::state_type s)
+    const
+{}
+
+prefix_ senf::PacketParserBase::data_iterator
+senf::detail::PacketSizeAuxParserPolicy::adjust(PacketParserBase::data_iterator i,
+                                                PacketParserBase::state_type s)
+    const
+{
+    return i;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 412bb2d..cdba703 100644 (file)
@@ -147,13 +147,25 @@ namespace detail {
         typename Transform::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
         void aux(typename Transform::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
     };
+
+    struct PacketSizeAuxParserPolicy
+    {
+        typedef PacketSizeAuxParserPolicy WrapperPolicy;
+        typedef PacketSizeAuxParserPolicy ParserPolicy;
+
+        static PacketParserBase::size_type const aux_bytes = 0;
+
+        PacketParserBase::size_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        void aux(unsigned v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+    };
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #endif
 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_AuxParser_i_)
 #define HH_SENF_Packets_AuxParser_i_
-//#include "AuxParser.cci"
+#include "AuxParser.cci"
 //#include "AuxParser.ct"
 #include "AuxParser.cti"
 #endif
diff --git a/Packets/AuxParser.test.cc b/Packets/AuxParser.test.cc
new file mode 100644 (file)
index 0000000..af26822
--- /dev/null
@@ -0,0 +1,177 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief AuxParser.test unit tests */
+
+//#include "AuxParser.test.hh"
+//#include "AuxParser.test.ih"
+
+// Custom includes
+#include "Packets.hh"
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+// The other aux policies are tested with the corresponding container classes
+
+BOOST_AUTO_UNIT_TEST(vectorPacketSizeAuxPolicy)
+{
+    unsigned char data[] = { 0x10, 0x11,  0x12, 0x13,  0x14, 0x15,
+                             0x20, 0x21,  0x22, 0x23,  0x24, 0x25 };
+    senf::Packet p (senf::DataPacket::create(data));
+
+    typedef senf::VectorParser<
+        senf::UInt8Parser,
+        senf::detail::PacketSizeAuxParserPolicy
+        > UInt8VectorParser;
+
+    {
+        UInt8VectorParser v (p.data().begin(), &p.data());
+
+        BOOST_CHECK_EQUAL( v.size(), p.data().size() );
+        BOOST_CHECK_EQUAL_COLLECTIONS( v.begin(), v.end(), data, data+sizeof(data) );
+    }
+
+    {
+        UInt8VectorParser v (p.data().begin(), &p.data());
+        UInt8VectorParser::container w (v);
+
+        BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(), data, data+sizeof(data) );
+
+        w.shift(w.begin()+1);
+        BOOST_CHECK_EQUAL( w.size(), p.data().size() );
+
+        w.erase(w.begin()+3, w.begin()+5);
+        BOOST_CHECK_EQUAL( w.size(), p.data().size() );
+
+        unsigned char data2[] = { 0x10, 0x00, 0x11, 0x14, 0x15,
+                                  0x20, 0x21,  0x22, 0x23,  0x24, 0x25 };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(), data2, data2+sizeof(data2) );
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(vectorPacketSizeAuxPolicy_transformed)
+{
+    unsigned char data[] = { 0x10, 0x11,  0x12, 0x13,  0x14, 0x15,
+                             0x20, 0x21,  0x22, 0x23,  0x24, 0x25 };
+    senf::Packet p (senf::DataPacket::create(data));
+
+    typedef senf::VectorParser<
+        senf::UInt16Parser,
+        senf::detail::TransformAuxParserPolicy<
+            senf::detail::PacketSizeAuxParserPolicy,
+            senf::detail::VectorParserBytesTransform<senf::UInt16Parser::fixed_bytes> >
+        > UInt16VectorParser;
+
+    {
+        UInt16VectorParser v (p.data().begin(), &p.data());
+        
+        BOOST_REQUIRE_EQUAL( v.size(), p.data().size()/2 );
+        BOOST_CHECK_EQUAL( v[0], 0x1011u );
+        BOOST_CHECK_EQUAL( v[1], 0x1213u );
+        BOOST_CHECK_EQUAL( v[5], 0x2425u );
+    }
+
+    {
+        UInt16VectorParser v (p.data().begin(), &p.data());
+        UInt16VectorParser::container w (v);
+
+        BOOST_REQUIRE_EQUAL( w.size(), p.data().size()/2 );
+        BOOST_CHECK_EQUAL( w[0], 0x1011u );
+        BOOST_CHECK_EQUAL( w[1], 0x1213u );
+        BOOST_CHECK_EQUAL( w[5], 0x2425u );
+
+        w.shift(w.begin()+1);
+        BOOST_CHECK_EQUAL( w.size(), p.data().size()/2 );
+
+        w.erase(w.begin()+3, w.begin()+5);
+        BOOST_CHECK_EQUAL( w.size(), p.data().size()/2 );
+
+        senf::UInt16Parser::value_type  data2[] = 
+            { 0x1011u, 0x0000u, 0x1213u, 0x2223u, 0x2425u };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(), 
+                                       data2, data2+sizeof(data2)/sizeof(data2[0]) );
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(listPacketSizeAuxPolicy)
+{
+    unsigned char data[] = { 0x10, 0x11,  0x12, 0x13,  0x14, 0x15,
+                             0x20, 0x21,  0x22, 0x23,  0x24, 0x25 };
+    senf::Packet p (senf::DataPacket::create(data));
+
+    typedef senf::ListParser<
+        senf::detail::ListBParser_Policy<
+            senf::UInt16Parser,
+            senf::detail::PacketSizeAuxParserPolicy>
+        > ListParser;
+
+    {
+        ListParser l (p.data().begin(), &p.data());
+
+        BOOST_REQUIRE_EQUAL( l.size(), p.data().size()/2 );
+        BOOST_CHECK_EQUAL( l.front(), 0x1011u );
+        BOOST_CHECK_EQUAL( l.back(), 0x2425u );
+    }
+
+    {
+        ListParser l (p.data().begin(), &p.data());
+        ListParser::container w (l);
+
+        BOOST_REQUIRE_EQUAL( w.size(), p.data().size()/2 );
+        BOOST_CHECK_EQUAL( *w.begin(), 0x1011u );
+        BOOST_CHECK_EQUAL( *boost::next(w.begin()), 0x1213u );
+        BOOST_CHECK_EQUAL( *boost::next(w.begin(),5), 0x2425u );
+
+        w.shift(boost::next(w.begin()));
+        BOOST_CHECK_EQUAL( w.size(), p.data().size()/2 );
+
+        w.erase(boost::next(w.begin(),3), boost::next(w.begin(),5));
+        BOOST_CHECK_EQUAL( w.size(), p.data().size()/2 );
+
+        senf::UInt16Parser::value_type  data2[] = 
+            { 0x1011u, 0x0000u, 0x1213u, 0x2223u, 0x2425u };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(), 
+                                       data2, data2+sizeof(data2)/sizeof(data2[0]) );
+    }
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 82b6dd3..585f176 100644 (file)
@@ -239,6 +239,108 @@ BOOST_AUTO_UNIT_TEST(listBytesMacro)
 
 }
 
+namespace {
+
+    struct TestPacketSizeList
+        : public senf::PacketParserBase
+    {
+#       include SENF_PARSER()
+
+        SENF_PARSER_LIST ( list, packetSize(), VectorParser );
+
+        SENF_PARSER_FINALIZE(TestPacketSizeList);
+    };
+
+
+}
+
+BOOST_AUTO_UNIT_TEST(listBytesParser_packetSize)
+{
+    unsigned char data[] = { 0x01,                   // list()[0].vec().size()
+                             0x05, 0x06,             // list()[0].vec()[0]
+                             0x02,                   // list()[1].vec().size()
+                             0x07, 0x08,             // list()[1].vec()[0]
+                             0x09, 0x0A,             // list()[1].vec()[1]
+                             0x00,                   // list()[2].vec().size()
+                             0x02,                   // list()[3].vec().size()
+                             0x0B, 0x0C,             // list()[3].vec()[0]
+                             0x0D, 0x0E,             // list()[3].vec()[1]
+                             0x01,                   // list()[4].vec().size()
+                             0x0F, 0x10 };           // list()[4].vec()[0]
+    
+    senf::DataPacket p (senf::DataPacket::create(data));
+
+    {
+        TestPacketSizeList l (p.data().begin(), &p.data());
+        BOOST_CHECK_EQUAL( l.list().size(), 5u );
+
+        TestPacketSizeList::list_t::container c (l.list());
+        TestPacketSizeList::list_t::container::iterator i (c.begin());
+
+        senf::UInt16Parser::value_type vec0[] = { 0x0506 };
+        senf::UInt16Parser::value_type vec1[] = { 0x0708, 0x090A };
+        senf::UInt16Parser::value_type vec2[] = {};
+        senf::UInt16Parser::value_type vec3[] = { 0x0B0C, 0x0D0E };
+        senf::UInt16Parser::value_type vec4[] = { 0x0F10 };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec0, vec0+sizeof(vec0)/sizeof(vec0[0]) );
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec1, vec1+sizeof(vec1)/sizeof(vec1[0]) );
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec2, vec2+sizeof(vec2)/sizeof(vec2[0]) );
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec3, vec3+sizeof(vec3)/sizeof(vec3[0]) );
+
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec4, vec4+sizeof(vec4)/sizeof(vec4[0]) );
+
+        ++ i;
+        BOOST_CHECK( i == c.end() );
+
+        i = c.begin();
+        ++i;
+        TestPacketSizeList::list_t::value_type::vec_t::container v (i->vec());
+        v.push_back(0xFEFF);
+    }
+
+    {
+        TestPacketSizeList l (p.data().begin(), &p.data());
+        BOOST_CHECK_EQUAL( l.list().size(), 5u );
+        BOOST_CHECK_EQUAL( l.list().bytes(), p.data().size() );
+
+        TestPacketSizeList::list_t::container c (l.list());
+        TestPacketSizeList::list_t::container::iterator i (c.begin());
+
+        senf::UInt16Parser::value_type vec0[] = { 0x0506 };
+        senf::UInt16Parser::value_type vec1[] = { 0x0708, 0x090A, 0xFEFF };
+        senf::UInt16Parser::value_type vec2[] = {};
+        senf::UInt16Parser::value_type vec3[] = { 0x0B0C, 0x0D0E };
+        senf::UInt16Parser::value_type vec4[] = { 0x0F10 };
+
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec0, vec0+sizeof(vec0)/sizeof(vec0[0]) );
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec1, vec1+sizeof(vec1)/sizeof(vec1[0]) );
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec2, vec2+sizeof(vec2)/sizeof(vec2[0]) );
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec3, vec3+sizeof(vec3)/sizeof(vec3[0]) );
+
+        ++ i;
+        BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
+                                       vec4, vec4+sizeof(vec4)/sizeof(vec4[0]) );
+        ++ i;
+        BOOST_CHECK( i == c.end() );
+    }
+}
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
index 817ba48..1b0a4f6 100644 (file)
@@ -244,6 +244,9 @@ namespace senf {
         <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the list in bytes not the
         number of contained elements</td></tr>
 
+        <tr><td>\c packetSize()</td><td>Use the size of the packet to get the list size. The
+        list will occupy all space up to the end of the packet.</td></tr>
+
         <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
         size value, the value is not used directly</td>
 
index f279f35..a4d1cd9 100644 (file)
   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
-#
-# // 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_AUXTYPE__bytes(x) auxField
 #
 # define SENF_PARSER_COLLECTION_TAG_GOBBLE__transform(x,y)
 # define SENF_PARSER_COLLECTION_TAG__transform(x,y) \
           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
 #
           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) )
 #
                   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, aux, tag, 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),                                                     \
               BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_EXPAND__, tag)                              \
                                      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);
                                           SENF_PARSER_CURRENT_FIXED_OFFSET()                      \
                                               - SENF_PARSER_FIXED_OFFSET(aux) >
 #
+# 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              \
           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
 #
index 3ac2e44..623e18f 100644 (file)
@@ -246,6 +246,9 @@ namespace senf {
         <table class="senf fixedcolumn">
         <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the vector in bytes not the
         number of contained elements</td></tr>
+        
+        <tr><td>\c packetSize()</td><td>Use the size of the packet to get the vector size. The
+        vector will occupy all space up to the end of the packet.</td></tr>
 
         <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
         size value, the value is not used directly</td>
@@ -266,6 +269,7 @@ namespace senf {
         The tags are applied to the \a size parameter:
         \code
         SENF_PARSER_VECTOR ( vec, transform(MyTransform, vec_size_), senf::UInt32Parser );
+        SENF_PARSER_VECTOR ( vec, packetSize(), senf::UInt32Parser );
         \endcode
         
         \param[in] name field name
index c00b541..f720df0 100644 (file)
@@ -337,6 +337,38 @@ BOOST_AUTO_UNIT_TEST(vectorMacro_inherit)
     BOOST_CHECK_EQUAL( parser.vec2()[1], 0x0D0Eu );
 }
 
+namespace {
+
+    struct TestPacketSizeVectorParser
+        : public senf::PacketParserBase
+    {
+#       include SENF_PARSER()
+
+        SENF_PARSER_VECTOR        ( vec   , packetSize() , senf::UInt16Parser );
+        
+        SENF_PARSER_FINALIZE( TestPacketSizeVectorParser );
+    };
+
+}
+
+BOOST_AUTO_UNIT_TEST(vectorMacro_packetSize)
+{
+    unsigned char data[] = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+                             0x21, 0x22, 0x23, 0x24, 0x25, 0x26 };
+
+    senf::DataPacket p (senf::DataPacket::create(data));
+    TestPacketSizeVectorParser parser (p.data().begin(), &p.data());
+
+    {
+        BOOST_CHECK_EQUAL( parser.vec().size(), 6u );
+        BOOST_CHECK_EQUAL( parser.vec()[0], 0x1112u );
+        BOOST_CHECK_EQUAL( parser.vec()[1], 0x1314u );
+        BOOST_CHECK_EQUAL( parser.vec()[5], 0x2526u );
+    }
+
+    // The real functionality is already tested in AuxPolixy.test.cc ...
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_