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