diff --git a/Examples/python/std_map/runme.py b/Examples/python/std_map/runme.py index 1a7e52524..addede01f 100644 --- a/Examples/python/std_map/runme.py +++ b/Examples/python/std_map/runme.py @@ -17,6 +17,13 @@ dmap = example.DoubleMap() dmap["hello"] = 1.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.keys() print dmap.values() @@ -26,6 +33,7 @@ print hmap.keys() print hmap.values() + dmap = {} dmap["hello"] = 2 dmap["hi"] = 4 @@ -34,3 +42,12 @@ hmap = example.halfi(dmap) print hmap print hmap.keys() print hmap.values() + + +dmap = hmap + +for i in dmap.iterkeys(): + print "key", i + +for i in dmap.itervalues(): + print "val", i diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg index 3a760a29b..066d70422 100644 --- a/Lib/python/pyiterators.swg +++ b/Lib/python/pyiterators.swg @@ -30,7 +30,18 @@ namespace swig %newobject PySwigIterator::operator - (ptrdiff_t n) const; } -%nodirector swig::PySwigIterator; +namespace swig +{ +%nodirector PySwigIterator; +%extend PySwigIterator +{ + %pythoncode { + def __iter__(self): + return self + } +} +} + %inline { namespace swig { struct stop_iteration @@ -78,6 +89,8 @@ namespace swig { public: + + PyObject *next() throw (stop_iteration) { PyObject *obj = value(); @@ -139,7 +152,7 @@ namespace swig { init = 1; } return desc; - } + } }; } } @@ -191,15 +204,30 @@ namespace swig { out_iterator current; }; + template + struct from_oper + { + typedef const ValueType& argument_type; + typedef PyObject *result_type; + result_type operator()(argument_type v) const + { + return swig::from(v); + } + }; + + - template + template::value_type, + typename FromOper = from_oper > class PySwigIteratorOpen_T : public PySwigIterator_T { public: + FromOper from; typedef OutIterator out_iterator; - typedef typename std::iterator_traits::value_type value_type; + typedef ValueType value_type; typedef PySwigIterator_T base; - typedef PySwigIteratorOpen_T self_type; + typedef PySwigIteratorOpen_T self_type; PySwigIteratorOpen_T(out_iterator curr, PyObject *seq) : PySwigIterator_T(curr, seq) @@ -207,7 +235,7 @@ namespace swig { } PyObject *value() const throw (stop_iteration) { - return swig::from((const value_type&)*(base::current)); + return from(static_cast(*(base::current))); } PySwigIterator *copy() const @@ -232,14 +260,17 @@ namespace swig { } }; - template + template::value_type, + typename FromOper = from_oper > class PySwigIteratorClosed_T : public PySwigIterator_T { public: + FromOper from; typedef OutIterator out_iterator; - typedef typename std::iterator_traits::value_type value_type; + typedef ValueType value_type; typedef PySwigIterator_T base; - typedef PySwigIteratorClosed_T self_type; + typedef PySwigIteratorClosed_T self_type; PySwigIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) : PySwigIterator_T(curr, seq), begin(first), end(last) @@ -250,7 +281,7 @@ namespace swig { if (base::current == end) { throw stop_iteration(); } else { - return swig::from((const value_type&)*(base::current)); + return from(static_cast(*(base::current))); } } @@ -282,7 +313,7 @@ namespace swig { } return this; } - + private: out_iterator begin; out_iterator end; diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i index 23725cf7e..9e6799fa9 100644 --- a/Lib/python/std_map.i +++ b/Lib/python/std_map.i @@ -62,6 +62,73 @@ } } }; + + template + 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 + 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 + struct PyMapIterator_T : PySwigIteratorClosed_T + { + PyMapIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : PySwigIteratorClosed_T(curr, first, last, seq) + { + } + }; + + + template > + struct PyMapKeyIterator_T : PyMapIterator_T + { + PyMapKeyIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : PyMapIterator_T(curr, first, last, seq) + { + } + }; + + template + inline PySwigIterator* + make_output_key_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) + { + return new PyMapKeyIterator_T(current, begin, end, seq); + } + + template > + struct PyMapValueIterator_T : PyMapIterator_T + { + PyMapValueIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : PyMapIterator_T(curr, first, last, seq) + { + } + }; + + + template + inline PySwigIterator* + make_output_value_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) + { + return new PyMapValueIterator_T(current, begin, end, seq); + } } } @@ -154,53 +221,16 @@ return self->find(key) != self->end(); } - PyObject* key_iterator() { - Map::size_type size = self->size(); - int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; - 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 + %newobject key_iterator(PyObject **PYTHON_SELF); + swig::PySwigIterator* key_iterator(PyObject **PYTHON_SELF) { + return swig::make_output_key_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } - PyObject* value_iterator() { - Map::size_type size = self->size(); - int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; - 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->second)); - } -%#if PY_VERSION_HEX >= 0x02020000 - PyObject* iter = PyObject_GetIter(keyTuple); - Py_DECREF(keyTuple); - return iter; -%#else - return keyTuple; -%#endif + + %newobject value_iterator(PyObject **PYTHON_SELF); + swig::PySwigIterator* value_iterator(PyObject **PYTHON_SELF) { + return swig::make_output_value_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } -#if !defined(SWIG_USE_STD_MAP_ITERATOR) + %pythoncode { def __iter__(self): return self.key_iterator() @@ -214,7 +244,6 @@ def iteritems(self): return self.iterator() } -#endif } %enddef