vecdispatch.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2001-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Thu Jul 12 12:15:46 2001
00010 // commit: $Id: vecdispatch.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/tcl/vecdispatch.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_TCL_VECDISPATCH_CC_UTC20050628162420_DEFINED
00035 #define GROOVX_TCL_VECDISPATCH_CC_UTC20050628162420_DEFINED
00036 
00037 #include "tcl/vecdispatch.h"
00038 
00039 #include "tcl/command.h"
00040 #include "tcl/list.h"
00041 
00042 #include "rutz/error.h"
00043 #include "rutz/shared_ptr.h"
00044 
00045 #include <vector>
00046 
00047 #include "rutz/trace.h"
00048 #include "rutz/debug.h"
00049 GVX_DBG_REGISTER
00050 
00051 namespace tcl
00052 {
00053   class vec_context;
00054 }
00055 
00057 //
00058 // tcl::vec_context implements the tcl::call_context interface in such
00059 // a way as to treat each of the arguments as lists, and provide
00060 // access to slices across those lists, thus allowing "vectorized"
00061 // command invocations.
00062 //
00064 
00065 class tcl::vec_context : public tcl::call_context
00066 {
00067 public:
00068   vec_context(tcl::interpreter& interp, unsigned int objc,
00069               Tcl_Obj* const objv[]) :
00070     call_context(interp, objc, objv),
00071     m_arg0(objv[0]),
00072     m_args(),
00073     m_result()
00074   {
00075     for (unsigned int i = 1; i < objc; ++i)
00076       {
00077         tcl::list arg(objv[i]);
00078         if (arg.length() == 0)
00079           {
00080             throw rutz::error("argument was empty", SRC_POS);
00081           }
00082         m_args.push_back( arg.begin<Tcl_Obj*>() );
00083       }
00084   }
00085 
00086   virtual ~vec_context() throw() {}
00087 
00088   void flush_result()
00089   {
00090     tcl::call_context::set_obj_result(m_result.as_obj());
00091   }
00092 
00093   void next()
00094   {
00095     for (unsigned int i = 0; i < m_args.size(); ++i)
00096       {
00097         if (m_args[i].has_more())
00098           ++(m_args[i]);
00099       }
00100   }
00101 
00102 protected:
00103   virtual Tcl_Obj* get_objv(unsigned int argn) throw()
00104   {
00105     if (argn == 0) return m_arg0;
00106 
00107     return *(m_args.at(argn-1));
00108   }
00109 
00110   virtual void set_obj_result(const tcl::obj& obj)
00111   {
00112     m_result.append(obj);
00113   }
00114 
00115 private:
00116   typedef tcl::list::iterator<Tcl_Obj*> Iter;
00117 
00118   Tcl_Obj* m_arg0;
00119   std::vector<Iter> m_args;
00120   tcl::list m_result;
00121 };
00122 
00123 namespace tcl
00124 {
00125   class vec_dispatcher;
00126 }
00127 
00129 
00137 
00138 
00139 class tcl::vec_dispatcher : public tcl::arg_dispatcher
00140 {
00141 public:
00142   vec_dispatcher(unsigned int key_argn) : m_key_argn(key_argn) {}
00143 
00144   virtual ~vec_dispatcher() throw() {}
00145 
00146   virtual void dispatch(tcl::interpreter& interp,
00147                         unsigned int objc, Tcl_Obj* const objv[],
00148                         tcl::function& callback);
00149 
00150 private:
00151   unsigned int m_key_argn;
00152 };
00153 
00154 
00155 void tcl::vec_dispatcher::dispatch(tcl::interpreter& interp,
00156                                    unsigned int objc,
00157                                    Tcl_Obj* const objv[],
00158                                    tcl::function& callback)
00159 {
00160 GVX_TRACE("tcl::vec_dispatcher::dispatch");
00161 
00162   const unsigned int ncalls
00163     = tcl::list::get_obj_list_length(objv[m_key_argn]);
00164 
00165   if (ncalls > 1)
00166     {
00167       vec_context cx(interp, objc, objv);
00168 
00169       for (unsigned int c = 0; c < ncalls; ++c)
00170         {
00171           callback.invoke(cx);
00172           cx.next();
00173         }
00174 
00175       cx.flush_result();
00176     }
00177   else if (ncalls == 1)
00178     {
00179       tcl::call_context cx(interp, objc, objv);
00180       callback.invoke(cx);
00181     }
00182   else // (ncalls == 0)
00183     {
00184       ;// do nothing, so we gracefully handle empty lists
00185     }
00186 }
00187 
00188 
00189 void tcl::use_vec_dispatch(tcl::command& cmd, unsigned int key_argn)
00190 {
00191   cmd.set_dispatcher(rutz::make_shared(new vec_dispatcher(key_argn)));
00192 }
00193 
00194 static const char __attribute__((used)) vcid_groovx_tcl_vecdispatch_cc_utc20050628162420[] = "$Id: vecdispatch.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00195 #endif // !GROOVX_TCL_VECDISPATCH_CC_UTC20050628162420_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:41 2008 by Doxygen version 1.5.5.