From: g0dil Date: Tue, 15 Apr 2008 22:22:44 +0000 (+0000) Subject: Console: Implement custom return-value formatter support X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=81a550d520e8531b7f353e1ce0da5b99c249cecb;p=senf.git Console: Implement custom return-value formatter support git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@813 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/ParsedCommand.cti b/Console/ParsedCommand.cti index f4b523f..029fa2d 100644 --- a/Console/ParsedCommand.cti +++ b/Console/ParsedCommand.cti @@ -126,9 +126,43 @@ senf::console::ParsedCommandAttributor::ParsedCommandAttributor(Overlo /////////////////////////////////////////////////////////////////////////// // senf::console::ParsedArgumentAttributorBase +template +prefix_ Self +senf::console::ParsedArgumentAttributorBase::doc(std::string const & doc) + const +{ + this->ParsedCommandAttributorBase::nodeDoc(doc); + return static_cast(*this); +} + +template +prefix_ Self senf::console::ParsedArgumentAttributorBase:: +overloadDoc(std::string const & doc) + const +{ + this->ParsedCommandAttributorBase::overloadDoc(doc); + return static_cast(*this); +} + +template +prefix_ Self senf::console::ParsedArgumentAttributorBase:: +formatter(typename Overload::Formatter f) + const +{ + this->overload().formatter(f); + return static_cast(*this); +} + +template +prefix_ +senf::console::ParsedArgumentAttributorBase:: +ParsedArgumentAttributorBase(Overload & overload, unsigned index) + : ParsedCommandAttributor (overload, index) +{} + template prefix_ Self -senf::console::ParsedArgumentAttributorBase::doc(std::string const & doc) +senf::console::ParsedArgumentAttributorBase::doc(std::string const & doc) const { this->ParsedCommandAttributorBase::nodeDoc(doc); @@ -136,7 +170,7 @@ senf::console::ParsedArgumentAttributorBase::doc(std::string cons } template -prefix_ Self senf::console::ParsedArgumentAttributorBase:: +prefix_ Self senf::console::ParsedArgumentAttributorBase:: overloadDoc(std::string const & doc) const { @@ -146,7 +180,7 @@ overloadDoc(std::string const & doc) template prefix_ -senf::console::ParsedArgumentAttributorBase:: +senf::console::ParsedArgumentAttributorBase:: ParsedArgumentAttributorBase(Overload & overload, unsigned index) : ParsedCommandAttributor (overload, index) {} @@ -379,23 +413,6 @@ senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & n senf::membind(fn,&owner)) ) ); } -/////////////////////////////////////////////////////////////////////////// -// senf::console::detail::CheckVoidReturn - -template -template -prefix_ void senf::console::detail::CheckVoidReturn::call(Fn fn, std::ostream & os) -{ - ReturnValueTraits::format(fn(),os); - os << "\n"; -} - -template -prefix_ void senf::console::detail::CheckVoidReturn::call(Fn fn, std::ostream & os) -{ - fn(); -} - ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/Console/ParsedCommand.hh b/Console/ParsedCommand.hh index 75724a8..a4ef298 100644 --- a/Console/ParsedCommand.hh +++ b/Console/ParsedCommand.hh @@ -168,8 +168,11 @@ namespace console { \c std::ostream first argument. \implementation This class is specialized for each supported number of command arguments. + + \todo Implement automatic binding of member functions for parser and formatter */ - template + template class ParsedCommandOverload : public ParsedCommandOverloadBase { public: @@ -213,12 +216,11 @@ namespace console { template void defaultValue(Type const & value) const; void typeName(std::string const & doc) const; void defaultDoc(std::string const & doc) const; - template void parser(Fn fn) const; ParsedCommandOverloadBase & overload() const; void overloadDoc(std::string const & doc) const; - void nodeDoc(std::string const & doc) const; + template void parser(Fn fn) const; private: ParsedCommandOverloadBase & overload_; @@ -404,13 +406,14 @@ namespace console { \see \ref console_autoparse */ - template + template class ParsedArgumentAttributorBase : public ParsedCommandAttributor { public: Self doc(std::string const & doc) const; ///< Set documentation for all overloads Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation + Self formatter(typename Overload::Formatter f) const; ///< Set return value formatter protected: ParsedArgumentAttributorBase(Overload & overload, unsigned index); @@ -418,6 +421,23 @@ namespace console { private: }; +#ifndef DOXYGEN + + template + class ParsedArgumentAttributorBase + : public ParsedCommandAttributor + { + public: + Self doc(std::string const & doc) const; ///< Set documentation for all overloads + Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation + + protected: + ParsedArgumentAttributorBase(Overload & overload, unsigned index); + + private: + }; + +#endif /** \brief Argument dependent ParsedCommandBase attributes diff --git a/Console/ParsedCommand.ih b/Console/ParsedCommand.ih index 19a4de6..d4a89f8 100644 --- a/Console/ParsedCommand.ih +++ b/Console/ParsedCommand.ih @@ -106,25 +106,13 @@ namespace detail { base_traits> ::type traits; + typedef typename senf::remove_cvref::type result_type; + static const bool is_member = boost::is_member_pointer::value; typedef typename senf::member_class::type class_type; }; - template - struct CheckVoidReturn - { - template - static void call(Fn fn, std::ostream & os); - }; - - template <> - struct CheckVoidReturn - { - template - static void call(Fn fn, std::ostream & os); - }; - #endif }}} diff --git a/Console/ParsedCommand.mpp b/Console/ParsedCommand.mpp index f1d6833..bfa3ef3 100644 --- a/Console/ParsedCommand.mpp +++ b/Console/ParsedCommand.mpp @@ -50,7 +50,7 @@ #define mpp_ArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n) #define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ ) -#define mpp_Args_(z,n,d) boost::cref(mpp_ArgN(n)) +#define mpp_Args_(z,n,d) mpp_ArgN(n) #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ ) #define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n))) @@ -62,8 +62,41 @@ // Header file (.hh) +template +class ParsedCommandOverload + : public ParsedCommandOverloadBase +{ +public: + typedef boost::intrusive_ptr ptr; + typedef FunctionTraits traits; + typedef boost::function Function; + typedef typename senf::remove_cvref::type result_type; + typedef boost::function Formatter; + +# define mpp_l(z,n,d) \ + typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \ + mpp_ArgTypeN(n); + BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ ) +# undef mpp_l + + static ptr create(Function fn); + + void formatter(Formatter f); + +protected: + +private: + ParsedCommandOverload(Function fn); + + virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const; + + Function function_; + Formatter formatter_; +}; + template -class ParsedCommandOverload +class ParsedCommandOverload : public ParsedCommandOverloadBase { public: @@ -71,6 +104,7 @@ public: typedef FunctionTraits traits; typedef boost::function Function; + typedef void result_type; # define mpp_l(z,n,d) \ typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \ @@ -96,16 +130,44 @@ private: // inline template implementation (.cti) +template +prefix_ typename senf::console::ParsedCommandOverload::ptr +senf::console::ParsedCommandOverload:: +create(Function fn) +{ + return ptr(new ParsedCommandOverload(fn)); +} + +template +void +senf::console::ParsedCommandOverload:: +formatter(Formatter f) +{ + formatter_ = f; +} + +template +prefix_ +senf::console::ParsedCommandOverload:: +ParsedCommandOverload(Function fn) + : function_ (fn) +{ +# define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >(); + BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ ) +# undef mpp_l +} + template -prefix_ typename senf::console::ParsedCommandOverload::ptr -senf::console::ParsedCommandOverload::create(Function fn) +prefix_ typename senf::console::ParsedCommandOverload::ptr +senf::console::ParsedCommandOverload:: +create(Function fn) { return ptr(new ParsedCommandOverload(fn)); } template prefix_ -senf::console::ParsedCommandOverload:: +senf::console::ParsedCommandOverload:: ParsedCommandOverload(Function fn) : function_ (fn) { @@ -120,8 +182,44 @@ ParsedCommandOverload(Function fn) // non-inline template implementation (.ct) +template +prefix_ void senf::console::ParsedCommandOverload:: +v_execute(std::ostream & os, ParseCommandInfo const & command) + const +{ + if ( command.arguments().size() > BOOST_PP_ITERATION() ) + throw SyntaxErrorException("invalid number of arguments"); + int nDefaults ( BOOST_PP_ITERATION() - command.arguments().size() ); + + typedef typename boost::range_const_reverse_iterator::type + riterator; + riterator i (boost::rbegin(command.arguments())); + riterator const i_end (boost::rend(command.arguments())); + +# define mpp_l(z,n,d) \ + mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue); \ + if (! arg(n).hasDefault || nDefaults-- <= 0) { \ + if (i == i_end) \ + throw SyntaxErrorException("invalid number of arguments"); \ + if (arg< mpp_ArgTypeN(n) >(n).parser) \ + arg< mpp_ArgTypeN(n) >(n).parser( *(i++), mpp_ArgN(n) ); \ + else \ + ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \ + } +# define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d) + BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ ) +# undef mpp_l +# undef mpp_l_ + + if (formatter_) + formatter_( function_(os mpp_TrailingArgs()), os ); + else + ReturnValueTraits::format( function_(os mpp_TrailingArgs()), os ); + os << "\n"; +} + template -prefix_ void senf::console::ParsedCommandOverload:: +prefix_ void senf::console::ParsedCommandOverload:: v_execute(std::ostream & os, ParseCommandInfo const & command) const { @@ -149,10 +247,7 @@ v_execute(std::ostream & os, ParseCommandInfo const & command) # undef mpp_l # undef mpp_l_ - detail::CheckVoidReturn::call( - boost::bind(function_, boost::ref(os) - mpp_TrailingArgs()), - os ); + function_(os mpp_TrailingArgs()); } // //////////////////////////////////////////////////////////////////////// diff --git a/Console/ParsedCommand.test.cc b/Console/ParsedCommand.test.cc index 39f028d..a9e47a4 100644 --- a/Console/ParsedCommand.test.cc +++ b/Console/ParsedCommand.test.cc @@ -58,6 +58,8 @@ namespace { { out = "true"; } }; + void testFormatter(double, std::ostream & os) + { os << "formatter"; } } BOOST_AUTO_UNIT_TEST(parsedCommand) @@ -137,7 +139,17 @@ BOOST_AUTO_UNIT_TEST(parsedCommand) parser.parse("test/cb6 false", boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); BOOST_CHECK_EQUAL( ss.str(), "Value: true\n" ); - + } + + { + std::stringstream ss; + + dir.add("cb7", &cb2) + .formatter( &testFormatter ); + BOOST_CHECK_NO_THROW( + parser.parse("test/cb7", + boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( ss.str(), "formatter\n" ); } {