Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

380 lines
9.7 KiB

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