Home | History | Annotate | Download | only in python
      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