Packets: Update AuxParser interface
g0dil [Mon, 9 Jun 2008 13:57:27 +0000 (13:57 +0000)]
Packets: Extend VectorParser implementation to support aux tags
Packets: Migrate ListParser and it's policies to use the new AuxParser/collection infrastructure

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@869 270642c3-0616-0410-b53a-bc976706d245

22 files changed:
Packets/AuxParser.cti
Packets/AuxParser.hh
Packets/ListBParser.cti
Packets/ListBParser.hh
Packets/ListBParser.ih
Packets/ListBParser.test.cc
Packets/ListNParser.ct
Packets/ListNParser.cti
Packets/ListNParser.hh
Packets/ListNParser.ih
Packets/ListNParser.test.cc
Packets/ListParser.ct
Packets/ListParser.cti
Packets/ListParser.dox
Packets/ListParser.hh
Packets/ListParser.ih
Packets/ParseHelpers.ih
Packets/VectorParser.ct
Packets/VectorParser.cti
Packets/VectorParser.hh
Packets/VectorParser.ih
Packets/VectorParser.test.cc

index 205d88d..e4f9832 100644 (file)
 // senf::detail::PrefixAuxParserPolicy<P>
 
 template <class P>
-prefix_ typename senf::detail::PrefixAuxParserPolicy<P>::ParserType
+prefix_ typename P::value_type
 senf::detail::PrefixAuxParserPolicy<P>::aux(PacketParserBase::data_iterator i,
                                             PacketParserBase::state_type s)
     const
 {
-    return ParserType(i, s);
+    return P(i, s).value();
+}
+
+template <class P>
+prefix_ void senf::detail::PrefixAuxParserPolicy<P>::aux(typename P::value_type const & v,
+                                                         PacketParserBase::data_iterator i,
+                                                         PacketParserBase::state_type s)
+    const
+{
+    P(i, s).value(v);
 }
 
 template <class P>
@@ -48,19 +57,28 @@ senf::detail::PrefixAuxParserPolicy<P>::adjust(PacketParserBase::data_iterator i
                                                PacketParserBase::state_type s)
     const
 {
-    return i+ParserType::fixed_bytes;
+    return i+P::fixed_bytes;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::FixedAuxParserPolicy<P>
 
 template <class P, unsigned Dist>
-prefix_ typename senf::detail::FixedAuxParserPolicy<P,Dist>::ParserType
+prefix_ typename P::value_type
 senf::detail::FixedAuxParserPolicy<P,Dist>::aux(PacketParserBase::data_iterator i,
                                                 PacketParserBase::state_type s)
     const
 {
-    return ParserType(i-Dist, s);
+    return P(i-Dist, s).value();
+}
+
+template <class P, unsigned Dist>
+prefix_ void senf::detail::FixedAuxParserPolicy<P,Dist>::aux(typename P::value_type const & v,
+                                                             PacketParserBase::data_iterator i,
+                                                             PacketParserBase::state_type s)
+    const
+{
+    P(i-Dist, s).value(v);
 }
 
 template <class P, unsigned Dist>
@@ -76,7 +94,7 @@ senf::detail::FixedAuxParserPolicy<P,Dist>::adjust(PacketParserBase::data_iterat
 // senf::detail::DynamicAuxParserPolicy<P>
 
 template <class P>
-prefix_ senf::detail::DynamicAuxParserPolicy<P>::DynamicAuxParserPolicy(ParserType p)
+prefix_ senf::detail::DynamicAuxParserPolicy<P>::DynamicAuxParserPolicy(P p)
     : p_ (p)
 {}
 
@@ -87,12 +105,21 @@ senf::detail::DynamicAuxParserPolicy<P>::DynamicAuxParserPolicy(WrapperPolicy co
 {}
 
 template <class P>
-prefix_ typename senf::detail::DynamicAuxParserPolicy<P>::ParserType
+prefix_ typename P::value_type
 senf::detail::DynamicAuxParserPolicy<P>::aux(PacketParserBase::data_iterator i,
                                              PacketParserBase::state_type s)
     const
 {
-    return p_;
+    return p_.value();
+}
+
+template <class P>
+prefix_ void senf::detail::DynamicAuxParserPolicy<P>::aux(typename P::value_type const & v,
+                                                          PacketParserBase::data_iterator i,
+                                                          PacketParserBase::state_type s)
+    const
+{
+    p_.value(v);
 }
 
 template <class P>
@@ -114,12 +141,22 @@ DynamicWrapperAuxParserPolicy(ParserPolicy const & other)
 {}
 
 template <class P>
-prefix_ typename senf::detail::DynamicWrapperAuxParserPolicy<P>::ParserType
+prefix_ typename P::value_type
 senf::detail::DynamicWrapperAuxParserPolicy<P>::aux(PacketParserBase::data_iterator i,
                                                     PacketParserBase::state_type s)
     const
 {
-    return * p_;
+    return p_->value();
+}
+
+template <class P>
+prefix_ void
+senf::detail::DynamicWrapperAuxParserPolicy<P>::aux(typename P::value_type const & v,
+                                                    PacketParserBase::data_iterator i,
+                                                    PacketParserBase::state_type s)
+    const
+{
+    p_->value(v);
 }
 
 template <class P>
@@ -131,6 +168,38 @@ senf::detail::DynamicWrapperAuxParserPolicy<P>::adjust(PacketParserBase::data_it
     return i;
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::TransformAuxParserPolicy<Policy,Transform>
+
+template <class Policy, class Transform>
+prefix_ senf::detail::TransformAuxParserPolicy<Policy,Transform>::TransformAuxParserPolicy()
+{}
+
+template <class Policy, class Transform>
+template <class Arg>
+prefix_ senf::detail::TransformAuxParserPolicy<Policy,Transform>::
+TransformAuxParserPolicy(Arg const & arg)
+    : Policy(arg)
+{}
+
+template <class Policy, class Transform>
+prefix_ typename Transform::value_type
+senf::detail::TransformAuxParserPolicy<Policy,Transform>::aux(PacketParserBase::data_iterator i,
+                                                              PacketParserBase::state_type s)
+    const
+{
+    return Transform::get(Policy::aux(i,s));
+}
+
+template <class Policy, class Transform>
+prefix_ void senf::detail::TransformAuxParserPolicy<Policy,Transform>::
+aux(typename Transform::value_type const & v, PacketParserBase::data_iterator i,
+    PacketParserBase::state_type s)
+    const
+{
+    Policy::aux(Transform::set(v), i, s);
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 162657e..5e4a427 100644 (file)
@@ -44,11 +44,12 @@ namespace detail {
     struct PrefixAuxParserPolicy
     {
         typedef PrefixAuxParserPolicy WrapperPolicy;
-        typedef P ParserType;
+        typedef PrefixAuxParserPolicy ParserPolicy;
 
-        static PacketParserBase::size_type const aux_bytes = ParserType::fixed_bytes;
+        static PacketParserBase::size_type const aux_bytes = P::fixed_bytes;
         
-        ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
         PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
     };
 
@@ -56,11 +57,12 @@ namespace detail {
     struct FixedAuxParserPolicy
     {
         typedef FixedAuxParserPolicy WrapperPolicy;
-        typedef P ParserType;
+        typedef FixedAuxParserPolicy ParserPolicy;
 
         static PacketParserBase::size_type const aux_bytes = 0;
         
-        ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
         PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
     };
 
@@ -70,33 +72,51 @@ namespace detail {
     struct DynamicAuxParserPolicy
     {
         typedef DynamicWrapperAuxParserPolicy<P> WrapperPolicy;
-        typedef P ParserType;
+        typedef DynamicAuxParserPolicy<P> ParserPolicy;
 
         static PacketParserBase::size_type const aux_bytes = 0;
 
-        DynamicAuxParserPolicy(ParserType p);
+        DynamicAuxParserPolicy(P p);
         DynamicAuxParserPolicy(WrapperPolicy const & other);
         
-        ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
         PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
 
-        ParserType p_;
+        mutable P p_;
     };
 
     template <class P>
     struct DynamicWrapperAuxParserPolicy
     {
+        typedef DynamicWrapperAuxParserPolicy<P> WrapperPolicy;
         typedef DynamicAuxParserPolicy<P> ParserPolicy;
-        typedef P ParserType;
 
         static PacketParserBase::size_type const aux_bytes = 0;
 
         DynamicWrapperAuxParserPolicy(ParserPolicy const & other);
         
-        ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
+        void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
         PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
 
-        SafePacketParserWrapper<ParserType> p_;
+        mutable SafePacketParserWrapper<P> p_;
+    };
+
+    template <class Policy, class Transform>
+    struct TransformAuxParserPolicy
+        : public Policy
+    {
+        typedef TransformAuxParserPolicy<typename Policy::WrapperPolicy, Transform> WrapperPolicy;
+        typedef TransformAuxParserPolicy<typename Policy::ParserPolicy, Transform> ParserPolicy;
+
+        static PacketParserBase::size_type const aux_bytes = Policy::aux_bytes;
+        
+        TransformAuxParserPolicy();
+        template <class Arg> TransformAuxParserPolicy(Arg const & arg);
+
+        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;
     };
 }}
 
index ac7b19c..ac603c3 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::detail::ListBParser_Policy<ElementParser,BytesParser>
+// senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>
+
+template <class ElementParser, class AuxPolicy>
+prefix_ senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::ListBParser_Policy()
+{}
 
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::size_type
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::bytes(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+template <class Arg>
+prefix_
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::ListBParser_Policy(Arg const & arg)
+    : AuxPolicy (arg)
+{}
+
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::size_type
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::bytes(data_iterator i, state_type s)
     const
 {
-    return BytesParser(i,s) + BytesParser::fixed_bytes;
+    return AuxPolicy::aux(i,s) + AuxPolicy::aux_bytes;
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::size_type
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::size(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::size_type
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::size(data_iterator i, state_type s)
     const
 {
-    parser_type l (i,s);
-    return std::distance(l.begin(),l.end());
+    parser_type p (*this, i, s);
+    container_type c (p);
+    return std::distance(c.begin(),c.end());
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ void senf::detail::ListBParser_Policy<ElementParser,BytesParser>::init(iterator i,
-                                                                               state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::init(data_iterator i,
+                                                                             state_type s)
     const
-{}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator_policy
-
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator_policy::
-setBegin(iterator i, state_type s)
 {
-    return boost::next(i,BytesParser::fixed_bytes);
+    AuxPolicy::aux(0,i,s);
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator_policy::
-setEnd(iterator i, state_type s)
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::ListBParser_Policy<ElementParser,BytesParser>
+
+template <class ElementParser, class AuxPolicy>
+prefix_
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+container_policy(parser_policy const & p)
+    : AuxPolicy (p)
 {
-    return boost::next(i,BytesParser(i,s) + BytesParser::fixed_bytes);
+    data_iterator const e (boost::next(parser_type::get(p).i(),parser_type::get(p).bytes()));
+    data_iterator i (AuxPolicy::adjust(parser_type::get(p).i(), parser_type::get(p).state()));
+    for( n_=0; i!=e; 
+         ++n_, std::advance(i,senf::bytes(ElementParser(i,parser_type::get(p).state())))) ;
+    container_size_ = parser_type::get(p).data().size();
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ void
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator_policy::
-setFromPosition(iterator i, state_type s, iterator p)
-{}
-
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator_policy::next(iterator i,
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::size_type
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::bytes(data_iterator i,
                                                                                    state_type s)
+    const
 {
-    return boost::next(i,senf::bytes(ElementParser(i,s)));
+    return AuxPolicy::aux(i,s) + AuxPolicy::aux_bytes;
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::iterator_policy::raw(iterator i,
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::size_type
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::size(data_iterator i,
                                                                                   state_type s)
     const
 {
-    return i;
+    return n_;
 }
 
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::ListBParser_Policy<ElementParser,BytesParser>
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+init(data_iterator i, state_type s)
+{
+    n_ = 0;
+    container_size_ = s->size();
+    AuxPolicy::aux(0,i,s);
+}
 
-template <class ElementParser, class BytesParser>
-prefix_
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-container_policy(parser_type const & list)
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+erase(container_type & c, data_iterator p)
 {
-    iterator const e (boost::next(list.i(),list.bytes()));
-    iterator i (boost::next(list.i(), BytesParser::fixed_bytes));
-    for(n_=0; i!=e; ++n_, std::advance(i,ElementParser(i,list.state()).bytes())) ;
-    container_size_ = list.data().size();
+    size_type b (senf::bytes(ElementParser(p,c.state())));
+    AuxPolicy::aux( AuxPolicy::aux(c.i(), c.state())-b, c.i(), c.state());
+    --n_;
+    // The container will be reduced by b bytes directly after this call
+    container_size_ = c.data().size()-b;
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::size_type
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-bytes(iterator i, state_type s)
-    const
+template <class ElementParser, class AuxPolicy>
+prefix_ void
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+insert(container_type & c, data_iterator p)
 {
-    return BytesParser(i,s) + BytesParser::fixed_bytes;
+    size_type b (senf::bytes(ElementParser(p,c.state())));
+    AuxPolicy::aux( AuxPolicy::aux(c.i(), c.state())+b, c.i(), c.state());
+    ++n_;
+    container_size_ = c.data().size();
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ typename senf::detail::ListBParser_Policy<ElementParser,BytesParser>::size_type
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-size(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ void
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+update(container_type const & c)
     const
 {
-    return n_;
+    if (container_size_ == c.data().size())
+        return;
+    data_iterator i (AuxPolicy::adjust(c.i(), c.state()));
+    data_iterator j (i);
+    for (size_type n (n_); n; --n, std::advance(j,senf::bytes(ElementParser(j,c.state())))) ;
+    aux( std::distance(i,j), c.i(), c.state() );
+    container_size_ = c.data().size();
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ void
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-erase(iterator i, state_type s, iterator p)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::data_iterator
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+setBegin(container_type const & c, iterator_data & d)
+    const
 {
-    size_type b (senf::bytes(ElementParser(p,s)));
-    BytesParser(i,s) -= b;
-    --n_;
-    // The container will be reduced by b bytes directly after this call
-    container_size_ = s->size()-b;
+    return AuxPolicy::adjust(c.i(), c.state());
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ void
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-insert(iterator i, state_type s, iterator p)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::data_iterator
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+setEnd(container_type const & c, iterator_data & d)
+    const
 {
-    BytesParser(i,s) += senf::bytes(ElementParser(p,s));
-    ++n_;
-    container_size_ = s->size();
+    return boost::next(AuxPolicy::adjust(c.i(), c.state()),aux(c.i(),c.state()));
 }
 
-template <class ElementParser, class BytesParser>
+template <class ElementParser, class AuxPolicy>
 prefix_ void
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-init(iterator i, state_type s)
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+setFromPosition(container_type const & c, iterator_data & d, data_iterator p)
+    const
+{}
+
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::data_iterator
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+next(container_type const & c, iterator_data & d)
+    const
 {
-    n_ = 0;
-    container_size_ = s->size();
+    return boost::next( container_type::iterator::get(d).i(),
+                        senf::bytes(ElementParser( container_type::iterator::get(d).i(), 
+                                                   c.state() )) );
 }
 
-template <class ElementParser, class BytesParser>
-prefix_ void
-senf::detail::ListBParser_Policy<ElementParser,BytesParser>::container_policy::
-update(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::data_iterator
+senf::detail::ListBParser_Policy<ElementParser,AuxPolicy>::container_policy::
+raw(container_type const & c, iterator_data const & d)
     const
 {
-    if (container_size_ == s->size())
-        return;
-    iterator j (boost::next(i,BytesParser::fixed_bytes));
-    for (size_type n (n_); n; --n, std::advance(j,ElementParser(j,s).bytes())) ;
-    BytesParser(i,s) = std::distance(i,j) - BytesParser::fixed_bytes;
-    container_size_ = s->size();
+    return container_type::iterator::get(d).i();
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 25f0a04..fdf4a8a 100644 (file)
@@ -64,7 +64,9 @@ namespace senf {
      */
     template <class ElementParser, class BytesParser>
     struct ListBParser {
-        typedef ListParser< detail::ListBParser_Policy<ElementParser,BytesParser> > parser;
+        typedef ListParser< 
+            detail::ListBParser_Policy< ElementParser,
+                                        detail::PrefixAuxParserPolicy<BytesParser> > > parser;
     };
 
     /** \brief Define ListBParser field
@@ -83,7 +85,6 @@ namespace senf {
 #    define SENF_PARSER_LIST_B(name, elt_type, size_type)                                         \
         typedef senf::ListBParser<elt_type, size_type>::parser BOOST_PP_CAT(name, _list_t);       \
         SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _list_t) )
-
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
index 9439ef2..b44e35a 100644 (file)
@@ -27,6 +27,7 @@
 #define IH_ListBParser_ 1
 
 // Custom includes
+#include "ListParser.ih"
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -37,15 +38,17 @@ namespace detail {
         \internal
         \see \ref ListBParser
      */
-    template <class ElementParser, class BytesParser>
+    template <class ElementParser, class AuxPolicy>
     struct ListBParser_Policy
+        : public AuxPolicy
     {
         // This policy needs to work around a serious problem with this type of list: When we change
-        // the size of any (direct or indirect) subelement of the list, This will change will render
-        // the list completely invalid and unparseable since the 'byte' field will now be invalid.
+        // the size of any (direct or indirect) sub-element of the list, this will change will
+        // render the list completely invalid and un-parseable since the 'byte' field will now be
+        // invalid.
         //
         // The solution we apply is to store the *size* (i.e. the number of elements) of the list
-        // when creating the container wrapper. We also maintain this value accross insert/erase
+        // when creating the container wrapper. We also maintain this value across insert/erase
         // statements. Additionally we also safe the complete size of the data container (the vector
         // holding the bytes). Since we only allow packet changes through this container while it
         // exists, any change in the container size must be a change within this list and therefore
@@ -66,60 +69,68 @@ namespace detail {
 
         struct container_policy;
 
-        typedef PacketParserBase::data_iterator iterator;
+        typedef PacketParserBase::data_iterator data_iterator;
         typedef PacketParserBase::state_type state_type;
         typedef PacketParserBase::size_type size_type;
+
         typedef ElementParser element_type;
         typedef ListParser< ListBParser_Policy > parser_type;
         typedef ListParser_Container< container_policy > container_type;
 
-        static const size_type init_bytes = BytesParser::fixed_bytes;
+        static const size_type init_bytes = AuxPolicy::aux_bytes;
 
-        size_type bytes  (iterator i, state_type s) const;
-        size_type size   (iterator i, state_type s) const;
-        void      init   (iterator i, state_type s) const;
+        ListBParser_Policy();
+        template <class Arg> ListBParser_Policy(Arg const & arg);
 
-        /** \brief Internal: ListBParser_Policy's iterator policy
-            \internal
-         */
-        struct iterator_policy
-        {
-            iterator setBegin        (iterator i, state_type s);
-            iterator setEnd          (iterator i, state_type s);
-            void     setFromPosition (iterator i, state_type s, iterator p);
-            iterator next            (iterator i, state_type s);
-            iterator raw             (iterator i, state_type s) const;
-        };
+        size_type bytes  (data_iterator i, state_type s) const;
+        size_type size   (data_iterator i, state_type s) const;
+        void      init   (data_iterator i, state_type s) const;
 
-        /** \brief Internal: ListBParser_Policy's container policy
-            \internal
-         */
         struct container_policy
+            : public AuxPolicy
         {
-            typedef typename ListBParser_Policy<
-                ElementParser,BytesParser>::iterator_policy iterator_policy;
-            typedef typename ListBParser_Policy<
-                ElementParser,BytesParser>::parser_type parser_type;
-            typedef typename ListBParser_Policy<
-                ElementParser,BytesParser>::element_type element_type;
+            typedef PacketParserBase::data_iterator data_iterator;
+            typedef PacketParserBase::state_type state_type;
+            typedef PacketParserBase::size_type size_type;
+
+            typedef ListBParser_Policy<ElementParser, AuxPolicy> parser_policy;
+            typedef typename parser_policy::element_type element_type;
+            typedef typename parser_policy::parser_type parser_type;
+            typedef typename parser_policy::container_type container_type;
+
+            static const size_type init_bytes = parser_policy::init_bytes;
+
+            container_policy(parser_policy const & p);
 
-            static const size_type init_bytes = ListBParser_Policy<
-                ElementParser,BytesParser>::init_bytes;
+            size_type bytes  (data_iterator i, state_type s) const;
+            size_type size   (data_iterator i, state_type s) const;
+            void      init   (data_iterator i, state_type s);
 
-            container_policy(parser_type const & list);
+            void      erase  (container_type & c, data_iterator p);
+            void      insert (container_type & c, data_iterator p);
+            void      update (container_type const & c) const;
 
-            size_type bytes  (iterator i, state_type s) const;
-            size_type size   (iterator i, state_type s) const;
-            void      erase  (iterator i, state_type s, iterator p);
-            void      insert (iterator i, state_type s, iterator p);
-            void      init   (iterator i, state_type s);
-            void      update (iterator i, state_type s) const;
+            struct iterator_data {};
+
+            data_iterator setBegin        (container_type const & c, iterator_data & d) const;
+            data_iterator setEnd          (container_type const & c, iterator_data & d) const;
+            void          setFromPosition (container_type const & c, iterator_data & d,
+                                           data_iterator p) const;
+
+            data_iterator next            (container_type const & c, iterator_data & d) const;
+            data_iterator raw             (container_type const & c, iterator_data const & d) const;
 
             size_type n_;
             mutable size_type container_size_;
         };
     };
 
+    template <class ElementParser, class AuxPolicy>
+    struct ListParserPolicy<ElementParser, AuxPolicy, senf::detail::auxtag::bytes>
+    {
+        typedef ListBParser_Policy<ElementParser, AuxPolicy> type;
+    };
+
 }}
 
 ///////////////////////////////ih.e////////////////////////////////////////
index fcc90f5..0a53ae4 100644 (file)
@@ -62,7 +62,6 @@ BOOST_AUTO_UNIT_TEST(ListBParser)
     BOOST_CHECK_EQUAL( p.size(), 0u );
     BOOST_CHECK_EQUAL( p.bytes(), 2u );
     BOOST_CHECK( p.empty() );
-    BOOST_CHECK( p.begin() == p.end() );
 
     // the mutators are really tested together with the container wrappers since they are based
     // on the container wrapper. Here we only need one call to make the list larger ...
@@ -72,7 +71,6 @@ BOOST_AUTO_UNIT_TEST(ListBParser)
     BOOST_CHECK_EQUAL( p.bytes(), 3u );
     BOOST_CHECK_EQUAL( p.size(), 1u );
     BOOST_CHECK( ! p.empty() );
-    BOOST_CHECK( p.begin() != p.end() );
 }
 
 BOOST_AUTO_UNIT_TEST(ListBParser_container)
@@ -147,6 +145,90 @@ BOOST_AUTO_UNIT_TEST(ListBParser_container)
     }
 }
 
+namespace {
+    
+    struct TestListParser
+        : public senf::PacketParserBase
+    {
+#       include SENF_PARSER()
+
+        SENF_PARSER_PRIVATE_FIELD ( size1 , senf::UInt8Parser );
+        SENF_PARSER_PRIVATE_FIELD ( size2 , senf::UInt8Parser );
+        SENF_PARSER_FIELD         ( dummy , senf::UInt32Parser );
+        SENF_PARSER_LIST          ( list1  , bytes(size1) , VectorParser );
+        SENF_PARSER_LIST          ( list2  , bytes(size2) , VectorParser );
+
+        SENF_PARSER_FINALIZE(TestListParser);
+    };
+
+}
+
+BOOST_AUTO_UNIT_TEST(listBytesMacro)
+{
+    unsigned char data[] = { 0x08,                   // size1
+                             0x09,                   // size2
+                             0x01, 0x02, 0x03, 0x04, // dummy
+                             0x01,                   // list1()[0].size()
+                             0x05, 0x06,             // list1().vec()[0]
+                             0x02,                   // list1()[1].size()
+                             0x07, 0x08,             // list1()[1].vec()[0]
+                             0x09, 0x0A,             // list1()[1].vec()[1]
+                             0x00,                   // list2()[0].size()
+                             0x02,                   // list2()[1].size()
+                             0x0B, 0x0C,             // list2()[1].vec()[0]
+                             0x0D, 0x0E,             // list2()[1].vec()[1]
+                             0x01,                   // list2()[2].size()
+                             0x0F, 0x10 };           // list2()[2].vec()[0]
+    
+    senf::DataPacket p (senf::DataPacket::create(data));
+    TestListParser parser (p.data().begin(), &p.data());
+    
+    BOOST_CHECK_EQUAL( parser.list1().size(), 2u );
+    BOOST_CHECK_EQUAL( parser.list2().size(), 3u );
+    BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
+
+    TestListParser::list2_t::container list2 (parser.list2());
+
+    {
+        TestListParser::list1_t::container list (parser.list1());
+        BOOST_CHECK_EQUAL( list.size(), 2u );
+
+        TestListParser::list1_t::container::iterator i (list.begin());
+        BOOST_CHECK_EQUAL( i->vec().size(), 1u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0506u );
+
+        ++i;
+        BOOST_CHECK_EQUAL( i->vec().size(), 2u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0708u );
+        BOOST_CHECK_EQUAL( i->vec()[1], 0x090Au );
+        
+        ++i;
+        BOOST_CHECK( i == list.end() );
+    }
+
+    {
+        TestListParser::list2_t::container list (parser.list2());
+        BOOST_CHECK_EQUAL( list.size(), 3u );
+
+        TestListParser::list2_t::container::iterator i (list.begin());
+        BOOST_CHECK_EQUAL( i->vec().size(), 0u );
+
+        ++i;
+        BOOST_CHECK_EQUAL( i->vec().size(), 2u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0B0Cu );
+        BOOST_CHECK_EQUAL( i->vec()[1], 0x0D0Eu );
+        
+        ++i;
+        BOOST_CHECK_EQUAL( i->vec().size(), 1u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0F10u );
+        
+        ++i;
+        BOOST_CHECK( i == list.end() );
+    }
+
+}
+
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 225bf52..5b19099 100644 (file)
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
 
-template <class ElementParser, class SizeParser>
+template <class ElementParser, class AuxPolicy>
 prefix_ void
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator_policy::
-setFromPosition(iterator i, state_type s, iterator p)
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::setFromPosition(container_type const & c,
+                                                                           iterator_data & d,
+                                                                           data_iterator p)
+    const
 {
-    l_ = i;
-    if (p == data(s).end()) {
-        n_ = 0;
+    if (p == c.data().end()) {
+        d.n_ = 0;
         return;
     }
-    n_ = SizeParser(i,s);
-    iterator j (boost::next(i,SizeParser::fixed_bytes));
-    for (; n_; --n_, j += ElementParser(j,s).bytes())
+    d.n_ = this->aux(c.i(),c.state());
+    data_iterator j (this->adjust(c.i(),c.state()));
+    for (; d.n_; --d.n_, j += ElementParser(j,c.state()).bytes())
         if (j==p)
             return;
     SENF_ASSERT( false );
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ typename senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator_policy::raw(iterator i,
-                                                                                 state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::data_iterator
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::raw(container_type const & c,
+                                                               iterator_data const & d)
     const
 {
-    if (i != data(s).end())
-        return i;
-    size_type n (SizeParser(l_,s));
-    iterator j (boost::next(l_,SizeParser::fixed_bytes));
+    if (container_type::iterator::get(d).i() != c.data().end())
+        return container_type::iterator::get(d).i();
+    size_type n (this->aux(c.i(),c.state()));
+    data_iterator j (this->adjust(c.i(),c.state()));
     for (; n; --n)
-        j += ElementParser(j,s).bytes();
+        j += ElementParser(j,c.state()).bytes();
     return j;
 }
 
index e3cc7b7..ca46454 100644 (file)
 #define prefix_ inline
 ///////////////////////////////cti.p///////////////////////////////////////
 
-template <class ElementParser, class SizeParser>
-prefix_ typename senf::detail::ListNParser_Policy<ElementParser,SizeParser>::size_type
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::bytes(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::ListNParser_Policy()
+{}
+
+template <class ElementParser, class AuxPolicy>
+template <class Arg>
+prefix_
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::ListNParser_Policy(Arg const & aux)
+    : AuxPolicy (aux)
+{}
+
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::size_type
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::bytes(data_iterator i, state_type s)
     const
 {
-    return std::distance(i,parser_type(i,s).end().raw());
+    container_type c (parser_type(*this, i, s));
+    return std::distance(i,c.end().raw());
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ typename senf::detail::ListNParser_Policy<ElementParser,SizeParser>::size_type
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::size(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::size_type
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::size(data_iterator i, state_type s)
     const
 {
-    return SizeParser(i,s);
+    return AuxPolicy::aux(i,s);
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ void senf::detail::ListNParser_Policy<ElementParser,SizeParser>::init(iterator i,
-                                                                              state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::init(data_iterator i,
+                                                                             state_type s)
     const
-{}
+{
+    AuxPolicy::aux(0,i,s);
+}
 
-template <class ElementParser, class SizeParser>
-prefix_ void senf::detail::ListNParser_Policy<ElementParser,SizeParser>::erase(iterator i,
-                                                                               state_type s,
-                                                                               iterator p)
+template <class ElementParser, class AuxPolicy>
+prefix_ void
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::erase(container_type & c,
+                                                                 data_iterator p)
     const
 {
-    --SizeParser(i,s);
+    this->aux(this->aux(c.i(),c.state())-1,c.i(),c.state());
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ void senf::detail::ListNParser_Policy<ElementParser,SizeParser>::insert(iterator i,
-                                                                                state_type s,
-                                                                                iterator p)
+template <class ElementParser, class AuxPolicy>
+prefix_ void
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::insert(container_type & c,
+                                                                  data_iterator p)
     const
 {
-    ++SizeParser(i,s);
+    this->aux(this->aux(c.i(),c.state())+1,c.i(),c.state());
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ void senf::detail::ListNParser_Policy<ElementParser,SizeParser>::update(iterator i,
-                                                                                state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ void
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::update(container_type const & c)
     const
 {}
 
-template <class ElementParser, class SizeParser>
-prefix_ typename senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator_policy::
-setBegin(iterator i, state_type s)
-{
-    l_ = i;
-    n_ = SizeParser(i,s);
-    return n_ ? boost::next(i,SizeParser::fixed_bytes) : data(s).end();
-}
-
-template <class ElementParser, class SizeParser>
-prefix_ typename senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator_policy::
-setEnd(iterator i, state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::data_iterator
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::setBegin(container_type const & c,
+                                                                    iterator_data & d)
+    const
 {
-    l_ = i;
-    n_ = 0;
-    return data(s).end();
+    d.n_ = this->aux(c.i(),c.state());
+    return d.n_ ? this->adjust(c.i(),c.state()) : c.data().end();
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ typename senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::iterator_policy::next(iterator i,
-                                                                                  state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::data_iterator
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::setEnd(container_type const & c,
+                                                                  iterator_data & d)
+    const
 {
-    --n_;
-    return n_ ? boost::next(i,senf::bytes(ElementParser(i,s))) : data(s).end();
+    d.n_ = 0;
+    return c.data().end();
 }
 
-template <class ElementParser, class SizeParser>
-prefix_ senf::PacketData &
-senf::detail::ListNParser_Policy<ElementParser,SizeParser>::data(state_type s)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::data_iterator
+senf::detail::ListNParser_Policy<ElementParser,AuxPolicy>::next(container_type const & c,
+                                                                iterator_data & d)
+    const
 {
-    return *s;
+    --d.n_;
+    return d.n_ ? boost::next( container_type::iterator::get(d).i(),
+                               senf::bytes(* container_type::iterator::get(d)) )
+        : c.data().end();
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 2cb4292..08cf568 100644 (file)
 
 // Custom includes
 #include "ListParser.hh"
+#include "AuxParser.hh"
 
 //#include "ListNParser.mpp"
+#include "ListNParser.ih"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
 
-    namespace detail { template <class ElementParser, class SizeParser>
-                       class ListNParser_Policy; }
-
     /** \brief List parser with size-field giving number of list elements
 
         This parser will parse a list which size is giving by a preceding field containing the
@@ -53,7 +52,9 @@ namespace senf {
      */
     template <class ElementParser, class SizeParser>
     struct ListNParser {
-        typedef ListParser< detail::ListNParser_Policy<ElementParser,SizeParser> > parser;
+        typedef ListParser< detail::ListNParser_Policy<
+            ElementParser,
+            detail::PrefixAuxParserPolicy<SizeParser> > > parser;
     };
 
     /** \brief Define ListNParser field
@@ -71,7 +72,6 @@ namespace senf {
 #    define SENF_PARSER_LIST_N(name, elt_type, size_type)                                         \
         typedef senf::ListNParser<elt_type, size_type>::parser BOOST_PP_CAT(name, _list_t);       \
         SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _list_t) )
-
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
index 51be7c5..ba39b52 100644 (file)
@@ -27,6 +27,7 @@
 #define IH_ListNParser_ 1
 
 // Custom includes
+#include "ListParser.ih"
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -37,41 +38,52 @@ namespace detail {
         \internal
         \see \ref ListNParser
      */
-    template <class ElementParser, class SizeParser>
+    template <class ElementParser, class AuxPolicy>
     struct ListNParser_Policy
+        : public AuxPolicy
     {
-        typedef PacketParserBase::data_iterator iterator;
+        typedef PacketParserBase::data_iterator data_iterator;
         typedef PacketParserBase::state_type state_type;
         typedef PacketParserBase::size_type size_type;
         typedef ElementParser element_type;
         typedef ListParser< ListNParser_Policy > parser_type;
         typedef ListParser_Container< ListNParser_Policy > container_type;
 
-        static const size_type init_bytes = SizeParser::fixed_bytes;
-
-        size_type bytes  (iterator i, state_type s) const;
-        size_type size   (iterator i, state_type s) const;
-        void      init   (iterator i, state_type s) const;
-        void      erase  (iterator i, state_type s, iterator p) const;
-        void      insert (iterator i, state_type s, iterator p) const;
-        void      update (iterator i, state_type s) const;
-
-        /** \brief Iternal: ListNParser_Policy's iterator policy
-            \internal
-         */
-        struct iterator_policy
-        {
-            iterator setBegin        (iterator i, state_type s);
-            iterator setEnd          (iterator i, state_type s);
-            void     setFromPosition (iterator i, state_type s, iterator p);
-            iterator next            (iterator i, state_type s);
-            iterator raw             (iterator i, state_type s) const;
+        static const size_type init_bytes = AuxPolicy::aux_bytes;
 
+        ListNParser_Policy();
+        template <class Arg> ListNParser_Policy(Arg const & aux);
+
+        size_type bytes  (data_iterator i, state_type s) const;
+        size_type size   (data_iterator i, state_type s) const;
+        void      init   (data_iterator i, state_type s) const;
+        
+        void      erase  (container_type & c, data_iterator p) const;
+        void      insert (container_type & c, data_iterator p) const;
+        void      update (container_type const & c) const;
+
+        struct iterator_data {
             size_type n_;
-            iterator l_;
         };
 
-        static PacketData & data(state_type s);
+        data_iterator setBegin        (container_type const & c, iterator_data & d) const;
+        data_iterator setEnd          (container_type const & c, iterator_data & d) const;
+        void          setFromPosition (container_type const & c, iterator_data & d, data_iterator p) const;
+        data_iterator next            (container_type const & c, iterator_data & d) const;
+        data_iterator raw             (container_type const & c, iterator_data const & d) const;
+    };
+
+    template <class ElementParser, class AuxPolicy>
+    struct ListParserPolicy<ElementParser, AuxPolicy, senf::detail::auxtag::none>
+    {
+        typedef ListNParser_Policy<ElementParser, AuxPolicy> type;
+    };
+
+    template <class ElementParser, class AuxPolicy, class Transform>
+    struct ListParserPolicy<ElementParser, AuxPolicy, senf::detail::auxtag::transform<Transform> >
+    {
+        typedef ListNParser_Policy< ElementParser,
+                                    TransformAuxParserPolicy<AuxPolicy, Transform> > type;
     };
 
 }}
index f4d5e38..ebfee8a 100644 (file)
@@ -51,6 +51,37 @@ namespace {
     };
 }
 
+BOOST_AUTO_UNIT_TEST(ListNParser_container)
+{
+    typedef senf::ListNParser<MyVec,senf::UInt16Parser>::parser MyListNParser;
+    
+    VoidPacket vp (VoidPacket::create(MyListNParser::init_bytes));
+    MyListNParser(vp.data().begin(),&vp.data()).init();
+
+    {
+        MyListNParser::container c (MyListNParser(vp.data().begin(),&vp.data()));
+
+        c.push_back_space(2u);
+        BOOST_CHECK_EQUAL( std::distance(c.begin(), c.end()), 2 );
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), c.begin().raw()), 2 );
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), c.front().vec().begin().raw()), 3 );
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), c.front().vec().end().raw()), 3 );
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), c.back().vec().begin().raw()), 4 );
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), c.back().vec().end().raw()), 4 );
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), c.end().raw()), 4 );
+        BOOST_CHECK_EQUAL( c.bytes(), 4u );
+
+        MyListNParser::container::iterator i (c.begin());
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), i->i()), 2 );
+        BOOST_CHECK( i != c.end() );
+        ++i;
+        BOOST_CHECK_EQUAL( std::distance(c.data().begin(), i->i()), 3 );
+        BOOST_CHECK( i != c.end() );
+        ++i;
+        BOOST_CHECK( i == c.end() );
+    }
+}
+
 BOOST_AUTO_UNIT_TEST(ListNParser)
 {
     typedef senf::ListNParser<MyVec,senf::UInt16Parser>::parser MyListNParser;
@@ -63,7 +94,6 @@ BOOST_AUTO_UNIT_TEST(ListNParser)
         BOOST_CHECK_EQUAL( p.size(), 0u );
         BOOST_CHECK_EQUAL( p.bytes(), 2u );
         BOOST_CHECK( p.empty() );
-        BOOST_CHECK( p.begin() == p.end() );
     }
 
     {
@@ -85,11 +115,13 @@ BOOST_AUTO_UNIT_TEST(ListNParser)
 
         p.front().vec().push_back(0x2345u);
         BOOST_CHECK_EQUAL( p.front().vec().back(), 0x2345u );
+        BOOST_CHECK_EQUAL( p.front().vec().size(), 2u );
         BOOST_CHECK_EQUAL( p.bytes(), 7u );
 
         p.push_back_space();
         BOOST_CHECK_EQUAL( p.size(), 2u );
         BOOST_CHECK_EQUAL( p.bytes(), 8u );
+        BOOST_CHECK_EQUAL( p.back().vec().size(), 0u );
         
         p.back().vec().push_front(0x0123u);
         BOOST_CHECK_EQUAL( p.front().vec().size(), 2u );
@@ -108,17 +140,95 @@ BOOST_AUTO_UNIT_TEST(ListNParser)
     }
 }
 
-BOOST_AUTO_UNIT_TEST(ListNParser_container)
-{
-    typedef senf::ListNParser<MyVec,senf::UInt16Parser>::parser MyListNParser;
+namespace {
     
-    VoidPacket vp (VoidPacket::create(MyListNParser::init_bytes));
+    struct TestTransform
+    {
+        typedef unsigned value_type;
+        static unsigned get(unsigned v) { return v/2; }
+        static unsigned set(unsigned v) { return 2*v; }
+    };
 
-    MyListNParser(vp.data().begin(),&vp.data()).init();
+    struct TestListParser
+        : public senf::PacketParserBase
+    {
+#       include SENF_PARSER()
+
+        SENF_PARSER_PRIVATE_FIELD ( size1 , senf::UInt8Parser );
+        SENF_PARSER_PRIVATE_FIELD ( size2 , senf::UInt8Parser );
+        SENF_PARSER_FIELD         ( dummy , senf::UInt32Parser );
+        SENF_PARSER_LIST          ( list1  , transform(TestTransform, size1) , MyVec );
+        SENF_PARSER_LIST          ( list2  , size2 , MyVec );
+
+        SENF_PARSER_FINALIZE(TestListParser);
+    };
 
-    
 }
 
+BOOST_AUTO_UNIT_TEST(listMacro)
+{
+    unsigned char data[] = { 0x04,                   // size1
+                             0x03,                   // size2
+                             0x01, 0x02, 0x03, 0x04, // dummy
+                             0x01,                   // list1()[0].size()
+                             0x05, 0x06,             // list1().vec()[0]
+                             0x02,                   // list1()[1].size()
+                             0x07, 0x08,             // list1()[1].vec()[0]
+                             0x09, 0x0A,             // list1()[1].vec()[1]
+                             0x00,                   // list2()[0].size()
+                             0x02,                   // list2()[1].size()
+                             0x0B, 0x0C,             // list2()[1].vec()[0]
+                             0x0D, 0x0E,             // list2()[1].vec()[1]
+                             0x01,                   // list2()[2].size()
+                             0x0F, 0x10 };           // list2()[2].vec()[0]
+    
+    senf::DataPacket p (senf::DataPacket::create(data));
+    TestListParser parser (p.data().begin(), &p.data());
+    
+    BOOST_CHECK_EQUAL( parser.list1().size(), 2u );
+    BOOST_CHECK_EQUAL( parser.list2().size(), 3u );
+    BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
+
+    TestListParser::list2_t::container list2 (parser.list2());
+
+    {
+        TestListParser::list1_t::container list (parser.list1());
+        BOOST_CHECK_EQUAL( list.size(), 2u );
+
+        TestListParser::list1_t::container::iterator i (list.begin());
+        BOOST_CHECK_EQUAL( i->vec().size(), 1u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0506u );
+
+        ++i;
+        BOOST_CHECK_EQUAL( i->vec().size(), 2u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0708u );
+        BOOST_CHECK_EQUAL( i->vec()[1], 0x090Au );
+        
+        ++i;
+        BOOST_CHECK( i == list.end() );
+    }
+
+    {
+        TestListParser::list2_t::container list (parser.list2());
+        BOOST_CHECK_EQUAL( list.size(), 3u );
+
+        TestListParser::list2_t::container::iterator i (list.begin());
+        BOOST_CHECK_EQUAL( i->vec().size(), 0u );
+
+        ++i;
+        BOOST_CHECK_EQUAL( i->vec().size(), 2u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0B0Cu );
+        BOOST_CHECK_EQUAL( i->vec()[1], 0x0D0Eu );
+        
+        ++i;
+        BOOST_CHECK_EQUAL( i->vec().size(), 1u );
+        BOOST_CHECK_EQUAL( i->vec()[0], 0x0F10u );
+        
+        ++i;
+        BOOST_CHECK( i == list.end() );
+    }
+
+}
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
index 39915c2..19fccdb 100644 (file)
@@ -39,8 +39,9 @@ prefix_ void senf::ListParser<ListPolicy>::init()
     const
 {
     ListPolicy::init(i(),state());
-    iterator i (begin());
-    iterator const e (end());
+    container c (*this);
+    typename container::iterator i (c.begin());
+    typename container::iterator const e (c.end());
     for(; i!=e; ++i)
         i->init();
 }
@@ -51,8 +52,9 @@ senf::ListParser<ListPolicy>::back()
     const
 {
     SENF_ASSERT( ! empty() );
-    iterator i (begin()), j;
-    iterator const e (end());
+    container c(*this);
+    typename container::iterator i (c.begin()), j;
+    typename container::iterator const e (c.end());
     for (j=i; i!=e; j=i, ++i) ;
     return *j;
 }
@@ -75,13 +77,12 @@ senf::ListParser_Container<ListPolicy>::back()
 template <class ListPolicy>
 prefix_ void senf::ListParser_Container<ListPolicy>::shift(iterator pos, size_type n)
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     safe_data_iterator sp (data(),pos.raw());
-    safe_data_iterator si (data(),i());
     for (; n>0; --n) {
         data().insert(sp,senf::init_bytes<value_type>::value,0);
         value_type(sp,state()).init();
-        ListPolicy::insert(si,state(),sp);
+        ListPolicy::insert(*this,sp);
     }
 }
 
@@ -91,14 +92,13 @@ prefix_ void senf::ListParser_Container<ListPolicy>::insert(iterator pos,
                                                             size_type n,
                                                             Value const & t)
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     safe_data_iterator sp (data(),pos.raw());
-    safe_data_iterator si (data(),i());
     for (; n>0; --n) {
         data().insert(sp,senf::init_bytes<value_type>::value,0);
         value_type(sp,state()).init();
         value_type(sp,state()) << t;
-        ListPolicy::insert(si,state(),sp);
+        ListPolicy::insert(*this,sp);
     }
 }
 
@@ -109,14 +109,13 @@ prefix_ void senf::ListParser_Container<ListPolicy>::
 insert(iterator pos, ForwardIterator f, ForwardIterator l,
        typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type *)
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     safe_data_iterator sp (data(),pos.raw());
-    safe_data_iterator si (data(),i());
     for (; f!=l; ++f) {
         data().insert(sp,senf::init_bytes<value_type>::value,0);
         value_type(sp,state()).init();
         value_type(sp,state()) << *f;
-        ListPolicy::insert(si,state(),sp);
+        ListPolicy::insert(*this,sp);
         sp += senf::bytes(value_type(sp,state()));
     }
 }
@@ -132,11 +131,10 @@ template <class ListPolicy>
 prefix_ void senf::ListParser_Container<ListPolicy>::erase(iterator pos,
                                                            size_type n)
 {
-    ListPolicy::update(i(),state());
-    safe_data_iterator si (data(),i());
+    ListPolicy::update(*this);
     safe_data_iterator sp (data(),pos.raw());
     for (; n>0; --n) {
-        ListPolicy::erase(si,state(),sp);
+        ListPolicy::erase(*this,sp);
         data().erase(sp,boost::next(sp,senf::bytes(value_type(sp,state()))));
     }
 }
index 919b913..9847a65 100644 (file)
@@ -68,23 +68,8 @@ template <class ListPolicy>
 prefix_ bool senf::ListParser<ListPolicy>::empty()
     const
 {
-    return begin() == end();
-}
-
-template <class ListPolicy>
-prefix_ typename senf::ListParser<ListPolicy>::iterator
-senf::ListParser<ListPolicy>::begin()
-    const
-{
-    return iterator(i(),state(),iterator::Begin);
-}
-
-template <class ListPolicy>
-prefix_ typename senf::ListParser<ListPolicy>::iterator
-senf::ListParser<ListPolicy>::end()
-    const
-{
-    return iterator(i(),state(),iterator::End);
+    container c (*this);
+    return c.empty();
 }
 
 template <class ListPolicy>
@@ -93,7 +78,8 @@ senf::ListParser<ListPolicy>::front()
     const
 {
     SENF_ASSERT( ! empty() );
-    return *begin();
+    container c(*this);
+    return *(c.begin());
 }
 
 template <class ListPolicy>
@@ -147,62 +133,83 @@ prefix_ void senf::ListParser<ListPolicy>::resize(size_type n, Value value)
     c.resize(n,value);
 }
 
+template <class ListPolicy>
+prefix_ typename senf::ListParser<ListPolicy> &
+senf::ListParser<ListPolicy>::get(ListPolicy & p)
+{
+    return static_cast<ListParser &>(p);
+}
+
+template <class ListPolicy>
+prefix_ typename senf::ListParser<ListPolicy> const &
+senf::ListParser<ListPolicy>::get(ListPolicy const & p)
+{
+    return static_cast<ListParser const &>(p);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>
 
-template <class ElementParser, class IteratorPolicy>
-prefix_ senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::ListParser_Iterator()
-{}
-
-template <class ElementParser, class IteratorPolicy>
-prefix_ senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::
-ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, Begin_t)
-    : IteratorPolicy(), i_(IteratorPolicy::setBegin(i,s)), s_(s)
+template <class Container>
+prefix_ senf::detail::ListParser_Iterator<Container>::ListParser_Iterator()
 {}
 
-template <class ElementParser, class IteratorPolicy>
-prefix_ senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::
-ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, End_t)
-    : IteratorPolicy(), i_(IteratorPolicy::setEnd(i,s)), s_(s)
+template <class Container>
+prefix_ senf::detail::ListParser_Iterator<Container>::ListParser_Iterator(Container const & c)
+    : c_ (&c)
 {}
 
-template <class ElementParser, class IteratorPolicy>
-prefix_ senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::
-ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s,
-                    PacketParserBase::data_iterator p)
-    : IteratorPolicy(), i_(p), s_(s)
+template <class Container>
+prefix_ senf::PacketParserBase::data_iterator
+senf::detail::ListParser_Iterator<Container>::raw()
+    const
 {
-    IteratorPolicy::setFromPosition(i,s,p);
+    return c_->Container::policy::raw(*c_, *this);
 }
 
-template <class ElementParser, class IteratorPolicy>
+template <class Container>
 prefix_ senf::PacketParserBase::data_iterator
-senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::raw()
+senf::detail::ListParser_Iterator<Container>::i()
     const
 {
-    return IteratorPolicy::raw(i_,s_);
+    return i_;
+}
+
+template <class Container>
+prefix_ typename senf::detail::ListParser_Iterator<Container> &
+senf::detail::ListParser_Iterator<Container>::get(typename Container::policy::iterator_data & d)
+{
+    return static_cast<ListParser_Iterator &>(d);
+}
+
+template <class Container>
+prefix_ typename senf::detail::ListParser_Iterator<Container> const &
+senf::detail::ListParser_Iterator<Container>::
+get(typename Container::policy::iterator_data const & d)
+{
+    return static_cast<ListParser_Iterator const &>(d);
 }
 
-template <class ElementParser, class IteratorPolicy>
-prefix_ ElementParser
-senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::dereference()
+template <class Container>
+prefix_ typename senf::detail::ListParser_Iterator<Container>::value_type
+senf::detail::ListParser_Iterator<Container>::dereference()
     const
 {
-    return ElementParser(i_,s_);
+    return value_type(i_,c_->state());
 }
 
-template <class ElementParser, class IteratorPolicy>
-prefix_ bool senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::
-equal(ListParser_Iterator const & other)
+template <class Container>
+prefix_ bool
+senf::detail::ListParser_Iterator<Container>::equal(ListParser_Iterator const & other)
     const
 {
     return i_ == other.i_;
 }
 
-template <class ElementParser, class IteratorPolicy>
-prefix_ void senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::increment()
+template <class Container>
+prefix_ void senf::detail::ListParser_Iterator<Container>::increment()
 {
-    i_ = IteratorPolicy::next(i_,s_);
+    i_ = c_->Container::policy::next(*c_, *this);
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -213,13 +220,14 @@ prefix_ void senf::detail::ListParser_Iterator<ElementParser,IteratorPolicy>::in
 template <class ListPolicy>
 prefix_ senf::ListParser_Container<ListPolicy>::
 ListParser_Container(parser_type const & list)
-    : ListPolicy(list), state_(list.state()), i_(std::distance(data().begin(),list.i()))
+    : ListPolicy(static_cast<typename parser_type::policy const &>(list)),
+      state_(list.state()), i_(std::distance(data().begin(),list.i()))
 {}
 
 template <class ListPolicy>
 prefix_ senf::ListParser_Container<ListPolicy>::~ListParser_Container()
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
 }
 
 // Accessors
@@ -229,7 +237,7 @@ prefix_ typename senf::ListParser_Container<ListPolicy>::size_type
 senf::ListParser_Container<ListPolicy>::size()
     const
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     return ListPolicy::size(i(),state());
 }
 
@@ -237,7 +245,7 @@ template <class ListPolicy>
 prefix_ bool senf::ListParser_Container<ListPolicy>::empty()
     const
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     return begin() == end();
 }
 
@@ -246,8 +254,10 @@ prefix_ typename senf::ListParser_Container<ListPolicy>::iterator
 senf::ListParser_Container<ListPolicy>::begin()
     const
 {
-    ListPolicy::update(i(),state());
-    return iterator(i(),state(),iterator::Begin);
+    ListPolicy::update(*this);
+    iterator i (*this);
+    i.i_ = ListPolicy::setBegin(*this, i);
+    return i;
 }
 
 template <class ListPolicy>
@@ -255,8 +265,10 @@ prefix_ typename senf::ListParser_Container<ListPolicy>::iterator
 senf::ListParser_Container<ListPolicy>::end()
     const
 {
-    ListPolicy::update(i(),state());
-    return iterator(i(),state(),iterator::End);
+    ListPolicy::update(*this);
+    iterator i (*this);
+    i.i_ = ListPolicy::setEnd(*this, i);
+    return i;
 }
 
 template <class ListPolicy>
@@ -319,7 +331,7 @@ prefix_ typename senf::ListParser_Container<ListPolicy>::parser_type
 senf::ListParser_Container<ListPolicy>::parser()
     const
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     return parser_type(i(),state());
 }
 
@@ -351,7 +363,7 @@ prefix_ typename senf::ListParser_Container<ListPolicy>::size_type
 senf::ListParser_Container<ListPolicy>::bytes()
     const
 {
-    ListPolicy::update(i(),state());
+    ListPolicy::update(*this);
     return ListPolicy::bytes(i(),state());
 }
 
index fd20833..d42310c 100644 (file)
@@ -48,17 +48,18 @@ namespace senf {
             void      init   (data_iterator i, state_type s) const;
 
             // Members needed only in the container policy
-            void      erase  (data_iterator i, state_type s, iterator p) const;
-            void      insert (data_iterator i, state_type s, iterator p) const;
-
-            struct iterator_policy
-            {
-                iterator setBegin        (data_iterator i, state_type s);
-                iterator setEnd          (data_iterator i, state_type s);
-                void     setFromPosition (data_iterator i, state_type s, iterator p);
-                iterator next            (data_iterator i, state_type s);
-                iterator raw             (data_iterator i, state_type s) const;
-            };
+            void      erase  (container_type & c, data_iterator p) const;
+            void      insert (container_type & c, data_iterator p) const;
+            void      update (container_type const & c, data_iterator p) const;
+
+            // Members needed in the container policy for iteration
+            struct iterator_data {};
+
+            data_iterator setBegin        (container_type const & c, iterator_data & d) const;
+            data_iterator setEnd          (container_type const & c, iterator_data & d) const;
+            void          setFromPosition (container_type const & c, iterator_data & d, iterator p) const;
+            data_iterator next            (container_type const & c, iterator_data & d) const;
+            data_iterator raw             (container_type const & c, iterator_data const & d) const;
         };
         \endcode
 
@@ -79,13 +80,13 @@ namespace senf {
         typedef PacketParserBase::state_type state_type;
         typedef PacketParserBase::size_type size_type;
 
-        typedef void element_type;      ///< Type of list elements
+        typedef unspecified element_type; ///< Type of list elements
                                         /**< This is the parser used to parse the list elements. */
-        typedef void parser_type;       ///< List parser type
+        typedef unspecified parser_type; ///< List parser type
                                         /**< parser_type is the list parser used to parse a list of
                                              this type,
                                              e.g. <tt>senf::Parse_List<ExampleListPolicy></tt>. */
-        typedef void container_type;    ///< Type of container wrapper
+        typedef unspecified container_type; ///< Type of container wrapper
                                         /**< This is the container wrapper of the list, e.g.
                                              <tt>Parse_List_Container<ExampleListPolicy></tt>. The
                                              container may however use a \e different policy, as
@@ -123,14 +124,7 @@ namespace senf {
                                         /**< This is called after an element has been inserted at p
                                              into the List (i,s) to update the meta-data. */
 
-        /** \brief Example of a list iterator policy. ONLY FOR EXPOSITION.
-
-            \see \ref ExampleListPolicy \n
-                 \ref ListParser
-         */
-        struct iterator_policy
-        {
-            iterator setBegin(iterator i, state_type s); ///< Initialize iterator to begin()
+        iterator setBegin(iterator i, state_type s); ///< Initialize iterator to begin()
                                         /**< Initialize the policy from the given List (i,s). Set
                                              the iterator to the beginning iterator. Return
                                              data_iterator to the first element.
@@ -138,42 +132,35 @@ namespace senf {
                                              \warning if the list is empty, the returned iterator
                                              \e must be the same as the one returned by setEnd. */
 
-            iterator setEnd(iterator i, state_type s); ///< Initialize iterator to end()
+        iterator setEnd(iterator i, state_type s); ///< Initialize iterator to end()
                                         /**< Initialize the policy from the given List (i,s). Set
                                              the iterator to the end iterator. Return data_iterator
                                              used to mark the end of the range. This may be a
                                              special sentinel value (e.g. data().end()) if
                                              needed. */
 
-            void setFromPosition(iterator i, state_type s, iterator p);
+        void setFromPosition(iterator i, state_type s, iterator p);
                                         ///< Initialize iterator from the given raw position
                                         /**< Set the iterator to the Element at raw position p. This
                                              operation can potentially be very inefficient if the
                                              list needs to be traversed from the beginning until the
                                              iterator is found. */
 
-            iterator next(iterator i, state_type s); ///< Advance to next element
+        iterator next(iterator i, state_type s); ///< Advance to next element
                                         /**< given an iterator to an element, go to the next
                                              element. */
 
-            iterator raw(iterator i, state_type s); ///< Return raw position of element
+        iterator raw(iterator i, state_type s); ///< Return raw position of element
                                         /**< Given the iterator state (i,s), return the raw iterator
                                              to the datum. This will be i in almost all cases EXCEPT
                                              if a special sentinel value is used as end() value. In
                                              this case, this member must return the real position
                                              after the last element. */
-        };
 
-        /** \brief Example of a list container policy. ONLY FOR EXPOSITION
+        void update(iterator i, state_type s); ///< Called before every container access
 
-            \see \ref ExampleListPolicy \n
-                 \ref ListParser
-         */
-        struct container_policy
-        {
-            void init(iterator i, state_type s); ///< Initialize new container
-            void update(iterator i, state_type s); ///< Called before every container access
-        };
+        struct iterator_data
+        {};
     };
 
 }
index ae3d9ae..c101b82 100644 (file)
@@ -35,8 +35,7 @@
 
 namespace senf {
 
-    namespace detail { template <class ElementParser, class IteratorPolicy>
-                       class ListParser_Iterator; }
+    namespace detail { template <class Container> class ListParser_Iterator; }
 
     template <class ListPolicy>
     class ListParser_Container;
@@ -65,6 +64,8 @@ namespace senf {
           private ListPolicy
     {
     public:
+        typedef ListPolicy policy;
+
         ListParser(data_iterator i, state_type s);
         ListParser(ListPolicy policy, data_iterator i, state_type s);
                                         ///< Additional policy specific constructor
@@ -80,17 +81,11 @@ namespace senf {
         // Container interface
 
         typedef typename ListPolicy::element_type value_type;
-        typedef detail::ListParser_Iterator<
-            value_type, typename ListPolicy::iterator_policy > iterator;
-        typedef iterator const_iterator;
         typedef typename ListPolicy::container_type container;
 
         size_type size() const;
         bool empty() const;
 
-        iterator begin() const;
-        iterator end() const;
-
         value_type front() const;
         value_type back() const;
 
@@ -101,6 +96,9 @@ namespace senf {
                                void resize           (size_type n) const;
         template <class Value> void resize           (size_type n, Value value) const;
 
+        static ListParser & get(ListPolicy & p);
+        static ListParser const & get(ListPolicy const & p);
+
     private:
         template <class Policy> friend class ListParser_Container;
     };
@@ -131,13 +129,13 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
+        typedef ListPolicy policy;
         typedef typename ListPolicy::parser_type parser_type;
         typedef PacketParserBase::data_iterator data_iterator;
         typedef PacketParserBase::size_type size_type;
         typedef PacketParserBase::difference_type difference_type;
         typedef typename ListPolicy::element_type value_type;
-        typedef detail::ListParser_Iterator<
-            value_type, typename ListPolicy::iterator_policy> iterator;
+        typedef detail::ListParser_Iterator<ListParser_Container> iterator;
         typedef iterator const_iterator;
         typedef PacketParserBase::state_type state_type;
 
@@ -213,10 +211,17 @@ namespace senf {
         ///@}
 
     private:
+        friend class detail::ListParser_Iterator<ListParser_Container>;
+
         state_type state_;
         size_type i_;
     };
 
+#    define SENF_PARSER_LIST(name, size, elt_type) \
+         SENF_PARSER_LIST_I(public, name, size, elt_type)
+
+#    define SENF_PARSER_PRIVATE_LIST(name, size, elt_type) \
+        SENF_PARSER_LIST_I(private, name, size, elt_type)
 
 }
 
index e6c7d30..e97d2fa 100644 (file)
@@ -38,39 +38,59 @@ namespace detail {
 
         \internal
      */
-    template <class ElementParser, class IteratorPolicy>
+    template <class Container>
     class ListParser_Iterator
-        : public boost::iterator_facade< ListParser_Iterator<ElementParser,IteratorPolicy>,
-                                         ElementParser,
+        : public boost::iterator_facade< ListParser_Iterator<Container>,
+                                         typename Container::value_type,
                                          boost::forward_traversal_tag,
-                                         ElementParser >,
-          private IteratorPolicy
+                                         typename Container::value_type >,
+          private Container::policy::iterator_data
     {
     public:
-        enum Begin_t { Begin };
-        enum End_t { End };
+        typedef typename Container::value_type value_type;
 
         ListParser_Iterator();
-        ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, 
-                            Begin_t);
-        ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, 
-                            End_t);
-        ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, 
-                            PacketParserBase::data_iterator p);
+        explicit ListParser_Iterator(Container const & c);
 
         PacketParserBase::data_iterator raw() const;
+        PacketParserBase::data_iterator i() const;
         
+        static ListParser_Iterator & get(typename Container::policy::iterator_data & d);
+        static ListParser_Iterator const & get(typename Container::policy::iterator_data const & d);
+
     private:
         friend class boost::iterator_core_access;
+        template <class P> friend class ListParser_Container;
         
-        ElementParser dereference() const;
+        value_type dereference() const;
         bool equal(ListParser_Iterator const & other) const;
         void increment();
 
         PacketParserBase::data_iterator i_;
-        PacketParserBase::state_type s_;
+        Container const * c_;
+    };
+
+    template <class ElementParser, class AuxPolicy, class AuxTag>
+    struct ListParserPolicy
+    {};
+
+    template <class ElementParser>
+    struct ListParserTraits
+    {
+        template <class AuxPolicy, class AuxTag>
+        struct parser {
+            typedef senf::ListParser<
+                typename ListParserPolicy<ElementParser, AuxPolicy, AuxTag>::type > type;
+        };
     };
 
+#   define SENF_PARSER_LIST_I(access, name, size, elt_type)                                       \
+        SENF_PARSER_REQUIRE_VAR(list)                                                             \
+            SENF_PARSER_COLLECTION_I( access,                                                     \
+                                      name,                                                       \
+                                      size,                                                       \
+                                      senf::detail::ListParserTraits<elt_type> )
+
 }}
 
 ///////////////////////////////ih.e////////////////////////////////////////
index d936097..18f58e5 100644 (file)
@@ -26,6 +26,9 @@
 #
 # // 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 "../Utils/mpl.hh"
 #
 # ////////////////////////////////ih.p///////////////////////////////////////
 # ///////////////////////////////////////////////////////////////////////////
 # // SENF_PARSER_COLLECTION_I
 #
-  namespace senf { namespace detail { namespace auxtag { struct none {}; } } }
+  namespace senf { namespace detail { namespace auxtag { 
+      struct none {}; } } }
+  namespace senf { namespace detail { namespace auxtag { 
+      struct bytes {}; } } }
+  namespace senf { namespace detail { namespace auxtag { 
+      template <class T> 
+      struct transform {}; } } }
+#
+# define SENF_PARSER_COLLECTION_TAG_GOBBLE__bytes(x)
+# define SENF_PARSER_COLLECTION_TAG__bytes(x) senf::detail::auxtag::bytes
+# define SENF_PARSER_COLLECTION_TAG_GETAUX__bytes(x) x
+#
+# define SENF_PARSER_COLLECTION_TAG_GOBBLE__transform(x,y)
+# define SENF_PARSER_COLLECTION_TAG__transform(x,y) senf::detail::auxtag::transform<x>
+# define SENF_PARSER_COLLECTION_TAG_GETAUX__transform(x,y) y
+#
+# define SENF_PARSER_COLLECTION_HAS_KEYWORD(x)                                                    \
+      BOOST_PP_IS_EMPTY( BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_GOBBLE__, x) )
 #
 # 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,                                                                         \
+                    BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG_GETAUX__, aux),                       \
+                    BOOST_PP_CAT(SENF_PARSER_COLLECTION_TAG__, aux),                              \
+                    traits ),                                                                     \
+                  ( access,                                                                       \
+                    name,                                                                         \
+                    aux,                                                                          \
+                    senf::detail::auxtag::none,                                                   \
+                    traits ) ))
+#
+# define SENF_PARSER_COLLECTION_II(access, name, 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);                                                     \
           typedef traits::parser<                                                                 \
               BOOST_PP_CAT(name,_aux_policy),                                                     \
-              senf::detail::auxtag::none                                                          \
+              tag                                                                                 \
               >::type BOOST_PP_CAT(name, _collection_t);                                          \
       access:                                                                                     \
           SENF_PARSER_FIELD_SETUP_I( name,                                                        \
                                           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_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>( 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)                                          \
index fb89187..2b519fe 100644 (file)
 ///////////////////////////////ct.p////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::VectorParser<ElementParser,Sizer>
+// senf::VectorParser<ElementParser,AuxPolicy>
 
-template <class ElementParser, class Sizer>
-prefix_ void senf::VectorParser<ElementParser,Sizer>::init()
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::VectorParser<ElementParser,AuxPolicy>::init()
     const
 {
-    aux(i(), state()) = 0;
+    aux(0, i(), state());
     iterator i (begin());
     iterator const e (end());
     for (; i!=e; ++i)
@@ -45,10 +45,10 @@ prefix_ void senf::VectorParser<ElementParser,Sizer>::init()
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::VectorParser_Container<ElementParser,Sizer>
+// senf::VectorParser_Container<ElementParser,AuxPolicy>
 
-template <class ElementParser, class Sizer>
-prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::init()
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::init()
     const
 {
     iterator i (begin());
@@ -59,9 +59,9 @@ prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::init()
 
 // Mutators
 
-template <class ElementParser, class Sizer>
-prefix_ typename senf::VectorParser_Container<ElementParser,Sizer>::iterator
-senf::VectorParser_Container<ElementParser,Sizer>::shift(iterator pos, size_type n)
+template <class ElementParser, class AuxPolicy>
+prefix_ typename senf::VectorParser_Container<ElementParser,AuxPolicy>::iterator
+senf::VectorParser_Container<ElementParser,AuxPolicy>::shift(iterator pos, size_type n)
 {
     size_type ix (std::distance(data().begin(),pos.raw()));
     data().insert(pos.raw(),n*ElementParser::fixed_bytes,0);
@@ -69,9 +69,9 @@ senf::VectorParser_Container<ElementParser,Sizer>::shift(iterator pos, size_type
     return iterator(boost::next(data().begin(),ix),state());
 }
 
-template <class ElementParser, class Sizer>
+template <class ElementParser, class AuxPolicy>
 template <class Value>
-prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::insert(iterator pos,
+prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::insert(iterator pos,
                                                                        size_type n,
                                                                        Value const & t)
 {
@@ -80,9 +80,9 @@ prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::insert(iterator
 }
 
 #ifndef DOXYGEN
-template <class ElementParser, class Sizer>
+template <class ElementParser, class AuxPolicy>
 template <class ForwardIterator>
-prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::
+prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::
 insert(iterator pos, ForwardIterator f, ForwardIterator l,
        typename boost::disable_if< boost::is_convertible<ForwardIterator,size_type> >::type *)
 {
@@ -90,15 +90,15 @@ insert(iterator pos, ForwardIterator f, ForwardIterator l,
         *j << *f;
 }
 #else
-template <class ElementParser, class Sizer>
+template <class ElementParser, class AuxPolicy>
 template <class ForwardIterator>
-prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::
+prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::
 insert(iterator pos, ForwardIterator f, ForwardIterator l)
 {}
 #endif
 
-template <class ElementParser, class Sizer>
-prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::resize(size_type n)
+template <class ElementParser, class AuxPolicy>
+prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::resize(size_type n)
 {
     if (size()>=n)
         erase(boost::next(begin(),n),end());
@@ -106,9 +106,10 @@ prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::resize(size_type
         push_back_space(n-size());
 }
 
-template <class ElementParser, class Sizer>
+template <class ElementParser, class AuxPolicy>
 template <class Value>
-prefix_ void senf::VectorParser_Container<ElementParser,Sizer>::resize(size_type n, Value value)
+prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::resize(size_type n,
+                                                                           Value value)
 {
     if (size()>=n)
         erase(boost::next(begin(),n),end());
index 430427f..b7040bc 100644 (file)
@@ -338,7 +338,7 @@ senf::VectorParser_Container<ElementParser,AuxPolicy>::bytes()
 template <class ElementParser, class AuxPolicy>
 prefix_ void senf::VectorParser_Container<ElementParser,AuxPolicy>::setSize(size_type value)
 {
-    aux(i(),state()).value(value);
+    aux(value, i(),state());
 }
 
 /////////////////////////////cti.e///////////////////////////////////////
index ac7a15a..bfba929 100644 (file)
@@ -40,7 +40,7 @@
 
 namespace senf {
 
-    template <class ElementParser, class Sizer> class VectorParser_Container;
+    template <class ElementParser, class AuxPolicy> class VectorParser_Container;
 
     /** \brief Collection of fixed-size elements
 
index 6da8f49..7a013cc 100644 (file)
@@ -42,12 +42,47 @@ namespace detail {
         > BOOST_PP_CAT(name, _vec_t);                                                             \
         field( name, BOOST_PP_CAT(name, _vec_t) )
 
+    template <class ElementParser, class AuxPolicy, class AuxTag>
+    struct VectorParserPolicy
+    {};
+
+    template <class ElementParser, class AuxPolicy>
+    struct VectorParserPolicy<ElementParser, AuxPolicy, senf::detail::auxtag::none>
+    {
+        typedef AuxPolicy type;
+    };
+
+    template <class ElementParser, class AuxPolicy, class Transform>
+    struct VectorParserPolicy<ElementParser, AuxPolicy, 
+                              senf::detail::auxtag::transform<Transform> >
+    {
+        typedef senf::detail::TransformAuxParserPolicy<AuxPolicy, Transform> type;
+    };
+
+    template <unsigned fixedSize>
+    struct VectorParserBytesTransform
+    {
+        typedef PacketParserBase::size_type value_type;
+        static value_type get(value_type v) { return v/fixedSize; }
+        static value_type set(value_type v) { return v*fixedSize; }
+    };
+
+    template <class ElementParser, class AuxPolicy>
+    struct VectorParserPolicy<ElementParser, AuxPolicy, senf::detail::auxtag::bytes>
+    {
+        typedef senf::detail::TransformAuxParserPolicy<
+            AuxPolicy, 
+            VectorParserBytesTransform<ElementParser::fixed_bytes> > type;
+    };
+
     template <class ElementParser>
     struct VectorParserTraits
     {
         template <class AuxPolicy, class AuxTag>
         struct parser {
-            typedef senf::VectorParser<ElementParser, AuxPolicy> type;
+            typedef senf::VectorParser<
+                ElementParser, 
+                typename VectorParserPolicy<ElementParser, AuxPolicy, AuxTag>::type > type;
         };
     };
 
index b51b392..e1f9d2b 100644 (file)
@@ -200,6 +200,13 @@ BOOST_AUTO_UNIT_TEST(dynamicPolicyVector)
 
 namespace {
 
+    struct TestTransform
+    {
+        typedef unsigned value_type;
+        static unsigned get(unsigned v) { return v-2; }
+        static unsigned set(unsigned v) { return v+2; }
+    };
+
     struct TestVectorParser 
         : public senf::PacketParserBase
     {
@@ -208,8 +215,8 @@ namespace {
         SENF_PARSER_PRIVATE_FIELD ( size1 , senf::UInt8Parser );
         SENF_PARSER_PRIVATE_FIELD ( size2 , senf::UInt8Parser );
         SENF_PARSER_FIELD         ( dummy , senf::UInt32Parser );
-        SENF_PARSER_VECTOR        ( vec1  , size1, senf::UInt16Parser );
-        SENF_PARSER_VECTOR        ( vec2  , size2, senf::UInt16Parser );
+        SENF_PARSER_VECTOR        ( vec1  , transform(TestTransform, size1) , senf::UInt16Parser );
+        SENF_PARSER_VECTOR        ( vec2  , bytes(size2) , senf::UInt16Parser );
 
         SENF_PARSER_FINALIZE( TestVectorParser );
     };
@@ -218,8 +225,8 @@ namespace {
 
 BOOST_AUTO_UNIT_TEST(vectorMacro)
 {
-    unsigned char data[] = { 0x03,                   // size1
-                             0x02,                   // size2
+    unsigned char data[] = { 0x05,                   // size1
+                             0x04,                   // size2
                              0x01, 0x02, 0x03, 0x04, // dummy
                              0x05, 0x06,             // vec1[0]
                              0x07, 0x08,             // vec1[1]