Search:

SENF Extensible Network Framework

  • Home
  • Download
  • Wiki
  • BerliOS
  • ChangeLog
  • Browse SVN
  • Bug Tracker
  • Overview
  • Examples
  • HowTos
  • Glossary
  • PPI
  • Packets
  • Scheduler
  • Socket
  • Utils
  • Console
  • Daemon
  • Logger
  • Termlib
  • Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

ParsedCommand.mpp

Go to the documentation of this file.
00001 // $Id: ParsedCommand.mpp 1742 2010-11-04 14:51:56Z g0dil $
00002 //
00003 // Copyright (C) 2008
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Stefan Bund <g0dil@berlios.de>
00007 //
00008 // This program is free software; you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation; either version 2 of the License, or
00011 // (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the
00020 // Free Software Foundation, Inc.,
00021 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00026 #if !BOOST_PP_IS_ITERATING && !defined(MPP_ParsedCommand_)
00027 #define MPP_ParsedCommand_ 1
00028 
00029 // Custom includes
00030 #include <boost/preprocessor/iteration/iterate.hpp>
00031 #include <boost/preprocessor/repetition/enum_trailing.hpp>
00032 #include <boost/preprocessor/repetition/enum_params.hpp>
00033 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
00034 #include <boost/preprocessor/cat.hpp>
00035 #include <boost/preprocessor/arithmetic/inc.hpp>
00036 #include <boost/preprocessor/arithmetic/sub.hpp>
00037 #include <boost/preprocessor/repetition/repeat.hpp>
00038 #include <boost/type_traits/remove_reference.hpp>
00039 #include <boost/type_traits/remove_const.hpp>
00040 #include <boost/bind.hpp>
00041 #include <boost/mpl/vector.hpp>
00042 #include <boost/mpl/at.hpp>
00043 #include "senf/Utils/IgnoreValue.hh"
00044 
00045 //-///////////////////////////mpp.p////////////////////////////////////////
00046 #elif BOOST_PP_IS_ITERATING //-
00047 //-
00048 // Local Macros
00049 
00050 #define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
00051 #define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
00052 
00053 #define mpp_TrailingArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
00054 #define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_TrailingArgTypes_, _ )
00055 
00056 #define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
00057 #define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
00058 
00059 #define mpp_Args_(z,n,d) mpp_ArgN(n)
00060 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
00061 
00062 #define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
00063 #define mpp_TrailingBindArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_BindArgs_, _ )
00064 
00065 //-////////////////////////////////////////////////////////////////////////
00066 #if BOOST_PP_ITERATION_FLAGS()==1 //-
00067 //-
00068 
00069 // Header file (.hh)
00070 
00071 template <class FunctionTraits, class ReturnValue>
00072 class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
00073     : public ParsedCommandOverloadBase
00074 {
00075 public:
00076     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
00077     typedef FunctionTraits traits;
00078     typedef boost::function<typename traits::result_type(std::ostream &
00079                                                          mpp_TrailingArgTypes())> Function;
00080     typedef typename senf::remove_cvref<typename traits::result_type>::type result_type;
00081     typedef boost::function<void (result_type const &, std::ostream &)> Formatter;
00082 
00083 #   define mpp_l(z,n,d)                                                                           \
00084         typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type             \
00085             mpp_ArgTypeN(n);
00086     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
00087 #   undef mpp_l
00088 
00089     typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
00090 
00091     static ptr create(Function fn);
00092 
00093     void formatter(Formatter f);
00094 
00095     using ParsedCommandOverloadBase::arg;
00096     template <unsigned n>
00097     detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
00098 
00099     void function(Function fn);
00100 
00101 protected:
00102 
00103 private:
00104     ParsedCommandOverload(Function fn);
00105 
00106     virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
00107         const;
00108 
00109     Function function_;
00110     Formatter formatter_;
00111 };
00112 
00113 template <class FunctionTraits>
00114 class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
00115     : public ParsedCommandOverloadBase
00116 {
00117 public:
00118     typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
00119     typedef FunctionTraits traits;
00120     typedef boost::function<typename traits::result_type(std::ostream &
00121                                                          mpp_TrailingArgTypes())> Function;
00122     typedef void result_type;
00123 
00124 #   define mpp_l(z,n,d)                                                                           \
00125         typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type             \
00126             mpp_ArgTypeN(n);
00127     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
00128 #   undef mpp_l
00129 
00130     typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
00131 
00132     static ptr create(Function fn);
00133 
00134     using ParsedCommandOverloadBase::arg;
00135     template <unsigned n>
00136     detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
00137 
00138     void function(Function fn);
00139 
00140 protected:
00141 
00142 private:
00143     ParsedCommandOverload(Function fn);
00144 
00145     virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
00146         const;
00147 
00148     Function function_;
00149 };
00150 
00151 //-////////////////////////////////////////////////////////////////////////
00152 #elif BOOST_PP_ITERATION_FLAGS()==2 //-
00153 //-
00154 
00155 // inline template implementation (.cti)
00156 
00157 template <class FunctionTraits, class ReturnValue>
00158 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::ptr
00159 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
00160 create(Function fn)
00161 {
00162     return ptr(new ParsedCommandOverload(fn));
00163 }
00164 
00165 template <class FunctionTraits, class ReturnValue>
00166 void
00167 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
00168 formatter(Formatter f)
00169 {
00170     formatter_ = f;
00171 }
00172 
00173 template <class FunctionTraits, class ReturnValue>
00174 template <unsigned n>
00175 senf::console::detail::ArgumentInfo<
00176     typename boost::mpl::at_c<
00177         typename senf::console::ParsedCommandOverload<
00178             FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::arg_types,
00179         n>::type> &
00180 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
00181 arg() const
00182 {
00183     return static_cast< detail::ArgumentInfo<
00184         typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
00185 }
00186 
00187 template <class FunctionTraits, class ReturnValue>
00188 void
00189 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
00190 function(Function fn)
00191 {
00192     function_ = fn;
00193 }
00194 
00195 template <class FunctionTraits, class ReturnValue>
00196 prefix_
00197 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
00198 ParsedCommandOverload(Function fn)
00199     : function_ (fn)
00200 {
00201 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
00202     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
00203 #   undef mpp_l
00204 }
00205 
00206 template <class FunctionTraits>
00207 prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::ptr
00208 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
00209 create(Function fn)
00210 {
00211     return ptr(new ParsedCommandOverload(fn));
00212 }
00213 
00214 template <class FunctionTraits>
00215 template <unsigned n>
00216 senf::console::detail::ArgumentInfo<
00217     typename boost::mpl::at_c<
00218         typename senf::console::ParsedCommandOverload<
00219             FunctionTraits, void, BOOST_PP_ITERATION()>::arg_types,
00220         n>::type> &
00221 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
00222 arg() const
00223 {
00224     return static_cast< detail::ArgumentInfo<
00225         typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
00226 }
00227 
00228 template <class FunctionTraits>
00229 void
00230 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
00231 function(Function fn)
00232 {
00233     function_ = fn;
00234 }
00235 
00236 template <class FunctionTraits>
00237 prefix_
00238 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
00239 ParsedCommandOverload(Function fn)
00240     : function_ (fn)
00241 {
00242 #   define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
00243     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
00244 #   undef mpp_l
00245 }
00246 
00247 //-////////////////////////////////////////////////////////////////////////
00248 #elif BOOST_PP_ITERATION_FLAGS()==3 //-
00249 //-
00250 
00251 // non-inline template implementation (.ct)
00252 
00253 template <class FunctionTraits, class ReturnValue>
00254 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
00255 v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
00256     const
00257 {
00258     // We NEED to know the number of arguments beforehand so we can assign default values
00259     // correctly ... hrmpf ...
00260     unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
00261     if ( nArgs > BOOST_PP_ITERATION() )
00262         throw SyntaxErrorException("invalid number of arguments");
00263     int nDefaults ( BOOST_PP_ITERATION() - nArgs );
00264     senf::IGNORE( nDefaults );
00265 
00266     typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
00267         riterator;
00268     riterator i (boost::rbegin(command.arguments()));
00269     riterator const i_end (boost::rend(command.arguments()));
00270 
00271 #   define mpp_l(z,n,d)                                                                           \
00272         mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
00273         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
00274             if (i == i_end)                                                                       \
00275                 throw SyntaxErrorException("invalid number of arguments");                        \
00276             if (arg<n>().parser)                                                                  \
00277                 arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
00278             else                                                                                  \
00279                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
00280         }
00281 #   define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
00282     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
00283 #   undef mpp_l
00284 #   undef mpp_l_
00285 
00286     ReturnValue rvv (function_(os mpp_TrailingArgs()));
00287     rv = rvv;
00288     if (formatter_)
00289         formatter_(rvv, os);
00290     else
00291         ReturnValueTraits<result_type>::format(rvv, os);
00292     os << "\n";
00293 }
00294 
00295 template <class FunctionTraits>
00296 prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
00297 v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
00298     const
00299 {
00300     // We NEED to know the number of arguments beforehand so we can assign default values
00301     // correctly ... hrmpf ...
00302     unsigned nArgs ( std::distance(command.arguments().begin(), command.arguments().end()) );
00303     if ( nArgs > BOOST_PP_ITERATION() )
00304         throw SyntaxErrorException("invalid number of arguments");
00305     int nDefaults ( BOOST_PP_ITERATION() - nArgs );
00306     senf::IGNORE( nDefaults );
00307 
00308     typedef typename boost::range_reverse_iterator<const ParseCommandInfo::ArgumentsRange>::type
00309         riterator;
00310     riterator i (boost::rbegin(command.arguments()));
00311     riterator const i_end (boost::rend(command.arguments()));
00312 
00313 #   define mpp_l(z,n,d)                                                                           \
00314         mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
00315         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
00316             if (i == i_end)                                                                       \
00317                 throw SyntaxErrorException("invalid number of arguments");                        \
00318             if (arg<n>().parser)                                                                  \
00319                 arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
00320             else                                                                                  \
00321                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
00322         }
00323 #   define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
00324     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
00325 #   undef mpp_l
00326 #   undef mpp_l_
00327 
00328     function_(os mpp_TrailingArgs());
00329 }
00330 
00331 //-////////////////////////////////////////////////////////////////////////
00332 #elif BOOST_PP_ITERATION_FLAGS()==4 //-
00333 //-
00334 
00335 // CreateParsedCommandOverload
00336 
00337 template <class Traits>
00338 struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
00339 {
00340     typedef typename Traits::traits traits;
00341 
00342     template <class Function>
00343     static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
00344         {
00345             return senf::console::ParsedCommandOverload<traits>::create(
00346                 boost::bind(fn  mpp_TrailingBindArgs()) );
00347         }
00348 
00349 };
00350 
00351 //-////////////////////////////////////////////////////////////////////////
00352 #elif BOOST_PP_ITERATION_FLAGS()==5 //-
00353 //-
00354 
00355 // Create keyword arg forwarding functions
00356 
00357 template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) >
00358 next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
00359                 typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
00360                     kw = arg_params()) {
00361     return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
00362 }
00363 
00364 //-////////////////////////////////////////////////////////////////////////
00365 #endif //-
00366 //-
00367 // Undefine local Macros
00368 
00369 #undef mpp_TrailingBindArgs
00370 #undef mpp_BindArgs_
00371 
00372 #undef mpp_TrailingArgs
00373 #undef mpp_Args_
00374 
00375 #undef mpp_ArgTypes
00376 #undef mpp_ArgTypes_
00377 
00378 #undef mpp_TrailingArgTypes
00379 #undef mpp_TrailingArgTypes_
00380 
00381 #undef mpp_ArgN
00382 #undef mpp_ArgTypeN
00383 
00384 //-////////////////////////////////////////////////////////////////////////
00385 #endif //-
00386 //-
00387 
00388 
00389 // Local Variables:
00390 // mode: c++
00391 // fill-column: 100
00392 // comment-column: 40
00393 // c-file-style: "senf"
00394 // indent-tabs-mode: nil
00395 // ispell-local-dictionary: "american"
00396 // compile-command: "scons -u test"
00397 // End:

Contact: senf-dev@lists.berlios.de | © 2006-2010 Fraunhofer Institute for Open Communication Systems, Network Research