From: g0dil Date: Thu, 12 Nov 2009 22:31:35 +0000 (+0000) Subject: Utils/Console: Add std::map and std::set support X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=411b898d78f6b51341b95448c9b73c0f8ad074aa;p=senf.git Utils/Console: Add std::map and std::set support git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1519 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Utils/Console/STLSupport.ct b/senf/Utils/Console/STLSupport.ct index 18af3dc..569211e 100644 --- a/senf/Utils/Console/STLSupport.ct +++ b/senf/Utils/Console/STLSupport.ct @@ -33,48 +33,128 @@ #ifndef DOXYGEN -template -prefix_ void senf::console::SequenceArgumentTraits:: -parse(ParseCommandInfo::TokensRange const & tokens, type & out) +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::CollectionArgumentTraitsBase + +template +prefix_ std::string +senf::console::detail::CollectionArgumentTraitsBase::description() +{ + std::string type (prettyName(typeid(Collection))); + std::string::size_type e (type.find('<')); + if (e == std::string::npos) e = type.size(); + std::string::size_type b (type.rfind(':', e)); + if (b == std::string::npos) b = 0; else ++b; + return type.substr(b,e-b) + "<" + + ArgumentTraits::description() + ">"; +} + +template +prefix_ std::string +senf::console::detail::CollectionArgumentTraitsBase::str(Collection const & value) +{ + std::stringstream ss; + senf::console::format(value, ss); + return ss.str(); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::CollectionArgumentTraits + +template +prefix_ void senf::console::detail::CollectionArgumentTraits:: +parse(ParseCommandInfo::TokensRange const & tokens, Collection & out) { out.clear(); CheckedArgumentIteratorWrapper arg (tokens); while (arg) { - out.push_back(typename Sequence::value_type()); - senf::console::parse( *(arg++), out.back() ); + typename Collection::value_type v; + senf::console::parse( *(arg++), v ); + Adder::add(out,v); } } -template -prefix_ std::string senf::console::SequenceArgumentTraits::description() +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::CollectionReturnValueTraits + +template +prefix_ void +senf::console::detail::CollectionReturnValueTraits::format(Collection const & value, + std::ostream & os) { - std::string type (prettyName(typeid(Sequence))); + os << "("; + typename type::const_iterator i (value.begin()); + typename type::const_iterator const i_end (value.end()); + if (i != i_end) + for (;;) { + senf::console::format(*i, os); + if (++i == i_end) + break; + else + os << " "; + } + os << ")"; +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::MapArgumentTraits + +template +prefix_ void senf::console::detail::MapArgumentTraits:: +parse(ParseCommandInfo::TokensRange const & tokens, Collection & out) +{ + out.clear(); + CheckedArgumentIteratorWrapper arg (tokens); + while (arg) { + typename Collection::key_type key; + typename Collection::mapped_type data; + senf::console::parse( *(arg++), key ); + ParseCommandInfo::TokensRange sep (*(arg++)); + if (sep.size() != 1 || sep[0].type() != Token::OtherPunctuation || sep[0].value() != "=") + throw SyntaxErrorException("'=' expected"); + senf::console::parse( *(arg++), data ); + out.insert(std::make_pair(key,data)); + } +} + +template +prefix_ std::string senf::console::detail::MapArgumentTraits::description() +{ + std::string type (prettyName(typeid(Collection))); std::string::size_type e (type.find('<')); if (e == std::string::npos) e = type.size(); std::string::size_type b (type.rfind(':', e)); if (b == std::string::npos) b = 0; else ++b; return type.substr(b,e-b) + "<" - + ArgumentTraits::description() + ">"; + + ArgumentTraits::description() + "," + + ArgumentTraits::description() + ">"; } -template -prefix_ std::string senf::console::SequenceArgumentTraits::str(type const & value) +template +prefix_ std::string +senf::console::detail::MapArgumentTraits::str(Collection const & value) { std::stringstream ss; senf::console::format(value, ss); return ss.str(); } -template -prefix_ void senf::console::SequenceReturnValueTraits::format(type const & value, - std::ostream & os) +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::MapReturnValueTraits + +template +prefix_ void +senf::console::detail::MapReturnValueTraits::format(Collection const & value, + std::ostream & os) { os << "("; typename type::const_iterator i (value.begin()); typename type::const_iterator const i_end (value.end()); if (i != i_end) for (;;) { - senf::console::format(*i, os); + senf::console::format(i->first, os); + os << "="; + senf::console::format(i->second, os); if (++i == i_end) break; else @@ -83,6 +163,9 @@ prefix_ void senf::console::SequenceReturnValueTraits::format(type con os << ")"; } +/////////////////////////////////////////////////////////////////////////// +// senf::console::ArgumentTraits< std::pair > + template prefix_ void senf::console::ArgumentTraits< std::pair >:: parse(ParseCommandInfo::TokensRange const & tokens, type & out) @@ -108,6 +191,9 @@ prefix_ std::string senf::console::ArgumentTraits< std::pair >::str(type return ss.str(); } +/////////////////////////////////////////////////////////////////////////// +// senf::console::ReturnValueTraits< std::pair > + template prefix_ void senf::console::ReturnValueTraits< std::pair >::format(type const & value, std::ostream & os) diff --git a/senf/Utils/Console/STLSupport.cti b/senf/Utils/Console/STLSupport.cti new file mode 100644 index 0000000..6932f1a --- /dev/null +++ b/senf/Utils/Console/STLSupport.cti @@ -0,0 +1,65 @@ +// $Id$ +// +// Copyright (C) 2009 +// 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 STLSupport inline template implementation */ + +#include "STLSupport.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::PushBackFunctor + +template +prefix_ void senf::console::detail::PushBackFunctor::add(Sequence & seq, + ValueType const & value) +{ + seq.push_back(value); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::detail::InsertFunctor + +template +prefix_ void senf::console::detail::InsertFunctor::add(Collection & seq, + ValueType const & value) +{ + seq.insert(value); +} + +///////////////////////////////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/Utils/Console/STLSupport.hh b/senf/Utils/Console/STLSupport.hh index d459488..5523f21 100644 --- a/senf/Utils/Console/STLSupport.hh +++ b/senf/Utils/Console/STLSupport.hh @@ -32,6 +32,7 @@ #include "Traits.hh" //#include "STLSupport.mpp" +#include "STLSupport.ih" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { @@ -39,43 +40,68 @@ namespace console { #ifndef DOXYGEN - template - struct SequenceArgumentTraits - { - typedef Sequence type; - static bool const singleToken = false; - - static void parse(ParseCommandInfo::TokensRange const & tokens, type & out); - static std::string description(); - static std::string str(type const & value); - }; - - template - struct SequenceReturnValueTraits - { - typedef Sequence type; - - static void format(type const & value, std::ostream & os); - }; - template struct ArgumentTraits< std::vector > - : public SequenceArgumentTraits< std::vector > + : public detail::CollectionArgumentTraits< std::vector, + detail::PushBackFunctor > {}; template struct ReturnValueTraits< std::vector > - : public SequenceReturnValueTraits< std::vector > + : public detail::CollectionReturnValueTraits< std::vector > {}; template struct ArgumentTraits< std::list > - : public SequenceArgumentTraits< std::list > + : public detail::CollectionArgumentTraits< std::list, + detail::PushBackFunctor > {}; template struct ReturnValueTraits< std::list > - : public SequenceReturnValueTraits< std::list > + : public detail::CollectionReturnValueTraits< std::list > + {}; + + template + struct ArgumentTraits< std::set > + : public detail::CollectionArgumentTraits< std::set, + detail::InsertFunctor > + {}; + + template + struct ReturnValueTraits< std::set > + : public detail::CollectionReturnValueTraits< std::set > + {}; + + template + struct ArgumentTraits< std::multiset > + : public detail::CollectionArgumentTraits< std::multiset, + detail::InsertFunctor > + {}; + + template + struct ReturnValueTraits< std::multiset > + : public detail::CollectionReturnValueTraits< std::multiset > + {}; + + template + struct ArgumentTraits< std::map > + : public detail::MapArgumentTraits< std::map > + {}; + + template + struct ReturnValueTraits< std::map > + : public detail::MapReturnValueTraits< std::map > + {}; + + template + struct ArgumentTraits< std::multimap > + : public detail::MapArgumentTraits< std::multimap > + {}; + + template + struct ReturnValueTraits< std::multimap > + : public detail::MapReturnValueTraits< std::multimap > {}; template @@ -104,7 +130,7 @@ namespace console { ///////////////////////////////hh.e//////////////////////////////////////// //#include "STLSupport.cci" #include "STLSupport.ct" -//#include "STLSupport.cti" +#include "STLSupport.cti" #endif diff --git a/senf/Utils/Console/STLSupport.ih b/senf/Utils/Console/STLSupport.ih new file mode 100644 index 0000000..2372a84 --- /dev/null +++ b/senf/Utils/Console/STLSupport.ih @@ -0,0 +1,107 @@ +// $Id$ +// +// Copyright (C) 2009 +// 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 STLSupport internal header */ + +#ifndef IH_SENF_senf_Utils_Console_STLSupport_ +#define IH_SENF_senf_Utils_Console_STLSupport_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace senf { +namespace console { +namespace detail { + + template + struct CollectionArgumentTraitsBase + { + typedef Collection type; + static bool const singleToken = false; + + static std::string description(); + static std::string str(Collection const & value); + }; + + template + struct CollectionArgumentTraits + : detail::CollectionArgumentTraitsBase + { + static void parse(ParseCommandInfo::TokensRange const & tokens, Collection & out); + }; + + template + struct CollectionReturnValueTraits + { + typedef Collection type; + + static void format(Collection const & value, std::ostream & os); + }; + + struct PushBackFunctor + { + template + static void add(Sequence & seq, ValueType const & value); + }; + + struct InsertFunctor + { + template + static void add(Collection & seq, ValueType const & value); + }; + + template + struct MapArgumentTraits + { + typedef Collection type; + static bool const singleToken = false; + + static void parse(ParseCommandInfo::TokensRange const & tokens, Collection & out); + static std::string description(); + static std::string str(Collection const & value); + }; + + template + struct MapReturnValueTraits + { + typedef Collection type; + + static void format(Collection const & value, std::ostream & os); + }; + +}}} + +///////////////////////////////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/Utils/Console/STLSupport.test.cc b/senf/Utils/Console/STLSupport.test.cc index c920f62..878c909 100644 --- a/senf/Utils/Console/STLSupport.test.cc +++ b/senf/Utils/Console/STLSupport.test.cc @@ -42,22 +42,31 @@ namespace { - int vectorTest(std::vector const & data) + template + struct Summer { - int sum (0); - for (std::vector::const_iterator i (data.begin()); i != data.end(); ++i) - sum += *i; - return sum; - } - - int listTest(std::list const & data) + static int test(Container const & data) + { + int sum (0); + for (typename Container::const_iterator i (data.begin()), i_end (data.end()); + i != i_end; ++i) + sum += *i; + return sum; + } + }; + + std::pair mapTest(std::map const & data) { + std::string keys; int sum (0); - for (std::list::const_iterator i (data.begin()); i != data.end(); ++i) - sum += *i; - return sum; + for (std::map::const_iterator i (data.begin()), i_end (data.end()); + i != i_end; ++i) { + keys += i->first; + sum += i->second; + } + return std::make_pair(keys,sum); } - + } BOOST_AUTO_UNIT_TEST(vectorSupport) @@ -68,7 +77,7 @@ BOOST_AUTO_UNIT_TEST(vectorSupport) senf::console::root().add("test", dir); std::vector defv (boost::assign::list_of(7)(2).to_container(defv)); - dir.add("test", &vectorTest) + dir.add("test", &Summer >::test) .arg("data", "test data", senf::console::kw::default_value = defv); std::stringstream ss; @@ -99,7 +108,7 @@ BOOST_AUTO_UNIT_TEST(listSupport) senf::console::root().add("test", dir); std::list defv (boost::assign::list_of(7)(2).to_container(defv)); - dir.add("test", &listTest) + dir.add("test", &Summer >::test) .arg("data", "test data", senf::console::kw::default_value = defv); std::stringstream ss; @@ -122,6 +131,70 @@ BOOST_AUTO_UNIT_TEST(listSupport) " default: (7 2)\n" ); } +BOOST_AUTO_UNIT_TEST(setSupport) +{ + senf::console::Executor executor; + senf::console::CommandParser parser; + senf::console::ScopedDirectory<> dir; + senf::console::root().add("test", dir); + + std::set defv (boost::assign::list_of(7)(2).to_container(defv)); + dir.add("test", &Summer >::test) + .arg("data", "test data", senf::console::kw::default_value = defv); + std::stringstream ss; + + SENF_CHECK_NO_THROW( + parser.parse("test/test; test/test (); test/test 5; test/test (13); test/test (4 5 8)", + boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( ss.str(), "9\n" "0\n" "5\n" "13\n" "17\n" ); + + ss.str(""); + SENF_CHECK_NO_THROW( + parser.parse("help test/test", + boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( + ss.str(), + "Usage:\n" + " test [data:set]\n" + "\n" + "With:\n" + " data test data\n" + " default: (2 7)\n" ); +} + +BOOST_AUTO_UNIT_TEST(mapSupport) +{ + senf::console::Executor executor; + senf::console::CommandParser parser; + senf::console::ScopedDirectory<> dir; + senf::console::root().add("test", dir); + + std::map defv ( + boost::assign::map_list_of("foo",7)("bar",2).to_container(defv)); + dir.add("test", &mapTest) + .arg("data", "test data", senf::console::kw::default_value = defv); + std::stringstream ss; + + SENF_CHECK_NO_THROW( + parser.parse("test/test; test/test (); " + "test/test (vier=4 fuenf = 5 acht=8 )", + boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( ss.str(), "(barfoo 9)\n" "( 0)\n" "(achtfuenfvier 17)\n" ); + + ss.str(""); + SENF_CHECK_NO_THROW( + parser.parse("help test/test", + boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( + ss.str(), + "Usage:\n" + " test [data:map]\n" + "\n" + "With:\n" + " data test data\n" + " default: (bar=2 foo=7)\n" ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_