blob: e49224d83d416d84ed3cbc617970aec88a6c18da [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 *
180deque_extend(dequeobject *deque, PyObject *iterable)
181{
182 PyObject *it, *item;
183
184 it = PyObject_GetIter(iterable);
185 if (it == NULL)
186 return NULL;
187
188 while ((item = PyIter_Next(it)) != NULL) {
189 deque->rightindex++;
190 deque->len++;
191 if (deque->rightindex == BLOCKLEN) {
192 block *b = newblock(deque->rightblock, NULL);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000193 if (b == NULL) {
194 Py_DECREF(item);
195 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000196 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000197 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000198 assert(deque->rightblock->rightlink == NULL);
199 deque->rightblock->rightlink = b;
200 deque->rightblock = b;
201 deque->rightindex = 0;
202 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000203 deque->rightblock->data[deque->rightindex] = item;
204 }
205 Py_DECREF(it);
206 if (PyErr_Occurred())
207 return NULL;
208 Py_RETURN_NONE;
209}
210
211PyDoc_STRVAR(extend_doc,
212"Extend the right side of the deque with elements from the iterable");
213
214static PyObject *
215deque_extendleft(dequeobject *deque, PyObject *iterable)
216{
217 PyObject *it, *item;
218
219 it = PyObject_GetIter(iterable);
220 if (it == NULL)
221 return NULL;
222
223 while ((item = PyIter_Next(it)) != NULL) {
224 deque->leftindex--;
225 deque->len++;
226 if (deque->leftindex == -1) {
227 block *b = newblock(NULL, deque->leftblock);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000228 if (b == NULL) {
229 Py_DECREF(item);
230 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000231 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000232 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000233 assert(deque->leftblock->leftlink == NULL);
234 deque->leftblock->leftlink = b;
235 deque->leftblock = b;
236 deque->leftindex = BLOCKLEN - 1;
237 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000238 deque->leftblock->data[deque->leftindex] = item;
239 }
240 Py_DECREF(it);
241 if (PyErr_Occurred())
242 return NULL;
243 Py_RETURN_NONE;
244}
245
246PyDoc_STRVAR(extendleft_doc,
247"Extend the left side of the deque with elements from the iterable");
248
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000249static PyObject *
250deque_rotate(dequeobject *deque, PyObject *args)
251{
Raymond Hettingeree33b272004-02-08 04:05:26 +0000252 int i, n=1, len=deque->len, halflen=(len+1)>>1;
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000253 PyObject *item, *rv;
254
Raymond Hettingeree33b272004-02-08 04:05:26 +0000255 if (!PyArg_ParseTuple(args, "|i:rotate", &n))
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000256 return NULL;
257
Raymond Hettingeree33b272004-02-08 04:05:26 +0000258 if (len == 0)
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000259 Py_RETURN_NONE;
Raymond Hettingeree33b272004-02-08 04:05:26 +0000260 if (n > halflen || n < -halflen) {
261 n %= len;
262 if (n > halflen)
263 n -= len;
264 else if (n < -halflen)
265 n += len;
266 }
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000267
268 for (i=0 ; i<n ; i++) {
269 item = deque_pop(deque, NULL);
270 if (item == NULL)
271 return NULL;
272 rv = deque_appendleft(deque, item);
273 Py_DECREF(item);
274 if (rv == NULL)
275 return NULL;
276 Py_DECREF(rv);
277 }
278 for (i=0 ; i>n ; i--) {
279 item = deque_popleft(deque, NULL);
280 if (item == NULL)
281 return NULL;
282 rv = deque_append(deque, item);
283 Py_DECREF(item);
284 if (rv == NULL)
285 return NULL;
286 Py_DECREF(rv);
287 }
288 Py_RETURN_NONE;
289}
290
291PyDoc_STRVAR(rotate_doc,
Raymond Hettingeree33b272004-02-08 04:05:26 +0000292"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left.");
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000293
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000294static int
295deque_len(dequeobject *deque)
296{
297 return deque->len;
298}
299
300static int
301deque_clear(dequeobject *deque)
302{
303 PyObject *item;
304
305 while (deque_len(deque)) {
306 item = deque_pop(deque, NULL);
307 if (item == NULL)
308 return -1;
309 Py_DECREF(item);
310 }
311 assert(deque->leftblock == deque->rightblock &&
312 deque->leftindex > deque->rightindex);
313 return 0;
314}
315
316static PyObject *
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000317deque_item(dequeobject *deque, int i)
318{
319 block *b;
320 PyObject *item;
321 int n;
322
323 if (i < 0 || i >= deque->len) {
324 PyErr_SetString(PyExc_IndexError,
325 "deque index out of range");
326 return NULL;
327 }
328
Raymond Hettinger6c79a512004-03-04 08:00:54 +0000329 if (i == 0) {
330 i = deque->leftindex;
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000331 b = deque->leftblock;
Raymond Hettinger6c79a512004-03-04 08:00:54 +0000332 } else if (i == deque->len - 1) {
333 i = deque->rightindex;
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000334 b = deque->rightblock;
Raymond Hettinger6c79a512004-03-04 08:00:54 +0000335 } else {
336 i += deque->leftindex;
337 n = i / BLOCKLEN;
338 i %= BLOCKLEN;
339 if (i < (deque->len >> 1)) {
340 b = deque->leftblock;
341 while (n--)
342 b = b->rightlink;
343 } else {
344 n = (deque->leftindex + deque->len - 1) / BLOCKLEN - n;
345 b = deque->rightblock;
346 while (n--)
347 b = b->leftlink;
348 }
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000349 }
350 item = b->data[i];
351 Py_INCREF(item);
352 return item;
353}
354
355static int
Raymond Hettinger0e371f22004-05-12 20:55:56 +0000356deque_del_item(dequeobject *deque, int i)
357{
358 PyObject *item=NULL, *minus_i=NULL, *plus_i=NULL;
359 int rv = -1;
360
361 assert (i >= 0 && i < deque->len);
362
363 minus_i = Py_BuildValue("(i)", -i);
364 if (minus_i == NULL)
365 goto fail;
366
367 plus_i = Py_BuildValue("(i)", i);
368 if (plus_i == NULL)
369 goto fail;
370
371 item = deque_rotate(deque, minus_i);
372 if (item == NULL)
373 goto fail;
374 Py_DECREF(item);
375
376 item = deque_popleft(deque, NULL);
377 if (item == NULL)
378 goto fail;
379 Py_DECREF(item);
380
381 item = deque_rotate(deque, plus_i);
382 if (item == NULL)
383 goto fail;
384
385 rv = 0;
386fail:
387 Py_XDECREF(item);
388 Py_XDECREF(minus_i);
389 Py_XDECREF(plus_i);
390 return rv;
391}
392
393static int
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000394deque_ass_item(dequeobject *deque, int i, PyObject *v)
395{
396 PyObject *old_value;
397 block *b;
398 int n;
399
400 if (i < 0 || i >= deque->len) {
401 PyErr_SetString(PyExc_IndexError,
402 "deque index out of range");
403 return -1;
404 }
Raymond Hettinger0e371f22004-05-12 20:55:56 +0000405 if (v == NULL)
406 return deque_del_item(deque, i);
407
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000408 i += deque->leftindex;
409 n = i / BLOCKLEN;
410 i %= BLOCKLEN;
411 if (i < (deque->len >> 1)) {
412 b = deque->leftblock;
413 while (n--)
414 b = b->rightlink;
415 } else {
416 n = (deque->leftindex + deque->len - 1) / BLOCKLEN - n;
417 b = deque->rightblock;
418 while (n--)
419 b = b->leftlink;
420 }
421 Py_INCREF(v);
422 old_value = b->data[i];
423 b->data[i] = v;
424 Py_DECREF(old_value);
425 return 0;
426}
427
428static PyObject *
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000429deque_clearmethod(dequeobject *deque)
430{
431 if (deque_clear(deque) == -1)
432 return NULL;
433 Py_RETURN_NONE;
434}
435
436PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
437
438static void
439deque_dealloc(dequeobject *deque)
440{
441 PyObject_GC_UnTrack(deque);
442 if (deque->leftblock != NULL) {
443 int err = deque_clear(deque);
444 assert(err == 0);
445 assert(deque->leftblock != NULL);
446 PyMem_Free(deque->leftblock);
447 }
448 deque->leftblock = NULL;
449 deque->rightblock = NULL;
450 deque->ob_type->tp_free(deque);
451}
452
453static int
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000454deque_traverse(dequeobject *deque, visitproc visit, void *arg)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000455{
456 block * b = deque->leftblock;
457 int index = deque->leftindex;
458 int err;
459 PyObject *item;
460
461 while (b != deque->rightblock || index <= deque->rightindex) {
462 item = b->data[index];
463 index++;
464 if (index == BLOCKLEN && b->rightlink != NULL) {
465 b = b->rightlink;
466 index = 0;
467 }
468 err = visit(item, arg);
469 if (err)
470 return err;
471 }
472 return 0;
473}
474
475static long
476deque_nohash(PyObject *self)
477{
478 PyErr_SetString(PyExc_TypeError, "deque objects are unhashable");
479 return -1;
480}
481
482static PyObject *
483deque_copy(PyObject *deque)
484{
485 return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type),
486 deque, NULL);
487}
488
489PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
490
491static PyObject *
492deque_reduce(dequeobject *deque)
493{
494 PyObject *seq, *args, *result;
495
496 seq = PySequence_Tuple((PyObject *)deque);
497 if (seq == NULL)
498 return NULL;
499 args = PyTuple_Pack(1, seq);
500 if (args == NULL) {
501 Py_DECREF(seq);
502 return NULL;
503 }
504 result = PyTuple_Pack(2, deque->ob_type, args);
505 Py_DECREF(seq);
506 Py_DECREF(args);
507 return result;
508}
509
510PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
511
512static PyObject *
513deque_repr(PyObject *deque)
514{
515 PyObject *aslist, *result, *fmt;
516 int i;
517
518 i = Py_ReprEnter(deque);
519 if (i != 0) {
520 if (i < 0)
521 return NULL;
522 return PyString_FromString("[...]");
523 }
524
525 aslist = PySequence_List(deque);
526 if (aslist == NULL) {
527 Py_ReprLeave(deque);
528 return NULL;
529 }
530
531 fmt = PyString_FromString("deque(%r)");
532 if (fmt == NULL) {
533 Py_DECREF(aslist);
534 Py_ReprLeave(deque);
535 return NULL;
536 }
537 result = PyString_Format(fmt, aslist);
538 Py_DECREF(fmt);
539 Py_DECREF(aslist);
540 Py_ReprLeave(deque);
541 return result;
542}
543
544static int
545deque_tp_print(PyObject *deque, FILE *fp, int flags)
546{
547 PyObject *it, *item;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000548 char *emit = ""; /* No separator emitted on first pass */
549 char *separator = ", ";
550 int i;
551
552 i = Py_ReprEnter(deque);
553 if (i != 0) {
554 if (i < 0)
555 return i;
556 fputs("[...]", fp);
557 return 0;
558 }
559
560 it = PyObject_GetIter(deque);
561 if (it == NULL)
562 return -1;
563
564 fputs("deque([", fp);
565 while ((item = PyIter_Next(it)) != NULL) {
566 fputs(emit, fp);
567 emit = separator;
568 if (PyObject_Print(item, fp, 0) != 0) {
569 Py_DECREF(item);
570 Py_DECREF(it);
571 Py_ReprLeave(deque);
572 return -1;
573 }
574 Py_DECREF(item);
575 }
576 Py_ReprLeave(deque);
577 Py_DECREF(it);
578 if (PyErr_Occurred())
579 return -1;
580 fputs("])", fp);
581 return 0;
582}
583
Raymond Hettinger738ec902004-02-29 02:15:56 +0000584static PyObject *
585deque_richcompare(PyObject *v, PyObject *w, int op)
586{
587 PyObject *it1=NULL, *it2=NULL, *x, *y;
588 int i, b, vs, ws, minlen, cmp=-1;
589
590 if (v->ob_type != &deque_type || w->ob_type != &deque_type) {
591 Py_INCREF(Py_NotImplemented);
592 return Py_NotImplemented;
593 }
594
595 /* Shortcuts */
596 vs = ((dequeobject *)v)->len;
597 ws = ((dequeobject *)w)->len;
598 if (op == Py_EQ) {
599 if (v == w)
600 Py_RETURN_TRUE;
601 if (vs != ws)
602 Py_RETURN_FALSE;
603 }
604 if (op == Py_NE) {
605 if (v == w)
606 Py_RETURN_FALSE;
607 if (vs != ws)
608 Py_RETURN_TRUE;
609 }
610
611 /* Search for the first index where items are different */
612 it1 = PyObject_GetIter(v);
613 if (it1 == NULL)
614 goto done;
615 it2 = PyObject_GetIter(w);
616 if (it2 == NULL)
617 goto done;
618 minlen = (vs < ws) ? vs : ws;
619 for (i=0 ; i < minlen ; i++) {
620 x = PyIter_Next(it1);
621 if (x == NULL)
622 goto done;
623 y = PyIter_Next(it2);
624 if (y == NULL) {
625 Py_DECREF(x);
626 goto done;
627 }
628 b = PyObject_RichCompareBool(x, y, Py_EQ);
629 if (b == 0) {
630 cmp = PyObject_RichCompareBool(x, y, op);
631 Py_DECREF(x);
632 Py_DECREF(y);
633 goto done;
634 }
635 Py_DECREF(x);
636 Py_DECREF(y);
637 if (b == -1)
638 goto done;
639 }
640 /* Elements are equal through minlen. The longest input is the greatest */
641 switch (op) {
642 case Py_LT: cmp = vs < ws; break;
643 case Py_LE: cmp = vs <= ws; break;
644 case Py_EQ: cmp = vs == ws; break;
645 case Py_NE: cmp = vs != ws; break;
646 case Py_GT: cmp = vs > ws; break;
647 case Py_GE: cmp = vs >= ws; break;
648 }
649
650done:
651 Py_XDECREF(it1);
652 Py_XDECREF(it2);
653 if (cmp == 1)
654 Py_RETURN_TRUE;
655 if (cmp == 0)
656 Py_RETURN_FALSE;
657 return NULL;
658}
659
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000660static int
661deque_init(dequeobject *deque, PyObject *args, PyObject *kwds)
662{
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000663 PyObject *iterable = NULL;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000664
665 if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable))
666 return -1;
667
668 if (iterable != NULL) {
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000669 PyObject *rv = deque_extend(deque, iterable);
670 if (rv == NULL)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000671 return -1;
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000672 Py_DECREF(rv);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000673 }
674 return 0;
675}
676
677static PySequenceMethods deque_as_sequence = {
678 (inquiry)deque_len, /* sq_length */
679 0, /* sq_concat */
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000680 0, /* sq_repeat */
681 (intargfunc)deque_item, /* sq_item */
682 0, /* sq_slice */
683 (intobjargproc)deque_ass_item, /* sq_ass_item */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000684};
685
686/* deque object ********************************************************/
687
688static PyObject *deque_iter(dequeobject *deque);
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000689static PyObject *deque_reviter(dequeobject *deque);
690PyDoc_STRVAR(reversed_doc,
691 "D.__reversed__() -- return a reverse iterator over the deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000692
693static PyMethodDef deque_methods[] = {
694 {"append", (PyCFunction)deque_append,
695 METH_O, append_doc},
696 {"appendleft", (PyCFunction)deque_appendleft,
697 METH_O, appendleft_doc},
698 {"clear", (PyCFunction)deque_clearmethod,
699 METH_NOARGS, clear_doc},
700 {"__copy__", (PyCFunction)deque_copy,
701 METH_NOARGS, copy_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000702 {"extend", (PyCFunction)deque_extend,
703 METH_O, extend_doc},
704 {"extendleft", (PyCFunction)deque_extendleft,
705 METH_O, extendleft_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000706 {"pop", (PyCFunction)deque_pop,
707 METH_NOARGS, pop_doc},
708 {"popleft", (PyCFunction)deque_popleft,
709 METH_NOARGS, popleft_doc},
710 {"__reduce__", (PyCFunction)deque_reduce,
711 METH_NOARGS, reduce_doc},
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000712 {"__reversed__", (PyCFunction)deque_reviter,
713 METH_NOARGS, reversed_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000714 {"rotate", (PyCFunction)deque_rotate,
715 METH_VARARGS, rotate_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000716 {NULL, NULL} /* sentinel */
717};
718
719PyDoc_STRVAR(deque_doc,
720"deque(iterable) --> deque object\n\
721\n\
722Build an ordered collection accessible from endpoints only.");
723
Neal Norwitz87f10132004-02-29 15:40:53 +0000724static PyTypeObject deque_type = {
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000725 PyObject_HEAD_INIT(NULL)
726 0, /* ob_size */
727 "collections.deque", /* tp_name */
728 sizeof(dequeobject), /* tp_basicsize */
729 0, /* tp_itemsize */
730 /* methods */
731 (destructor)deque_dealloc, /* tp_dealloc */
732 (printfunc)deque_tp_print, /* tp_print */
733 0, /* tp_getattr */
734 0, /* tp_setattr */
735 0, /* tp_compare */
736 (reprfunc)deque_repr, /* tp_repr */
737 0, /* tp_as_number */
738 &deque_as_sequence, /* tp_as_sequence */
739 0, /* tp_as_mapping */
740 deque_nohash, /* tp_hash */
741 0, /* tp_call */
742 0, /* tp_str */
743 PyObject_GenericGetAttr, /* tp_getattro */
744 0, /* tp_setattro */
745 0, /* tp_as_buffer */
746 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
747 deque_doc, /* tp_doc */
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000748 (traverseproc)deque_traverse, /* tp_traverse */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000749 (inquiry)deque_clear, /* tp_clear */
Raymond Hettinger738ec902004-02-29 02:15:56 +0000750 (richcmpfunc)deque_richcompare, /* tp_richcompare */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000751 0, /* tp_weaklistoffset*/
752 (getiterfunc)deque_iter, /* tp_iter */
753 0, /* tp_iternext */
754 deque_methods, /* tp_methods */
755 0, /* tp_members */
756 0, /* tp_getset */
757 0, /* tp_base */
758 0, /* tp_dict */
759 0, /* tp_descr_get */
760 0, /* tp_descr_set */
761 0, /* tp_dictoffset */
762 (initproc)deque_init, /* tp_init */
763 PyType_GenericAlloc, /* tp_alloc */
764 deque_new, /* tp_new */
765 PyObject_GC_Del, /* tp_free */
766};
767
768/*********************** Deque Iterator **************************/
769
770typedef struct {
771 PyObject_HEAD
772 int index;
773 block *b;
774 dequeobject *deque;
775 int len;
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000776 int counter;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000777} dequeiterobject;
778
779PyTypeObject dequeiter_type;
780
781static PyObject *
782deque_iter(dequeobject *deque)
783{
784 dequeiterobject *it;
785
786 it = PyObject_New(dequeiterobject, &dequeiter_type);
787 if (it == NULL)
788 return NULL;
789 it->b = deque->leftblock;
790 it->index = deque->leftindex;
791 Py_INCREF(deque);
792 it->deque = deque;
793 it->len = deque->len;
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000794 it->counter = deque->len;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000795 return (PyObject *)it;
796}
797
798static void
799dequeiter_dealloc(dequeiterobject *dio)
800{
801 Py_XDECREF(dio->deque);
802 dio->ob_type->tp_free(dio);
803}
804
805static PyObject *
806dequeiter_next(dequeiterobject *it)
807{
808 PyObject *item;
809 if (it->b == it->deque->rightblock && it->index > it->deque->rightindex)
810 return NULL;
811
812 if (it->len != it->deque->len) {
813 it->len = -1; /* Make this state sticky */
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000814 it->counter = 0;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000815 PyErr_SetString(PyExc_RuntimeError,
816 "deque changed size during iteration");
817 return NULL;
818 }
819
820 item = it->b->data[it->index];
821 it->index++;
822 if (it->index == BLOCKLEN && it->b->rightlink != NULL) {
823 it->b = it->b->rightlink;
824 it->index = 0;
825 }
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000826 it->counter--;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000827 Py_INCREF(item);
828 return item;
829}
830
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000831static int
832dequeiter_len(dequeiterobject *it)
833{
834 return it->counter;
835}
836
837static PySequenceMethods dequeiter_as_sequence = {
838 (inquiry)dequeiter_len, /* sq_length */
839 0, /* sq_concat */
840};
841
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000842PyTypeObject dequeiter_type = {
843 PyObject_HEAD_INIT(NULL)
844 0, /* ob_size */
845 "deque_iterator", /* tp_name */
846 sizeof(dequeiterobject), /* tp_basicsize */
847 0, /* tp_itemsize */
848 /* methods */
849 (destructor)dequeiter_dealloc, /* tp_dealloc */
850 0, /* tp_print */
851 0, /* tp_getattr */
852 0, /* tp_setattr */
853 0, /* tp_compare */
854 0, /* tp_repr */
855 0, /* tp_as_number */
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000856 &dequeiter_as_sequence, /* tp_as_sequence */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000857 0, /* tp_as_mapping */
858 0, /* tp_hash */
859 0, /* tp_call */
860 0, /* tp_str */
861 PyObject_GenericGetAttr, /* tp_getattro */
862 0, /* tp_setattro */
863 0, /* tp_as_buffer */
864 Py_TPFLAGS_DEFAULT, /* tp_flags */
865 0, /* tp_doc */
866 0, /* tp_traverse */
867 0, /* tp_clear */
868 0, /* tp_richcompare */
869 0, /* tp_weaklistoffset */
870 PyObject_SelfIter, /* tp_iter */
871 (iternextfunc)dequeiter_next, /* tp_iternext */
872 0,
873};
874
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000875/*********************** Deque Reverse Iterator **************************/
876
877PyTypeObject dequereviter_type;
878
879static PyObject *
880deque_reviter(dequeobject *deque)
881{
882 dequeiterobject *it;
883
884 it = PyObject_New(dequeiterobject, &dequereviter_type);
885 if (it == NULL)
886 return NULL;
887 it->b = deque->rightblock;
888 it->index = deque->rightindex;
889 Py_INCREF(deque);
890 it->deque = deque;
891 it->len = deque->len;
892 it->counter = deque->len;
893 return (PyObject *)it;
894}
895
896static PyObject *
897dequereviter_next(dequeiterobject *it)
898{
899 PyObject *item;
900 if (it->b == it->deque->leftblock && it->index < it->deque->leftindex)
901 return NULL;
902
903 if (it->len != it->deque->len) {
904 it->len = -1; /* Make this state sticky */
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000905 it->counter = 0;
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000906 PyErr_SetString(PyExc_RuntimeError,
907 "deque changed size during iteration");
908 return NULL;
909 }
910
911 item = it->b->data[it->index];
912 it->index--;
913 if (it->index == -1 && it->b->leftlink != NULL) {
914 it->b = it->b->leftlink;
915 it->index = BLOCKLEN - 1;
916 }
917 it->counter--;
918 Py_INCREF(item);
919 return item;
920}
921
922PyTypeObject dequereviter_type = {
923 PyObject_HEAD_INIT(NULL)
924 0, /* ob_size */
925 "deque_reverse_iterator", /* tp_name */
926 sizeof(dequeiterobject), /* tp_basicsize */
927 0, /* tp_itemsize */
928 /* methods */
929 (destructor)dequeiter_dealloc, /* tp_dealloc */
930 0, /* tp_print */
931 0, /* tp_getattr */
932 0, /* tp_setattr */
933 0, /* tp_compare */
934 0, /* tp_repr */
935 0, /* tp_as_number */
936 &dequeiter_as_sequence, /* tp_as_sequence */
937 0, /* tp_as_mapping */
938 0, /* tp_hash */
939 0, /* tp_call */
940 0, /* tp_str */
941 PyObject_GenericGetAttr, /* tp_getattro */
942 0, /* tp_setattro */
943 0, /* tp_as_buffer */
944 Py_TPFLAGS_DEFAULT, /* tp_flags */
945 0, /* tp_doc */
946 0, /* tp_traverse */
947 0, /* tp_clear */
948 0, /* tp_richcompare */
949 0, /* tp_weaklistoffset */
950 PyObject_SelfIter, /* tp_iter */
951 (iternextfunc)dequereviter_next, /* tp_iternext */
952 0,
953};
954
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000955/* module level code ********************************************************/
956
957PyDoc_STRVAR(module_doc,
958"High performance data structures\n\
959");
960
961PyMODINIT_FUNC
962initcollections(void)
963{
964 PyObject *m;
965
966 m = Py_InitModule3("collections", NULL, module_doc);
967
968 if (PyType_Ready(&deque_type) < 0)
969 return;
970 Py_INCREF(&deque_type);
971 PyModule_AddObject(m, "deque", (PyObject *)&deque_type);
972
973 if (PyType_Ready(&dequeiter_type) < 0)
974 return;
975
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000976 if (PyType_Ready(&dequereviter_type) < 0)
977 return;
978
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000979 return;
980}