map iterators now use the native PySwigIterator, which is very very good for large maps, since no more temporals key/value tuples are needed

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@8311 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2006-01-09 00:40:44 +00:00
commit ea53f7c645
3 changed files with 134 additions and 57 deletions

View file

@ -17,6 +17,13 @@ dmap = example.DoubleMap()
dmap["hello"] = 1.0 dmap["hello"] = 1.0
dmap["hi"] = 2.0 dmap["hi"] = 2.0
for i in dmap.iterkeys():
print "key", i
for i in dmap.itervalues():
print "val", i
print dmap.items() print dmap.items()
print dmap.keys() print dmap.keys()
print dmap.values() print dmap.values()
@ -26,6 +33,7 @@ print hmap.keys()
print hmap.values() print hmap.values()
dmap = {} dmap = {}
dmap["hello"] = 2 dmap["hello"] = 2
dmap["hi"] = 4 dmap["hi"] = 4
@ -34,3 +42,12 @@ hmap = example.halfi(dmap)
print hmap print hmap
print hmap.keys() print hmap.keys()
print hmap.values() print hmap.values()
dmap = hmap
for i in dmap.iterkeys():
print "key", i
for i in dmap.itervalues():
print "val", i

View file

@ -30,7 +30,18 @@ namespace swig
%newobject PySwigIterator::operator - (ptrdiff_t n) const; %newobject PySwigIterator::operator - (ptrdiff_t n) const;
} }
%nodirector swig::PySwigIterator; namespace swig
{
%nodirector PySwigIterator;
%extend PySwigIterator
{
%pythoncode {
def __iter__(self):
return self
}
}
}
%inline { %inline {
namespace swig { namespace swig {
struct stop_iteration struct stop_iteration
@ -78,6 +89,8 @@ namespace swig {
public: public:
PyObject *next() throw (stop_iteration) PyObject *next() throw (stop_iteration)
{ {
PyObject *obj = value(); PyObject *obj = value();
@ -139,7 +152,7 @@ namespace swig {
init = 1; init = 1;
} }
return desc; return desc;
} }
}; };
} }
} }
@ -191,15 +204,30 @@ namespace swig {
out_iterator current; 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> template<typename OutIterator,
typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
typename FromOper = from_oper<ValueType> >
class PySwigIteratorOpen_T : public PySwigIterator_T<OutIterator> class PySwigIteratorOpen_T : public PySwigIterator_T<OutIterator>
{ {
public: public:
FromOper from;
typedef OutIterator out_iterator; typedef OutIterator out_iterator;
typedef typename std::iterator_traits<out_iterator>::value_type value_type; typedef ValueType value_type;
typedef PySwigIterator_T<out_iterator> base; typedef PySwigIterator_T<out_iterator> base;
typedef PySwigIteratorOpen_T<out_iterator> self_type; typedef PySwigIteratorOpen_T<OutIterator, ValueType, FromOper> self_type;
PySwigIteratorOpen_T(out_iterator curr, PyObject *seq) PySwigIteratorOpen_T(out_iterator curr, PyObject *seq)
: PySwigIterator_T<OutIterator>(curr, seq) : PySwigIterator_T<OutIterator>(curr, seq)
@ -207,7 +235,7 @@ namespace swig {
} }
PyObject *value() const throw (stop_iteration) { PyObject *value() const throw (stop_iteration) {
return swig::from((const value_type&)*(base::current)); return from(static_cast<const value_type&>(*(base::current)));
} }
PySwigIterator *copy() const PySwigIterator *copy() const
@ -232,14 +260,17 @@ namespace swig {
} }
}; };
template<typename OutIterator> template<typename OutIterator,
typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
typename FromOper = from_oper<ValueType> >
class PySwigIteratorClosed_T : public PySwigIterator_T<OutIterator> class PySwigIteratorClosed_T : public PySwigIterator_T<OutIterator>
{ {
public: public:
FromOper from;
typedef OutIterator out_iterator; typedef OutIterator out_iterator;
typedef typename std::iterator_traits<out_iterator>::value_type value_type; typedef ValueType value_type;
typedef PySwigIterator_T<out_iterator> base; typedef PySwigIterator_T<out_iterator> base;
typedef PySwigIteratorClosed_T<out_iterator> self_type; typedef PySwigIteratorClosed_T<OutIterator, ValueType, FromOper> self_type;
PySwigIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) PySwigIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq)
: PySwigIterator_T<OutIterator>(curr, seq), begin(first), end(last) : PySwigIterator_T<OutIterator>(curr, seq), begin(first), end(last)
@ -250,7 +281,7 @@ namespace swig {
if (base::current == end) { if (base::current == end) {
throw stop_iteration(); throw stop_iteration();
} else { } else {
return swig::from((const value_type&)*(base::current)); return from(static_cast<const value_type&>(*(base::current)));
} }
} }
@ -282,7 +313,7 @@ namespace swig {
} }
return this; return this;
} }
private: private:
out_iterator begin; out_iterator begin;
out_iterator end; out_iterator end;

View file

@ -62,6 +62,73 @@
} }
} }
}; };
template <class ValueType>
struct from_key_oper
{
typedef const ValueType& argument_type;
typedef PyObject *result_type;
result_type operator()(argument_type v) const
{
return swig::from(v.first);
}
};
template <class ValueType>
struct from_value_oper
{
typedef const ValueType& argument_type;
typedef PyObject *result_type;
result_type operator()(argument_type v) const
{
return swig::from(v.second);
}
};
template<class OutIterator, class FromOper, class ValueType = typename OutIterator::value_type>
struct PyMapIterator_T : PySwigIteratorClosed_T<OutIterator, ValueType, FromOper>
{
PyMapIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
: PySwigIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq)
{
}
};
template<class OutIterator,
class FromOper = from_key_oper<typename OutIterator::value_type> >
struct PyMapKeyIterator_T : PyMapIterator_T<OutIterator, FromOper>
{
PyMapKeyIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
: PyMapIterator_T<OutIterator, FromOper>(curr, first, last, seq)
{
}
};
template<typename OutIter>
inline PySwigIterator*
make_output_key_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
{
return new PyMapKeyIterator_T<OutIter>(current, begin, end, seq);
}
template<class OutIterator,
class FromOper = from_value_oper<typename OutIterator::value_type> >
struct PyMapValueIterator_T : PyMapIterator_T<OutIterator, FromOper>
{
PyMapValueIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
: PyMapIterator_T<OutIterator, FromOper>(curr, first, last, seq)
{
}
};
template<typename OutIter>
inline PySwigIterator*
make_output_value_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
{
return new PyMapValueIterator_T<OutIter>(current, begin, end, seq);
}
} }
} }
@ -154,53 +221,16 @@
return self->find(key) != self->end(); return self->find(key) != self->end();
} }
PyObject* key_iterator() { %newobject key_iterator(PyObject **PYTHON_SELF);
Map::size_type size = self->size(); swig::PySwigIterator* key_iterator(PyObject **PYTHON_SELF) {
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; return swig::make_output_key_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject* keyTuple = PyTuple_New(pysize);
Map::const_iterator i = self->begin();
for (int j = 0; j < pysize; ++i, ++j) {
PyTuple_SET_ITEM(keyTuple, j, swig::from(i->first));
}
%#if PY_VERSION_HEX >= 0x02020000
PyObject* iter = PyObject_GetIter(keyTuple);
Py_DECREF(keyTuple);
return iter;
%#else
return keyTuple;
%#endif
} }
PyObject* value_iterator() {
Map::size_type size = self->size(); %newobject value_iterator(PyObject **PYTHON_SELF);
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; swig::PySwigIterator* value_iterator(PyObject **PYTHON_SELF) {
if (pysize < 0) { return swig::make_output_value_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject* keyTuple = PyTuple_New(pysize);
Map::const_iterator i = self->begin();
for (int j = 0; j < pysize; ++i, ++j) {
PyTuple_SET_ITEM(keyTuple, j, swig::from(i->second));
}
%#if PY_VERSION_HEX >= 0x02020000
PyObject* iter = PyObject_GetIter(keyTuple);
Py_DECREF(keyTuple);
return iter;
%#else
return keyTuple;
%#endif
} }
#if !defined(SWIG_USE_STD_MAP_ITERATOR)
%pythoncode { %pythoncode {
def __iter__(self): def __iter__(self):
return self.key_iterator() return self.key_iterator()
@ -214,7 +244,6 @@
def iteritems(self): def iteritems(self):
return self.iterator() return self.iterator()
} }
#endif
} }
%enddef %enddef