swig/SWIG/Lib/python/pyiterators.swg
William S Fulton a658cc52aa remove unnecessary exception specifications, thereby preventing Visual Studio from having epileptic warnings fits filling the screen with heaps of compete and utter rubbish because it doesn't handle exception specifications properly.
Marcelo, please check that this doesn't remove any generated catch handlers. I dont' feel up to chasing a million and one macros to be sure.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@8397 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2006-01-12 22:36:04 +00:00

340 lines
7.6 KiB
Text

//
// Implemet 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>
namespace swig
{
/*
Throw a StopIteration exception
*/
%ignore 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::value;
%newobject PySwigIterator::next;
%newobject PySwigIterator::previous;
%newobject PySwigIterator::operator + (ptrdiff_t n) const;
%newobject PySwigIterator::operator - (ptrdiff_t n) const;
}
namespace swig
{
%nodirector PySwigIterator;
%extend PySwigIterator
{
%pythoncode {
def __iter__(self):
return self
}
}
}
%inline {
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 throw (stop_iteration) = 0;
// Forward iterator method, required by Python
virtual PySwigIterator *incr(size_t n = 1) throw (stop_iteration) = 0;
// Backward iterator method, very common in C++, but not required in Python
virtual PySwigIterator *decr(size_t n = 1) throw (stop_iteration)
{
throw stop_iteration();
}
// Random access iterator methods, but not required in Python
virtual ptrdiff_t distance(const PySwigIterator &x) const throw (std::invalid_argument)
{
throw std::invalid_argument("operation not supported");
}
virtual bool equal (const PySwigIterator &x) const throw (std::invalid_argument)
{
throw std::invalid_argument("operation not supported");
}
// C++ common/needed methods
virtual PySwigIterator *copy() const = 0;
public:
PyObject *next() throw (stop_iteration)
{
PyObject *obj = value();
incr();
return obj;
}
PyObject *previous() throw (stop_iteration)
{
decr();
return value();
}
PySwigIterator *advance(ptrdiff_t n) throw (stop_iteration)
{
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) throw (stop_iteration)
{
return *advance(n);
}
PySwigIterator& operator -= (ptrdiff_t n) throw (stop_iteration)
{
return *advance(-n);
}
PySwigIterator* operator + (ptrdiff_t n) const throw (stop_iteration)
{
return copy()->advance(n);
}
PySwigIterator* operator - (ptrdiff_t n) const throw (stop_iteration)
{
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="StdTraits") {
%#include <iterator>
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);
}
}
}