1 /* ----------------------------------------------------------------------------- 2 * pycontainer.swg 3 * 4 * Python sequence <-> C++ container wrapper 5 * 6 * This wrapper, and its iterator, allows a general use (and reuse) of 7 * the mapping between C++ and Python, thanks to the C++ templates. 8 * 9 * Of course, it needs the C++ compiler to support templates, but 10 * since we will use this wrapper with the STL containers, that should 11 * be the case. 12 * ----------------------------------------------------------------------------- */ 13 14 %{ 15 #include <iostream> 16 17 #if PY_VERSION_HEX >= 0x03020000 18 # define SWIGPY_SLICE_ARG(obj) ((PyObject*) (obj)) 19 #else 20 # define SWIGPY_SLICE_ARG(obj) ((PySliceObject*) (obj)) 21 #endif 22 %} 23 24 25 #if !defined(SWIG_NO_EXPORT_ITERATOR_METHODS) 26 # if !defined(SWIG_EXPORT_ITERATOR_METHODS) 27 # define SWIG_EXPORT_ITERATOR_METHODS SWIG_EXPORT_ITERATOR_METHODS 28 # endif 29 #endif 30 31 %include <pyiterators.swg> 32 33 /**** The PySequence C++ Wrap ***/ 34 35 %insert(header) %{ 36 #include <stdexcept> 37 %} 38 39 %include <std_except.i> 40 41 %fragment(SWIG_Traits_frag(swig::SwigPtr_PyObject),"header",fragment="StdTraits") { 42 namespace swig { 43 template <> struct traits<SwigPtr_PyObject > { 44 typedef value_category category; 45 static const char* type_name() { return "SwigPtr_PyObject"; } 46 }; 47 48 template <> struct traits_from<SwigPtr_PyObject> { 49 typedef SwigPtr_PyObject value_type; 50 static PyObject *from(const value_type& val) { 51 PyObject *obj = static_cast<PyObject *>(val); 52 Py_XINCREF(obj); 53 return obj; 54 } 55 }; 56 57 template <> 58 struct traits_check<SwigPtr_PyObject, value_category> { 59 static bool check(SwigPtr_PyObject) { 60 return true; 61 } 62 }; 63 64 template <> struct traits_asval<SwigPtr_PyObject > { 65 typedef SwigPtr_PyObject value_type; 66 static int asval(PyObject *obj, value_type *val) { 67 if (val) *val = obj; 68 return SWIG_OK; 69 } 70 }; 71 } 72 } 73 74 %fragment(SWIG_Traits_frag(swig::SwigVar_PyObject),"header",fragment="StdTraits") { 75 namespace swig { 76 template <> struct traits<SwigVar_PyObject > { 77 typedef value_category category; 78 static const char* type_name() { return "SwigVar_PyObject"; } 79 }; 80 81 template <> struct traits_from<SwigVar_PyObject> { 82 typedef SwigVar_PyObject value_type; 83 static PyObject *from(const value_type& val) { 84 PyObject *obj = static_cast<PyObject *>(val); 85 Py_XINCREF(obj); 86 return obj; 87 } 88 }; 89 90 template <> 91 struct traits_check<SwigVar_PyObject, value_category> { 92 static bool check(SwigVar_PyObject) { 93 return true; 94 } 95 }; 96 97 template <> struct traits_asval<SwigVar_PyObject > { 98 typedef SwigVar_PyObject value_type; 99 static int asval(PyObject *obj, value_type *val) { 100 if (val) *val = obj; 101 return SWIG_OK; 102 } 103 }; 104 } 105 } 106 107 %fragment("SwigPySequence_Base","header",fragment="<stddef.h>") 108 { 109 %#include <functional> 110 111 namespace std { 112 template <> 113 struct less <PyObject *>: public binary_function<PyObject *, PyObject *, bool> 114 { 115 bool 116 operator()(PyObject * v, PyObject *w) const 117 { 118 bool res; 119 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 120 res = PyObject_RichCompareBool(v, w, Py_LT) ? true : false; 121 /* This may fall into a case of inconsistent 122 eg. ObjA > ObjX > ObjB 123 but ObjA < ObjB 124 */ 125 if( PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError) ) 126 { 127 /* Objects can't be compared, this mostly occurred in Python 3.0 */ 128 /* Compare their ptr directly for a workaround */ 129 res = (v < w); 130 PyErr_Clear(); 131 } 132 SWIG_PYTHON_THREAD_END_BLOCK; 133 return res; 134 } 135 }; 136 137 template <> 138 struct less <swig::SwigPtr_PyObject>: public binary_function<swig::SwigPtr_PyObject, swig::SwigPtr_PyObject, bool> 139 { 140 bool 141 operator()(const swig::SwigPtr_PyObject& v, const swig::SwigPtr_PyObject& w) const 142 { 143 return std::less<PyObject *>()(v, w); 144 } 145 }; 146 147 template <> 148 struct less <swig::SwigVar_PyObject>: public binary_function<swig::SwigVar_PyObject, swig::SwigVar_PyObject, bool> 149 { 150 bool 151 operator()(const swig::SwigVar_PyObject& v, const swig::SwigVar_PyObject& w) const 152 { 153 return std::less<PyObject *>()(v, w); 154 } 155 }; 156 157 } 158 159 namespace swig { 160 template <> struct traits<PyObject *> { 161 typedef value_category category; 162 static const char* type_name() { return "PyObject *"; } 163 }; 164 165 template <> struct traits_asval<PyObject * > { 166 typedef PyObject * value_type; 167 static int asval(PyObject *obj, value_type *val) { 168 if (val) *val = obj; 169 return SWIG_OK; 170 } 171 }; 172 173 template <> 174 struct traits_check<PyObject *, value_category> { 175 static bool check(PyObject *) { 176 return true; 177 } 178 }; 179 180 template <> struct traits_from<PyObject *> { 181 typedef PyObject * value_type; 182 static PyObject *from(const value_type& val) { 183 Py_XINCREF(val); 184 return val; 185 } 186 }; 187 188 } 189 190 namespace swig { 191 template <class Difference> 192 inline size_t 193 check_index(Difference i, size_t size, bool insert = false) { 194 if ( i < 0 ) { 195 if ((size_t) (-i) <= size) 196 return (size_t) (i + size); 197 } else if ( (size_t) i < size ) { 198 return (size_t) i; 199 } else if (insert && ((size_t) i == size)) { 200 return size; 201 } 202 throw std::out_of_range("index out of range"); 203 } 204 205 template <class Difference> 206 void 207 slice_adjust(Difference i, Difference j, Py_ssize_t step, size_t size, Difference &ii, Difference &jj, bool insert = false) { 208 if (step == 0) { 209 throw std::invalid_argument("slice step cannot be zero"); 210 } else if (step > 0) { 211 // Required range: 0 <= i < size, 0 <= j < size 212 if (i < 0) { 213 ii = 0; 214 } else if (i < (Difference)size) { 215 ii = i; 216 } else if (insert && (i >= (Difference)size)) { 217 ii = (Difference)size; 218 } 219 if ( j < 0 ) { 220 jj = 0; 221 } else { 222 jj = (j < (Difference)size) ? j : (Difference)size; 223 } 224 } else { 225 // Required range: -1 <= i < size-1, -1 <= j < size-1 226 if (i < -1) { 227 ii = -1; 228 } else if (i < (Difference) size) { 229 ii = i; 230 } else if (i >= (Difference)(size-1)) { 231 ii = (Difference)(size-1); 232 } 233 if (j < -1) { 234 jj = -1; 235 } else { 236 jj = (j < (Difference)size ) ? j : (Difference)(size-1); 237 } 238 } 239 } 240 241 template <class Sequence, class Difference> 242 inline typename Sequence::iterator 243 getpos(Sequence* self, Difference i) { 244 typename Sequence::iterator pos = self->begin(); 245 std::advance(pos, check_index(i,self->size())); 246 return pos; 247 } 248 249 template <class Sequence, class Difference> 250 inline typename Sequence::const_iterator 251 cgetpos(const Sequence* self, Difference i) { 252 typename Sequence::const_iterator pos = self->begin(); 253 std::advance(pos, check_index(i,self->size())); 254 return pos; 255 } 256 257 template <class Sequence, class Difference> 258 inline Sequence* 259 getslice(const Sequence* self, Difference i, Difference j, Py_ssize_t step) { 260 typename Sequence::size_type size = self->size(); 261 Difference ii = 0; 262 Difference jj = 0; 263 swig::slice_adjust(i, j, step, size, ii, jj); 264 265 if (step > 0) { 266 typename Sequence::const_iterator sb = self->begin(); 267 typename Sequence::const_iterator se = self->begin(); 268 std::advance(sb,ii); 269 std::advance(se,jj); 270 if (step == 1) { 271 return new Sequence(sb, se); 272 } else { 273 Sequence *sequence = new Sequence(); 274 typename Sequence::const_iterator it = sb; 275 while (it!=se) { 276 sequence->push_back(*it); 277 for (Py_ssize_t c=0; c<step && it!=se; ++c) 278 it++; 279 } 280 return sequence; 281 } 282 } else { 283 Sequence *sequence = new Sequence(); 284 if (ii > jj) { 285 typename Sequence::const_reverse_iterator sb = self->rbegin(); 286 typename Sequence::const_reverse_iterator se = self->rbegin(); 287 std::advance(sb,size-ii-1); 288 std::advance(se,size-jj-1); 289 typename Sequence::const_reverse_iterator it = sb; 290 while (it!=se) { 291 sequence->push_back(*it); 292 for (Py_ssize_t c=0; c<-step && it!=se; ++c) 293 it++; 294 } 295 } 296 return sequence; 297 } 298 } 299 300 template <class Sequence, class Difference, class InputSeq> 301 inline void 302 setslice(Sequence* self, Difference i, Difference j, Py_ssize_t step, const InputSeq& is = InputSeq()) { 303 typename Sequence::size_type size = self->size(); 304 Difference ii = 0; 305 Difference jj = 0; 306 swig::slice_adjust(i, j, step, size, ii, jj, true); 307 if (step > 0) { 308 if (jj < ii) 309 jj = ii; 310 if (step == 1) { 311 size_t ssize = jj - ii; 312 if (ssize <= is.size()) { 313 // expanding/staying the same size 314 typename Sequence::iterator sb = self->begin(); 315 typename InputSeq::const_iterator isit = is.begin(); 316 std::advance(sb,ii); 317 std::advance(isit, jj - ii); 318 self->insert(std::copy(is.begin(), isit, sb), isit, is.end()); 319 } else { 320 // shrinking 321 typename Sequence::iterator sb = self->begin(); 322 typename Sequence::iterator se = self->begin(); 323 std::advance(sb,ii); 324 std::advance(se,jj); 325 self->erase(sb,se); 326 sb = self->begin(); 327 std::advance(sb,ii); 328 self->insert(sb, is.begin(), is.end()); 329 } 330 } else { 331 size_t replacecount = (jj - ii + step - 1) / step; 332 if (is.size() != replacecount) { 333 char msg[1024]; 334 sprintf(msg, "attempt to assign sequence of size %lu to extended slice of size %lu", (unsigned long)is.size(), (unsigned long)replacecount); 335 throw std::invalid_argument(msg); 336 } 337 typename Sequence::const_iterator isit = is.begin(); 338 typename Sequence::iterator it = self->begin(); 339 std::advance(it,ii); 340 for (size_t rc=0; rc<replacecount; ++rc) { 341 *it++ = *isit++; 342 for (Py_ssize_t c=0; c<(step-1) && it != self->end(); ++c) 343 it++; 344 } 345 } 346 } else { 347 if (jj > ii) 348 jj = ii; 349 size_t replacecount = (ii - jj - step - 1) / -step; 350 if (is.size() != replacecount) { 351 char msg[1024]; 352 sprintf(msg, "attempt to assign sequence of size %lu to extended slice of size %lu", (unsigned long)is.size(), (unsigned long)replacecount); 353 throw std::invalid_argument(msg); 354 } 355 typename Sequence::const_iterator isit = is.begin(); 356 typename Sequence::reverse_iterator it = self->rbegin(); 357 std::advance(it,size-ii-1); 358 for (size_t rc=0; rc<replacecount; ++rc) { 359 *it++ = *isit++; 360 for (Py_ssize_t c=0; c<(-step-1) && it != self->rend(); ++c) 361 it++; 362 } 363 } 364 } 365 366 template <class Sequence, class Difference> 367 inline void 368 delslice(Sequence* self, Difference i, Difference j, Py_ssize_t step) { 369 typename Sequence::size_type size = self->size(); 370 Difference ii = 0; 371 Difference jj = 0; 372 swig::slice_adjust(i, j, step, size, ii, jj, true); 373 if (step > 0) { 374 if (jj > ii) { 375 typename Sequence::iterator sb = self->begin(); 376 std::advance(sb,ii); 377 if (step == 1) { 378 typename Sequence::iterator se = self->begin(); 379 std::advance(se,jj); 380 self->erase(sb,se); 381 } else { 382 typename Sequence::iterator it = sb; 383 size_t delcount = (jj - ii + step - 1) / step; 384 while (delcount) { 385 it = self->erase(it); 386 for (Py_ssize_t c=0; c<(step-1) && it != self->end(); ++c) 387 it++; 388 delcount--; 389 } 390 } 391 } 392 } else { 393 if (ii > jj) { 394 typename Sequence::reverse_iterator sb = self->rbegin(); 395 std::advance(sb,size-ii-1); 396 typename Sequence::reverse_iterator it = sb; 397 size_t delcount = (ii - jj - step - 1) / -step; 398 while (delcount) { 399 it = typename Sequence::reverse_iterator(self->erase((++it).base())); 400 for (Py_ssize_t c=0; c<(-step-1) && it != self->rend(); ++c) 401 it++; 402 delcount--; 403 } 404 } 405 } 406 } 407 } 408 } 409 410 %fragment("SwigPySequence_Cont","header", 411 fragment="StdTraits", 412 fragment="SwigPySequence_Base", 413 fragment="SwigPyIterator_T") 414 { 415 namespace swig 416 { 417 template <class T> 418 struct SwigPySequence_Ref 419 { 420 SwigPySequence_Ref(PyObject* seq, int index) 421 : _seq(seq), _index(index) 422 { 423 } 424 425 operator T () const 426 { 427 swig::SwigVar_PyObject item = PySequence_GetItem(_seq, _index); 428 try { 429 return swig::as<T>(item, true); 430 } catch (std::exception& e) { 431 char msg[1024]; 432 sprintf(msg, "in sequence element %d ", _index); 433 if (!PyErr_Occurred()) { 434 ::%type_error(swig::type_name<T>()); 435 } 436 SWIG_Python_AddErrorMsg(msg); 437 SWIG_Python_AddErrorMsg(e.what()); 438 throw; 439 } 440 } 441 442 SwigPySequence_Ref& operator=(const T& v) 443 { 444 PySequence_SetItem(_seq, _index, swig::from<T>(v)); 445 return *this; 446 } 447 448 private: 449 PyObject* _seq; 450 int _index; 451 }; 452 453 template <class T> 454 struct SwigPySequence_ArrowProxy 455 { 456 SwigPySequence_ArrowProxy(const T& x): m_value(x) {} 457 const T* operator->() const { return &m_value; } 458 operator const T*() const { return &m_value; } 459 T m_value; 460 }; 461 462 template <class T, class Reference > 463 struct SwigPySequence_InputIterator 464 { 465 typedef SwigPySequence_InputIterator<T, Reference > self; 466 467 typedef std::random_access_iterator_tag iterator_category; 468 typedef Reference reference; 469 typedef T value_type; 470 typedef T* pointer; 471 typedef int difference_type; 472 473 SwigPySequence_InputIterator() 474 { 475 } 476 477 SwigPySequence_InputIterator(PyObject* seq, int index) 478 : _seq(seq), _index(index) 479 { 480 } 481 482 reference operator*() const 483 { 484 return reference(_seq, _index); 485 } 486 487 SwigPySequence_ArrowProxy<T> 488 operator->() const { 489 return SwigPySequence_ArrowProxy<T>(operator*()); 490 } 491 492 bool operator==(const self& ri) const 493 { 494 return (_index == ri._index) && (_seq == ri._seq); 495 } 496 497 bool operator!=(const self& ri) const 498 { 499 return !(operator==(ri)); 500 } 501 502 self& operator ++ () 503 { 504 ++_index; 505 return *this; 506 } 507 508 self& operator -- () 509 { 510 --_index; 511 return *this; 512 } 513 514 self& operator += (difference_type n) 515 { 516 _index += n; 517 return *this; 518 } 519 520 self operator +(difference_type n) const 521 { 522 return self(_seq, _index + n); 523 } 524 525 self& operator -= (difference_type n) 526 { 527 _index -= n; 528 return *this; 529 } 530 531 self operator -(difference_type n) const 532 { 533 return self(_seq, _index - n); 534 } 535 536 difference_type operator - (const self& ri) const 537 { 538 return _index - ri._index; 539 } 540 541 bool operator < (const self& ri) const 542 { 543 return _index < ri._index; 544 } 545 546 reference 547 operator[](difference_type n) const 548 { 549 return reference(_seq, _index + n); 550 } 551 552 private: 553 PyObject* _seq; 554 difference_type _index; 555 }; 556 557 template <class T> 558 struct SwigPySequence_Cont 559 { 560 typedef SwigPySequence_Ref<T> reference; 561 typedef const SwigPySequence_Ref<T> const_reference; 562 typedef T value_type; 563 typedef T* pointer; 564 typedef int difference_type; 565 typedef int size_type; 566 typedef const pointer const_pointer; 567 typedef SwigPySequence_InputIterator<T, reference> iterator; 568 typedef SwigPySequence_InputIterator<T, const_reference> const_iterator; 569 570 SwigPySequence_Cont(PyObject* seq) : _seq(0) 571 { 572 if (!PySequence_Check(seq)) { 573 throw std::invalid_argument("a sequence is expected"); 574 } 575 _seq = seq; 576 Py_INCREF(_seq); 577 } 578 579 ~SwigPySequence_Cont() 580 { 581 Py_XDECREF(_seq); 582 } 583 584 size_type size() const 585 { 586 return static_cast<size_type>(PySequence_Size(_seq)); 587 } 588 589 bool empty() const 590 { 591 return size() == 0; 592 } 593 594 iterator begin() 595 { 596 return iterator(_seq, 0); 597 } 598 599 const_iterator begin() const 600 { 601 return const_iterator(_seq, 0); 602 } 603 604 iterator end() 605 { 606 return iterator(_seq, size()); 607 } 608 609 const_iterator end() const 610 { 611 return const_iterator(_seq, size()); 612 } 613 614 reference operator[](difference_type n) 615 { 616 return reference(_seq, n); 617 } 618 619 const_reference operator[](difference_type n) const 620 { 621 return const_reference(_seq, n); 622 } 623 624 bool check(bool set_err = true) const 625 { 626 int s = size(); 627 for (int i = 0; i < s; ++i) { 628 swig::SwigVar_PyObject item = PySequence_GetItem(_seq, i); 629 if (!swig::check<value_type>(item)) { 630 if (set_err) { 631 char msg[1024]; 632 sprintf(msg, "in sequence element %d", i); 633 SWIG_Error(SWIG_RuntimeError, msg); 634 } 635 return false; 636 } 637 } 638 return true; 639 } 640 641 private: 642 PyObject* _seq; 643 }; 644 645 } 646 } 647 648 %define %swig_sequence_iterator(Sequence...) 649 #if defined(SWIG_EXPORT_ITERATOR_METHODS) 650 class iterator; 651 class reverse_iterator; 652 class const_iterator; 653 class const_reverse_iterator; 654 655 %typemap(out,noblock=1,fragment="SwigPySequence_Cont") 656 iterator, reverse_iterator, const_iterator, const_reverse_iterator { 657 $result = SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &)), 658 swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN); 659 } 660 %typemap(out,noblock=1,fragment="SwigPySequence_Cont") 661 std::pair<iterator, iterator>, std::pair<const_iterator, const_iterator> { 662 $result = PyTuple_New(2); 663 PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), 664 swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); 665 PyTuple_SetItem($result,1,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).second), 666 swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); 667 } 668 669 %fragment("SwigPyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="SwigPySequence_Cont") {} 670 671 %typemap(out,noblock=1,fragment="SwigPyPairBoolOutputIterator") 672 std::pair<iterator, bool>, std::pair<const_iterator, bool> { 673 $result = PyTuple_New(2); 674 PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), 675 swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); 676 PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second)); 677 } 678 679 %typemap(in,noblock=1,fragment="SwigPySequence_Cont") 680 iterator(swig::SwigPyIterator *iter = 0, int res), 681 reverse_iterator(swig::SwigPyIterator *iter = 0, int res), 682 const_iterator(swig::SwigPyIterator *iter = 0, int res), 683 const_reverse_iterator(swig::SwigPyIterator *iter = 0, int res) { 684 res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::SwigPyIterator::descriptor(), 0); 685 if (!SWIG_IsOK(res) || !iter) { 686 %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); 687 } else { 688 swig::SwigPyIterator_T<$type > *iter_t = dynamic_cast<swig::SwigPyIterator_T<$type > *>(iter); 689 if (iter_t) { 690 $1 = iter_t->get_current(); 691 } else { 692 %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); 693 } 694 } 695 } 696 697 %typecheck(%checkcode(ITERATOR),noblock=1,fragment="SwigPySequence_Cont") 698 iterator, reverse_iterator, const_iterator, const_reverse_iterator { 699 swig::SwigPyIterator *iter = 0; 700 int res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::SwigPyIterator::descriptor(), 0); 701 $1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::SwigPyIterator_T<$type > *>(iter) != 0)); 702 } 703 704 %fragment("SwigPySequence_Cont"); 705 706 %newobject iterator(PyObject **PYTHON_SELF); 707 %extend { 708 swig::SwigPyIterator* iterator(PyObject **PYTHON_SELF) { 709 return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); 710 } 711 712 #if defined(SWIGPYTHON_BUILTIN) 713 %feature("python:slot", "tp_iter", functype="getiterfunc") iterator; 714 #else 715 %pythoncode {def __iter__(self): return self.iterator()} 716 #endif 717 } 718 719 #endif //SWIG_EXPORT_ITERATOR_METHODS 720 %enddef 721 722 723 /**** The python container methods ****/ 724 725 %define %swig_container_methods(Container...) 726 727 /* deprecated in Python 2 */ 728 #if 1 729 %newobject __getslice__; 730 #endif 731 %newobject __getitem__(PySliceObject *slice); 732 733 #if defined(SWIGPYTHON_BUILTIN) 734 %feature("python:slot", "nb_nonzero", functype="inquiry") __nonzero__; 735 %feature("python:slot", "sq_length", functype="lenfunc") __len__; 736 #endif // SWIGPYTHON_BUILTIN 737 738 %extend { 739 bool __nonzero__() const { 740 return !(self->empty()); 741 } 742 743 /* Alias for Python 3 compatibility */ 744 bool __bool__() const { 745 return !(self->empty()); 746 } 747 748 size_type __len__() const { 749 return self->size(); 750 } 751 } 752 753 %enddef 754 755 756 757 %define %swig_sequence_methods_common(Sequence...) 758 %swig_sequence_iterator(%arg(Sequence)) 759 %swig_container_methods(%arg(Sequence)) 760 761 %fragment("SwigPySequence_Base"); 762 763 #if defined(SWIGPYTHON_BUILTIN) 764 //%feature("python:slot", "sq_item", functype="ssizeargfunc") __getitem__; 765 //%feature("python:slot", "sq_slice", functype="ssizessizeargfunc") __getslice__; 766 //%feature("python:slot", "sq_ass_item", functype="ssizeobjargproc") __setitem__; 767 //%feature("python:slot", "sq_ass_slice", functype="ssizessizeobjargproc") __setslice__; 768 %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; 769 %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; 770 #endif // SWIGPYTHON_BUILTIN 771 772 %extend { 773 value_type pop() throw (std::out_of_range) { 774 if (self->size() == 0) 775 throw std::out_of_range("pop from empty container"); 776 Sequence::value_type x = self->back(); 777 self->pop_back(); 778 return x; 779 } 780 781 /* typemap for slice object support */ 782 %typemap(in) PySliceObject* { 783 if (!PySlice_Check($input)) { 784 %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); 785 } 786 $1 = (PySliceObject *) $input; 787 } 788 %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) PySliceObject* { 789 $1 = PySlice_Check($input); 790 } 791 792 /* deprecated in Python 2 */ 793 #if 1 794 Sequence* __getslice__(difference_type i, difference_type j) throw (std::out_of_range, std::invalid_argument) { 795 return swig::getslice(self, i, j, 1); 796 } 797 798 void __setslice__(difference_type i, difference_type j, const Sequence& v = Sequence()) throw (std::out_of_range, std::invalid_argument) { 799 swig::setslice(self, i, j, 1, v); 800 } 801 802 void __delslice__(difference_type i, difference_type j) throw (std::out_of_range, std::invalid_argument) { 803 swig::delslice(self, i, j, 1); 804 } 805 #endif 806 807 void __delitem__(difference_type i) throw (std::out_of_range) { 808 self->erase(swig::getpos(self,i)); 809 } 810 811 812 /* Overloaded methods for Python 3 compatibility 813 * (Also useful in Python 2.x) 814 */ 815 Sequence* __getitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) { 816 Py_ssize_t i, j, step; 817 if( !PySlice_Check(slice) ) { 818 SWIG_Error(SWIG_TypeError, "Slice object expected."); 819 return NULL; 820 } 821 PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); 822 Sequence::difference_type id = i; 823 Sequence::difference_type jd = j; 824 return swig::getslice(self, id, jd, step); 825 } 826 827 void __setitem__(PySliceObject *slice, const Sequence& v) throw (std::out_of_range, std::invalid_argument) { 828 Py_ssize_t i, j, step; 829 if( !PySlice_Check(slice) ) { 830 SWIG_Error(SWIG_TypeError, "Slice object expected."); 831 return; 832 } 833 PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); 834 Sequence::difference_type id = i; 835 Sequence::difference_type jd = j; 836 swig::setslice(self, id, jd, step, v); 837 } 838 839 void __setitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) { 840 Py_ssize_t i, j, step; 841 if( !PySlice_Check(slice) ) { 842 SWIG_Error(SWIG_TypeError, "Slice object expected."); 843 return; 844 } 845 PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); 846 Sequence::difference_type id = i; 847 Sequence::difference_type jd = j; 848 swig::delslice(self, id, jd, step); 849 } 850 851 void __delitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) { 852 Py_ssize_t i, j, step; 853 if( !PySlice_Check(slice) ) { 854 SWIG_Error(SWIG_TypeError, "Slice object expected."); 855 return; 856 } 857 PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); 858 Sequence::difference_type id = i; 859 Sequence::difference_type jd = j; 860 swig::delslice(self, id, jd, step); 861 } 862 863 } 864 865 %enddef 866 867 %define %swig_sequence_methods(Sequence...) 868 %swig_sequence_methods_common(%arg(Sequence)) 869 %extend { 870 const value_type& __getitem__(difference_type i) const throw (std::out_of_range) { 871 return *(swig::cgetpos(self, i)); 872 } 873 874 void __setitem__(difference_type i, const value_type& x) throw (std::out_of_range) { 875 *(swig::getpos(self,i)) = x; 876 } 877 878 void append(const value_type& x) { 879 self->push_back(x); 880 } 881 } 882 883 %enddef 884 885 %define %swig_sequence_methods_val(Sequence...) 886 %swig_sequence_methods_common(%arg(Sequence)) 887 %extend { 888 value_type __getitem__(difference_type i) throw (std::out_of_range) { 889 return *(swig::cgetpos(self, i)); 890 } 891 892 void __setitem__(difference_type i, value_type x) throw (std::out_of_range) { 893 *(swig::getpos(self,i)) = x; 894 } 895 896 void append(value_type x) { 897 self->push_back(x); 898 } 899 } 900 901 %enddef 902 903 904 905 // 906 // Common fragments 907 // 908 909 %fragment("StdSequenceTraits","header", 910 fragment="StdTraits", 911 fragment="SwigPySequence_Cont") 912 { 913 namespace swig { 914 template <class SwigPySeq, class Seq> 915 inline void 916 assign(const SwigPySeq& swigpyseq, Seq* seq) { 917 // seq->assign(swigpyseq.begin(), swigpyseq.end()); // not used as not always implemented 918 typedef typename SwigPySeq::value_type value_type; 919 typename SwigPySeq::const_iterator it = swigpyseq.begin(); 920 for (;it != swigpyseq.end(); ++it) { 921 seq->insert(seq->end(),(value_type)(*it)); 922 } 923 } 924 925 template <class Seq, class T = typename Seq::value_type > 926 struct traits_asptr_stdseq { 927 typedef Seq sequence; 928 typedef T value_type; 929 930 static int asptr(PyObject *obj, sequence **seq) { 931 if (obj == Py_None || SWIG_Python_GetSwigThis(obj)) { 932 sequence *p; 933 if (::SWIG_ConvertPtr(obj,(void**)&p, 934 swig::type_info<sequence>(),0) == SWIG_OK) { 935 if (seq) *seq = p; 936 return SWIG_OLDOBJ; 937 } 938 } else if (PySequence_Check(obj)) { 939 try { 940 SwigPySequence_Cont<value_type> swigpyseq(obj); 941 if (seq) { 942 sequence *pseq = new sequence(); 943 assign(swigpyseq, pseq); 944 *seq = pseq; 945 return SWIG_NEWOBJ; 946 } else { 947 return swigpyseq.check() ? SWIG_OK : SWIG_ERROR; 948 } 949 } catch (std::exception& e) { 950 if (seq) { 951 if (!PyErr_Occurred()) { 952 PyErr_SetString(PyExc_TypeError, e.what()); 953 } 954 } 955 return SWIG_ERROR; 956 } 957 } 958 return SWIG_ERROR; 959 } 960 }; 961 962 template <class Seq, class T = typename Seq::value_type > 963 struct traits_from_stdseq { 964 typedef Seq sequence; 965 typedef T value_type; 966 typedef typename Seq::size_type size_type; 967 typedef typename sequence::const_iterator const_iterator; 968 969 static PyObject *from(const sequence& seq) { 970 %#ifdef SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS 971 swig_type_info *desc = swig::type_info<sequence>(); 972 if (desc && desc->clientdata) { 973 return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN); 974 } 975 %#endif 976 size_type size = seq.size(); 977 if (size <= (size_type)INT_MAX) { 978 PyObject *obj = PyTuple_New((int)size); 979 int i = 0; 980 for (const_iterator it = seq.begin(); 981 it != seq.end(); ++it, ++i) { 982 PyTuple_SetItem(obj,i,swig::from<value_type>(*it)); 983 } 984 return obj; 985 } else { 986 PyErr_SetString(PyExc_OverflowError,"sequence size not valid in python"); 987 return NULL; 988 } 989 } 990 }; 991 } 992 } 993