| /* ----------------------------------------------------------------------------- | |
| * pyiterators.swg | |
| * | |
| * Implement a python 'output' iterator. | |
| * | |
| * Users can derive form the SwigPyIterator to implement their | |
| * own iterators. As an example (real one since we use it for STL/STD | |
| * containers), the template SwigPyIterator_T does the | |
| * implementation for generic C++ iterators. | |
| * | |
| * The concept here is for a 'closed' iterator to implement a true Python | |
| * iterator which raises a StopIteration at the end of an iteration over a range. | |
| * An 'open' iterator is more like a traditional C++ iterator and does not | |
| * raise a StopIteration. | |
| * ----------------------------------------------------------------------------- */ | |
| %include <std_common.i> | |
| %fragment("SwigPyIterator","header",fragment="<stddef.h>") { | |
| namespace swig { | |
| struct SwigPyIterator { | |
| private: | |
| SwigPtr_PyObject _seq; | |
| protected: | |
| SwigPyIterator(PyObject *seq) : _seq(seq) | |
| { | |
| } | |
| void raise_stop_iteration() const | |
| { | |
| SWIG_SetErrorObj(PyExc_StopIteration, SWIG_Py_Void()); | |
| } | |
| public: | |
| virtual ~SwigPyIterator() {} | |
| // Access iterator method, required by Python | |
| virtual PyObject *value() const = 0; | |
| // Forward iterator method, required by Python | |
| virtual SwigPyIterator *incr(size_t n = 1) = 0; | |
| // Backward iterator method, very common in C++, but not required in Python | |
| // This default probably ought to instead raise some sort of unsupported exception | |
| virtual SwigPyIterator *decr(size_t /*n*/ = 1) | |
| { | |
| raise_stop_iteration(); | |
| return NULL; | |
| } | |
| // Random access iterator methods, but not required in Python | |
| virtual ptrdiff_t distance(const SwigPyIterator &/*x*/) const | |
| { | |
| throw std::invalid_argument("operation not supported"); | |
| } | |
| virtual bool equal (const SwigPyIterator &/*x*/) const | |
| { | |
| throw std::invalid_argument("operation not supported"); | |
| } | |
| // C++ common/needed methods | |
| virtual SwigPyIterator *copy() const = 0; | |
| PyObject *__next__() | |
| { | |
| SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads | |
| PyObject *obj = value(); | |
| if (obj) | |
| if (!incr()) | |
| obj = NULL; | |
| SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads | |
| return obj; | |
| } | |
| PyObject *previous() | |
| { | |
| SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads | |
| if (!decr()) | |
| return NULL; | |
| PyObject *obj = value(); | |
| SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads | |
| return obj; | |
| } | |
| SwigPyIterator *advance(ptrdiff_t n) | |
| { | |
| return (n > 0) ? incr((size_t)n) : decr((size_t)(-n)); | |
| } | |
| bool operator == (const SwigPyIterator& x) const | |
| { | |
| return equal(x); | |
| } | |
| bool operator != (const SwigPyIterator& x) const | |
| { | |
| return ! operator==(x); | |
| } | |
| SwigPyIterator& operator += (ptrdiff_t n) | |
| { | |
| SwigPyIterator *ret = advance(n); | |
| return ret ? *ret : *this; | |
| } | |
| SwigPyIterator& operator -= (ptrdiff_t n) | |
| { | |
| SwigPyIterator *ret = advance(-n); | |
| return ret ? *ret : *this; | |
| } | |
| SwigPyIterator* operator + (ptrdiff_t n) const | |
| { | |
| return copy()->advance(n); | |
| } | |
| SwigPyIterator* operator - (ptrdiff_t n) const | |
| { | |
| return copy()->advance(-n); | |
| } | |
| ptrdiff_t operator - (const SwigPyIterator& x) const | |
| { | |
| return x.distance(*this); | |
| } | |
| static swig_type_info* descriptor() { | |
| static swig_type_info* desc = SWIG_TypeQuery("swig::" SWIG_STRINGIFY(SwigPyIterator) " *"); | |
| return desc; | |
| } | |
| }; | |
| %#if defined(SWIGPYTHON_BUILTIN) | |
| inline PyObject* make_output_iterator_builtin (PyObject *pyself) | |
| { | |
| SWIG_Py_INCREF(pyself); | |
| return pyself; | |
| } | |
| %#endif | |
| } | |
| } | |
| %fragment("SwigPyIterator_T","header",fragment="<stddef.h>",fragment="SwigPyIterator",fragment="StdTraits",fragment="StdIteratorTraits") { | |
| namespace swig { | |
| template<typename OutIterator> | |
| class SwigPyIterator_T : public SwigPyIterator | |
| { | |
| public: | |
| typedef OutIterator out_iterator; | |
| typedef typename std::iterator_traits<out_iterator>::value_type value_type; | |
| typedef SwigPyIterator_T<out_iterator> self_type; | |
| SwigPyIterator_T(out_iterator curr, PyObject *seq) | |
| : SwigPyIterator(seq), current(curr) | |
| { | |
| } | |
| const out_iterator& get_current() const | |
| { | |
| return current; | |
| } | |
| bool equal (const SwigPyIterator &iter) const SWIG_OVERRIDE | |
| { | |
| const self_type *iters = dynamic_cast<const self_type *>(&iter); | |
| if (iters) { | |
| return (current == iters->get_current()); | |
| } else { | |
| throw std::invalid_argument("bad iterator type"); | |
| } | |
| } | |
| ptrdiff_t distance(const SwigPyIterator &iter) const SWIG_OVERRIDE | |
| { | |
| const self_type *iters = dynamic_cast<const self_type *>(&iter); | |
| if (iters) { | |
| return std::distance(current, iters->get_current()); | |
| } else { | |
| throw std::invalid_argument("bad iterator type"); | |
| } | |
| } | |
| protected: | |
| out_iterator current; | |
| }; | |
| template <class ValueType> | |
| struct from_oper | |
| { | |
| typedef const ValueType& argument_type; | |
| typedef PyObject *result_type; | |
| result_type operator()(argument_type v) const | |
| { | |
| return swig::from(v); | |
| } | |
| }; | |
| template<typename OutIterator, | |
| typename ValueType = typename std::iterator_traits<OutIterator>::value_type, | |
| typename FromOper = from_oper<ValueType> > | |
| class SwigPyForwardIteratorOpen_T : public SwigPyIterator_T<OutIterator> | |
| { | |
| public: | |
| FromOper from; | |
| typedef OutIterator out_iterator; | |
| typedef ValueType value_type; | |
| typedef SwigPyIterator_T<out_iterator> base; | |
| typedef SwigPyForwardIteratorOpen_T<OutIterator, ValueType, FromOper> self_type; | |
| SwigPyForwardIteratorOpen_T(out_iterator curr, PyObject *seq) | |
| : SwigPyIterator_T<OutIterator>(curr, seq) | |
| { | |
| } | |
| PyObject *value() const SWIG_OVERRIDE { | |
| return from(static_cast<const value_type&>(*(base::current))); | |
| } | |
| SwigPyIterator *copy() const SWIG_OVERRIDE | |
| { | |
| return new self_type(*this); | |
| } | |
| SwigPyIterator *incr(size_t n = 1) SWIG_OVERRIDE | |
| { | |
| // Open iterator does not raise StopIteration | |
| while (n--) { | |
| ++base::current; | |
| } | |
| return this; | |
| } | |
| }; | |
| template<typename OutIterator, | |
| typename ValueType = typename std::iterator_traits<OutIterator>::value_type, | |
| typename FromOper = from_oper<ValueType> > | |
| class SwigPyIteratorOpen_T : public SwigPyForwardIteratorOpen_T<OutIterator, ValueType, FromOper> | |
| { | |
| public: | |
| FromOper from; | |
| typedef OutIterator out_iterator; | |
| typedef ValueType value_type; | |
| typedef SwigPyIterator_T<out_iterator> base; | |
| typedef SwigPyIteratorOpen_T<OutIterator, ValueType, FromOper> self_type; | |
| SwigPyIteratorOpen_T(out_iterator curr, PyObject *seq) | |
| : SwigPyForwardIteratorOpen_T<OutIterator>(curr, seq) | |
| { | |
| } | |
| SwigPyIterator *decr(size_t n = 1) SWIG_OVERRIDE | |
| { | |
| // Open iterator does not raise StopIteration | |
| while (n--) { | |
| --base::current; | |
| } | |
| return this; | |
| } | |
| }; | |
| template<typename OutIterator, | |
| typename ValueType = typename std::iterator_traits<OutIterator>::value_type, | |
| typename FromOper = from_oper<ValueType> > | |
| class SwigPyForwardIteratorClosed_T : public SwigPyIterator_T<OutIterator> | |
| { | |
| public: | |
| FromOper from; | |
| typedef OutIterator out_iterator; | |
| typedef ValueType value_type; | |
| typedef SwigPyIterator_T<out_iterator> base; | |
| typedef SwigPyForwardIteratorClosed_T<OutIterator, ValueType, FromOper> self_type; | |
| SwigPyForwardIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) | |
| : SwigPyIterator_T<OutIterator>(curr, seq), begin(first), end(last) | |
| { | |
| } | |
| PyObject *value() const SWIG_OVERRIDE { | |
| if (base::current == end) { | |
| base::raise_stop_iteration(); | |
| return NULL; | |
| } else { | |
| return from(static_cast<const value_type&>(*(base::current))); | |
| } | |
| } | |
| SwigPyIterator *copy() const SWIG_OVERRIDE | |
| { | |
| return new self_type(*this); | |
| } | |
| SwigPyIterator *incr(size_t n = 1) SWIG_OVERRIDE | |
| { | |
| while (n--) { | |
| if (base::current == end) { | |
| base::raise_stop_iteration(); | |
| return NULL; | |
| } else { | |
| ++base::current; | |
| } | |
| } | |
| return this; | |
| } | |
| protected: | |
| out_iterator begin; | |
| out_iterator end; | |
| }; | |
| template<typename OutIterator, | |
| typename ValueType = typename std::iterator_traits<OutIterator>::value_type, | |
| typename FromOper = from_oper<ValueType> > | |
| class SwigPyIteratorClosed_T : public SwigPyForwardIteratorClosed_T<OutIterator,ValueType,FromOper> | |
| { | |
| public: | |
| FromOper from; | |
| typedef OutIterator out_iterator; | |
| typedef ValueType value_type; | |
| typedef SwigPyIterator_T<out_iterator> base; | |
| typedef SwigPyForwardIteratorClosed_T<OutIterator, ValueType, FromOper> base0; | |
| typedef SwigPyIteratorClosed_T<OutIterator, ValueType, FromOper> self_type; | |
| SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) | |
| : SwigPyForwardIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq) | |
| { | |
| } | |
| SwigPyIterator *decr(size_t n = 1) SWIG_OVERRIDE | |
| { | |
| while (n--) { | |
| if (base::current == base0::begin) { | |
| base0::raise_stop_iteration(); | |
| return NULL; | |
| } else { | |
| --base::current; | |
| } | |
| } | |
| return this; | |
| } | |
| }; | |
| template<typename OutIter> | |
| inline SwigPyIterator* | |
| make_output_forward_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) | |
| { | |
| return new SwigPyForwardIteratorClosed_T<OutIter>(current, begin, end, seq); | |
| } | |
| template<typename OutIter> | |
| inline SwigPyIterator* | |
| make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) | |
| { | |
| return new SwigPyIteratorClosed_T<OutIter>(current, begin, end, seq); | |
| } | |
| template<typename OutIter> | |
| inline SwigPyIterator* | |
| make_output_forward_iterator(const OutIter& current, PyObject *seq = 0) | |
| { | |
| return new SwigPyForwardIteratorOpen_T<OutIter>(current, seq); | |
| } | |
| template<typename OutIter> | |
| inline SwigPyIterator* | |
| make_output_iterator(const OutIter& current, PyObject *seq = 0) | |
| { | |
| return new SwigPyIteratorOpen_T<OutIter>(current, seq); | |
| } | |
| } | |
| } | |
| %fragment("SwigPyIterator"); | |
| namespace swig | |
| { | |
| %typemap(out, noblock=1) SwigPyIterator * { | |
| if (!$1) SWIG_fail; | |
| $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), $descriptor, $owner); | |
| } | |
| %typemap(out, noblock=1) SwigPyIterator & { | |
| if (PyErr_Occurred()) SWIG_fail; | |
| $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), $descriptor, $owner); | |
| } | |
| /* | |
| Mark methods that return new objects | |
| */ | |
| %newobject SwigPyIterator::copy; | |
| %newobject SwigPyIterator::operator + (ptrdiff_t n) const; | |
| %newobject SwigPyIterator::operator - (ptrdiff_t n) const; | |
| %nodirector SwigPyIterator; | |
| #if defined(SWIGPYTHON_BUILTIN) | |
| %feature("python:tp_iter") SwigPyIterator "&swig::make_output_iterator_builtin"; | |
| %feature("python:slot", "tp_iternext", functype="iternextfunc") SwigPyIterator::__next__; | |
| #else | |
| %extend SwigPyIterator { | |
| %pythoncode %{def __iter__(self): | |
| return self%} | |
| } | |
| #endif | |
| %catches(std::invalid_argument) SwigPyIterator::distance(const SwigPyIterator &x) const; | |
| %catches(std::invalid_argument) SwigPyIterator::equal (const SwigPyIterator &x) const; | |
| struct SwigPyIterator | |
| { | |
| protected: | |
| SwigPyIterator(PyObject *seq); | |
| void raise_stop_iteration(); | |
| public: | |
| virtual ~SwigPyIterator(); | |
| // Access iterator method, required by Python | |
| virtual PyObject *value() const = 0; | |
| // Forward iterator method, required by Python | |
| virtual SwigPyIterator *incr(size_t n = 1) = 0; | |
| // Backward iterator method, very common in C++, but not required in Python | |
| virtual SwigPyIterator *decr(size_t n = 1); | |
| // Random access iterator methods, but not required in Python | |
| virtual ptrdiff_t distance(const SwigPyIterator &x) const; | |
| virtual bool equal (const SwigPyIterator &x) const; | |
| // C++ common/needed methods | |
| virtual SwigPyIterator *copy() const = 0; | |
| PyObject *__next__(); | |
| PyObject *previous(); | |
| SwigPyIterator *advance(ptrdiff_t n); | |
| bool operator == (const SwigPyIterator& x) const; | |
| bool operator != (const SwigPyIterator& x) const; | |
| SwigPyIterator& operator += (ptrdiff_t n); | |
| SwigPyIterator& operator -= (ptrdiff_t n); | |
| SwigPyIterator* operator + (ptrdiff_t n) const; | |
| SwigPyIterator* operator - (ptrdiff_t n) const; | |
| ptrdiff_t operator - (const SwigPyIterator& x) const; | |
| }; | |
| } | |