3333%ignore container_type##_iterator::size;
3434%ignore container_type##_iterator::##container_type##_iterator;
3535%ignore container_type##_iterator::operator *;
36- %ignore container_type##_iterator::valid;
3736%feature(" docstring" ) container_type##_iterator "
3837Python wrapper for an :class:`" #container_type " ` iterator. It has most of
3938the methods of :class:`" #datum_type " ` allowing easy access to the
@@ -51,18 +50,20 @@ KEEP_REFERENCE(container_type##_iterator*)
5150%inline %{
5251// Base class implements all methods except dereferencing
5352class container_type ##_iterator {
54- protected :
53+ private :
5554 Exiv2::container_type::iterator ptr;
5655 Exiv2::container_type::iterator end;
56+ bool invalidated;
5757public:
5858 container_type##_iterator(Exiv2::container_type::iterator ptr,
5959 Exiv2::container_type::iterator end) {
6060 this ->ptr = ptr;
6161 this ->end = end;
62+ invalidated = false ;
6263 }
6364 container_type##_iterator* __iter__ () { return this ; }
6465 Exiv2::datum_type* __next__ () {
65- if (! valid () )
66+ if (ptr == end )
6667 return NULL ;
6768 Exiv2::datum_type* result = &(*ptr);
6869 ptr++;
@@ -76,30 +77,31 @@ public:
7677 return *other != ptr;
7778 }
7879 std::string __str__ () {
79- if (valid ())
80- return " iterator<" + ptr->key () + " : " + ptr->print () + " >" ;
81- return " iterator<end>" ;
80+ if (invalidated)
81+ return " invalid iterator" ;
82+ if (ptr == end)
83+ return " iterator<end>" ;
84+ return " iterator<" + ptr->key () + " : " + ptr->print () + " >" ;
8285 }
83- bool valid () { return ptr != end; }
8486 // Provide method to invalidate iterator
85- void _invalidate () { ptr = end ; }
87+ void _invalidate () { invalidated = true ; }
8688 // Provide size() C++ method for buffer size check
8789 size_t size () {
88- if (valid () )
89- return ptr-> size () ;
90- return 0 ;
90+ if (invalidated || ptr == end )
91+ return 0 ;
92+ return ptr-> size () ;
9193 }
9294 // Dereference operator gives access to all datum methods
93- Exiv2::datum_type* operator ->() const { return &(*ptr); }
95+ Exiv2::datum_type* operator ->() const {
96+ if (invalidated)
97+ throw std::runtime_error (
98+ " container_type changed size during iteration" );
99+ if (ptr == end)
100+ throw std::runtime_error (
101+ " container_type iterator is at end of data" );
102+ return &(*ptr);
103+ }
94104};
95- // Bypass validity check for some methods
96- #define NOCHECK_delete_ ##container_type##_iterator
97- #define NOCHECK_ ##container_type##_iterator___iter__
98- #define NOCHECK_ ##container_type##_iterator___next__
99- #define NOCHECK_ ##container_type##_iterator___eq__
100- #define NOCHECK_ ##container_type##_iterator___ne__
101- #define NOCHECK_ ##container_type##_iterator___str__
102- #define NOCHECK_ ##container_type##_iterator__invalidate
103105%}
104106%enddef // DATA_ITERATOR_CLASSES
105107
@@ -144,15 +146,6 @@ public:
144146 argp->_invalidate ();
145147#endif
146148}
147- // Check validity of iterator before dereferencing
148- %typemap(check) container_type##_iterator* self {
149- %#ifndef NOCHECK_ ##$symname
150- if (!$1 ->valid ()) {
151- SWIG_exception_fail (SWIG_ValueError, " in method '" " $symname"
152- " ', invalid iterator cannot be dereferenced" );
153- }
154- %#endif
155- }
156149
157150// Functions to store weak references to iterators (swig >= v4.4)
158151%fragment(" iterator_weakref_funcs" , " header" , fragment=" private_data" ) {
@@ -227,11 +220,9 @@ static int store_iterator_weakref(PyObject* py_self, PyObject* iterator) {
227220 tmp, arg1->end ());
228221 $typemap (out, container_type##_iterator*);
229222#if SWIG_VERSION >= 0x040400
230- if ($1 ->valid ()) {
231- // Keep weak reference to the Python iterator
232- if (store_iterator_weakref (self, $result)) {
233- SWIG_fail;
234- }
223+ // Keep weak reference to the Python iterator
224+ if (store_iterator_weakref (self, $result)) {
225+ SWIG_fail;
235226 }
236227#endif // SWIG_VERSION
237228}
0 commit comments