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.

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