blob: e32ef8cfed2a60ae215417fb907a8171359ab532 [file] [log] [blame]
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001
2#include "Python.h"
3
4/* Itertools module written and maintained
5 by Raymond D. Hettinger <python@rcn.com>
6 Copyright (c) 2003 Python Software Foundation.
7 All rights reserved.
8*/
9
10/* dropwhile object **********************************************************/
11
12typedef struct {
13 PyObject_HEAD
14 PyObject *func;
15 PyObject *it;
16 long start;
17} dropwhileobject;
18
19PyTypeObject dropwhile_type;
20
21static PyObject *
22dropwhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
23{
24 PyObject *func, *seq;
25 PyObject *it;
26 dropwhileobject *lz;
27
28 if (!PyArg_UnpackTuple(args, "dropwhile", 2, 2, &func, &seq))
29 return NULL;
30
31 /* Get iterator. */
32 it = PyObject_GetIter(seq);
33 if (it == NULL)
34 return NULL;
35
36 /* create dropwhileobject structure */
37 lz = (dropwhileobject *)type->tp_alloc(type, 0);
38 if (lz == NULL) {
39 Py_DECREF(it);
40 return NULL;
41 }
42 Py_INCREF(func);
43 lz->func = func;
44 lz->it = it;
45 lz->start = 0;
46
47 return (PyObject *)lz;
48}
49
50static void
51dropwhile_dealloc(dropwhileobject *lz)
52{
53 PyObject_GC_UnTrack(lz);
54 Py_XDECREF(lz->func);
55 Py_XDECREF(lz->it);
56 lz->ob_type->tp_free(lz);
57}
58
59static int
60dropwhile_traverse(dropwhileobject *lz, visitproc visit, void *arg)
61{
62 int err;
63
64 if (lz->it) {
65 err = visit(lz->it, arg);
66 if (err)
67 return err;
68 }
69 if (lz->func) {
70 err = visit(lz->func, arg);
71 if (err)
72 return err;
73 }
74 return 0;
75}
76
77static PyObject *
78dropwhile_next(dropwhileobject *lz)
79{
80 PyObject *item, *good;
81 long ok;
82
83 for (;;) {
84 item = PyIter_Next(lz->it);
85 if (item == NULL)
86 return NULL;
87 if (lz->start == 1)
88 return item;
89
90 good = PyObject_CallFunctionObjArgs(lz->func, item, NULL);
91 if (good == NULL) {
92 Py_DECREF(item);
93 return NULL;
94 }
95 ok = PyObject_IsTrue(good);
96 Py_DECREF(good);
97 if (!ok) {
98 lz->start = 1;
99 return item;
100 }
101 Py_DECREF(item);
102 }
103}
104
105static PyObject *
106dropwhile_getiter(PyObject *lz)
107{
108 Py_INCREF(lz);
109 return lz;
110}
111
112PyDoc_STRVAR(dropwhile_doc,
113"dropwhile(predicate, iterable) --> dropwhile object\n\
114\n\
115Drop items from the iterable while predicate(item) is true.\n\
116Afterwards, return every element until the iterable is exhausted.");
117
118PyTypeObject dropwhile_type = {
119 PyObject_HEAD_INIT(NULL)
120 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000121 "itertools.dropwhile", /* tp_name */
122 sizeof(dropwhileobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000123 0, /* tp_itemsize */
124 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000125 (destructor)dropwhile_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000126 0, /* tp_print */
127 0, /* tp_getattr */
128 0, /* tp_setattr */
129 0, /* tp_compare */
130 0, /* tp_repr */
131 0, /* tp_as_number */
132 0, /* tp_as_sequence */
133 0, /* tp_as_mapping */
134 0, /* tp_hash */
135 0, /* tp_call */
136 0, /* tp_str */
137 PyObject_GenericGetAttr, /* tp_getattro */
138 0, /* tp_setattro */
139 0, /* tp_as_buffer */
140 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
141 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000142 dropwhile_doc, /* tp_doc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000143 (traverseproc)dropwhile_traverse, /* tp_traverse */
144 0, /* tp_clear */
145 0, /* tp_richcompare */
146 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000147 (getiterfunc)dropwhile_getiter, /* tp_iter */
148 (iternextfunc)dropwhile_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000149 0, /* tp_methods */
150 0, /* tp_members */
151 0, /* tp_getset */
152 0, /* tp_base */
153 0, /* tp_dict */
154 0, /* tp_descr_get */
155 0, /* tp_descr_set */
156 0, /* tp_dictoffset */
157 0, /* tp_init */
158 PyType_GenericAlloc, /* tp_alloc */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000159 dropwhile_new, /* tp_new */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000160 PyObject_GC_Del, /* tp_free */
161};
162
163
164/* takewhile object **********************************************************/
165
166typedef struct {
167 PyObject_HEAD
168 PyObject *func;
169 PyObject *it;
170 long stop;
171} takewhileobject;
172
173PyTypeObject takewhile_type;
174
175static PyObject *
176takewhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
177{
178 PyObject *func, *seq;
179 PyObject *it;
180 takewhileobject *lz;
181
182 if (!PyArg_UnpackTuple(args, "takewhile", 2, 2, &func, &seq))
183 return NULL;
184
185 /* Get iterator. */
186 it = PyObject_GetIter(seq);
187 if (it == NULL)
188 return NULL;
189
190 /* create takewhileobject structure */
191 lz = (takewhileobject *)type->tp_alloc(type, 0);
192 if (lz == NULL) {
193 Py_DECREF(it);
194 return NULL;
195 }
196 Py_INCREF(func);
197 lz->func = func;
198 lz->it = it;
199 lz->stop = 0;
200
201 return (PyObject *)lz;
202}
203
204static void
205takewhile_dealloc(takewhileobject *lz)
206{
207 PyObject_GC_UnTrack(lz);
208 Py_XDECREF(lz->func);
209 Py_XDECREF(lz->it);
210 lz->ob_type->tp_free(lz);
211}
212
213static int
214takewhile_traverse(takewhileobject *lz, visitproc visit, void *arg)
215{
216 int err;
217
218 if (lz->it) {
219 err = visit(lz->it, arg);
220 if (err)
221 return err;
222 }
223 if (lz->func) {
224 err = visit(lz->func, arg);
225 if (err)
226 return err;
227 }
228 return 0;
229}
230
231static PyObject *
232takewhile_next(takewhileobject *lz)
233{
234 PyObject *item, *good;
235 long ok;
236
237 if (lz->stop == 1)
238 return NULL;
239
240 item = PyIter_Next(lz->it);
241 if (item == NULL)
242 return NULL;
243
244 good = PyObject_CallFunctionObjArgs(lz->func, item, NULL);
245 if (good == NULL) {
246 Py_DECREF(item);
247 return NULL;
248 }
249 ok = PyObject_IsTrue(good);
250 Py_DECREF(good);
251 if (ok)
252 return item;
253 Py_DECREF(item);
254 lz->stop = 1;
255 return NULL;
256}
257
258static PyObject *
259takewhile_getiter(PyObject *lz)
260{
261 Py_INCREF(lz);
262 return lz;
263}
264
265PyDoc_STRVAR(takewhile_doc,
266"takewhile(predicate, iterable) --> takewhile object\n\
267\n\
268Return successive entries from an iterable as long as the \n\
269predicate evaluates to true for each entry.");
270
271PyTypeObject takewhile_type = {
272 PyObject_HEAD_INIT(NULL)
273 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000274 "itertools.takewhile", /* tp_name */
275 sizeof(takewhileobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000276 0, /* tp_itemsize */
277 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000278 (destructor)takewhile_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000279 0, /* tp_print */
280 0, /* tp_getattr */
281 0, /* tp_setattr */
282 0, /* tp_compare */
283 0, /* tp_repr */
284 0, /* tp_as_number */
285 0, /* tp_as_sequence */
286 0, /* tp_as_mapping */
287 0, /* tp_hash */
288 0, /* tp_call */
289 0, /* tp_str */
290 PyObject_GenericGetAttr, /* tp_getattro */
291 0, /* tp_setattro */
292 0, /* tp_as_buffer */
293 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
294 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000295 takewhile_doc, /* tp_doc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000296 (traverseproc)takewhile_traverse, /* tp_traverse */
297 0, /* tp_clear */
298 0, /* tp_richcompare */
299 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000300 (getiterfunc)takewhile_getiter, /* tp_iter */
301 (iternextfunc)takewhile_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000302 0, /* tp_methods */
303 0, /* tp_members */
304 0, /* tp_getset */
305 0, /* tp_base */
306 0, /* tp_dict */
307 0, /* tp_descr_get */
308 0, /* tp_descr_set */
309 0, /* tp_dictoffset */
310 0, /* tp_init */
311 PyType_GenericAlloc, /* tp_alloc */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000312 takewhile_new, /* tp_new */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000313 PyObject_GC_Del, /* tp_free */
314};
315
316
317/* islice object ************************************************************/
318
319typedef struct {
320 PyObject_HEAD
321 PyObject *it;
322 long next;
323 long stop;
324 long step;
325 long cnt;
326} isliceobject;
327
328PyTypeObject islice_type;
329
330static PyObject *
331islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
332{
333 PyObject *seq;
334 long a1=0, a2=0, a3=0, start=0, stop=0, step=1;
335 PyObject *it;
336 int numargs;
337 isliceobject *lz;
338
339 numargs = PyTuple_Size(args);
340 if (!PyArg_ParseTuple(args, "Ol|ll:islice", &seq, &a1, &a2, &a3))
341 return NULL;
342
343 if (numargs == 2) {
344 stop = a1;
345 } else if (numargs == 3) {
346 start = a1;
347 stop = a2;
348 } else {
349 start = a1;
350 stop = a2;
351 step = a3;
352 }
353
354 if (start<0 || stop<0) {
355 PyErr_SetString(PyExc_ValueError,
356 "Indices for islice() must be positive.");
357 return NULL;
358 }
359
360 if (step<1) {
361 PyErr_SetString(PyExc_ValueError,
362 "Step must be one or larger for islice().");
363 return NULL;
364 }
365
366 /* Get iterator. */
367 it = PyObject_GetIter(seq);
368 if (it == NULL)
369 return NULL;
370
371 /* create isliceobject structure */
372 lz = (isliceobject *)type->tp_alloc(type, 0);
373 if (lz == NULL) {
374 Py_DECREF(it);
375 return NULL;
376 }
377 lz->it = it;
378 lz->next = start;
379 lz->stop = stop;
380 lz->step = step;
381 lz->cnt = 0L;
382
383 return (PyObject *)lz;
384}
385
386static void
387islice_dealloc(isliceobject *lz)
388{
389 PyObject_GC_UnTrack(lz);
390 Py_XDECREF(lz->it);
391 lz->ob_type->tp_free(lz);
392}
393
394static int
395islice_traverse(isliceobject *lz, visitproc visit, void *arg)
396{
397 if (lz->it)
398 return visit(lz->it, arg);
399 return 0;
400}
401
402static PyObject *
403islice_next(isliceobject *lz)
404{
405 PyObject *item;
Raymond Hettinger2012f172003-02-07 05:32:58 +0000406 long oldnext;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000407
408 while (lz->cnt < lz->next) {
409 item = PyIter_Next(lz->it);
410 if (item == NULL)
411 return NULL;
412 Py_DECREF(item);
413 lz->cnt++;
414 }
415 if (lz->cnt >= lz->stop)
416 return NULL;
417 item = PyIter_Next(lz->it);
418 if (item == NULL)
419 return NULL;
420 lz->cnt++;
Raymond Hettinger2012f172003-02-07 05:32:58 +0000421 oldnext = lz->next;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000422 lz->next += lz->step;
Raymond Hettinger2012f172003-02-07 05:32:58 +0000423 if (lz->next < oldnext) /* Check for overflow */
424 lz->next = lz->stop;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000425 return item;
426}
427
428static PyObject *
429islice_getiter(PyObject *lz)
430{
431 Py_INCREF(lz);
432 return lz;
433}
434
435PyDoc_STRVAR(islice_doc,
436"islice(iterable, [start,] stop [, step]) --> islice object\n\
437\n\
438Return an iterator whose next() method returns selected values from an\n\
439iterable. If start is specified, will skip all preceding elements;\n\
440otherwise, start defaults to zero. Step defaults to one. If\n\
441specified as another value, step determines how many values are \n\
442skipped between successive calls. Works like a slice() on a list\n\
443but returns an iterator.");
444
445PyTypeObject islice_type = {
446 PyObject_HEAD_INIT(NULL)
447 0, /* ob_size */
448 "itertools.islice", /* tp_name */
449 sizeof(isliceobject), /* tp_basicsize */
450 0, /* tp_itemsize */
451 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000452 (destructor)islice_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000453 0, /* tp_print */
454 0, /* tp_getattr */
455 0, /* tp_setattr */
456 0, /* tp_compare */
457 0, /* tp_repr */
458 0, /* tp_as_number */
459 0, /* tp_as_sequence */
460 0, /* tp_as_mapping */
461 0, /* tp_hash */
462 0, /* tp_call */
463 0, /* tp_str */
464 PyObject_GenericGetAttr, /* tp_getattro */
465 0, /* tp_setattro */
466 0, /* tp_as_buffer */
467 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
468 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000469 islice_doc, /* tp_doc */
470 (traverseproc)islice_traverse, /* tp_traverse */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000471 0, /* tp_clear */
472 0, /* tp_richcompare */
473 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000474 (getiterfunc)islice_getiter, /* tp_iter */
475 (iternextfunc)islice_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000476 0, /* tp_methods */
477 0, /* tp_members */
478 0, /* tp_getset */
479 0, /* tp_base */
480 0, /* tp_dict */
481 0, /* tp_descr_get */
482 0, /* tp_descr_set */
483 0, /* tp_dictoffset */
484 0, /* tp_init */
485 PyType_GenericAlloc, /* tp_alloc */
486 islice_new, /* tp_new */
487 PyObject_GC_Del, /* tp_free */
488};
489
490
491/* starmap object ************************************************************/
492
493typedef struct {
494 PyObject_HEAD
495 PyObject *func;
496 PyObject *it;
497} starmapobject;
498
499PyTypeObject starmap_type;
500
501static PyObject *
502starmap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
503{
504 PyObject *func, *seq;
505 PyObject *it;
506 starmapobject *lz;
507
508 if (!PyArg_UnpackTuple(args, "starmap", 2, 2, &func, &seq))
509 return NULL;
510
511 /* Get iterator. */
512 it = PyObject_GetIter(seq);
513 if (it == NULL)
514 return NULL;
515
516 /* create starmapobject structure */
517 lz = (starmapobject *)type->tp_alloc(type, 0);
518 if (lz == NULL) {
519 Py_DECREF(it);
520 return NULL;
521 }
522 Py_INCREF(func);
523 lz->func = func;
524 lz->it = it;
525
526 return (PyObject *)lz;
527}
528
529static void
530starmap_dealloc(starmapobject *lz)
531{
532 PyObject_GC_UnTrack(lz);
533 Py_XDECREF(lz->func);
534 Py_XDECREF(lz->it);
535 lz->ob_type->tp_free(lz);
536}
537
538static int
539starmap_traverse(starmapobject *lz, visitproc visit, void *arg)
540{
541 int err;
542
543 if (lz->it) {
544 err = visit(lz->it, arg);
545 if (err)
546 return err;
547 }
548 if (lz->func) {
549 err = visit(lz->func, arg);
550 if (err)
551 return err;
552 }
553 return 0;
554}
555
556static PyObject *
557starmap_next(starmapobject *lz)
558{
559 PyObject *args;
560 PyObject *result;
561
562 args = PyIter_Next(lz->it);
563 if (args == NULL)
564 return NULL;
Raymond Hettinger2012f172003-02-07 05:32:58 +0000565 if (!PyTuple_CheckExact(args)) {
566 Py_DECREF(args);
567 PyErr_SetString(PyExc_TypeError,
568 "iterator must return a tuple");
569 return NULL;
570 }
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000571 result = PyObject_Call(lz->func, args, NULL);
572 Py_DECREF(args);
573 return result;
574}
575
576static PyObject *
577starmap_getiter(PyObject *lz)
578{
579 Py_INCREF(lz);
580 return lz;
581}
582
583PyDoc_STRVAR(starmap_doc,
584"starmap(function, sequence) --> starmap object\n\
585\n\
586Return an iterator whose values are returned from the function evaluated\n\
587with a argument tuple taken from the given sequence.");
588
589PyTypeObject starmap_type = {
590 PyObject_HEAD_INIT(NULL)
591 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000592 "itertools.starmap", /* tp_name */
593 sizeof(starmapobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000594 0, /* tp_itemsize */
595 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000596 (destructor)starmap_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000597 0, /* tp_print */
598 0, /* tp_getattr */
599 0, /* tp_setattr */
600 0, /* tp_compare */
601 0, /* tp_repr */
602 0, /* tp_as_number */
603 0, /* tp_as_sequence */
604 0, /* tp_as_mapping */
605 0, /* tp_hash */
606 0, /* tp_call */
607 0, /* tp_str */
608 PyObject_GenericGetAttr, /* tp_getattro */
609 0, /* tp_setattro */
610 0, /* tp_as_buffer */
611 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
612 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000613 starmap_doc, /* tp_doc */
614 (traverseproc)starmap_traverse, /* tp_traverse */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000615 0, /* tp_clear */
616 0, /* tp_richcompare */
617 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000618 (getiterfunc)starmap_getiter, /* tp_iter */
619 (iternextfunc)starmap_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000620 0, /* tp_methods */
621 0, /* tp_members */
622 0, /* tp_getset */
623 0, /* tp_base */
624 0, /* tp_dict */
625 0, /* tp_descr_get */
626 0, /* tp_descr_set */
627 0, /* tp_dictoffset */
628 0, /* tp_init */
629 PyType_GenericAlloc, /* tp_alloc */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000630 starmap_new, /* tp_new */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000631 PyObject_GC_Del, /* tp_free */
632};
633
634
635/* imap object ************************************************************/
636
637typedef struct {
638 PyObject_HEAD
639 PyObject *iters;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000640 PyObject *func;
641} imapobject;
642
643PyTypeObject imap_type;
644
645static PyObject *
646imap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
647{
Raymond Hettingerf0c00242003-02-07 07:26:25 +0000648 PyObject *it, *iters, *func;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000649 imapobject *lz;
650 int numargs, i;
651
652 numargs = PyTuple_Size(args);
653 if (numargs < 2) {
654 PyErr_SetString(PyExc_TypeError,
655 "imap() must have at least two arguments.");
656 return NULL;
657 }
658
659 iters = PyTuple_New(numargs-1);
660 if (iters == NULL)
661 return NULL;
662
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000663 for (i=1 ; i<numargs ; i++) {
664 /* Get iterator. */
665 it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));
666 if (it == NULL) {
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000667 Py_DECREF(iters);
668 return NULL;
669 }
670 PyTuple_SET_ITEM(iters, i-1, it);
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000671 }
672
673 /* create imapobject structure */
674 lz = (imapobject *)type->tp_alloc(type, 0);
675 if (lz == NULL) {
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000676 Py_DECREF(iters);
677 return NULL;
678 }
679 lz->iters = iters;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000680 func = PyTuple_GET_ITEM(args, 0);
681 Py_INCREF(func);
682 lz->func = func;
683
684 return (PyObject *)lz;
685}
686
687static void
688imap_dealloc(imapobject *lz)
689{
690 PyObject_GC_UnTrack(lz);
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000691 Py_XDECREF(lz->iters);
692 Py_XDECREF(lz->func);
693 lz->ob_type->tp_free(lz);
694}
695
696static int
697imap_traverse(imapobject *lz, visitproc visit, void *arg)
698{
699 int err;
700
701 if (lz->iters) {
702 err = visit(lz->iters, arg);
703 if (err)
704 return err;
705 }
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000706 if (lz->func) {
707 err = visit(lz->func, arg);
708 if (err)
709 return err;
710 }
711 return 0;
712}
713
Raymond Hettinger2012f172003-02-07 05:32:58 +0000714/*
715imap() is an iterator version of __builtins__.map() except that it does
716not have the None fill-in feature. That was intentionally left out for
717the following reasons:
718
719 1) Itertools are designed to be easily combined and chained together.
720 Having all tools stop with the shortest input is a unifying principle
721 that makes it easier to combine finite iterators (supplying data) with
722 infinite iterators like count() and repeat() (for supplying sequential
723 or constant arguments to a function).
724
725 2) In typical use cases for combining itertools, having one finite data
726 supplier run out before another is likely to be an error condition which
727 should not pass silently by automatically supplying None.
728
729 3) The use cases for automatic None fill-in are rare -- not many functions
730 do something useful when a parameter suddenly switches type and becomes
731 None.
732
733 4) If a need does arise, it can be met by __builtins__.map() or by
734 writing a generator.
735
736 5) Similar toolsets in Haskell and SML do not have automatic None fill-in.
737*/
738
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000739static PyObject *
740imap_next(imapobject *lz)
741{
742 PyObject *val;
Raymond Hettingerf0c00242003-02-07 07:26:25 +0000743 PyObject *argtuple;
744 PyObject *result;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000745 int numargs, i;
746
747 numargs = PyTuple_Size(lz->iters);
Raymond Hettingerf0c00242003-02-07 07:26:25 +0000748 argtuple = PyTuple_New(numargs);
749 if (argtuple == NULL)
750 return NULL;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000751
Raymond Hettingerf0c00242003-02-07 07:26:25 +0000752 for (i=0 ; i<numargs ; i++) {
753 val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));
754 if (val == NULL) {
755 Py_DECREF(argtuple);
756 return NULL;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000757 }
Raymond Hettingerf0c00242003-02-07 07:26:25 +0000758 PyTuple_SET_ITEM(argtuple, i, val);
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000759 }
Raymond Hettingerf0c00242003-02-07 07:26:25 +0000760 if (lz->func == Py_None)
761 return argtuple;
762 result = PyObject_Call(lz->func, argtuple, NULL);
763 Py_DECREF(argtuple);
764 return result;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000765}
766
767static PyObject *
768imap_getiter(PyObject *lz)
769{
770 Py_INCREF(lz);
771 return lz;
772}
773
774PyDoc_STRVAR(imap_doc,
775"imap(func, *iterables) --> imap object\n\
776\n\
777Make an iterator that computes the function using arguments from\n\
778each of the iterables. Like map() except that it returns\n\
779an iterator instead of a list and that it stops when the shortest\n\
780iterable is exhausted instead of filling in None for shorter\n\
781iterables.");
782
783PyTypeObject imap_type = {
784 PyObject_HEAD_INIT(NULL)
785 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000786 "itertools.imap", /* tp_name */
787 sizeof(imapobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000788 0, /* tp_itemsize */
789 /* methods */
790 (destructor)imap_dealloc, /* tp_dealloc */
791 0, /* tp_print */
792 0, /* tp_getattr */
793 0, /* tp_setattr */
794 0, /* tp_compare */
795 0, /* tp_repr */
796 0, /* tp_as_number */
797 0, /* tp_as_sequence */
798 0, /* tp_as_mapping */
799 0, /* tp_hash */
800 0, /* tp_call */
801 0, /* tp_str */
802 PyObject_GenericGetAttr, /* tp_getattro */
803 0, /* tp_setattro */
804 0, /* tp_as_buffer */
805 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
806 Py_TPFLAGS_BASETYPE, /* tp_flags */
807 imap_doc, /* tp_doc */
808 (traverseproc)imap_traverse, /* tp_traverse */
809 0, /* tp_clear */
810 0, /* tp_richcompare */
811 0, /* tp_weaklistoffset */
812 (getiterfunc)imap_getiter, /* tp_iter */
813 (iternextfunc)imap_next, /* tp_iternext */
814 0, /* tp_methods */
815 0, /* tp_members */
816 0, /* tp_getset */
817 0, /* tp_base */
818 0, /* tp_dict */
819 0, /* tp_descr_get */
820 0, /* tp_descr_set */
821 0, /* tp_dictoffset */
822 0, /* tp_init */
823 PyType_GenericAlloc, /* tp_alloc */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000824 imap_new, /* tp_new */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000825 PyObject_GC_Del, /* tp_free */
826};
827
828
829/* times object ************************************************************/
830
831typedef struct {
832 PyObject_HEAD
833 PyObject *obj;
834 long cnt;
835} timesobject;
836
837PyTypeObject times_type;
838
839static PyObject *
840times_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
841{
842 timesobject *lz;
843 PyObject *obj = Py_None;
844 long cnt;
845
846 if (!PyArg_ParseTuple(args, "l|O:times", &cnt, &obj))
847 return NULL;
848
849 if (cnt < 0) {
850 PyErr_SetString(PyExc_ValueError,
Raymond Hettinger2012f172003-02-07 05:32:58 +0000851 "count for times() cannot be negative.");
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000852 return NULL;
853 }
854
855 /* create timesobject structure */
856 lz = (timesobject *)type->tp_alloc(type, 0);
857 if (lz == NULL)
858 return NULL;
859 lz->cnt = cnt;
860 Py_INCREF(obj);
861 lz->obj = obj;
862
863 return (PyObject *)lz;
864}
865
866static void
867times_dealloc(timesobject *lz)
868{
869 PyObject_GC_UnTrack(lz);
870 Py_XDECREF(lz->obj);
871 lz->ob_type->tp_free(lz);
872}
873
Raymond Hettinger2012f172003-02-07 05:32:58 +0000874static int
875times_traverse(timesobject *lz, visitproc visit, void *arg)
876{
877 if (lz->obj)
878 return visit(lz->obj, arg);
879 return 0;
880}
881
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000882static PyObject *
883times_next(timesobject *lz)
884{
885 PyObject *obj = lz->obj;
886
887 if (lz->cnt > 0) {
888 lz->cnt--;
889 Py_INCREF(obj);
890 return obj;
891 }
892 return NULL;
893}
894
895static PyObject *
896times_getiter(PyObject *lz)
897{
898 Py_INCREF(lz);
899 return lz;
900}
901
902PyDoc_STRVAR(times_doc,
903"times(n [,obj]) --> times object\n\
904\n\
905Return a times object whose .next() method returns n consecutive\n\
906instances of obj (default is None).");
907
908PyTypeObject times_type = {
909 PyObject_HEAD_INIT(NULL)
910 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000911 "itertools.times", /* tp_name */
912 sizeof(timesobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000913 0, /* tp_itemsize */
914 /* methods */
915 (destructor)times_dealloc, /* tp_dealloc */
916 0, /* tp_print */
917 0, /* tp_getattr */
918 0, /* tp_setattr */
919 0, /* tp_compare */
920 0, /* tp_repr */
921 0, /* tp_as_number */
922 0, /* tp_as_sequence */
923 0, /* tp_as_mapping */
924 0, /* tp_hash */
925 0, /* tp_call */
926 0, /* tp_str */
927 PyObject_GenericGetAttr, /* tp_getattro */
928 0, /* tp_setattro */
929 0, /* tp_as_buffer */
930 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
931 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000932 times_doc, /* tp_doc */
Raymond Hettinger2012f172003-02-07 05:32:58 +0000933 (traverseproc)times_traverse, /* tp_traverse */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000934 0, /* tp_clear */
935 0, /* tp_richcompare */
936 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +0000937 (getiterfunc)times_getiter, /* tp_iter */
938 (iternextfunc)times_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000939 0, /* tp_methods */
940 0, /* tp_members */
941 0, /* tp_getset */
942 0, /* tp_base */
943 0, /* tp_dict */
944 0, /* tp_descr_get */
945 0, /* tp_descr_set */
946 0, /* tp_dictoffset */
947 0, /* tp_init */
948 PyType_GenericAlloc, /* tp_alloc */
949 times_new, /* tp_new */
950 PyObject_GC_Del, /* tp_free */
951};
952
953
954/* ifilter object ************************************************************/
955
956typedef struct {
957 PyObject_HEAD
958 PyObject *func;
959 PyObject *it;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000960} ifilterobject;
961
962PyTypeObject ifilter_type;
963
964static PyObject *
965ifilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
966{
Raymond Hettinger60eca932003-02-09 06:40:58 +0000967 PyObject *func, *seq;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000968 PyObject *it;
969 ifilterobject *lz;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000970
Raymond Hettinger60eca932003-02-09 06:40:58 +0000971 if (!PyArg_UnpackTuple(args, "ifilter", 2, 2, &func, &seq))
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000972 return NULL;
973
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000974 /* Get iterator. */
975 it = PyObject_GetIter(seq);
976 if (it == NULL)
977 return NULL;
978
979 /* create ifilterobject structure */
980 lz = (ifilterobject *)type->tp_alloc(type, 0);
981 if (lz == NULL) {
982 Py_DECREF(it);
983 return NULL;
984 }
985 Py_INCREF(func);
986 lz->func = func;
987 lz->it = it;
Raymond Hettinger96ef8112003-02-01 00:10:11 +0000988
989 return (PyObject *)lz;
990}
991
992static void
993ifilter_dealloc(ifilterobject *lz)
994{
995 PyObject_GC_UnTrack(lz);
996 Py_XDECREF(lz->func);
997 Py_XDECREF(lz->it);
998 lz->ob_type->tp_free(lz);
999}
1000
1001static int
1002ifilter_traverse(ifilterobject *lz, visitproc visit, void *arg)
1003{
1004 int err;
1005
1006 if (lz->it) {
1007 err = visit(lz->it, arg);
1008 if (err)
1009 return err;
1010 }
1011 if (lz->func) {
1012 err = visit(lz->func, arg);
1013 if (err)
1014 return err;
1015 }
1016 return 0;
1017}
1018
1019static PyObject *
1020ifilter_next(ifilterobject *lz)
1021{
1022 PyObject *item;
1023 long ok;
1024
1025 for (;;) {
1026 item = PyIter_Next(lz->it);
1027 if (item == NULL)
1028 return NULL;
1029
1030 if (lz->func == Py_None) {
1031 ok = PyObject_IsTrue(item);
1032 } else {
1033 PyObject *good;
1034 good = PyObject_CallFunctionObjArgs(lz->func,
1035 item, NULL);
1036 if (good == NULL) {
1037 Py_DECREF(item);
1038 return NULL;
1039 }
1040 ok = PyObject_IsTrue(good);
1041 Py_DECREF(good);
1042 }
Raymond Hettinger60eca932003-02-09 06:40:58 +00001043 if (ok)
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001044 return item;
1045 Py_DECREF(item);
1046 }
1047}
1048
1049static PyObject *
1050ifilter_getiter(PyObject *lz)
1051{
1052 Py_INCREF(lz);
1053 return lz;
1054}
1055
1056PyDoc_STRVAR(ifilter_doc,
Raymond Hettinger60eca932003-02-09 06:40:58 +00001057"ifilter(function or None, sequence) --> ifilter object\n\
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001058\n\
Raymond Hettinger60eca932003-02-09 06:40:58 +00001059Return those items of sequence for which function(item) is true.\n\
1060If function is None, return the items that are true.");
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001061
1062PyTypeObject ifilter_type = {
1063 PyObject_HEAD_INIT(NULL)
1064 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001065 "itertools.ifilter", /* tp_name */
1066 sizeof(ifilterobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001067 0, /* tp_itemsize */
1068 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001069 (destructor)ifilter_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001070 0, /* tp_print */
1071 0, /* tp_getattr */
1072 0, /* tp_setattr */
1073 0, /* tp_compare */
1074 0, /* tp_repr */
1075 0, /* tp_as_number */
1076 0, /* tp_as_sequence */
1077 0, /* tp_as_mapping */
1078 0, /* tp_hash */
1079 0, /* tp_call */
1080 0, /* tp_str */
1081 PyObject_GenericGetAttr, /* tp_getattro */
1082 0, /* tp_setattro */
1083 0, /* tp_as_buffer */
1084 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1085 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001086 ifilter_doc, /* tp_doc */
1087 (traverseproc)ifilter_traverse, /* tp_traverse */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001088 0, /* tp_clear */
1089 0, /* tp_richcompare */
1090 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001091 (getiterfunc)ifilter_getiter, /* tp_iter */
1092 (iternextfunc)ifilter_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001093 0, /* tp_methods */
1094 0, /* tp_members */
1095 0, /* tp_getset */
1096 0, /* tp_base */
1097 0, /* tp_dict */
1098 0, /* tp_descr_get */
1099 0, /* tp_descr_set */
1100 0, /* tp_dictoffset */
1101 0, /* tp_init */
1102 PyType_GenericAlloc, /* tp_alloc */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001103 ifilter_new, /* tp_new */
1104 PyObject_GC_Del, /* tp_free */
1105};
1106
1107
1108/* ifilterfalse object ************************************************************/
1109
1110typedef struct {
1111 PyObject_HEAD
1112 PyObject *func;
1113 PyObject *it;
1114} ifilterfalseobject;
1115
1116PyTypeObject ifilterfalse_type;
1117
1118static PyObject *
1119ifilterfalse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1120{
1121 PyObject *func, *seq, *invert=NULL;
1122 PyObject *it;
1123 ifilterfalseobject *lz;
1124
1125 if (!PyArg_UnpackTuple(args, "ifilterfalse", 2, 2, &func, &seq))
1126 return NULL;
1127
1128 /* Get iterator. */
1129 it = PyObject_GetIter(seq);
1130 if (it == NULL)
1131 return NULL;
1132
1133 /* create ifilterfalseobject structure */
1134 lz = (ifilterfalseobject *)type->tp_alloc(type, 0);
1135 if (lz == NULL) {
1136 Py_DECREF(it);
1137 return NULL;
1138 }
1139 Py_INCREF(func);
1140 lz->func = func;
1141 lz->it = it;
1142
1143 return (PyObject *)lz;
1144}
1145
1146static void
1147ifilterfalse_dealloc(ifilterfalseobject *lz)
1148{
1149 PyObject_GC_UnTrack(lz);
1150 Py_XDECREF(lz->func);
1151 Py_XDECREF(lz->it);
1152 lz->ob_type->tp_free(lz);
1153}
1154
1155static int
1156ifilterfalse_traverse(ifilterfalseobject *lz, visitproc visit, void *arg)
1157{
1158 int err;
1159
1160 if (lz->it) {
1161 err = visit(lz->it, arg);
1162 if (err)
1163 return err;
1164 }
1165 if (lz->func) {
1166 err = visit(lz->func, arg);
1167 if (err)
1168 return err;
1169 }
1170 return 0;
1171}
1172
1173static PyObject *
1174ifilterfalse_next(ifilterfalseobject *lz)
1175{
1176 PyObject *item;
1177 long ok;
1178
1179 for (;;) {
1180 item = PyIter_Next(lz->it);
1181 if (item == NULL)
1182 return NULL;
1183
1184 if (lz->func == Py_None) {
1185 ok = PyObject_IsTrue(item);
1186 } else {
1187 PyObject *good;
1188 good = PyObject_CallFunctionObjArgs(lz->func,
1189 item, NULL);
1190 if (good == NULL) {
1191 Py_DECREF(item);
1192 return NULL;
1193 }
1194 ok = PyObject_IsTrue(good);
1195 Py_DECREF(good);
1196 }
1197 if (!ok)
1198 return item;
1199 Py_DECREF(item);
1200 }
1201}
1202
1203static PyObject *
1204ifilterfalse_getiter(PyObject *lz)
1205{
1206 Py_INCREF(lz);
1207 return lz;
1208}
1209
1210PyDoc_STRVAR(ifilterfalse_doc,
1211"ifilterfalse(function or None, sequence) --> ifilterfalse object\n\
1212\n\
1213Return those items of sequence for which function(item) is false.\n\
1214If function is None, return the items that are false.");
1215
1216PyTypeObject ifilterfalse_type = {
1217 PyObject_HEAD_INIT(NULL)
1218 0, /* ob_size */
1219 "itertools.ifilterfalse", /* tp_name */
1220 sizeof(ifilterfalseobject), /* tp_basicsize */
1221 0, /* tp_itemsize */
1222 /* methods */
1223 (destructor)ifilterfalse_dealloc, /* tp_dealloc */
1224 0, /* tp_print */
1225 0, /* tp_getattr */
1226 0, /* tp_setattr */
1227 0, /* tp_compare */
1228 0, /* tp_repr */
1229 0, /* tp_as_number */
1230 0, /* tp_as_sequence */
1231 0, /* tp_as_mapping */
1232 0, /* tp_hash */
1233 0, /* tp_call */
1234 0, /* tp_str */
1235 PyObject_GenericGetAttr, /* tp_getattro */
1236 0, /* tp_setattro */
1237 0, /* tp_as_buffer */
1238 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1239 Py_TPFLAGS_BASETYPE, /* tp_flags */
1240 ifilterfalse_doc, /* tp_doc */
1241 (traverseproc)ifilterfalse_traverse, /* tp_traverse */
1242 0, /* tp_clear */
1243 0, /* tp_richcompare */
1244 0, /* tp_weaklistoffset */
1245 (getiterfunc)ifilterfalse_getiter, /* tp_iter */
1246 (iternextfunc)ifilterfalse_next, /* tp_iternext */
1247 0, /* tp_methods */
1248 0, /* tp_members */
1249 0, /* tp_getset */
1250 0, /* tp_base */
1251 0, /* tp_dict */
1252 0, /* tp_descr_get */
1253 0, /* tp_descr_set */
1254 0, /* tp_dictoffset */
1255 0, /* tp_init */
1256 PyType_GenericAlloc, /* tp_alloc */
1257 ifilterfalse_new, /* tp_new */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001258 PyObject_GC_Del, /* tp_free */
1259};
1260
1261
1262/* count object ************************************************************/
1263
1264typedef struct {
1265 PyObject_HEAD
1266 long cnt;
1267} countobject;
1268
1269PyTypeObject count_type;
1270
1271static PyObject *
1272count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1273{
1274 countobject *lz;
1275 long cnt = 0;
1276
1277 if (!PyArg_ParseTuple(args, "|l:count", &cnt))
1278 return NULL;
1279
1280 /* create countobject structure */
1281 lz = (countobject *)PyObject_New(countobject, &count_type);
1282 if (lz == NULL)
1283 return NULL;
1284 lz->cnt = cnt;
1285
1286 return (PyObject *)lz;
1287}
1288
1289static PyObject *
1290count_next(countobject *lz)
1291{
1292 return PyInt_FromLong(lz->cnt++);
1293}
1294
1295static PyObject *
1296count_getiter(PyObject *lz)
1297{
1298 Py_INCREF(lz);
1299 return lz;
1300}
1301
1302PyDoc_STRVAR(count_doc,
1303"count([firstval]) --> count object\n\
1304\n\
1305Return a count object whose .next() method returns consecutive\n\
1306integers starting from zero or, if specified, from firstval.");
1307
1308PyTypeObject count_type = {
1309 PyObject_HEAD_INIT(NULL)
1310 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001311 "itertools.count", /* tp_name */
1312 sizeof(countobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001313 0, /* tp_itemsize */
1314 /* methods */
1315 (destructor)PyObject_Del, /* tp_dealloc */
1316 0, /* tp_print */
1317 0, /* tp_getattr */
1318 0, /* tp_setattr */
1319 0, /* tp_compare */
1320 0, /* tp_repr */
1321 0, /* tp_as_number */
1322 0, /* tp_as_sequence */
1323 0, /* tp_as_mapping */
1324 0, /* tp_hash */
1325 0, /* tp_call */
1326 0, /* tp_str */
1327 PyObject_GenericGetAttr, /* tp_getattro */
1328 0, /* tp_setattro */
1329 0, /* tp_as_buffer */
1330 Py_TPFLAGS_DEFAULT, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001331 count_doc, /* tp_doc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001332 0, /* tp_traverse */
1333 0, /* tp_clear */
1334 0, /* tp_richcompare */
1335 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001336 (getiterfunc)count_getiter, /* tp_iter */
1337 (iternextfunc)count_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001338 0, /* tp_methods */
1339 0, /* tp_members */
1340 0, /* tp_getset */
1341 0, /* tp_base */
1342 0, /* tp_dict */
1343 0, /* tp_descr_get */
1344 0, /* tp_descr_set */
1345 0, /* tp_dictoffset */
1346 0, /* tp_init */
1347 PyType_GenericAlloc, /* tp_alloc */
1348 count_new, /* tp_new */
1349};
1350
1351
1352/* izip object ************************************************************/
1353
1354#include "Python.h"
1355
1356typedef struct {
1357 PyObject_HEAD
1358 long tuplesize;
1359 PyObject *ittuple; /* tuple of iterators */
Raymond Hettinger2012f172003-02-07 05:32:58 +00001360 PyObject *result;
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001361} izipobject;
1362
1363PyTypeObject izip_type;
1364
1365static PyObject *
1366izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1367{
1368 izipobject *lz;
1369 int i;
1370 PyObject *ittuple; /* tuple of iterators */
Raymond Hettinger2012f172003-02-07 05:32:58 +00001371 PyObject *result;
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001372 int tuplesize = PySequence_Length(args);
1373
1374 if (tuplesize < 1) {
1375 PyErr_SetString(PyExc_TypeError,
1376 "izip() requires at least one sequence");
1377 return NULL;
1378 }
1379
1380 /* args must be a tuple */
1381 assert(PyTuple_Check(args));
1382
1383 /* obtain iterators */
1384 ittuple = PyTuple_New(tuplesize);
1385 if(ittuple == NULL)
1386 return NULL;
1387 for (i=0; i < tuplesize; ++i) {
1388 PyObject *item = PyTuple_GET_ITEM(args, i);
1389 PyObject *it = PyObject_GetIter(item);
1390 if (it == NULL) {
1391 if (PyErr_ExceptionMatches(PyExc_TypeError))
1392 PyErr_Format(PyExc_TypeError,
1393 "izip argument #%d must support iteration",
1394 i+1);
1395 Py_DECREF(ittuple);
1396 return NULL;
1397 }
1398 PyTuple_SET_ITEM(ittuple, i, it);
1399 }
1400
Raymond Hettinger2012f172003-02-07 05:32:58 +00001401 /* create a result holder */
1402 result = PyTuple_New(tuplesize);
1403 if (result == NULL) {
1404 Py_DECREF(ittuple);
1405 return NULL;
1406 }
1407 for (i=0 ; i < tuplesize ; i++) {
1408 Py_INCREF(Py_None);
1409 PyTuple_SET_ITEM(result, i, Py_None);
1410 }
1411
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001412 /* create izipobject structure */
1413 lz = (izipobject *)type->tp_alloc(type, 0);
1414 if (lz == NULL) {
1415 Py_DECREF(ittuple);
Raymond Hettinger2012f172003-02-07 05:32:58 +00001416 Py_DECREF(result);
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001417 return NULL;
1418 }
1419 lz->ittuple = ittuple;
1420 lz->tuplesize = tuplesize;
Raymond Hettinger2012f172003-02-07 05:32:58 +00001421 lz->result = result;
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001422
1423 return (PyObject *)lz;
1424}
1425
1426static void
1427izip_dealloc(izipobject *lz)
1428{
1429 PyObject_GC_UnTrack(lz);
1430 Py_XDECREF(lz->ittuple);
Raymond Hettinger2012f172003-02-07 05:32:58 +00001431 Py_XDECREF(lz->result);
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001432 lz->ob_type->tp_free(lz);
1433}
1434
1435static int
1436izip_traverse(izipobject *lz, visitproc visit, void *arg)
1437{
1438 if (lz->ittuple)
1439 return visit(lz->ittuple, arg);
1440 return 0;
1441}
1442
1443static PyObject *
1444izip_next(izipobject *lz)
1445{
1446 int i;
1447 long tuplesize = lz->tuplesize;
Raymond Hettinger2012f172003-02-07 05:32:58 +00001448 PyObject *result = lz->result;
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001449 PyObject *it;
1450 PyObject *item;
1451
Raymond Hettinger2012f172003-02-07 05:32:58 +00001452 if (result->ob_refcnt == 1) {
1453 for (i=0 ; i < tuplesize ; i++) {
Raymond Hettingerf0c00242003-02-07 07:26:25 +00001454 it = PyTuple_GET_ITEM(lz->ittuple, i);
1455 item = PyIter_Next(it);
1456 if (item == NULL)
1457 return NULL;
Raymond Hettinger2012f172003-02-07 05:32:58 +00001458 Py_DECREF(PyTuple_GET_ITEM(result, i));
Raymond Hettingerf0c00242003-02-07 07:26:25 +00001459 PyTuple_SET_ITEM(result, i, item);
Raymond Hettinger2012f172003-02-07 05:32:58 +00001460 }
1461 Py_INCREF(result);
1462 } else {
Raymond Hettinger2012f172003-02-07 05:32:58 +00001463 result = PyTuple_New(tuplesize);
1464 if (result == NULL)
1465 return NULL;
Raymond Hettingerf0c00242003-02-07 07:26:25 +00001466 for (i=0 ; i < tuplesize ; i++) {
1467 it = PyTuple_GET_ITEM(lz->ittuple, i);
1468 item = PyIter_Next(it);
1469 if (item == NULL) {
1470 Py_DECREF(result);
1471 return NULL;
1472 }
1473 PyTuple_SET_ITEM(result, i, item);
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001474 }
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001475 }
1476 return result;
1477}
1478
1479static PyObject *
1480izip_getiter(PyObject *lz)
1481{
1482 Py_INCREF(lz);
1483 return lz;
1484}
1485
1486PyDoc_STRVAR(izip_doc,
1487"izip(iter1 [,iter2 [...]]) --> izip object\n\
1488\n\
1489Return a izip object whose .next() method returns a tuple where\n\
1490the i-th element comes from the i-th iterable argument. The .next()\n\
1491method continues until the shortest iterable in the argument sequence\n\
1492is exhausted and then it raises StopIteration. Works like the zip()\n\
1493function but consumes less memory by returning an iterator instead of\n\
1494a list.");
1495
1496PyTypeObject izip_type = {
1497 PyObject_HEAD_INIT(NULL)
1498 0, /* ob_size */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001499 "itertools.izip", /* tp_name */
1500 sizeof(izipobject), /* tp_basicsize */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001501 0, /* tp_itemsize */
1502 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001503 (destructor)izip_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001504 0, /* tp_print */
1505 0, /* tp_getattr */
1506 0, /* tp_setattr */
1507 0, /* tp_compare */
1508 0, /* tp_repr */
1509 0, /* tp_as_number */
1510 0, /* tp_as_sequence */
1511 0, /* tp_as_mapping */
1512 0, /* tp_hash */
1513 0, /* tp_call */
1514 0, /* tp_str */
1515 PyObject_GenericGetAttr, /* tp_getattro */
1516 0, /* tp_setattro */
1517 0, /* tp_as_buffer */
1518 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1519 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001520 izip_doc, /* tp_doc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001521 (traverseproc)izip_traverse, /* tp_traverse */
1522 0, /* tp_clear */
1523 0, /* tp_richcompare */
1524 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001525 (getiterfunc)izip_getiter, /* tp_iter */
1526 (iternextfunc)izip_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001527 0, /* tp_methods */
1528 0, /* tp_members */
1529 0, /* tp_getset */
1530 0, /* tp_base */
1531 0, /* tp_dict */
1532 0, /* tp_descr_get */
1533 0, /* tp_descr_set */
1534 0, /* tp_dictoffset */
1535 0, /* tp_init */
1536 PyType_GenericAlloc, /* tp_alloc */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001537 izip_new, /* tp_new */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001538 PyObject_GC_Del, /* tp_free */
1539};
1540
1541
1542/* repeat object ************************************************************/
1543
1544typedef struct {
1545 PyObject_HEAD
1546 PyObject *element;
1547} repeatobject;
1548
1549PyTypeObject repeat_type;
1550
1551static PyObject *
1552repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1553{
1554 repeatobject *ro;
1555 PyObject *element;
1556
1557 if (!PyArg_UnpackTuple(args, "repeat", 1, 1, &element))
1558 return NULL;
1559
1560 ro = (repeatobject *)type->tp_alloc(type, 0);
1561 if (ro == NULL)
1562 return NULL;
1563 Py_INCREF(element);
1564 ro->element = element;
1565 return (PyObject *)ro;
1566}
1567
1568static void
1569repeat_dealloc(repeatobject *ro)
1570{
1571 PyObject_GC_UnTrack(ro);
1572 Py_XDECREF(ro->element);
1573 ro->ob_type->tp_free(ro);
1574}
1575
1576static int
1577repeat_traverse(repeatobject *ro, visitproc visit, void *arg)
1578{
1579 if (ro->element)
1580 return visit(ro->element, arg);
1581 return 0;
1582}
1583
1584static PyObject *
1585repeat_next(repeatobject *ro)
1586{
1587 Py_INCREF(ro->element);
1588 return ro->element;
1589}
1590
1591static PyObject *
1592repeat_getiter(PyObject *ro)
1593{
1594 Py_INCREF(ro);
1595 return ro;
1596}
1597
1598PyDoc_STRVAR(repeat_doc,
1599"repeat(element) -> create an iterator which returns the element endlessly.");
1600
1601PyTypeObject repeat_type = {
1602 PyObject_HEAD_INIT(NULL)
1603 0, /* ob_size */
1604 "itertools.repeat", /* tp_name */
1605 sizeof(repeatobject), /* tp_basicsize */
1606 0, /* tp_itemsize */
1607 /* methods */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001608 (destructor)repeat_dealloc, /* tp_dealloc */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001609 0, /* tp_print */
1610 0, /* tp_getattr */
1611 0, /* tp_setattr */
1612 0, /* tp_compare */
1613 0, /* tp_repr */
1614 0, /* tp_as_number */
1615 0, /* tp_as_sequence */
1616 0, /* tp_as_mapping */
1617 0, /* tp_hash */
1618 0, /* tp_call */
1619 0, /* tp_str */
1620 PyObject_GenericGetAttr, /* tp_getattro */
1621 0, /* tp_setattro */
1622 0, /* tp_as_buffer */
1623 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1624 Py_TPFLAGS_BASETYPE, /* tp_flags */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001625 repeat_doc, /* tp_doc */
1626 (traverseproc)repeat_traverse, /* tp_traverse */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001627 0, /* tp_clear */
1628 0, /* tp_richcompare */
1629 0, /* tp_weaklistoffset */
Raymond Hettinger60eca932003-02-09 06:40:58 +00001630 (getiterfunc)repeat_getiter, /* tp_iter */
1631 (iternextfunc)repeat_next, /* tp_iternext */
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001632 0, /* tp_methods */
1633 0, /* tp_members */
1634 0, /* tp_getset */
1635 0, /* tp_base */
1636 0, /* tp_dict */
1637 0, /* tp_descr_get */
1638 0, /* tp_descr_set */
1639 0, /* tp_dictoffset */
1640 0, /* tp_init */
1641 PyType_GenericAlloc, /* tp_alloc */
1642 repeat_new, /* tp_new */
1643 PyObject_GC_Del, /* tp_free */
1644};
1645
1646
1647/* module level code ********************************************************/
1648
1649PyDoc_STRVAR(module_doc,
1650"Functional tools for creating and using iterators.\n\
1651\n\
1652Infinite iterators:\n\
1653count([n]) --> n, n+1, n+2, ...\n\
1654repeat(elem) --> elem, elem, elem, ...\n\
1655\n\
1656Iterators terminating on the shortest input sequence:\n\
1657izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\
Raymond Hettinger60eca932003-02-09 06:40:58 +00001658ifilter(pred, seq) --> elements of seq where pred(elem) is True\n\
1659ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001660islice(seq, [start,] stop [, step]) --> elements from\n\
1661 seq[start:stop:step]\n\
1662imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
1663starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
1664times(n, [obj]) --> obj, obj, ... for n times. obj defaults to None\n\
1665takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\
1666dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
1667");
1668
1669
1670PyMODINIT_FUNC
1671inititertools(void)
1672{
Raymond Hettinger60eca932003-02-09 06:40:58 +00001673 int i;
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001674 PyObject *m;
Raymond Hettinger60eca932003-02-09 06:40:58 +00001675 char *name;
1676 PyTypeObject *typelist[] = {
1677 &dropwhile_type,
1678 &takewhile_type,
1679 &islice_type,
1680 &starmap_type,
1681 &imap_type,
1682 &times_type,
1683 &ifilter_type,
1684 &ifilterfalse_type,
1685 &count_type,
1686 &izip_type,
1687 &repeat_type,
1688 NULL
1689 };
1690
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001691 m = Py_InitModule3("itertools", NULL, module_doc);
1692
Raymond Hettinger60eca932003-02-09 06:40:58 +00001693 for (i=0 ; typelist[i] != NULL ; i++) {
1694 if (PyType_Ready(typelist[i]) < 0)
1695 return;
1696 name = strchr(typelist[i]->tp_name, '.') + 1;
1697 if (name == NULL)
1698 return;
1699 Py_INCREF(typelist[i]);
1700 PyModule_AddObject(m, name, (PyObject *)typelist[i]);
1701 }
Raymond Hettinger96ef8112003-02-01 00:10:11 +00001702}