#ifndef DOXYGEN
-template <class Sequence>
-prefix_ void senf::console::SequenceArgumentTraits<Sequence>::
-parse(ParseCommandInfo::TokensRange const & tokens, type & out)
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::CollectionArgumentTraitsBase<Collection>
+
+template <class Collection>
+prefix_ std::string
+senf::console::detail::CollectionArgumentTraitsBase<Collection>::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<typename Collection::value_type>::description() + ">";
+}
+
+template <class Collection>
+prefix_ std::string
+senf::console::detail::CollectionArgumentTraitsBase<Collection>::str(Collection const & value)
+{
+ std::stringstream ss;
+ senf::console::format(value, ss);
+ return ss.str();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::CollectionArgumentTraits<Collection,Adder>
+
+template <class Collection, class Adder>
+prefix_ void senf::console::detail::CollectionArgumentTraits<Collection,Adder>::
+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 <class Sequence>
-prefix_ std::string senf::console::SequenceArgumentTraits<Sequence>::description()
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::CollectionReturnValueTraits<Collection>
+
+template <class Collection>
+prefix_ void
+senf::console::detail::CollectionReturnValueTraits<Collection>::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<Collection>
+
+template <class Collection>
+prefix_ void senf::console::detail::MapArgumentTraits<Collection>::
+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 <class Collection>
+prefix_ std::string senf::console::detail::MapArgumentTraits<Collection>::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<typename Sequence::value_type>::description() + ">";
+ + ArgumentTraits<typename Collection::key_type>::description() + ","
+ + ArgumentTraits<typename Collection::mapped_type>::description() + ">";
}
-template <class Sequence>
-prefix_ std::string senf::console::SequenceArgumentTraits<Sequence>::str(type const & value)
+template <class Collection>
+prefix_ std::string
+senf::console::detail::MapArgumentTraits<Collection>::str(Collection const & value)
{
std::stringstream ss;
senf::console::format(value, ss);
return ss.str();
}
-template <class Sequence>
-prefix_ void senf::console::SequenceReturnValueTraits<Sequence>::format(type const & value,
- std::ostream & os)
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::MapReturnValueTraits<Collection>
+
+template <class Collection>
+prefix_ void
+senf::console::detail::MapReturnValueTraits<Collection>::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
os << ")";
}
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ArgumentTraits< std::pair<T1,T2> >
+
template <class T1, class T2>
prefix_ void senf::console::ArgumentTraits< std::pair<T1,T2> >::
parse(ParseCommandInfo::TokensRange const & tokens, type & out)
return ss.str();
}
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ReturnValueTraits< std::pair<T1,T2> >
+
template <class T1, class T2>
prefix_ void senf::console::ReturnValueTraits< std::pair<T1,T2> >::format(type const & value,
std::ostream & os)
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.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 STLSupport inline template implementation */
+
+#include "STLSupport.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::PushBackFunctor
+
+template <class Sequence, class ValueType>
+prefix_ void senf::console::detail::PushBackFunctor::add(Sequence & seq,
+ ValueType const & value)
+{
+ seq.push_back(value);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::InsertFunctor
+
+template <class Collection, class ValueType>
+prefix_ void senf::console::detail::InsertFunctor::add(Collection & seq,
+ ValueType const & value)
+{
+ seq.insert(value);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// 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:
#include "Traits.hh"
//#include "STLSupport.mpp"
+#include "STLSupport.ih"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
#ifndef DOXYGEN
- template <class Sequence>
- 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 <class Sequence>
- struct SequenceReturnValueTraits
- {
- typedef Sequence type;
-
- static void format(type const & value, std::ostream & os);
- };
-
template <class T, class Alloc>
struct ArgumentTraits< std::vector<T,Alloc> >
- : public SequenceArgumentTraits< std::vector<T,Alloc> >
+ : public detail::CollectionArgumentTraits< std::vector<T,Alloc>,
+ detail::PushBackFunctor >
{};
template <class T, class Alloc>
struct ReturnValueTraits< std::vector<T,Alloc> >
- : public SequenceReturnValueTraits< std::vector<T,Alloc> >
+ : public detail::CollectionReturnValueTraits< std::vector<T,Alloc> >
{};
template <class T, class Alloc>
struct ArgumentTraits< std::list<T,Alloc> >
- : public SequenceArgumentTraits< std::list<T,Alloc> >
+ : public detail::CollectionArgumentTraits< std::list<T,Alloc>,
+ detail::PushBackFunctor >
{};
template <class T, class Alloc>
struct ReturnValueTraits< std::list<T,Alloc> >
- : public SequenceReturnValueTraits< std::list<T,Alloc> >
+ : public detail::CollectionReturnValueTraits< std::list<T,Alloc> >
+ {};
+
+ template <class Key, class Compare, class Alloc>
+ struct ArgumentTraits< std::set<Key,Compare,Alloc> >
+ : public detail::CollectionArgumentTraits< std::set<Key,Compare,Alloc>,
+ detail::InsertFunctor >
+ {};
+
+ template <class Key, class Compare, class Alloc>
+ struct ReturnValueTraits< std::set<Key,Compare,Alloc> >
+ : public detail::CollectionReturnValueTraits< std::set<Key,Compare,Alloc> >
+ {};
+
+ template <class Key, class Compare, class Alloc>
+ struct ArgumentTraits< std::multiset<Key,Compare,Alloc> >
+ : public detail::CollectionArgumentTraits< std::multiset<Key,Compare,Alloc>,
+ detail::InsertFunctor >
+ {};
+
+ template <class Key, class Compare, class Alloc>
+ struct ReturnValueTraits< std::multiset<Key,Compare,Alloc> >
+ : public detail::CollectionReturnValueTraits< std::multiset<Key,Compare,Alloc> >
+ {};
+
+ template <class Key, class Data, class Compare, class Alloc>
+ struct ArgumentTraits< std::map<Key,Data,Compare,Alloc> >
+ : public detail::MapArgumentTraits< std::map<Key,Data,Compare,Alloc> >
+ {};
+
+ template <class Key, class Data, class Compare, class Alloc>
+ struct ReturnValueTraits< std::map<Key,Data,Compare,Alloc> >
+ : public detail::MapReturnValueTraits< std::map<Key,Data,Compare,Alloc> >
+ {};
+
+ template <class Key, class Data, class Compare, class Alloc>
+ struct ArgumentTraits< std::multimap<Key,Data,Compare,Alloc> >
+ : public detail::MapArgumentTraits< std::multimap<Key,Data,Compare,Alloc> >
+ {};
+
+ template <class Key, class Data, class Compare, class Alloc>
+ struct ReturnValueTraits< std::multimap<Key,Data,Compare,Alloc> >
+ : public detail::MapReturnValueTraits< std::multimap<Key,Data,Compare,Alloc> >
{};
template <class T1, class T2>
///////////////////////////////hh.e////////////////////////////////////////
//#include "STLSupport.cci"
#include "STLSupport.ct"
-//#include "STLSupport.cti"
+#include "STLSupport.cti"
#endif
\f
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.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 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 <class Collection>
+ struct CollectionArgumentTraitsBase
+ {
+ typedef Collection type;
+ static bool const singleToken = false;
+
+ static std::string description();
+ static std::string str(Collection const & value);
+ };
+
+ template <class Collection, class Adder>
+ struct CollectionArgumentTraits
+ : detail::CollectionArgumentTraitsBase<Collection>
+ {
+ static void parse(ParseCommandInfo::TokensRange const & tokens, Collection & out);
+ };
+
+ template <class Collection>
+ struct CollectionReturnValueTraits
+ {
+ typedef Collection type;
+
+ static void format(Collection const & value, std::ostream & os);
+ };
+
+ struct PushBackFunctor
+ {
+ template <class Sequence, class ValueType>
+ static void add(Sequence & seq, ValueType const & value);
+ };
+
+ struct InsertFunctor
+ {
+ template <class Collection, class ValueType>
+ static void add(Collection & seq, ValueType const & value);
+ };
+
+ template <class Collection>
+ 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 <class Collection>
+ struct MapReturnValueTraits
+ {
+ typedef Collection type;
+
+ static void format(Collection const & value, std::ostream & os);
+ };
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// 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:
namespace {
- int vectorTest(std::vector<int> const & data)
+ template <class Container>
+ struct Summer
{
- int sum (0);
- for (std::vector<int>::const_iterator i (data.begin()); i != data.end(); ++i)
- sum += *i;
- return sum;
- }
-
- int listTest(std::list<int> 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<std::string, int> mapTest(std::map<std::string,int> const & data)
{
+ std::string keys;
int sum (0);
- for (std::list<int>::const_iterator i (data.begin()); i != data.end(); ++i)
- sum += *i;
- return sum;
+ for (std::map<std::string,int>::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)
senf::console::root().add("test", dir);
std::vector<int> defv (boost::assign::list_of(7)(2).to_container(defv));
- dir.add("test", &vectorTest)
+ dir.add("test", &Summer<std::vector<int> >::test)
.arg("data", "test data", senf::console::kw::default_value = defv);
std::stringstream ss;
senf::console::root().add("test", dir);
std::list<int> defv (boost::assign::list_of(7)(2).to_container(defv));
- dir.add("test", &listTest)
+ dir.add("test", &Summer<std::list<int> >::test)
.arg("data", "test data", senf::console::kw::default_value = defv);
std::stringstream ss;
" 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<int> defv (boost::assign::list_of(7)(2).to_container(defv));
+ dir.add("test", &Summer<std::set<int> >::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<void>( 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<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL(
+ ss.str(),
+ "Usage:\n"
+ " test [data:set<int>]\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<std::string, int> 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<void>( 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<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL(
+ ss.str(),
+ "Usage:\n"
+ " test [data:map<string,int>]\n"
+ "\n"
+ "With:\n"
+ " data test data\n"
+ " default: (bar=2 foo=7)\n" );
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_