TCL_obj_templates.h
Go to the documentation of this file.
1 /*
2  @copyright Russell Standish 2000-2013
3  @author Russell Standish
4  This file is part of EcoLab
5 
6  Open source licensed under the MIT license. See LICENSE for details.
7 */
8 
9 /*
10  Standard C++ insists that function prototypes need to be declared
11  before any template that might make use of them. Since these *might*
12  include declarations from classdesc generated files, we put any such
13  templates into a separate header file. Users will need to add an
14  extra line
15  #include "TCL_obj_templates.h"
16  after including any .cd files.
17 */
18 
20 
21 #ifndef TCL_OBJ_TEMPLATES_H
22 #define TCL_OBJ_TEMPLATES_H
23 
24 #include "TCL_obj_base.h" // This should have been included already.
25 
26 namespace
27 {
28  int TCL_obj_template_not_included() {return 0;}
29 }
30 
31 namespace ecolab
32 {
33  // split between container support, and generic classdesc processed stuff here
34  template <class T>
35  typename enable_if<Not<is_container<T> >, void>::T
36  TCL_objp(TCL_obj_t& t,const classdesc::string& desc, T& arg, dummy<0> d=0)
37  {
39  }
40 
41  /*
42  This template ensures that an object is registered before processing members
43  */
44  template <class T>
45  void TCL_obj(TCL_obj_t& t,const classdesc::string& desc, T& arg)
46  {
47  TCL_obj_register(t,desc,arg);
48  TCL_objp(t,desc,arg);
49  TCL_obj_custom_register(desc,arg);
50  }
51 
52 
53  // deal with base classes
54  template <class T>
55  void TCL_obj_onbase(TCL_obj_t& t,const classdesc::string& desc, T& arg)
56  {
57  TCL_obj_register(t,desc,arg,true);
58  TCL_objp(t,desc,arg);
59  TCL_obj_custom_register(desc,arg);
60  }
61 
62 
63  template <class T>
65  {
66  T* object;
67  void pack(classdesc::pack_t& p) {::pack(p,string(),*object);}
68  void unpack(classdesc::pack_t& p) {::unpack(p,string(),*object);}
69  };
70 
71 
72  template <class T>
73  int TCL_obj_init(T& x)
74  {
75  if (isa(x,TCL_obj_t()))
76  {
77  TCL_obj_t *b=(TCL_obj_t *)(&x);
78  b->check_functor=new TCL_obj_checkr<T>;
79  ((TCL_obj_checkr<T>*)(b->check_functor))->object=&x;
80  }
81  return 1;
82  }
83 
85 #define make_model(x) \
86  namespace x##_ns { \
87  DEFINE_ECOLAB_LIBRARY; \
88  int TCL_obj_##x=(ecolab::TCL_obj_init(x),TCL_obj(ecolab::null_TCL_obj,(std::string)#x,x),1); \
89  }
90 
92 #define register(x) static int \
93  TCL_obj_register_##x=(ecolab::TCL_obj_register(ecolab::null_TCL_obj,(string)#x,x), \
94  TCL_obj(ecolab::null_TCL_obj,(string)#x,x),1)
95 
97 #define TCLTYPE(x) TCLTYPEBASE(x,x,)
98 #define TCLTYPEARGS(x) TCLTYPEBASE(x,x,(largv))
99 #define TCLPOLYTYPE(x,itf) TCLTYPEBASE(x,itf,)
100 #define TCLPOLYTYPEARGS(x,itf) TCLTYPEBASE(x,itf,(largv))
101 
102 #define TCLTYPEBASE(x,itf,contructorArgs) \
103  namespace x_tcltype_##x { \
104  DEFINE_ECOLAB_LIBRARY; \
105  \
106  int deleteobject(ClientData cd, Tcl_Interp *interp, int argc, const char **argv) \
107  { \
108  assert( strcmp(argv[0]+strlen(argv[0])-strlen(".delete"), \
109  ".delete")==0); \
110  std::string s(argv[0]); \
111  ecolab::TCL_obj_deregister(s.substr(0,s.length()-strlen(".delete"))); \
112  delete (x*)cd; \
113  return TCL_OK; \
114  } \
115  \
116  int createobject(ClientData cd, Tcl_Interp *interp, int argc, Tcl_Obj *const*argv) \
117  { \
118  if (argc<2) throw ecolab::error("object name not specified"); \
119  std::string name=Tcl_GetString(argv[1]); \
120  /* strip object name from argument list */ \
121  ecolab::TCL_args largv(1,argv); \
122  for (int i=2; i<argc; ++i) largv.pushObj(argv[i]); \
123  x *object=new x contructorArgs; \
124  ecolab::eraseAllNamesStartingWith(name); \
125  TCL_obj(ecolab::null_TCL_obj,name,*object); \
126  assert(ecolab::TCL_newcommand((name+".delete").c_str())); \
127  Tcl_CreateCommand(ecolab::interp(), \
128  (name+".delete").c_str(), \
129  (Tcl_CmdProc*)deleteobject, \
130  (ClientData)object,NULL); \
131  return TCL_OK; \
132  } \
133  \
134  int dummy=( \
135  /*gcc 3 bug */ /*assert(TCL_newcommand(#x)),*/ \
136  Tcl_CreateObjCommand \
137  (ecolab::interp(),#x, \
138  (Tcl_ObjCmdProc*)createobject,NULL,NULL),1); \
139  }
140 
141  /*
142  Code for supporting arrays of things
143  */
144 
145 
146  template <class T>
147  inline void tclret(const T&) {}
148 
149  inline void tclret(const char& x) {tclreturn() << x;}
150  inline void tclret(const signed char& x) {tclreturn() << x;}
151  inline void tclret(const unsigned char& x) {tclreturn() << x;}
152  inline void tclret(const int& x) {tclreturn() << x;}
153  inline void tclret(const unsigned int& x) {tclreturn() << x;}
154  inline void tclret(const long& x) {tclreturn() << x;}
155  inline void tclret(const unsigned long& x) {tclreturn() << x;}
156  inline void tclret(const short& x) {tclreturn() << x;}
157  inline void tclret(const unsigned short& x) {tclreturn() << x;}
158  inline void tclret(const bool& x) {tclreturn() << x;}
159  inline void tclret(const float& x) {tclreturn() << x;}
160  inline void tclret(const double& x) {tclreturn() << x;}
161  inline void tclret(const long double& x) {tclreturn() << x;}
162 #if defined(__GNUC__)
163  inline void tclret(const long long& x) {tclreturn() << x;}
164  inline void tclret(const unsigned long long& x) {tclreturn() << x;}
165 #endif
166 
167  template <class T>
168  inline void asgtclret(T& x,TCL_args& y) {}
169 
170  //inline void asgtclret(char& x, TCL_args& y) {x=y; tclreturn() << x;}
171  //inline void asgtclret(signed char& x, TCL_args& y) {x=y;tclreturn() << x;}
172  //inline void asgtclret(unsigned char& x, TCL_args& y) {x=y;tclreturn() << x;}
173  inline void asgtclret(int& x, TCL_args& y) {x=y;tclreturn() << x;}
174  inline void asgtclret(unsigned int& x, TCL_args& y) {x=y;tclreturn() << x;}
175  inline void asgtclret(long& x, TCL_args& y) {x=y;tclreturn() << x;}
176  //inline void asgtclret(unsigned long& x, TCL_args& y) {x=y;tclreturn() << x;}
177  //inline void asgtclret(short& x, TCL_args& y) {x=y;tclreturn() << x;}
178  //inline void asgtclret(unsigned short& x, TCL_args& y) {x=y;tclreturn() << x;}
179  inline void asgtclret(bool& x, TCL_args& y) {x=y;tclreturn() << x;}
180  inline void asgtclret(float& x, TCL_args& y) {x=y;tclreturn() << x;}
181  inline void asgtclret(double& x, TCL_args& y) {x=y;tclreturn() << x;}
182  //inline void asgtclret(long double& x, TCL_args& y) {x=y;tclreturn() << x;}
183 #if defined(__GNUC__)
184  //inline void asgtclret(long long& x, TCL_args& y) {x=y;tclreturn() << x;}
185  //inline void asgtclret(unsigned long long& x, TCL_args& y) {x=y;tclreturn() << x;}
186 #endif
187 
188  template <class T>
189  inline bool is_simpletype(const T& x) {return false;}
190 
191  inline bool is_simpletype(const char& x) {return true;}
192  inline bool is_simpletype(const signed char& x) {return true;}
193  inline bool is_simpletype(const unsigned char& x) {return true;}
194  inline bool is_simpletype(const int& x) {return true;}
195  inline bool is_simpletype(const unsigned int& x) {return true;}
196  inline bool is_simpletype(const long& x) {return true;}
197  inline bool is_simpletype(const unsigned long& x) {return true;}
198  inline bool is_simpletype(const short& x) {return true;}
199  inline bool is_simpletype(const unsigned short& x) {return true;}
200  inline bool is_simpletype(const bool& x) {return true;}
201  inline bool is_simpletype(const float& x) {return true;}
202  inline bool is_simpletype(const double& x) {return true;}
203  inline bool is_simpletype(const long double& x) {return true;}
204 #if defined(__GNUC__)
205  inline bool is_simpletype(const long long& x) {return true;}
206  inline bool is_simpletype(const unsigned long long& x) {return true;}
207 #endif
208 
209  template <class Object>
211  {
212  std::vector<int> dims; /* dimensions of multidimensional array */
213  Object *o; /* pointer to array of Objects */
214  void get(TCL_args a)
215  {
216  size_t i, idx;
217  for (i=0, idx=0; i<dims.size(); i++)
218  {
219  idx*=dims[i];
220  idx+=(int)a[i];
221  };
222  if (is_simpletype(o[idx]))
223  tclret(o[idx]);
224  else
225  {
226  /* create a default TCL name for index object */
227  string name=a[-1];
228  // *strrchr((const char*)name,'.')='\0';
229  name=name.substr(0,name.rfind('.'));/* strip off trailing .get from name */
230  name+='(';
231  name+=(const char*)a[0];
232  for (size_t i=1; i<dims.size(); i++)
233  {
234  name+=',';
235  name+=(const char*)a[i];
236  }
237  name+=')';
238  TCL_obj(null_TCL_obj,name,o[idx]);
239  tclreturn() << name;
240  }
241  }
242  void set(TCL_args a)
243  {
244  size_t i, idx;
245  for (i=0, idx=0; i<dims.size(); i++)
246  {
247  idx*=dims[i];
248  idx+=(int)a;
249  };
250  if (is_simpletype(o[idx]) )
251  asgtclret(o[idx],a);
252  else
253  {
254  /* last argument is taken to be the TCL name of indexed object */
255  string name=a;
256  TCL_obj(null_TCL_obj,name,o[idx]);
257  tclreturn() << name;
258  }
259  }
260  };
261 
262  template <class T>
263  void TCL_obj(TCL_obj_t& targ, const string& desc, classdesc::is_array ia,
264  T &arg,int dims,...)
265  {
266  int i, ncopies=1;
267  va_list ap;
268  va_start(ap,dims);
269 
270  /* initialise array handler object */
272  ah->o=&arg;
273  for (int i=0; i<dims; i++) ah->dims.push_back(va_arg(ap,int));
274 
275  /* create functors for the get and set methods */
278  get->init(*ah,&array_handler<T>::get);
279  get->name=desc+".get";
280  TCL_OBJ_DBG(printf("registering %s\n",get->name.c_str()));
281  Tcl_CreateObjCommand(interp(),get->name.c_str(),TCL_oproc,(ClientData)get,NULL);
282 
285  set->init(*ah,&array_handler<T>::set);
286  set->name=desc+".set";
287  TCL_OBJ_DBG(printf("registering %s\n",set->name.c_str()));
288  Tcl_CreateObjCommand(interp(),set->name.c_str(),TCL_oproc,(ClientData)set,NULL);
289  }
290 
291  /* deal with treenode & graphnode pointers */
292  template <class T>
293  void TCL_obj(TCL_obj_t& targ, const string& desc, classdesc::is_treenode dum, T& arg)
294  {if (arg) TCL_obj(targ,desc,*arg);}
295 
296  template <class T>
297  void TCL_obj(TCL_obj_t& targ, const string& desc, classdesc::is_graphnode dum, T& arg)
298  {if (arg) TCL_obj(targ,desc,*arg);}
299 
300 
301  template<class T, class CharT, class Traits>
302  typename classdesc::enable_if<
304  Not<is_container<T> > >, std::basic_istream<CharT,Traits>&>::T
305  operator>>(std::basic_istream<CharT,Traits>& x,T& y)
306  {
307  throw error("operator>> not implemented for %s",typeid(T).name());
308  return x;
309  }
310 
311  template<class T, class CharT, class Traits>
312  typename classdesc::enable_if<classdesc::is_enum<T>, std::basic_istream<CharT,Traits>&>::T
313  operator>>(std::basic_istream<CharT,Traits>& x,T& y)
314  {
315  string s;
316  x>>s;
317  y=enum_keys<T>()(s);
318  return x;
319  }
320 
321  template <class T>
322  std::istream& operator>>(std::istream& i, ecolab::ref<T>& a)
323  {
324  if (a)
325  i>>*a;
326  else
327  {T dummy; i>>dummy;} //throw away item
328  return i;
329  }
330 
331  template <class T>
332  eco_strstream& operator|(eco_strstream& o, ecolab::ref<T>& a)
333  {if (a) o|*a; return o;}
334 
335  template <class T> inline void member_entry<const T>::get()
336  {tclreturn()<<*memberptr;}
337  template <class T> inline void member_entry<T>::get()
338  {tclreturn()<<*memberptr;}
339 
340  template <class T> inline void member_entry<T>::put(const char *s)
341  {
342 #if (defined(__osf__))
343  /* Tru 64 istream fails when eof encountered while reading
344  stream !! - append a whitespace character to stream to
345  ensure correct behaviour */
346  const char *os=s;
347  s=new char[strlen(s)+2]; strcpy((char*)s,(char*)os);
348  strcat((char*)s," ");
349 #endif
350  assert(memberptr);
351  std::istringstream r(s); r>>*memberptr;
352  tclreturn() << s;
353 #if (defined(__osf__))
354  delete [] s;
355 #endif
356  }
357 
358  template <> inline void member_entry<string>::put(const char *s)
359  {
360  assert(memberptr);
361  *memberptr=s;
362  tclreturn() << s;
363  }
364 
365  template <class T> inline void member_entry<const Enum_handle<T> >::get()
366  {tclreturn()<<string(*memberptr);}
367 
368  template <class T> inline void member_entry<const Enum_handle<T> >::put(const char *s)
369  {
370  assert(memberptr);
371  *memberptr=s;
372  tclreturn() << s;
373  }
374 
375 #if 0
376  //template clash with std::string - resolve overload here
377  std::istream& operator>>(std::istream& s, std::string& x)
378  {
379  return std::operator>>(s,x);
380  }
381 #endif
382 
383  template <class T>
385  if (!datum) name.clear();
386  ::pack(buf,"",name);
387  if (name.length()) ::pack(buf,"",*datum);
388  }
389  template <class T>
391  ::unpack(buf,"",name);
392  if (name.length()) {
393  set(name.c_str());
394  ::unpack(buf,"",*datum);
395  }
396  }
397 
398  template <class T>
399  TCL_args& operator>>(TCL_args& a, T& x)
400  {std::istringstream s((char*)a); s>>x; return a;}
401 
402 }
403 
404 namespace classdesc_access
405 {
406  template <class T>
407  struct access_pack<ecolab::TCL_obj_ref<T> >
408  {
409  void operator()(classdesc::pack_t& buf, const classdesc::string& desc,
411  {arg.pack(buf);}
412  };
413 
414  template <class T>
415  struct access_unpack<ecolab::TCL_obj_ref<T> >
416  {
417  void operator()(classdesc::pack_t& buf, const classdesc::string& desc,
419  {arg.unpack(buf);}
420  };
421 
422  template <class T>
423  struct access_TCL_obj<classdesc::ref<T> >
424  {
425  void operator()(ecolab::TCL_obj_t& t, const classdesc::string& d, classdesc::ref<T>& a)
426  {
427  if (a)
428  TCL_obj(t,d,*a);
429  }
430  };
431 
432 }
433 
434 #endif /* TCL_OBJ_TEMPLATES_H */
An RAII class for returning values to TCL.
Definition: tcl++.h:563
a slightly safer way of referring to registered objects than bare pointers
Definition: TCL_obj_base.h:449
Definition: ref.h:27
An EcoLab string stream class.
Definition: eco_strstream.h:64
EcoLab exception class.
Definition: error.h:25
Tcl_Interp * interp()
default interpreter. Set to NULL when interp() is destroyed
Definition: tcl++.h:222
classdesc::TCL_obj_t null_TCL_obj
a null TCL_obj_t suitable for nothing if needed.
Definition: TCL_obj_base.h:624
Definition: TCL_obj_base.h:330
Definition: TCL_obj_base.h:267
class to allow access to private members
Definition: classdesc_access.h:21
Definition: TCL_obj_base.h:632
Definition: TCL_obj_base.h:327
Definition: TCL_obj_stl.h:185
Definition: TCL_obj_templates.h:210
bool isa(const trialT &x, const baseT &y)
Definition: isa_base.h:69
Definition: TCL_obj_base.h:511
class to allow access to private members
Definition: classdesc_access.h:22
void TCL_obj_custom_register(const string &desc, T &arg)
a &#39;hook&#39; to allow registrations to occur for TCL_objects (overriding base classes) ...
Definition: TCL_obj_base.h:668
controlled template specialisation: stolen from boost::enable_if.
Definition: TCL_obj_base.h:250
Represent arguments to TCL commands.
Definition: TCL_obj_base.h:138
Definition: TCL_obj_base.h:315
TCL access descriptor.
Definition: TCL_obj_templates.h:64
Definition: TCL_obj_base.h:364
Contains definitions related to classdesc functionality.
Definition: arrays.h:2514
Definition: pack_base.h:124
Definition: TCL_obj_base.h:124
_OPENMP
Definition: accessor.h:16
TCL_obj descriptor object.
Definition: TCL_obj_base.h:327
Definition: TCL_obj_base.h:27
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition: accessor.h:55
Definition: TCL_obj_base.h:631
Definition: TCL_obj_base.h:702