/* ----------------------------------------------------------------------------- * pyiterators.swg * * Implement a python 'output' iterator for Python 2.2 or higher. * * 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. * ----------------------------------------------------------------------------- */ %include <std_common.i> %fragment("SwigPyIterator","header",fragment="<stddef.h>") { namespace swig { struct stop_iteration { }; struct SwigPyIterator { private: SwigPtr_PyObject _seq; protected: SwigPyIterator(PyObject *seq) : _seq(seq) { } 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) { throw stop_iteration(); } // 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(); incr(); SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads return obj; } /* Make an alias for Python 3.x */ PyObject *__next__() { return next(); } PyObject *previous() { SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads decr(); PyObject *obj = value(); SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads return obj; } SwigPyIterator *advance(ptrdiff_t n) { return (n > 0) ? incr(n) : decr(-n); } bool operator == (const SwigPyIterator& x) const { return equal(x); } bool operator != (const SwigPyIterator& x) const { return ! operator==(x); } SwigPyIterator& operator += (ptrdiff_t n) { return *advance(n); } SwigPyIterator& operator -= (ptrdiff_t n) { return *advance(-n); } 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 int init = 0; static swig_type_info* desc = 0; if (!init) { desc = SWIG_TypeQuery("swig::SwigPyIterator *"); init = 1; } return desc; } }; %#if defined(SWIGPYTHON_BUILTIN) inline PyObject* make_output_iterator_builtin (PyObject *pyself) { 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 { 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 { 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 SwigPyIteratorOpen_T : public SwigPyIterator_T<OutIterator> { 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) : SwigPyIterator_T<OutIterator>(curr, seq) { } PyObject *value() const { return from(static_cast<const value_type&>(*(base::current))); } SwigPyIterator *copy() const { return new self_type(*this); } SwigPyIterator *incr(size_t n = 1) { while (n--) { ++base::current; } return this; } SwigPyIterator *decr(size_t n = 1) { while (n--) { --base::current; } return this; } }; template<typename OutIterator, typename ValueType = typename std::iterator_traits<OutIterator>::value_type, typename FromOper = from_oper<ValueType> > class SwigPyIteratorClosed_T : public SwigPyIterator_T<OutIterator> { public: FromOper from; typedef OutIterator out_iterator; typedef ValueType value_type; typedef SwigPyIterator_T<out_iterator> base; typedef SwigPyIteratorClosed_T<OutIterator, ValueType, FromOper> self_type; SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) : SwigPyIterator_T<OutIterator>(curr, seq), begin(first), end(last) { } PyObject *value() const { if (base::current == end) { throw stop_iteration(); } else { return from(static_cast<const value_type&>(*(base::current))); } } SwigPyIterator *copy() const { return new self_type(*this); } SwigPyIterator *incr(size_t n = 1) { while (n--) { if (base::current == end) { throw stop_iteration(); } else { ++base::current; } } return this; } SwigPyIterator *decr(size_t n = 1) { while (n--) { if (base::current == begin) { throw stop_iteration(); } else { --base::current; } } return this; } private: out_iterator begin; out_iterator end; }; 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_iterator(const OutIter& current, PyObject *seq = 0) { return new SwigPyIteratorOpen_T<OutIter>(current, seq); } } } %fragment("SwigPyIterator"); namespace swig { /* Throw a StopIteration exception */ %ignore stop_iteration; struct stop_iteration {}; %typemap(throws) stop_iteration { (void)$1; SWIG_SetErrorObj(PyExc_StopIteration, SWIG_Py_Void()); SWIG_fail; } /* 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(swig::stop_iteration) SwigPyIterator::value() const; %catches(swig::stop_iteration) SwigPyIterator::incr(size_t n = 1); %catches(swig::stop_iteration) SwigPyIterator::decr(size_t n = 1); %catches(std::invalid_argument) SwigPyIterator::distance(const SwigPyIterator &x) const; %catches(std::invalid_argument) SwigPyIterator::equal (const SwigPyIterator &x) const; %catches(swig::stop_iteration) SwigPyIterator::__next__(); %catches(swig::stop_iteration) SwigPyIterator::next(); %catches(swig::stop_iteration) SwigPyIterator::previous(); %catches(swig::stop_iteration) SwigPyIterator::advance(ptrdiff_t n); %catches(swig::stop_iteration) SwigPyIterator::operator += (ptrdiff_t n); %catches(swig::stop_iteration) SwigPyIterator::operator -= (ptrdiff_t n); %catches(swig::stop_iteration) SwigPyIterator::operator + (ptrdiff_t n) const; %catches(swig::stop_iteration) SwigPyIterator::operator - (ptrdiff_t n) const; struct SwigPyIterator { protected: SwigPyIterator(PyObject *seq); 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 *__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; }; }