blob: 3533fc5e2f279e2dfe0bbff253c70f92e4f04c59 [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
37static PyObject *
38deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
39{
40 dequeobject *deque;
41 block *b;
42
43 /* create dequeobject structure */
44 deque = (dequeobject *)type->tp_alloc(type, 0);
45 if (deque == NULL)
46 return NULL;
47
48 b = newblock(NULL, NULL);
49 if (b == NULL) {
50 Py_DECREF(deque);
51 return NULL;
52 }
53
54 deque->leftblock = b;
55 deque->rightblock = b;
56 deque->leftindex = BLOCKLEN / 2 + 1;
57 deque->rightindex = BLOCKLEN / 2;
58 deque->len = 0;
59
60 return (PyObject *)deque;
61}
62
63static PyObject *
64deque_append(dequeobject *deque, PyObject *item)
65{
66 deque->rightindex++;
67 deque->len++;
68 if (deque->rightindex == BLOCKLEN) {
69 block *b = newblock(deque->rightblock, NULL);
70 if (b == NULL)
71 return NULL;
72 assert(deque->rightblock->rightlink == NULL);
73 deque->rightblock->rightlink = b;
74 deque->rightblock = b;
75 deque->rightindex = 0;
76 }
77 Py_INCREF(item);
78 deque->rightblock->data[deque->rightindex] = item;
79 Py_RETURN_NONE;
80}
81
82PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque.");
83
84static PyObject *
85deque_appendleft(dequeobject *deque, PyObject *item)
86{
87 deque->leftindex--;
88 deque->len++;
89 if (deque->leftindex == -1) {
90 block *b = newblock(NULL, deque->leftblock);
91 if (b == NULL)
92 return NULL;
93 assert(deque->leftblock->leftlink == NULL);
94 deque->leftblock->leftlink = b;
95 deque->leftblock = b;
96 deque->leftindex = BLOCKLEN - 1;
97 }
98 Py_INCREF(item);
99 deque->leftblock->data[deque->leftindex] = item;
100 Py_RETURN_NONE;
101}
102
103PyDoc_STRVAR(appendleft_doc, "Add an element to the left side of the deque.");
104
105static PyObject *
106deque_pop(dequeobject *deque, PyObject *unused)
107{
108 PyObject *item;
109 block *prevblock;
110
111 if (deque->len == 0) {
Raymond Hettingerd0814eb2004-01-29 07:29:32 +0000112 PyErr_SetString(PyExc_LookupError, "pop from an empty deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000113 return NULL;
114 }
115 item = deque->rightblock->data[deque->rightindex];
116 deque->rightindex--;
117 deque->len--;
118
119 if (deque->rightindex == -1) {
120 if (deque->len == 0) {
121 assert(deque->leftblock == deque->rightblock);
122 assert(deque->leftindex == deque->rightindex+1);
123 /* re-center instead of freeing a block */
124 deque->leftindex = BLOCKLEN / 2 + 1;
125 deque->rightindex = BLOCKLEN / 2;
126 } else {
127 prevblock = deque->rightblock->leftlink;
128 assert(deque->leftblock != deque->rightblock);
129 PyMem_Free(deque->rightblock);
130 prevblock->rightlink = NULL;
131 deque->rightblock = prevblock;
132 deque->rightindex = BLOCKLEN - 1;
133 }
134 }
135 return item;
136}
137
138PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element.");
139
140static PyObject *
141deque_popleft(dequeobject *deque, PyObject *unused)
142{
143 PyObject *item;
144 block *prevblock;
145
146 if (deque->len == 0) {
Raymond Hettingerd0814eb2004-01-29 07:29:32 +0000147 PyErr_SetString(PyExc_LookupError, "pop from an empty deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000148 return NULL;
149 }
150 item = deque->leftblock->data[deque->leftindex];
151 deque->leftindex++;
152 deque->len--;
153
154 if (deque->leftindex == BLOCKLEN) {
155 if (deque->len == 0) {
156 assert(deque->leftblock == deque->rightblock);
157 assert(deque->leftindex == deque->rightindex+1);
158 /* re-center instead of freeing a block */
159 deque->leftindex = BLOCKLEN / 2 + 1;
160 deque->rightindex = BLOCKLEN / 2;
161 } else {
162 assert(deque->leftblock != deque->rightblock);
163 prevblock = deque->leftblock->rightlink;
164 assert(deque->leftblock != NULL);
165 PyMem_Free(deque->leftblock);
166 assert(prevblock != NULL);
167 prevblock->leftlink = NULL;
168 deque->leftblock = prevblock;
169 deque->leftindex = 0;
170 }
171 }
172 return item;
173}
174
175PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element.");
176
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000177static PyObject *
178deque_extend(dequeobject *deque, PyObject *iterable)
179{
180 PyObject *it, *item;
181
182 it = PyObject_GetIter(iterable);
183 if (it == NULL)
184 return NULL;
185
186 while ((item = PyIter_Next(it)) != NULL) {
187 deque->rightindex++;
188 deque->len++;
189 if (deque->rightindex == BLOCKLEN) {
190 block *b = newblock(deque->rightblock, NULL);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000191 if (b == NULL) {
192 Py_DECREF(item);
193 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000194 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000195 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000196 assert(deque->rightblock->rightlink == NULL);
197 deque->rightblock->rightlink = b;
198 deque->rightblock = b;
199 deque->rightindex = 0;
200 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000201 deque->rightblock->data[deque->rightindex] = item;
202 }
203 Py_DECREF(it);
204 if (PyErr_Occurred())
205 return NULL;
206 Py_RETURN_NONE;
207}
208
209PyDoc_STRVAR(extend_doc,
210"Extend the right side of the deque with elements from the iterable");
211
212static PyObject *
213deque_extendleft(dequeobject *deque, PyObject *iterable)
214{
215 PyObject *it, *item;
216
217 it = PyObject_GetIter(iterable);
218 if (it == NULL)
219 return NULL;
220
221 while ((item = PyIter_Next(it)) != NULL) {
222 deque->leftindex--;
223 deque->len++;
224 if (deque->leftindex == -1) {
225 block *b = newblock(NULL, deque->leftblock);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000226 if (b == NULL) {
227 Py_DECREF(item);
228 Py_DECREF(it);
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000229 return NULL;
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000230 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000231 assert(deque->leftblock->leftlink == NULL);
232 deque->leftblock->leftlink = b;
233 deque->leftblock = b;
234 deque->leftindex = BLOCKLEN - 1;
235 }
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000236 deque->leftblock->data[deque->leftindex] = item;
237 }
238 Py_DECREF(it);
239 if (PyErr_Occurred())
240 return NULL;
241 Py_RETURN_NONE;
242}
243
244PyDoc_STRVAR(extendleft_doc,
245"Extend the left side of the deque with elements from the iterable");
246
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000247static int
248deque_len(dequeobject *deque)
249{
250 return deque->len;
251}
252
253static int
254deque_clear(dequeobject *deque)
255{
256 PyObject *item;
257
258 while (deque_len(deque)) {
259 item = deque_pop(deque, NULL);
260 if (item == NULL)
261 return -1;
262 Py_DECREF(item);
263 }
264 assert(deque->leftblock == deque->rightblock &&
265 deque->leftindex > deque->rightindex);
266 return 0;
267}
268
269static PyObject *
270deque_clearmethod(dequeobject *deque)
271{
272 if (deque_clear(deque) == -1)
273 return NULL;
274 Py_RETURN_NONE;
275}
276
277PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
278
279static void
280deque_dealloc(dequeobject *deque)
281{
282 PyObject_GC_UnTrack(deque);
283 if (deque->leftblock != NULL) {
284 int err = deque_clear(deque);
285 assert(err == 0);
286 assert(deque->leftblock != NULL);
287 PyMem_Free(deque->leftblock);
288 }
289 deque->leftblock = NULL;
290 deque->rightblock = NULL;
291 deque->ob_type->tp_free(deque);
292}
293
294static int
295set_traverse(dequeobject *deque, visitproc visit, void *arg)
296{
297 block * b = deque->leftblock;
298 int index = deque->leftindex;
299 int err;
300 PyObject *item;
301
302 while (b != deque->rightblock || index <= deque->rightindex) {
303 item = b->data[index];
304 index++;
305 if (index == BLOCKLEN && b->rightlink != NULL) {
306 b = b->rightlink;
307 index = 0;
308 }
309 err = visit(item, arg);
310 if (err)
311 return err;
312 }
313 return 0;
314}
315
316static long
317deque_nohash(PyObject *self)
318{
319 PyErr_SetString(PyExc_TypeError, "deque objects are unhashable");
320 return -1;
321}
322
323static PyObject *
324deque_copy(PyObject *deque)
325{
326 return PyObject_CallFunctionObjArgs((PyObject *)(deque->ob_type),
327 deque, NULL);
328}
329
330PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
331
332static PyObject *
333deque_reduce(dequeobject *deque)
334{
335 PyObject *seq, *args, *result;
336
337 seq = PySequence_Tuple((PyObject *)deque);
338 if (seq == NULL)
339 return NULL;
340 args = PyTuple_Pack(1, seq);
341 if (args == NULL) {
342 Py_DECREF(seq);
343 return NULL;
344 }
345 result = PyTuple_Pack(2, deque->ob_type, args);
346 Py_DECREF(seq);
347 Py_DECREF(args);
348 return result;
349}
350
351PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
352
353static PyObject *
354deque_repr(PyObject *deque)
355{
356 PyObject *aslist, *result, *fmt;
357 int i;
358
359 i = Py_ReprEnter(deque);
360 if (i != 0) {
361 if (i < 0)
362 return NULL;
363 return PyString_FromString("[...]");
364 }
365
366 aslist = PySequence_List(deque);
367 if (aslist == NULL) {
368 Py_ReprLeave(deque);
369 return NULL;
370 }
371
372 fmt = PyString_FromString("deque(%r)");
373 if (fmt == NULL) {
374 Py_DECREF(aslist);
375 Py_ReprLeave(deque);
376 return NULL;
377 }
378 result = PyString_Format(fmt, aslist);
379 Py_DECREF(fmt);
380 Py_DECREF(aslist);
381 Py_ReprLeave(deque);
382 return result;
383}
384
385static int
386deque_tp_print(PyObject *deque, FILE *fp, int flags)
387{
388 PyObject *it, *item;
389 int pos=0;
390 char *emit = ""; /* No separator emitted on first pass */
391 char *separator = ", ";
392 int i;
393
394 i = Py_ReprEnter(deque);
395 if (i != 0) {
396 if (i < 0)
397 return i;
398 fputs("[...]", fp);
399 return 0;
400 }
401
402 it = PyObject_GetIter(deque);
403 if (it == NULL)
404 return -1;
405
406 fputs("deque([", fp);
407 while ((item = PyIter_Next(it)) != NULL) {
408 fputs(emit, fp);
409 emit = separator;
410 if (PyObject_Print(item, fp, 0) != 0) {
411 Py_DECREF(item);
412 Py_DECREF(it);
413 Py_ReprLeave(deque);
414 return -1;
415 }
416 Py_DECREF(item);
417 }
418 Py_ReprLeave(deque);
419 Py_DECREF(it);
420 if (PyErr_Occurred())
421 return -1;
422 fputs("])", fp);
423 return 0;
424}
425
426static int
427deque_init(dequeobject *deque, PyObject *args, PyObject *kwds)
428{
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000429 PyObject *iterable = NULL;
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000430
431 if (!PyArg_UnpackTuple(args, "deque", 0, 1, &iterable))
432 return -1;
433
434 if (iterable != NULL) {
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000435 PyObject *rv = deque_extend(deque, iterable);
436 if (rv == NULL)
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000437 return -1;
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000438 Py_DECREF(rv);
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000439 }
440 return 0;
441}
442
443static PySequenceMethods deque_as_sequence = {
444 (inquiry)deque_len, /* sq_length */
445 0, /* sq_concat */
446};
447
448/* deque object ********************************************************/
449
450static PyObject *deque_iter(dequeobject *deque);
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000451static PyObject *deque_reviter(dequeobject *deque);
452PyDoc_STRVAR(reversed_doc,
453 "D.__reversed__() -- return a reverse iterator over the deque");
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000454
455static PyMethodDef deque_methods[] = {
456 {"append", (PyCFunction)deque_append,
457 METH_O, append_doc},
458 {"appendleft", (PyCFunction)deque_appendleft,
459 METH_O, appendleft_doc},
460 {"clear", (PyCFunction)deque_clearmethod,
461 METH_NOARGS, clear_doc},
462 {"__copy__", (PyCFunction)deque_copy,
463 METH_NOARGS, copy_doc},
464 {"pop", (PyCFunction)deque_pop,
465 METH_NOARGS, pop_doc},
466 {"popleft", (PyCFunction)deque_popleft,
467 METH_NOARGS, popleft_doc},
468 {"__reduce__", (PyCFunction)deque_reduce,
469 METH_NOARGS, reduce_doc},
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000470 {"__reversed__", (PyCFunction)deque_reviter,
471 METH_NOARGS, reversed_doc},
Raymond Hettinger3ba85c22004-02-06 19:04:56 +0000472 {"extend", (PyCFunction)deque_extend,
473 METH_O, extend_doc},
474 {"extendleft", (PyCFunction)deque_extendleft,
475 METH_O, extendleft_doc},
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000476 {NULL, NULL} /* sentinel */
477};
478
479PyDoc_STRVAR(deque_doc,
480"deque(iterable) --> deque object\n\
481\n\
482Build an ordered collection accessible from endpoints only.");
483
484PyTypeObject deque_type = {
485 PyObject_HEAD_INIT(NULL)
486 0, /* ob_size */
487 "collections.deque", /* tp_name */
488 sizeof(dequeobject), /* tp_basicsize */
489 0, /* tp_itemsize */
490 /* methods */
491 (destructor)deque_dealloc, /* tp_dealloc */
492 (printfunc)deque_tp_print, /* tp_print */
493 0, /* tp_getattr */
494 0, /* tp_setattr */
495 0, /* tp_compare */
496 (reprfunc)deque_repr, /* tp_repr */
497 0, /* tp_as_number */
498 &deque_as_sequence, /* tp_as_sequence */
499 0, /* tp_as_mapping */
500 deque_nohash, /* tp_hash */
501 0, /* tp_call */
502 0, /* tp_str */
503 PyObject_GenericGetAttr, /* tp_getattro */
504 0, /* tp_setattro */
505 0, /* tp_as_buffer */
506 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
507 deque_doc, /* tp_doc */
508 (traverseproc)set_traverse, /* tp_traverse */
509 (inquiry)deque_clear, /* tp_clear */
510 0, /* tp_richcompare */
511 0, /* tp_weaklistoffset*/
512 (getiterfunc)deque_iter, /* tp_iter */
513 0, /* tp_iternext */
514 deque_methods, /* tp_methods */
515 0, /* tp_members */
516 0, /* tp_getset */
517 0, /* tp_base */
518 0, /* tp_dict */
519 0, /* tp_descr_get */
520 0, /* tp_descr_set */
521 0, /* tp_dictoffset */
522 (initproc)deque_init, /* tp_init */
523 PyType_GenericAlloc, /* tp_alloc */
524 deque_new, /* tp_new */
525 PyObject_GC_Del, /* tp_free */
526};
527
528/*********************** Deque Iterator **************************/
529
530typedef struct {
531 PyObject_HEAD
532 int index;
533 block *b;
534 dequeobject *deque;
535 int len;
536} dequeiterobject;
537
538PyTypeObject dequeiter_type;
539
540static PyObject *
541deque_iter(dequeobject *deque)
542{
543 dequeiterobject *it;
544
545 it = PyObject_New(dequeiterobject, &dequeiter_type);
546 if (it == NULL)
547 return NULL;
548 it->b = deque->leftblock;
549 it->index = deque->leftindex;
550 Py_INCREF(deque);
551 it->deque = deque;
552 it->len = deque->len;
553 return (PyObject *)it;
554}
555
556static void
557dequeiter_dealloc(dequeiterobject *dio)
558{
559 Py_XDECREF(dio->deque);
560 dio->ob_type->tp_free(dio);
561}
562
563static PyObject *
564dequeiter_next(dequeiterobject *it)
565{
566 PyObject *item;
567 if (it->b == it->deque->rightblock && it->index > it->deque->rightindex)
568 return NULL;
569
570 if (it->len != it->deque->len) {
571 it->len = -1; /* Make this state sticky */
572 PyErr_SetString(PyExc_RuntimeError,
573 "deque changed size during iteration");
574 return NULL;
575 }
576
577 item = it->b->data[it->index];
578 it->index++;
579 if (it->index == BLOCKLEN && it->b->rightlink != NULL) {
580 it->b = it->b->rightlink;
581 it->index = 0;
582 }
583 Py_INCREF(item);
584 return item;
585}
586
587PyTypeObject dequeiter_type = {
588 PyObject_HEAD_INIT(NULL)
589 0, /* ob_size */
590 "deque_iterator", /* tp_name */
591 sizeof(dequeiterobject), /* tp_basicsize */
592 0, /* tp_itemsize */
593 /* methods */
594 (destructor)dequeiter_dealloc, /* tp_dealloc */
595 0, /* tp_print */
596 0, /* tp_getattr */
597 0, /* tp_setattr */
598 0, /* tp_compare */
599 0, /* tp_repr */
600 0, /* tp_as_number */
601 0, /* tp_as_sequence */
602 0, /* tp_as_mapping */
603 0, /* tp_hash */
604 0, /* tp_call */
605 0, /* tp_str */
606 PyObject_GenericGetAttr, /* tp_getattro */
607 0, /* tp_setattro */
608 0, /* tp_as_buffer */
609 Py_TPFLAGS_DEFAULT, /* tp_flags */
610 0, /* tp_doc */
611 0, /* tp_traverse */
612 0, /* tp_clear */
613 0, /* tp_richcompare */
614 0, /* tp_weaklistoffset */
615 PyObject_SelfIter, /* tp_iter */
616 (iternextfunc)dequeiter_next, /* tp_iternext */
617 0,
618};
619
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000620/*********************** Deque Reverse Iterator **************************/
621
622PyTypeObject dequereviter_type;
623
624static PyObject *
625deque_reviter(dequeobject *deque)
626{
627 dequeiterobject *it;
628
629 it = PyObject_New(dequeiterobject, &dequereviter_type);
630 if (it == NULL)
631 return NULL;
632 it->b = deque->rightblock;
633 it->index = deque->rightindex;
634 Py_INCREF(deque);
635 it->deque = deque;
636 it->len = deque->len;
637 return (PyObject *)it;
638}
639
640static PyObject *
641dequereviter_next(dequeiterobject *it)
642{
643 PyObject *item;
644 if (it->b == it->deque->leftblock && it->index < it->deque->leftindex)
645 return NULL;
646
647 if (it->len != it->deque->len) {
648 it->len = -1; /* Make this state sticky */
649 PyErr_SetString(PyExc_RuntimeError,
650 "deque changed size during iteration");
651 return NULL;
652 }
653
654 item = it->b->data[it->index];
655 it->index--;
656 if (it->index == -1 && it->b->leftlink != NULL) {
657 it->b = it->b->leftlink;
658 it->index = BLOCKLEN - 1;
659 }
660 Py_INCREF(item);
661 return item;
662}
663
664PyTypeObject dequereviter_type = {
665 PyObject_HEAD_INIT(NULL)
666 0, /* ob_size */
667 "deque_reverse_iterator", /* tp_name */
668 sizeof(dequeiterobject), /* tp_basicsize */
669 0, /* tp_itemsize */
670 /* methods */
671 (destructor)dequeiter_dealloc, /* tp_dealloc */
672 0, /* tp_print */
673 0, /* tp_getattr */
674 0, /* tp_setattr */
675 0, /* tp_compare */
676 0, /* tp_repr */
677 0, /* tp_as_number */
678 0, /* tp_as_sequence */
679 0, /* tp_as_mapping */
680 0, /* tp_hash */
681 0, /* tp_call */
682 0, /* tp_str */
683 PyObject_GenericGetAttr, /* tp_getattro */
684 0, /* tp_setattro */
685 0, /* tp_as_buffer */
686 Py_TPFLAGS_DEFAULT, /* tp_flags */
687 0, /* tp_doc */
688 0, /* tp_traverse */
689 0, /* tp_clear */
690 0, /* tp_richcompare */
691 0, /* tp_weaklistoffset */
692 PyObject_SelfIter, /* tp_iter */
693 (iternextfunc)dequereviter_next, /* tp_iternext */
694 0,
695};
696
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000697/* module level code ********************************************************/
698
699PyDoc_STRVAR(module_doc,
700"High performance data structures\n\
701");
702
703PyMODINIT_FUNC
704initcollections(void)
705{
706 PyObject *m;
707
708 m = Py_InitModule3("collections", NULL, module_doc);
709
710 if (PyType_Ready(&deque_type) < 0)
711 return;
712 Py_INCREF(&deque_type);
713 PyModule_AddObject(m, "deque", (PyObject *)&deque_type);
714
715 if (PyType_Ready(&dequeiter_type) < 0)
716 return;
717
Raymond Hettingerc058fd12004-02-07 02:45:22 +0000718 if (PyType_Ready(&dequereviter_type) < 0)
719 return;
720
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000721 return;
722}