command.h

Go to the documentation of this file.
00001 /** @file tcl/command.h binds a wrapped c++ function to a
00002     tcl::arg_spec and a tcl::dispatcher */
00003 
00004 ///////////////////////////////////////////////////////////////////////
00005 //
00006 // Copyright (c) 1999-2004 California Institute of Technology
00007 // Copyright (c) 2004-2007 University of Southern California
00008 // Rob Peters <rjpeters at usc dot edu>
00009 //
00010 // created: Fri Jun 11 14:50:43 1999
00011 // commit: $Id: command.h 11876 2009-10-22 15:53:06Z icore $
00012 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/tcl/command.h $
00013 //
00014 // --------------------------------------------------------------------
00015 //
00016 // This file is part of GroovX
00017 //   [http://ilab.usc.edu/rjpeters/groovx/]
00018 //
00019 // GroovX is free software; you can redistribute it and/or modify it
00020 // under the terms of the GNU General Public License as published by
00021 // the Free Software Foundation; either version 2 of the License, or
00022 // (at your option) any later version.
00023 //
00024 // GroovX is distributed in the hope that it will be useful, but
00025 // WITHOUT ANY WARRANTY; without even the implied warranty of
00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027 // General Public License for more details.
00028 //
00029 // You should have received a copy of the GNU General Public License
00030 // along with GroovX; if not, write to the Free Software Foundation,
00031 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00032 //
00033 ///////////////////////////////////////////////////////////////////////
00034 
00035 #ifndef GROOVX_TCL_COMMAND_H_UTC20050628162421_DEFINED
00036 #define GROOVX_TCL_COMMAND_H_UTC20050628162421_DEFINED
00037 
00038 #include "tcl/argspec.h"
00039 #include "tcl/conversions.h"
00040 #include "tcl/obj.h"
00041 
00042 #include "rutz/shared_ptr.h"
00043 
00044 typedef struct Tcl_Obj Tcl_Obj;
00045 
00046 namespace rutz
00047 {
00048   class file_pos;
00049   class fstring;
00050   template <class T> class shared_ptr;
00051 }
00052 
00053 namespace tcl
00054 {
00055   class arg_spec;
00056   class function;
00057   class command;
00058   class call_context;
00059   class arg_dispatcher;
00060   class interpreter;
00061 }
00062 
00063 /// Abstract interface for the core function to be embedded in a tcl::command.
00064 class tcl::function
00065 {
00066 public:
00067   virtual ~function() throw();
00068 
00069   /// Abstract function performs this command's specific functionality.
00070   /** The \c tcl::call_context& argument allows Tcl command arguments
00071       to be retrieved, and allows the interpreter's result to be
00072       set.*/
00073   virtual void invoke(tcl::call_context& ctx) = 0;
00074 };
00075 
00076 ///////////////////////////////////////////////////////////////////////
00077 /**
00078  *
00079  * \c tcl::command provides a way to wrap Tcl commands in C++
00080  * classes. The \c tcl::command class itself takes care of such things
00081  * as checking the argument count, and issuing an error message if the
00082  * argument count is incorrect.
00083  *
00084  * \c tcl::command uses class \c tcl::call_context to represent the
00085  * set of Tcl command arguments and the interpreter's result.
00086  *
00087  * If more than one tcl::command is created with the same name, an
00088  * overloading sequence is created. Overloading is done by argument
00089  * counts. The first tcl::command in an overload sequence to match the
00090  * argument count of the context will be used.
00091  *
00092  * Most clients of tcl::command will be able to simply use
00093  * tcl::make_command() or tcl::make_vec_command(), which detect the
00094  * types of C++ functions and build generic tcl::command's that call
00095  * the functions appropriately, or use tcl::pkg::def() and related
00096  * functions, which call tcl::make_command() but in addition help to
00097  * relate the commands to a particular package.
00098  *
00099  **/
00100 ///////////////////////////////////////////////////////////////////////
00101 
00102 class tcl::command
00103 {
00104 public:
00105   /// Build a tcl::command object.
00106   /** BUT, you almost certainly don't want to use this function
00107       directly, but should instead call tcl::command_group::make(). If
00108       you just create a tcl::command on its own, it won't do anything
00109       (it won't be registered with the tcl interpreter). The
00110       tcl::command needs to be hooked into a tcl::command_group, and
00111       the way to do that is by creating it through
00112       tcl::command_group::make(). */
00113   command(rutz::shared_ptr<tcl::function> callback,
00114           const char* usage, const arg_spec& spec);
00115 
00116   /// Non-virtual destructor since this class is not for use as a base class.
00117   ~command() throw();
00118 
00119   /// Returns a string describing the arguments expected by this command.
00120   rutz::fstring usage_string() const;
00121 
00122   /// Check if the given argument count is acceptable.
00123   bool allows_argc(unsigned int objc) const;
00124 
00125   /// Check if the given argument count is unacceptable.
00126   bool rejects_argc(unsigned int objc) const;
00127 
00128   /// Send arguments to its tcl::function via its tcl::arg_dispatcher.
00129   void call(tcl::interpreter& interp,
00130             unsigned int objc, Tcl_Obj* const objv[]);
00131 
00132   /// Get the current tcl::arg_dispatcher for this command.
00133   rutz::shared_ptr<arg_dispatcher> get_dispatcher() const;
00134 
00135   /// Change the tcl::arg_dispatcher for this command.
00136   void set_dispatcher(rutz::shared_ptr<arg_dispatcher> dpx);
00137 
00138 private:
00139   command(const command&); // not implemented
00140   command& operator=(const command&); // not implemented
00141 
00142   class impl;
00143   impl* const rep;
00144 };
00145 
00146 ///////////////////////////////////////////////////////////////////////
00147 /**
00148  *
00149  * \c tcl::arg_dispatcher. This may be subclassed in order to provide
00150  * a different interface to the raw Tcl arguments (such as for
00151  * vectorizing a function over a set of arguments). The default
00152  * dispatcher used by tcl::command's implementation just sets up a \c
00153  * tcl::call_context and calls \a invoke().  Errors should be signaled
00154  * by throwing appropriate exceptions, which will be caught and
00155  * returned back to the Tcl interpreter as normal Tcl error messages.
00156  *
00157  **/
00158 ///////////////////////////////////////////////////////////////////////
00159 
00160 class tcl::arg_dispatcher
00161 {
00162 public:
00163   /// Virtual destructor.
00164   virtual ~arg_dispatcher() throw();
00165 
00166   /** Interprets the Tcl_Obj* arguments, sets up an appropriate
00167       tcl::call_context, and calls invoke() on the \a cmd with that
00168       context. */
00169   virtual void dispatch(tcl::interpreter& interp,
00170                         unsigned int objc, Tcl_Obj* const objv[],
00171                         tcl::function& callback) = 0;
00172 };
00173 
00174 ///////////////////////////////////////////////////////////////////////
00175 /**
00176  *
00177  * \c tcl::call_context, which is passed to \a tcl::command::invoke(),
00178  * provides a get_arg() for getting values from command arguments, and
00179  * provides set_result() for returning values to the Tcl interpreter.
00180  *
00181  **/
00182 ///////////////////////////////////////////////////////////////////////
00183 
00184 class tcl::call_context
00185 {
00186 public:
00187   friend class tcl::command;
00188 
00189   /// Construct with a Tcl interpreter and an argument list.
00190   call_context(tcl::interpreter& interp,
00191                unsigned int objc, Tcl_Obj* const* objv);
00192 
00193   /// Virtual destructor.
00194   virtual ~call_context() throw();
00195 
00196   /// Get the Tcl interpreter of the current invocation.
00197   tcl::interpreter& interp() const throw() { return m_interp; }
00198 
00199   /// Return the number of arguments in the current invocation.
00200   unsigned int objc() const throw() { return m_objc; }
00201 
00202 
00203   /** Attempt to convert argument number \a argn to type \c T, and
00204       return the result of the conversion. */
00205   template <class T>
00206   typename returnable<T>::type get_arg(unsigned int argn)
00207     {
00208       return tcl::convert_to<T>(get_objv(argn));
00209     }
00210 
00211 
00212   /// Return satisfactorily with the result \a t of type \c T.
00213   template <class T>
00214   void set_result(T t)
00215     {
00216       set_obj_result(tcl::convert_from<T>(t));
00217     }
00218 
00219   /// Get the raw objv array.
00220   Tcl_Obj* const* get_raw_args() const throw()
00221     {
00222       return m_objv;
00223     }
00224 
00225 protected:
00226   /// Get the n'th argument.
00227   virtual Tcl_Obj* get_objv(unsigned int n) throw() { return m_objv[n]; }
00228 
00229   /// Return a Tcl_Obj*.
00230   virtual void set_obj_result(const tcl::obj& obj);
00231 
00232 private:
00233   call_context(const call_context&);
00234   call_context& operator=(const call_context&);
00235 
00236   tcl::interpreter&        m_interp;
00237   unsigned int       const m_objc;
00238   Tcl_Obj* const*    const m_objv;
00239 };
00240 
00241 static const char __attribute__((used)) vcid_groovx_tcl_command_h_utc20050628162421[] = "$Id: command.h 11876 2009-10-22 15:53:06Z icore $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/tcl/command.h $";
00242 #endif // !GROOVX_TCL_COMMAND_H_UTC20050628162421_DEFINED
Generated on Sun May 8 08:06:54 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3