blob: 156cda1c2f4ef86674e853b3eb84fe53b6e3165d [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 Rossumfa3da8a1992-01-27 16:53:23 +000028#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000029
30object *
31newlistobject(size)
32 int size;
33{
34 int i;
35 listobject *op;
36 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000037 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000038 return NULL;
39 }
40 op = (listobject *) malloc(sizeof(listobject));
41 if (op == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000042 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043 }
44 if (size <= 0) {
45 op->ob_item = NULL;
46 }
47 else {
48 op->ob_item = (object **) malloc(size * sizeof(object *));
49 if (op->ob_item == NULL) {
50 free((ANY *)op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000051 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000052 }
53 }
54 NEWREF(op);
55 op->ob_type = &Listtype;
56 op->ob_size = size;
57 for (i = 0; i < size; i++)
58 op->ob_item[i] = NULL;
59 return (object *) op;
60}
61
62int
63getlistsize(op)
64 object *op;
65{
66 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000067 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000068 return -1;
69 }
70 else
71 return ((listobject *)op) -> ob_size;
72}
73
74object *
75getlistitem(op, i)
76 object *op;
77 int i;
78{
79 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000080 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000081 return NULL;
82 }
83 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000084 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000085 return NULL;
86 }
87 return ((listobject *)op) -> ob_item[i];
88}
89
90int
91setlistitem(op, i, newitem)
92 register object *op;
93 register int i;
94 register object *newitem;
95{
96 register object *olditem;
97 if (!is_listobject(op)) {
Guido van Rossume6f7d181991-10-20 20:20:40 +000098 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000099 err_badcall();
100 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000101 }
102 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossume6f7d181991-10-20 20:20:40 +0000103 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000104 err_setstr(IndexError, "list assignment index out of range");
105 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000106 }
107 olditem = ((listobject *)op) -> ob_item[i];
108 ((listobject *)op) -> ob_item[i] = newitem;
Guido van Rossume6f7d181991-10-20 20:20:40 +0000109 XDECREF(olditem);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110 return 0;
111}
112
113static int
114ins1(self, where, v)
115 listobject *self;
116 int where;
117 object *v;
118{
119 int i;
120 object **items;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000121 if (v == NULL) {
122 err_badcall();
123 return -1;
124 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000125 items = self->ob_item;
126 RESIZE(items, object *, self->ob_size+1);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000127 if (items == NULL) {
128 err_nomem();
129 return -1;
130 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000131 if (where < 0)
132 where = 0;
133 if (where > self->ob_size)
134 where = self->ob_size;
135 for (i = self->ob_size; --i >= where; )
136 items[i+1] = items[i];
137 INCREF(v);
138 items[where] = v;
139 self->ob_item = items;
140 self->ob_size++;
141 return 0;
142}
143
144int
145inslistitem(op, where, newitem)
146 object *op;
147 int where;
148 object *newitem;
149{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000150 if (!is_listobject(op)) {
151 err_badcall();
152 return -1;
153 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000154 return ins1((listobject *)op, where, newitem);
155}
156
157int
158addlistitem(op, newitem)
159 object *op;
160 object *newitem;
161{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000162 if (!is_listobject(op)) {
163 err_badcall();
164 return -1;
165 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166 return ins1((listobject *)op,
167 (int) ((listobject *)op)->ob_size, newitem);
168}
169
170/* Methods */
171
172static void
173list_dealloc(op)
174 listobject *op;
175{
176 int i;
177 for (i = 0; i < op->ob_size; i++) {
Guido van Rossume6f7d181991-10-20 20:20:40 +0000178 XDECREF(op->ob_item[i]);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000179 }
180 if (op->ob_item != NULL)
181 free((ANY *)op->ob_item);
182 free((ANY *)op);
183}
184
Guido van Rossum90933611991-06-07 16:10:43 +0000185static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000186list_print(op, fp, flags)
187 listobject *op;
188 FILE *fp;
189 int flags;
190{
191 int i;
192 fprintf(fp, "[");
Guido van Rossum90933611991-06-07 16:10:43 +0000193 for (i = 0; i < op->ob_size; i++) {
194 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000195 fprintf(fp, ", ");
Guido van Rossum90933611991-06-07 16:10:43 +0000196 if (printobject(op->ob_item[i], fp, flags) != 0)
197 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000198 }
199 fprintf(fp, "]");
Guido van Rossum90933611991-06-07 16:10:43 +0000200 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000201}
202
203object *
204list_repr(v)
205 listobject *v;
206{
207 object *s, *t, *comma;
208 int i;
209 s = newstringobject("[");
210 comma = newstringobject(", ");
211 for (i = 0; i < v->ob_size && s != NULL; i++) {
212 if (i > 0)
213 joinstring(&s, comma);
214 t = reprobject(v->ob_item[i]);
215 joinstring(&s, t);
216 DECREF(t);
217 }
218 DECREF(comma);
219 t = newstringobject("]");
220 joinstring(&s, t);
221 DECREF(t);
222 return s;
223}
224
225static int
226list_compare(v, w)
227 listobject *v, *w;
228{
229 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
230 int i;
231 for (i = 0; i < len; i++) {
232 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
233 if (cmp != 0)
234 return cmp;
235 }
236 return v->ob_size - w->ob_size;
237}
238
239static int
240list_length(a)
241 listobject *a;
242{
243 return a->ob_size;
244}
245
246static object *
247list_item(a, i)
248 listobject *a;
249 int i;
250{
251 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000252 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000253 return NULL;
254 }
255 INCREF(a->ob_item[i]);
256 return a->ob_item[i];
257}
258
259static object *
260list_slice(a, ilow, ihigh)
261 listobject *a;
262 int ilow, ihigh;
263{
264 listobject *np;
265 int i;
266 if (ilow < 0)
267 ilow = 0;
268 else if (ilow > a->ob_size)
269 ilow = a->ob_size;
270 if (ihigh < 0)
271 ihigh = 0;
272 if (ihigh < ilow)
273 ihigh = ilow;
274 else if (ihigh > a->ob_size)
275 ihigh = a->ob_size;
276 np = (listobject *) newlistobject(ihigh - ilow);
277 if (np == NULL)
278 return NULL;
279 for (i = ilow; i < ihigh; i++) {
280 object *v = a->ob_item[i];
281 INCREF(v);
282 np->ob_item[i - ilow] = v;
283 }
284 return (object *)np;
285}
286
287static object *
288list_concat(a, bb)
289 listobject *a;
290 object *bb;
291{
292 int size;
293 int i;
294 listobject *np;
295 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000296 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000297 return NULL;
298 }
299#define b ((listobject *)bb)
300 size = a->ob_size + b->ob_size;
301 np = (listobject *) newlistobject(size);
302 if (np == NULL) {
Guido van Rossum90933611991-06-07 16:10:43 +0000303 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000304 }
305 for (i = 0; i < a->ob_size; i++) {
306 object *v = a->ob_item[i];
307 INCREF(v);
308 np->ob_item[i] = v;
309 }
310 for (i = 0; i < b->ob_size; i++) {
311 object *v = b->ob_item[i];
312 INCREF(v);
313 np->ob_item[i + a->ob_size] = v;
314 }
315 return (object *)np;
316#undef b
317}
318
Guido van Rossumed98d481991-03-06 13:07:53 +0000319static object *
320list_repeat(a, n)
321 listobject *a;
322 int n;
323{
324 int i, j;
325 int size;
326 listobject *np;
327 object **p;
328 if (n < 0)
329 n = 0;
330 size = a->ob_size * n;
331 np = (listobject *) newlistobject(size);
332 if (np == NULL)
333 return NULL;
334 p = np->ob_item;
335 for (i = 0; i < n; i++) {
336 for (j = 0; j < a->ob_size; j++) {
337 *p = a->ob_item[j];
338 INCREF(*p);
339 p++;
340 }
341 }
342 return (object *) np;
343}
344
Guido van Rossumbfe14c51991-04-16 08:41:06 +0000345/* XXX The following function has a bug: don't try assigning a
346 XXX list object to a slice of itself (e.g., a[:1] = a). */
347
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000348static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000349list_ass_slice(a, ilow, ihigh, v)
350 listobject *a;
351 int ilow, ihigh;
352 object *v;
353{
354 object **item;
355 int n; /* Size of replacement list */
356 int d; /* Change in size */
357 int k; /* Loop index */
358#define b ((listobject *)v)
359 if (v == NULL)
360 n = 0;
Guido van Rossum32dffaa1991-12-24 13:27:34 +0000361 else if (is_listobject(v)) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000362 n = b->ob_size;
Guido van Rossum32dffaa1991-12-24 13:27:34 +0000363 if (a == b) {
364 /* Special case "a[i:j] = a" -- copy b first */
365 int ret;
366 v = list_slice(b, 0, n);
367 ret = list_ass_slice(a, ilow, ihigh, v);
368 DECREF(v);
369 return ret;
370 }
371 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000372 else {
373 err_badarg();
374 return -1;
375 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000376 if (ilow < 0)
377 ilow = 0;
378 else if (ilow > a->ob_size)
379 ilow = a->ob_size;
380 if (ihigh < 0)
381 ihigh = 0;
382 if (ihigh < ilow)
383 ihigh = ilow;
384 else if (ihigh > a->ob_size)
385 ihigh = a->ob_size;
386 item = a->ob_item;
387 d = n - (ihigh-ilow);
388 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
389 for (k = ilow; k < ihigh; k++)
390 DECREF(item[k]);
391 if (d < 0) {
392 for (/*k = ihigh*/; k < a->ob_size; k++)
393 item[k+d] = item[k];
394 a->ob_size += d;
395 RESIZE(item, object *, a->ob_size); /* Can't fail */
396 a->ob_item = item;
397 }
398 }
399 else { /* Insert d items; DECREF ihigh-ilow items */
400 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000401 if (item == NULL) {
402 err_nomem();
403 return -1;
404 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000405 for (k = a->ob_size; --k >= ihigh; )
406 item[k+d] = item[k];
407 for (/*k = ihigh-1*/; k >= ilow; --k)
408 DECREF(item[k]);
409 a->ob_item = item;
410 a->ob_size += d;
411 }
412 for (k = 0; k < n; k++, ilow++) {
413 object *w = b->ob_item[k];
414 INCREF(w);
415 item[ilow] = w;
416 }
417 return 0;
418#undef b
419}
420
Guido van Rossum4a450d01991-04-03 19:05:18 +0000421static int
422list_ass_item(a, i, v)
423 listobject *a;
424 int i;
425 object *v;
426{
427 if (i < 0 || i >= a->ob_size) {
428 err_setstr(IndexError, "list assignment index out of range");
429 return -1;
430 }
431 if (v == NULL)
432 return list_ass_slice(a, i, i+1, v);
433 INCREF(v);
434 DECREF(a->ob_item[i]);
435 a->ob_item[i] = v;
436 return 0;
437}
438
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000439static object *
440ins(self, where, v)
441 listobject *self;
442 int where;
443 object *v;
444{
445 if (ins1(self, where, v) != 0)
446 return NULL;
447 INCREF(None);
448 return None;
449}
450
451static object *
452listinsert(self, args)
453 listobject *self;
454 object *args;
455{
456 int i;
457 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000458 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000459 return NULL;
460 }
461 if (!getintarg(gettupleitem(args, 0), &i))
462 return NULL;
463 return ins(self, i, gettupleitem(args, 1));
464}
465
466static object *
467listappend(self, args)
468 listobject *self;
469 object *args;
470{
471 return ins(self, (int) self->ob_size, args);
472}
473
474static int
475cmp(v, w)
476 char *v, *w;
477{
478 return cmpobject(* (object **) v, * (object **) w);
479}
480
481static object *
482listsort(self, args)
483 listobject *self;
484 object *args;
485{
486 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000487 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000488 return NULL;
489 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000490 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000491 if (self->ob_size > 1)
492 qsort((char *)self->ob_item,
493 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000494 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000495 return NULL;
496 INCREF(None);
497 return None;
498}
499
Guido van Rossumed98d481991-03-06 13:07:53 +0000500static object *
501listreverse(self, args)
502 listobject *self;
503 object *args;
504{
505 register object **p, **q;
506 register object *tmp;
507
508 if (args != NULL) {
509 err_badarg();
510 return NULL;
511 }
512
513 if (self->ob_size > 1) {
514 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
515 p < q; p++, q--) {
516 tmp = *p;
517 *p = *q;
518 *q = tmp;
519 }
520 }
521
522 INCREF(None);
523 return None;
524}
525
Guido van Rossum84c76f51990-10-30 13:32:20 +0000526int
527sortlist(v)
528 object *v;
529{
530 if (v == NULL || !is_listobject(v)) {
531 err_badcall();
532 return -1;
533 }
534 v = listsort((listobject *)v, (object *)NULL);
535 if (v == NULL)
536 return -1;
537 DECREF(v);
538 return 0;
539}
540
Guido van Rossumed98d481991-03-06 13:07:53 +0000541static object *
542listindex(self, args)
543 listobject *self;
544 object *args;
545{
546 int i;
547
548 if (args == NULL) {
549 err_badarg();
550 return NULL;
551 }
552 for (i = 0; i < self->ob_size; i++) {
553 if (cmpobject(self->ob_item[i], args) == 0)
554 return newintobject(i);
555 }
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000556 err_setstr(ValueError, "list.index(x): x not in list");
Guido van Rossumed98d481991-03-06 13:07:53 +0000557 return NULL;
558}
559
560static object *
Guido van Rossume6f7d181991-10-20 20:20:40 +0000561listcount(self, args)
562 listobject *self;
563 object *args;
564{
565 int count = 0;
566 int i;
567
568 if (args == NULL) {
569 err_badarg();
570 return NULL;
571 }
572 for (i = 0; i < self->ob_size; i++) {
573 if (cmpobject(self->ob_item[i], args) == 0)
574 count++;
575 }
576 return newintobject((long)count);
577}
578
579static object *
Guido van Rossumed98d481991-03-06 13:07:53 +0000580listremove(self, args)
581 listobject *self;
582 object *args;
583{
584 int i;
585
586 if (args == NULL) {
587 err_badarg();
588 return NULL;
589 }
590 for (i = 0; i < self->ob_size; i++) {
591 if (cmpobject(self->ob_item[i], args) == 0) {
592 if (list_ass_slice(self, i, i+1, (object *)NULL) != 0)
593 return NULL;
594 INCREF(None);
595 return None;
596 }
597
598 }
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000599 err_setstr(ValueError, "list.remove(x): x not in list");
Guido van Rossumed98d481991-03-06 13:07:53 +0000600 return NULL;
601}
602
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000603static struct methodlist list_methods[] = {
604 {"append", listappend},
Guido van Rossume6f7d181991-10-20 20:20:40 +0000605 {"count", listcount},
Guido van Rossumed98d481991-03-06 13:07:53 +0000606 {"index", listindex},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000607 {"insert", listinsert},
608 {"sort", listsort},
Guido van Rossumed98d481991-03-06 13:07:53 +0000609 {"remove", listremove},
610 {"reverse", listreverse},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000611 {NULL, NULL} /* sentinel */
612};
613
614static object *
615list_getattr(f, name)
616 listobject *f;
617 char *name;
618{
619 return findmethod(list_methods, (object *)f, name);
620}
621
622static sequence_methods list_as_sequence = {
623 list_length, /*sq_length*/
624 list_concat, /*sq_concat*/
Guido van Rossumed98d481991-03-06 13:07:53 +0000625 list_repeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000626 list_item, /*sq_item*/
627 list_slice, /*sq_slice*/
628 list_ass_item, /*sq_ass_item*/
629 list_ass_slice, /*sq_ass_slice*/
630};
631
632typeobject Listtype = {
633 OB_HEAD_INIT(&Typetype)
634 0,
635 "list",
636 sizeof(listobject),
637 0,
638 list_dealloc, /*tp_dealloc*/
639 list_print, /*tp_print*/
640 list_getattr, /*tp_getattr*/
641 0, /*tp_setattr*/
642 list_compare, /*tp_compare*/
643 list_repr, /*tp_repr*/
644 0, /*tp_as_number*/
645 &list_as_sequence, /*tp_as_sequence*/
646 0, /*tp_as_mapping*/
647};