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 * SWIG typemaps for std::vector types 8 * ----------------------------------------------------------------------------- */ 9 10%include <std_common.i> 11 12// ------------------------------------------------------------------------ 13// std::vector 14// 15// The aim of all that follows would be to integrate std::vector with 16// Perl as much as possible, namely, to allow the user to pass and 17// be returned Perl arrays. 18// const declarations are used to guess the intent of the function being 19// exported; therefore, the following rationale is applied: 20// 21// -- f(std::vector<T>), f(const std::vector<T>&), f(const std::vector<T>*): 22// the parameter being read-only, either a Perl sequence or a 23// previously wrapped std::vector<T> can be passed. 24// -- f(std::vector<T>&), f(std::vector<T>*): 25// the parameter must be modified; therefore, only a wrapped std::vector 26// can be passed. 27// -- std::vector<T> f(): 28// the vector is returned by copy; therefore, a Perl sequence of T:s 29// is returned which is most easily used in other Perl functions 30// -- std::vector<T>& f(), std::vector<T>* f(), const std::vector<T>& f(), 31// const std::vector<T>* f(): 32// the vector is returned by reference; therefore, a wrapped std::vector 33// is returned 34// ------------------------------------------------------------------------ 35 36%{ 37#include <vector> 38#include <algorithm> 39#include <stdexcept> 40%} 41 42// exported class 43 44namespace std { 45 46 template<class T> class vector { 47 %typemap(in) vector<T> (std::vector<T>* v) { 48 if (SWIG_ConvertPtr($input,(void **) &v, 49 $&1_descriptor,1) != -1) { 50 $1 = *v; 51 } else if (SvROK($input)) { 52 AV *av = (AV *)SvRV($input); 53 if (SvTYPE(av) != SVt_PVAV) 54 SWIG_croak("Type error in argument $argnum of $symname. " 55 "Expected an array of " #T); 56 SV **tv; 57 I32 len = av_len(av) + 1; 58 T* obj; 59 for (int i=0; i<len; i++) { 60 tv = av_fetch(av, i, 0); 61 if (SWIG_ConvertPtr(*tv, (void **)&obj, 62 $descriptor(T *),0) != -1) { 63 $1.push_back(*obj); 64 } else { 65 SWIG_croak("Type error in argument $argnum of " 66 "$symname. " 67 "Expected an array of " #T); 68 } 69 } 70 } else { 71 SWIG_croak("Type error in argument $argnum of $symname. " 72 "Expected an array of " #T); 73 } 74 } 75 %typemap(in) const vector<T>& (std::vector<T> temp, 76 std::vector<T>* v), 77 const vector<T>* (std::vector<T> temp, 78 std::vector<T>* v) { 79 if (SWIG_ConvertPtr($input,(void **) &v, 80 $1_descriptor,1) != -1) { 81 $1 = v; 82 } else if (SvROK($input)) { 83 AV *av = (AV *)SvRV($input); 84 if (SvTYPE(av) != SVt_PVAV) 85 SWIG_croak("Type error in argument $argnum of $symname. " 86 "Expected an array of " #T); 87 SV **tv; 88 I32 len = av_len(av) + 1; 89 T* obj; 90 for (int i=0; i<len; i++) { 91 tv = av_fetch(av, i, 0); 92 if (SWIG_ConvertPtr(*tv, (void **)&obj, 93 $descriptor(T *),0) != -1) { 94 temp.push_back(*obj); 95 } else { 96 SWIG_croak("Type error in argument $argnum of " 97 "$symname. " 98 "Expected an array of " #T); 99 } 100 } 101 $1 = &temp; 102 } else { 103 SWIG_croak("Type error in argument $argnum of $symname. " 104 "Expected an array of " #T); 105 } 106 } 107 %typemap(out) vector<T> { 108 size_t len = $1.size(); 109 SV **svs = new SV*[len]; 110 for (size_t i=0; i<len; i++) { 111 T* ptr = new T($1[i]); 112 svs[i] = sv_newmortal(); 113 SWIG_MakePtr(svs[i], (void*) ptr, 114 $descriptor(T *), $shadow|$owner); 115 } 116 AV *myav = av_make(len, svs); 117 delete[] svs; 118 $result = newRV_noinc((SV*) myav); 119 sv_2mortal($result); 120 argvi++; 121 } 122 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { 123 { 124 /* wrapped vector? */ 125 std::vector<T >* v; 126 if (SWIG_ConvertPtr($input,(void **) &v, 127 $&1_descriptor,0) != -1) { 128 $1 = 1; 129 } else if (SvROK($input)) { 130 /* native sequence? */ 131 AV *av = (AV *)SvRV($input); 132 if (SvTYPE(av) == SVt_PVAV) { 133 I32 len = av_len(av) + 1; 134 if (len == 0) { 135 /* an empty sequence can be of any type */ 136 $1 = 1; 137 } else { 138 /* check the first element only */ 139 T* obj; 140 SV **tv = av_fetch(av, 0, 0); 141 if (SWIG_ConvertPtr(*tv, (void **)&obj, 142 $descriptor(T *),0) != -1) 143 $1 = 1; 144 else 145 $1 = 0; 146 } 147 } 148 } else { 149 $1 = 0; 150 } 151 } 152 } 153 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, 154 const vector<T>* { 155 { 156 /* wrapped vector? */ 157 std::vector<T >* v; 158 if (SWIG_ConvertPtr($input,(void **) &v, 159 $1_descriptor,0) != -1) { 160 $1 = 1; 161 } else if (SvROK($input)) { 162 /* native sequence? */ 163 AV *av = (AV *)SvRV($input); 164 if (SvTYPE(av) == SVt_PVAV) { 165 I32 len = av_len(av) + 1; 166 if (len == 0) { 167 /* an empty sequence can be of any type */ 168 $1 = 1; 169 } else { 170 /* check the first element only */ 171 T* obj; 172 SV **tv = av_fetch(av, 0, 0); 173 if (SWIG_ConvertPtr(*tv, (void **)&obj, 174 $descriptor(T *),0) != -1) 175 $1 = 1; 176 else 177 $1 = 0; 178 } 179 } 180 } else { 181 $1 = 0; 182 } 183 } 184 } 185 public: 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 vector(unsigned int size = 0); 356 vector(unsigned int size, T *value); 357 vector(const vector<T *> &); 358 359 unsigned int size() const; 360 bool empty() const; 361 void clear(); 362 %rename(push) push_back; 363 void push_back(T *x); 364 %extend { 365 T *pop() throw (std::out_of_range) { 366 if (self->size() == 0) 367 throw std::out_of_range("pop from empty vector"); 368 T *x = self->back(); 369 self->pop_back(); 370 return x; 371 } 372 T *get(int i) throw (std::out_of_range) { 373 int size = int(self->size()); 374 if (i>=0 && i<size) 375 return (*self)[i]; 376 else 377 throw std::out_of_range("vector index out of range"); 378 } 379 void set(int i, T *x) throw (std::out_of_range) { 380 int size = int(self->size()); 381 if (i>=0 && i<size) 382 (*self)[i] = x; 383 else 384 throw std::out_of_range("vector index out of range"); 385 } 386 } 387 }; 388 389 390 // specializations for built-ins 391 392 %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T) 393 template<> class vector<T> { 394 %typemap(in) vector<T> (std::vector<T>* v) { 395 if (SWIG_ConvertPtr($input,(void **) &v, 396 $&1_descriptor,1) != -1){ 397 $1 = *v; 398 } else if (SvROK($input)) { 399 AV *av = (AV *)SvRV($input); 400 if (SvTYPE(av) != SVt_PVAV) 401 SWIG_croak("Type error in argument $argnum of $symname. " 402 "Expected an array of " #T); 403 SV **tv; 404 I32 len = av_len(av) + 1; 405 for (int i=0; i<len; i++) { 406 tv = av_fetch(av, i, 0); 407 if (CHECK_T(*tv)) { 408 $1.push_back((T)TO_T(*tv)); 409 } else { 410 SWIG_croak("Type error in argument $argnum of " 411 "$symname. " 412 "Expected an array of " #T); 413 } 414 } 415 } else { 416 SWIG_croak("Type error in argument $argnum of $symname. " 417 "Expected an array of " #T); 418 } 419 } 420 %typemap(in) const vector<T>& (std::vector<T> temp, 421 std::vector<T>* v), 422 const vector<T>* (std::vector<T> temp, 423 std::vector<T>* v) { 424 if (SWIG_ConvertPtr($input,(void **) &v, 425 $1_descriptor,1) != -1) { 426 $1 = v; 427 } else if (SvROK($input)) { 428 AV *av = (AV *)SvRV($input); 429 if (SvTYPE(av) != SVt_PVAV) 430 SWIG_croak("Type error in argument $argnum of $symname. " 431 "Expected an array of " #T); 432 SV **tv; 433 I32 len = av_len(av) + 1; 434 for (int i=0; i<len; i++) { 435 tv = av_fetch(av, i, 0); 436 if (CHECK_T(*tv)) { 437 temp.push_back((T)TO_T(*tv)); 438 } else { 439 SWIG_croak("Type error in argument $argnum of " 440 "$symname. " 441 "Expected an array of " #T); 442 } 443 } 444 $1 = &temp; 445 } else { 446 SWIG_croak("Type error in argument $argnum of $symname. " 447 "Expected an array of " #T); 448 } 449 } 450 %typemap(out) vector<T> { 451 size_t len = $1.size(); 452 SV **svs = new SV*[len]; 453 for (size_t i=0; i<len; i++) { 454 svs[i] = sv_newmortal(); 455 FROM_T(svs[i], $1[i]); 456 } 457 AV *myav = av_make(len, svs); 458 delete[] svs; 459 $result = newRV_noinc((SV*) myav); 460 sv_2mortal($result); 461 argvi++; 462 } 463 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { 464 { 465 /* wrapped vector? */ 466 std::vector<T >* v; 467 if (SWIG_ConvertPtr($input,(void **) &v, 468 $&1_descriptor,0) != -1) { 469 $1 = 1; 470 } else if (SvROK($input)) { 471 /* native sequence? */ 472 AV *av = (AV *)SvRV($input); 473 if (SvTYPE(av) == SVt_PVAV) { 474 I32 len = av_len(av) + 1; 475 if (len == 0) { 476 /* an empty sequence can be of any type */ 477 $1 = 1; 478 } else { 479 /* check the first element only */ 480 SV **tv = av_fetch(av, 0, 0); 481 if (CHECK_T(*tv)) 482 $1 = 1; 483 else 484 $1 = 0; 485 } 486 } 487 } else { 488 $1 = 0; 489 } 490 } 491 } 492 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, 493 const vector<T>* { 494 { 495 /* wrapped vector? */ 496 std::vector<T >* v; 497 if (SWIG_ConvertPtr($input,(void **) &v, 498 $1_descriptor,0) != -1) { 499 $1 = 1; 500 } else if (SvROK($input)) { 501 /* native sequence? */ 502 AV *av = (AV *)SvRV($input); 503 if (SvTYPE(av) == SVt_PVAV) { 504 I32 len = av_len(av) + 1; 505 if (len == 0) { 506 /* an empty sequence can be of any type */ 507 $1 = 1; 508 } else { 509 /* check the first element only */ 510 SV **tv = av_fetch(av, 0, 0); 511 if (CHECK_T(*tv)) 512 $1 = 1; 513 else 514 $1 = 0; 515 } 516 } 517 } else { 518 $1 = 0; 519 } 520 } 521 } 522 public: 523 vector(unsigned int size = 0); 524 vector(unsigned int size, T value); 525 vector(const vector<T> &); 526 527 unsigned int size() const; 528 bool empty() const; 529 void clear(); 530 %rename(push) push_back; 531 void push_back(T x); 532 %extend { 533 T pop() throw (std::out_of_range) { 534 if (self->size() == 0) 535 throw std::out_of_range("pop from empty vector"); 536 T x = self->back(); 537 self->pop_back(); 538 return x; 539 } 540 T get(int i) throw (std::out_of_range) { 541 int size = int(self->size()); 542 if (i>=0 && i<size) 543 return (*self)[i]; 544 else 545 throw std::out_of_range("vector index out of range"); 546 } 547 void set(int i, T x) throw (std::out_of_range) { 548 int size = int(self->size()); 549 if (i>=0 && i<size) 550 (*self)[i] = x; 551 else 552 throw std::out_of_range("vector index out of range"); 553 } 554 } 555 }; 556 %enddef 557 558 specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv); 559 specialize_std_vector(char,SvIOK,SvIVX,sv_setiv); 560 specialize_std_vector(int,SvIOK,SvIVX,sv_setiv); 561 specialize_std_vector(short,SvIOK,SvIVX,sv_setiv); 562 specialize_std_vector(long,SvIOK,SvIVX,sv_setiv); 563 specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv); 564 specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv); 565 specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv); 566 specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv); 567 specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv); 568 specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv); 569 specialize_std_vector(std::string,SvPOK,SwigSvToString,SwigSvFromString); 570} 571 572