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.

381 lines
12 KiB

  1. /* enumerate object */
  2. #include "Python.h"
  3. typedef struct {
  4. PyObject_HEAD
  5. Py_ssize_t en_index; /* current index of enumeration */
  6. PyObject* en_sit; /* secondary iterator of enumeration */
  7. PyObject* en_result; /* result tuple */
  8. PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */
  9. } enumobject;
  10. static PyObject *
  11. enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  12. {
  13. enumobject *en;
  14. PyObject *seq = NULL;
  15. PyObject *start = NULL;
  16. static char *kwlist[] = {"sequence", "start", 0};
  17. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:enumerate", kwlist,
  18. &seq, &start))
  19. return NULL;
  20. en = (enumobject *)type->tp_alloc(type, 0);
  21. if (en == NULL)
  22. return NULL;
  23. if (start != NULL) {
  24. start = PyNumber_Index(start);
  25. if (start == NULL) {
  26. Py_DECREF(en);
  27. return NULL;
  28. }
  29. assert(PyInt_Check(start) || PyLong_Check(start));
  30. en->en_index = PyInt_AsSsize_t(start);
  31. if (en->en_index == -1 && PyErr_Occurred()) {
  32. PyErr_Clear();
  33. en->en_index = PY_SSIZE_T_MAX;
  34. en->en_longindex = start;
  35. } else {
  36. en->en_longindex = NULL;
  37. Py_DECREF(start);
  38. }
  39. } else {
  40. en->en_index = 0;
  41. en->en_longindex = NULL;
  42. }
  43. en->en_sit = PyObject_GetIter(seq);
  44. if (en->en_sit == NULL) {
  45. Py_DECREF(en);
  46. return NULL;
  47. }
  48. en->en_result = PyTuple_Pack(2, Py_None, Py_None);
  49. if (en->en_result == NULL) {
  50. Py_DECREF(en);
  51. return NULL;
  52. }
  53. return (PyObject *)en;
  54. }
  55. static void
  56. enum_dealloc(enumobject *en)
  57. {
  58. PyObject_GC_UnTrack(en);
  59. Py_XDECREF(en->en_sit);
  60. Py_XDECREF(en->en_result);
  61. Py_XDECREF(en->en_longindex);
  62. Py_TYPE(en)->tp_free(en);
  63. }
  64. static int
  65. enum_traverse(enumobject *en, visitproc visit, void *arg)
  66. {
  67. Py_VISIT(en->en_sit);
  68. Py_VISIT(en->en_result);
  69. Py_VISIT(en->en_longindex);
  70. return 0;
  71. }
  72. static PyObject *
  73. enum_next_long(enumobject *en, PyObject* next_item)
  74. {
  75. static PyObject *one = NULL;
  76. PyObject *result = en->en_result;
  77. PyObject *next_index;
  78. PyObject *stepped_up;
  79. if (en->en_longindex == NULL) {
  80. en->en_longindex = PyInt_FromSsize_t(PY_SSIZE_T_MAX);
  81. if (en->en_longindex == NULL)
  82. return NULL;
  83. }
  84. if (one == NULL) {
  85. one = PyInt_FromLong(1);
  86. if (one == NULL)
  87. return NULL;
  88. }
  89. next_index = en->en_longindex;
  90. assert(next_index != NULL);
  91. stepped_up = PyNumber_Add(next_index, one);
  92. if (stepped_up == NULL)
  93. return NULL;
  94. en->en_longindex = stepped_up;
  95. if (result->ob_refcnt == 1) {
  96. Py_INCREF(result);
  97. Py_DECREF(PyTuple_GET_ITEM(result, 0));
  98. Py_DECREF(PyTuple_GET_ITEM(result, 1));
  99. } else {
  100. result = PyTuple_New(2);
  101. if (result == NULL) {
  102. Py_DECREF(next_index);
  103. Py_DECREF(next_item);
  104. return NULL;
  105. }
  106. }
  107. PyTuple_SET_ITEM(result, 0, next_index);
  108. PyTuple_SET_ITEM(result, 1, next_item);
  109. return result;
  110. }
  111. static PyObject *
  112. enum_next(enumobject *en)
  113. {
  114. PyObject *next_index;
  115. PyObject *next_item;
  116. PyObject *result = en->en_result;
  117. PyObject *it = en->en_sit;
  118. next_item = (*Py_TYPE(it)->tp_iternext)(it);
  119. if (next_item == NULL)
  120. return NULL;
  121. if (en->en_index == PY_SSIZE_T_MAX)
  122. return enum_next_long(en, next_item);
  123. next_index = PyInt_FromSsize_t(en->en_index);
  124. if (next_index == NULL) {
  125. Py_DECREF(next_item);
  126. return NULL;
  127. }
  128. en->en_index++;
  129. if (result->ob_refcnt == 1) {
  130. Py_INCREF(result);
  131. Py_DECREF(PyTuple_GET_ITEM(result, 0));
  132. Py_DECREF(PyTuple_GET_ITEM(result, 1));
  133. } else {
  134. result = PyTuple_New(2);
  135. if (result == NULL) {
  136. Py_DECREF(next_index);
  137. Py_DECREF(next_item);
  138. return NULL;
  139. }
  140. }
  141. PyTuple_SET_ITEM(result, 0, next_index);
  142. PyTuple_SET_ITEM(result, 1, next_item);
  143. return result;
  144. }
  145. PyDoc_STRVAR(enum_doc,
  146. "enumerate(iterable[, start]) -> iterator for index, value of iterable\n"
  147. "\n"
  148. "Return an enumerate object. iterable must be another object that supports\n"
  149. "iteration. The enumerate object yields pairs containing a count (from\n"
  150. "start, which defaults to zero) and a value yielded by the iterable argument.\n"
  151. "enumerate is useful for obtaining an indexed list:\n"
  152. " (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");
  153. PyTypeObject PyEnum_Type = {
  154. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  155. "enumerate", /* tp_name */
  156. sizeof(enumobject), /* tp_basicsize */
  157. 0, /* tp_itemsize */
  158. /* methods */
  159. (destructor)enum_dealloc, /* tp_dealloc */
  160. 0, /* tp_print */
  161. 0, /* tp_getattr */
  162. 0, /* tp_setattr */
  163. 0, /* tp_compare */
  164. 0, /* tp_repr */
  165. 0, /* tp_as_number */
  166. 0, /* tp_as_sequence */
  167. 0, /* tp_as_mapping */
  168. 0, /* tp_hash */
  169. 0, /* tp_call */
  170. 0, /* tp_str */
  171. PyObject_GenericGetAttr, /* tp_getattro */
  172. 0, /* tp_setattro */
  173. 0, /* tp_as_buffer */
  174. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
  175. Py_TPFLAGS_BASETYPE, /* tp_flags */
  176. enum_doc, /* tp_doc */
  177. (traverseproc)enum_traverse, /* tp_traverse */
  178. 0, /* tp_clear */
  179. 0, /* tp_richcompare */
  180. 0, /* tp_weaklistoffset */
  181. PyObject_SelfIter, /* tp_iter */
  182. (iternextfunc)enum_next, /* tp_iternext */
  183. 0, /* tp_methods */
  184. 0, /* tp_members */
  185. 0, /* tp_getset */
  186. 0, /* tp_base */
  187. 0, /* tp_dict */
  188. 0, /* tp_descr_get */
  189. 0, /* tp_descr_set */
  190. 0, /* tp_dictoffset */
  191. 0, /* tp_init */
  192. PyType_GenericAlloc, /* tp_alloc */
  193. enum_new, /* tp_new */
  194. PyObject_GC_Del, /* tp_free */
  195. };
  196. /* Reversed Object ***************************************************************/
  197. typedef struct {
  198. PyObject_HEAD
  199. Py_ssize_t index;
  200. PyObject* seq;
  201. } reversedobject;
  202. static PyObject *
  203. reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  204. {
  205. Py_ssize_t n;
  206. PyObject *seq, *reversed_meth;
  207. static PyObject *reversed_cache = NULL;
  208. reversedobject *ro;
  209. if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds))
  210. return NULL;
  211. if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) )
  212. return NULL;
  213. if (PyInstance_Check(seq)) {
  214. reversed_meth = PyObject_GetAttrString(seq, "__reversed__");
  215. if (reversed_meth == NULL) {
  216. if (PyErr_ExceptionMatches(PyExc_AttributeError))
  217. PyErr_Clear();
  218. else
  219. return NULL;
  220. }
  221. }
  222. else {
  223. reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__",
  224. &reversed_cache);
  225. if (reversed_meth == NULL && PyErr_Occurred())
  226. return NULL;
  227. }
  228. if (reversed_meth != NULL) {
  229. PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);
  230. Py_DECREF(reversed_meth);
  231. return res;
  232. }
  233. if (!PySequence_Check(seq)) {
  234. PyErr_SetString(PyExc_TypeError,
  235. "argument to reversed() must be a sequence");
  236. return NULL;
  237. }
  238. n = PySequence_Size(seq);
  239. if (n == -1)
  240. return NULL;
  241. ro = (reversedobject *)type->tp_alloc(type, 0);
  242. if (ro == NULL)
  243. return NULL;
  244. ro->index = n-1;
  245. Py_INCREF(seq);
  246. ro->seq = seq;
  247. return (PyObject *)ro;
  248. }
  249. static void
  250. reversed_dealloc(reversedobject *ro)
  251. {
  252. PyObject_GC_UnTrack(ro);
  253. Py_XDECREF(ro->seq);
  254. Py_TYPE(ro)->tp_free(ro);
  255. }
  256. static int
  257. reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
  258. {
  259. Py_VISIT(ro->seq);
  260. return 0;
  261. }
  262. static PyObject *
  263. reversed_next(reversedobject *ro)
  264. {
  265. PyObject *item;
  266. Py_ssize_t index = ro->index;
  267. if (index >= 0) {
  268. item = PySequence_GetItem(ro->seq, index);
  269. if (item != NULL) {
  270. ro->index--;
  271. return item;
  272. }
  273. if (PyErr_ExceptionMatches(PyExc_IndexError) ||
  274. PyErr_ExceptionMatches(PyExc_StopIteration))
  275. PyErr_Clear();
  276. }
  277. ro->index = -1;
  278. Py_CLEAR(ro->seq);
  279. return NULL;
  280. }
  281. PyDoc_STRVAR(reversed_doc,
  282. "reversed(sequence) -> reverse iterator over values of the sequence\n"
  283. "\n"
  284. "Return a reverse iterator");
  285. static PyObject *
  286. reversed_len(reversedobject *ro)
  287. {
  288. Py_ssize_t position, seqsize;
  289. if (ro->seq == NULL)
  290. return PyInt_FromLong(0);
  291. seqsize = PySequence_Size(ro->seq);
  292. if (seqsize == -1)
  293. return NULL;
  294. position = ro->index + 1;
  295. return PyInt_FromSsize_t((seqsize < position) ? 0 : position);
  296. }
  297. PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
  298. static PyMethodDef reversediter_methods[] = {
  299. {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
  300. {NULL, NULL} /* sentinel */
  301. };
  302. PyTypeObject PyReversed_Type = {
  303. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  304. "reversed", /* tp_name */
  305. sizeof(reversedobject), /* tp_basicsize */
  306. 0, /* tp_itemsize */
  307. /* methods */
  308. (destructor)reversed_dealloc, /* tp_dealloc */
  309. 0, /* tp_print */
  310. 0, /* tp_getattr */
  311. 0, /* tp_setattr */
  312. 0, /* tp_compare */
  313. 0, /* tp_repr */
  314. 0, /* tp_as_number */
  315. 0, /* tp_as_sequence */
  316. 0, /* tp_as_mapping */
  317. 0, /* tp_hash */
  318. 0, /* tp_call */
  319. 0, /* tp_str */
  320. PyObject_GenericGetAttr, /* tp_getattro */
  321. 0, /* tp_setattro */
  322. 0, /* tp_as_buffer */
  323. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
  324. Py_TPFLAGS_BASETYPE, /* tp_flags */
  325. reversed_doc, /* tp_doc */
  326. (traverseproc)reversed_traverse,/* tp_traverse */
  327. 0, /* tp_clear */
  328. 0, /* tp_richcompare */
  329. 0, /* tp_weaklistoffset */
  330. PyObject_SelfIter, /* tp_iter */
  331. (iternextfunc)reversed_next, /* tp_iternext */
  332. reversediter_methods, /* tp_methods */
  333. 0, /* tp_members */
  334. 0, /* tp_getset */
  335. 0, /* tp_base */
  336. 0, /* tp_dict */
  337. 0, /* tp_descr_get */
  338. 0, /* tp_descr_set */
  339. 0, /* tp_dictoffset */
  340. 0, /* tp_init */
  341. PyType_GenericAlloc, /* tp_alloc */
  342. reversed_new, /* tp_new */
  343. PyObject_GC_Del, /* tp_free */
  344. };