/Objects/iterobject.c

http://unladen-swallow.googlecode.com/ · C · 230 lines · 206 code · 20 blank · 4 comment · 25 complexity · 1f939df03c62fe668637860c33ba07f3 MD5 · raw file

  1. /* Iterator objects */
  2. #include "Python.h"
  3. typedef struct {
  4. PyObject_HEAD
  5. long 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. seqsize = PySequence_Size(it->it_seq);
  69. if (seqsize == -1)
  70. return NULL;
  71. len = seqsize - it->it_index;
  72. if (len >= 0)
  73. return PyInt_FromSsize_t(len);
  74. }
  75. return PyInt_FromLong(0);
  76. }
  77. PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
  78. static PyMethodDef seqiter_methods[] = {
  79. {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
  80. {NULL, NULL} /* sentinel */
  81. };
  82. PyTypeObject PySeqIter_Type = {
  83. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  84. "iterator", /* tp_name */
  85. sizeof(seqiterobject), /* tp_basicsize */
  86. 0, /* tp_itemsize */
  87. /* methods */
  88. (destructor)iter_dealloc, /* tp_dealloc */
  89. 0, /* tp_print */
  90. 0, /* tp_getattr */
  91. 0, /* tp_setattr */
  92. 0, /* tp_compare */
  93. 0, /* tp_repr */
  94. 0, /* tp_as_number */
  95. 0, /* tp_as_sequence */
  96. 0, /* tp_as_mapping */
  97. 0, /* tp_hash */
  98. 0, /* tp_call */
  99. 0, /* tp_str */
  100. PyObject_GenericGetAttr, /* tp_getattro */
  101. 0, /* tp_setattro */
  102. 0, /* tp_as_buffer */
  103. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
  104. 0, /* tp_doc */
  105. (traverseproc)iter_traverse, /* tp_traverse */
  106. 0, /* tp_clear */
  107. 0, /* tp_richcompare */
  108. 0, /* tp_weaklistoffset */
  109. PyObject_SelfIter, /* tp_iter */
  110. iter_iternext, /* tp_iternext */
  111. seqiter_methods, /* tp_methods */
  112. 0, /* tp_members */
  113. };
  114. /* -------------------------------------- */
  115. typedef struct {
  116. PyObject_HEAD
  117. PyObject *it_callable; /* Set to NULL when iterator is exhausted */
  118. PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
  119. } calliterobject;
  120. PyObject *
  121. PyCallIter_New(PyObject *callable, PyObject *sentinel)
  122. {
  123. calliterobject *it;
  124. it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
  125. if (it == NULL)
  126. return NULL;
  127. Py_INCREF(callable);
  128. it->it_callable = callable;
  129. Py_INCREF(sentinel);
  130. it->it_sentinel = sentinel;
  131. _PyObject_GC_TRACK(it);
  132. return (PyObject *)it;
  133. }
  134. static void
  135. calliter_dealloc(calliterobject *it)
  136. {
  137. _PyObject_GC_UNTRACK(it);
  138. Py_XDECREF(it->it_callable);
  139. Py_XDECREF(it->it_sentinel);
  140. PyObject_GC_Del(it);
  141. }
  142. static int
  143. calliter_traverse(calliterobject *it, visitproc visit, void *arg)
  144. {
  145. Py_VISIT(it->it_callable);
  146. Py_VISIT(it->it_sentinel);
  147. return 0;
  148. }
  149. static PyObject *
  150. calliter_iternext(calliterobject *it)
  151. {
  152. if (it->it_callable != NULL) {
  153. PyObject *args = PyTuple_New(0);
  154. PyObject *result;
  155. if (args == NULL)
  156. return NULL;
  157. result = PyObject_Call(it->it_callable, args, NULL);
  158. Py_DECREF(args);
  159. if (result != NULL) {
  160. int ok;
  161. ok = PyObject_RichCompareBool(result,
  162. it->it_sentinel,
  163. Py_EQ);
  164. if (ok == 0)
  165. return result; /* Common case, fast path */
  166. Py_DECREF(result);
  167. if (ok > 0) {
  168. Py_CLEAR(it->it_callable);
  169. Py_CLEAR(it->it_sentinel);
  170. }
  171. }
  172. else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
  173. PyErr_Clear();
  174. Py_CLEAR(it->it_callable);
  175. Py_CLEAR(it->it_sentinel);
  176. }
  177. }
  178. return NULL;
  179. }
  180. PyTypeObject PyCallIter_Type = {
  181. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  182. "callable-iterator", /* tp_name */
  183. sizeof(calliterobject), /* tp_basicsize */
  184. 0, /* tp_itemsize */
  185. /* methods */
  186. (destructor)calliter_dealloc, /* tp_dealloc */
  187. 0, /* tp_print */
  188. 0, /* tp_getattr */
  189. 0, /* tp_setattr */
  190. 0, /* tp_compare */
  191. 0, /* tp_repr */
  192. 0, /* tp_as_number */
  193. 0, /* tp_as_sequence */
  194. 0, /* tp_as_mapping */
  195. 0, /* tp_hash */
  196. 0, /* tp_call */
  197. 0, /* tp_str */
  198. PyObject_GenericGetAttr, /* tp_getattro */
  199. 0, /* tp_setattro */
  200. 0, /* tp_as_buffer */
  201. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
  202. 0, /* tp_doc */
  203. (traverseproc)calliter_traverse, /* tp_traverse */
  204. 0, /* tp_clear */
  205. 0, /* tp_richcompare */
  206. 0, /* tp_weaklistoffset */
  207. PyObject_SelfIter, /* tp_iter */
  208. (iternextfunc)calliter_iternext, /* tp_iternext */
  209. 0, /* tp_methods */
  210. };