OLD | NEW |
(Empty) | |
| 1 /* ----------------------------------------------------------------------------- |
| 2 * See the LICENSE file for information on copyright, usage and redistribution |
| 3 * of SWIG, and the README file for authors - http://www.swig.org/release.html. |
| 4 * |
| 5 * pyiterators.swg |
| 6 * |
| 7 * Implement a python 'output' iterator for Python 2.2 or higher. |
| 8 * |
| 9 * Users can derive form the SwigPyIterator to implement their |
| 10 * own iterators. As an example (real one since we use it for STL/STD |
| 11 * containers), the template SwigPyIterator_T does the |
| 12 * implementation for generic C++ iterators. |
| 13 * -----------------------------------------------------------------------------
*/ |
| 14 |
| 15 %include <std_common.i> |
| 16 |
| 17 %fragment("SwigPyIterator","header") { |
| 18 namespace swig { |
| 19 struct stop_iteration { |
| 20 }; |
| 21 |
| 22 struct SwigPyIterator { |
| 23 private: |
| 24 SwigPtr_PyObject _seq; |
| 25 |
| 26 protected: |
| 27 SwigPyIterator(PyObject *seq) : _seq(seq) |
| 28 { |
| 29 } |
| 30 |
| 31 public: |
| 32 virtual ~SwigPyIterator() {} |
| 33 |
| 34 // Access iterator method, required by Python |
| 35 virtual PyObject *value() const = 0; |
| 36 |
| 37 // Forward iterator method, required by Python |
| 38 virtual SwigPyIterator *incr(size_t n = 1) = 0; |
| 39 |
| 40 // Backward iterator method, very common in C++, but not required in Python |
| 41 virtual SwigPyIterator *decr(size_t /*n*/ = 1) |
| 42 { |
| 43 throw stop_iteration(); |
| 44 } |
| 45 |
| 46 // Random access iterator methods, but not required in Python |
| 47 virtual ptrdiff_t distance(const SwigPyIterator &/*x*/) const |
| 48 { |
| 49 throw std::invalid_argument("operation not supported"); |
| 50 } |
| 51 |
| 52 virtual bool equal (const SwigPyIterator &/*x*/) const |
| 53 { |
| 54 throw std::invalid_argument("operation not supported"); |
| 55 } |
| 56 |
| 57 // C++ common/needed methods |
| 58 virtual SwigPyIterator *copy() const = 0; |
| 59 |
| 60 PyObject *next() |
| 61 { |
| 62 SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads |
| 63 PyObject *obj = value(); |
| 64 incr(); |
| 65 SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads |
| 66 return obj; |
| 67 } |
| 68 |
| 69 /* Make an alias for Python 3.x */ |
| 70 PyObject *__next__() |
| 71 { |
| 72 return next(); |
| 73 } |
| 74 |
| 75 PyObject *previous() |
| 76 { |
| 77 SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads |
| 78 decr(); |
| 79 PyObject *obj = value(); |
| 80 SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads |
| 81 return obj; |
| 82 } |
| 83 |
| 84 SwigPyIterator *advance(ptrdiff_t n) |
| 85 { |
| 86 return (n > 0) ? incr(n) : decr(-n); |
| 87 } |
| 88 |
| 89 bool operator == (const SwigPyIterator& x) const |
| 90 { |
| 91 return equal(x); |
| 92 } |
| 93 |
| 94 bool operator != (const SwigPyIterator& x) const |
| 95 { |
| 96 return ! operator==(x); |
| 97 } |
| 98 |
| 99 SwigPyIterator& operator += (ptrdiff_t n) |
| 100 { |
| 101 return *advance(n); |
| 102 } |
| 103 |
| 104 SwigPyIterator& operator -= (ptrdiff_t n) |
| 105 { |
| 106 return *advance(-n); |
| 107 } |
| 108 |
| 109 SwigPyIterator* operator + (ptrdiff_t n) const |
| 110 { |
| 111 return copy()->advance(n); |
| 112 } |
| 113 |
| 114 SwigPyIterator* operator - (ptrdiff_t n) const |
| 115 { |
| 116 return copy()->advance(-n); |
| 117 } |
| 118 |
| 119 ptrdiff_t operator - (const SwigPyIterator& x) const |
| 120 { |
| 121 return x.distance(*this); |
| 122 } |
| 123 |
| 124 static swig_type_info* descriptor() { |
| 125 static int init = 0; |
| 126 static swig_type_info* desc = 0; |
| 127 if (!init) { |
| 128 desc = SWIG_TypeQuery("swig::SwigPyIterator *"); |
| 129 init = 1; |
| 130 } |
| 131 return desc; |
| 132 } |
| 133 }; |
| 134 } |
| 135 } |
| 136 |
| 137 %fragment("SwigPyIterator_T","header",fragment="SwigPyIterator",fragment="StdTra
its",fragment="StdIteratorTraits") { |
| 138 namespace swig { |
| 139 template<typename OutIterator> |
| 140 class SwigPyIterator_T : public SwigPyIterator |
| 141 { |
| 142 public: |
| 143 typedef OutIterator out_iterator; |
| 144 typedef typename std::iterator_traits<out_iterator>::value_type value_type;
|
| 145 typedef SwigPyIterator_T<out_iterator> self_type; |
| 146 |
| 147 SwigPyIterator_T(out_iterator curr, PyObject *seq) |
| 148 : SwigPyIterator(seq), current(curr) |
| 149 { |
| 150 } |
| 151 |
| 152 const out_iterator& get_current() const |
| 153 { |
| 154 return current; |
| 155 } |
| 156 |
| 157 |
| 158 bool equal (const SwigPyIterator &iter) const |
| 159 { |
| 160 const self_type *iters = dynamic_cast<const self_type *>(&iter); |
| 161 if (iters) { |
| 162 return (current == iters->get_current()); |
| 163 } else { |
| 164 throw std::invalid_argument("bad iterator type"); |
| 165 } |
| 166 } |
| 167 |
| 168 ptrdiff_t distance(const SwigPyIterator &iter) const |
| 169 { |
| 170 const self_type *iters = dynamic_cast<const self_type *>(&iter); |
| 171 if (iters) { |
| 172 return std::distance(current, iters->get_current()); |
| 173 } else { |
| 174 throw std::invalid_argument("bad iterator type"); |
| 175 } |
| 176 } |
| 177 |
| 178 protected: |
| 179 out_iterator current; |
| 180 }; |
| 181 |
| 182 template <class ValueType> |
| 183 struct from_oper |
| 184 { |
| 185 typedef const ValueType& argument_type; |
| 186 typedef PyObject *result_type; |
| 187 result_type operator()(argument_type v) const |
| 188 { |
| 189 return swig::from(v); |
| 190 } |
| 191 }; |
| 192 |
| 193 template<typename OutIterator, |
| 194 typename ValueType = typename std::iterator_traits<OutIterator>::valu
e_type, |
| 195 typename FromOper = from_oper<ValueType> > |
| 196 class SwigPyIteratorOpen_T : public SwigPyIterator_T<OutIterator> |
| 197 { |
| 198 public: |
| 199 FromOper from; |
| 200 typedef OutIterator out_iterator; |
| 201 typedef ValueType value_type; |
| 202 typedef SwigPyIterator_T<out_iterator> base; |
| 203 typedef SwigPyIteratorOpen_T<OutIterator, ValueType, FromOper> self_type; |
| 204 |
| 205 SwigPyIteratorOpen_T(out_iterator curr, PyObject *seq) |
| 206 : SwigPyIterator_T<OutIterator>(curr, seq) |
| 207 { |
| 208 } |
| 209 |
| 210 PyObject *value() const { |
| 211 return from(static_cast<const value_type&>(*(base::current))); |
| 212 } |
| 213 |
| 214 SwigPyIterator *copy() const |
| 215 { |
| 216 return new self_type(*this); |
| 217 } |
| 218 |
| 219 SwigPyIterator *incr(size_t n = 1) |
| 220 { |
| 221 while (n--) { |
| 222 ++base::current; |
| 223 } |
| 224 return this; |
| 225 } |
| 226 |
| 227 SwigPyIterator *decr(size_t n = 1) |
| 228 { |
| 229 while (n--) { |
| 230 --base::current; |
| 231 } |
| 232 return this; |
| 233 } |
| 234 }; |
| 235 |
| 236 template<typename OutIterator, |
| 237 typename ValueType = typename std::iterator_traits<OutIterator>::valu
e_type, |
| 238 typename FromOper = from_oper<ValueType> > |
| 239 class SwigPyIteratorClosed_T : public SwigPyIterator_T<OutIterator> |
| 240 { |
| 241 public: |
| 242 FromOper from; |
| 243 typedef OutIterator out_iterator; |
| 244 typedef ValueType value_type; |
| 245 typedef SwigPyIterator_T<out_iterator> base; |
| 246 typedef SwigPyIteratorClosed_T<OutIterator, ValueType, FromOper> self_type; |
| 247 |
| 248 SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator l
ast, PyObject *seq) |
| 249 : SwigPyIterator_T<OutIterator>(curr, seq), begin(first), end(last) |
| 250 { |
| 251 } |
| 252 |
| 253 PyObject *value() const { |
| 254 if (base::current == end) { |
| 255 throw stop_iteration(); |
| 256 } else { |
| 257 return from(static_cast<const value_type&>(*(base::current))); |
| 258 } |
| 259 } |
| 260 |
| 261 SwigPyIterator *copy() const |
| 262 { |
| 263 return new self_type(*this); |
| 264 } |
| 265 |
| 266 SwigPyIterator *incr(size_t n = 1) |
| 267 { |
| 268 while (n--) { |
| 269 if (base::current == end) { |
| 270 throw stop_iteration(); |
| 271 } else { |
| 272 ++base::current; |
| 273 } |
| 274 } |
| 275 return this; |
| 276 } |
| 277 |
| 278 SwigPyIterator *decr(size_t n = 1) |
| 279 { |
| 280 while (n--) { |
| 281 if (base::current == begin) { |
| 282 throw stop_iteration(); |
| 283 } else { |
| 284 --base::current; |
| 285 } |
| 286 } |
| 287 return this; |
| 288 } |
| 289 |
| 290 private: |
| 291 out_iterator begin; |
| 292 out_iterator end; |
| 293 }; |
| 294 |
| 295 template<typename OutIter> |
| 296 inline SwigPyIterator* |
| 297 make_output_iterator(const OutIter& current, const OutIter& begin,const OutIte
r& end, PyObject *seq = 0) |
| 298 { |
| 299 return new SwigPyIteratorClosed_T<OutIter>(current, begin, end, seq); |
| 300 } |
| 301 |
| 302 template<typename OutIter> |
| 303 inline SwigPyIterator* |
| 304 make_output_iterator(const OutIter& current, PyObject *seq = 0) |
| 305 { |
| 306 return new SwigPyIteratorOpen_T<OutIter>(current, seq); |
| 307 } |
| 308 } |
| 309 } |
| 310 |
| 311 |
| 312 %fragment("SwigPyIterator"); |
| 313 namespace swig |
| 314 { |
| 315 /* |
| 316 Throw a StopIteration exception |
| 317 */ |
| 318 %ignore stop_iteration; |
| 319 struct stop_iteration {}; |
| 320 |
| 321 %typemap(throws) stop_iteration { |
| 322 (void)$1; |
| 323 SWIG_SetErrorObj(PyExc_StopIteration, SWIG_Py_Void()); |
| 324 SWIG_fail; |
| 325 } |
| 326 |
| 327 /* |
| 328 Mark methods that return new objects |
| 329 */ |
| 330 %newobject SwigPyIterator::copy; |
| 331 %newobject SwigPyIterator::operator + (ptrdiff_t n) const; |
| 332 %newobject SwigPyIterator::operator - (ptrdiff_t n) const; |
| 333 |
| 334 %nodirector SwigPyIterator; |
| 335 %extend SwigPyIterator { |
| 336 %pythoncode {def __iter__(self): return self} |
| 337 } |
| 338 |
| 339 %catches(swig::stop_iteration) SwigPyIterator::value() const; |
| 340 %catches(swig::stop_iteration) SwigPyIterator::incr(size_t n = 1); |
| 341 %catches(swig::stop_iteration) SwigPyIterator::decr(size_t n = 1); |
| 342 %catches(std::invalid_argument) SwigPyIterator::distance(const SwigPyIterator
&x) const; |
| 343 %catches(std::invalid_argument) SwigPyIterator::equal (const SwigPyIterator &x
) const; |
| 344 %catches(swig::stop_iteration) SwigPyIterator::__next__(); |
| 345 %catches(swig::stop_iteration) SwigPyIterator::next(); |
| 346 %catches(swig::stop_iteration) SwigPyIterator::previous(); |
| 347 %catches(swig::stop_iteration) SwigPyIterator::advance(ptrdiff_t n); |
| 348 %catches(swig::stop_iteration) SwigPyIterator::operator += (ptrdiff_t n); |
| 349 %catches(swig::stop_iteration) SwigPyIterator::operator -= (ptrdiff_t n); |
| 350 %catches(swig::stop_iteration) SwigPyIterator::operator + (ptrdiff_t n) const; |
| 351 %catches(swig::stop_iteration) SwigPyIterator::operator - (ptrdiff_t n) const; |
| 352 |
| 353 |
| 354 struct SwigPyIterator |
| 355 { |
| 356 protected: |
| 357 SwigPyIterator(PyObject *seq); |
| 358 |
| 359 public: |
| 360 virtual ~SwigPyIterator(); |
| 361 |
| 362 // Access iterator method, required by Python |
| 363 virtual PyObject *value() const = 0; |
| 364 |
| 365 // Forward iterator method, required by Python |
| 366 virtual SwigPyIterator *incr(size_t n = 1) = 0; |
| 367 |
| 368 // Backward iterator method, very common in C++, but not required in Python |
| 369 virtual SwigPyIterator *decr(size_t n = 1); |
| 370 |
| 371 // Random access iterator methods, but not required in Python |
| 372 virtual ptrdiff_t distance(const SwigPyIterator &x) const; |
| 373 |
| 374 virtual bool equal (const SwigPyIterator &x) const; |
| 375 |
| 376 // C++ common/needed methods |
| 377 virtual SwigPyIterator *copy() const = 0; |
| 378 |
| 379 PyObject *next(); |
| 380 PyObject *__next__(); |
| 381 PyObject *previous(); |
| 382 SwigPyIterator *advance(ptrdiff_t n); |
| 383 |
| 384 bool operator == (const SwigPyIterator& x) const; |
| 385 bool operator != (const SwigPyIterator& x) const; |
| 386 SwigPyIterator& operator += (ptrdiff_t n); |
| 387 SwigPyIterator& operator -= (ptrdiff_t n); |
| 388 SwigPyIterator* operator + (ptrdiff_t n) const; |
| 389 SwigPyIterator* operator - (ptrdiff_t n) const; |
| 390 ptrdiff_t operator - (const SwigPyIterator& x) const; |
| 391 }; |
| 392 } |
| 393 |
OLD | NEW |