Move sourcecode into 'senf/' directory
[senf.git] / senf / Utils / Console / Traits.hh
diff --git a/senf/Utils/Console/Traits.hh b/senf/Utils/Console/Traits.hh
new file mode 100644 (file)
index 0000000..da5eb60
--- /dev/null
@@ -0,0 +1,306 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// 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 Traits public header */
+
+#ifndef HH_SENF_Scheduler_Console_Traits_
+#define HH_SENF_Scheduler_Console_Traits_ 1
+
+// Custom includes
+#include <iostream>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include "../../Utils/intrusive_refcount.hh"
+#include "Parse.hh"
+#include "Node.hh"
+
+#include "Traits.ih"
+//#include "Traits.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+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
+        string-description of a type and to convert a value back into it's string representation
+        used to display default values.
+        
+        The default implementation provided here 
+        \li will use senf_console_parse_argument() to parse a value. This functions default
+            implementation uses \c boost::lexical_cast and thereby \c iostreams to convert an
+            argument consisting of a single input token into the required type.
+        \li will name types by returning the last component of the fully scoped name (e.g. \c
+            "string" for \c std::string). 
+        \li Will format values (for default value display) by forwarding the value to the
+            ReturnValueTraits of that type.
+
+        To customize just the argument parsing, just provide an implementation of
+        senf_console_parse_argument(). Alternatively or to customize type naming or default value
+        formatting, specialize ArgumentTraits  for the type.
+     */
+    template <class Type>
+    struct ArgumentTraits
+    {
+        typedef Type type;
+
+        static bool const singleToken = 
+            boost::is_same< typeof(senf_console_parse_argument(
+                                       *static_cast<ParseCommandInfo::TokensRange const *>(0),
+                                       *static_cast<Type*>(0))),
+                            bool >::value;
+
+        static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out);
+                                        ///< Parse token range into value
+                                        /**< This function needs to parse \a tokens and write the
+                                             parsed value into \a out. This function needs to parse
+                                             the \e complete list of tokens, additional tokens must
+                                             be considered as syntax error.
+                                             \throws SyntaxErrorException
+                                             \param[in] tokens tokens to parse
+                                             \param[out] out parsed value */
+
+        static std::string description(); ///< String description of type
+                                        /**< Returns the string description of \a Type. Used to
+                                             generate online help. */
+        static std::string str(Type const & value); ///< Stringify value
+                                        /**< To show default values in the online help, this
+                                             function converts a value back into a one-line string
+                                             representation. The default implementation uses the
+                                             ReturnValueTraits for this conversion. */
+    };
+
+    /** \brief Argument parser
+
+        \see ArgumentTraits
+
+        \related ArgumentTraits
+     */
+    template <class Type>
+    bool senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out);
+
+    /** \brief Parse token range
+
+        This helper will invoke the correct ArgumentTraits::parse function to parse the input tokens
+        into the passed in variable.
+
+        \see ArgumentTraits
+     */
+    template <class Type>
+    void parse(ParseCommandInfo::TokensRange const & tokens, Type & out);
+
+    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);
+    };
+
+#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
+
+        Enum types need to be registered explicitly to support parsing. 
+        \code
+        enum Foo { Foo1, Foo2 };
+        SENF_CONSOLE_REGISTER_ENUM( Foo, (Foo1)(Foo2) );
+        \endcode
+        This macro will register an enum type and it's enumerators defined at namespace scope. See
+        \ref SENF_CONSOLE_REGISTER_ENUM_MEMBER to register a member enum type.
+
+        \note All enumerator values must be unique ignoring case.
+
+        The enum parser will accept any unique initial substring ignoring case as valid enum value.
+
+        \ingroup console_commands
+     */
+#   define SENF_CONSOLE_REGISTER_ENUM(Type, Values) \
+        SENF_CONSOLE_REGISTER_ENUM_(BOOST_PP_EMPTY(), Type, Values)
+
+    /** \brief Register enum type for argument parsing
+
+        Enum types need to be registered explicitly to support parsing. 
+        \code
+        class SomeClass
+        {
+            enum Foo { Foo1, Foo2 };
+        };
+
+        SENF_CONSOLE_REGISTER_ENUM_MEMBER( SomeClass, Foo, (Foo1)(Foo2) );
+        \endcode This macro will register an enum type and it's enumerators defined in a class. See
+        \ref SENF_CONSOLE_REGISTER_ENUM to register an enum type declared at namespace scope.
+
+        \ingroup console_commands
+     */
+#   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. 
+
+        \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;
+    };
+
+    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);
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Traits.cci"
+#include "Traits.ct"
+#include "Traits.cti"
+#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: