1/* ----------------------------------------------------------------------------- 2 * See the LICENSE file for information on copyright, usage and redistribution 3 * of SWIG, and the README file for authors - http://www.swig.org/release.html. 4 * 5 * std_vector.i 6 * ----------------------------------------------------------------------------- */ 7 8%include <std_common.i> 9 10// ------------------------------------------------------------------------ 11// std::vector 12// 13// The aim of all that follows would be to integrate std::vector with 14// Tcl as much as possible, namely, to allow the user to pass and 15// be returned Tcl lists. 16// const declarations are used to guess the intent of the function being 17// exported; therefore, the following rationale is applied: 18// 19// -- f(std::vector< T >), f(const std::vector< T >&), f(const std::vector< T >*): 20// the parameter being read-only, either a Tcl list or a 21// previously wrapped std::vector< T > can be passed. 22// -- f(std::vector< T >&), f(std::vector< T >*): 23// the parameter must be modified; therefore, only a wrapped std::vector 24// can be passed. 25// -- std::vector< T > f(): 26// the vector is returned by copy; therefore, a Tcl list of T:s 27// is returned which is most easily used in other Tcl functions procs 28// -- std::vector< T >& f(), std::vector< T >* f(), const std::vector< T >& f(), 29// const std::vector< T >* f(): 30// the vector is returned by reference; therefore, a wrapped std::vector 31// is returned 32// ------------------------------------------------------------------------ 33 34%{ 35#include <vector> 36#include <algorithm> 37#include <stdexcept> 38#include <string> 39 40Tcl_Obj* SwigString_FromString(const std::string &s) { 41 return Tcl_NewStringObj(s.data(), (int)s.length()); 42} 43 44int Tcl_GetBoolFromObj(Tcl_Interp *interp, Tcl_Obj *o, bool *val) { 45 int v; 46 int res = Tcl_GetBooleanFromObj(interp, o, &v); 47 if (res == TCL_OK) { 48 *val = v ? true : false; 49 } 50 return res; 51} 52 53int SwigString_AsString(Tcl_Interp *interp, Tcl_Obj *o, std::string *val) { 54 int len; 55 const char* temp = Tcl_GetStringFromObj(o, &len); 56 if (temp == NULL) 57 return TCL_ERROR; 58 val->assign(temp, len); 59 return TCL_OK; 60} 61 62// behaviour of this is such as the real Tcl_GetIntFromObj 63template <typename Type> 64int SwigInt_As(Tcl_Interp *interp, Tcl_Obj *o, Type *val) { 65 int temp_val, return_val; 66 return_val = Tcl_GetIntFromObj(interp, o, &temp_val); 67 *val = (Type) temp_val; 68 return return_val; 69} 70 71// behaviour of this is such as the real Tcl_GetDoubleFromObj 72template <typename Type> 73int SwigDouble_As(Tcl_Interp *interp, Tcl_Obj *o, Type *val) { 74 int return_val; 75 double temp_val; 76 return_val = Tcl_GetDoubleFromObj(interp, o, &temp_val); 77 *val = (Type) temp_val; 78 return return_val; 79} 80 81%} 82 83// exported class 84 85namespace std { 86 87 template<class T> class vector { 88 %typemap(in) vector< T > (std::vector< T > *v) { 89 Tcl_Obj **listobjv; 90 int nitems; 91 int i; 92 T* temp; 93 94 if (SWIG_ConvertPtr($input, (void **) &v, \ 95 $&1_descriptor, 0) == 0){ 96 $1 = *v; 97 } else { 98 // It isn't a vector< T > so it should be a list of T's 99 if(Tcl_ListObjGetElements(interp, $input, \ 100 &nitems, &listobjv) == TCL_ERROR) 101 return TCL_ERROR; 102 $1 = std::vector< T >(); 103 for (i = 0; i < nitems; i++) { 104 if ((SWIG_ConvertPtr(listobjv[i],(void **) &temp, 105 $descriptor(T *),0)) != 0) { 106 char message[] = 107 "list of " #T " expected"; 108 Tcl_SetResult(interp, message, TCL_VOLATILE); 109 return TCL_ERROR; 110 } 111 $1.push_back(*temp); 112 } 113 } 114 } 115 116 %typemap(in) const vector< T >* (std::vector< T > *v, std::vector< T > w), 117 const vector< T >& (std::vector< T > *v, std::vector< T > w) { 118 Tcl_Obj **listobjv; 119 int nitems; 120 int i; 121 T* temp; 122 123 if(SWIG_ConvertPtr($input, (void **) &v, \ 124 $&1_descriptor, 0) == 0) { 125 $1 = v; 126 } else { 127 // It isn't a vector< T > so it should be a list of T's 128 if(Tcl_ListObjGetElements(interp, $input, 129 &nitems, &listobjv) == TCL_ERROR) 130 return TCL_ERROR; 131 w = std::vector< T >(); 132 for (i = 0; i < nitems; i++) { 133 if ((SWIG_ConvertPtr(listobjv[i],(void **) &temp, 134 $descriptor(T *),0)) != 0) { 135 char message[] = 136 "list of " #T " expected"; 137 Tcl_SetResult(interp, message, TCL_VOLATILE); 138 return TCL_ERROR; 139 } 140 w.push_back(*temp); 141 } 142 $1 = &w; 143 } 144 } 145 146 %typemap(out) vector< T > { 147 for (unsigned int i=0; i<$1.size(); i++) { 148 T* ptr = new T((($1_type &)$1)[i]); 149 Tcl_ListObjAppendElement(interp, $result, \ 150 SWIG_NewInstanceObj(ptr, 151 $descriptor(T *), 152 0)); 153 } 154 } 155 156 %typecheck(SWIG_TYPECHECK_VECTOR) vector< T > { 157 Tcl_Obj **listobjv; 158 int nitems; 159 T* temp; 160 std::vector< T > *v; 161 162 if(SWIG_ConvertPtr($input, (void **) &v, \ 163 $&1_descriptor, 0) == 0) { 164 /* wrapped vector */ 165 $1 = 1; 166 } else { 167 // It isn't a vector< T > so it should be a list of T's 168 if(Tcl_ListObjGetElements(interp, $input, 169 &nitems, &listobjv) == TCL_ERROR) 170 $1 = 0; 171 else 172 if (nitems == 0) 173 $1 = 1; 174 //check the first value to see if it is of correct type 175 else if ((SWIG_ConvertPtr(listobjv[0], 176 (void **) &temp, 177 $descriptor(T *),0)) != 0) 178 $1 = 0; 179 else 180 $1 = 1; 181 } 182 } 183 184 %typecheck(SWIG_TYPECHECK_VECTOR) const vector< T >&, 185 const vector< T >* { 186 Tcl_Obj **listobjv; 187 int nitems; 188 T* temp; 189 std::vector< T > *v; 190 191 if(SWIG_ConvertPtr($input, (void **) &v, \ 192 $1_descriptor, 0) == 0){ 193 /* wrapped vector */ 194 $1 = 1; 195 } else { 196 // It isn't a vector< T > so it should be a list of T's 197 if(Tcl_ListObjGetElements(interp, $input, 198 &nitems, &listobjv) == TCL_ERROR) 199 $1 = 0; 200 else 201 if (nitems == 0) 202 $1 = 1; 203 //check the first value to see if it is of correct type 204 else if ((SWIG_ConvertPtr(listobjv[0], 205 (void **) &temp, 206 $descriptor(T *),0)) != 0) 207 $1 = 0; 208 else 209 $1 = 1; 210 } 211 } 212 213 public: 214 vector(unsigned int size = 0); 215 vector(unsigned int size, const T& value); 216 vector(const vector< T > &); 217 218 unsigned int size() const; 219 bool empty() const; 220 void clear(); 221 %rename(push) push_back; 222 void push_back(const T& x); 223 %extend { 224 T pop() throw (std::out_of_range) { 225 if (self->size() == 0) 226 throw std::out_of_range("pop from empty vector"); 227 T x = self->back(); 228 self->pop_back(); 229 return x; 230 } 231 T& get(int i) throw (std::out_of_range) { 232 int size = int(self->size()); 233 if (i<0) i += size; 234 if (i>=0 && i<size) 235 return (*self)[i]; 236 else 237 throw std::out_of_range("vector index out of range"); 238 } 239 void set(int i, const T& x) throw (std::out_of_range) { 240 int size = int(self->size()); 241 if (i<0) i+= size; 242 if (i>=0 && i<size) 243 (*self)[i] = x; 244 else 245 throw std::out_of_range("vector index out of range"); 246 } 247 } 248 }; 249 250 251 // specializations for built-ins 252 253 %define specialize_std_vector(T, CONVERT_FROM, CONVERT_TO) 254 template<> class vector< T > { 255 256 %typemap(in) vector< T > (std::vector< T > *v){ 257 Tcl_Obj **listobjv; 258 int nitems; 259 int i; 260 T temp; 261 262 if(SWIG_ConvertPtr($input, (void **) &v, \ 263 $&1_descriptor, 0) == 0) { 264 $1 = *v; 265 } else { 266 // It isn't a vector< T > so it should be a list of T's 267 if(Tcl_ListObjGetElements(interp, $input, 268 &nitems, &listobjv) == TCL_ERROR) 269 return TCL_ERROR; 270 $1 = std::vector< T >(); 271 for (i = 0; i < nitems; i++) { 272 if (CONVERT_FROM(interp, listobjv[i], &temp) == TCL_ERROR) 273 return TCL_ERROR; 274 $1.push_back(temp); 275 } 276 } 277 } 278 279 %typemap(in) const vector< T >& (std::vector< T > *v,std::vector< T > w), 280 const vector< T >* (std::vector< T > *v,std::vector< T > w) { 281 Tcl_Obj **listobjv; 282 int nitems; 283 int i; 284 T temp; 285 286 if(SWIG_ConvertPtr($input, (void **) &v, \ 287 $1_descriptor, 0) == 0) { 288 $1 = v; 289 } else { 290 // It isn't a vector< T > so it should be a list of T's 291 if(Tcl_ListObjGetElements(interp, $input, 292 &nitems, &listobjv) == TCL_ERROR) 293 return TCL_ERROR; 294 w = std::vector< T >(); 295 for (i = 0; i < nitems; i++) { 296 if (CONVERT_FROM(interp, listobjv[i], &temp) == TCL_ERROR) 297 return TCL_ERROR; 298 w.push_back(temp); 299 } 300 $1 = &w; 301 } 302 } 303 304 %typemap(out) vector< T > { 305 for (unsigned int i=0; i<$1.size(); i++) { 306 Tcl_ListObjAppendElement(interp, $result, \ 307 CONVERT_TO((($1_type &)$1)[i])); 308 } 309 } 310 311 %typecheck(SWIG_TYPECHECK_VECTOR) vector< T > { 312 Tcl_Obj **listobjv; 313 int nitems; 314 T temp; 315 std::vector< T > *v; 316 317 if(SWIG_ConvertPtr($input, (void **) &v, \ 318 $&1_descriptor, 0) == 0){ 319 /* wrapped vector */ 320 $1 = 1; 321 } else { 322 // It isn't a vector< T > so it should be a list of T's 323 if(Tcl_ListObjGetElements(interp, $input, 324 &nitems, &listobjv) == TCL_ERROR) 325 $1 = 0; 326 else 327 if (nitems == 0) 328 $1 = 1; 329 //check the first value to see if it is of correct type 330 if (CONVERT_FROM(interp, listobjv[0], &temp) == TCL_ERROR) 331 $1 = 0; 332 else 333 $1 = 1; 334 } 335 } 336 337 %typecheck(SWIG_TYPECHECK_VECTOR) const vector< T >&, 338 const vector< T >*{ 339 Tcl_Obj **listobjv; 340 int nitems; 341 T temp; 342 std::vector< T > *v; 343 344 if(SWIG_ConvertPtr($input, (void **) &v, \ 345 $1_descriptor, 0) == 0){ 346 /* wrapped vector */ 347 $1 = 1; 348 } else { 349 // It isn't a vector< T > so it should be a list of T's 350 if(Tcl_ListObjGetElements(interp, $input, 351 &nitems, &listobjv) == TCL_ERROR) 352 $1 = 0; 353 else 354 if (nitems == 0) 355 $1 = 1; 356 //check the first value to see if it is of correct type 357 if (CONVERT_FROM(interp, listobjv[0], &temp) == TCL_ERROR) 358 $1 = 0; 359 else 360 $1 = 1; 361 } 362 } 363 364 public: 365 vector(unsigned int size = 0); 366 vector(unsigned int size, const T& value); 367 vector(const vector< T > &); 368 369 unsigned int size() const; 370 bool empty() const; 371 void clear(); 372 %rename(push) push_back; 373 void push_back(T x); 374 %extend { 375 T pop() throw (std::out_of_range) { 376 if (self->size() == 0) 377 throw std::out_of_range("pop from empty vector"); 378 T x = self->back(); 379 self->pop_back(); 380 return x; 381 } 382 T get(int i) throw (std::out_of_range) { 383 int size = int(self->size()); 384 if (i<0) i += size; 385 if (i>=0 && i<size) 386 return (*self)[i]; 387 else 388 throw std::out_of_range("vector index out of range"); 389 } 390 void set(int i, T x) throw (std::out_of_range) { 391 int size = int(self->size()); 392 if (i<0) i+= size; 393 if (i>=0 && i<size) 394 (*self)[i] = x; 395 else 396 throw std::out_of_range("vector index out of range"); 397 } 398 } 399 }; 400 %enddef 401 402 specialize_std_vector(bool, Tcl_GetBoolFromObj, Tcl_NewBooleanObj); 403 specialize_std_vector(char, SwigInt_As<char>,Tcl_NewIntObj); 404 specialize_std_vector(int, Tcl_GetIntFromObj,Tcl_NewIntObj); 405 specialize_std_vector(short, SwigInt_As<short>, Tcl_NewIntObj); 406 specialize_std_vector(long, SwigInt_As<long>, Tcl_NewIntObj); 407 specialize_std_vector(unsigned char, 408 SwigInt_As<unsigned char>, Tcl_NewIntObj); 409 specialize_std_vector(unsigned int, 410 SwigInt_As<unsigned int>, Tcl_NewIntObj); 411 specialize_std_vector(unsigned short, 412 SwigInt_As<unsigned short>, Tcl_NewIntObj); 413 specialize_std_vector(unsigned long, 414 SwigInt_As<unsigned long>, Tcl_NewIntObj); 415 specialize_std_vector(double, Tcl_GetDoubleFromObj, Tcl_NewDoubleObj); 416 specialize_std_vector(float, SwigDouble_As<float>, Tcl_NewDoubleObj); 417 specialize_std_vector(std::string, 418 SwigString_AsString, SwigString_FromString); 419 420} 421 422 423