/trunk/Lib/perl5/std_vector.i
Swig | 568 lines | 524 code | 15 blank | 29 comment | 0 complexity | 4fe15ce6b786561f7f191e5e629a0f73 MD5 | raw file
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 41namespace 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 vector(unsigned int size = 0); 184 vector(unsigned int size, const T& value); 185 vector(const vector<T> &); 186 187 unsigned int size() const; 188 bool empty() const; 189 void clear(); 190 %rename(push) push_back; 191 void push_back(const T& x); 192 %extend { 193 T pop() throw (std::out_of_range) { 194 if (self->size() == 0) 195 throw std::out_of_range("pop from empty vector"); 196 T x = self->back(); 197 self->pop_back(); 198 return x; 199 } 200 T& get(int i) throw (std::out_of_range) { 201 int size = int(self->size()); 202 if (i>=0 && i<size) 203 return (*self)[i]; 204 else 205 throw std::out_of_range("vector index out of range"); 206 } 207 void set(int i, const T& x) throw (std::out_of_range) { 208 int size = int(self->size()); 209 if (i>=0 && i<size) 210 (*self)[i] = x; 211 else 212 throw std::out_of_range("vector index out of range"); 213 } 214 } 215 }; 216 217 // specializations for pointers 218 template<class T> class vector<T*> { 219 %typemap(in) vector<T*> (std::vector<T*>* v) { 220 int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0); 221 if (SWIG_IsOK(res)){ 222 $1 = *v; 223 } else if (SvROK($input)) { 224 AV *av = (AV *)SvRV($input); 225 if (SvTYPE(av) != SVt_PVAV) 226 SWIG_croak("Type error in argument $argnum of $symname. " 227 "Expected an array of " #T); 228 I32 len = av_len(av) + 1; 229 for (int i=0; i<len; i++) { 230 void *v; 231 SV **tv = av_fetch(av, i, 0); 232 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 233 if (SWIG_IsOK(res)) { 234 $1.push_back(%static_cast(v, T *)); 235 } else { 236 SWIG_croak("Type error in argument $argnum of " 237 "$symname. " 238 "Expected an array of " #T); 239 } 240 } 241 } else { 242 SWIG_croak("Type error in argument $argnum of $symname. " 243 "Expected an array of " #T); 244 } 245 } 246 %typemap(in) const vector<T *>& (std::vector<T *> temp,std::vector<T *>* v), 247 const vector<T *>* (std::vector<T *> temp,std::vector<T *>* v) { 248 int res = SWIG_ConvertPtr($input,(void **) &v, $1_descriptor,0); 249 if (SWIG_IsOK(res)) { 250 $1 = v; 251 } else if (SvROK($input)) { 252 AV *av = (AV *)SvRV($input); 253 if (SvTYPE(av) != SVt_PVAV) 254 SWIG_croak("Type error in argument $argnum of $symname. " 255 "Expected an array of " #T); 256 I32 len = av_len(av) + 1; 257 for (int i=0; i<len; i++) { 258 void *v; 259 SV **tv = av_fetch(av, i, 0); 260 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 261 if (SWIG_IsOK(res)) { 262 temp.push_back(%static_cast(v, T *)); 263 } else { 264 SWIG_croak("Type error in argument $argnum of " 265 "$symname. " 266 "Expected an array of " #T); 267 } 268 } 269 $1 = &temp; 270 } else { 271 SWIG_croak("Type error in argument $argnum of $symname. " 272 "Expected an array of " #T); 273 } 274 } 275 %typemap(out) vector<T *> { 276 size_t len = $1.size(); 277 SV **svs = new SV*[len]; 278 for (size_t i=0; i<len; i++) { 279 T *x = (($1_type &)$1)[i]; 280 svs[i] = sv_newmortal(); 281 sv_setsv(svs[i], SWIG_NewPointerObj(x, $descriptor(T *), 0)); 282 } 283 AV *myav = av_make(len, svs); 284 delete[] svs; 285 $result = newRV_noinc((SV*) myav); 286 sv_2mortal($result); 287 argvi++; 288 } 289 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T *> { 290 { 291 /* wrapped vector? */ 292 std::vector<T *>* v; 293 int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0); 294 if (SWIG_IsOK(res)) { 295 $1 = 1; 296 } else if (SvROK($input)) { 297 /* native sequence? */ 298 AV *av = (AV *)SvRV($input); 299 if (SvTYPE(av) == SVt_PVAV) { 300 I32 len = av_len(av) + 1; 301 if (len == 0) { 302 /* an empty sequence can be of any type */ 303 $1 = 1; 304 } else { 305 /* check the first element only */ 306 void *v; 307 SV **tv = av_fetch(av, 0, 0); 308 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 309 if (SWIG_IsOK(res)) 310 $1 = 1; 311 else 312 $1 = 0; 313 } 314 } 315 } else { 316 $1 = 0; 317 } 318 } 319 } 320 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T *>&,const vector<T *>* { 321 { 322 /* wrapped vector? */ 323 std::vector<T *> *v; 324 int res = SWIG_ConvertPtr($input,%as_voidptrptr(&v), $1_descriptor,0); 325 if (SWIG_IsOK(res)) { 326 $1 = 1; 327 } else if (SvROK($input)) { 328 /* native sequence? */ 329 AV *av = (AV *)SvRV($input); 330 if (SvTYPE(av) == SVt_PVAV) { 331 I32 len = av_len(av) + 1; 332 if (len == 0) { 333 /* an empty sequence can be of any type */ 334 $1 = 1; 335 } else { 336 /* check the first element only */ 337 void *v; 338 SV **tv = av_fetch(av, 0, 0); 339 int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0); 340 if (SWIG_IsOK(res)) 341 $1 = 1; 342 else 343 $1 = 0; 344 } 345 } 346 } else { 347 $1 = 0; 348 } 349 } 350 } 351 public: 352 vector(unsigned int size = 0); 353 vector(unsigned int size, T *value); 354 vector(const vector<T *> &); 355 356 unsigned int size() const; 357 bool empty() const; 358 void clear(); 359 %rename(push) push_back; 360 void push_back(T *x); 361 %extend { 362 T *pop() throw (std::out_of_range) { 363 if (self->size() == 0) 364 throw std::out_of_range("pop from empty vector"); 365 T *x = self->back(); 366 self->pop_back(); 367 return x; 368 } 369 T *get(int i) throw (std::out_of_range) { 370 int size = int(self->size()); 371 if (i>=0 && i<size) 372 return (*self)[i]; 373 else 374 throw std::out_of_range("vector index out of range"); 375 } 376 void set(int i, T *x) throw (std::out_of_range) { 377 int size = int(self->size()); 378 if (i>=0 && i<size) 379 (*self)[i] = x; 380 else 381 throw std::out_of_range("vector index out of range"); 382 } 383 } 384 }; 385 386 387 // specializations for built-ins 388 389 %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T) 390 template<> class vector<T> { 391 %typemap(in) vector<T> (std::vector<T>* v) { 392 if (SWIG_ConvertPtr($input,(void **) &v, 393 $&1_descriptor,1) != -1){ 394 $1 = *v; 395 } else if (SvROK($input)) { 396 AV *av = (AV *)SvRV($input); 397 if (SvTYPE(av) != SVt_PVAV) 398 SWIG_croak("Type error in argument $argnum of $symname. " 399 "Expected an array of " #T); 400 SV **tv; 401 I32 len = av_len(av) + 1; 402 for (int i=0; i<len; i++) { 403 tv = av_fetch(av, i, 0); 404 if (CHECK_T(*tv)) { 405 $1.push_back((T)TO_T(*tv)); 406 } else { 407 SWIG_croak("Type error in argument $argnum of " 408 "$symname. " 409 "Expected an array of " #T); 410 } 411 } 412 } else { 413 SWIG_croak("Type error in argument $argnum of $symname. " 414 "Expected an array of " #T); 415 } 416 } 417 %typemap(in) const vector<T>& (std::vector<T> temp, 418 std::vector<T>* v), 419 const vector<T>* (std::vector<T> temp, 420 std::vector<T>* v) { 421 if (SWIG_ConvertPtr($input,(void **) &v, 422 $1_descriptor,1) != -1) { 423 $1 = v; 424 } else if (SvROK($input)) { 425 AV *av = (AV *)SvRV($input); 426 if (SvTYPE(av) != SVt_PVAV) 427 SWIG_croak("Type error in argument $argnum of $symname. " 428 "Expected an array of " #T); 429 SV **tv; 430 I32 len = av_len(av) + 1; 431 for (int i=0; i<len; i++) { 432 tv = av_fetch(av, i, 0); 433 if (CHECK_T(*tv)) { 434 temp.push_back((T)TO_T(*tv)); 435 } else { 436 SWIG_croak("Type error in argument $argnum of " 437 "$symname. " 438 "Expected an array of " #T); 439 } 440 } 441 $1 = &temp; 442 } else { 443 SWIG_croak("Type error in argument $argnum of $symname. " 444 "Expected an array of " #T); 445 } 446 } 447 %typemap(out) vector<T> { 448 size_t len = $1.size(); 449 SV **svs = new SV*[len]; 450 for (size_t i=0; i<len; i++) { 451 svs[i] = sv_newmortal(); 452 FROM_T(svs[i], $1[i]); 453 } 454 AV *myav = av_make(len, svs); 455 delete[] svs; 456 $result = newRV_noinc((SV*) myav); 457 sv_2mortal($result); 458 argvi++; 459 } 460 %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { 461 { 462 /* wrapped vector? */ 463 std::vector<T >* v; 464 if (SWIG_ConvertPtr($input,(void **) &v, 465 $&1_descriptor,0) != -1) { 466 $1 = 1; 467 } else if (SvROK($input)) { 468 /* native sequence? */ 469 AV *av = (AV *)SvRV($input); 470 if (SvTYPE(av) == SVt_PVAV) { 471 I32 len = av_len(av) + 1; 472 if (len == 0) { 473 /* an empty sequence can be of any type */ 474 $1 = 1; 475 } else { 476 /* check the first element only */ 477 SV **tv = av_fetch(av, 0, 0); 478 if (CHECK_T(*tv)) 479 $1 = 1; 480 else 481 $1 = 0; 482 } 483 } 484 } else { 485 $1 = 0; 486 } 487 } 488 } 489 %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, 490 const vector<T>* { 491 { 492 /* wrapped vector? */ 493 std::vector<T >* v; 494 if (SWIG_ConvertPtr($input,(void **) &v, 495 $1_descriptor,0) != -1) { 496 $1 = 1; 497 } else if (SvROK($input)) { 498 /* native sequence? */ 499 AV *av = (AV *)SvRV($input); 500 if (SvTYPE(av) == SVt_PVAV) { 501 I32 len = av_len(av) + 1; 502 if (len == 0) { 503 /* an empty sequence can be of any type */ 504 $1 = 1; 505 } else { 506 /* check the first element only */ 507 SV **tv = av_fetch(av, 0, 0); 508 if (CHECK_T(*tv)) 509 $1 = 1; 510 else 511 $1 = 0; 512 } 513 } 514 } else { 515 $1 = 0; 516 } 517 } 518 } 519 public: 520 vector(unsigned int size = 0); 521 vector(unsigned int size, T value); 522 vector(const vector<T> &); 523 524 unsigned int size() const; 525 bool empty() const; 526 void clear(); 527 %rename(push) push_back; 528 void push_back(T x); 529 %extend { 530 T pop() throw (std::out_of_range) { 531 if (self->size() == 0) 532 throw std::out_of_range("pop from empty vector"); 533 T x = self->back(); 534 self->pop_back(); 535 return x; 536 } 537 T get(int i) throw (std::out_of_range) { 538 int size = int(self->size()); 539 if (i>=0 && i<size) 540 return (*self)[i]; 541 else 542 throw std::out_of_range("vector index out of range"); 543 } 544 void set(int i, T x) throw (std::out_of_range) { 545 int size = int(self->size()); 546 if (i>=0 && i<size) 547 (*self)[i] = x; 548 else 549 throw std::out_of_range("vector index out of range"); 550 } 551 } 552 }; 553 %enddef 554 555 specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv); 556 specialize_std_vector(char,SvIOK,SvIVX,sv_setiv); 557 specialize_std_vector(int,SvIOK,SvIVX,sv_setiv); 558 specialize_std_vector(short,SvIOK,SvIVX,sv_setiv); 559 specialize_std_vector(long,SvIOK,SvIVX,sv_setiv); 560 specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv); 561 specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv); 562 specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv); 563 specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv); 564 specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv); 565 specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv); 566 specialize_std_vector(std::string,SvPOK,SwigSvToString,SwigSvFromString); 567} 568