diff options
Diffstat (limited to 'Lib/python/pycontainer.swg')
-rw-r--r-- | Lib/python/pycontainer.swg | 315 |
1 files changed, 52 insertions, 263 deletions
diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index 4910fecc0..ceee27f5d 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -456,239 +456,6 @@ namespace swig { } } -%fragment("SwigPySequence_Cont","header", - fragment="StdTraits", - fragment="SwigPySequence_Base", - fragment="SwigPyIterator_T") -{ -namespace swig -{ - template <class T> - struct SwigPySequence_Ref - { - SwigPySequence_Ref(PyObject* seq, Py_ssize_t index) - : _seq(seq), _index(index) - { - } - - operator T () const - { - swig::SwigVar_PyObject item = PySequence_GetItem(_seq, _index); - try { - return swig::as<T>(item); - } catch (const std::invalid_argument& e) { - char msg[1024]; - PyOS_snprintf(msg, sizeof(msg), "in sequence element %d ", (int)_index); - if (!PyErr_Occurred()) { - ::%type_error(swig::type_name<T>()); - } - SWIG_Python_AddErrorMsg(msg); - SWIG_Python_AddErrorMsg(e.what()); - throw; - } - } - - SwigPySequence_Ref& operator=(const T& v) - { - PySequence_SetItem(_seq, _index, swig::from<T>(v)); - return *this; - } - - private: - PyObject* _seq; - Py_ssize_t _index; - }; - - template <class T> - struct SwigPySequence_ArrowProxy - { - SwigPySequence_ArrowProxy(const T& x): m_value(x) {} - const T* operator->() const { return &m_value; } - operator const T*() const { return &m_value; } - T m_value; - }; - - template <class T, class Reference > - struct SwigPySequence_InputIterator - { - typedef SwigPySequence_InputIterator<T, Reference > self; - - typedef std::random_access_iterator_tag iterator_category; - typedef Reference reference; - typedef T value_type; - typedef T* pointer; - typedef Py_ssize_t difference_type; - - SwigPySequence_InputIterator() - { - } - - SwigPySequence_InputIterator(PyObject* seq, Py_ssize_t index) - : _seq(seq), _index(index) - { - } - - reference operator*() const - { - return reference(_seq, _index); - } - - SwigPySequence_ArrowProxy<T> - operator->() const { - return SwigPySequence_ArrowProxy<T>(operator*()); - } - - bool operator==(const self& ri) const - { - return (_index == ri._index) && (_seq == ri._seq); - } - - bool operator!=(const self& ri) const - { - return !(operator==(ri)); - } - - self& operator ++ () - { - ++_index; - return *this; - } - - self& operator -- () - { - --_index; - return *this; - } - - self& operator += (difference_type n) - { - _index += n; - return *this; - } - - self operator +(difference_type n) const - { - return self(_seq, _index + n); - } - - self& operator -= (difference_type n) - { - _index -= n; - return *this; - } - - self operator -(difference_type n) const - { - return self(_seq, _index - n); - } - - difference_type operator - (const self& ri) const - { - return _index - ri._index; - } - - bool operator < (const self& ri) const - { - return _index < ri._index; - } - - reference - operator[](difference_type n) const - { - return reference(_seq, _index + n); - } - - private: - PyObject* _seq; - difference_type _index; - }; - - // STL container wrapper around a Python sequence - template <class T> - struct SwigPySequence_Cont - { - typedef SwigPySequence_Ref<T> reference; - typedef const SwigPySequence_Ref<T> const_reference; - typedef T value_type; - typedef T* pointer; - typedef Py_ssize_t difference_type; - typedef size_t size_type; - typedef const pointer const_pointer; - typedef SwigPySequence_InputIterator<T, reference> iterator; - typedef SwigPySequence_InputIterator<T, const_reference> const_iterator; - - SwigPySequence_Cont(PyObject* seq) : _seq(0) - { - if (!PySequence_Check(seq)) { - throw std::invalid_argument("a sequence is expected"); - } - _seq = seq; - Py_INCREF(_seq); - } - - ~SwigPySequence_Cont() - { - Py_XDECREF(_seq); - } - - size_type size() const - { - return static_cast<size_type>(PySequence_Size(_seq)); - } - - bool empty() const - { - return size() == 0; - } - - iterator begin() - { - return iterator(_seq, 0); - } - - const_iterator begin() const - { - return const_iterator(_seq, 0); - } - - iterator end() - { - return iterator(_seq, size()); - } - - const_iterator end() const - { - return const_iterator(_seq, size()); - } - - reference operator[](difference_type n) - { - return reference(_seq, n); - } - - const_reference operator[](difference_type n) const - { - return const_reference(_seq, n); - } - - bool check() const - { - Py_ssize_t s = size(); - for (Py_ssize_t i = 0; i < s; ++i) { - swig::SwigVar_PyObject item = PySequence_GetItem(_seq, i); - if (!swig::check<value_type>(item)) - return false; - } - return true; - } - - private: - PyObject* _seq; - }; - -} -} - %define %swig_sequence_iterator(Sequence...) %swig_sequence_iterator_with_making_function(swig::make_output_iterator,Sequence...) %enddef @@ -704,12 +471,12 @@ namespace swig class const_iterator; class const_reverse_iterator; - %typemap(out,noblock=1,fragment="SwigPySequence_Cont") + %typemap(out,noblock=1,fragment="SwigPyIterator_T") iterator, reverse_iterator, const_iterator, const_reverse_iterator { $result = SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &)), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN); } - %typemap(out,noblock=1,fragment="SwigPySequence_Cont") + %typemap(out,noblock=1,fragment="SwigPyIterator_T") std::pair<iterator, iterator>, std::pair<const_iterator, const_iterator> { $result = PyTuple_New(2); PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first), @@ -718,7 +485,7 @@ namespace swig swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); } - %fragment("SwigPyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="SwigPySequence_Cont") {} + %fragment("SwigPyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="SwigPyIterator_T") {} %typemap(out,noblock=1,fragment="SwigPyPairBoolOutputIterator") std::pair<iterator, bool>, std::pair<const_iterator, bool> { @@ -728,7 +495,7 @@ namespace swig PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second)); } - %typemap(in,noblock=1,fragment="SwigPySequence_Cont") + %typemap(in,noblock=1,fragment="SwigPyIterator_T") iterator(swig::SwigPyIterator *iter = 0, int res), reverse_iterator(swig::SwigPyIterator *iter = 0, int res), const_iterator(swig::SwigPyIterator *iter = 0, int res), @@ -746,14 +513,14 @@ namespace swig } } - %typecheck(%checkcode(ITERATOR),noblock=1,fragment="SwigPySequence_Cont") + %typecheck(%checkcode(ITERATOR),noblock=1,fragment="SwigPyIterator_T") iterator, reverse_iterator, const_iterator, const_reverse_iterator { swig::SwigPyIterator *iter = 0; int res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::SwigPyIterator::descriptor(), 0); $1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::SwigPyIterator_T<$type > *>(iter) != 0)); } - %fragment("SwigPySequence_Cont"); + %fragment("SwigPyIterator_T"); %newobject iterator(PyObject **PYTHON_SELF); %extend { @@ -999,26 +766,50 @@ namespace swig %fragment("StdSequenceTraits","header", fragment="StdTraits", - fragment="SwigPySequence_Cont") + fragment="SwigPySequence_Base") { namespace swig { - template <class SwigPySeq, class Seq> - inline void - assign(const SwigPySeq& swigpyseq, Seq* seq) { - // seq->assign(swigpyseq.begin(), swigpyseq.end()); // not used as not always implemented - typedef typename SwigPySeq::value_type value_type; - typename SwigPySeq::const_iterator it = swigpyseq.begin(); - for (;it != swigpyseq.end(); ++it) { - seq->insert(seq->end(),(value_type)(*it)); + template <class Seq, class T = typename Seq::value_type > + struct IteratorProtocol { + static void assign(PyObject *obj, Seq *seq) { + SwigVar_PyObject iter = PyObject_GetIter(obj); + if (iter) { + SwigVar_PyObject item = PyIter_Next(iter); + while (item) { + seq->insert(seq->end(), swig::as<T>(item)); + item = PyIter_Next(iter); + } + } } - } + + static bool check(PyObject *obj) { + int ret = false; + SwigVar_PyObject iter = PyObject_GetIter(obj); + if (iter) { + SwigVar_PyObject item = PyIter_Next(iter); + ret = true; + while (item) { + ret = swig::check<T>(item); + item = ret ? PyIter_Next(iter) : 0; + } + } + return ret; + } + }; template <class Seq, class T = typename Seq::value_type > struct traits_asptr_stdseq { typedef Seq sequence; typedef T value_type; + static bool is_iterable(PyObject *obj) { + SwigVar_PyObject iter = PyObject_GetIter(obj); + PyErr_Clear(); + return iter != 0; + } + static int asptr(PyObject *obj, sequence **seq) { + int ret = SWIG_ERROR; if (obj == Py_None || SWIG_Python_GetSwigThis(obj)) { sequence *p; swig_type_info *descriptor = swig::type_info<sequence>(); @@ -1026,27 +817,25 @@ namespace swig { if (seq) *seq = p; return SWIG_OLDOBJ; } - } else if (PySequence_Check(obj)) { + } else if (is_iterable(obj)) { try { - SwigPySequence_Cont<value_type> swigpyseq(obj); if (seq) { - sequence *pseq = new sequence(); - assign(swigpyseq, pseq); - *seq = pseq; - return SWIG_NEWOBJ; + *seq = new sequence(); + IteratorProtocol<Seq, T>::assign(obj, *seq); + if (!PyErr_Occurred()) + return SWIG_NEWOBJ; } else { - return swigpyseq.check() ? SWIG_OK : SWIG_ERROR; + return IteratorProtocol<Seq, T>::check(obj) ? SWIG_OK : SWIG_ERROR; } } catch (std::exception& e) { - if (seq) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, e.what()); - } - } - return SWIG_ERROR; + if (seq && !PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, e.what()); } + if (seq) + delete *seq; + return SWIG_ERROR; } - return SWIG_ERROR; + return ret; } }; |