blob: 9b8a091a04c8dd956387a1320a921911439aa6c5 [file] [log] [blame]
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001#include "Python.h"
Raymond Hettinger691d8052004-05-30 07:26:47 +00002#include "structmember.h"
Raymond Hettinger756b3f32004-01-29 06:37:52 +00003
4/* collections module implementation of a deque() datatype
5 Written and maintained by Raymond D. Hettinger <python@rcn.com>
6 Copyright (c) 2004 Python Software Foundation.
7 All rights reserved.
8*/
9
10#define BLOCKLEN 46
11
12typedef struct BLOCK {
13 struct BLOCK *leftlink;
14 struct BLOCK *rightlink;
15 PyObject *data[BLOCKLEN];
16} block;
17
18static block *newblock(block *leftlink, block *rightlink) {
19 block *b = PyMem_Malloc(sizeof(block));
20 if (b == NULL) {
21 PyErr_NoMemory();
22 return NULL;
23 }
24 b->leftlink = leftlink;
25 b->rightlink = rightlink;
26 return b;
27}
28
29typedef struct {
30 PyObject_HEAD
31 block *leftblock;
32 block *rightblock;
33 int leftindex;
34 int rightindex;
35 int len;
Raymond Hettinger691d8052004-05-30 07:26:47 +000036 PyObject *weakreflist; /* List of weak references */
Raymond Hettinger756b3f32004-01-29 06:37:52 +000037} dequeobject;
38
Neal Norwitz87f10132004-02-29 15:40:53 +000039static PyTypeObject deque_type;
Raymond Hettinger738ec902004-02-29 02:15:56 +000040
Raymond Hettinger756b3f32004-01-29 06:37:52 +000041static PyObject *
42deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
43{
44 dequeobject *deque;
45 block *b;
46
47 /* create dequeobject structure */
48 deque = (dequeobject *)type->tp_alloc(type, 0);
49 if (deque == NULL)
50 return NULL;
51
52 b = newblock(NULL, NULL);
53 if (b == NULL) {
54 Py_DECREF(deque);
55 return NULL;
56 }
57
58 deque->leftblock = b;
59 deque->rightblock = b;
60 deque->leftindex = BLOCKLEN / 2 + 1;
61 deque->rightindex = BLOCKLEN / 2;
62 deque->len = 0;
Raymond Hettinger691d8052004-05-30 07:26:47 +000063 deque->weakreflist = NULL;
Raymond Hettinger756b3f32004-01-29 06:37:52 +000064
65 return (PyObject *)deque;
66}
67
68static PyObject *
69deque_append(dequeobject *deque, PyObject *item)
70{
71 deque->rightindex++;
72 deque->len++;
73 if (deque->rightindex == BLOCKLEN) {
74 block *b = newblock(deque->rightblock, NULL);
75 if (b == NULL)
76 return NULL;
77 assert(deque->rightblock->rightlink == NULL);
78 deque->rightblock->rightlink = b;
79 deque->rightblock = b;
80 deque->rightindex = 0;
81 }
82 Py_INCREF(item);
83 deque->rightblock->data[deque->rightindex] = item;
84 Py_RETURN_NONE;
85}
86
87PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque.");
88
89static PyObject *
90deque_appendleft(dequeobject *deque, PyObject *item)
91{
92 deque->leftindex--;
93 deque->len++;
94 if (deque->leftindex == -1) {
95 block *b = newblock(NULL, deque->leftblock);
96 if (b == NULL)
97 return NULL;
98 assert(deque->leftblock->leftlink == NULL);
99 deque->leftblock->leftlink = b;
100 deque->leftblock = b;
101 deque->leftindex = BLOCKLEN - 1;
102 }
103 Py_INCREF(item);
104 deque->leftblock->data[deque->leftindex] = item;
105 Py_RETURN_NONE;
106}
107
108PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque.");
109
110static PyObject *
111deque_pop(dequeobject *deque, PyObject *unused)
112{
113 PyObject *item;
114 block *prevblock;
115
116 if (deque->len == 0) {
Raymond Hettinger738ec902004-02-29 02:15:56 +0000117 PyErr_SetString(PyExc_IndexError, "pop from an empty deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000118 return NULL;
119 }
120 item = deque->rightblock->data[deque->rightindex];
121 deque->rightindex--;
122 deque->len--;
123
124 if (deque->rightindex == -1) {
125 if (deque->len == 0) {
126 assert(deque->leftblock == deque->rightblock);
127 assert(deque->leftindex == deque->rightindex+1);
128 /* re-center instead of freeing a block */
129 deque->leftindex = BLOCKLEN / 2 + 1;
130 deque->rightindex = BLOCKLEN / 2;
131 } else {
132 prevblock = deque->rightblock->leftlink;
133 assert(deque->leftblock != deque->rightblock);
134 PyMem_Free(deque->rightblock);
135 prevblock->rightlink = NULL;
136 deque->rightblock = prevblock;
137 deque->rightindex = BLOCKLEN - 1;
138 }
139 }
140 return item;
141}
142
143PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element.");
144
145static PyObject *
146deque_popleft(dequeobject *deque, PyObject *unused)
147{
148 PyObject *item;
149 block *prevblock;
150
151 if (deque->len == 0) {
Raymond Hettinger738ec902004-02-29 02:15:56 +0000152 PyErr_SetString(PyExc_IndexError, "pop from an empty deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000153 return NULL;
154 }
155 item = deque->leftblock->data[deque->leftindex];
156 deque->leftindex++;
157 deque->len--;
158
159 if (deque->leftindex == BLOCKLEN) {
160 if (deque->len == 0) {
161 assert(deque->leftblock == deque->rightblock);
162 assert(deque->leftindex == deque->rightindex+1);
163 /* re-center instead of freeing a block */
164 deque->leftindex = BLOCKLEN / 2 + 1;
165 deque->rightindex = BLOCKLEN / 2;
166 } else {
167 assert(deque->leftblock != deque->rightblock);
168 prevblock = deque->leftblock->rightlink;
169 assert(deque->leftblock != NULL);
170 PyMem_Free(deque->leftblock);
171 assert(prevblock != NULL);
172 prevblock->leftlink = NULL;
173 deque->leftblock = prevblock;
174 deque->leftindex = 0;
175 }
176 }
177 return item;
178}
179
180PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element.");
181
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000182static PyObject *
183deque_extend(dequeobject *deque, PyObject *iterable)
184{
185 PyObject *it, *item;
186
187 it = PyObject_GetIter(iterable);
188 if (it == NULL)
189 return NULL;
190
191 while ((item = PyIter_Next(it)) != NULL) {
192 deque->rightindex++;
193 deque->len++;
194 if (deque->rightindex == BLOCKLEN) {
195 block *b = newblock(deque->rightblock, NULL);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000196 if (b == NULL) {
197 Py_DECREF(item);
198 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000199 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000200 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000201 assert(deque->rightblock->rightlink == NULL);
202 deque->rightblock->rightlink = b;
203 deque->rightblock = b;
204 deque->rightindex = 0;
205 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000206 deque->rightblock->data[deque->rightindex] = item;
207 }
208 Py_DECREF(it);
209 if (PyErr_Occurred())
210 return NULL;
211 Py_RETURN_NONE;
212}
213
214PyDoc_STRVAR(extend_doc,
215"Extend the right side of the deque with elements from the iterable");
216
217static PyObject *
218deque_extendleft(dequeobject *deque, PyObject *iterable)
219{
220 PyObject *it, *item;
221
222 it = PyObject_GetIter(iterable);
223 if (it == NULL)
224 return NULL;
225
226 while ((item = PyIter_Next(it)) != NULL) {
227 deque->leftindex--;
228 deque->len++;
229 if (deque->leftindex == -1) {
230 block *b = newblock(NULL, deque->leftblock);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000231 if (b == NULL) {
232 Py_DECREF(item);
233 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000234 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000235 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000236 assert(deque->leftblock->leftlink == NULL);
237 deque->leftblock->leftlink = b;
238 deque->leftblock = b;
239 deque->leftindex = BLOCKLEN - 1;
240 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000241 deque->leftblock->data[deque->leftindex] = item;
242 }
243 Py_DECREF(it);
Raymond Hettingera435c532004-07-09 04:10:20 +0000244 if (PyErr_Occurred())
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000245 return NULL;
246 Py_RETURN_NONE;
247}
248
249PyDoc_STRVAR(extendleft_doc,
250"Extend the left side of the deque with elements from the iterable");
251
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000252static PyObject *
253deque_rotate(dequeobject *deque, PyObject *args)
254{
Raymond Hettingeree33b272004-02-08 04:05:26 +0000255 int i, n=1, len=deque->len, halflen=(len+1)>>1;
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000256 PyObject *item, *rv;
257
Raymond Hettingeree33b272004-02-08 04:05:26 +0000258 if (!PyArg_ParseTuple(args, "|i:rotate", &n))
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000259 return NULL;
260
Raymond Hettingeree33b272004-02-08 04:05:26 +0000261 if (len == 0)
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000262 Py_RETURN_NONE;
Raymond Hettingeree33b272004-02-08 04:05:26 +0000263 if (n > halflen || n < -halflen) {
264 n %= len;
265 if (n > halflen)
266 n -= len;
267 else if (n < -halflen)
268 n += len;
269 }
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000270
271 for (i=0 ; i<n ; i++) {
272 item = deque_pop(deque, NULL);
Raymond Hettingera435c532004-07-09 04:10:20 +0000273 assert (item != NULL);
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000274 rv = deque_appendleft(deque, item);
275 Py_DECREF(item);
276 if (rv == NULL)
277 return NULL;
278 Py_DECREF(rv);
279 }
280 for (i=0 ; i>n ; i--) {
281 item = deque_popleft(deque, NULL);
Raymond Hettingera435c532004-07-09 04:10:20 +0000282 assert (item != NULL);
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000283 rv = deque_append(deque, item);
284 Py_DECREF(item);
285 if (rv == NULL)
286 return NULL;
287 Py_DECREF(rv);
288 }
289 Py_RETURN_NONE;
290}
291
292PyDoc_STRVAR(rotate_doc,
Raymond Hettingeree33b272004-02-08 04:05:26 +0000293"Rotate the deque n steps to the right (default n=1). If n is negative, rotates left.");
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000294
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000295static int
296deque_len(dequeobject *deque)
297{
298 return deque->len;
299}
300
301static int
302deque_clear(dequeobject *deque)
303{
304 PyObject *item;
305
306 while (deque_len(deque)) {
307 item = deque_pop(deque, NULL);
Raymond Hettingera435c532004-07-09 04:10:20 +0000308 assert (item != NULL);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000309 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
Raymond Hettinger616f4f62004-06-26 04:42:06 +0000355/* delitem() implemented in terms of rotate for simplicity and reasonable
356 performance near the end points. If for some reason this method becomes
357 popular, it is not hard to re-implement this using direct data movement
358 (similar to code in list slice assignment) and achieve a two or threefold
359 performance boost.
360*/
361
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000362static int
Raymond Hettinger0e371f22004-05-12 20:55:56 +0000363deque_del_item(dequeobject *deque, int i)
364{
365 PyObject *item=NULL, *minus_i=NULL, *plus_i=NULL;
366 int rv = -1;
367
368 assert (i >= 0 && i < deque->len);
369
370 minus_i = Py_BuildValue("(i)", -i);
371 if (minus_i == NULL)
372 goto fail;
373
374 plus_i = Py_BuildValue("(i)", i);
375 if (plus_i == NULL)
376 goto fail;
377
378 item = deque_rotate(deque, minus_i);
379 if (item == NULL)
380 goto fail;
381 Py_DECREF(item);
382
383 item = deque_popleft(deque, NULL);
Raymond Hettingera435c532004-07-09 04:10:20 +0000384 assert (item != NULL);
Raymond Hettinger0e371f22004-05-12 20:55:56 +0000385 Py_DECREF(item);
386
387 item = deque_rotate(deque, plus_i);
388 if (item == NULL)
389 goto fail;
390
391 rv = 0;
392fail:
393 Py_XDECREF(item);
394 Py_XDECREF(minus_i);
395 Py_XDECREF(plus_i);
396 return rv;
397}
398
399static int
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000400deque_ass_item(dequeobject *deque, int i, PyObject *v)
401{
402 PyObject *old_value;
403 block *b;
Raymond Hettingera435c532004-07-09 04:10:20 +0000404 int n, len=deque->len, halflen=(len+1)>>1, index=i;
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000405
Raymond Hettingera435c532004-07-09 04:10:20 +0000406 if (i < 0 || i >= len) {
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000407 PyErr_SetString(PyExc_IndexError,
408 "deque index out of range");
409 return -1;
410 }
Raymond Hettinger0e371f22004-05-12 20:55:56 +0000411 if (v == NULL)
412 return deque_del_item(deque, i);
413
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000414 i += deque->leftindex;
415 n = i / BLOCKLEN;
416 i %= BLOCKLEN;
Raymond Hettingera435c532004-07-09 04:10:20 +0000417 if (index <= halflen) {
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000418 b = deque->leftblock;
419 while (n--)
420 b = b->rightlink;
421 } else {
Raymond Hettingera435c532004-07-09 04:10:20 +0000422 n = (deque->leftindex + len - 1) / BLOCKLEN - n;
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000423 b = deque->rightblock;
424 while (n--)
425 b = b->leftlink;
426 }
427 Py_INCREF(v);
428 old_value = b->data[i];
429 b->data[i] = v;
430 Py_DECREF(old_value);
431 return 0;
432}
433
434static PyObject *
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000435deque_clearmethod(dequeobject *deque)
436{
Raymond Hettingera435c532004-07-09 04:10:20 +0000437 int rv;
438
439 rv = deque_clear(deque);
440 assert (rv != -1);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000441 Py_RETURN_NONE;
442}
443
444PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
445
446static void
447deque_dealloc(dequeobject *deque)
448{
449 PyObject_GC_UnTrack(deque);
Raymond Hettinger691d8052004-05-30 07:26:47 +0000450 if (deque->weakreflist != NULL)
451 PyObject_ClearWeakRefs((PyObject *) deque);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000452 if (deque->leftblock != NULL) {
453 int err = deque_clear(deque);
454 assert(err == 0);
455 assert(deque->leftblock != NULL);
456 PyMem_Free(deque->leftblock);
457 }
458 deque->leftblock = NULL;
459 deque->rightblock = NULL;
460 deque->ob_type->tp_free(deque);
461}
462
463static int
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000464deque_traverse(dequeobject *deque, visitproc visit, void *arg)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000465{
466 block * b = deque->leftblock;
467 int index = deque->leftindex;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000468 PyObject *item;
469
470 while (b != deque->rightblock || index <= deque->rightindex) {
471 item = b->data[index];
472 index++;
Raymond Hettinger67115a22004-07-15 21:32:18 +0000473 if (index == BLOCKLEN ) {
474 assert(b->rightlink != NULL);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000475 b = b->rightlink;
476 index = 0;
477 }
Raymond Hettinger67115a22004-07-15 21:32:18 +0000478 Py_VISIT(item);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000479 }
480 return 0;
481}
482
483static long
484deque_nohash(PyObject *self)
485{
486 PyErr_SetString(PyExc_TypeError, "deque objects are unhashable");
487 return -1;
488}
489
490static PyObject *
491deque_copy(PyObject *deque)
492{
493 return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type),
494 deque, NULL);
495}
496
497PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
498
499static PyObject *
500deque_reduce(dequeobject *deque)
501{
502 PyObject *seq, *args, *result;
503
504 seq = PySequence_Tuple((PyObject *)deque);
505 if (seq == NULL)
506 return NULL;
507 args = PyTuple_Pack(1, seq);
508 if (args == NULL) {
509 Py_DECREF(seq);
510 return NULL;
511 }
512 result = PyTuple_Pack(2, deque->ob_type, args);
513 Py_DECREF(seq);
514 Py_DECREF(args);
515 return result;
516}
517
518PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
519
520static PyObject *
521deque_repr(PyObject *deque)
522{
523 PyObject *aslist, *result, *fmt;
524 int i;
525
526 i = Py_ReprEnter(deque);
527 if (i != 0) {
528 if (i < 0)
529 return NULL;
530 return PyString_FromString("[...]");
531 }
532
533 aslist = PySequence_List(deque);
534 if (aslist == NULL) {
535 Py_ReprLeave(deque);
536 return NULL;
537 }
538
539 fmt = PyString_FromString("deque(%r)");
540 if (fmt == NULL) {
541 Py_DECREF(aslist);
542 Py_ReprLeave(deque);
543 return NULL;
544 }
545 result = PyString_Format(fmt, aslist);
546 Py_DECREF(fmt);
547 Py_DECREF(aslist);
548 Py_ReprLeave(deque);
549 return result;
550}
551
552static int
553deque_tp_print(PyObject *deque, FILE *fp, int flags)
554{
555 PyObject *it, *item;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000556 char *emit = ""; /* No separator emitted on first pass */
557 char *separator = ", ";
558 int i;
559
560 i = Py_ReprEnter(deque);
561 if (i != 0) {
562 if (i < 0)
563 return i;
564 fputs("[...]", fp);
565 return 0;
566 }
567
568 it = PyObject_GetIter(deque);
569 if (it == NULL)
570 return -1;
571
572 fputs("deque([", fp);
573 while ((item = PyIter_Next(it)) != NULL) {
574 fputs(emit, fp);
575 emit = separator;
576 if (PyObject_Print(item, fp, 0) != 0) {
577 Py_DECREF(item);
578 Py_DECREF(it);
579 Py_ReprLeave(deque);
580 return -1;
581 }
582 Py_DECREF(item);
583 }
584 Py_ReprLeave(deque);
585 Py_DECREF(it);
586 if (PyErr_Occurred())
587 return -1;
588 fputs("])", fp);
589 return 0;
590}
591
Raymond Hettinger738ec902004-02-29 02:15:56 +0000592static PyObject *
593deque_richcompare(PyObject *v, PyObject *w, int op)
594{
595 PyObject *it1=NULL, *it2=NULL, *x, *y;
596 int i, b, vs, ws, minlen, cmp=-1;
597
Raymond Hettinger285cfcc2004-05-18 18:15:03 +0000598 if (!PyObject_TypeCheck(v, &deque_type) ||
599 !PyObject_TypeCheck(w, &deque_type)) {
Raymond Hettinger738ec902004-02-29 02:15:56 +0000600 Py_INCREF(Py_NotImplemented);
601 return Py_NotImplemented;
602 }
603
604 /* Shortcuts */
605 vs = ((dequeobject *)v)->len;
606 ws = ((dequeobject *)w)->len;
607 if (op == Py_EQ) {
608 if (v == w)
609 Py_RETURN_TRUE;
610 if (vs != ws)
611 Py_RETURN_FALSE;
612 }
613 if (op == Py_NE) {
614 if (v == w)
615 Py_RETURN_FALSE;
616 if (vs != ws)
617 Py_RETURN_TRUE;
618 }
619
620 /* Search for the first index where items are different */
621 it1 = PyObject_GetIter(v);
622 if (it1 == NULL)
623 goto done;
624 it2 = PyObject_GetIter(w);
625 if (it2 == NULL)
626 goto done;
627 minlen = (vs < ws) ? vs : ws;
628 for (i=0 ; i < minlen ; i++) {
629 x = PyIter_Next(it1);
630 if (x == NULL)
631 goto done;
632 y = PyIter_Next(it2);
633 if (y == NULL) {
634 Py_DECREF(x);
635 goto done;
636 }
637 b = PyObject_RichCompareBool(x, y, Py_EQ);
638 if (b == 0) {
639 cmp = PyObject_RichCompareBool(x, y, op);
640 Py_DECREF(x);
641 Py_DECREF(y);
642 goto done;
643 }
644 Py_DECREF(x);
645 Py_DECREF(y);
646 if (b == -1)
647 goto done;
648 }
649 /* Elements are equal through minlen. The longest input is the greatest */
650 switch (op) {
651 case Py_LT: cmp = vs < ws; break;
652 case Py_LE: cmp = vs <= ws; break;
653 case Py_EQ: cmp = vs == ws; break;
654 case Py_NE: cmp = vs != ws; break;
655 case Py_GT: cmp = vs > ws; break;
656 case Py_GE: cmp = vs >= ws; break;
657 }
658
659done:
660 Py_XDECREF(it1);
661 Py_XDECREF(it2);
662 if (cmp == 1)
663 Py_RETURN_TRUE;
664 if (cmp == 0)
665 Py_RETURN_FALSE;
666 return NULL;
667}
668
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000669static int
670deque_init(dequeobject *deque, PyObject *args, PyObject *kwds)
671{
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000672 PyObject *iterable = NULL;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000673
674 if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable))
675 return -1;
676
677 if (iterable != NULL) {
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000678 PyObject *rv = deque_extend(deque, iterable);
679 if (rv == NULL)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000680 return -1;
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000681 Py_DECREF(rv);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000682 }
683 return 0;
684}
685
686static PySequenceMethods deque_as_sequence = {
687 (inquiry)deque_len, /* sq_length */
688 0, /* sq_concat */
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000689 0, /* sq_repeat */
690 (intargfunc)deque_item, /* sq_item */
691 0, /* sq_slice */
692 (intobjargproc)deque_ass_item, /* sq_ass_item */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000693};
694
695/* deque object ********************************************************/
696
697static PyObject *deque_iter(dequeobject *deque);
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000698static PyObject *deque_reviter(dequeobject *deque);
699PyDoc_STRVAR(reversed_doc,
700 "D.__reversed__() -- return a reverse iterator over the deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000701
702static PyMethodDef deque_methods[] = {
703 {"append", (PyCFunction)deque_append,
704 METH_O, append_doc},
705 {"appendleft", (PyCFunction)deque_appendleft,
706 METH_O, appendleft_doc},
707 {"clear", (PyCFunction)deque_clearmethod,
708 METH_NOARGS, clear_doc},
709 {"__copy__", (PyCFunction)deque_copy,
710 METH_NOARGS, copy_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000711 {"extend", (PyCFunction)deque_extend,
712 METH_O, extend_doc},
713 {"extendleft", (PyCFunction)deque_extendleft,
714 METH_O, extendleft_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000715 {"pop", (PyCFunction)deque_pop,
716 METH_NOARGS, pop_doc},
717 {"popleft", (PyCFunction)deque_popleft,
718 METH_NOARGS, popleft_doc},
719 {"__reduce__", (PyCFunction)deque_reduce,
720 METH_NOARGS, reduce_doc},
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000721 {"__reversed__", (PyCFunction)deque_reviter,
722 METH_NOARGS, reversed_doc},
Raymond Hettinger5c5eb862004-02-07 21:13:00 +0000723 {"rotate", (PyCFunction)deque_rotate,
724 METH_VARARGS, rotate_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000725 {NULL, NULL} /* sentinel */
726};
727
728PyDoc_STRVAR(deque_doc,
729"deque(iterable) --> deque object\n\
730\n\
731Build an ordered collection accessible from endpoints only.");
732
Neal Norwitz87f10132004-02-29 15:40:53 +0000733static PyTypeObject deque_type = {
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000734 PyObject_HEAD_INIT(NULL)
735 0, /* ob_size */
736 "collections.deque", /* tp_name */
737 sizeof(dequeobject), /* tp_basicsize */
738 0, /* tp_itemsize */
739 /* methods */
740 (destructor)deque_dealloc, /* tp_dealloc */
741 (printfunc)deque_tp_print, /* tp_print */
742 0, /* tp_getattr */
743 0, /* tp_setattr */
744 0, /* tp_compare */
745 (reprfunc)deque_repr, /* tp_repr */
746 0, /* tp_as_number */
747 &deque_as_sequence, /* tp_as_sequence */
748 0, /* tp_as_mapping */
749 deque_nohash, /* tp_hash */
750 0, /* tp_call */
751 0, /* tp_str */
752 PyObject_GenericGetAttr, /* tp_getattro */
753 0, /* tp_setattro */
754 0, /* tp_as_buffer */
Raymond Hettinger691d8052004-05-30 07:26:47 +0000755 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
756 Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000757 deque_doc, /* tp_doc */
Raymond Hettinger0a4977c2004-03-01 23:16:22 +0000758 (traverseproc)deque_traverse, /* tp_traverse */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000759 (inquiry)deque_clear, /* tp_clear */
Raymond Hettinger738ec902004-02-29 02:15:56 +0000760 (richcmpfunc)deque_richcompare, /* tp_richcompare */
Raymond Hettinger691d8052004-05-30 07:26:47 +0000761 offsetof(dequeobject, weakreflist), /* tp_weaklistoffset*/
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000762 (getiterfunc)deque_iter, /* tp_iter */
763 0, /* tp_iternext */
764 deque_methods, /* tp_methods */
765 0, /* tp_members */
766 0, /* tp_getset */
767 0, /* tp_base */
768 0, /* tp_dict */
769 0, /* tp_descr_get */
770 0, /* tp_descr_set */
771 0, /* tp_dictoffset */
772 (initproc)deque_init, /* tp_init */
773 PyType_GenericAlloc, /* tp_alloc */
774 deque_new, /* tp_new */
775 PyObject_GC_Del, /* tp_free */
776};
777
778/*********************** Deque Iterator **************************/
779
780typedef struct {
781 PyObject_HEAD
782 int index;
783 block *b;
784 dequeobject *deque;
785 int len;
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000786 int counter;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000787} dequeiterobject;
788
789PyTypeObject dequeiter_type;
790
791static PyObject *
792deque_iter(dequeobject *deque)
793{
794 dequeiterobject *it;
795
796 it = PyObject_New(dequeiterobject, &dequeiter_type);
797 if (it == NULL)
798 return NULL;
799 it->b = deque->leftblock;
800 it->index = deque->leftindex;
801 Py_INCREF(deque);
802 it->deque = deque;
803 it->len = deque->len;
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000804 it->counter = deque->len;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000805 return (PyObject *)it;
806}
807
808static void
809dequeiter_dealloc(dequeiterobject *dio)
810{
811 Py_XDECREF(dio->deque);
812 dio->ob_type->tp_free(dio);
813}
814
815static PyObject *
816dequeiter_next(dequeiterobject *it)
817{
818 PyObject *item;
819 if (it->b == it->deque->rightblock && it->index > it->deque->rightindex)
820 return NULL;
821
822 if (it->len != it->deque->len) {
823 it->len = -1; /* Make this state sticky */
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000824 it->counter = 0;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000825 PyErr_SetString(PyExc_RuntimeError,
826 "deque changed size during iteration");
827 return NULL;
828 }
829
830 item = it->b->data[it->index];
831 it->index++;
832 if (it->index == BLOCKLEN && it->b->rightlink != NULL) {
833 it->b = it->b->rightlink;
834 it->index = 0;
835 }
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000836 it->counter--;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000837 Py_INCREF(item);
838 return item;
839}
840
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000841static int
842dequeiter_len(dequeiterobject *it)
843{
844 return it->counter;
845}
846
847static PySequenceMethods dequeiter_as_sequence = {
848 (inquiry)dequeiter_len, /* sq_length */
849 0, /* sq_concat */
850};
851
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000852PyTypeObject dequeiter_type = {
853 PyObject_HEAD_INIT(NULL)
854 0, /* ob_size */
855 "deque_iterator", /* tp_name */
856 sizeof(dequeiterobject), /* tp_basicsize */
857 0, /* tp_itemsize */
858 /* methods */
859 (destructor)dequeiter_dealloc, /* tp_dealloc */
860 0, /* tp_print */
861 0, /* tp_getattr */
862 0, /* tp_setattr */
863 0, /* tp_compare */
864 0, /* tp_repr */
865 0, /* tp_as_number */
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000866 &dequeiter_as_sequence, /* tp_as_sequence */
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000867 0, /* tp_as_mapping */
868 0, /* tp_hash */
869 0, /* tp_call */
870 0, /* tp_str */
871 PyObject_GenericGetAttr, /* tp_getattro */
872 0, /* tp_setattro */
873 0, /* tp_as_buffer */
874 Py_TPFLAGS_DEFAULT, /* tp_flags */
875 0, /* tp_doc */
876 0, /* tp_traverse */
877 0, /* tp_clear */
878 0, /* tp_richcompare */
879 0, /* tp_weaklistoffset */
880 PyObject_SelfIter, /* tp_iter */
881 (iternextfunc)dequeiter_next, /* tp_iternext */
882 0,
883};
884
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000885/*********************** Deque Reverse Iterator **************************/
886
887PyTypeObject dequereviter_type;
888
889static PyObject *
890deque_reviter(dequeobject *deque)
891{
892 dequeiterobject *it;
893
894 it = PyObject_New(dequeiterobject, &dequereviter_type);
895 if (it == NULL)
896 return NULL;
897 it->b = deque->rightblock;
898 it->index = deque->rightindex;
899 Py_INCREF(deque);
900 it->deque = deque;
901 it->len = deque->len;
902 it->counter = deque->len;
903 return (PyObject *)it;
904}
905
906static PyObject *
907dequereviter_next(dequeiterobject *it)
908{
909 PyObject *item;
910 if (it->b == it->deque->leftblock && it->index < it->deque->leftindex)
911 return NULL;
912
913 if (it->len != it->deque->len) {
914 it->len = -1; /* Make this state sticky */
Raymond Hettinger7892b1c2004-04-12 18:10:01 +0000915 it->counter = 0;
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000916 PyErr_SetString(PyExc_RuntimeError,
917 "deque changed size during iteration");
918 return NULL;
919 }
920
921 item = it->b->data[it->index];
922 it->index--;
923 if (it->index == -1 && it->b->leftlink != NULL) {
924 it->b = it->b->leftlink;
925 it->index = BLOCKLEN - 1;
926 }
927 it->counter--;
928 Py_INCREF(item);
929 return item;
930}
931
932PyTypeObject dequereviter_type = {
933 PyObject_HEAD_INIT(NULL)
934 0, /* ob_size */
935 "deque_reverse_iterator", /* tp_name */
936 sizeof(dequeiterobject), /* tp_basicsize */
937 0, /* tp_itemsize */
938 /* methods */
939 (destructor)dequeiter_dealloc, /* tp_dealloc */
940 0, /* tp_print */
941 0, /* tp_getattr */
942 0, /* tp_setattr */
943 0, /* tp_compare */
944 0, /* tp_repr */
945 0, /* tp_as_number */
946 &dequeiter_as_sequence, /* tp_as_sequence */
947 0, /* tp_as_mapping */
948 0, /* tp_hash */
949 0, /* tp_call */
950 0, /* tp_str */
951 PyObject_GenericGetAttr, /* tp_getattro */
952 0, /* tp_setattro */
953 0, /* tp_as_buffer */
954 Py_TPFLAGS_DEFAULT, /* tp_flags */
955 0, /* tp_doc */
956 0, /* tp_traverse */
957 0, /* tp_clear */
958 0, /* tp_richcompare */
959 0, /* tp_weaklistoffset */
960 PyObject_SelfIter, /* tp_iter */
961 (iternextfunc)dequereviter_next, /* tp_iternext */
962 0,
963};
964
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000965/* module level code ********************************************************/
966
967PyDoc_STRVAR(module_doc,
968"High performance data structures\n\
969");
970
971PyMODINIT_FUNC
972initcollections(void)
973{
974 PyObject *m;
975
976 m = Py_InitModule3("collections", NULL, module_doc);
977
978 if (PyType_Ready(&deque_type) < 0)
979 return;
980 Py_INCREF(&deque_type);
981 PyModule_AddObject(m, "deque", (PyObject *)&deque_type);
982
983 if (PyType_Ready(&dequeiter_type) < 0)
984 return;
985
Raymond Hettinger1e5809f2004-03-18 11:04:57 +0000986 if (PyType_Ready(&dequereviter_type) < 0)
987 return;
988
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000989 return;
990}