You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
380 lines
9.7 KiB
380 lines
9.7 KiB
/* ----------------------------------------------------------------------------- |
|
* See the LICENSE file for information on copyright, usage and redistribution |
|
* of SWIG, and the README file for authors - http://www.swig.org/release.html. |
|
* |
|
* pyiterators.swg |
|
* |
|
* Implement a python 'output' iterator for Python 2.2 or higher. |
|
* |
|
* Users can derive form the PySwigIterator to implemet their |
|
* own iterators. As an example (real one since we use it for STL/STD |
|
* containers), the template PySwigIterator_T does the |
|
* implementation for genereic C++ iterators. |
|
* ----------------------------------------------------------------------------- */ |
|
|
|
%include <std_common.i> |
|
|
|
%fragment("PySwigIterator","header") { |
|
namespace swig { |
|
struct stop_iteration { |
|
}; |
|
|
|
struct PySwigIterator { |
|
private: |
|
PyObject_ptr _seq; |
|
|
|
protected: |
|
PySwigIterator(PyObject *seq) : _seq(seq) |
|
{ |
|
} |
|
|
|
public: |
|
virtual ~PySwigIterator() {} |
|
|
|
// Access iterator method, required by Python |
|
virtual PyObject *value() const = 0; |
|
|
|
// Forward iterator method, required by Python |
|
virtual PySwigIterator *incr(size_t n = 1) = 0; |
|
|
|
// Backward iterator method, very common in C++, but not required in Python |
|
virtual PySwigIterator *decr(size_t n = 1) |
|
{ |
|
throw stop_iteration(); |
|
} |
|
|
|
// Random access iterator methods, but not required in Python |
|
virtual ptrdiff_t distance(const PySwigIterator &x) const |
|
{ |
|
throw std::invalid_argument("operation not supported"); |
|
} |
|
|
|
virtual bool equal (const PySwigIterator &x) const |
|
{ |
|
throw std::invalid_argument("operation not supported"); |
|
} |
|
|
|
// C++ common/needed methods |
|
virtual PySwigIterator *copy() const = 0; |
|
|
|
PyObject *next() |
|
{ |
|
PyObject *obj = value(); |
|
incr(); |
|
return obj; |
|
} |
|
|
|
PyObject *previous() |
|
{ |
|
decr(); |
|
return value(); |
|
} |
|
|
|
PySwigIterator *advance(ptrdiff_t n) |
|
{ |
|
return (n > 0) ? incr(n) : decr(-n); |
|
} |
|
|
|
bool operator == (const PySwigIterator& x) const |
|
{ |
|
return equal(x); |
|
} |
|
|
|
bool operator != (const PySwigIterator& x) const |
|
{ |
|
return ! operator==(x); |
|
} |
|
|
|
PySwigIterator& operator += (ptrdiff_t n) |
|
{ |
|
return *advance(n); |
|
} |
|
|
|
PySwigIterator& operator -= (ptrdiff_t n) |
|
{ |
|
return *advance(-n); |
|
} |
|
|
|
PySwigIterator* operator + (ptrdiff_t n) const |
|
{ |
|
return copy()->advance(n); |
|
} |
|
|
|
PySwigIterator* operator - (ptrdiff_t n) const |
|
{ |
|
return copy()->advance(-n); |
|
} |
|
|
|
ptrdiff_t operator - (const PySwigIterator& 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::PySwigIterator *"); |
|
init = 1; |
|
} |
|
return desc; |
|
} |
|
}; |
|
} |
|
} |
|
|
|
%fragment("PySwigIterator_T","header",fragment="PySwigIterator",fragment="StdTraits",fragment="StdIteratorTraits") { |
|
namespace swig { |
|
template<typename OutIterator> |
|
class PySwigIterator_T : public PySwigIterator |
|
{ |
|
public: |
|
typedef OutIterator out_iterator; |
|
typedef typename std::iterator_traits<out_iterator>::value_type value_type; |
|
typedef PySwigIterator_T<out_iterator> self_type; |
|
|
|
PySwigIterator_T(out_iterator curr, PyObject *seq) |
|
: PySwigIterator(seq), current(curr) |
|
{ |
|
} |
|
|
|
const out_iterator& get_current() const |
|
{ |
|
return current; |
|
} |
|
|
|
|
|
bool equal (const PySwigIterator &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 PySwigIterator &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 PySwigIteratorOpen_T : public PySwigIterator_T<OutIterator> |
|
{ |
|
public: |
|
FromOper from; |
|
typedef OutIterator out_iterator; |
|
typedef ValueType value_type; |
|
typedef PySwigIterator_T<out_iterator> base; |
|
typedef PySwigIteratorOpen_T<OutIterator, ValueType, FromOper> self_type; |
|
|
|
PySwigIteratorOpen_T(out_iterator curr, PyObject *seq) |
|
: PySwigIterator_T<OutIterator>(curr, seq) |
|
{ |
|
} |
|
|
|
PyObject *value() const { |
|
return from(static_cast<const value_type&>(*(base::current))); |
|
} |
|
|
|
PySwigIterator *copy() const |
|
{ |
|
return new self_type(*this); |
|
} |
|
|
|
PySwigIterator *incr(size_t n = 1) |
|
{ |
|
while (n--) { |
|
++base::current; |
|
} |
|
return this; |
|
} |
|
|
|
PySwigIterator *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 PySwigIteratorClosed_T : public PySwigIterator_T<OutIterator> |
|
{ |
|
public: |
|
FromOper from; |
|
typedef OutIterator out_iterator; |
|
typedef ValueType value_type; |
|
typedef PySwigIterator_T<out_iterator> base; |
|
typedef PySwigIteratorClosed_T<OutIterator, ValueType, FromOper> self_type; |
|
|
|
PySwigIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) |
|
: PySwigIterator_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))); |
|
} |
|
} |
|
|
|
PySwigIterator *copy() const |
|
{ |
|
return new self_type(*this); |
|
} |
|
|
|
PySwigIterator *incr(size_t n = 1) |
|
{ |
|
while (n--) { |
|
if (base::current == end) { |
|
throw stop_iteration(); |
|
} else { |
|
++base::current; |
|
} |
|
} |
|
return this; |
|
} |
|
|
|
PySwigIterator *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 PySwigIterator* |
|
make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) |
|
{ |
|
return new PySwigIteratorClosed_T<OutIter>(current, begin, end, seq); |
|
} |
|
|
|
template<typename OutIter> |
|
inline PySwigIterator* |
|
make_output_iterator(const OutIter& current, PyObject *seq = 0) |
|
{ |
|
return new PySwigIteratorOpen_T<OutIter>(current, seq); |
|
} |
|
} |
|
} |
|
|
|
|
|
%fragment("PySwigIterator"); |
|
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 PySwigIterator::copy; |
|
%newobject PySwigIterator::operator + (ptrdiff_t n) const; |
|
%newobject PySwigIterator::operator - (ptrdiff_t n) const; |
|
|
|
%nodirector PySwigIterator; |
|
%extend PySwigIterator { |
|
%pythoncode {def __iter__(self): return self} |
|
} |
|
|
|
%catches(swig::stop_iteration) PySwigIterator::value() const; |
|
%catches(swig::stop_iteration) PySwigIterator::incr(size_t n = 1); |
|
%catches(swig::stop_iteration) PySwigIterator::decr(size_t n = 1); |
|
%catches(std::invalid_argument) PySwigIterator::distance(const PySwigIterator &x) const; |
|
%catches(std::invalid_argument) PySwigIterator::equal (const PySwigIterator &x) const; |
|
%catches(swig::stop_iteration) PySwigIterator::next(); |
|
%catches(swig::stop_iteration) PySwigIterator::previous(); |
|
%catches(swig::stop_iteration) PySwigIterator::advance(ptrdiff_t n); |
|
%catches(swig::stop_iteration) PySwigIterator::operator += (ptrdiff_t n); |
|
%catches(swig::stop_iteration) PySwigIterator::operator -= (ptrdiff_t n); |
|
%catches(swig::stop_iteration) PySwigIterator::operator + (ptrdiff_t n) const; |
|
%catches(swig::stop_iteration) PySwigIterator::operator - (ptrdiff_t n) const; |
|
|
|
|
|
struct PySwigIterator |
|
{ |
|
protected: |
|
PySwigIterator(PyObject *seq); |
|
|
|
public: |
|
virtual ~PySwigIterator(); |
|
|
|
// Access iterator method, required by Python |
|
virtual PyObject *value() const = 0; |
|
|
|
// Forward iterator method, required by Python |
|
virtual PySwigIterator *incr(size_t n = 1) = 0; |
|
|
|
// Backward iterator method, very common in C++, but not required in Python |
|
virtual PySwigIterator *decr(size_t n = 1); |
|
|
|
// Random access iterator methods, but not required in Python |
|
virtual ptrdiff_t distance(const PySwigIterator &x) const; |
|
|
|
virtual bool equal (const PySwigIterator &x) const; |
|
|
|
// C++ common/needed methods |
|
virtual PySwigIterator *copy() const = 0; |
|
|
|
PyObject *next(); |
|
PyObject *previous(); |
|
PySwigIterator *advance(ptrdiff_t n); |
|
|
|
bool operator == (const PySwigIterator& x) const; |
|
bool operator != (const PySwigIterator& x) const; |
|
PySwigIterator& operator += (ptrdiff_t n); |
|
PySwigIterator& operator -= (ptrdiff_t n); |
|
PySwigIterator* operator + (ptrdiff_t n) const; |
|
PySwigIterator* operator - (ptrdiff_t n) const; |
|
ptrdiff_t operator - (const PySwigIterator& x) const; |
|
}; |
|
} |
|
|
|
|