blob: 5811f406e483d3860f0b308aec7fd0c7adc2ec3b [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* List object implementation */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000028
29object *
30newlistobject(size)
31 int size;
32{
33 int i;
34 listobject *op;
35 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000036 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000037 return NULL;
38 }
39 op = (listobject *) malloc(sizeof(listobject));
40 if (op == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000041 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000042 }
43 if (size <= 0) {
44 op->ob_item = NULL;
45 }
46 else {
47 op->ob_item = (object **) malloc(size * sizeof(object *));
48 if (op->ob_item == NULL) {
49 free((ANY *)op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000050 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000051 }
52 }
53 NEWREF(op);
54 op->ob_type = &Listtype;
55 op->ob_size = size;
56 for (i = 0; i < size; i++)
57 op->ob_item[i] = NULL;
58 return (object *) op;
59}
60
61int
62getlistsize(op)
63 object *op;
64{
65 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000066 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000067 return -1;
68 }
69 else
70 return ((listobject *)op) -> ob_size;
71}
72
73object *
74getlistitem(op, i)
75 object *op;
76 int i;
77{
78 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000079 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000080 return NULL;
81 }
82 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000083 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000084 return NULL;
85 }
86 return ((listobject *)op) -> ob_item[i];
87}
88
89int
90setlistitem(op, i, newitem)
91 register object *op;
92 register int i;
93 register object *newitem;
94{
95 register object *olditem;
96 if (!is_listobject(op)) {
Guido van Rossume6f7d181991-10-20 20:20:40 +000097 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000098 err_badcall();
99 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000100 }
101 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossume6f7d181991-10-20 20:20:40 +0000102 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000103 err_setstr(IndexError, "list assignment index out of range");
104 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000105 }
106 olditem = ((listobject *)op) -> ob_item[i];
107 ((listobject *)op) -> ob_item[i] = newitem;
Guido van Rossume6f7d181991-10-20 20:20:40 +0000108 XDECREF(olditem);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 return 0;
110}
111
112static int
113ins1(self, where, v)
114 listobject *self;
115 int where;
116 object *v;
117{
118 int i;
119 object **items;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000120 if (v == NULL) {
121 err_badcall();
122 return -1;
123 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000124 items = self->ob_item;
125 RESIZE(items, object *, self->ob_size+1);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000126 if (items == NULL) {
127 err_nomem();
128 return -1;
129 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130 if (where < 0)
131 where = 0;
132 if (where > self->ob_size)
133 where = self->ob_size;
134 for (i = self->ob_size; --i >= where; )
135 items[i+1] = items[i];
136 INCREF(v);
137 items[where] = v;
138 self->ob_item = items;
139 self->ob_size++;
140 return 0;
141}
142
143int
144inslistitem(op, where, newitem)
145 object *op;
146 int where;
147 object *newitem;
148{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000149 if (!is_listobject(op)) {
150 err_badcall();
151 return -1;
152 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153 return ins1((listobject *)op, where, newitem);
154}
155
156int
157addlistitem(op, newitem)
158 object *op;
159 object *newitem;
160{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000161 if (!is_listobject(op)) {
162 err_badcall();
163 return -1;
164 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165 return ins1((listobject *)op,
166 (int) ((listobject *)op)->ob_size, newitem);
167}
168
169/* Methods */
170
171static void
172list_dealloc(op)
173 listobject *op;
174{
175 int i;
176 for (i = 0; i < op->ob_size; i++) {
Guido van Rossume6f7d181991-10-20 20:20:40 +0000177 XDECREF(op->ob_item[i]);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000178 }
179 if (op->ob_item != NULL)
180 free((ANY *)op->ob_item);
181 free((ANY *)op);
182}
183
Guido van Rossum90933611991-06-07 16:10:43 +0000184static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000185list_print(op, fp, flags)
186 listobject *op;
187 FILE *fp;
188 int flags;
189{
190 int i;
191 fprintf(fp, "[");
Guido van Rossum90933611991-06-07 16:10:43 +0000192 for (i = 0; i < op->ob_size; i++) {
193 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000194 fprintf(fp, ", ");
Guido van Rossum90933611991-06-07 16:10:43 +0000195 if (printobject(op->ob_item[i], fp, flags) != 0)
196 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000197 }
198 fprintf(fp, "]");
Guido van Rossum90933611991-06-07 16:10:43 +0000199 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000200}
201
202object *
203list_repr(v)
204 listobject *v;
205{
206 object *s, *t, *comma;
207 int i;
208 s = newstringobject("[");
209 comma = newstringobject(", ");
210 for (i = 0; i < v->ob_size && s != NULL; i++) {
211 if (i > 0)
212 joinstring(&s, comma);
213 t = reprobject(v->ob_item[i]);
214 joinstring(&s, t);
215 DECREF(t);
216 }
217 DECREF(comma);
218 t = newstringobject("]");
219 joinstring(&s, t);
220 DECREF(t);
221 return s;
222}
223
224static int
225list_compare(v, w)
226 listobject *v, *w;
227{
228 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
229 int i;
230 for (i = 0; i < len; i++) {
231 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
232 if (cmp != 0)
233 return cmp;
234 }
235 return v->ob_size - w->ob_size;
236}
237
238static int
239list_length(a)
240 listobject *a;
241{
242 return a->ob_size;
243}
244
245static object *
246list_item(a, i)
247 listobject *a;
248 int i;
249{
250 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000251 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000252 return NULL;
253 }
254 INCREF(a->ob_item[i]);
255 return a->ob_item[i];
256}
257
258static object *
259list_slice(a, ilow, ihigh)
260 listobject *a;
261 int ilow, ihigh;
262{
263 listobject *np;
264 int i;
265 if (ilow < 0)
266 ilow = 0;
267 else if (ilow > a->ob_size)
268 ilow = a->ob_size;
269 if (ihigh < 0)
270 ihigh = 0;
271 if (ihigh < ilow)
272 ihigh = ilow;
273 else if (ihigh > a->ob_size)
274 ihigh = a->ob_size;
275 np = (listobject *) newlistobject(ihigh - ilow);
276 if (np == NULL)
277 return NULL;
278 for (i = ilow; i < ihigh; i++) {
279 object *v = a->ob_item[i];
280 INCREF(v);
281 np->ob_item[i - ilow] = v;
282 }
283 return (object *)np;
284}
285
286static object *
287list_concat(a, bb)
288 listobject *a;
289 object *bb;
290{
291 int size;
292 int i;
293 listobject *np;
294 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000295 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000296 return NULL;
297 }
298#define b ((listobject *)bb)
299 size = a->ob_size + b->ob_size;
300 np = (listobject *) newlistobject(size);
301 if (np == NULL) {
Guido van Rossum90933611991-06-07 16:10:43 +0000302 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000303 }
304 for (i = 0; i < a->ob_size; i++) {
305 object *v = a->ob_item[i];
306 INCREF(v);
307 np->ob_item[i] = v;
308 }
309 for (i = 0; i < b->ob_size; i++) {
310 object *v = b->ob_item[i];
311 INCREF(v);
312 np->ob_item[i + a->ob_size] = v;
313 }
314 return (object *)np;
315#undef b
316}
317
Guido van Rossumed98d481991-03-06 13:07:53 +0000318static object *
319list_repeat(a, n)
320 listobject *a;
321 int n;
322{
323 int i, j;
324 int size;
325 listobject *np;
326 object **p;
327 if (n < 0)
328 n = 0;
329 size = a->ob_size * n;
330 np = (listobject *) newlistobject(size);
331 if (np == NULL)
332 return NULL;
333 p = np->ob_item;
334 for (i = 0; i < n; i++) {
335 for (j = 0; j < a->ob_size; j++) {
336 *p = a->ob_item[j];
337 INCREF(*p);
338 p++;
339 }
340 }
341 return (object *) np;
342}
343
Guido van Rossumbfe14c51991-04-16 08:41:06 +0000344/* XXX The following function has a bug: don't try assigning a
345 XXX list object to a slice of itself (e.g., a[:1] = a). */
346
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000347static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000348list_ass_slice(a, ilow, ihigh, v)
349 listobject *a;
350 int ilow, ihigh;
351 object *v;
352{
353 object **item;
354 int n; /* Size of replacement list */
355 int d; /* Change in size */
356 int k; /* Loop index */
357#define b ((listobject *)v)
358 if (v == NULL)
359 n = 0;
Guido van Rossum32dffaa1991-12-24 13:27:34 +0000360 else if (is_listobject(v)) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000361 n = b->ob_size;
Guido van Rossum32dffaa1991-12-24 13:27:34 +0000362 if (a == b) {
363 /* Special case "a[i:j] = a" -- copy b first */
364 int ret;
365 v = list_slice(b, 0, n);
366 ret = list_ass_slice(a, ilow, ihigh, v);
367 DECREF(v);
368 return ret;
369 }
370 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000371 else {
372 err_badarg();
373 return -1;
374 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000375 if (ilow < 0)
376 ilow = 0;
377 else if (ilow > a->ob_size)
378 ilow = a->ob_size;
379 if (ihigh < 0)
380 ihigh = 0;
381 if (ihigh < ilow)
382 ihigh = ilow;
383 else if (ihigh > a->ob_size)
384 ihigh = a->ob_size;
385 item = a->ob_item;
386 d = n - (ihigh-ilow);
387 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
388 for (k = ilow; k < ihigh; k++)
389 DECREF(item[k]);
390 if (d < 0) {
391 for (/*k = ihigh*/; k < a->ob_size; k++)
392 item[k+d] = item[k];
393 a->ob_size += d;
394 RESIZE(item, object *, a->ob_size); /* Can't fail */
395 a->ob_item = item;
396 }
397 }
398 else { /* Insert d items; DECREF ihigh-ilow items */
399 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000400 if (item == NULL) {
401 err_nomem();
402 return -1;
403 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000404 for (k = a->ob_size; --k >= ihigh; )
405 item[k+d] = item[k];
406 for (/*k = ihigh-1*/; k >= ilow; --k)
407 DECREF(item[k]);
408 a->ob_item = item;
409 a->ob_size += d;
410 }
411 for (k = 0; k < n; k++, ilow++) {
412 object *w = b->ob_item[k];
413 INCREF(w);
414 item[ilow] = w;
415 }
416 return 0;
417#undef b
418}
419
Guido van Rossum4a450d01991-04-03 19:05:18 +0000420static int
421list_ass_item(a, i, v)
422 listobject *a;
423 int i;
424 object *v;
425{
426 if (i < 0 || i >= a->ob_size) {
427 err_setstr(IndexError, "list assignment index out of range");
428 return -1;
429 }
430 if (v == NULL)
431 return list_ass_slice(a, i, i+1, v);
432 INCREF(v);
433 DECREF(a->ob_item[i]);
434 a->ob_item[i] = v;
435 return 0;
436}
437
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000438static object *
439ins(self, where, v)
440 listobject *self;
441 int where;
442 object *v;
443{
444 if (ins1(self, where, v) != 0)
445 return NULL;
446 INCREF(None);
447 return None;
448}
449
450static object *
451listinsert(self, args)
452 listobject *self;
453 object *args;
454{
455 int i;
456 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000457 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000458 return NULL;
459 }
460 if (!getintarg(gettupleitem(args, 0), &i))
461 return NULL;
462 return ins(self, i, gettupleitem(args, 1));
463}
464
465static object *
466listappend(self, args)
467 listobject *self;
468 object *args;
469{
470 return ins(self, (int) self->ob_size, args);
471}
472
473static int
474cmp(v, w)
475 char *v, *w;
476{
477 return cmpobject(* (object **) v, * (object **) w);
478}
479
480static object *
481listsort(self, args)
482 listobject *self;
483 object *args;
484{
485 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000486 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000487 return NULL;
488 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000489 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000490 if (self->ob_size > 1)
491 qsort((char *)self->ob_item,
492 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000493 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000494 return NULL;
495 INCREF(None);
496 return None;
497}
498
Guido van Rossumed98d481991-03-06 13:07:53 +0000499static object *
500listreverse(self, args)
501 listobject *self;
502 object *args;
503{
504 register object **p, **q;
505 register object *tmp;
506
507 if (args != NULL) {
508 err_badarg();
509 return NULL;
510 }
511
512 if (self->ob_size > 1) {
513 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
514 p < q; p++, q--) {
515 tmp = *p;
516 *p = *q;
517 *q = tmp;
518 }
519 }
520
521 INCREF(None);
522 return None;
523}
524
Guido van Rossum84c76f51990-10-30 13:32:20 +0000525int
526sortlist(v)
527 object *v;
528{
529 if (v == NULL || !is_listobject(v)) {
530 err_badcall();
531 return -1;
532 }
533 v = listsort((listobject *)v, (object *)NULL);
534 if (v == NULL)
535 return -1;
536 DECREF(v);
537 return 0;
538}
539
Guido van Rossumed98d481991-03-06 13:07:53 +0000540static object *
541listindex(self, args)
542 listobject *self;
543 object *args;
544{
545 int i;
546
547 if (args == NULL) {
548 err_badarg();
549 return NULL;
550 }
551 for (i = 0; i < self->ob_size; i++) {
552 if (cmpobject(self->ob_item[i], args) == 0)
553 return newintobject(i);
554 }
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000555 err_setstr(ValueError, "list.index(x): x not in list");
Guido van Rossumed98d481991-03-06 13:07:53 +0000556 return NULL;
557}
558
559static object *
Guido van Rossume6f7d181991-10-20 20:20:40 +0000560listcount(self, args)
561 listobject *self;
562 object *args;
563{
564 int count = 0;
565 int i;
566
567 if (args == NULL) {
568 err_badarg();
569 return NULL;
570 }
571 for (i = 0; i < self->ob_size; i++) {
572 if (cmpobject(self->ob_item[i], args) == 0)
573 count++;
574 }
575 return newintobject((long)count);
576}
577
578static object *
Guido van Rossumed98d481991-03-06 13:07:53 +0000579listremove(self, args)
580 listobject *self;
581 object *args;
582{
583 int i;
584
585 if (args == NULL) {
586 err_badarg();
587 return NULL;
588 }
589 for (i = 0; i < self->ob_size; i++) {
590 if (cmpobject(self->ob_item[i], args) == 0) {
591 if (list_ass_slice(self, i, i+1, (object *)NULL) != 0)
592 return NULL;
593 INCREF(None);
594 return None;
595 }
596
597 }
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000598 err_setstr(ValueError, "list.remove(x): x not in list");
Guido van Rossumed98d481991-03-06 13:07:53 +0000599 return NULL;
600}
601
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000602static struct methodlist list_methods[] = {
603 {"append", listappend},
Guido van Rossume6f7d181991-10-20 20:20:40 +0000604 {"count", listcount},
Guido van Rossumed98d481991-03-06 13:07:53 +0000605 {"index", listindex},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000606 {"insert", listinsert},
607 {"sort", listsort},
Guido van Rossumed98d481991-03-06 13:07:53 +0000608 {"remove", listremove},
609 {"reverse", listreverse},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000610 {NULL, NULL} /* sentinel */
611};
612
613static object *
614list_getattr(f, name)
615 listobject *f;
616 char *name;
617{
618 return findmethod(list_methods, (object *)f, name);
619}
620
621static sequence_methods list_as_sequence = {
622 list_length, /*sq_length*/
623 list_concat, /*sq_concat*/
Guido van Rossumed98d481991-03-06 13:07:53 +0000624 list_repeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000625 list_item, /*sq_item*/
626 list_slice, /*sq_slice*/
627 list_ass_item, /*sq_ass_item*/
628 list_ass_slice, /*sq_ass_slice*/
629};
630
631typeobject Listtype = {
632 OB_HEAD_INIT(&Typetype)
633 0,
634 "list",
635 sizeof(listobject),
636 0,
637 list_dealloc, /*tp_dealloc*/
638 list_print, /*tp_print*/
639 list_getattr, /*tp_getattr*/
640 0, /*tp_setattr*/
641 list_compare, /*tp_compare*/
642 list_repr, /*tp_repr*/
643 0, /*tp_as_number*/
644 &list_as_sequence, /*tp_as_sequence*/
645 0, /*tp_as_mapping*/
646};