From: g0dil Date: Fri, 6 Jun 2008 08:02:26 +0000 (+0000) Subject: Packets: Implement basic AuxParser X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=4ee78597a1dae53669f5295cbb686c58146d2449;p=senf.git Packets: Implement basic AuxParser Packets: Implement generic internel collection parser macro infrastructure Packets: Update VectorParser to use the new AuxParser/collection infrastructure git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@868 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/AuxParser.cti b/Packets/AuxParser.cti new file mode 100644 index 0000000..205d88d --- /dev/null +++ b/Packets/AuxParser.cti @@ -0,0 +1,146 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief AuxParser inline template implementation */ + +//#include "AuxParser.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::detail::PrefixAuxParserPolicy

+ +template +prefix_ typename senf::detail::PrefixAuxParserPolicy

::ParserType +senf::detail::PrefixAuxParserPolicy

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

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

+ +template +prefix_ typename senf::detail::FixedAuxParserPolicy::ParserType +senf::detail::FixedAuxParserPolicy::aux(PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + return ParserType(i-Dist, s); +} + +template +prefix_ senf::PacketParserBase::data_iterator +senf::detail::FixedAuxParserPolicy::adjust(PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + return i; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::detail::DynamicAuxParserPolicy

+ +template +prefix_ senf::detail::DynamicAuxParserPolicy

::DynamicAuxParserPolicy(ParserType p) + : p_ (p) +{} + +template +prefix_ +senf::detail::DynamicAuxParserPolicy

::DynamicAuxParserPolicy(WrapperPolicy const & other) + : p_ (* other.p_) +{} + +template +prefix_ typename senf::detail::DynamicAuxParserPolicy

::ParserType +senf::detail::DynamicAuxParserPolicy

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

::adjust(PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + return i; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::detail::DynamicWrapperAuxParserPolicy

+ +template +prefix_ senf::detail::DynamicWrapperAuxParserPolicy

:: +DynamicWrapperAuxParserPolicy(ParserPolicy const & other) + : p_ (other.p_) +{} + +template +prefix_ typename senf::detail::DynamicWrapperAuxParserPolicy

::ParserType +senf::detail::DynamicWrapperAuxParserPolicy

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

::adjust(PacketParserBase::data_iterator i, + PacketParserBase::state_type s) + const +{ + return i; +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Packets/AuxParser.hh b/Packets/AuxParser.hh new file mode 100644 index 0000000..162657e --- /dev/null +++ b/Packets/AuxParser.hh @@ -0,0 +1,121 @@ +// $Id$ +// +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief AuxParser public header */ + +#ifndef HH_AuxParser_ +#define HH_AuxParser_ 1 + +#ifndef HH_Packets_ +#error "Don't include 'AuxParser.hh' directly, include 'Packets.hh'" +#endif + +// Custom includes +#include "PacketParser.hh" +#include "SafeIterator.hh" + +//#include "AuxParser.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace detail { + + template + struct PrefixAuxParserPolicy + { + typedef PrefixAuxParserPolicy WrapperPolicy; + typedef P ParserType; + + static PacketParserBase::size_type const aux_bytes = ParserType::fixed_bytes; + + ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + }; + + template + struct FixedAuxParserPolicy + { + typedef FixedAuxParserPolicy WrapperPolicy; + typedef P ParserType; + + static PacketParserBase::size_type const aux_bytes = 0; + + ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + }; + + template struct DynamicWrapperAuxParserPolicy; + + template + struct DynamicAuxParserPolicy + { + typedef DynamicWrapperAuxParserPolicy

WrapperPolicy; + typedef P ParserType; + + static PacketParserBase::size_type const aux_bytes = 0; + + DynamicAuxParserPolicy(ParserType p); + DynamicAuxParserPolicy(WrapperPolicy const & other); + + ParserType aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + + ParserType p_; + }; + + template + struct DynamicWrapperAuxParserPolicy + { + 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; + PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const; + + SafePacketParserWrapper p_; + }; +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#endif +#if !defined(HH_Packets__decls_) && !defined(HH_AuxParser_i_) +#define HH_AuxParser_i_ +//#include "AuxParser.cci" +//#include "AuxParser.ct" +#include "AuxParser.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Packets/PacketParser.cti b/Packets/PacketParser.cti index 9cb4968..098908f 100644 --- a/Packets/PacketParser.cti +++ b/Packets/PacketParser.cti @@ -42,6 +42,13 @@ prefix_ Parser senf::PacketParserBase::parse(data_iterator i) return Parser(i,state()); } +template +prefix_ Parser senf::PacketParserBase::parse(Arg const & arg, data_iterator i) + const +{ + return Parser(arg, i, state()); +} + template prefix_ Parser senf::PacketParserBase::parse(size_type n) const @@ -49,6 +56,13 @@ prefix_ Parser senf::PacketParserBase::parse(size_type n) return Parser(boost::next(i(),n),state()); } +template +prefix_ Parser senf::PacketParserBase::parse(Arg const & arg, size_type n) + const +{ + return Parser(arg, boost::next(i(),n), state()); +} + /////////////////////////////////////////////////////////////////////////// // namespace members diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh index c85ff2f..1e389da 100644 --- a/Packets/PacketParser.hh +++ b/Packets/PacketParser.hh @@ -328,11 +328,22 @@ namespace senf { beginning at \a i. Automatically passes \a state() to the new parser. */ + template Parser parse(Arg const & arg, data_iterator i) const; + ///< Create sub-parser + /**< This is like parse(data_iterator), however it passes + the extra argument \a arg to the \a Parser + constructor. */ + template Parser parse(size_type n) const; ///< Create sub-parser /**< Creates a new instance of \a Parser to parse data * beginning at i() + \a n. Automatically passes \a state() to the new parser. */ + template Parser parse(Arg const & arg, size_type n) const; + ///< Create sub-parser + /**< This is like parse(size_type), however it passes the + extra argument \a arg to the \a Parser constructor. */ + void defaultInit() const; ///< Default implementation /**< This is just an empty default implementation. Re-implement this member in your own @@ -370,6 +381,7 @@ namespace senf { PacketParserBase::size_type bytes(Parser p); namespace detail { template class ParserInitBytes; } + namespace detail { template class ParserIsFixed; } /** \brief Return number of bytes to allocate to new object of given type @@ -390,6 +402,10 @@ namespace senf { struct init_bytes : public detail::ParserInitBytes {}; + template + struct is_fixed : public detail::ParserIsFixed + {}; + # ifndef DOXYGEN template typename boost::enable_if< diff --git a/Packets/PacketParser.ih b/Packets/PacketParser.ih index 450bc03..4596ea8 100644 --- a/Packets/PacketParser.ih +++ b/Packets/PacketParser.ih @@ -84,6 +84,18 @@ namespace detail { struct ParserInitBytes : public ParserInitBytes_Choose(0))> {}; + template + struct ParserIsFixed_Choose + : public boost::false_type {}; + + template + struct ParserIsFixed_Choose + : public boost::true_type {}; + + template + struct ParserIsFixed + : public ParserIsFixed_Choose(0))> {}; + # endif }} diff --git a/Packets/Packets.hh b/Packets/Packets.hh index 6cd5626..90036c0 100644 --- a/Packets/Packets.hh +++ b/Packets/Packets.hh @@ -38,6 +38,7 @@ #include "PacketParser.hh" #include "SafeIterator.hh" #include "ArrayParser.hh" +#include "AuxParser.hh" #include "ListParser.hh" #include "ListBParser.hh" #include "ListNParser.hh" @@ -59,6 +60,7 @@ #include "SafeIterator.hh" #include "ArrayParser.hh" #include "IntParser.hh" +#include "AuxParser.hh" #include "ListParser.hh" #include "ListBParser.hh" #include "ListNParser.hh" diff --git a/Packets/ParseHelpers.ih b/Packets/ParseHelpers.ih index 7e67282..d936097 100644 --- a/Packets/ParseHelpers.ih +++ b/Packets/ParseHelpers.ih @@ -50,6 +50,7 @@ SENF_MPL_SLOT_DEF_ZERO(init_bytes); \ SENF_MPL_SLOT_DEF_ZERO(bit); \ SENF_MPL_SLOT_DEF_ZERO(bitfield_size); \ + SENF_MPL_SLOT_DEF_ZERO(group); \ void init_chain(senf::mpl::rv<0>*) const {} \ size_type field_offset_(senf::mpl::rv<0>*) const { return 0; } \ public: @@ -94,6 +95,11 @@ # # define SENF_PARSER_FIELD_I(name, type, ofstype, rwtype, access) \ access: \ + SENF_PARSER_FIELD_SETUP_I(name, type, ofstype, rwtype, access) \ + BOOST_PP_CAT(SENF_PARSER_I_FIELD_VAL_, rwtype) (name, type, access) \ + public: +# +# define SENF_PARSER_FIELD_SETUP_I(name, type, ofstype, rwtype, access) \ SENF_PARSER_I_BITFIELD_RESET() \ SENF_PARSER_I_FIELD_INTRO(name, type, access) \ BOOST_PP_CAT(SENF_PARSER_I_FIELD_INIT_, rwtype) (name, type, access) \ @@ -102,9 +108,8 @@ name, type, \ BOOST_PP_CAT(SENF_PARSER_I_SIZE_, ofstype) (name, type), \ BOOST_PP_CAT(SENF_PARSER_I_INITBYTES_, ofstype) (name, type), \ - access ) \ - BOOST_PP_CAT(SENF_PARSER_I_FIELD_VAL_, rwtype) (name, type, access) \ - public: + BOOST_PP_CAT(SENF_PARSER_I_ISVAR_, ofstype) (name, type), \ + access ) # # //////////////////////////////////////// # // SENF_PARSER_I_FIELD_INTRO @@ -149,14 +154,16 @@ # //////////////////////////////////////// # // SENF_PARSER_I_ADVANCE_OFS_* # -# // Can't call 'name()' here if 'name' is an ro field ... -# define SENF_PARSER_I_SIZE_var(name, type) senf::bytes(parse(BOOST_PP_CAT(name,_offset)())) +# define SENF_PARSER_I_SIZE_var(name, type) senf::bytes(BOOST_PP_CAT(name, _)()) # define SENF_PARSER_I_INITBYTES_var(name, type) senf::init_bytes::value # # define SENF_PARSER_I_SIZE_fix(name, type) type::fixed_bytes # define SENF_PARSER_I_INITBYTES_fix(name, type) void # -# define SENF_PARSER_I_ADVANCE_OFS_var(name, type, size, isize, access) \ +# define SENF_PARSER_I_ISVAR_fix(name, type) 0 +# define SENF_PARSER_I_ISVAR_var(name, type) (senf::is_fixed::value?0:1) +# +# define SENF_PARSER_I_ADVANCE_OFS_var(name, type, size, isize, isvar, access) \ size_type BOOST_PP_CAT(name, _next_offset)() const { \ return BOOST_PP_CAT(name,_offset)() + size; \ } \ @@ -167,9 +174,11 @@ return BOOST_PP_CAT(name, _next_offset)(); \ } \ SENF_MPL_SLOT_SET(init_bytes, BOOST_PP_CAT(name,_next_init_bytes)); \ + static size_type const BOOST_PP_CAT(name, _group) = SENF_MPL_SLOT_GET(group) + isvar; \ + SENF_MPL_SLOT_SET(group, BOOST_PP_CAT(name, _group)); \ access: # -# define SENF_PARSER_I_ADVANCE_OFS_fix(name, type, size, isize, access) \ +# define SENF_PARSER_I_ADVANCE_OFS_fix(name, type, size, isize, isvar, access) \ static size_type const BOOST_PP_CAT(name, _next_offset) = \ BOOST_PP_CAT(name, _offset) + size; \ private: \ @@ -180,8 +189,13 @@ # // SENF_PARSER_I_FIELD_VAL_* # # define SENF_PARSER_I_FIELD_VAL_rw(name, type, access) \ - BOOST_PP_CAT(name, _t) name() const { \ + private: \ + BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const { \ return parse( SENF_PARSER_OFFSET(name) ); \ + } \ + access: \ + BOOST_PP_CAT(name, _t) name() const { \ + return BOOST_PP_CAT(name,_)(); \ } # # define SENF_PARSER_I_FIELD_VAL_ro(name, type, access) \ @@ -207,7 +221,7 @@ SENF_PARSER_I_FIELD_INTRO(name, type, public) \ SENF_PARSER_I_FIELD_INIT_ro(name, type, public) \ BOOST_PP_CAT(SENF_PARSER_I_FIELD_OFS_, ofstype) (name, type, public) \ - BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) (name, type, size, isize, public) \ + BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) (name, type, size, isize, 1, public) \ BOOST_PP_CAT(name, _t) name() const # # /////////////////////////////////////////////////////////////////////////// @@ -253,6 +267,7 @@ BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) ( \ name, type, \ BOOST_PP_CAT(name, _t)::fixed_bytes, BOOST_PP_CAT(name, _t)::fixed_bytes, \ + 0, \ access) \ private: \ SENF_MPL_SLOT_SET(bitfield_size, BOOST_PP_CAT(name, _t)::fixed_bytes); \ @@ -297,7 +312,8 @@ SENF_PARSER_I_FIELD_INTRO(name, void, private) \ SENF_PARSER_I_FIELD_INIT_ro(name, void, private) \ BOOST_PP_CAT(SENF_PARSER_I_FIELD_OFS_, ofstype) (name, type, access) \ - BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) (name, void, bytes, ibytes, private) \ + BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) (name, void, bytes, ibytes, 1, \ + private) \ public: # # /////////////////////////////////////////////////////////////////////////// @@ -359,7 +375,7 @@ SENF_PARSER_I_FIELD_INTRO(name, void, access) \ SENF_PARSER_I_FIELD_INIT_ro(name, void, access) \ BOOST_PP_CAT(SENF_PARSER_I_FIELD_OFS_, ofstype) (name, type, access) \ - BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) (name, void, 0, 0,access) \ + BOOST_PP_CAT(SENF_PARSER_I_ADVANCE_OFS_, ofstype) (name, void, 0, 0, 0, access) \ public: # # /////////////////////////////////////////////////////////////////////////// @@ -375,7 +391,7 @@ # define SENF_PARSER_FIXED_OFFSET_var(name) BOOST_PP_CAT(name, _init_bytes) # # /////////////////////////////////////////////////////////////////////////// -# // SENF_PARSER_FIXED_OFFSET_* +# // SENF_PARSER_CURRENT_FIXED_OFFSET_* # # define SENF_PARSER_CURRENT_FIXED_OFFSET_fix() SENF_MPL_SLOT_GET(offset) # define SENF_PARSER_CURRENT_FIXED_OFFSET_var() SENF_MPL_SLOT_GET(init_bytes) @@ -404,6 +420,91 @@ public: \ void init() const { init(0); } # +# /////////////////////////////////////////////////////////////////////////// +# // SENF_PARSER_REQUIRE_VAR +# +# define SENF_PARSER_REQUIRE_VAR(description) \ + BOOST_PP_CAT(SENF_PARSER_REQUIRE_VAR_, SENF_PARSER_TYPE)(description) +# +# define SENF_PARSER_REQUIRE_VAR_var(description) +# +# define SENF_PARSER_REQUIRE_VAR_fix(description) \ + typedef BOOST_PP_CAT( PARSER_ERROR__, \ + BOOST_PP_CAT(description, _not_allowed_in_fixed_parser) ) \ + BOOST_PP_CAT(errsym_, __LINE__); +# +# /////////////////////////////////////////////////////////////////////////// +# // SENF_PARSER_COLLECTION_I +# + namespace senf { namespace detail { namespace auxtag { struct none {}; } } } +# +# define SENF_PARSER_COLLECTION_I(access, name, aux, 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 \ + >::type BOOST_PP_CAT(name, _collection_t); \ + access: \ + SENF_PARSER_FIELD_SETUP_I( name, \ + BOOST_PP_CAT(name, _collection_t), \ + SENF_PARSER_TYPE, \ + rw, \ + access ) \ + BOOST_PP_CAT(SENF_PARSER_COLLECTION_VAL_, SENF_PARSER_TYPE)(name, aux, access) \ + public: +# +# define SENF_PARSER_COLLECTION_AUXTYPE_var(name, aux) \ + static bool const BOOST_PP_CAT(name, _aux_fixed) = \ + (SENF_MPL_SLOT_GET(group) - BOOST_PP_CAT(aux, _group) == 0); +# +# define SENF_PARSER_COLLECTION_AUXTYPE_fix(name, aux) +# + namespace senf { namespace detail { + template struct DynamicAuxParserPolicy; + template struct FixedAuxParserPolicy; + template + struct ParserAuxPolicySelect + { typedef senf::detail::DynamicAuxParserPolicy type; }; + template + struct ParserAuxPolicySelect + { typedef senf::detail::FixedAuxParserPolicy type; }; + }}; +# +# define SENF_PARSER_COLLECTION_AUX_I_var(name, aux) \ + senf::detail::ParserAuxPolicySelect< BOOST_PP_CAT(aux, _t), \ + SENF_PARSER_CURRENT_FIXED_OFFSET() \ + - SENF_PARSER_FIXED_OFFSET(aux), \ + BOOST_PP_CAT(name, _aux_fixed) >::type +# +# define SENF_PARSER_COLLECTION_AUX_I_fix(name, aux) \ + senf::detail::FixedAuxParserPolicy< BOOST_PP_CAT(aux, _t), \ + 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 \ + { return BOOST_PP_CAT(name, _)(); } +# +# define SENF_PARSER_COLLECTION_VAL_fix(name,aux,access) \ + private: \ + BOOST_PP_CAT(name, _t) BOOST_PP_CAT(name, _)() const \ + { return parse( SENF_PARSER_OFFSET(name) ); } \ + access: \ + BOOST_PP_CAT(name, _t) name() const \ + { return BOOST_PP_CAT(name, _)(); } +# # ////////////////////////////////ih.e/////////////////////////////////////// # endif # diff --git a/Packets/VectorParser.ct b/Packets/VectorParser.ct index 7d15db4..fb89187 100644 --- a/Packets/VectorParser.ct +++ b/Packets/VectorParser.ct @@ -37,7 +37,7 @@ template prefix_ void senf::VectorParser::init() const { - sizer_.init(i(),state()); + aux(i(), state()) = 0; iterator i (begin()); iterator const e (end()); for (; i!=e; ++i) diff --git a/Packets/VectorParser.cti b/Packets/VectorParser.cti index 4ecf3bb..430427f 100644 --- a/Packets/VectorParser.cti +++ b/Packets/VectorParser.cti @@ -33,77 +33,77 @@ /////////////////////////////////////////////////////////////////////////// // senf::VectorParser -template -prefix_ senf::VectorParser::VectorParser(data_iterator i, state_type s) - : PacketParserBase(i,s), sizer_() +template +prefix_ senf::VectorParser::VectorParser(data_iterator i, state_type s) + : PacketParserBase(i,s), AuxPolicy() {} -template -prefix_ senf::VectorParser::VectorParser(Sizer sizer, data_iterator i, - state_type s) - : PacketParserBase(i,s), sizer_(sizer) +template +prefix_ senf::VectorParser::VectorParser(AuxPolicy policy, + data_iterator i, state_type s) + : PacketParserBase(i,s), AuxPolicy(policy) {} -template -prefix_ typename senf::VectorParser::size_type -senf::VectorParser::bytes() +template +prefix_ typename senf::VectorParser::size_type +senf::VectorParser::bytes() const { - return size()*ElementParser::fixed_bytes + sizer_.bytes(i(),state()); + return size()*ElementParser::fixed_bytes + AuxPolicy::aux_bytes; } // Container interface -template -prefix_ typename senf::VectorParser::size_type -senf::VectorParser::size() +template +prefix_ typename senf::VectorParser::size_type +senf::VectorParser::size() const { - return sizer_.size(i(),state()); + return aux(i(),state()); } -template -prefix_ bool senf::VectorParser::empty() +template +prefix_ bool senf::VectorParser::empty() const { return size()==0; } -template -prefix_ typename senf::VectorParser::iterator -senf::VectorParser::begin() +template +prefix_ typename senf::VectorParser::iterator +senf::VectorParser::begin() const { - return iterator(sizer_.begin(i(),state()),state()); + return iterator(adjust(i(),state()),state()); } -template -prefix_ typename senf::VectorParser::iterator -senf::VectorParser::end() +template +prefix_ typename senf::VectorParser::iterator +senf::VectorParser::end() const { return boost::next(begin(),size()); } -template -prefix_ typename senf::VectorParser::value_type -senf::VectorParser::operator[](difference_type i) +template +prefix_ typename senf::VectorParser::value_type +senf::VectorParser::operator[](difference_type i) const { return begin()[i]; } -template -prefix_ typename senf::VectorParser::value_type -senf::VectorParser::front() +template +prefix_ typename senf::VectorParser::value_type +senf::VectorParser::front() const { return begin()[0]; } -template -prefix_ typename senf::VectorParser::value_type -senf::VectorParser::back() +template +prefix_ typename senf::VectorParser::value_type +senf::VectorParser::back() const { return begin()[size()-1]; @@ -111,51 +111,51 @@ senf::VectorParser::back() // Mutators -template +template template -prefix_ void senf::VectorParser::push_back(Value value, size_type n) +prefix_ void senf::VectorParser::push_back(Value value, size_type n) const { container c (*this); c.push_back(value,n); } -template -prefix_ void senf::VectorParser::push_back_space(size_type n) +template +prefix_ void senf::VectorParser::push_back_space(size_type n) const { container c (*this); c.push_back_space(n); } -template +template template -prefix_ void senf::VectorParser::push_front(Value value, size_type n) +prefix_ void senf::VectorParser::push_front(Value value, size_type n) const { container c (*this); c.push_front(value,n); } -template -prefix_ void senf::VectorParser::push_front_space(size_type n) +template +prefix_ void senf::VectorParser::push_front_space(size_type n) const { container c (*this); c.push_front_space(n); } -template -prefix_ void senf::VectorParser::resize(size_type n) +template +prefix_ void senf::VectorParser::resize(size_type n) const { container c (*this); c.resize(n); } -template +template template -prefix_ void senf::VectorParser::resize(size_type n, Value value) +prefix_ void senf::VectorParser::resize(size_type n, Value value) const { container c (*this); @@ -163,48 +163,6 @@ prefix_ void senf::VectorParser::resize(size_type n, Value } /////////////////////////////////////////////////////////////////////////// -// senf::SimpleSizeParser - -template -prefix_ typename senf::detail::VectorNParser_Sizer::size_type -senf::detail::VectorNParser_Sizer::size(iterator i, state_type s) - const -{ - return SizeParser(boost::prior(i, Distance), s).value(); -} - -template -prefix_ void senf::detail::VectorNParser_Sizer::size(iterator i, - state_type s, - size_type v) - const -{ - SizeParser(boost::prior(i, Distance), s).value(v); -} - -template -prefix_ typename senf::detail::VectorNParser_Sizer::iterator -senf::detail::VectorNParser_Sizer::begin(iterator i, state_type s) - const -{ - return i; -} - -template -prefix_ typename senf::detail::VectorNParser_Sizer::size_type -senf::detail::VectorNParser_Sizer::bytes(iterator i, state_type s) - const -{ - return 0; -} - -template -prefix_ void senf::detail::VectorNParser_Sizer::init(iterator i, - state_type s) - const -{} - -/////////////////////////////////////////////////////////////////////////// // senf::VectorParser_wrapper // structors and default members @@ -212,65 +170,65 @@ prefix_ void senf::detail::VectorNParser_Sizer::init(iterat // hm ... be careful here ! the data() member is called in an incompletely intitialized // instance. However, data() only depends on state_ which is initialized before the call. YOU MUST // NOT CHANGE THE ORDERING OF THE DATA MEMBERS -template -prefix_ senf::VectorParser_Container:: +template +prefix_ senf::VectorParser_Container:: VectorParser_Container(parser_type const & vector) - : sizer_ (vector.sizer_), state_ (vector.state()), + : AuxPolicy(vector), state_ (vector.state()), i_ (std::distance(data().begin(),vector.i())) {} // accessors -template -prefix_ typename senf::VectorParser_Container::size_type -senf::VectorParser_Container::size() +template +prefix_ typename senf::VectorParser_Container::size_type +senf::VectorParser_Container::size() const { - return sizer_.size(i(),state()); + return aux(i(),state()); } -template -prefix_ bool senf::VectorParser_Container::empty() +template +prefix_ bool senf::VectorParser_Container::empty() const { return size() == 0; } -template -prefix_ typename senf::VectorParser_Container::iterator -senf::VectorParser_Container::begin() +template +prefix_ typename senf::VectorParser_Container::iterator +senf::VectorParser_Container::begin() const { - return iterator(sizer_.begin(i(),state()),state()); + return iterator(adjust(i(),state()),state()); } -template -prefix_ typename senf::VectorParser_Container::iterator -senf::VectorParser_Container::end() +template +prefix_ typename senf::VectorParser_Container::iterator +senf::VectorParser_Container::end() const { return boost::next(begin(),size()); } -template -prefix_ typename senf::VectorParser_Container::value_type -senf::VectorParser_Container::operator[](difference_type i) +template +prefix_ typename senf::VectorParser_Container::value_type +senf::VectorParser_Container::operator[](difference_type i) const { return begin()[i]; } -template -prefix_ typename senf::VectorParser_Container::value_type -senf::VectorParser_Container::front() +template +prefix_ typename senf::VectorParser_Container::value_type +senf::VectorParser_Container::front() const { return begin()[0]; } -template -prefix_ typename senf::VectorParser_Container::value_type -senf::VectorParser_Container::back() +template +prefix_ typename senf::VectorParser_Container::value_type +senf::VectorParser_Container::back() const { return begin()[size()-1]; @@ -278,109 +236,109 @@ senf::VectorParser_Container::back() // Mutators -template +template template -prefix_ void senf::VectorParser_Container::insert(iterator pos, +prefix_ void senf::VectorParser_Container::insert(iterator pos, Value const & t) { *shift(pos) << t; } -template -prefix_ void senf::VectorParser_Container::erase(iterator pos, size_type n) +template +prefix_ void senf::VectorParser_Container::erase(iterator pos, size_type n) { data().erase(pos.raw(),boost::next(pos.raw(),n*ElementParser::fixed_bytes)); setSize(size()-n); } -template -prefix_ void senf::VectorParser_Container::erase(iterator f, iterator l) +template +prefix_ void senf::VectorParser_Container::erase(iterator f, iterator l) { erase(f,std::distance(f,l)); } -template -prefix_ void senf::VectorParser_Container::clear() +template +prefix_ void senf::VectorParser_Container::clear() { erase(begin(),end()); } -template +template template -prefix_ void senf::VectorParser_Container::push_back(Value value, +prefix_ void senf::VectorParser_Container::push_back(Value value, size_type n) { insert(end(),n,value); } -template -prefix_ void senf::VectorParser_Container::push_back_space(size_type n) +template +prefix_ void senf::VectorParser_Container::push_back_space(size_type n) { shift(end(),n); } -template +template template -prefix_ void senf::VectorParser_Container::push_front(Value value, +prefix_ void senf::VectorParser_Container::push_front(Value value, size_type n) { insert(begin(),n,value); } -template -prefix_ void senf::VectorParser_Container::push_front_space(size_type n) +template +prefix_ void senf::VectorParser_Container::push_front_space(size_type n) { shift(begin(),n); } // Parser interface -template -prefix_ typename senf::VectorParser_Container::parser_type -senf::VectorParser_Container::parser() +template +prefix_ typename senf::VectorParser_Container::parser_type +senf::VectorParser_Container::parser() const { return parser_type(i(),state()); } -template -prefix_ typename senf::VectorParser_Container::data_iterator -senf::VectorParser_Container::i() +template +prefix_ typename senf::VectorParser_Container::data_iterator +senf::VectorParser_Container::i() const { return boost::next(data().begin(),i_); } -template -prefix_ typename senf::VectorParser_Container::state_type -senf::VectorParser_Container::state() +template +prefix_ typename senf::VectorParser_Container::state_type +senf::VectorParser_Container::state() const { return state_; } -template +template prefix_ senf::PacketData & -senf::VectorParser_Container::data() +senf::VectorParser_Container::data() const { return *state_; } -template -prefix_ typename senf::VectorParser_Container::size_type -senf::VectorParser_Container::bytes() +template +prefix_ typename senf::VectorParser_Container::size_type +senf::VectorParser_Container::bytes() const { - return size()*ElementParser::fixed_bytes + sizer_.bytes(i(),state()); + return size()*ElementParser::fixed_bytes + AuxPolicy::aux_bytes; } // private members -template -prefix_ void senf::VectorParser_Container::setSize(size_type value) +template +prefix_ void senf::VectorParser_Container::setSize(size_type value) { - sizer_.size(i(),state(),value); + aux(i(),state()).value(value); } /////////////////////////////cti.e/////////////////////////////////////// diff --git a/Packets/VectorParser.hh b/Packets/VectorParser.hh index b135cd8..ac7a15a 100644 --- a/Packets/VectorParser.hh +++ b/Packets/VectorParser.hh @@ -33,9 +33,9 @@ #include #include "PacketParser.hh" #include "ArrayParser.hh" // for ArrayParser_iterator +#include "AuxParser.hh" // for the AuxPolicies //#include "VectorParser.mpp" -#include "VectorParser.ih" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { @@ -61,11 +61,13 @@ namespace senf { \see ExampleVectorPolicy \ingroup parsecollection */ - template - struct VectorParser : public PacketParserBase + template + struct VectorParser + : public PacketParserBase, + private AuxPolicy { VectorParser(data_iterator i, state_type s); - VectorParser(Sizer sizer, data_iterator i, state_type s); + VectorParser(AuxPolicy policy, data_iterator i, state_type s); ///< Additional sizer specific constructor /**< This constructor may be used, if the sizer needs additional parameters. */ @@ -73,7 +75,7 @@ namespace senf { size_type bytes() const; void init() const; - static const size_type init_bytes = Sizer::init_bytes; + static const size_type init_bytes = AuxPolicy::aux_bytes; /////////////////////////////////////////////////////////////////////////// // Container interface @@ -81,7 +83,7 @@ namespace senf { typedef ElementParser value_type; typedef detail::ArrayParser_iterator iterator; typedef iterator const_iterator; - typedef VectorParser_Container container; + typedef VectorParser_Container container; size_type size() const; bool empty() const; @@ -107,33 +109,8 @@ namespace senf { template void resize (size_type n, Value value) const; private: - Sizer sizer_; - friend class VectorParser_Container; - }; - - /** \brief Vector with prefix sizing - - This is a 'template typedef'. It defines a vector with a directly preceding size - field holding the number of vector elements. The size field is considered part of the - vector. - \code - // Define MyVector as a vector of 16bit unsigned elements with a directly preceding - // 8bit unsigned size field - typedef senf::VectorNParser::parser MyVector; - \endcode - - \param ElementParser \e fixed-size parser for parsing the vector elements - \param SizeParser parser for parsing the vector size (number of elements) - - \see VectorParser - \ingroup parsecollection - */ - template - struct VectorNParser - { - typedef VectorParser< ElementParser, - detail::VectorNParser_Sizer > parser; + friend class VectorParser_Container; }; /** \brief Define VectorNParser field @@ -145,7 +122,7 @@ namespace senf { // The size field should be declared private (size is accessible via the vector) SENF_PARSER_PRIVATE_FIELD ( vec_size_, senf::UInt16Parser ); // Define the vector, here it has 32bit unsigned integer elements - SENF_PARSER_VEC_N ( vec, _vec_size, senf::UInt32Parser ); + SENF_PARSER_VEC_N ( vec, vec_size_, senf::UInt32Parser ); \endcode \param[in] name field name @@ -166,6 +143,14 @@ namespace senf { # define SENF_PARSER_PRIVATE_VEC_N(name, size, elt_type) \ SENF_PARSER_VEC_N_I(SENF_PARSER_PRIVATE_FIELD, name, size, elt_type) +# define SENF_PARSER_VECTOR(name, size, elt_type) \ + SENF_PARSER_VECTOR_I(public, name, size, elt_type) + +# define SENF_PARSER_PRIVATE_VECTOR(name, size, elt_type) \ + SENF_PARSER_VECTOR_I(private, name, size, elt_type) + + + /** \brief VectorParser container wrapper This is the container wrapper used for vector parsers. The container wrapper will stay valid @@ -184,14 +169,15 @@ namespace senf { \see VectorParser */ - template + template class VectorParser_Container + : private AuxPolicy { public: /////////////////////////////////////////////////////////////////////////// // Types - typedef VectorParser parser_type; + typedef VectorParser parser_type; typedef PacketParserBase::data_iterator data_iterator; typedef PacketParserBase::size_type size_type; typedef PacketParserBase::difference_type difference_type; @@ -276,7 +262,6 @@ namespace senf { private: void setSize(size_type value); - Sizer sizer_; state_type state_; size_type i_; }; diff --git a/Packets/VectorParser.ih b/Packets/VectorParser.ih index c7b4340..6da8f49 100644 --- a/Packets/VectorParser.ih +++ b/Packets/VectorParser.ih @@ -33,38 +33,34 @@ namespace senf { namespace detail { - /** \brief Internal: Sizer implementing prefix sizing - - \internal +# define SENF_PARSER_VEC_N_I(field, name, size, elt_type) \ + typedef senf::VectorParser< \ + elt_type, \ + senf::detail::FixedAuxParserPolicy< BOOST_PP_CAT(size, _t), \ + SENF_PARSER_CURRENT_FIXED_OFFSET() \ + - SENF_PARSER_FIXED_OFFSET(size) > \ + > BOOST_PP_CAT(name, _vec_t); \ + field( name, BOOST_PP_CAT(name, _vec_t) ) - This is the sizer policy used by VectorNParser - */ - template - struct VectorNParser_Sizer + template + struct VectorParserTraits { - typedef PacketParserBase::size_type size_type; - typedef PacketParserBase::data_iterator iterator; - typedef PacketParserBase::state_type state_type; - - static const size_type init_bytes = 0; - - size_type size (iterator i, state_type s) const; - void size (iterator i, state_type s, size_type v) const; - iterator begin (iterator i, state_type s) const; - size_type bytes (iterator i, state_type s) const; - void init (iterator i, state_type s) const; + template + struct parser { + typedef senf::VectorParser type; + }; }; -# define SENF_PARSER_VEC_N_I(field, name, size, elt_type) \ - typedef senf::VectorNParser< elt_type, \ - BOOST_PP_CAT(size, _t), \ - SENF_PARSER_CURRENT_FIXED_OFFSET() \ - - SENF_PARSER_FIXED_OFFSET(size) \ - >::parser BOOST_PP_CAT(name, _vec_t); \ - field( name, BOOST_PP_CAT(name, _vec_t) ) -}} +# define SENF_PARSER_VECTOR_I(access, name, size, elt_type) \ + SENF_PARSER_REQUIRE_VAR(vector) \ + SENF_PARSER_COLLECTION_I( access, \ + name, \ + size, \ + senf::detail::VectorParserTraits ) +}} + ///////////////////////////////ih.e//////////////////////////////////////// #endif diff --git a/Packets/VectorParser.test.cc b/Packets/VectorParser.test.cc index ef7cffe..b51b392 100644 --- a/Packets/VectorParser.test.cc +++ b/Packets/VectorParser.test.cc @@ -48,7 +48,7 @@ BOOST_AUTO_UNIT_TEST(VectorParser) senf::PacketInterpreterBase::ptr p (senf::PacketInterpreter::create(data)); typedef senf::VectorParser< senf::UInt16Parser, - senf::detail::VectorNParser_Sizer + senf::detail::FixedAuxParserPolicy > UInt16VectorParser; { @@ -123,7 +123,7 @@ BOOST_AUTO_UNIT_TEST(VectorParser_wrapper) senf::PacketInterpreterBase::ptr p (senf::PacketInterpreter::create(data)); typedef senf::VectorParser< senf::UInt16Parser, - senf::detail::VectorNParser_Sizer + senf::detail::FixedAuxParserPolicy > UInt16VectorParser; UInt16VectorParser v (boost::next(p->data().begin(),1), &p->data()); UInt16VectorParser::container w (v); @@ -172,6 +172,74 @@ BOOST_AUTO_UNIT_TEST(VectorParser_wrapper) BOOST_CHECK_EQUAL( w.parser().size(), 0u ); } +BOOST_AUTO_UNIT_TEST(dynamicPolicyVector) +{ + unsigned char data[] = { 0x03, // size + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // data + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25 }; + senf::PacketInterpreterBase::ptr p (senf::PacketInterpreter::create(data)); + + typedef senf::VectorParser< + senf::UInt16Parser, + senf::detail::DynamicAuxParserPolicy + > UInt16VectorParser; + + UInt16VectorParser v (senf::UInt8Parser(p->data().begin(), &p->data()), + boost::next(p->data().begin(),1), &p->data()); + UInt16VectorParser::container w (v); + + BOOST_CHECK_EQUAL( v.size(), 3u ); + BOOST_CHECK_EQUAL( w.size(), 3u ); + + BOOST_CHECK_EQUAL( v[0], 0x1011 ); + BOOST_CHECK_EQUAL( v[2], 0x1415 ); + + BOOST_CHECK_EQUAL( w[0], 0x1011 ); + BOOST_CHECK_EQUAL( w[2], 0x1415 ); +} + +namespace { + + struct TestVectorParser + : 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_VECTOR ( vec1 , size1, senf::UInt16Parser ); + SENF_PARSER_VECTOR ( vec2 , size2, senf::UInt16Parser ); + + SENF_PARSER_FINALIZE( TestVectorParser ); + }; + +} + +BOOST_AUTO_UNIT_TEST(vectorMacro) +{ + unsigned char data[] = { 0x03, // size1 + 0x02, // size2 + 0x01, 0x02, 0x03, 0x04, // dummy + 0x05, 0x06, // vec1[0] + 0x07, 0x08, // vec1[1] + 0x09, 0x0A, // vec1[2] + 0x0B, 0x0C, // vec2[0] + 0x0D, 0x0E }; // vec2[1] + + senf::DataPacket p (senf::DataPacket::create(data)); + TestVectorParser parser (p.data().begin(), &p.data()); + + BOOST_CHECK_EQUAL( parser.vec1().size(), 3u ); + BOOST_CHECK_EQUAL( parser.vec2().size(), 2u ); + BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u ); + BOOST_CHECK_EQUAL( parser.vec1()[0], 0x0506u ); + BOOST_CHECK_EQUAL( parser.vec1()[1], 0x0708u ); + BOOST_CHECK_EQUAL( parser.vec1()[2], 0x090Au ); + BOOST_CHECK_EQUAL( parser.vec2()[0], 0x0B0Cu ); + BOOST_CHECK_EQUAL( parser.vec2()[1], 0x0D0Eu ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_