blob: 0f517359de6d25575b47c8dcbd414efba9b2fccd [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumf70e43a1991-02-19 12:39:46 +00003Netherlands.
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 Rossumff4949e1992-08-05 19:58:53 +000029#include "ceval.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000030
31object *
32newlistobject(size)
33 int size;
34{
35 int i;
36 listobject *op;
37 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000038 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000039 return NULL;
40 }
41 op = (listobject *) malloc(sizeof(listobject));
42 if (op == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000043 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000044 }
45 if (size <= 0) {
46 op->ob_item = NULL;
47 }
48 else {
49 op->ob_item = (object **) malloc(size * sizeof(object *));
50 if (op->ob_item == NULL) {
51 free((ANY *)op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000052 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000053 }
54 }
55 NEWREF(op);
56 op->ob_type = &Listtype;
57 op->ob_size = size;
58 for (i = 0; i < size; i++)
59 op->ob_item[i] = NULL;
60 return (object *) op;
61}
62
63int
64getlistsize(op)
65 object *op;
66{
67 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000068 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000069 return -1;
70 }
71 else
72 return ((listobject *)op) -> ob_size;
73}
74
75object *
76getlistitem(op, i)
77 object *op;
78 int i;
79{
80 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000081 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000082 return NULL;
83 }
84 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000085 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000086 return NULL;
87 }
88 return ((listobject *)op) -> ob_item[i];
89}
90
91int
92setlistitem(op, i, newitem)
93 register object *op;
94 register int i;
95 register object *newitem;
96{
97 register object *olditem;
98 if (!is_listobject(op)) {
Guido van Rossume6f7d181991-10-20 20:20:40 +000099 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000100 err_badcall();
101 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000102 }
103 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossume6f7d181991-10-20 20:20:40 +0000104 XDECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000105 err_setstr(IndexError, "list assignment index out of range");
106 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000107 }
108 olditem = ((listobject *)op) -> ob_item[i];
109 ((listobject *)op) -> ob_item[i] = newitem;
Guido van Rossume6f7d181991-10-20 20:20:40 +0000110 XDECREF(olditem);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000111 return 0;
112}
113
114static int
115ins1(self, where, v)
116 listobject *self;
117 int where;
118 object *v;
119{
120 int i;
121 object **items;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000122 if (v == NULL) {
123 err_badcall();
124 return -1;
125 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000126 items = self->ob_item;
127 RESIZE(items, object *, self->ob_size+1);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000128 if (items == NULL) {
129 err_nomem();
130 return -1;
131 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 if (where < 0)
133 where = 0;
134 if (where > self->ob_size)
135 where = self->ob_size;
136 for (i = self->ob_size; --i >= where; )
137 items[i+1] = items[i];
138 INCREF(v);
139 items[where] = v;
140 self->ob_item = items;
141 self->ob_size++;
142 return 0;
143}
144
145int
146inslistitem(op, where, newitem)
147 object *op;
148 int where;
149 object *newitem;
150{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000151 if (!is_listobject(op)) {
152 err_badcall();
153 return -1;
154 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000155 return ins1((listobject *)op, where, newitem);
156}
157
158int
159addlistitem(op, newitem)
160 object *op;
161 object *newitem;
162{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000163 if (!is_listobject(op)) {
164 err_badcall();
165 return -1;
166 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000167 return ins1((listobject *)op,
168 (int) ((listobject *)op)->ob_size, newitem);
169}
170
171/* Methods */
172
173static void
174list_dealloc(op)
175 listobject *op;
176{
177 int i;
178 for (i = 0; i < op->ob_size; i++) {
Guido van Rossume6f7d181991-10-20 20:20:40 +0000179 XDECREF(op->ob_item[i]);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000180 }
181 if (op->ob_item != NULL)
182 free((ANY *)op->ob_item);
183 free((ANY *)op);
184}
185
Guido van Rossum90933611991-06-07 16:10:43 +0000186static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000187list_print(op, fp, flags)
188 listobject *op;
189 FILE *fp;
190 int flags;
191{
192 int i;
193 fprintf(fp, "[");
Guido van Rossum90933611991-06-07 16:10:43 +0000194 for (i = 0; i < op->ob_size; i++) {
195 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000196 fprintf(fp, ", ");
Guido van Rossum90933611991-06-07 16:10:43 +0000197 if (printobject(op->ob_item[i], fp, flags) != 0)
198 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000199 }
200 fprintf(fp, "]");
Guido van Rossum90933611991-06-07 16:10:43 +0000201 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000202}
203
204object *
205list_repr(v)
206 listobject *v;
207{
208 object *s, *t, *comma;
209 int i;
210 s = newstringobject("[");
211 comma = newstringobject(", ");
212 for (i = 0; i < v->ob_size && s != NULL; i++) {
213 if (i > 0)
214 joinstring(&s, comma);
215 t = reprobject(v->ob_item[i]);
216 joinstring(&s, t);
217 DECREF(t);
218 }
219 DECREF(comma);
220 t = newstringobject("]");
221 joinstring(&s, t);
222 DECREF(t);
223 return s;
224}
225
226static int
227list_compare(v, w)
228 listobject *v, *w;
229{
230 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
231 int i;
232 for (i = 0; i < len; i++) {
233 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
234 if (cmp != 0)
235 return cmp;
236 }
237 return v->ob_size - w->ob_size;
238}
239
240static int
241list_length(a)
242 listobject *a;
243{
244 return a->ob_size;
245}
246
247static object *
248list_item(a, i)
249 listobject *a;
250 int i;
251{
252 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000253 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000254 return NULL;
255 }
256 INCREF(a->ob_item[i]);
257 return a->ob_item[i];
258}
259
260static object *
261list_slice(a, ilow, ihigh)
262 listobject *a;
263 int ilow, ihigh;
264{
265 listobject *np;
266 int i;
267 if (ilow < 0)
268 ilow = 0;
269 else if (ilow > a->ob_size)
270 ilow = a->ob_size;
271 if (ihigh < 0)
272 ihigh = 0;
273 if (ihigh < ilow)
274 ihigh = ilow;
275 else if (ihigh > a->ob_size)
276 ihigh = a->ob_size;
277 np = (listobject *) newlistobject(ihigh - ilow);
278 if (np == NULL)
279 return NULL;
280 for (i = ilow; i < ihigh; i++) {
281 object *v = a->ob_item[i];
282 INCREF(v);
283 np->ob_item[i - ilow] = v;
284 }
285 return (object *)np;
286}
287
288static object *
289list_concat(a, bb)
290 listobject *a;
291 object *bb;
292{
293 int size;
294 int i;
295 listobject *np;
296 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000297 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000298 return NULL;
299 }
300#define b ((listobject *)bb)
301 size = a->ob_size + b->ob_size;
302 np = (listobject *) newlistobject(size);
303 if (np == NULL) {
Guido van Rossum90933611991-06-07 16:10:43 +0000304 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000305 }
306 for (i = 0; i < a->ob_size; i++) {
307 object *v = a->ob_item[i];
308 INCREF(v);
309 np->ob_item[i] = v;
310 }
311 for (i = 0; i < b->ob_size; i++) {
312 object *v = b->ob_item[i];
313 INCREF(v);
314 np->ob_item[i + a->ob_size] = v;
315 }
316 return (object *)np;
317#undef b
318}
319
Guido van Rossumed98d481991-03-06 13:07:53 +0000320static object *
321list_repeat(a, n)
322 listobject *a;
323 int n;
324{
325 int i, j;
326 int size;
327 listobject *np;
328 object **p;
329 if (n < 0)
330 n = 0;
331 size = a->ob_size * n;
332 np = (listobject *) newlistobject(size);
333 if (np == NULL)
334 return NULL;
335 p = np->ob_item;
336 for (i = 0; i < n; i++) {
337 for (j = 0; j < a->ob_size; j++) {
338 *p = a->ob_item[j];
339 INCREF(*p);
340 p++;
341 }
342 }
343 return (object *) np;
344}
345
Guido van Rossumbfe14c51991-04-16 08:41:06 +0000346/* XXX The following function has a bug: don't try assigning a
347 XXX list object to a slice of itself (e.g., a[:1] = a). */
348
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000349static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000350list_ass_slice(a, ilow, ihigh, v)
351 listobject *a;
352 int ilow, ihigh;
353 object *v;
354{
355 object **item;
356 int n; /* Size of replacement list */
357 int d; /* Change in size */
358 int k; /* Loop index */
359#define b ((listobject *)v)
360 if (v == NULL)
361 n = 0;
Guido van Rossum32dffaa1991-12-24 13:27:34 +0000362 else if (is_listobject(v)) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000363 n = b->ob_size;
Guido van Rossum32dffaa1991-12-24 13:27:34 +0000364 if (a == b) {
365 /* Special case "a[i:j] = a" -- copy b first */
366 int ret;
367 v = list_slice(b, 0, n);
368 ret = list_ass_slice(a, ilow, ihigh, v);
369 DECREF(v);
370 return ret;
371 }
372 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000373 else {
374 err_badarg();
375 return -1;
376 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000377 if (ilow < 0)
378 ilow = 0;
379 else if (ilow > a->ob_size)
380 ilow = a->ob_size;
381 if (ihigh < 0)
382 ihigh = 0;
383 if (ihigh < ilow)
384 ihigh = ilow;
385 else if (ihigh > a->ob_size)
386 ihigh = a->ob_size;
387 item = a->ob_item;
388 d = n - (ihigh-ilow);
389 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
390 for (k = ilow; k < ihigh; k++)
391 DECREF(item[k]);
392 if (d < 0) {
393 for (/*k = ihigh*/; k < a->ob_size; k++)
394 item[k+d] = item[k];
395 a->ob_size += d;
396 RESIZE(item, object *, a->ob_size); /* Can't fail */
397 a->ob_item = item;
398 }
399 }
400 else { /* Insert d items; DECREF ihigh-ilow items */
401 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000402 if (item == NULL) {
403 err_nomem();
404 return -1;
405 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000406 for (k = a->ob_size; --k >= ihigh; )
407 item[k+d] = item[k];
408 for (/*k = ihigh-1*/; k >= ilow; --k)
409 DECREF(item[k]);
410 a->ob_item = item;
411 a->ob_size += d;
412 }
413 for (k = 0; k < n; k++, ilow++) {
414 object *w = b->ob_item[k];
415 INCREF(w);
416 item[ilow] = w;
417 }
418 return 0;
419#undef b
420}
421
Guido van Rossum4a450d01991-04-03 19:05:18 +0000422static int
423list_ass_item(a, i, v)
424 listobject *a;
425 int i;
426 object *v;
427{
428 if (i < 0 || i >= a->ob_size) {
429 err_setstr(IndexError, "list assignment index out of range");
430 return -1;
431 }
432 if (v == NULL)
433 return list_ass_slice(a, i, i+1, v);
434 INCREF(v);
435 DECREF(a->ob_item[i]);
436 a->ob_item[i] = v;
437 return 0;
438}
439
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000440static object *
441ins(self, where, v)
442 listobject *self;
443 int where;
444 object *v;
445{
446 if (ins1(self, where, v) != 0)
447 return NULL;
448 INCREF(None);
449 return None;
450}
451
452static object *
453listinsert(self, args)
454 listobject *self;
455 object *args;
456{
457 int i;
458 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000459 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000460 return NULL;
461 }
462 if (!getintarg(gettupleitem(args, 0), &i))
463 return NULL;
464 return ins(self, i, gettupleitem(args, 1));
465}
466
467static object *
468listappend(self, args)
469 listobject *self;
470 object *args;
471{
472 return ins(self, (int) self->ob_size, args);
473}
474
Guido van Rossume10a19e1992-08-03 19:05:37 +0000475static object *cmpfunc;
476
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000477static int
478cmp(v, w)
479 char *v, *w;
480{
Guido van Rossume10a19e1992-08-03 19:05:37 +0000481 object *t, *res;
482 long i;
483
484 if (err_occurred())
485 return 0;
486
487 if (cmpfunc == NULL)
488 return cmpobject(* (object **) v, * (object **) w);
489
490 /* Call the user-supplied comparison function */
491 t = newtupleobject(2);
492 if (t == NULL)
493 return 0;
494 INCREF(* (object **) v);
495 settupleitem(t, 0, * (object **) v);
496 INCREF(* (object **) w);
497 settupleitem(t, 1, * (object **) w);
498 res = call_object(cmpfunc, t);
499 DECREF(t);
500 if (res == NULL)
501 return 0;
502 if (!is_intobject(res)) {
503 err_setstr(TypeError, "comparison function should return int");
504 i = 0;
505 }
506 else {
507 i = getintvalue(res);
508 if (i < 0)
509 i = -1;
510 else if (i > 0)
511 i = 1;
512 }
513 DECREF(res);
514 return (int) i;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000515}
516
517static object *
518listsort(self, args)
519 listobject *self;
520 object *args;
521{
Guido van Rossume10a19e1992-08-03 19:05:37 +0000522 object *save_cmpfunc;
523 if (self->ob_size <= 1) {
524 INCREF(None);
525 return None;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000526 }
Guido van Rossume10a19e1992-08-03 19:05:37 +0000527 save_cmpfunc = cmpfunc;
528 cmpfunc = args;
529 if (cmpfunc != NULL) {
530 /* Test the comparison function for obvious errors */
531 (void) cmp(&self->ob_item[0], &self->ob_item[1]);
532 if (err_occurred()) {
533 cmpfunc = save_cmpfunc;
534 return NULL;
535 }
536 }
537 qsort((char *)self->ob_item,
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000538 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossume10a19e1992-08-03 19:05:37 +0000539 cmpfunc = save_cmpfunc;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000540 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000541 return NULL;
542 INCREF(None);
543 return None;
544}
545
Guido van Rossumed98d481991-03-06 13:07:53 +0000546static object *
547listreverse(self, args)
548 listobject *self;
549 object *args;
550{
551 register object **p, **q;
552 register object *tmp;
553
554 if (args != NULL) {
555 err_badarg();
556 return NULL;
557 }
558
559 if (self->ob_size > 1) {
560 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
561 p < q; p++, q--) {
562 tmp = *p;
563 *p = *q;
564 *q = tmp;
565 }
566 }
567
568 INCREF(None);
569 return None;
570}
571
Guido van Rossum84c76f51990-10-30 13:32:20 +0000572int
573sortlist(v)
574 object *v;
575{
576 if (v == NULL || !is_listobject(v)) {
577 err_badcall();
578 return -1;
579 }
580 v = listsort((listobject *)v, (object *)NULL);
581 if (v == NULL)
582 return -1;
583 DECREF(v);
584 return 0;
585}
586
Guido van Rossumed98d481991-03-06 13:07:53 +0000587static object *
588listindex(self, args)
589 listobject *self;
590 object *args;
591{
592 int i;
593
594 if (args == NULL) {
595 err_badarg();
596 return NULL;
597 }
598 for (i = 0; i < self->ob_size; i++) {
599 if (cmpobject(self->ob_item[i], args) == 0)
600 return newintobject(i);
601 }
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000602 err_setstr(ValueError, "list.index(x): x not in list");
Guido van Rossumed98d481991-03-06 13:07:53 +0000603 return NULL;
604}
605
606static object *
Guido van Rossume6f7d181991-10-20 20:20:40 +0000607listcount(self, args)
608 listobject *self;
609 object *args;
610{
611 int count = 0;
612 int i;
613
614 if (args == NULL) {
615 err_badarg();
616 return NULL;
617 }
618 for (i = 0; i < self->ob_size; i++) {
619 if (cmpobject(self->ob_item[i], args) == 0)
620 count++;
621 }
622 return newintobject((long)count);
623}
624
625static object *
Guido van Rossumed98d481991-03-06 13:07:53 +0000626listremove(self, args)
627 listobject *self;
628 object *args;
629{
630 int i;
631
632 if (args == NULL) {
633 err_badarg();
634 return NULL;
635 }
636 for (i = 0; i < self->ob_size; i++) {
637 if (cmpobject(self->ob_item[i], args) == 0) {
638 if (list_ass_slice(self, i, i+1, (object *)NULL) != 0)
639 return NULL;
640 INCREF(None);
641 return None;
642 }
643
644 }
Guido van Rossum87e7ea71991-12-10 14:00:03 +0000645 err_setstr(ValueError, "list.remove(x): x not in list");
Guido van Rossumed98d481991-03-06 13:07:53 +0000646 return NULL;
647}
648
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000649static struct methodlist list_methods[] = {
650 {"append", listappend},
Guido van Rossume6f7d181991-10-20 20:20:40 +0000651 {"count", listcount},
Guido van Rossumed98d481991-03-06 13:07:53 +0000652 {"index", listindex},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000653 {"insert", listinsert},
654 {"sort", listsort},
Guido van Rossumed98d481991-03-06 13:07:53 +0000655 {"remove", listremove},
656 {"reverse", listreverse},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000657 {NULL, NULL} /* sentinel */
658};
659
660static object *
661list_getattr(f, name)
662 listobject *f;
663 char *name;
664{
665 return findmethod(list_methods, (object *)f, name);
666}
667
668static sequence_methods list_as_sequence = {
669 list_length, /*sq_length*/
670 list_concat, /*sq_concat*/
Guido van Rossumed98d481991-03-06 13:07:53 +0000671 list_repeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000672 list_item, /*sq_item*/
673 list_slice, /*sq_slice*/
674 list_ass_item, /*sq_ass_item*/
675 list_ass_slice, /*sq_ass_slice*/
676};
677
678typeobject Listtype = {
679 OB_HEAD_INIT(&Typetype)
680 0,
681 "list",
682 sizeof(listobject),
683 0,
684 list_dealloc, /*tp_dealloc*/
685 list_print, /*tp_print*/
686 list_getattr, /*tp_getattr*/
687 0, /*tp_setattr*/
688 list_compare, /*tp_compare*/
689 list_repr, /*tp_repr*/
690 0, /*tp_as_number*/
691 &list_as_sequence, /*tp_as_sequence*/
692 0, /*tp_as_mapping*/
693};