Utils/Console: Parse char arguments as integers
g0dil [Fri, 13 Nov 2009 12:39:01 +0000 (12:39 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1524 270642c3-0616-0410-b53a-bc976706d245

senf/Utils/Console/STLSupport.ct
senf/Utils/Console/Traits.ct
senf/Utils/Console/Traits.cti
senf/Utils/Console/Traits.hh
senf/Utils/Console/Traits.ih
senf/Utils/Console/Traits.test.cc
senf/Utils/Console/Utility.ct
senf/Utils/Console/Utility.hh
senf/Utils/Console/Utility.test.cc [new file with mode: 0644]
senf/Utils/TypeInfo.cc
senf/Utils/TypeInfo.hh

index 08116a0..108b974 100644 (file)
@@ -40,12 +40,7 @@ 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) + "<" 
+    return senf::prettyBaseName(typeid(Collection)) + "<" 
         + ArgumentTraits<typename Collection::value_type>::description() + ">";
 }
 
@@ -120,12 +115,7 @@ parse(ParseCommandInfo::TokensRange const & tokens, Collection & out)
 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) + "<" 
+    return senf::prettyBaseName(typeid(Collection)) + "<" 
         + ArgumentTraits<typename Collection::key_type>::description() + ","
         + ArgumentTraits<typename Collection::mapped_type>::description() + ">";
 }
index 8749e9a..6f90704 100644 (file)
@@ -47,57 +47,6 @@ senf::console::senf_console_parse_argument(ParseCommandInfo::TokensRange const &
     return false;
 }
 
-///////////////////////////////////////////////////////////////////////////
-// senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >
-
-template <class Enum>
-prefix_ void senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::
-parse(ParseCommandInfo::TokensRange const & tokens, type & out)
-{
-    CheckedArgumentIteratorWrapper arg (tokens);
-    out.value = 0;
-    while (arg) {
-        Enum v;
-        senf::console::parse( *(arg++), v);
-        out.value |= v;
-    }
-}
-
-template <class Enum>
-prefix_ std::string
-senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::description()
-{
-    return ArgumentTraits<Enum>::description();
-}
-
-template <class Enum>
-prefix_ std::string
-senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::str(type const & value)
-{
-    std::stringstream ss;
-    senf::console::format(value, ss);
-    return ss.str();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::console::ReturnValueTraits< senf::console::FlagCollection<Enum> >
-
-template <class Enum>
-prefix_ void senf::console::ReturnValueTraits< senf::console::FlagCollection<Enum> >::
-format(type const & value, std::ostream & os)
-{
-    unsigned n (0);
-    std::stringstream ss;
-    unsigned long flag (1);
-    for (unsigned bit (0); bit<sizeof(value.value)*CHAR_BIT; ++bit, flag<<=1) {
-        if (value.value & flag) {
-            if (n++) ss << " ";
-            senf::console::format(static_cast<Enum>(flag), ss);
-        }
-    }
-    os << (n != 1 ? "(" + ss.str() + ")" : ss.str());
-}
-
 ///////////////////////////////ct.e////////////////////////////////////////
 #undef prefix_
 
index 0173633..c96ae78 100644 (file)
@@ -80,9 +80,7 @@ prefix_ void senf::console::format(Type const & value, std::ostream & os)
 template <class Type>
 prefix_ std::string senf::console::ArgumentTraits<Type>::description()
 {
-    std::string type (prettyName(typeid(Type)));
-    std::string::size_type i (type.rfind(':'));
-    return i == std::string::npos ? type : type.substr(i+1);
+    return prettyBaseName(typeid(Type));
 }
 
 template <class Type>
@@ -93,6 +91,24 @@ prefix_ std::string senf::console::ArgumentTraits<Type>::str(Type const & value)
     return ss.str();
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::console::detail::CharArgumentTraits<CharT>
+
+template <class CharT>
+prefix_ void senf::console::detail::CharArgumentTraits<CharT>::
+parse(ParseCommandInfo::TokensRange const & tokens, CharT & out)
+{
+    typename base::type v;
+    base::parse(tokens,v);
+    out = v;
+}
+
+template <class CharT>
+prefix_ std::string senf::console::detail::CharArgumentTraits<CharT>::description()
+{
+    return prettyBaseName(typeid(CharT));
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 811be19..19565b8 100644 (file)
 namespace senf {
 namespace console {
 
-    /** \brief Customize return value formating
-
-        ReturnValueTraits provides return value formatting. The default implementation provided here
-        will forward the call directly to senf_console_format_value(). The default implementation of
-        that function will write the \a value to \a os using standard iostream formatting.
-
-        To customize this behavior for some type, either provide an implementation of
-        senf_console_format_value() in the types namespace or provide a specialization of
-        ReturnValueTraits.
-
-        The output should \e not end in a newline since one is added automatically.
-     */
-    template <class Type>
-    struct ReturnValueTraits
-    {
-        typedef Type type;
-
-        static void format(Type const & value, std::ostream & os);
-                                        ///< Write \a value to \a os
-    };
-
-    /** \brief Return value formatter
-
-        \see ReturnValuetraits
-
-        \related ReturnValueTraits
-     */
-    template <class Type>
-    void senf_console_format_value(Type const & value, std::ostream & os);
-
     /** \brief Customize argument parsing
         
         ArgumentTraits provides argument parsing, Additionally, this class provides a way to get a
@@ -130,6 +100,38 @@ namespace console {
     template <class Type>
     bool senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out);
 
+
+    /** \brief Customize return value formating
+
+        ReturnValueTraits provides return value formatting. The default implementation provided here
+        will forward the call directly to senf_console_format_value(). The default implementation of
+        that function will write the \a value to \a os using standard iostream formatting.
+
+        To customize this behavior for some type, either provide an implementation of
+        senf_console_format_value() in the types namespace or provide a specialization of
+        ReturnValueTraits.
+
+        The output should \e not end in a newline since one is added automatically.
+     */
+    template <class Type>
+    struct ReturnValueTraits
+    {
+        typedef Type type;
+
+        static void format(Type const & value, std::ostream & os);
+                                        ///< Write \a value to \a os
+    };
+
+    /** \brief Return value formatter
+
+        \see ReturnValuetraits
+
+        \related ReturnValueTraits
+     */
+    template <class Type>
+    void senf_console_format_value(Type const & value, std::ostream & os);
+
+
     /** \brief Parse token range
 
         This helper will invoke the correct ArgumentTraits::parse function to parse the input tokens
@@ -159,55 +161,6 @@ namespace console {
     template <class Type>
     void format(Type const & value, std::ostream & os);
 
-#ifndef DOXYGEN
-
-    // Parse bool: true/false, yes/no, enabled/disabled, 0/1
-    template <>
-    struct ArgumentTraits<bool>
-    {
-        typedef bool type;
-        static bool const singleToken = true;
-
-        static void parse(ParseCommandInfo::TokensRange const & tokens, bool & out);
-        static std::string description();
-        static std::string str(bool value);
-    };
-
-    template <>
-    struct ReturnValueTraits<bool>
-    {
-        typedef bool type;
-
-        static void format(bool value, std::ostream & os);
-    };
-
-    template <>
-    struct ArgumentTraits<std::string>
-    {
-        typedef std::string type;
-        static bool const singleToken = true;
-
-        static void parse(ParseCommandInfo::TokensRange const & tokens, std::string & out);
-        static std::string description();
-        static std::string str(std::string const & value);
-    };
-
-#endif
-
-    /** \brief Format boolean value as \c true / \c false */
-    void formatTrueFalse(bool value, std::ostream & os);
-
-    /** \brief Format boolean value as \c yes / \c no */
-    void formatYesNo(bool value, std::ostream & os);
-
-    /** \brief Format boolean value as \c enabled / \c disabled */
-    void formatEnabledDisabled(bool value, std::ostream & os);
-    
-    /** \brief Format boolean value as \c on / \c off */
-    void formatOnOff(bool value, std::ostream & os);
-
-    /** \brief Format boolean value as \c 1 / \c 0 */
-    void formatOneZero(bool value, std::ostream & os);
 
     /** \brief Register enum type for argument parsing
 
@@ -246,73 +199,65 @@ namespace console {
 #   define SENF_CONSOLE_REGISTER_ENUM_MEMBER(Class, Type, Values) \
         SENF_CONSOLE_REGISTER_ENUM_(Class::, Type, Values)
 
-    /** \brief Bit-mask flag argument type
 
-        senf::console::FlagCollection supplies a special argument type for use in registering
-        console commands. This argument type is used to represent a bit-mask of single flags. 
+    /** \brief Format boolean value as \c true / \c false */
+    void formatTrueFalse(bool value, std::ostream & os);
 
-        \code
-        // Function taking a flags argument
-        void func(unsigned flags);
-
-        // Enum containing all the possible flag values
-        enum MyFlags { Foo = 1,
-                     Bar = 2,
-                     Baz = 4,
-                     Doo = 8 };
-        SENF_CONSOLE_REGISTER_ENUM(MyFlags, (Foo)(Bar)(Baz)(Boo));
-        
-        // Register the function with a FlagCollection argument type
-        consoleDir.add("func", boost::function<void (FlagCollection<MyFlags>)>(&func));
-        \endcode
+    /** \brief Format boolean value as \c yes / \c no */
+    void formatYesNo(bool value, std::ostream & os);
 
-        To use the FlagCollection class
-        \li you need a function which takes a bit-mask of flags as argument
-        \li you define and register an enum with all possible flag values
-        \li you register the function with a FlagCollection argument type using \c boost::function
-            for the conversion. This is also possible for return values.
-
-        The nice thing is, that \c boot::function supports compatible argument types and does
-        automatic type conversion. Since a FlagCollection is convertible to and from unsigned long,
-        this conversion will work. 
-
-        After registering this function, you can call it with a collection of flags as argument
-
-        <pre>
-        console:/$ help func
-        Usage:
-            func arg11:MyFlags
-        console:/$ func Foo
-        console:/$ func (Foo Boo)
-        </pre>
-     */
-    template <class Enum>
-    struct FlagCollection
+    /** \brief Format boolean value as \c enabled / \c disabled */
+    void formatEnabledDisabled(bool value, std::ostream & os);
+    
+    /** \brief Format boolean value as \c on / \c off */
+    void formatOnOff(bool value, std::ostream & os);
+
+    /** \brief Format boolean value as \c 1 / \c 0 */
+    void formatOneZero(bool value, std::ostream & os);
+
+
+#ifndef DOXYGEN
+
+    // Parse bool: true/false, yes/no, enabled/disabled, 0/1
+    template <>
+    struct ArgumentTraits<bool>
     {
-        operator unsigned long() const { return value; }
-        FlagCollection() : value (0) {}
-        FlagCollection(unsigned long value_) : value (value_) {}
-        FlagCollection(Enum value_) : value (value_) {}
-        unsigned long value;
+        typedef bool type;
+        static bool const singleToken = true;
+
+        static void parse(ParseCommandInfo::TokensRange const & tokens, bool & out);
+        static std::string description();
+        static std::string str(bool value);
     };
 
-    template <class Enum>
-    struct ArgumentTraits< FlagCollection<Enum> >
+    template <>
+    struct ReturnValueTraits<bool>
     {
-        typedef FlagCollection<Enum> 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);
+        typedef bool type;
+
+        static void format(bool value, std::ostream & os);
     };
 
-    template <class Enum>
-    struct ReturnValueTraits< FlagCollection<Enum> >
+    template <>
+    struct ArgumentTraits<std::string>
     {
-        typedef FlagCollection<Enum> type;
-        static void format(type const & value, std::ostream & os);
+        typedef std::string type;
+        static bool const singleToken = true;
+
+        static void parse(ParseCommandInfo::TokensRange const & tokens, std::string & out);
+        static std::string description();
+        static std::string str(std::string const & value);
     };
 
+    template <> struct ArgumentTraits<char> : public detail::CharArgumentTraits<char> {};
+    template <> struct ReturnValueTraits<char> : public detail::CharReturnValueTraits<char> {};
+    template <> struct ArgumentTraits<signed char> : public detail::CharArgumentTraits<signed char> {};
+    template <> struct ReturnValueTraits<signed char> : public detail::CharReturnValueTraits<signed char> {};
+    template <> struct ArgumentTraits<unsigned char> : public detail::CharArgumentTraits<unsigned char> {};
+    template <> struct ReturnValueTraits<unsigned char> : public detail::CharReturnValueTraits<unsigned char> {};    
+
+#endif
+
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
index 85213bb..c3d6127 100644 (file)
 
 // Custom includes
 #include <string>
+#include <limits>
 #include <boost/preprocessor/seq/for_each.hpp>
 #include <boost/preprocessor/stringize.hpp>
 #include <boost/preprocessor/facilities/empty.hpp>
 #include <boost/bimap.hpp>
 #include <boost/assign/list_inserter.hpp>
 #include <boost/algorithm/string/case_conv.hpp>
+#include <boost/mpl/if.hpp>
 #include <senf/Utils/singleton.hh>
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
 namespace senf {
 namespace console {
+
+    template <class _> struct ArgumentTraits;
+    template <class _> struct ReturnValueTraits;
+
 namespace detail {
+    
+    template <class CharT>
+    struct MatchingShortType
+        : public boost::mpl::if_c<std::numeric_limits<CharT>::is_signed,short,unsigned short>
+    {};
+
+    template <class CharT>
+    struct CharArgumentTraits
+        : public ArgumentTraits<typename MatchingShortType<CharT>::type>
+    {
+        typedef ArgumentTraits<typename MatchingShortType<CharT>::type> base;
+        typedef CharT type;
+        static void parse(ParseCommandInfo::TokensRange const & tokens, CharT & out);
+        static std::string description();
+    };
+
+    template <class CharT>
+    struct CharReturnValueTraits
+        : public ReturnValueTraits<typename MatchingShortType<CharT>::type>
+    {
+        typedef CharT type;
+    };
 
 #ifndef DOXYGEN
     struct StringILess
index b8d1d1f..85b9f35 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include "Traits.hh"
+#include "Utility.hh"
 #include "ParsedCommand.hh"
 #include "Executor.hh"
 #include "Parse.hh"
 ///////////////////////////////cc.p////////////////////////////////////////
 
 namespace {
+    char charTest(char value) { return value; }
+    signed char scharTest(signed char value) { return value; }
+    unsigned char ucharTest(unsigned char value) { return value; }
+
+    bool boolTest(bool value) { return value; }
+
     enum TestEnum { Foo=1, Bar=2, FooBar=4 };
     SENF_CONSOLE_REGISTER_ENUM( TestEnum, (Foo)(Bar)(FooBar) );
 
@@ -50,11 +57,37 @@ namespace {
         static MemberEnum test (MemberEnum value) { return value; }
     };
     SENF_CONSOLE_REGISTER_ENUM_MEMBER( TestClass, MemberEnum, (MemberFoo)(MemberBar) );
+}
 
-    bool boolTest(bool value) { return value; }
+BOOST_AUTO_UNIT_TEST(charTraits)
+{
+    senf::console::Executor executor;
+    senf::console::CommandParser parser;
+    senf::console::ScopedDirectory<> dir;
+    senf::console::root().add("test", dir);
+    std::stringstream ss;
+
+    dir.add("test",&charTest);
+    dir.add("stest",&scharTest);
+    dir.add("utest",&ucharTest);
 
-    senf::console::FlagCollection<TestEnum> collectionTest(
-        senf::console::FlagCollection<TestEnum> flags) { return flags; }
+    SENF_CHECK_NO_THROW(
+        parser.parse("test/test 10; test/test 20",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "10\n" "20\n" );
+    ss.str("");
+
+    SENF_CHECK_NO_THROW(
+        parser.parse("test/stest 10; test/stest -20",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "10\n" "-20\n" );
+    ss.str("");
+
+    SENF_CHECK_NO_THROW(
+        parser.parse("test/utest 10; test/utest 20",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "10\n" "20\n" );
+    ss.str("");
 }
 
 BOOST_AUTO_UNIT_TEST(boolTraits)
@@ -162,35 +195,6 @@ BOOST_AUTO_UNIT_TEST(enumSupport)
     BOOST_CHECK_EQUAL( ss.str(), "Foo\n" );
 }
 
-BOOST_AUTO_UNIT_TEST(flagCollection)
-{
-    senf::console::Executor executor;
-    senf::console::CommandParser parser;
-    senf::console::ScopedDirectory<> dir;
-    senf::console::root().add("test", dir);
-    std::stringstream ss;
-
-    dir.add("test",&collectionTest);
-    
-    ss.str("");
-    SENF_CHECK_NO_THROW(
-        parser.parse("test/test foo",
-                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
-    BOOST_CHECK_EQUAL( ss.str(), "Foo\n" );
-
-    ss.str("");
-    SENF_CHECK_NO_THROW(
-        parser.parse("test/test (foo bar)",
-                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
-    BOOST_CHECK_EQUAL( ss.str(), "(Foo Bar)\n" );
-
-    ss.str("");
-    SENF_CHECK_NO_THROW(
-        parser.parse("test/test ()",
-                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
-    BOOST_CHECK_EQUAL( ss.str(), "()\n" );
-}
-
 BOOST_AUTO_UNIT_TEST(singleToken)
 {
     BOOST_CHECK( senf::console::ArgumentTraits<std::string>::singleToken );
index 771e36d..2f12892 100644 (file)
@@ -32,6 +32,9 @@
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ArgumentTraits< senf::console::ValueRange<T> >
+
 template <class T>
 prefix_ void senf::console::ArgumentTraits< senf::console::ValueRange<T> >::
 parse(ParseCommandInfo::TokensRange const & tokens, type & out)
@@ -69,6 +72,9 @@ str(type const & value)
     return ss.str();
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ReturnValueTraits< senf::console::ValueRange<T> >
+
 template <class T>
 prefix_ void senf::console::ReturnValueTraits< senf::console::ValueRange<T> >::
 format(type const & value, std::ostream & os)
@@ -78,6 +84,57 @@ format(type const & value, std::ostream & os)
         os << ':' << senf::console::str(value.high);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >
+
+template <class Enum>
+prefix_ void senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::
+parse(ParseCommandInfo::TokensRange const & tokens, type & out)
+{
+    CheckedArgumentIteratorWrapper arg (tokens);
+    out.value = 0;
+    while (arg) {
+        Enum v;
+        senf::console::parse( *(arg++), v);
+        out.value |= v;
+    }
+}
+
+template <class Enum>
+prefix_ std::string
+senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::description()
+{
+    return ArgumentTraits<Enum>::description();
+}
+
+template <class Enum>
+prefix_ std::string
+senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::str(type const & value)
+{
+    std::stringstream ss;
+    senf::console::format(value, ss);
+    return ss.str();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::console::ReturnValueTraits< senf::console::FlagCollection<Enum> >
+
+template <class Enum>
+prefix_ void senf::console::ReturnValueTraits< senf::console::FlagCollection<Enum> >::
+format(type const & value, std::ostream & os)
+{
+    unsigned n (0);
+    std::stringstream ss;
+    unsigned long flag (1);
+    for (unsigned bit (0); bit<sizeof(value.value)*CHAR_BIT; ++bit, flag<<=1) {
+        if (value.value & flag) {
+            if (n++) ss << " ";
+            senf::console::format(static_cast<Enum>(flag), ss);
+        }
+    }
+    os << (n != 1 ? "(" + ss.str() + ")" : ss.str());
+}
+
 ///////////////////////////////ct.e////////////////////////////////////////
 #undef prefix_
 
index beb8982..6ccc579 100644 (file)
@@ -71,6 +71,77 @@ namespace console {
 
 #endif
 
+    /** \brief Bit-mask flag argument type
+
+        senf::console::FlagCollection supplies a special argument type for use in registering
+        console commands. This argument type is used to represent a bit-mask of single flags. 
+
+        \code
+        // Function taking a flags argument
+        void func(unsigned flags);
+
+        // Enum containing all the possible flag values
+        enum MyFlags { Foo = 1,
+                     Bar = 2,
+                     Baz = 4,
+                     Doo = 8 };
+        SENF_CONSOLE_REGISTER_ENUM(MyFlags, (Foo)(Bar)(Baz)(Boo));
+        
+        // Register the function with a FlagCollection argument type
+        consoleDir.add("func", boost::function<void (FlagCollection<MyFlags>)>(&func));
+        \endcode
+
+        To use the FlagCollection class
+        \li you need a function which takes a bit-mask of flags as argument
+        \li you define and register an enum with all possible flag values
+        \li you register the function with a FlagCollection argument type using \c boost::function
+            for the conversion. This is also possible for return values.
+
+        The nice thing is, that \c boot::function supports compatible argument types and does
+        automatic type conversion. Since a FlagCollection is convertible to and from unsigned long,
+        this conversion will work. 
+
+        After registering this function, you can call it with a collection of flags as argument
+
+        <pre>
+        console:/$ help func
+        Usage:
+            func arg11:MyFlags
+        console:/$ func Foo
+        console:/$ func (Foo Boo)
+        </pre>
+     */
+    template <class Enum>
+    struct FlagCollection
+    {
+        operator unsigned long() const { return value; }
+        FlagCollection() : value (0) {}
+        FlagCollection(unsigned long value_) : value (value_) {}
+        FlagCollection(Enum value_) : value (value_) {}
+        unsigned long value;
+    };
+
+#ifndef DOXYGEN
+
+    template <class Enum>
+    struct ArgumentTraits< FlagCollection<Enum> >
+    {
+        typedef FlagCollection<Enum> 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 Enum>
+    struct ReturnValueTraits< FlagCollection<Enum> >
+    {
+        typedef FlagCollection<Enum> type;
+        static void format(type const & value, std::ostream & os);
+    };
+
+#endif
+
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
diff --git a/senf/Utils/Console/Utility.test.cc b/senf/Utils/Console/Utility.test.cc
new file mode 100644 (file)
index 0000000..f5ff939
--- /dev/null
@@ -0,0 +1,94 @@
+// $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 Utility.test unit tests */
+
+//#include "Utility.test.hh"
+//#include "Utility.test.ih"
+
+// Custom includes
+#include "Utility.hh"
+#include "Traits.hh"
+#include "ParsedCommand.hh"
+#include "Executor.hh"
+#include "Parse.hh"
+#include "ScopedDirectory.hh"
+
+#include <senf/Utils/auto_unit_test.hh>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+    enum TestEnum { Foo=1, Bar=2, FooBar=4 };
+    SENF_CONSOLE_REGISTER_ENUM( TestEnum, (Foo)(Bar)(FooBar) );
+
+    senf::console::FlagCollection<TestEnum> collectionTest(
+        senf::console::FlagCollection<TestEnum> flags) { return flags; }
+
+}
+
+BOOST_AUTO_UNIT_TEST(flagCollection)
+{
+    senf::console::Executor executor;
+    senf::console::CommandParser parser;
+    senf::console::ScopedDirectory<> dir;
+    senf::console::root().add("test", dir);
+    std::stringstream ss;
+
+    dir.add("test",&collectionTest);
+    
+    ss.str("");
+    SENF_CHECK_NO_THROW(
+        parser.parse("test/test foo",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "Foo\n" );
+
+    ss.str("");
+    SENF_CHECK_NO_THROW(
+        parser.parse("test/test (foo bar)",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "(Foo Bar)\n" );
+
+    ss.str("");
+    SENF_CHECK_NO_THROW(
+        parser.parse("test/test ()",
+                     boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+    BOOST_CHECK_EQUAL( ss.str(), "()\n" );
+}
+
+///////////////////////////////cc.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:
index bed2876..94d7cae 100644 (file)
@@ -45,6 +45,16 @@ prefix_ std::string senf::prettyName(std::type_info const & type)
     return name;
 }
 
+prefix_ std::string senf::prettyBaseName(std::type_info const & type)
+{
+    std::string name (prettyName(type));
+    std::string::size_type e (name.find('<'));
+    if (e == std::string::npos) e = name.size();
+    std::string::size_type b (name.rfind(':', e));
+    if (b == std::string::npos) b = 0; else ++b;
+    return name.substr(b,e-b);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "TypeInfo.mpp"
index e5e6998..6ce7311 100644 (file)
@@ -37,15 +37,26 @@ namespace senf {
 
     /** \brief Try to return readable type for given type_info
 
-        This function will try to return a demangled type name for the
-        given type_info object. If the demangling fails, the possibly
-        mangled name (type->name()) will be returned.
+        This function will try to return a demangled type name for the given type_info object. If
+        the demangling fails, the possibly mangled name (type->name()) will be returned.
 
         \param[in] type type_info object
         \returns type name, possibly demangled
      */
     std::string prettyName(std::type_info const & type);
 
+    /** \brief Try to return readable type name without namespace or template arguments
+
+        This function will try to return a demangled type name for the given type_info object. If
+        the demangling fails, the possibly mangled name (type->name()) will be returned. The
+        namespace prefix and template arguments will be stripped.
+
+        \param[in] type type_info object
+        \returns type name, possibly demangled and without namespace or template args
+     */
+
+    std::string prettyBaseName(std::type_info const & type);
+
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////