blob: ddc6f88461b60ce9c5bda48e844a9ce9e586b13f [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
356deque_ass_item(dequeobject *deque, int i, PyObject *v)
357{
358 PyObject *old_value;
359 block *b;
360 int n;
361
362 if (i < 0 || i >= deque->len) {
363 PyErr_SetString(PyExc_IndexError,
364 "deque index out of range");
365 return -1;
366 }
367 i += deque->leftindex;
368 n = i / BLOCKLEN;
369 i %= BLOCKLEN;
370 if (i < (deque->len >> 1)) {
371 b = deque->leftblock;
372 while (n--)
373 b = b->rightlink;
374 } else {
375 n = (deque->leftindex + deque->len - 1) / BLOCKLEN - n;
376 b = deque->rightblock;
377 while (n--)
378 b = b->leftlink;
379 }
380 Py_INCREF(v);
381 old_value = b->data[i];
382 b->data[i] = v;
383 Py_DECREF(old_value);
384 return 0;
385}
386
387static PyObject *
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000388deque_clearmethod(dequeobject *deque)
389{
390 if (deque_clear(deque) == -1)
391 return NULL;
392 Py_RETURN_NONE;
393}
394
395PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
396
397static void
398deque_dealloc(dequeobject *deque)
399{
400 PyObject_GC_UnTrack(deque);
401 if (deque->leftblock != NULL) {
402 int err = deque_clear(deque);
403 assert(err == 0);
404 assert(deque->leftblock != NULL);
405 PyMem_Free(deque->leftblock);
406 }
407 deque->leftblock = NULL;
408 deque->rightblock = NULL;
409 deque->ob_type->tp_free(deque);
410}
411
412static int
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000413deque_traverse(dequeobject *deque, visitproc visit, void *arg)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000414{
415 block * b = deque->leftblock;
416 int index = deque->leftindex;
417 int err;
418 PyObject *item;
419
420 while (b != deque->rightblock || index <= deque->rightindex) {
421 item = b->data[index];
422 index++;
423 if (index == BLOCKLEN && b->rightlink != NULL) {
424 b = b->rightlink;
425 index = 0;
426 }
427 err = visit(item, arg);
428 if (err)
429 return err;
430 }
431 return 0;
432}
433
434static long
435deque_nohash(PyObject *self)
436{
437 PyErr_SetString(PyExc_TypeError, "deque objects are unhashable");
438 return -1;
439}
440
441static PyObject *
442deque_copy(PyObject *deque)
443{
444 return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type),
445 deque, NULL);
446}
447
448PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
449
450static PyObject *
451deque_reduce(dequeobject *deque)
452{
453 PyObject *seq, *args, *result;
454
455 seq = PySequence_Tuple((PyObject *)deque);
456 if (seq == NULL)
457 return NULL;
458 args = PyTuple_Pack(1, seq);
459 if (args == NULL) {
460 Py_DECREF(seq);
461 return NULL;
462 }
463 result = PyTuple_Pack(2, deque->ob_type, args);
464 Py_DECREF(seq);
465 Py_DECREF(args);
466 return result;
467}
468
469PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
470
471static PyObject *
472deque_repr(PyObject *deque)
473{
474 PyObject *aslist, *result, *fmt;
475 int i;
476
477 i = Py_ReprEnter(deque);
478 if (i != 0) {
479 if (i < 0)
480 return NULL;
481 return PyString_FromString("[...]");
482 }
483
484 aslist = PySequence_List(deque);
485 if (aslist == NULL) {
486 Py_ReprLeave(deque);
487 return NULL;
488 }
489
490 fmt = PyString_FromString("deque(%r)");
491 if (fmt == NULL) {
492 Py_DECREF(aslist);
493 Py_ReprLeave(deque);
494 return NULL;
495 }
496 result = PyString_Format(fmt, aslist);
497 Py_DECREF(fmt);
498 Py_DECREF(aslist);
499 Py_ReprLeave(deque);
500 return result;
501}
502
503static int
504deque_tp_print(PyObject *deque, FILE *fp, int flags)
505{
506 PyObject *it, *item;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000507 char *emit = ""; /* No separator emitted on first pass */
508 char *separator = ", ";
509 int i;
510
511 i = Py_ReprEnter(deque);
512 if (i != 0) {
513 if (i < 0)
514 return i;
515 fputs("[...]", fp);
516 return 0;
517 }
518
519 it = PyObject_GetIter(deque);
520 if (it == NULL)
521 return -1;
522
523 fputs("deque([", fp);
524 while ((item = PyIter_Next(it)) != NULL) {
525 fputs(emit, fp);
526 emit = separator;
527 if (PyObject_Print(item, fp, 0) != 0) {
528 Py_DECREF(item);
529 Py_DECREF(it);
530 Py_ReprLeave(deque);
531 return -1;
532 }
533 Py_DECREF(item);
534 }
535 Py_ReprLeave(deque);
536 Py_DECREF(it);
537 if (PyErr_Occurred())
538 return -1;
539 fputs("])", fp);
540 return 0;
541}
542
Raymond Hettinger738ec902004-02-29 02:15:56 +0000543static PyObject *
544deque_richcompare(PyObject *v, PyObject *w, int op)
545{
546 PyObject *it1=NULL, *it2=NULL, *x, *y;
547 int i, b, vs, ws, minlen, cmp=-1;
548
549 if (v->ob_type != &deque_type || w->ob_type != &deque_type) {
550 Py_INCREF(Py_NotImplemented);
551 return Py_NotImplemented;
552 }
553
554 /* Shortcuts */
555 vs = ((dequeobject *)v)->len;
556 ws = ((dequeobject *)w)->len;
557 if (op == Py_EQ) {
558 if (v == w)
559 Py_RETURN_TRUE;
560 if (vs != ws)
561 Py_RETURN_FALSE;
562 }
563 if (op == Py_NE) {
564 if (v == w)
565 Py_RETURN_FALSE;
566 if (vs != ws)
567 Py_RETURN_TRUE;
568 }
569
570 /* Search for the first index where items are different */
571 it1 = PyObject_GetIter(v);
572 if (it1 == NULL)
573 goto done;
574 it2 = PyObject_GetIter(w);
575 if (it2 == NULL)
576 goto done;
577 minlen = (vs < ws) ? vs : ws;
578 for (i=0 ; i < minlen ; i++) {
579 x = PyIter_Next(it1);
580 if (x == NULL)
581 goto done;
582 y = PyIter_Next(it2);
583 if (y == NULL) {
584 Py_DECREF(x);
585 goto done;
586 }
587 b = PyObject_RichCompareBool(x, y, Py_EQ);
588 if (b == 0) {
589 cmp = PyObject_RichCompareBool(x, y, op);
590 Py_DECREF(x);
591 Py_DECREF(y);
592 goto done;
593 }
594 Py_DECREF(x);
595 Py_DECREF(y);
596 if (b == -1)
597 goto done;
598 }
599 /* Elements are equal through minlen. The longest input is the greatest */
600 switch (op) {
601 case Py_LT: cmp = vs < ws; break;
602 case Py_LE: cmp = vs <= ws; break;
603 case Py_EQ: cmp = vs == ws; break;
604 case Py_NE: cmp = vs != ws; break;
605 case Py_GT: cmp = vs > ws; break;
606 case Py_GE: cmp = vs >= ws; break;
607 }
608
609done:
610 Py_XDECREF(it1);
611 Py_XDECREF(it2);
612 if (cmp == 1)
613 Py_RETURN_TRUE;
614 if (cmp == 0)
615 Py_RETURN_FALSE;
616 return NULL;
617}
618
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000619static int
620deque_init(dequeobject *deque, PyObject *args, PyObject *kwds)
621{
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000622 PyObject *iterable = NULL;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000623
624 if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable))
625 return -1;
626
627 if (iterable != NULL) {
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000628 PyObject *rv = deque_extend(deque, iterable);
629 if (rv == NULL)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000630 return -1;
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000631 Py_DECREF(rv);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000632 }
633 return 0;
634}
635
636static PySequenceMethods deque_as_sequence = {
637 (inquiry)deque_len, /* sq_length */
638 0, /* sq_concat */
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000639 0, /* sq_repeat */
640 (intargfunc)deque_item, /* sq_item */
641 0, /* sq_slice */
642 (intobjargproc)deque_ass_item, /* sq_ass_item */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000643};
644
645/* deque object ********************************************************/
646
647static PyObject *deque_iter(dequeobject *deque);
648
649static PyMethodDef deque_methods[] = {
650 {"append", (PyCFunction)deque_append,
651 METH_O, append_doc},
652 {"appendleft", (PyCFunction)deque_appendleft,
653 METH_O, appendleft_doc},
654 {"clear", (PyCFunction)deque_clearmethod,
655 METH_NOARGS, clear_doc},
656 {"__copy__", (PyCFunction)deque_copy,
657 METH_NOARGS, copy_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000658 {"extend", (PyCFunction)deque_extend,
659 METH_O, extend_doc},
660 {"extendleft", (PyCFunction)deque_extendleft,
661 METH_O, extendleft_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000662 {"pop", (PyCFunction)deque_pop,
663 METH_NOARGS, pop_doc},
664 {"popleft", (PyCFunction)deque_popleft,
665 METH_NOARGS, popleft_doc},
666 {"__reduce__", (PyCFunction)deque_reduce,
667 METH_NOARGS, reduce_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000668 {"rotate", (PyCFunction)deque_rotate,
669 METH_VARARGS, rotate_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000670 {NULL, NULL} /* sentinel */
671};
672
673PyDoc_STRVAR(deque_doc,
674"deque(iterable) --> deque object\n\
675\n\
676Build an ordered collection accessible from endpoints only.");
677
Neal Norwitz87f10132004-02-29 15:40:53 +0000678static PyTypeObject deque_type = {
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000679 PyObject_HEAD_INIT(NULL)
680 0, /* ob_size */
681 "collections.deque", /* tp_name */
682 sizeof(dequeobject), /* tp_basicsize */
683 0, /* tp_itemsize */
684 /* methods */
685 (destructor)deque_dealloc, /* tp_dealloc */
686 (printfunc)deque_tp_print, /* tp_print */
687 0, /* tp_getattr */
688 0, /* tp_setattr */
689 0, /* tp_compare */
690 (reprfunc)deque_repr, /* tp_repr */
691 0, /* tp_as_number */
692 &deque_as_sequence, /* tp_as_sequence */
693 0, /* tp_as_mapping */
694 deque_nohash, /* tp_hash */
695 0, /* tp_call */
696 0, /* tp_str */
697 PyObject_GenericGetAttr, /* tp_getattro */
698 0, /* tp_setattro */
699 0, /* tp_as_buffer */
700 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
701 deque_doc, /* tp_doc */
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000702 (traverseproc)deque_traverse, /* tp_traverse */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000703 (inquiry)deque_clear, /* tp_clear */
Raymond Hettinger738ec902004-02-29 02:15:56 +0000704 (richcmpfunc)deque_richcompare, /* tp_richcompare */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000705 0, /* tp_weaklistoffset*/
706 (getiterfunc)deque_iter, /* tp_iter */
707 0, /* tp_iternext */
708 deque_methods, /* tp_methods */
709 0, /* tp_members */
710 0, /* tp_getset */
711 0, /* tp_base */
712 0, /* tp_dict */
713 0, /* tp_descr_get */
714 0, /* tp_descr_set */
715 0, /* tp_dictoffset */
716 (initproc)deque_init, /* tp_init */
717 PyType_GenericAlloc, /* tp_alloc */
718 deque_new, /* tp_new */
719 PyObject_GC_Del, /* tp_free */
720};
721
722/*********************** Deque Iterator **************************/
723
724typedef struct {
725 PyObject_HEAD
726 int index;
727 block *b;
728 dequeobject *deque;
729 int len;
730} dequeiterobject;
731
732PyTypeObject dequeiter_type;
733
734static PyObject *
735deque_iter(dequeobject *deque)
736{
737 dequeiterobject *it;
738
739 it = PyObject_New(dequeiterobject, &dequeiter_type);
740 if (it == NULL)
741 return NULL;
742 it->b = deque->leftblock;
743 it->index = deque->leftindex;
744 Py_INCREF(deque);
745 it->deque = deque;
746 it->len = deque->len;
747 return (PyObject *)it;
748}
749
750static void
751dequeiter_dealloc(dequeiterobject *dio)
752{
753 Py_XDECREF(dio->deque);
754 dio->ob_type->tp_free(dio);
755}
756
757static PyObject *
758dequeiter_next(dequeiterobject *it)
759{
760 PyObject *item;
761 if (it->b == it->deque->rightblock && it->index > it->deque->rightindex)
762 return NULL;
763
764 if (it->len != it->deque->len) {
765 it->len = -1; /* Make this state sticky */
766 PyErr_SetString(PyExc_RuntimeError,
767 "deque changed size during iteration");
768 return NULL;
769 }
770
771 item = it->b->data[it->index];
772 it->index++;
773 if (it->index == BLOCKLEN && it->b->rightlink != NULL) {
774 it->b = it->b->rightlink;
775 it->index = 0;
776 }
777 Py_INCREF(item);
778 return item;
779}
780
781PyTypeObject dequeiter_type = {
782 PyObject_HEAD_INIT(NULL)
783 0, /* ob_size */
784 "deque_iterator", /* tp_name */
785 sizeof(dequeiterobject), /* tp_basicsize */
786 0, /* tp_itemsize */
787 /* methods */
788 (destructor)dequeiter_dealloc, /* tp_dealloc */
789 0, /* tp_print */
790 0, /* tp_getattr */
791 0, /* tp_setattr */
792 0, /* tp_compare */
793 0, /* tp_repr */
794 0, /* tp_as_number */
795 0, /* tp_as_sequence */
796 0, /* tp_as_mapping */
797 0, /* tp_hash */
798 0, /* tp_call */
799 0, /* tp_str */
800 PyObject_GenericGetAttr, /* tp_getattro */
801 0, /* tp_setattro */
802 0, /* tp_as_buffer */
803 Py_TPFLAGS_DEFAULT, /* tp_flags */
804 0, /* tp_doc */
805 0, /* tp_traverse */
806 0, /* tp_clear */
807 0, /* tp_richcompare */
808 0, /* tp_weaklistoffset */
809 PyObject_SelfIter, /* tp_iter */
810 (iternextfunc)dequeiter_next, /* tp_iternext */
811 0,
812};
813
814/* module level code ********************************************************/
815
816PyDoc_STRVAR(module_doc,
817"High performance data structures\n\
818");
819
820PyMODINIT_FUNC
821initcollections(void)
822{
823 PyObject *m;
824
825 m = Py_InitModule3("collections", NULL, module_doc);
826
827 if (PyType_Ready(&deque_type) < 0)
828 return;
829 Py_INCREF(&deque_type);
830 PyModule_AddObject(m, "deque", (PyObject *)&deque_type);
831
832 if (PyType_Ready(&dequeiter_type) < 0)
833 return;
834
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000835 return;
836}