1 /* ----------------------------------------------------------------------------- 2 * std_vector.i 3 * 4 * SWIG typemaps for std::vector types 5 * ----------------------------------------------------------------------------- */ 6 7 %include <std_common.i> 8 9 // ------------------------------------------------------------------------ 10 // std::vector 11 // 12 // The aim of all that follows would be to integrate std::vector with 13 // Perl as much as possible, namely, to allow the user to pass and 14 // be returned Perl arrays. 15 // const declarations are used to guess the intent of the function being 16 // exported; therefore, the following rationale is applied: 17 // 18 // -- f(std::vector<T>), f(const std::vector<T>&), f(const std::vector<T>*): 19 // the parameter being read-only, either a Perl sequence or a 20 // previously wrapped std::vector<T> can be passed. 21 // -- f(std::vector<T>&), f(std::vector<T>*): 22 // the parameter must be modified; therefore, only a wrapped std::vector 23 // can be passed. 24 // -- std::vector<T> f(): 25 // the vector is returned by copy; therefore, a Perl sequence of T:s 26 // is returned which is most easily used in other Perl functions 27 // -- std::vector<T>& f(), std::vector<T>* f(), const std::vector<T>& f(), 28 // const std::vector<T>* f(): 29 // the vector is returned by reference; therefore, a wrapped std::vector 30 // is returned 31 // ------------------------------------------------------------------------ 32 33 %{ 34 #include <vector> 35 #include <algorithm> 36 #include <stdexcept> 37 %} 38 39 // exported class 40 41 namespace std { 42 43 template<class T> class vector { 44 %typemap(in) vector<T> (std::vector<T>* v) { 45 if (SWIG_ConvertPtr($input,(void **) &v, 46 $&1_descriptor,1) != -1) { 47 $1 = *v; 48 } else if (SvROK($input)) { 49 AV *av = (AV *)SvRV($input); 50 if (SvTYPE(av) != SVt_PVAV) 51 SWIG_croak("Type error in argument $argnum of $symname. " 52 "Expected an array of " #T); 53 SV **tv; 54 I32 len = av_len(av) + 1; 55 T* obj; 56 for (int i=0; i<len; i++) { 57 tv = av_fetch(av, i, 0); 58 if (SWIG_ConvertPtr(*tv, (void **)&obj, 59 $descriptor(T *),0) != -1) { 60 $1.push_back(*obj); 61 } else { 62 SWIG_croak("Type error in argument $argnum of " 63 "$symname. " 64 "Expected an array of " #T); 65 } 66 } 67 } else { 68 SWIG_croak("Type error in argument $argnum of $symname. " 69 "Expected an array of " #T); 70 } 71 } 72 %typemap(in) const vector<T>& (std::vector<T> temp, 73 std::vector<T>* v), 74 const vector<T>* (std::vector<T> temp, 75 std::vector<T>* v) { 76 if (SWIG_ConvertPtr($input,(void **) &v, 77 $1_descriptor,1) != -1) { 78 $1 = v; 79 } else if (SvROK($input)) { 80 AV *av = (AV *)SvRV($input); 81 if (SvTYPE(av) != SVt_PVAV) 82 SWIG_croak("Type error in argument $argnum of $symname. " 83 "Expected an array of " #T); 84 SV **tv; 85 I32 len = av_len(av) + 1; 86 T* obj; 87 for (int i=0; i<len; i++) { 88 tv = av_fetch(av, i, 0); 89 if (SWIG_ConvertPtr(*tv, (void **)&obj, 90 $descriptor(T *),0) != -1) { 91 temp.push_back(*obj); 92 } else { 93 SWIG_croak("Type error in argument $argnum of " 94 "$symname. " 95 "Expected an array of " #T); 96 } 97 } 98 $1 = &temp; 99 } else { 100 SWIG_croak("Type error in argument $argnum of $symname. " 101 "Expected an array of " #T); 102 } 103 } 104 %typemap(out) vector<T> { 105 size_t len = $1.size(); 106 SV **svs = new SV*[len]; 107 for (size_t i=0; i<len; i++) { 108 T* ptr = new T($1[i]); 109 svs[i] = sv_newmortal(); 110 SWIG_MakePtr(svs[i], (void*) ptr, 111 $descriptor(T *), $shadow|$owner); 112 } 113 AV *myav = av_make(len, svs); 114 delete[] svs; 115 $result = newRV_noinc((SV*) myav); 116 sv_2mortal($result); 117 argvi++; 118 } 119 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { 120 { 121 /* wrapped vector? */ 122 std::vector<T >* v; 123 if (SWIG_ConvertPtr($input,(void **) &v, 124 $&1_descriptor,0) != -1) { 125 $1 = 1; 126 } else if (SvROK($input)) { 127 /* native sequence? */ 128 AV *av = (AV *)SvRV($input); 129 if (SvTYPE(av) == SVt_PVAV) { 130 I32 len = av_len(av) + 1; 131 if (len == 0) { 132 /* an empty sequence can be of any type */ 133 $1 = 1; 134 } else { 135 /* check the first element only */ 136 T* obj; 137 SV **tv = av_fetch(av, 0, 0); 138 if (SWIG_ConvertPtr(*tv, (void **)&obj, 139 $descriptor(T *),0) != -1) 140 $1 = 1; 141 else 142 $1 = 0; 143 } 144 } 145 } else { 146 $1 = 0; 147 } 148 } 149 } 150 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, 151 const vector<T>* { 152 { 153 /* wrapped vector? */ 154 std::vector<T >* v; 155 if (SWIG_ConvertPtr($input,(void **) &v, 156 $1_descriptor,0) != -1) { 157 $1 = 1; 158 } else if (SvROK($input)) { 159 /* native sequence? */ 160 AV *av = (AV *)SvRV($input); 161 if (SvTYPE(av) == SVt_PVAV) { 162 I32 len = av_len(av) + 1; 163 if (len == 0) { 164 /* an empty sequence can be of any type */ 165 $1 = 1; 166 } else { 167 /* check the first element only */ 168 T* obj; 169 SV **tv = av_fetch(av, 0, 0); 170 if (SWIG_ConvertPtr(*tv, (void **)&obj, 171 $descriptor(T *),0) != -1) 172 $1 = 1; 173 else 174 $1 = 0; 175 } 176 } 177 } else { 178 $1 = 0; 179 } 180 } 181 } 182 public: 183 typedef size_t size_type; 184 typedef T value_type; 185 typedef const value_type& const_reference; 186 vector(unsigned int size = 0); 187 vector(unsigned int size, const T& value); 188 vector(const vector<T> &); 189 190 unsigned int size() const; 191 bool empty() const; 192 void clear(); 193 %rename(push) push_back; 194 void push_back(const T& x); 195 %extend { 196 T pop() throw (std::out_of_range) { 197 if (self->size() == 0) 198 throw std::out_of_range("pop from empty vector"); 199 T x = self->back(); 200 self->pop_back(); 201 return x; 202 } 203 T& get(int i) throw (std::out_of_range) { 204 int size = int(self->size()); 205 if (i>=0 && i<size) 206 return (*self)[i]; 207 else 208 throw std::out_of_range("vector index out of range"); 209 } 210 void set(int i, const T& x) throw (std::out_of_range) { 211 int size = int(self->size()); 212 if (i>=0 && i<size) 213 (*self)[i] = x; 214 else 215 throw std::out_of_range("vector index out of range"); 216 } 217 } 218 }; 219 220 // specializations for pointers 221 template<class T> class vector<T*> { 222 %typemap(in) vector<T*> (std::vector<T*>* v) { 223 int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0); 224 if (SWIG_IsOK(res)){ 225 $1 = *v; 226 } else if (SvROK($input)) { 227 AV *av = (AV *)SvRV($input); 228 if (SvTYPE(av) != SVt_PVAV) 229 SWIG_croak("Type error in argument $argnum of $symname. " 230 "Expected an array of " #T); 231 I32 len = av_len(av) + 1; 232 for (int i=0; i<len; i++) { 233 void *v; 234 SV **tv = av_fetch(av, i, 0); 235 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 236 if (SWIG_IsOK(res)) { 237 $1.push_back(%static_cast(v, T *)); 238 } else { 239 SWIG_croak("Type error in argument $argnum of " 240 "$symname. " 241 "Expected an array of " #T); 242 } 243 } 244 } else { 245 SWIG_croak("Type error in argument $argnum of $symname. " 246 "Expected an array of " #T); 247 } 248 } 249 %typemap(in) const vector<T *>& (std::vector<T *> temp,std::vector<T *>* v), 250 const vector<T *>* (std::vector<T *> temp,std::vector<T *>* v) { 251 int res = SWIG_ConvertPtr($input,(void **) &v, $1_descriptor,0); 252 if (SWIG_IsOK(res)) { 253 $1 = v; 254 } else if (SvROK($input)) { 255 AV *av = (AV *)SvRV($input); 256 if (SvTYPE(av) != SVt_PVAV) 257 SWIG_croak("Type error in argument $argnum of $symname. " 258 "Expected an array of " #T); 259 I32 len = av_len(av) + 1; 260 for (int i=0; i<len; i++) { 261 void *v; 262 SV **tv = av_fetch(av, i, 0); 263 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 264 if (SWIG_IsOK(res)) { 265 temp.push_back(%static_cast(v, T *)); 266 } else { 267 SWIG_croak("Type error in argument $argnum of " 268 "$symname. " 269 "Expected an array of " #T); 270 } 271 } 272 $1 = &temp; 273 } else { 274 SWIG_croak("Type error in argument $argnum of $symname. " 275 "Expected an array of " #T); 276 } 277 } 278 %typemap(out) vector<T *> { 279 size_t len = $1.size(); 280 SV **svs = new SV*[len]; 281 for (size_t i=0; i<len; i++) { 282 T *x = (($1_type &)$1)[i]; 283 svs[i] = sv_newmortal(); 284 sv_setsv(svs[i], SWIG_NewPointerObj(x, $descriptor(T *), 0)); 285 } 286 AV *myav = av_make(len, svs); 287 delete[] svs; 288 $result = newRV_noinc((SV*) myav); 289 sv_2mortal($result); 290 argvi++; 291 } 292 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T *> { 293 { 294 /* wrapped vector? */ 295 std::vector<T *>* v; 296 int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0); 297 if (SWIG_IsOK(res)) { 298 $1 = 1; 299 } else if (SvROK($input)) { 300 /* native sequence? */ 301 AV *av = (AV *)SvRV($input); 302 if (SvTYPE(av) == SVt_PVAV) { 303 I32 len = av_len(av) + 1; 304 if (len == 0) { 305 /* an empty sequence can be of any type */ 306 $1 = 1; 307 } else { 308 /* check the first element only */ 309 void *v; 310 SV **tv = av_fetch(av, 0, 0); 311 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 312 if (SWIG_IsOK(res)) 313 $1 = 1; 314 else 315 $1 = 0; 316 } 317 } 318 } else { 319 $1 = 0; 320 } 321 } 322 } 323 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T *>&,const vector<T *>* { 324 { 325 /* wrapped vector? */ 326 std::vector<T *> *v; 327 int res = SWIG_ConvertPtr($input,%as_voidptrptr(&v), $1_descriptor,0); 328 if (SWIG_IsOK(res)) { 329 $1 = 1; 330 } else if (SvROK($input)) { 331 /* native sequence? */ 332 AV *av = (AV *)SvRV($input); 333 if (SvTYPE(av) == SVt_PVAV) { 334 I32 len = av_len(av) + 1; 335 if (len == 0) { 336 /* an empty sequence can be of any type */ 337 $1 = 1; 338 } else { 339 /* check the first element only */ 340 void *v; 341 SV **tv = av_fetch(av, 0, 0); 342 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 343 if (SWIG_IsOK(res)) 344 $1 = 1; 345 else 346 $1 = 0; 347 } 348 } 349 } else { 350 $1 = 0; 351 } 352 } 353 } 354 public: 355 typedef size_t size_type; 356 typedef T value_type; 357 typedef const value_type& const_reference; 358 vector(unsigned int size = 0); 359 vector(unsigned int size, T *value); 360 vector(const vector<T *> &); 361 362 unsigned int size() const; 363 bool empty() const; 364 void clear(); 365 %rename(push) push_back; 366 void push_back(T *x); 367 %extend { 368 T *pop() throw (std::out_of_range) { 369 if (self->size() == 0) 370 throw std::out_of_range("pop from empty vector"); 371 T *x = self->back(); 372 self->pop_back(); 373 return x; 374 } 375 T *get(int i) throw (std::out_of_range) { 376 int size = int(self->size()); 377 if (i>=0 && i<size) 378 return (*self)[i]; 379 else 380 throw std::out_of_range("vector index out of range"); 381 } 382 void set(int i, T *x) throw (std::out_of_range) { 383 int size = int(self->size()); 384 if (i>=0 && i<size) 385 (*self)[i] = x; 386 else 387 throw std::out_of_range("vector index out of range"); 388 } 389 } 390 }; 391 392 393 // specializations for built-ins 394 395 %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T) 396 template<> class vector<T> { 397 %typemap(in) vector<T> (std::vector<T>* v) { 398 if (SWIG_ConvertPtr($input,(void **) &v, 399 $&1_descriptor,1) != -1){ 400 $1 = *v; 401 } else if (SvROK($input)) { 402 AV *av = (AV *)SvRV($input); 403 if (SvTYPE(av) != SVt_PVAV) 404 SWIG_croak("Type error in argument $argnum of $symname. " 405 "Expected an array of " #T); 406 SV **tv; 407 I32 len = av_len(av) + 1; 408 for (int i=0; i<len; i++) { 409 tv = av_fetch(av, i, 0); 410 if (CHECK_T(*tv)) { 411 $1.push_back((T)TO_T(*tv)); 412 } else { 413 SWIG_croak("Type error in argument $argnum of " 414 "$symname. " 415 "Expected an array of " #T); 416 } 417 } 418 } else { 419 SWIG_croak("Type error in argument $argnum of $symname. " 420 "Expected an array of " #T); 421 } 422 } 423 %typemap(in) const vector<T>& (std::vector<T> temp, 424 std::vector<T>* v), 425 const vector<T>* (std::vector<T> temp, 426 std::vector<T>* v) { 427 if (SWIG_ConvertPtr($input,(void **) &v, 428 $1_descriptor,1) != -1) { 429 $1 = v; 430 } else if (SvROK($input)) { 431 AV *av = (AV *)SvRV($input); 432 if (SvTYPE(av) != SVt_PVAV) 433 SWIG_croak("Type error in argument $argnum of $symname. " 434 "Expected an array of " #T); 435 SV **tv; 436 I32 len = av_len(av) + 1; 437 for (int i=0; i<len; i++) { 438 tv = av_fetch(av, i, 0); 439 if (CHECK_T(*tv)) { 440 temp.push_back((T)TO_T(*tv)); 441 } else { 442 SWIG_croak("Type error in argument $argnum of " 443 "$symname. " 444 "Expected an array of " #T); 445 } 446 } 447 $1 = &temp; 448 } else { 449 SWIG_croak("Type error in argument $argnum of $symname. " 450 "Expected an array of " #T); 451 } 452 } 453 %typemap(out) vector<T> { 454 size_t len = $1.size(); 455 SV **svs = new SV*[len]; 456 for (size_t i=0; i<len; i++) { 457 svs[i] = sv_newmortal(); 458 FROM_T(svs[i], $1[i]); 459 } 460 AV *myav = av_make(len, svs); 461 delete[] svs; 462 $result = newRV_noinc((SV*) myav); 463 sv_2mortal($result); 464 argvi++; 465 } 466 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { 467 { 468 /* wrapped vector? */ 469 std::vector<T >* v; 470 if (SWIG_ConvertPtr($input,(void **) &v, 471 $&1_descriptor,0) != -1) { 472 $1 = 1; 473 } else if (SvROK($input)) { 474 /* native sequence? */ 475 AV *av = (AV *)SvRV($input); 476 if (SvTYPE(av) == SVt_PVAV) { 477 I32 len = av_len(av) + 1; 478 if (len == 0) { 479 /* an empty sequence can be of any type */ 480 $1 = 1; 481 } else { 482 /* check the first element only */ 483 SV **tv = av_fetch(av, 0, 0); 484 if (CHECK_T(*tv)) 485 $1 = 1; 486 else 487 $1 = 0; 488 } 489 } 490 } else { 491 $1 = 0; 492 } 493 } 494 } 495 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, 496 const vector<T>* { 497 { 498 /* wrapped vector? */ 499 std::vector<T >* v; 500 if (SWIG_ConvertPtr($input,(void **) &v, 501 $1_descriptor,0) != -1) { 502 $1 = 1; 503 } else if (SvROK($input)) { 504 /* native sequence? */ 505 AV *av = (AV *)SvRV($input); 506 if (SvTYPE(av) == SVt_PVAV) { 507 I32 len = av_len(av) + 1; 508 if (len == 0) { 509 /* an empty sequence can be of any type */ 510 $1 = 1; 511 } else { 512 /* check the first element only */ 513 SV **tv = av_fetch(av, 0, 0); 514 if (CHECK_T(*tv)) 515 $1 = 1; 516 else 517 $1 = 0; 518 } 519 } 520 } else { 521 $1 = 0; 522 } 523 } 524 } 525 public: 526 typedef size_t size_type; 527 typedef T value_type; 528 typedef const value_type& const_reference; 529 vector(unsigned int size = 0); 530 vector(unsigned int size, T value); 531 vector(const vector<T> &); 532 533 unsigned int size() const; 534 bool empty() const; 535 void clear(); 536 %rename(push) push_back; 537 void push_back(T x); 538 %extend { 539 T pop() throw (std::out_of_range) { 540 if (self->size() == 0) 541 throw std::out_of_range("pop from empty vector"); 542 T x = self->back(); 543 self->pop_back(); 544 return x; 545 } 546 T get(int i) throw (std::out_of_range) { 547 int size = int(self->size()); 548 if (i>=0 && i<size) 549 return (*self)[i]; 550 else 551 throw std::out_of_range("vector index out of range"); 552 } 553 void set(int i, T x) throw (std::out_of_range) { 554 int size = int(self->size()); 555 if (i>=0 && i<size) 556 (*self)[i] = x; 557 else 558 throw std::out_of_range("vector index out of range"); 559 } 560 } 561 }; 562 %enddef 563 564 specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv); 565 specialize_std_vector(char,SvIOK,SvIVX,sv_setiv); 566 specialize_std_vector(int,SvIOK,SvIVX,sv_setiv); 567 specialize_std_vector(short,SvIOK,SvIVX,sv_setiv); 568 specialize_std_vector(long,SvIOK,SvIVX,sv_setiv); 569 specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv); 570 specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv); 571 specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv); 572 specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv); 573 specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv); 574 specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv); 575 specialize_std_vector(std::string,SvPOK,SwigSvToString,SwigSvFromString); 576 } 577 578