From: g0dil Date: Mon, 9 Jun 2008 13:57:27 +0000 (+0000) Subject: Packets: Update AuxParser interface X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=8f1a688cea76f2e76bfa0193dff9c1538929147e;p=senf.git Packets: Update AuxParser interface 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 --- diff --git a/Packets/AuxParser.cti b/Packets/AuxParser.cti index 205d88d..e4f9832 100644 --- a/Packets/AuxParser.cti +++ b/Packets/AuxParser.cti @@ -34,12 +34,21 @@ // senf::detail::PrefixAuxParserPolicy

template -prefix_ typename senf::detail::PrefixAuxParserPolicy

::ParserType +prefix_ typename P::value_type senf::detail::PrefixAuxParserPolicy

::aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const { - return ParserType(i, s); + return P(i, s).value(); +} + +template +prefix_ void senf::detail::PrefixAuxParserPolicy

::aux(typename P::value_type const & v, + PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + P(i, s).value(v); } template @@ -48,19 +57,28 @@ senf::detail::PrefixAuxParserPolicy

::adjust(PacketParserBase::data_iterator i PacketParserBase::state_type s) const { - return i+ParserType::fixed_bytes; + return i+P::fixed_bytes; } /////////////////////////////////////////////////////////////////////////// // senf::detail::FixedAuxParserPolicy

template -prefix_ typename senf::detail::FixedAuxParserPolicy::ParserType +prefix_ typename P::value_type senf::detail::FixedAuxParserPolicy::aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const { - return ParserType(i-Dist, s); + return P(i-Dist, s).value(); +} + +template +prefix_ void senf::detail::FixedAuxParserPolicy::aux(typename P::value_type const & v, + PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + P(i-Dist, s).value(v); } template @@ -76,7 +94,7 @@ senf::detail::FixedAuxParserPolicy::adjust(PacketParserBase::data_iterat // senf::detail::DynamicAuxParserPolicy

template -prefix_ senf::detail::DynamicAuxParserPolicy

::DynamicAuxParserPolicy(ParserType p) +prefix_ senf::detail::DynamicAuxParserPolicy

::DynamicAuxParserPolicy(P p) : p_ (p) {} @@ -87,12 +105,21 @@ senf::detail::DynamicAuxParserPolicy

::DynamicAuxParserPolicy(WrapperPolicy co {} template -prefix_ typename senf::detail::DynamicAuxParserPolicy

::ParserType +prefix_ typename P::value_type senf::detail::DynamicAuxParserPolicy

::aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const { - return p_; + return p_.value(); +} + +template +prefix_ void senf::detail::DynamicAuxParserPolicy

::aux(typename P::value_type const & v, + PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + p_.value(v); } template @@ -114,12 +141,22 @@ DynamicWrapperAuxParserPolicy(ParserPolicy const & other) {} template -prefix_ typename senf::detail::DynamicWrapperAuxParserPolicy

::ParserType +prefix_ typename P::value_type senf::detail::DynamicWrapperAuxParserPolicy

::aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const { - return * p_; + return p_->value(); +} + +template +prefix_ void +senf::detail::DynamicWrapperAuxParserPolicy

::aux(typename P::value_type const & v, + PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + p_->value(v); } template @@ -131,6 +168,38 @@ senf::detail::DynamicWrapperAuxParserPolicy

::adjust(PacketParserBase::data_it return i; } +/////////////////////////////////////////////////////////////////////////// +// senf::detail::TransformAuxParserPolicy + +template +prefix_ senf::detail::TransformAuxParserPolicy::TransformAuxParserPolicy() +{} + +template +template +prefix_ senf::detail::TransformAuxParserPolicy:: +TransformAuxParserPolicy(Arg const & arg) + : Policy(arg) +{} + +template +prefix_ typename Transform::value_type +senf::detail::TransformAuxParserPolicy::aux(PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + return Transform::get(Policy::aux(i,s)); +} + +template +prefix_ void senf::detail::TransformAuxParserPolicy:: +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_ diff --git a/Packets/AuxParser.hh b/Packets/AuxParser.hh index 162657e..5e4a427 100644 --- a/Packets/AuxParser.hh +++ b/Packets/AuxParser.hh @@ -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

WrapperPolicy; - typedef P ParserType; + typedef DynamicAuxParserPolicy

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 struct DynamicWrapperAuxParserPolicy { + typedef DynamicWrapperAuxParserPolicy

WrapperPolicy; typedef DynamicAuxParserPolicy

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 p_; + mutable SafePacketParserWrapper

p_; + }; + + template + struct TransformAuxParserPolicy + : public Policy + { + typedef TransformAuxParserPolicy WrapperPolicy; + typedef TransformAuxParserPolicy ParserPolicy; + + static PacketParserBase::size_type const aux_bytes = Policy::aux_bytes; + + TransformAuxParserPolicy(); + template 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; }; }} diff --git a/Packets/ListBParser.cti b/Packets/ListBParser.cti index ac7b19c..ac603c3 100644 --- a/Packets/ListBParser.cti +++ b/Packets/ListBParser.cti @@ -31,148 +31,168 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::detail::ListBParser_Policy +// senf::detail::ListBParser_Policy + +template +prefix_ senf::detail::ListBParser_Policy::ListBParser_Policy() +{} -template -prefix_ typename senf::detail::ListBParser_Policy::size_type -senf::detail::ListBParser_Policy::bytes(iterator i, state_type s) +template +template +prefix_ +senf::detail::ListBParser_Policy::ListBParser_Policy(Arg const & arg) + : AuxPolicy (arg) +{} + +template +prefix_ typename senf::detail::ListBParser_Policy::size_type +senf::detail::ListBParser_Policy::bytes(data_iterator i, state_type s) const { - return BytesParser(i,s) + BytesParser::fixed_bytes; + return AuxPolicy::aux(i,s) + AuxPolicy::aux_bytes; } -template -prefix_ typename senf::detail::ListBParser_Policy::size_type -senf::detail::ListBParser_Policy::size(iterator i, state_type s) +template +prefix_ typename senf::detail::ListBParser_Policy::size_type +senf::detail::ListBParser_Policy::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 -prefix_ void senf::detail::ListBParser_Policy::init(iterator i, - state_type s) +template +prefix_ void senf::detail::ListBParser_Policy::init(data_iterator i, + state_type s) const -{} - -/////////////////////////////////////////////////////////////////////////// -// senf::detail::ListBParser_Policy::iterator_policy - -template -prefix_ typename senf::detail::ListBParser_Policy::iterator -senf::detail::ListBParser_Policy::iterator_policy:: -setBegin(iterator i, state_type s) { - return boost::next(i,BytesParser::fixed_bytes); + AuxPolicy::aux(0,i,s); } -template -prefix_ typename senf::detail::ListBParser_Policy::iterator -senf::detail::ListBParser_Policy::iterator_policy:: -setEnd(iterator i, state_type s) +/////////////////////////////////////////////////////////////////////////// +// senf::detail::ListBParser_Policy + +template +prefix_ +senf::detail::ListBParser_Policy::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 -prefix_ void -senf::detail::ListBParser_Policy::iterator_policy:: -setFromPosition(iterator i, state_type s, iterator p) -{} - -template -prefix_ typename senf::detail::ListBParser_Policy::iterator -senf::detail::ListBParser_Policy::iterator_policy::next(iterator i, +template +prefix_ typename senf::detail::ListBParser_Policy::container_policy::size_type +senf::detail::ListBParser_Policy::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 -prefix_ typename senf::detail::ListBParser_Policy::iterator -senf::detail::ListBParser_Policy::iterator_policy::raw(iterator i, +template +prefix_ typename senf::detail::ListBParser_Policy::container_policy::size_type +senf::detail::ListBParser_Policy::container_policy::size(data_iterator i, state_type s) const { - return i; + return n_; } -/////////////////////////////////////////////////////////////////////////// -// senf::detail::ListBParser_Policy +template +prefix_ void senf::detail::ListBParser_Policy::container_policy:: +init(data_iterator i, state_type s) +{ + n_ = 0; + container_size_ = s->size(); + AuxPolicy::aux(0,i,s); +} -template -prefix_ -senf::detail::ListBParser_Policy::container_policy:: -container_policy(parser_type const & list) +template +prefix_ void senf::detail::ListBParser_Policy::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 -prefix_ typename senf::detail::ListBParser_Policy::size_type -senf::detail::ListBParser_Policy::container_policy:: -bytes(iterator i, state_type s) - const +template +prefix_ void +senf::detail::ListBParser_Policy::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 -prefix_ typename senf::detail::ListBParser_Policy::size_type -senf::detail::ListBParser_Policy::container_policy:: -size(iterator i, state_type s) +template +prefix_ void +senf::detail::ListBParser_Policy::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 -prefix_ void -senf::detail::ListBParser_Policy::container_policy:: -erase(iterator i, state_type s, iterator p) +template +prefix_ typename senf::detail::ListBParser_Policy::container_policy::data_iterator +senf::detail::ListBParser_Policy::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 -prefix_ void -senf::detail::ListBParser_Policy::container_policy:: -insert(iterator i, state_type s, iterator p) +template +prefix_ typename senf::detail::ListBParser_Policy::container_policy::data_iterator +senf::detail::ListBParser_Policy::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 +template prefix_ void -senf::detail::ListBParser_Policy::container_policy:: -init(iterator i, state_type s) +senf::detail::ListBParser_Policy::container_policy:: +setFromPosition(container_type const & c, iterator_data & d, data_iterator p) + const +{} + +template +prefix_ typename senf::detail::ListBParser_Policy::container_policy::data_iterator +senf::detail::ListBParser_Policy::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 -prefix_ void -senf::detail::ListBParser_Policy::container_policy:: -update(iterator i, state_type s) +template +prefix_ typename senf::detail::ListBParser_Policy::container_policy::data_iterator +senf::detail::ListBParser_Policy::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/////////////////////////////////////// diff --git a/Packets/ListBParser.hh b/Packets/ListBParser.hh index 25f0a04..fdf4a8a 100644 --- a/Packets/ListBParser.hh +++ b/Packets/ListBParser.hh @@ -64,7 +64,9 @@ namespace senf { */ template struct ListBParser { - typedef ListParser< detail::ListBParser_Policy > parser; + typedef ListParser< + detail::ListBParser_Policy< ElementParser, + detail::PrefixAuxParserPolicy > > parser; }; /** \brief Define ListBParser field @@ -83,7 +85,6 @@ namespace senf { # define SENF_PARSER_LIST_B(name, elt_type, size_type) \ typedef senf::ListBParser::parser BOOST_PP_CAT(name, _list_t); \ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _list_t) ) - } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Packets/ListBParser.ih b/Packets/ListBParser.ih index 9439ef2..b44e35a 100644 --- a/Packets/ListBParser.ih +++ b/Packets/ListBParser.ih @@ -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 + template 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 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 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 + struct ListParserPolicy + { + typedef ListBParser_Policy type; + }; + }} ///////////////////////////////ih.e//////////////////////////////////////// diff --git a/Packets/ListBParser.test.cc b/Packets/ListBParser.test.cc index fcc90f5..0a53ae4 100644 --- a/Packets/ListBParser.test.cc +++ b/Packets/ListBParser.test.cc @@ -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_ diff --git a/Packets/ListNParser.ct b/Packets/ListNParser.ct index 225bf52..5b19099 100644 --- a/Packets/ListNParser.ct +++ b/Packets/ListNParser.ct @@ -31,36 +31,37 @@ #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// -template +template prefix_ void -senf::detail::ListNParser_Policy::iterator_policy:: -setFromPosition(iterator i, state_type s, iterator p) +senf::detail::ListNParser_Policy::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 -prefix_ typename senf::detail::ListNParser_Policy::iterator -senf::detail::ListNParser_Policy::iterator_policy::raw(iterator i, - state_type s) +template +prefix_ typename senf::detail::ListNParser_Policy::data_iterator +senf::detail::ListNParser_Policy::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; } diff --git a/Packets/ListNParser.cti b/Packets/ListNParser.cti index e3cc7b7..ca46454 100644 --- a/Packets/ListNParser.cti +++ b/Packets/ListNParser.cti @@ -30,86 +30,96 @@ #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// -template -prefix_ typename senf::detail::ListNParser_Policy::size_type -senf::detail::ListNParser_Policy::bytes(iterator i, state_type s) +template +prefix_ senf::detail::ListNParser_Policy::ListNParser_Policy() +{} + +template +template +prefix_ +senf::detail::ListNParser_Policy::ListNParser_Policy(Arg const & aux) + : AuxPolicy (aux) +{} + +template +prefix_ typename senf::detail::ListNParser_Policy::size_type +senf::detail::ListNParser_Policy::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 -prefix_ typename senf::detail::ListNParser_Policy::size_type -senf::detail::ListNParser_Policy::size(iterator i, state_type s) +template +prefix_ typename senf::detail::ListNParser_Policy::size_type +senf::detail::ListNParser_Policy::size(data_iterator i, state_type s) const { - return SizeParser(i,s); + return AuxPolicy::aux(i,s); } -template -prefix_ void senf::detail::ListNParser_Policy::init(iterator i, - state_type s) +template +prefix_ void senf::detail::ListNParser_Policy::init(data_iterator i, + state_type s) const -{} +{ + AuxPolicy::aux(0,i,s); +} -template -prefix_ void senf::detail::ListNParser_Policy::erase(iterator i, - state_type s, - iterator p) +template +prefix_ void +senf::detail::ListNParser_Policy::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 -prefix_ void senf::detail::ListNParser_Policy::insert(iterator i, - state_type s, - iterator p) +template +prefix_ void +senf::detail::ListNParser_Policy::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 -prefix_ void senf::detail::ListNParser_Policy::update(iterator i, - state_type s) +template +prefix_ void +senf::detail::ListNParser_Policy::update(container_type const & c) const {} -template -prefix_ typename senf::detail::ListNParser_Policy::iterator -senf::detail::ListNParser_Policy::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 -prefix_ typename senf::detail::ListNParser_Policy::iterator -senf::detail::ListNParser_Policy::iterator_policy:: -setEnd(iterator i, state_type s) +template +prefix_ typename senf::detail::ListNParser_Policy::data_iterator +senf::detail::ListNParser_Policy::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 -prefix_ typename senf::detail::ListNParser_Policy::iterator -senf::detail::ListNParser_Policy::iterator_policy::next(iterator i, - state_type s) +template +prefix_ typename senf::detail::ListNParser_Policy::data_iterator +senf::detail::ListNParser_Policy::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 -prefix_ senf::PacketData & -senf::detail::ListNParser_Policy::data(state_type s) +template +prefix_ typename senf::detail::ListNParser_Policy::data_iterator +senf::detail::ListNParser_Policy::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/////////////////////////////////////// diff --git a/Packets/ListNParser.hh b/Packets/ListNParser.hh index 2cb4292..08cf568 100644 --- a/Packets/ListNParser.hh +++ b/Packets/ListNParser.hh @@ -28,15 +28,14 @@ // Custom includes #include "ListParser.hh" +#include "AuxParser.hh" //#include "ListNParser.mpp" +#include "ListNParser.ih" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { - namespace detail { template - 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 struct ListNParser { - typedef ListParser< detail::ListNParser_Policy > parser; + typedef ListParser< detail::ListNParser_Policy< + ElementParser, + detail::PrefixAuxParserPolicy > > parser; }; /** \brief Define ListNParser field @@ -71,7 +72,6 @@ namespace senf { # define SENF_PARSER_LIST_N(name, elt_type, size_type) \ typedef senf::ListNParser::parser BOOST_PP_CAT(name, _list_t); \ SENF_PARSER_FIELD( name, BOOST_PP_CAT(name, _list_t) ) - } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Packets/ListNParser.ih b/Packets/ListNParser.ih index 51be7c5..ba39b52 100644 --- a/Packets/ListNParser.ih +++ b/Packets/ListNParser.ih @@ -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 + template 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 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 + struct ListParserPolicy + { + typedef ListNParser_Policy type; + }; + + template + struct ListParserPolicy > + { + typedef ListNParser_Policy< ElementParser, + TransformAuxParserPolicy > type; }; }} diff --git a/Packets/ListNParser.test.cc b/Packets/ListNParser.test.cc index f4d5e38..ebfee8a 100644 --- a/Packets/ListNParser.test.cc +++ b/Packets/ListNParser.test.cc @@ -51,6 +51,37 @@ namespace { }; } +BOOST_AUTO_UNIT_TEST(ListNParser_container) +{ + typedef senf::ListNParser::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::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::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_ diff --git a/Packets/ListParser.ct b/Packets/ListParser.ct index 39915c2..19fccdb 100644 --- a/Packets/ListParser.ct +++ b/Packets/ListParser.ct @@ -39,8 +39,9 @@ prefix_ void senf::ListParser::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::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::back() template prefix_ void senf::ListParser_Container::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,0); value_type(sp,state()).init(); - ListPolicy::insert(si,state(),sp); + ListPolicy::insert(*this,sp); } } @@ -91,14 +92,13 @@ prefix_ void senf::ListParser_Container::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,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:: insert(iterator pos, ForwardIterator f, ForwardIterator l, typename boost::disable_if< boost::is_convertible >::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,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 prefix_ void senf::ListParser_Container::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())))); } } diff --git a/Packets/ListParser.cti b/Packets/ListParser.cti index 919b913..9847a65 100644 --- a/Packets/ListParser.cti +++ b/Packets/ListParser.cti @@ -68,23 +68,8 @@ template prefix_ bool senf::ListParser::empty() const { - return begin() == end(); -} - -template -prefix_ typename senf::ListParser::iterator -senf::ListParser::begin() - const -{ - return iterator(i(),state(),iterator::Begin); -} - -template -prefix_ typename senf::ListParser::iterator -senf::ListParser::end() - const -{ - return iterator(i(),state(),iterator::End); + container c (*this); + return c.empty(); } template @@ -93,7 +78,8 @@ senf::ListParser::front() const { SENF_ASSERT( ! empty() ); - return *begin(); + container c(*this); + return *(c.begin()); } template @@ -147,62 +133,83 @@ prefix_ void senf::ListParser::resize(size_type n, Value value) c.resize(n,value); } +template +prefix_ typename senf::ListParser & +senf::ListParser::get(ListPolicy & p) +{ + return static_cast(p); +} + +template +prefix_ typename senf::ListParser const & +senf::ListParser::get(ListPolicy const & p) +{ + return static_cast(p); +} + /////////////////////////////////////////////////////////////////////////// // senf::detail::ListParser_Iterator -template -prefix_ senf::detail::ListParser_Iterator::ListParser_Iterator() -{} - -template -prefix_ senf::detail::ListParser_Iterator:: -ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, Begin_t) - : IteratorPolicy(), i_(IteratorPolicy::setBegin(i,s)), s_(s) +template +prefix_ senf::detail::ListParser_Iterator::ListParser_Iterator() {} -template -prefix_ senf::detail::ListParser_Iterator:: -ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, End_t) - : IteratorPolicy(), i_(IteratorPolicy::setEnd(i,s)), s_(s) +template +prefix_ senf::detail::ListParser_Iterator::ListParser_Iterator(Container const & c) + : c_ (&c) {} -template -prefix_ senf::detail::ListParser_Iterator:: -ListParser_Iterator(PacketParserBase::data_iterator i, PacketParserBase::state_type s, - PacketParserBase::data_iterator p) - : IteratorPolicy(), i_(p), s_(s) +template +prefix_ senf::PacketParserBase::data_iterator +senf::detail::ListParser_Iterator::raw() + const { - IteratorPolicy::setFromPosition(i,s,p); + return c_->Container::policy::raw(*c_, *this); } -template +template prefix_ senf::PacketParserBase::data_iterator -senf::detail::ListParser_Iterator::raw() +senf::detail::ListParser_Iterator::i() const { - return IteratorPolicy::raw(i_,s_); + return i_; +} + +template +prefix_ typename senf::detail::ListParser_Iterator & +senf::detail::ListParser_Iterator::get(typename Container::policy::iterator_data & d) +{ + return static_cast(d); +} + +template +prefix_ typename senf::detail::ListParser_Iterator const & +senf::detail::ListParser_Iterator:: +get(typename Container::policy::iterator_data const & d) +{ + return static_cast(d); } -template -prefix_ ElementParser -senf::detail::ListParser_Iterator::dereference() +template +prefix_ typename senf::detail::ListParser_Iterator::value_type +senf::detail::ListParser_Iterator::dereference() const { - return ElementParser(i_,s_); + return value_type(i_,c_->state()); } -template -prefix_ bool senf::detail::ListParser_Iterator:: -equal(ListParser_Iterator const & other) +template +prefix_ bool +senf::detail::ListParser_Iterator::equal(ListParser_Iterator const & other) const { return i_ == other.i_; } -template -prefix_ void senf::detail::ListParser_Iterator::increment() +template +prefix_ void senf::detail::ListParser_Iterator::increment() { - i_ = IteratorPolicy::next(i_,s_); + i_ = c_->Container::policy::next(*c_, *this); } /////////////////////////////////////////////////////////////////////////// @@ -213,13 +220,14 @@ prefix_ void senf::detail::ListParser_Iterator::in template prefix_ senf::ListParser_Container:: ListParser_Container(parser_type const & list) - : ListPolicy(list), state_(list.state()), i_(std::distance(data().begin(),list.i())) + : ListPolicy(static_cast(list)), + state_(list.state()), i_(std::distance(data().begin(),list.i())) {} template prefix_ senf::ListParser_Container::~ListParser_Container() { - ListPolicy::update(i(),state()); + ListPolicy::update(*this); } // Accessors @@ -229,7 +237,7 @@ prefix_ typename senf::ListParser_Container::size_type senf::ListParser_Container::size() const { - ListPolicy::update(i(),state()); + ListPolicy::update(*this); return ListPolicy::size(i(),state()); } @@ -237,7 +245,7 @@ template prefix_ bool senf::ListParser_Container::empty() const { - ListPolicy::update(i(),state()); + ListPolicy::update(*this); return begin() == end(); } @@ -246,8 +254,10 @@ prefix_ typename senf::ListParser_Container::iterator senf::ListParser_Container::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 @@ -255,8 +265,10 @@ prefix_ typename senf::ListParser_Container::iterator senf::ListParser_Container::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 @@ -319,7 +331,7 @@ prefix_ typename senf::ListParser_Container::parser_type senf::ListParser_Container::parser() const { - ListPolicy::update(i(),state()); + ListPolicy::update(*this); return parser_type(i(),state()); } @@ -351,7 +363,7 @@ prefix_ typename senf::ListParser_Container::size_type senf::ListParser_Container::bytes() const { - ListPolicy::update(i(),state()); + ListPolicy::update(*this); return ListPolicy::bytes(i(),state()); } diff --git a/Packets/ListParser.dox b/Packets/ListParser.dox index fd20833..d42310c 100644 --- a/Packets/ListParser.dox +++ b/Packets/ListParser.dox @@ -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. senf::Parse_List. */ - 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. Parse_List_Container. 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 + {}; }; } diff --git a/Packets/ListParser.hh b/Packets/ListParser.hh index ae3d9ae..c101b82 100644 --- a/Packets/ListParser.hh +++ b/Packets/ListParser.hh @@ -35,8 +35,7 @@ namespace senf { - namespace detail { template - class ListParser_Iterator; } + namespace detail { template class ListParser_Iterator; } template 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 void resize (size_type n, Value value) const; + static ListParser & get(ListPolicy & p); + static ListParser const & get(ListPolicy const & p); + private: template 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 iterator; typedef iterator const_iterator; typedef PacketParserBase::state_type state_type; @@ -213,10 +211,17 @@ namespace senf { ///@} private: + friend class detail::ListParser_Iterator; + 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) } diff --git a/Packets/ListParser.ih b/Packets/ListParser.ih index e6c7d30..e97d2fa 100644 --- a/Packets/ListParser.ih +++ b/Packets/ListParser.ih @@ -38,39 +38,59 @@ namespace detail { \internal */ - template + template class ListParser_Iterator - : public boost::iterator_facade< ListParser_Iterator, - ElementParser, + : public boost::iterator_facade< ListParser_Iterator, + 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 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 + struct ListParserPolicy + {}; + + template + struct ListParserTraits + { + template + struct parser { + typedef senf::ListParser< + typename ListParserPolicy::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 ) + }} ///////////////////////////////ih.e//////////////////////////////////////// diff --git a/Packets/ParseHelpers.ih b/Packets/ParseHelpers.ih index d936097..18f58e5 100644 --- a/Packets/ParseHelpers.ih +++ b/Packets/ParseHelpers.ih @@ -26,6 +26,9 @@ # # // Custom includes # include +# include +# include +# include # include "../Utils/mpl.hh" # # ////////////////////////////////ih.p/////////////////////////////////////// @@ -436,16 +439,49 @@ # /////////////////////////////////////////////////////////////////////////// # // 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 + 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 +# 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, \ @@ -484,17 +520,17 @@ SENF_PARSER_CURRENT_FIXED_OFFSET() \ - SENF_PARSER_FIXED_OFFSET(aux) > # -# define SENF_PARSER_COLLECTION_VAL_var(name,aux,access) \ - private: \ - template T BOOST_PP_CAT(name, _dispatch)(boost::true_type) const \ - { return parse( SENF_PARSER_OFFSET(name) ); } \ - template T BOOST_PP_CAT(name, _dispatch)(boost::false_type) const \ - { return parse( 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::integral_constant()); } \ - access: \ - BOOST_PP_CAT(name, _t) name() const \ +# define SENF_PARSER_COLLECTION_VAL_var(name,aux,access) \ + private: \ + template T BOOST_PP_CAT(name, _dispatch)(boost::true_type) const \ + { return parse( SENF_PARSER_OFFSET(name) ); } \ + template T BOOST_PP_CAT(name, _dispatch)(boost::false_type) const \ + { return parse( aux(), SENF_PARSER_OFFSET(name) ); } \ + BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const \ + { return BOOST_PP_CAT(name, _dispatch) ( \ + boost::integral_constant()); } \ + access: \ + BOOST_PP_CAT(name, _t) name() const \ { return BOOST_PP_CAT(name, _)(); } # # define SENF_PARSER_COLLECTION_VAL_fix(name,aux,access) \ diff --git a/Packets/VectorParser.ct b/Packets/VectorParser.ct index fb89187..2b519fe 100644 --- a/Packets/VectorParser.ct +++ b/Packets/VectorParser.ct @@ -31,13 +31,13 @@ ///////////////////////////////ct.p//////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::VectorParser +// senf::VectorParser -template -prefix_ void senf::VectorParser::init() +template +prefix_ void senf::VectorParser::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::init() } /////////////////////////////////////////////////////////////////////////// -// senf::VectorParser_Container +// senf::VectorParser_Container -template -prefix_ void senf::VectorParser_Container::init() +template +prefix_ void senf::VectorParser_Container::init() const { iterator i (begin()); @@ -59,9 +59,9 @@ prefix_ void senf::VectorParser_Container::init() // Mutators -template -prefix_ typename senf::VectorParser_Container::iterator -senf::VectorParser_Container::shift(iterator pos, size_type n) +template +prefix_ typename senf::VectorParser_Container::iterator +senf::VectorParser_Container::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::shift(iterator pos, size_type return iterator(boost::next(data().begin(),ix),state()); } -template +template template -prefix_ void senf::VectorParser_Container::insert(iterator pos, +prefix_ void senf::VectorParser_Container::insert(iterator pos, size_type n, Value const & t) { @@ -80,9 +80,9 @@ prefix_ void senf::VectorParser_Container::insert(iterator } #ifndef DOXYGEN -template +template template -prefix_ void senf::VectorParser_Container:: +prefix_ void senf::VectorParser_Container:: insert(iterator pos, ForwardIterator f, ForwardIterator l, typename boost::disable_if< boost::is_convertible >::type *) { @@ -90,15 +90,15 @@ insert(iterator pos, ForwardIterator f, ForwardIterator l, *j << *f; } #else -template +template template -prefix_ void senf::VectorParser_Container:: +prefix_ void senf::VectorParser_Container:: insert(iterator pos, ForwardIterator f, ForwardIterator l) {} #endif -template -prefix_ void senf::VectorParser_Container::resize(size_type n) +template +prefix_ void senf::VectorParser_Container::resize(size_type n) { if (size()>=n) erase(boost::next(begin(),n),end()); @@ -106,9 +106,10 @@ prefix_ void senf::VectorParser_Container::resize(size_type push_back_space(n-size()); } -template +template template -prefix_ void senf::VectorParser_Container::resize(size_type n, Value value) +prefix_ void senf::VectorParser_Container::resize(size_type n, + Value value) { if (size()>=n) erase(boost::next(begin(),n),end()); diff --git a/Packets/VectorParser.cti b/Packets/VectorParser.cti index 430427f..b7040bc 100644 --- a/Packets/VectorParser.cti +++ b/Packets/VectorParser.cti @@ -338,7 +338,7 @@ senf::VectorParser_Container::bytes() template prefix_ void senf::VectorParser_Container::setSize(size_type value) { - aux(i(),state()).value(value); + aux(value, i(),state()); } /////////////////////////////cti.e/////////////////////////////////////// diff --git a/Packets/VectorParser.hh b/Packets/VectorParser.hh index ac7a15a..bfba929 100644 --- a/Packets/VectorParser.hh +++ b/Packets/VectorParser.hh @@ -40,7 +40,7 @@ namespace senf { - template class VectorParser_Container; + template class VectorParser_Container; /** \brief Collection of fixed-size elements diff --git a/Packets/VectorParser.ih b/Packets/VectorParser.ih index 6da8f49..7a013cc 100644 --- a/Packets/VectorParser.ih +++ b/Packets/VectorParser.ih @@ -42,12 +42,47 @@ namespace detail { > BOOST_PP_CAT(name, _vec_t); \ field( name, BOOST_PP_CAT(name, _vec_t) ) + template + struct VectorParserPolicy + {}; + + template + struct VectorParserPolicy + { + typedef AuxPolicy type; + }; + + template + struct VectorParserPolicy > + { + typedef senf::detail::TransformAuxParserPolicy type; + }; + + template + 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 + struct VectorParserPolicy + { + typedef senf::detail::TransformAuxParserPolicy< + AuxPolicy, + VectorParserBytesTransform > type; + }; + template struct VectorParserTraits { template struct parser { - typedef senf::VectorParser type; + typedef senf::VectorParser< + ElementParser, + typename VectorParserPolicy::type > type; }; }; diff --git a/Packets/VectorParser.test.cc b/Packets/VectorParser.test.cc index b51b392..e1f9d2b 100644 --- a/Packets/VectorParser.test.cc +++ b/Packets/VectorParser.test.cc @@ -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]