blob: 252c5a6e410c33c958791d607beafb54130f3509 [file] [log] [blame]
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001#include "Python.h"
2
3/* collections module implementation of a deque() datatype
4 Written and maintained by Raymond D. Hettinger <python@rcn.com>
5 Copyright (c) 2004 Python Software Foundation.
6 All rights reserved.
7*/
8
9#define BLOCKLEN 46
10
11typedef struct BLOCK {
12 struct BLOCK *leftlink;
13 struct BLOCK *rightlink;
14 PyObject *data[BLOCKLEN];
15} block;
16
17static block *newblock(block *leftlink, block *rightlink) {
18 block *b = PyMem_Malloc(sizeof(block));
19 if (b == NULL) {
20 PyErr_NoMemory();
21 return NULL;
22 }
23 b->leftlink = leftlink;
24 b->rightlink = rightlink;
25 return b;
26}
27
28typedef struct {
29 PyObject_HEAD
30 block *leftblock;
31 block *rightblock;
32 int leftindex;
33 int rightindex;
34 int len;
35} dequeobject;
36
Neal Norwitz87f10132004-02-29 15:40:53 +000037static PyTypeObject deque_type;
Raymond Hettinger738ec902004-02-29 02:15:56 +000038
Raymond Hettinger756b3f32004-01-29 06:37:52 +000039static PyObject *
40deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
41{
42 dequeobject *deque;
43 block *b;
44
45 /* create dequeobject structure */
46 deque = (dequeobject *)type->tp_alloc(type, 0);
47 if (deque == NULL)
48 return NULL;
49
50 b = newblock(NULL, NULL);
51 if (b == NULL) {
52 Py_DECREF(deque);
53 return NULL;
54 }
55
56 deque->leftblock = b;
57 deque->rightblock = b;
58 deque->leftindex = BLOCKLEN / 2 + 1;
59 deque->rightindex = BLOCKLEN / 2;
60 deque->len = 0;
61
62 return (PyObject *)deque;
63}
64
65static PyObject *
66deque_append(dequeobject *deque, PyObject *item)
67{
68 deque->rightindex++;
69 deque->len++;
70 if (deque->rightindex == BLOCKLEN) {
71 block *b = newblock(deque->rightblock, NULL);
72 if (b == NULL)
73 return NULL;
74 assert(deque->rightblock->rightlink == NULL);
75 deque->rightblock->rightlink = b;
76 deque->rightblock = b;
77 deque->rightindex = 0;
78 }
79 Py_INCREF(item);
80 deque->rightblock->data[deque->rightindex] = item;
81 Py_RETURN_NONE;
82}
83
84PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque.");
85
86static PyObject *
87deque_appendleft(dequeobject *deque, PyObject *item)
88{
89 deque->leftindex--;
90 deque->len++;
91 if (deque->leftindex == -1) {
92 block *b = newblock(NULL, deque->leftblock);
93 if (b == NULL)
94 return NULL;
95 assert(deque->leftblock->leftlink == NULL);
96 deque->leftblock->leftlink = b;
97 deque->leftblock = b;
98 deque->leftindex = BLOCKLEN - 1;
99 }
100 Py_INCREF(item);
101 deque->leftblock->data[deque->leftindex] = item;
102 Py_RETURN_NONE;
103}
104
105PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque.");
106
107static PyObject *
108deque_pop(dequeobject *deque, PyObject *unused)
109{
110 PyObject *item;
111 block *prevblock;
112
113 if (deque->len == 0) {
Raymond Hettinger738ec902004-02-29 02:15:56 +0000114 PyErr_SetString(PyExc_IndexError, "pop from an empty deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000115 return NULL;
116 }
117 item = deque->rightblock->data[deque->rightindex];
118 deque->rightindex--;
119 deque->len--;
120
121 if (deque->rightindex == -1) {
122 if (deque->len == 0) {
123 assert(deque->leftblock == deque->rightblock);
124 assert(deque->leftindex == deque->rightindex+1);
125 /* re-center instead of freeing a block */
126 deque->leftindex = BLOCKLEN / 2 + 1;
127 deque->rightindex = BLOCKLEN / 2;
128 } else {
129 prevblock = deque->rightblock->leftlink;
130 assert(deque->leftblock != deque->rightblock);
131 PyMem_Free(deque->rightblock);
132 prevblock->rightlink = NULL;
133 deque->rightblock = prevblock;
134 deque->rightindex = BLOCKLEN - 1;
135 }
136 }
137 return item;
138}
139
140PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element.");
141
142static PyObject *
143deque_popleft(dequeobject *deque, PyObject *unused)
144{
145 PyObject *item;
146 block *prevblock;
147
148 if (deque->len == 0) {
Raymond Hettinger738ec902004-02-29 02:15:56 +0000149 PyErr_SetString(PyExc_IndexError, "pop from an empty deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000150 return NULL;
151 }
152 item = deque->leftblock->data[deque->leftindex];
153 deque->leftindex++;
154 deque->len--;
155
156 if (deque->leftindex == BLOCKLEN) {
157 if (deque->len == 0) {
158 assert(deque->leftblock == deque->rightblock);
159 assert(deque->leftindex == deque->rightindex+1);
160 /* re-center instead of freeing a block */
161 deque->leftindex = BLOCKLEN / 2 + 1;
162 deque->rightindex = BLOCKLEN / 2;
163 } else {
164 assert(deque->leftblock != deque->rightblock);
165 prevblock = deque->leftblock->rightlink;
166 assert(deque->leftblock != NULL);
167 PyMem_Free(deque->leftblock);
168 assert(prevblock != NULL);
169 prevblock->leftlink = NULL;
170 deque->leftblock = prevblock;
171 deque->leftindex = 0;
172 }
173 }
174 return item;
175}
176
177PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element.");
178
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000179static PyObject *
Raymond Hettinger738ec902004-02-29 02:15:56 +0000180deque_right(dequeobject *deque, PyObject *unused)
181{
182 PyObject *item;
183
184 if (deque->len == 0) {
185 PyErr_SetString(PyExc_IndexError, "deque is empty");
186 return NULL;
187 }
188 item = deque->rightblock->data[deque->rightindex];
189 Py_INCREF(item);
190 return item;
191}
192
193PyDoc_STRVAR(right_doc, "Return the rightmost element.");
194
195static PyObject *
196deque_left(dequeobject *deque, PyObject *unused)
197{
198 PyObject *item;
199
200 if (deque->len == 0) {
201 PyErr_SetString(PyExc_IndexError, "deque is empty");
202 return NULL;
203 }
204 item = deque->leftblock->data[deque->leftindex];
205 Py_INCREF(item);
206 return item;
207}
208
209PyDoc_STRVAR(left_doc, "Return the leftmost element.");
210
211static PyObject *
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000212deque_extend(dequeobject *deque, PyObject *iterable)
213{
214 PyObject *it, *item;
215
216 it = PyObject_GetIter(iterable);
217 if (it == NULL)
218 return NULL;
219
220 while ((item = PyIter_Next(it)) != NULL) {
221 deque->rightindex++;
222 deque->len++;
223 if (deque->rightindex == BLOCKLEN) {
224 block *b = newblock(deque->rightblock, NULL);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000225 if (b == NULL) {
226 Py_DECREF(item);
227 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000228 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000229 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000230 assert(deque->rightblock->rightlink == NULL);
231 deque->rightblock->rightlink = b;
232 deque->rightblock = b;
233 deque->rightindex = 0;
234 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000235 deque->rightblock->data[deque->rightindex] = item;
236 }
237 Py_DECREF(it);
238 if (PyErr_Occurred())
239 return NULL;
240 Py_RETURN_NONE;
241}
242
243PyDoc_STRVAR(extend_doc,
244"Extend the right side of the deque with elements from the iterable");
245
246static PyObject *
247deque_extendleft(dequeobject *deque, PyObject *iterable)
248{
249 PyObject *it, *item;
250
251 it = PyObject_GetIter(iterable);
252 if (it == NULL)
253 return NULL;
254
255 while ((item = PyIter_Next(it)) != NULL) {
256 deque->leftindex--;
257 deque->len++;
258 if (deque->leftindex == -1) {
259 block *b = newblock(NULL, deque->leftblock);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000260 if (b == NULL) {
261 Py_DECREF(item);
262 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000263 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000264 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000265 assert(deque->leftblock->leftlink == NULL);
266 deque->leftblock->leftlink = b;
267 deque->leftblock = b;
268 deque->leftindex = BLOCKLEN - 1;
269 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000270 deque->leftblock->data[deque->leftindex] = item;
271 }
272 Py_DECREF(it);
273 if (PyErr_Occurred())
274 return NULL;
275 Py_RETURN_NONE;
276}
277
278PyDoc_STRVAR(extendleft_doc,
279"Extend the left side of the deque with elements from the iterable");
280
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000281static PyObject *
282deque_rotate(dequeobject *deque, PyObject *args)
283{
Raymond Hettingeree33b272004-02-08 04:05:26 +0000284 int i, n=1, len=deque->len, halflen=(len+1)>>1;
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000285 PyObject *item, *rv;
286
Raymond Hettingeree33b272004-02-08 04:05:26 +0000287 if (!PyArg_ParseTuple(args, "|i:rotate", &n))
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000288 return NULL;
289
Raymond Hettingeree33b272004-02-08 04:05:26 +0000290 if (len == 0)
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000291 Py_RETURN_NONE;
Raymond Hettingeree33b272004-02-08 04:05:26 +0000292 if (n > halflen || n < -halflen) {
293 n %= len;
294 if (n > halflen)
295 n -= len;
296 else if (n < -halflen)
297 n += len;
298 }
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000299
300 for (i=0 ; i<n ; i++) {
301 item = deque_pop(deque, NULL);
302 if (item == NULL)
303 return NULL;
304 rv = deque_appendleft(deque, item);
305 Py_DECREF(item);
306 if (rv == NULL)
307 return NULL;
308 Py_DECREF(rv);
309 }
310 for (i=0 ; i>n ; i--) {
311 item = deque_popleft(deque, NULL);
312 if (item == NULL)
313 return NULL;
314 rv = deque_append(deque, item);
315 Py_DECREF(item);
316 if (rv == NULL)
317 return NULL;
318 Py_DECREF(rv);
319 }
320 Py_RETURN_NONE;
321}
322
323PyDoc_STRVAR(rotate_doc,
Raymond Hettingeree33b272004-02-08 04:05:26 +0000324"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left.");
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000325
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000326static int
327deque_len(dequeobject *deque)
328{
329 return deque->len;
330}
331
332static int
333deque_clear(dequeobject *deque)
334{
335 PyObject *item;
336
337 while (deque_len(deque)) {
338 item = deque_pop(deque, NULL);
339 if (item == NULL)
340 return -1;
341 Py_DECREF(item);
342 }
343 assert(deque->leftblock == deque->rightblock &&
344 deque->leftindex > deque->rightindex);
345 return 0;
346}
347
348static PyObject *
349deque_clearmethod(dequeobject *deque)
350{
351 if (deque_clear(deque) == -1)
352 return NULL;
353 Py_RETURN_NONE;
354}
355
356PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
357
358static void
359deque_dealloc(dequeobject *deque)
360{
361 PyObject_GC_UnTrack(deque);
362 if (deque->leftblock != NULL) {
363 int err = deque_clear(deque);
364 assert(err == 0);
365 assert(deque->leftblock != NULL);
366 PyMem_Free(deque->leftblock);
367 }
368 deque->leftblock = NULL;
369 deque->rightblock = NULL;
370 deque->ob_type->tp_free(deque);
371}
372
373static int
374set_traverse(dequeobject *deque, visitproc visit, void *arg)
375{
376 block * b = deque->leftblock;
377 int index = deque->leftindex;
378 int err;
379 PyObject *item;
380
381 while (b != deque->rightblock || index <= deque->rightindex) {
382 item = b->data[index];
383 index++;
384 if (index == BLOCKLEN && b->rightlink != NULL) {
385 b = b->rightlink;
386 index = 0;
387 }
388 err = visit(item, arg);
389 if (err)
390 return err;
391 }
392 return 0;
393}
394
395static long
396deque_nohash(PyObject *self)
397{
398 PyErr_SetString(PyExc_TypeError, "deque objects are unhashable");
399 return -1;
400}
401
402static PyObject *
403deque_copy(PyObject *deque)
404{
405 return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type),
406 deque, NULL);
407}
408
409PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
410
411static PyObject *
412deque_reduce(dequeobject *deque)
413{
414 PyObject *seq, *args, *result;
415
416 seq = PySequence_Tuple((PyObject *)deque);
417 if (seq == NULL)
418 return NULL;
419 args = PyTuple_Pack(1, seq);
420 if (args == NULL) {
421 Py_DECREF(seq);
422 return NULL;
423 }
424 result = PyTuple_Pack(2, deque->ob_type, args);
425 Py_DECREF(seq);
426 Py_DECREF(args);
427 return result;
428}
429
430PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
431
432static PyObject *
433deque_repr(PyObject *deque)
434{
435 PyObject *aslist, *result, *fmt;
436 int i;
437
438 i = Py_ReprEnter(deque);
439 if (i != 0) {
440 if (i < 0)
441 return NULL;
442 return PyString_FromString("[...]");
443 }
444
445 aslist = PySequence_List(deque);
446 if (aslist == NULL) {
447 Py_ReprLeave(deque);
448 return NULL;
449 }
450
451 fmt = PyString_FromString("deque(%r)");
452 if (fmt == NULL) {
453 Py_DECREF(aslist);
454 Py_ReprLeave(deque);
455 return NULL;
456 }
457 result = PyString_Format(fmt, aslist);
458 Py_DECREF(fmt);
459 Py_DECREF(aslist);
460 Py_ReprLeave(deque);
461 return result;
462}
463
464static int
465deque_tp_print(PyObject *deque, FILE *fp, int flags)
466{
467 PyObject *it, *item;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000468 char *emit = ""; /* No separator emitted on first pass */
469 char *separator = ", ";
470 int i;
471
472 i = Py_ReprEnter(deque);
473 if (i != 0) {
474 if (i < 0)
475 return i;
476 fputs("[...]", fp);
477 return 0;
478 }
479
480 it = PyObject_GetIter(deque);
481 if (it == NULL)
482 return -1;
483
484 fputs("deque([", fp);
485 while ((item = PyIter_Next(it)) != NULL) {
486 fputs(emit, fp);
487 emit = separator;
488 if (PyObject_Print(item, fp, 0) != 0) {
489 Py_DECREF(item);
490 Py_DECREF(it);
491 Py_ReprLeave(deque);
492 return -1;
493 }
494 Py_DECREF(item);
495 }
496 Py_ReprLeave(deque);
497 Py_DECREF(it);
498 if (PyErr_Occurred())
499 return -1;
500 fputs("])", fp);
501 return 0;
502}
503
Raymond Hettinger738ec902004-02-29 02:15:56 +0000504static PyObject *
505deque_richcompare(PyObject *v, PyObject *w, int op)
506{
507 PyObject *it1=NULL, *it2=NULL, *x, *y;
508 int i, b, vs, ws, minlen, cmp=-1;
509
510 if (v->ob_type != &deque_type || w->ob_type != &deque_type) {
511 Py_INCREF(Py_NotImplemented);
512 return Py_NotImplemented;
513 }
514
515 /* Shortcuts */
516 vs = ((dequeobject *)v)->len;
517 ws = ((dequeobject *)w)->len;
518 if (op == Py_EQ) {
519 if (v == w)
520 Py_RETURN_TRUE;
521 if (vs != ws)
522 Py_RETURN_FALSE;
523 }
524 if (op == Py_NE) {
525 if (v == w)
526 Py_RETURN_FALSE;
527 if (vs != ws)
528 Py_RETURN_TRUE;
529 }
530
531 /* Search for the first index where items are different */
532 it1 = PyObject_GetIter(v);
533 if (it1 == NULL)
534 goto done;
535 it2 = PyObject_GetIter(w);
536 if (it2 == NULL)
537 goto done;
538 minlen = (vs < ws) ? vs : ws;
539 for (i=0 ; i < minlen ; i++) {
540 x = PyIter_Next(it1);
541 if (x == NULL)
542 goto done;
543 y = PyIter_Next(it2);
544 if (y == NULL) {
545 Py_DECREF(x);
546 goto done;
547 }
548 b = PyObject_RichCompareBool(x, y, Py_EQ);
549 if (b == 0) {
550 cmp = PyObject_RichCompareBool(x, y, op);
551 Py_DECREF(x);
552 Py_DECREF(y);
553 goto done;
554 }
555 Py_DECREF(x);
556 Py_DECREF(y);
557 if (b == -1)
558 goto done;
559 }
560 /* Elements are equal through minlen. The longest input is the greatest */
561 switch (op) {
562 case Py_LT: cmp = vs < ws; break;
563 case Py_LE: cmp = vs <= ws; break;
564 case Py_EQ: cmp = vs == ws; break;
565 case Py_NE: cmp = vs != ws; break;
566 case Py_GT: cmp = vs > ws; break;
567 case Py_GE: cmp = vs >= ws; break;
568 }
569
570done:
571 Py_XDECREF(it1);
572 Py_XDECREF(it2);
573 if (cmp == 1)
574 Py_RETURN_TRUE;
575 if (cmp == 0)
576 Py_RETURN_FALSE;
577 return NULL;
578}
579
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000580static int
581deque_init(dequeobject *deque, PyObject *args, PyObject *kwds)
582{
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000583 PyObject *iterable = NULL;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000584
585 if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable))
586 return -1;
587
588 if (iterable != NULL) {
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000589 PyObject *rv = deque_extend(deque, iterable);
590 if (rv == NULL)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000591 return -1;
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000592 Py_DECREF(rv);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000593 }
594 return 0;
595}
596
597static PySequenceMethods deque_as_sequence = {
598 (inquiry)deque_len, /* sq_length */
599 0, /* sq_concat */
600};
601
602/* deque object ********************************************************/
603
604static PyObject *deque_iter(dequeobject *deque);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000605static PyObject *deque_reviter(dequeobject *deque);
606PyDoc_STRVAR(reversed_doc,
607 "D.__reversed__() -- return a reverse iterator over the deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000608
609static PyMethodDef deque_methods[] = {
610 {"append", (PyCFunction)deque_append,
611 METH_O, append_doc},
612 {"appendleft", (PyCFunction)deque_appendleft,
613 METH_O, appendleft_doc},
614 {"clear", (PyCFunction)deque_clearmethod,
615 METH_NOARGS, clear_doc},
616 {"__copy__", (PyCFunction)deque_copy,
617 METH_NOARGS, copy_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000618 {"extend", (PyCFunction)deque_extend,
619 METH_O, extend_doc},
620 {"extendleft", (PyCFunction)deque_extendleft,
621 METH_O, extendleft_doc},
Raymond Hettinger738ec902004-02-29 02:15:56 +0000622 {"left", (PyCFunction)deque_left,
623 METH_NOARGS, left_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000624 {"pop", (PyCFunction)deque_pop,
625 METH_NOARGS, pop_doc},
626 {"popleft", (PyCFunction)deque_popleft,
627 METH_NOARGS, popleft_doc},
628 {"__reduce__", (PyCFunction)deque_reduce,
629 METH_NOARGS, reduce_doc},
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000630 {"__reversed__", (PyCFunction)deque_reviter,
631 METH_NOARGS, reversed_doc},
Raymond Hettinger738ec902004-02-29 02:15:56 +0000632 {"right", (PyCFunction)deque_right,
633 METH_NOARGS, right_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000634 {"rotate", (PyCFunction)deque_rotate,
635 METH_VARARGS, rotate_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000636 {NULL, NULL} /* sentinel */
637};
638
639PyDoc_STRVAR(deque_doc,
640"deque(iterable) --> deque object\n\
641\n\
642Build an ordered collection accessible from endpoints only.");
643
Neal Norwitz87f10132004-02-29 15:40:53 +0000644static PyTypeObject deque_type = {
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000645 PyObject_HEAD_INIT(NULL)
646 0, /* ob_size */
647 "collections.deque", /* tp_name */
648 sizeof(dequeobject), /* tp_basicsize */
649 0, /* tp_itemsize */
650 /* methods */
651 (destructor)deque_dealloc, /* tp_dealloc */
652 (printfunc)deque_tp_print, /* tp_print */
653 0, /* tp_getattr */
654 0, /* tp_setattr */
655 0, /* tp_compare */
656 (reprfunc)deque_repr, /* tp_repr */
657 0, /* tp_as_number */
658 &deque_as_sequence, /* tp_as_sequence */
659 0, /* tp_as_mapping */
660 deque_nohash, /* tp_hash */
661 0, /* tp_call */
662 0, /* tp_str */
663 PyObject_GenericGetAttr, /* tp_getattro */
664 0, /* tp_setattro */
665 0, /* tp_as_buffer */
666 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
667 deque_doc, /* tp_doc */
668 (traverseproc)set_traverse, /* tp_traverse */
669 (inquiry)deque_clear, /* tp_clear */
Raymond Hettinger738ec902004-02-29 02:15:56 +0000670 (richcmpfunc)deque_richcompare, /* tp_richcompare */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000671 0, /* tp_weaklistoffset*/
672 (getiterfunc)deque_iter, /* tp_iter */
673 0, /* tp_iternext */
674 deque_methods, /* tp_methods */
675 0, /* tp_members */
676 0, /* tp_getset */
677 0, /* tp_base */
678 0, /* tp_dict */
679 0, /* tp_descr_get */
680 0, /* tp_descr_set */
681 0, /* tp_dictoffset */
682 (initproc)deque_init, /* tp_init */
683 PyType_GenericAlloc, /* tp_alloc */
684 deque_new, /* tp_new */
685 PyObject_GC_Del, /* tp_free */
686};
687
688/*********************** Deque Iterator **************************/
689
690typedef struct {
691 PyObject_HEAD
692 int index;
693 block *b;
694 dequeobject *deque;
695 int len;
696} dequeiterobject;
697
698PyTypeObject dequeiter_type;
699
700static PyObject *
701deque_iter(dequeobject *deque)
702{
703 dequeiterobject *it;
704
705 it = PyObject_New(dequeiterobject, &dequeiter_type);
706 if (it == NULL)
707 return NULL;
708 it->b = deque->leftblock;
709 it->index = deque->leftindex;
710 Py_INCREF(deque);
711 it->deque = deque;
712 it->len = deque->len;
713 return (PyObject *)it;
714}
715
716static void
717dequeiter_dealloc(dequeiterobject *dio)
718{
719 Py_XDECREF(dio->deque);
720 dio->ob_type->tp_free(dio);
721}
722
723static PyObject *
724dequeiter_next(dequeiterobject *it)
725{
726 PyObject *item;
727 if (it->b == it->deque->rightblock && it->index > it->deque->rightindex)
728 return NULL;
729
730 if (it->len != it->deque->len) {
731 it->len = -1; /* Make this state sticky */
732 PyErr_SetString(PyExc_RuntimeError,
733 "deque changed size during iteration");
734 return NULL;
735 }
736
737 item = it->b->data[it->index];
738 it->index++;
739 if (it->index == BLOCKLEN && it->b->rightlink != NULL) {
740 it->b = it->b->rightlink;
741 it->index = 0;
742 }
743 Py_INCREF(item);
744 return item;
745}
746
747PyTypeObject dequeiter_type = {
748 PyObject_HEAD_INIT(NULL)
749 0, /* ob_size */
750 "deque_iterator", /* tp_name */
751 sizeof(dequeiterobject), /* tp_basicsize */
752 0, /* tp_itemsize */
753 /* methods */
754 (destructor)dequeiter_dealloc, /* tp_dealloc */
755 0, /* tp_print */
756 0, /* tp_getattr */
757 0, /* tp_setattr */
758 0, /* tp_compare */
759 0, /* tp_repr */
760 0, /* tp_as_number */
761 0, /* tp_as_sequence */
762 0, /* tp_as_mapping */
763 0, /* tp_hash */
764 0, /* tp_call */
765 0, /* tp_str */
766 PyObject_GenericGetAttr, /* tp_getattro */
767 0, /* tp_setattro */
768 0, /* tp_as_buffer */
769 Py_TPFLAGS_DEFAULT, /* tp_flags */
770 0, /* tp_doc */
771 0, /* tp_traverse */
772 0, /* tp_clear */
773 0, /* tp_richcompare */
774 0, /* tp_weaklistoffset */
775 PyObject_SelfIter, /* tp_iter */
776 (iternextfunc)dequeiter_next, /* tp_iternext */
777 0,
778};
779
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000780/*********************** Deque Reverse Iterator **************************/
781
782PyTypeObject dequereviter_type;
783
784static PyObject *
785deque_reviter(dequeobject *deque)
786{
787 dequeiterobject *it;
788
789 it = PyObject_New(dequeiterobject, &dequereviter_type);
790 if (it == NULL)
791 return NULL;
792 it->b = deque->rightblock;
793 it->index = deque->rightindex;
794 Py_INCREF(deque);
795 it->deque = deque;
796 it->len = deque->len;
797 return (PyObject *)it;
798}
799
800static PyObject *
801dequereviter_next(dequeiterobject *it)
802{
803 PyObject *item;
804 if (it->b == it->deque->leftblock && it->index < it->deque->leftindex)
805 return NULL;
806
807 if (it->len != it->deque->len) {
808 it->len = -1; /* Make this state sticky */
809 PyErr_SetString(PyExc_RuntimeError,
810 "deque changed size during iteration");
811 return NULL;
812 }
813
814 item = it->b->data[it->index];
815 it->index--;
816 if (it->index == -1 && it->b->leftlink != NULL) {
817 it->b = it->b->leftlink;
818 it->index = BLOCKLEN - 1;
819 }
820 Py_INCREF(item);
821 return item;
822}
823
824PyTypeObject dequereviter_type = {
825 PyObject_HEAD_INIT(NULL)
826 0, /* ob_size */
827 "deque_reverse_iterator", /* tp_name */
828 sizeof(dequeiterobject), /* tp_basicsize */
829 0, /* tp_itemsize */
830 /* methods */
831 (destructor)dequeiter_dealloc, /* tp_dealloc */
832 0, /* tp_print */
833 0, /* tp_getattr */
834 0, /* tp_setattr */
835 0, /* tp_compare */
836 0, /* tp_repr */
837 0, /* tp_as_number */
838 0, /* tp_as_sequence */
839 0, /* tp_as_mapping */
840 0, /* tp_hash */
841 0, /* tp_call */
842 0, /* tp_str */
843 PyObject_GenericGetAttr, /* tp_getattro */
844 0, /* tp_setattro */
845 0, /* tp_as_buffer */
846 Py_TPFLAGS_DEFAULT, /* tp_flags */
847 0, /* tp_doc */
848 0, /* tp_traverse */
849 0, /* tp_clear */
850 0, /* tp_richcompare */
851 0, /* tp_weaklistoffset */
852 PyObject_SelfIter, /* tp_iter */
853 (iternextfunc)dequereviter_next, /* tp_iternext */
854 0,
855};
856
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000857/* module level code ********************************************************/
858
859PyDoc_STRVAR(module_doc,
860"High performance data structures\n\
861");
862
863PyMODINIT_FUNC
864initcollections(void)
865{
866 PyObject *m;
867
868 m = Py_InitModule3("collections", NULL, module_doc);
869
870 if (PyType_Ready(&deque_type) < 0)
871 return;
872 Py_INCREF(&deque_type);
873 PyModule_AddObject(m, "deque", (PyObject *)&deque_type);
874
875 if (PyType_Ready(&dequeiter_type) < 0)
876 return;
877
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000878 if (PyType_Ready(&dequereviter_type) < 0)
879 return;
880
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000881 return;
882}