00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00059
00060
00061
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
00183 {
00184 ;
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