PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Lib/python/pyiterators.swg

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