move iterator classes to pyiterator and add/test std_carray.i class
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@8010 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
c8977f2dbb
commit
67dafc531d
7 changed files with 529 additions and 333 deletions
239
SWIG/Lib/python/pyiterators.swg
Normal file
239
SWIG/Lib/python/pyiterators.swg
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
//
|
||||
// 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 {
|
||||
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;
|
||||
}
|
||||
|
||||
%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, out_iterator first, out_iterator last, PyObject *seq)
|
||||
: PySwigIterator(seq), current(curr), begin(first), end(last)
|
||||
{
|
||||
}
|
||||
|
||||
PyObject *value() const throw (stop_iteration) {
|
||||
if (current == end) {
|
||||
throw stop_iteration();
|
||||
} else {
|
||||
return swig::from((const value_type&)*(current));
|
||||
}
|
||||
}
|
||||
|
||||
PySwigIterator *copy() const
|
||||
{
|
||||
return new self_type(*this);
|
||||
}
|
||||
|
||||
PySwigIterator *incr(size_t n = 1) throw (stop_iteration)
|
||||
{
|
||||
while (n--) {
|
||||
if (current == end) {
|
||||
throw stop_iteration();
|
||||
} else {
|
||||
++current;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
PySwigIterator *decr(size_t n = 1) throw (stop_iteration)
|
||||
{
|
||||
while (n--) {
|
||||
if (current == begin) {
|
||||
throw stop_iteration();
|
||||
} else {
|
||||
--current;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
bool equal (const PySwigIterator &iter) const throw (std::invalid_argument)
|
||||
{
|
||||
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 throw (std::invalid_argument)
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
const out_iterator& get_current() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
out_iterator current;
|
||||
out_iterator begin;
|
||||
out_iterator end;
|
||||
};
|
||||
|
||||
template<typename OutIter>
|
||||
inline PySwigIterator*
|
||||
make_output_iterator(const OutIter& current, const OutIter& begin = OutIter(),
|
||||
const OutIter& end = OutIter(), PyObject *seq = 0)
|
||||
{
|
||||
return new PySwigIterator_T<OutIter>(current, begin, end, seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue