pycontainer.swg 29 KB

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