From 7efe29721c882072b062cbd3ae7d9c736129f503 Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Mon, 9 Jun 2008 13:57:27 +0000 Subject: [PATCH] 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 --- Packets/AuxParser.cti | 89 +++++++++++++-- Packets/AuxParser.hh | 44 ++++++-- Packets/ListBParser.cti | 208 +++++++++++++++++++---------------- Packets/ListBParser.hh | 5 +- Packets/ListBParser.ih | 87 ++++++++------- Packets/ListBParser.test.cc | 86 ++++++++++++++- Packets/ListNParser.ct | 37 ++++--- Packets/ListNParser.cti | 114 ++++++++++--------- Packets/ListNParser.hh | 10 +- Packets/ListNParser.ih | 58 ++++++---- Packets/ListNParser.test.cc | 124 +++++++++++++++++++-- Packets/ListParser.ct | 30 +++-- Packets/ListParser.cti | 130 ++++++++++++---------- Packets/ListParser.dox | 59 ++++------ Packets/ListParser.hh | 25 +++-- Packets/ListParser.ih | 50 ++++++--- Packets/ParseHelpers.ih | 62 ++++++++--- Packets/VectorParser.ct | 41 +++---- Packets/VectorParser.cti | 2 +- Packets/VectorParser.hh | 2 +- Packets/VectorParser.ih | 37 ++++++- Packets/VectorParser.test.cc | 15 ++- 22 files changed, 876 insertions(+), 439 deletions(-) diff --git a/Packets/AuxParser.cti b/Packets/AuxParser.cti index 205d88dc0..e4f98328f 100644 --- a/Packets/AuxParser.cti +++ b/Packets/AuxParser.cti @@ -34,12 +34,21 @@ // 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_ diff --git a/Packets/AuxParser.hh b/Packets/AuxParser.hh index 162657e15..5e4a42709 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<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; }; }} diff --git a/Packets/ListBParser.cti b/Packets/ListBParser.cti index ac7b19c1f..ac603c355 100644 --- a/Packets/ListBParser.cti +++ b/Packets/ListBParser.cti @@ -31,148 +31,168 @@ ///////////////////////////////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/////////////////////////////////////// diff --git a/Packets/ListBParser.hh b/Packets/ListBParser.hh index 25f0a0414..fdf4a8a17 100644 --- a/Packets/ListBParser.hh +++ b/Packets/ListBParser.hh @@ -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//////////////////////////////////////// diff --git a/Packets/ListBParser.ih b/Packets/ListBParser.ih index 9439ef2e9..b44e35a0a 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 <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//////////////////////////////////////// diff --git a/Packets/ListBParser.test.cc b/Packets/ListBParser.test.cc index fcc90f52a..0a53ae440 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 225bf52a3..5b19099c9 100644 --- a/Packets/ListNParser.ct +++ b/Packets/ListNParser.ct @@ -31,36 +31,37 @@ #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; } diff --git a/Packets/ListNParser.cti b/Packets/ListNParser.cti index e3cc7b74d..ca46454bb 100644 --- a/Packets/ListNParser.cti +++ b/Packets/ListNParser.cti @@ -30,86 +30,96 @@ #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/////////////////////////////////////// diff --git a/Packets/ListNParser.hh b/Packets/ListNParser.hh index 2cb4292f7..08cf568d6 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 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//////////////////////////////////////// diff --git a/Packets/ListNParser.ih b/Packets/ListNParser.ih index 51be7c53d..ba39b52d2 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 <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; }; }} diff --git a/Packets/ListNParser.test.cc b/Packets/ListNParser.test.cc index f4d5e38f9..ebfee8a27 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<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_ diff --git a/Packets/ListParser.ct b/Packets/ListParser.ct index 39915c265..19fccdbc3 100644 --- a/Packets/ListParser.ct +++ b/Packets/ListParser.ct @@ -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())))); } } diff --git a/Packets/ListParser.cti b/Packets/ListParser.cti index 919b913b8..9847a658a 100644 --- a/Packets/ListParser.cti +++ b/Packets/ListParser.cti @@ -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()); } diff --git a/Packets/ListParser.dox b/Packets/ListParser.dox index fd208336f..d42310cf0 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. <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 + {}; }; } diff --git a/Packets/ListParser.hh b/Packets/ListParser.hh index ae3d9ae21..c101b82bc 100644 --- a/Packets/ListParser.hh +++ b/Packets/ListParser.hh @@ -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) } diff --git a/Packets/ListParser.ih b/Packets/ListParser.ih index e6c7d30dd..e97d2fa3e 100644 --- a/Packets/ListParser.ih +++ b/Packets/ListParser.ih @@ -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//////////////////////////////////////// diff --git a/Packets/ParseHelpers.ih b/Packets/ParseHelpers.ih index d93609743..18f58e586 100644 --- a/Packets/ParseHelpers.ih +++ b/Packets/ParseHelpers.ih @@ -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/////////////////////////////////////// @@ -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 <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, \ @@ -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 <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) \ diff --git a/Packets/VectorParser.ct b/Packets/VectorParser.ct index fb8918744..2b519fed7 100644 --- a/Packets/VectorParser.ct +++ b/Packets/VectorParser.ct @@ -31,13 +31,13 @@ ///////////////////////////////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()); diff --git a/Packets/VectorParser.cti b/Packets/VectorParser.cti index 430427fe8..b7040bc6b 100644 --- a/Packets/VectorParser.cti +++ b/Packets/VectorParser.cti @@ -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/////////////////////////////////////// diff --git a/Packets/VectorParser.hh b/Packets/VectorParser.hh index ac7a15a87..bfba929e2 100644 --- a/Packets/VectorParser.hh +++ b/Packets/VectorParser.hh @@ -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 diff --git a/Packets/VectorParser.ih b/Packets/VectorParser.ih index 6da8f4901..7a013cc66 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 <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; }; }; diff --git a/Packets/VectorParser.test.cc b/Packets/VectorParser.test.cc index b51b392b6..e1f9d2b74 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] -- GitLab