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.

280 lines
8.9 KiB

  1. /* Iterator objects */
  2. #include "Python.h"
  3. typedef struct {
  4. PyObject_HEAD
  5. Py_ssize_t it_index;
  6. PyObject *it_seq; /* Set to NULL when iterator is exhausted */
  7. } seqiterobject;
  8. PyObject *
  9. PySeqIter_New(PyObject *seq)
  10. {
  11. seqiterobject *it;
  12. if (!PySequence_Check(seq)) {
  13. PyErr_BadInternalCall();
  14. return NULL;
  15. }
  16. it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
  17. if (it == NULL)
  18. return NULL;
  19. it->it_index = 0;
  20. Py_INCREF(seq);
  21. it->it_seq = seq;
  22. _PyObject_GC_TRACK(it);
  23. return (PyObject *)it;
  24. }
  25. static void
  26. iter_dealloc(seqiterobject *it)
  27. {
  28. _PyObject_GC_UNTRACK(it);
  29. Py_XDECREF(it->it_seq);
  30. PyObject_GC_Del(it);
  31. }
  32. static int
  33. iter_traverse(seqiterobject *it, visitproc visit, void *arg)
  34. {
  35. Py_VISIT(it->it_seq);
  36. return 0;
  37. }
  38. static PyObject *
  39. iter_iternext(PyObject *iterator)
  40. {
  41. seqiterobject *it;
  42. PyObject *seq;
  43. PyObject *result;
  44. assert(PySeqIter_Check(iterator));
  45. it = (seqiterobject *)iterator;
  46. seq = it->it_seq;
  47. if (seq == NULL)
  48. return NULL;
  49. result = PySequence_GetItem(seq, it->it_index);
  50. if (result != NULL) {
  51. it->it_index++;
  52. return result;
  53. }
  54. if (PyErr_ExceptionMatches(PyExc_IndexError) ||
  55. PyErr_ExceptionMatches(PyExc_StopIteration))
  56. {
  57. PyErr_Clear();
  58. Py_DECREF(seq);
  59. it->it_seq = NULL;
  60. }
  61. return NULL;
  62. }
  63. static PyObject *
  64. iter_len(seqiterobject *it)
  65. {
  66. Py_ssize_t seqsize, len;
  67. if (it->it_seq) {
  68. if (_PyObject_HasLen(it->it_seq)) {
  69. seqsize = PySequence_Size(it->it_seq);
  70. if (seqsize == -1)
  71. return NULL;
  72. }
  73. else {
  74. Py_RETURN_NOTIMPLEMENTED;
  75. }
  76. len = seqsize - it->it_index;
  77. if (len >= 0)
  78. return PyLong_FromSsize_t(len);
  79. }
  80. return PyLong_FromLong(0);
  81. }
  82. PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
  83. static PyObject *
  84. iter_reduce(seqiterobject *it)
  85. {
  86. if (it->it_seq != NULL)
  87. return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
  88. it->it_seq, it->it_index);
  89. else
  90. return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
  91. }
  92. PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
  93. static PyObject *
  94. iter_setstate(seqiterobject *it, PyObject *state)
  95. {
  96. Py_ssize_t index = PyLong_AsSsize_t(state);
  97. if (index == -1 && PyErr_Occurred())
  98. return NULL;
  99. if (it->it_seq != NULL) {
  100. if (index < 0)
  101. index = 0;
  102. it->it_index = index;
  103. }
  104. Py_RETURN_NONE;
  105. }
  106. PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
  107. static PyMethodDef seqiter_methods[] = {
  108. {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
  109. {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
  110. {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
  111. {NULL, NULL} /* sentinel */
  112. };
  113. PyTypeObject PySeqIter_Type = {
  114. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  115. "iterator", /* tp_name */
  116. sizeof(seqiterobject), /* tp_basicsize */
  117. 0, /* tp_itemsize */
  118. /* methods */
  119. (destructor)iter_dealloc, /* tp_dealloc */
  120. 0, /* tp_print */
  121. 0, /* tp_getattr */
  122. 0, /* tp_setattr */
  123. 0, /* tp_reserved */
  124. 0, /* tp_repr */
  125. 0, /* tp_as_number */
  126. 0, /* tp_as_sequence */
  127. 0, /* tp_as_mapping */
  128. 0, /* tp_hash */
  129. 0, /* tp_call */
  130. 0, /* tp_str */
  131. PyObject_GenericGetAttr, /* tp_getattro */
  132. 0, /* tp_setattro */
  133. 0, /* tp_as_buffer */
  134. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
  135. 0, /* tp_doc */
  136. (traverseproc)iter_traverse, /* tp_traverse */
  137. 0, /* tp_clear */
  138. 0, /* tp_richcompare */
  139. 0, /* tp_weaklistoffset */
  140. PyObject_SelfIter, /* tp_iter */
  141. iter_iternext, /* tp_iternext */
  142. seqiter_methods, /* tp_methods */
  143. 0, /* tp_members */
  144. };
  145. /* -------------------------------------- */
  146. typedef struct {
  147. PyObject_HEAD
  148. PyObject *it_callable; /* Set to NULL when iterator is exhausted */
  149. PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
  150. } calliterobject;
  151. PyObject *
  152. PyCallIter_New(PyObject *callable, PyObject *sentinel)
  153. {
  154. calliterobject *it;
  155. it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
  156. if (it == NULL)
  157. return NULL;
  158. Py_INCREF(callable);
  159. it->it_callable = callable;
  160. Py_INCREF(sentinel);
  161. it->it_sentinel = sentinel;
  162. _PyObject_GC_TRACK(it);
  163. return (PyObject *)it;
  164. }
  165. static void
  166. calliter_dealloc(calliterobject *it)
  167. {
  168. _PyObject_GC_UNTRACK(it);
  169. Py_XDECREF(it->it_callable);
  170. Py_XDECREF(it->it_sentinel);
  171. PyObject_GC_Del(it);
  172. }
  173. static int
  174. calliter_traverse(calliterobject *it, visitproc visit, void *arg)
  175. {
  176. Py_VISIT(it->it_callable);
  177. Py_VISIT(it->it_sentinel);
  178. return 0;
  179. }
  180. static PyObject *
  181. calliter_iternext(calliterobject *it)
  182. {
  183. if (it->it_callable != NULL) {
  184. PyObject *args = PyTuple_New(0);
  185. PyObject *result;
  186. if (args == NULL)
  187. return NULL;
  188. result = PyObject_Call(it->it_callable, args, NULL);
  189. Py_DECREF(args);
  190. if (result != NULL) {
  191. int ok;
  192. ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
  193. if (ok == 0)
  194. return result; /* Common case, fast path */
  195. Py_DECREF(result);
  196. if (ok > 0) {
  197. Py_CLEAR(it->it_callable);
  198. Py_CLEAR(it->it_sentinel);
  199. }
  200. }
  201. else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
  202. PyErr_Clear();
  203. Py_CLEAR(it->it_callable);
  204. Py_CLEAR(it->it_sentinel);
  205. }
  206. }
  207. return NULL;
  208. }
  209. static PyObject *
  210. calliter_reduce(calliterobject *it)
  211. {
  212. if (it->it_callable != NULL && it->it_sentinel != NULL)
  213. return Py_BuildValue("N(OO)", _PyObject_GetBuiltin("iter"),
  214. it->it_callable, it->it_sentinel);
  215. else
  216. return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
  217. }
  218. static PyMethodDef calliter_methods[] = {
  219. {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
  220. {NULL, NULL} /* sentinel */
  221. };
  222. PyTypeObject PyCallIter_Type = {
  223. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  224. "callable_iterator", /* tp_name */
  225. sizeof(calliterobject), /* tp_basicsize */
  226. 0, /* tp_itemsize */
  227. /* methods */
  228. (destructor)calliter_dealloc, /* tp_dealloc */
  229. 0, /* tp_print */
  230. 0, /* tp_getattr */
  231. 0, /* tp_setattr */
  232. 0, /* tp_reserved */
  233. 0, /* tp_repr */
  234. 0, /* tp_as_number */
  235. 0, /* tp_as_sequence */
  236. 0, /* tp_as_mapping */
  237. 0, /* tp_hash */
  238. 0, /* tp_call */
  239. 0, /* tp_str */
  240. PyObject_GenericGetAttr, /* tp_getattro */
  241. 0, /* tp_setattro */
  242. 0, /* tp_as_buffer */
  243. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
  244. 0, /* tp_doc */
  245. (traverseproc)calliter_traverse, /* tp_traverse */
  246. 0, /* tp_clear */
  247. 0, /* tp_richcompare */
  248. 0, /* tp_weaklistoffset */
  249. PyObject_SelfIter, /* tp_iter */
  250. (iternextfunc)calliter_iternext, /* tp_iternext */
  251. calliter_methods, /* tp_methods */
  252. };