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.

292 lines
9.2 KiB

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