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:
parent
670f9611e2
commit
ea53f7c645
3 changed files with 134 additions and 57 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue