From: pug Date: Thu, 27 Aug 2009 15:27:12 +0000 (+0000) Subject: added IPv6 Option Type List Parser and generic packet parser with raw data access... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=25976ed67c66d30811fa0a01043e50347e9d1e69;p=senf.git added IPv6 Option Type List Parser and generic packet parser with raw data access - unittests will follow closly git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1347 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Packets/DefaultBundle/IPv6ExtOptionType.cc b/senf/Packets/DefaultBundle/IPv6ExtOptionType.cc new file mode 100644 index 0000000..f8273ae --- /dev/null +++ b/senf/Packets/DefaultBundle/IPv6ExtOptionType.cc @@ -0,0 +1,44 @@ +// $Id: IPv6ExtOptionType.cc 869 2008-06-09 13:57:27Z pug $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp.Batroff@fokus.fraunhofer.de +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#include "IPv6ExtOptionType.hh" +// Custom includes + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ senf::PacketInterpreterBase::range senf::GenericOptTypeTLVPacketParser::value() const { + senf::PacketData::iterator begin (boost::next(data().begin(), 2 + optionLength() )); + return PacketInterpreterBase::range(begin, boost::next( begin, optionLength()) ); +} + + +// 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/senf/Packets/DefaultBundle/IPv6ExtOptionType.ct b/senf/Packets/DefaultBundle/IPv6ExtOptionType.ct new file mode 100644 index 0000000..3aa4f2a --- /dev/null +++ b/senf/Packets/DefaultBundle/IPv6ExtOptionType.ct @@ -0,0 +1,49 @@ +// $Id: IPv6ExtOptionType.ct 869 2008-06-09 13:57:27Z pug $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp.Batroff@fokus.fraunhofer.de +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +//#include "IPv6ExtOptionType.hh" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ void senf::GenericOptTypeTLVPacketParser::value(ForwardReadableRange const &range) +{ + safe_data_iterator si = resizeValueField( boost::size(range) ); + std::copy( boost::begin(range), boost::end(range), si); +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// comment-column: 40 +// End: diff --git a/senf/Packets/DefaultBundle/IPv6ExtOptionType.hh b/senf/Packets/DefaultBundle/IPv6ExtOptionType.hh new file mode 100644 index 0000000..ab8adf6 --- /dev/null +++ b/senf/Packets/DefaultBundle/IPv6ExtOptionType.hh @@ -0,0 +1,73 @@ +// $Id: IPv6ExtOptionType.hh 869 2008-06-09 13:57:27Z pug $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp.Batroff@fokus.fraunhofer.de +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_SENF_Packets_DefaultBundle_IPV6EXTOPTIONTYPE_HH_ +#define HH_SENF_Packets_DefaultBundle_IPV6EXTOPTIONTYPE_HH_1 + +// Custom includes +#include + +//#include "IPv6ExtOptionType.mpp" +///////////////////////////////hh.p//////////////////////////////////////// +namespace senf { + +class OptTypeTLVPacketParser: public PacketParserBase { +public: +# include SENF_PARSER() + SENF_PARSER_BITFIELD (altAction, 2, unsigned); + SENF_PARSER_BITFIELD (changeFlag, 1, unsigned); + SENF_PARSER_BITFIELD (optionType, 5, unsigned); + SENF_PARSER_FIELD (optionLength, UInt8Parser); + SENF_PARSER_FINALIZE (OptTypeTLVPacketParser); + +}; //OptTypeTLVPacketParser + +struct GenericOptTypeTLVPacketParser: public OptTypeTLVPacketParser { +# include SENF_PARSER() + SENF_PARSER_INHERIT ( OptTypeTLVPacketParser ); + SENF_PARSER_SKIP ( optionLength(), 0 ); + SENF_PARSER_FINALIZE ( GenericOptTypeTLVPacketParser ); + + senf::PacketInterpreterBase::range value() const; + + template + void value(ForwardReadableRange const &range); +}; + +} //namespace senf + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "IPv6ExtOptionType.cci" +#include "IPv6ExtOptionType.ct" +//#include "IPv6ExtOptionType.cti" +#endif /* HH_SENF_Packets_DefaultBundle_IPV6EXTOPTIONTYPE_HH_ */ + +// 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/senf/Packets/DefaultBundle/IPv6Extensions.hh b/senf/Packets/DefaultBundle/IPv6Extensions.hh index 197f5c9..5f6ba13 100644 --- a/senf/Packets/DefaultBundle/IPv6Extensions.hh +++ b/senf/Packets/DefaultBundle/IPv6Extensions.hh @@ -27,8 +27,12 @@ #define HH_SENF_Packets_DefaultBundle_IPv6Extensions_ 1 // Custom includes -#include "IPv6Packet.hh" +#include +#include +#include +#include +#include "IPv6Packet.hh" //#include "IPv6Extensions.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -225,13 +229,19 @@ The Type 0 Routing header has the following format: (RFC 2460) RFC 2460 */ -// Hop-By-Hop skeleton without Options +// Hop-By-Hop Extension Header struct IPv6PacketParserExtension_HopByHop : public PacketParserBase { # include SENF_PARSER() SENF_PARSER_FIELD ( nextHeader, UInt8Parser ); SENF_PARSER_FIELD ( headerLength, UInt8Parser ); - + + typedef detail::FixedAuxParserPolicy ListOptionTypeAuxPolicy; + typedef detail::ListOptionTypeParser_Policy ListOptionTypePolicy; + typedef ListParser ListOptionTypeParser; + + SENF_PARSER_FIELD ( options, ListOptionTypeParser); + SENF_PARSER_FINALIZE ( IPv6PacketParserExtension_HopByHop ); }; @@ -295,6 +305,7 @@ The Type 0 Routing header has the following format: (RFC 2460) // Destination Options skeleton without TLV-Options struct IPv6PacketParserExtension_Destination : public PacketParserBase { + # include SENF_PARSER() SENF_PARSER_FIELD ( nextHeader, UInt8Parser ); SENF_PARSER_FIELD ( headerLength, UInt8Parser ); diff --git a/senf/Packets/ListOptionTypeParser.cti b/senf/Packets/ListOptionTypeParser.cti new file mode 100644 index 0000000..125921d --- /dev/null +++ b/senf/Packets/ListOptionTypeParser.cti @@ -0,0 +1,230 @@ +// $Id: ListOptionTypeParser.cti 869 2008-06-09 13:57:27Z pug $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp.Batroff@fokus.fraunhofer.de +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief ListOptionTypeParser inline template implementation */ + +#include "ListOptionTypeParser.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::detail::ListOptionTypeParser_Policy + +template +prefix_ senf::detail::ListOptionTypeParser_Policy::ListOptionTypeParser_Policy() { +} + +template +template +prefix_ senf::detail::ListOptionTypeParser_Policy::ListOptionTypeParser_Policy(Arg const & arg) :AuxPolicy(arg) { +} + +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::size_type +senf::detail::ListOptionTypeParser_Policy::bytes(data_iterator i, state_type s) const { + return AuxPolicy::aux(i, s) + AuxPolicy::aux_bytes; +} + +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::size_type +senf::detail::ListOptionTypeParser_Policy::size(data_iterator i, state_type s) const { + parser_type p(*this, i, s); + container_type c(p); + return std::distance(c.begin(), c.end()); +} + +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::init(data_iterator i, state_type s) const { + AuxPolicy::aux(0, i, s); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::detail::ListOptionTypeParser_Policy + +//constructor +template +prefix_ senf::detail::ListOptionTypeParser_Policy::container_policy::container_policy(parser_policy const & p) : + AuxPolicy(p) { +} + +//destructor +template +prefix_ senf::detail::ListOptionTypeParser_Policy::container_policy::~container_policy() +{} + +//construct method +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::construct(container_type & c) { + data_iterator i = c.i(); + realAux_ = (AuxPolicy::aux(i, c.state()) * 8) + 6; + data_iterator e = i + realAux_; + for (n_ = 0; i != e; ++n_) { + unsigned int elByte = senf::bytes(ElementParser(i, c.state())); + if (((i + elByte) == e) && (i[0] == 0u || i[0] == 1u)) { //check wether last element is padding or not + realAux_ -= std::distance(i, e); + c.data().erase(i, e); //delete padding + e = i; //set end iterator + } else + std::advance(i, elByte); + } + // container_size_ = std::distance(i,e); + container_size_ = c.data().size(); //set actual size without padding +} + +//destruct method +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::destruct(container_type & c) { + // data_iterator i (AuxPolicy::adjust(parser_type::get(p).i(), parser_type::get(p).state())); + data_iterator i = c.i(); + data_iterator const e = i + realAux_; + unsigned int padBytes = (realAux_ % 8); + c.data().insert(e, padBytes, 0u); + if (padBytes > 0) { + if (padBytes > 1) { + e[0] = 1; + e[1] = padBytes - 2; + } else + e[0] = 0; + container_size_ += padBytes; + ++n_; + } + AuxPolicy::aux((realAux_ / 8 - 1), i, c.state()); +} + +//bytes() +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::container_policy::size_type +senf::detail::ListOptionTypeParser_Policy::container_policy::bytes(data_iterator i,state_type s) const { + return (realAux_ + 2); +} + +//size() +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::container_policy::size_type +senf::detail::ListOptionTypeParser_Policy::container_policy::size(data_iterator i,state_type s) const { + return n_; +} + +//init() +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::init(data_iterator i, state_type s) { + n_ = 0; + container_size_ = s->size(); + AuxPolicy::aux(0, i, s); +} + +//erase() +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::erase(container_type & c, data_iterator p) { + size_type b(senf::bytes(ElementParser(p, c.state()))); //length of parser + // AuxPolicy::aux( + // AuxPolicy::aux( c.i(), c.state()) -b, + // c.i(), + // c.state()); + realAux_ -= b; + --n_; + // The container will be reduced by b bytes directly after this call + container_size_ = c.data().size() - b; +} + +//insert() +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::insert(container_type & c, data_iterator p) { + size_type b(senf::bytes(ElementParser(p, c.state()))); + // AuxPolicy::aux( AuxPolicy::aux(c.i(), c.state())+b, c.i(), c.state()); + realAux_ += b; + ++n_; + container_size_ = c.data().size(); +} + +//update() +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::update(container_type const & c) const { + 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())))); + realAux_ = std::distance(i, j); + // aux( std::distance(i,j), c.i(), c.state() ); + container_size_ = c.data().size(); +} + +//setbegin() +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::container_policy::data_iterator +senf::detail::ListOptionTypeParser_Policy::container_policy::setBegin(container_type const & c, iterator_data & d) const { + return c.i(); + // return AuxPolicy::adjust(c.i(), c.state()); +} + +//setEnd() +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::container_policy::data_iterator +senf::detail::ListOptionTypeParser_Policy::container_policy::setEnd(container_type const & c, iterator_data & d) const { //wtf?? + return boost::next(AuxPolicy::adjust(c.i(), c.state()), aux(c.i(),c.state())); +} + +//setFromPosition() +template +prefix_ void +senf::detail::ListOptionTypeParser_Policy::container_policy::setFromPosition(container_type const & c, iterator_data & d, data_iterator p) const { +} + +//next() +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::container_policy::data_iterator +senf::detail::ListOptionTypeParser_Policy::container_policy::next(container_type const & c, iterator_data & d) const { + return boost::next(container_type::iterator::get(d).i(), senf::bytes(ElementParser(container_type::iterator::get(d).i(), c.state()))); +} + +//raw() +template +prefix_ typename senf::detail::ListOptionTypeParser_Policy::container_policy::data_iterator +senf::detail::ListOptionTypeParser_Policy::container_policy::raw(container_type const & c, iterator_data const & d) const { + return container_type::iterator::get(d).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/senf/Packets/ListOptionTypeParser.hh b/senf/Packets/ListOptionTypeParser.hh new file mode 100644 index 0000000..bec6708 --- /dev/null +++ b/senf/Packets/ListOptionTypeParser.hh @@ -0,0 +1,56 @@ +// $Id: ListOptionTypeParser.hh 965 2008-11-18 16:04:20Z pug $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp.Batroff@fokus.fraunhofer.de +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief ListOptionTypeParser public header */ + +#ifndef HH_SENF_Packets_ListOptionTypeParser_ +#define HH_SENF_Packets_ListOptionTypeParser_ 1 + +// Custom includes +#include "ListParser.hh" + +//#include "ListOptionTypeParser.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { + +} + +///////////////////////////////hh.e//////////////////////////////////////// +#endif +#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_ListOptionTypeParser_i_) +#define HH_SENF_Packets_ListOptionTypeParser_i_ +//#include "ListOptionTypeParser.cci" +//#include "ListOptionTypeParser.ct" +#include "ListOptionTypeParser.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/senf/Packets/ListOptionTypeParser.ih b/senf/Packets/ListOptionTypeParser.ih new file mode 100644 index 0000000..207bc76 --- /dev/null +++ b/senf/Packets/ListOptionTypeParser.ih @@ -0,0 +1,122 @@ +// $Id: ListOptionTypeParser.ih 965 2008-11-18 16:04:20Z pug $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp.Batroff@fokus.fraunhofer.de +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief ListOptionTypeParser internal header */ + +#ifndef IH_SENF_Packets_ListOptionTypeParser_ +#define IH_SENF_Packets_ListOptionTypeParser_ 1 + +// Custom includes +#include "ListParser.ih" + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace senf { + namespace detail { + + /** \brief Internal: ListPolicy defing the ListOptionTypeParser parser + \internal + \see \ref ListOptionTypeParser + */ + template + struct ListOptionTypeParser_Policy + : public AuxPolicy + { + struct container_policy; + + typedef PacketParserBase::data_iterator data_iterator; + typedef PacketParserBase::state_type state_type; + typedef PacketParserBase::size_type size_type; + + typedef ElementParser element_type; + typedef ListParser< ListOptionTypeParser_Policy > parser_type; + typedef ListParser_Container< container_policy > container_type; + + static const size_type init_bytes = AuxPolicy::aux_bytes; + + ListOptionTypeParser_Policy(); + template ListOptionTypeParser_Policy(Arg const & arg); + + 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: ListOptionTypeParser container/wrapper policy */ + struct container_policy + : public AuxPolicy + { + typedef PacketParserBase::data_iterator data_iterator; + typedef PacketParserBase::state_type state_type; + typedef PacketParserBase::size_type size_type; + + typedef ListOptionTypeParser_Policy parser_policy; + typedef typename parser_policy::element_type element_type; + typedef typename parser_policy::parser_type parser_type; + typedef typename parser_policy::container_type container_type; + + static const size_type init_bytes = parser_policy::init_bytes; + + container_policy(parser_policy const & p); + ~container_policy(); + 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); + + void erase (container_type & c, data_iterator p); + void insert (container_type & c, data_iterator p); + void update (container_type const & c) const; + + void destruct(container_type & c); + void construct(container_type & c); + + /** \brief Internal: ListOptionTypeParser specific iterator data */ + 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 realAux_; + mutable size_type container_size_; + }; + }; +} +} + +///////////////////////////////ih.e//////////////////////////////////////// +#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/senf/Packets/Packets.hh b/senf/Packets/Packets.hh index 087d012..a3d8ebd 100644 --- a/senf/Packets/Packets.hh +++ b/senf/Packets/Packets.hh @@ -42,6 +42,7 @@ #include "ListParser.hh" #include "ListBParser.hh" #include "ListNParser.hh" +#include "ListOptionTypeParser.hh" #include "VariantParser.hh" #include "VectorParser.hh" #include "ParseHelpers.hh" @@ -65,6 +66,7 @@ #include "ListParser.hh" #include "ListBParser.hh" #include "ListNParser.hh" +#include "ListOptionTypeParser.hh" #include "VariantParser.hh" #include "VectorParser.hh" #include "ParseHelpers.hh"