blob: 402662267350f270163e68342f11a996e5c21293 [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)) {
97 if (newitem != NULL)
98 DECREF(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) {
103 if (newitem != NULL)
104 DECREF(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;
110 if (olditem != NULL)
111 DECREF(olditem);
112 return 0;
113}
114
115static int
116ins1(self, where, v)
117 listobject *self;
118 int where;
119 object *v;
120{
121 int i;
122 object **items;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000123 if (v == NULL) {
124 err_badcall();
125 return -1;
126 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000127 items = self->ob_item;
128 RESIZE(items, object *, self->ob_size+1);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000129 if (items == NULL) {
130 err_nomem();
131 return -1;
132 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000133 if (where < 0)
134 where = 0;
135 if (where > self->ob_size)
136 where = self->ob_size;
137 for (i = self->ob_size; --i >= where; )
138 items[i+1] = items[i];
139 INCREF(v);
140 items[where] = v;
141 self->ob_item = items;
142 self->ob_size++;
143 return 0;
144}
145
146int
147inslistitem(op, where, newitem)
148 object *op;
149 int where;
150 object *newitem;
151{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000152 if (!is_listobject(op)) {
153 err_badcall();
154 return -1;
155 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000156 return ins1((listobject *)op, where, newitem);
157}
158
159int
160addlistitem(op, newitem)
161 object *op;
162 object *newitem;
163{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000164 if (!is_listobject(op)) {
165 err_badcall();
166 return -1;
167 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000168 return ins1((listobject *)op,
169 (int) ((listobject *)op)->ob_size, newitem);
170}
171
172/* Methods */
173
174static void
175list_dealloc(op)
176 listobject *op;
177{
178 int i;
179 for (i = 0; i < op->ob_size; i++) {
180 if (op->ob_item[i] != NULL)
181 DECREF(op->ob_item[i]);
182 }
183 if (op->ob_item != NULL)
184 free((ANY *)op->ob_item);
185 free((ANY *)op);
186}
187
Guido van Rossum90933611991-06-07 16:10:43 +0000188static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000189list_print(op, fp, flags)
190 listobject *op;
191 FILE *fp;
192 int flags;
193{
194 int i;
195 fprintf(fp, "[");
Guido van Rossum90933611991-06-07 16:10:43 +0000196 for (i = 0; i < op->ob_size; i++) {
197 if (i > 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000198 fprintf(fp, ", ");
Guido van Rossum90933611991-06-07 16:10:43 +0000199 if (printobject(op->ob_item[i], fp, flags) != 0)
200 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000201 }
202 fprintf(fp, "]");
Guido van Rossum90933611991-06-07 16:10:43 +0000203 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000204}
205
206object *
207list_repr(v)
208 listobject *v;
209{
210 object *s, *t, *comma;
211 int i;
212 s = newstringobject("[");
213 comma = newstringobject(", ");
214 for (i = 0; i < v->ob_size && s != NULL; i++) {
215 if (i > 0)
216 joinstring(&s, comma);
217 t = reprobject(v->ob_item[i]);
218 joinstring(&s, t);
219 DECREF(t);
220 }
221 DECREF(comma);
222 t = newstringobject("]");
223 joinstring(&s, t);
224 DECREF(t);
225 return s;
226}
227
228static int
229list_compare(v, w)
230 listobject *v, *w;
231{
232 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
233 int i;
234 for (i = 0; i < len; i++) {
235 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
236 if (cmp != 0)
237 return cmp;
238 }
239 return v->ob_size - w->ob_size;
240}
241
242static int
243list_length(a)
244 listobject *a;
245{
246 return a->ob_size;
247}
248
249static object *
250list_item(a, i)
251 listobject *a;
252 int i;
253{
254 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000255 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000256 return NULL;
257 }
258 INCREF(a->ob_item[i]);
259 return a->ob_item[i];
260}
261
262static object *
263list_slice(a, ilow, ihigh)
264 listobject *a;
265 int ilow, ihigh;
266{
267 listobject *np;
268 int i;
269 if (ilow < 0)
270 ilow = 0;
271 else if (ilow > a->ob_size)
272 ilow = a->ob_size;
273 if (ihigh < 0)
274 ihigh = 0;
275 if (ihigh < ilow)
276 ihigh = ilow;
277 else if (ihigh > a->ob_size)
278 ihigh = a->ob_size;
279 np = (listobject *) newlistobject(ihigh - ilow);
280 if (np == NULL)
281 return NULL;
282 for (i = ilow; i < ihigh; i++) {
283 object *v = a->ob_item[i];
284 INCREF(v);
285 np->ob_item[i - ilow] = v;
286 }
287 return (object *)np;
288}
289
290static object *
291list_concat(a, bb)
292 listobject *a;
293 object *bb;
294{
295 int size;
296 int i;
297 listobject *np;
298 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000299 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000300 return NULL;
301 }
302#define b ((listobject *)bb)
303 size = a->ob_size + b->ob_size;
304 np = (listobject *) newlistobject(size);
305 if (np == NULL) {
Guido van Rossum90933611991-06-07 16:10:43 +0000306 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000307 }
308 for (i = 0; i < a->ob_size; i++) {
309 object *v = a->ob_item[i];
310 INCREF(v);
311 np->ob_item[i] = v;
312 }
313 for (i = 0; i < b->ob_size; i++) {
314 object *v = b->ob_item[i];
315 INCREF(v);
316 np->ob_item[i + a->ob_size] = v;
317 }
318 return (object *)np;
319#undef b
320}
321
Guido van Rossumed98d481991-03-06 13:07:53 +0000322static object *
323list_repeat(a, n)
324 listobject *a;
325 int n;
326{
327 int i, j;
328 int size;
329 listobject *np;
330 object **p;
331 if (n < 0)
332 n = 0;
333 size = a->ob_size * n;
334 np = (listobject *) newlistobject(size);
335 if (np == NULL)
336 return NULL;
337 p = np->ob_item;
338 for (i = 0; i < n; i++) {
339 for (j = 0; j < a->ob_size; j++) {
340 *p = a->ob_item[j];
341 INCREF(*p);
342 p++;
343 }
344 }
345 return (object *) np;
346}
347
Guido van Rossumbfe14c51991-04-16 08:41:06 +0000348/* XXX The following function has a bug: don't try assigning a
349 XXX list object to a slice of itself (e.g., a[:1] = a). */
350
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000351static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000352list_ass_slice(a, ilow, ihigh, v)
353 listobject *a;
354 int ilow, ihigh;
355 object *v;
356{
357 object **item;
358 int n; /* Size of replacement list */
359 int d; /* Change in size */
360 int k; /* Loop index */
361#define b ((listobject *)v)
362 if (v == NULL)
363 n = 0;
364 else if (is_listobject(v))
365 n = b->ob_size;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000366 else {
367 err_badarg();
368 return -1;
369 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000370 if (ilow < 0)
371 ilow = 0;
372 else if (ilow > a->ob_size)
373 ilow = a->ob_size;
374 if (ihigh < 0)
375 ihigh = 0;
376 if (ihigh < ilow)
377 ihigh = ilow;
378 else if (ihigh > a->ob_size)
379 ihigh = a->ob_size;
380 item = a->ob_item;
381 d = n - (ihigh-ilow);
382 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
383 for (k = ilow; k < ihigh; k++)
384 DECREF(item[k]);
385 if (d < 0) {
386 for (/*k = ihigh*/; k < a->ob_size; k++)
387 item[k+d] = item[k];
388 a->ob_size += d;
389 RESIZE(item, object *, a->ob_size); /* Can't fail */
390 a->ob_item = item;
391 }
392 }
393 else { /* Insert d items; DECREF ihigh-ilow items */
394 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000395 if (item == NULL) {
396 err_nomem();
397 return -1;
398 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000399 for (k = a->ob_size; --k >= ihigh; )
400 item[k+d] = item[k];
401 for (/*k = ihigh-1*/; k >= ilow; --k)
402 DECREF(item[k]);
403 a->ob_item = item;
404 a->ob_size += d;
405 }
406 for (k = 0; k < n; k++, ilow++) {
407 object *w = b->ob_item[k];
408 INCREF(w);
409 item[ilow] = w;
410 }
411 return 0;
412#undef b
413}
414
Guido van Rossum4a450d01991-04-03 19:05:18 +0000415static int
416list_ass_item(a, i, v)
417 listobject *a;
418 int i;
419 object *v;
420{
421 if (i < 0 || i >= a->ob_size) {
422 err_setstr(IndexError, "list assignment index out of range");
423 return -1;
424 }
425 if (v == NULL)
426 return list_ass_slice(a, i, i+1, v);
427 INCREF(v);
428 DECREF(a->ob_item[i]);
429 a->ob_item[i] = v;
430 return 0;
431}
432
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000433static object *
434ins(self, where, v)
435 listobject *self;
436 int where;
437 object *v;
438{
439 if (ins1(self, where, v) != 0)
440 return NULL;
441 INCREF(None);
442 return None;
443}
444
445static object *
446listinsert(self, args)
447 listobject *self;
448 object *args;
449{
450 int i;
451 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000452 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000453 return NULL;
454 }
455 if (!getintarg(gettupleitem(args, 0), &i))
456 return NULL;
457 return ins(self, i, gettupleitem(args, 1));
458}
459
460static object *
461listappend(self, args)
462 listobject *self;
463 object *args;
464{
465 return ins(self, (int) self->ob_size, args);
466}
467
468static int
469cmp(v, w)
470 char *v, *w;
471{
472 return cmpobject(* (object **) v, * (object **) w);
473}
474
475static object *
476listsort(self, args)
477 listobject *self;
478 object *args;
479{
480 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000481 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000482 return NULL;
483 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000484 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000485 if (self->ob_size > 1)
486 qsort((char *)self->ob_item,
487 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000488 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000489 return NULL;
490 INCREF(None);
491 return None;
492}
493
Guido van Rossumed98d481991-03-06 13:07:53 +0000494static object *
495listreverse(self, args)
496 listobject *self;
497 object *args;
498{
499 register object **p, **q;
500 register object *tmp;
501
502 if (args != NULL) {
503 err_badarg();
504 return NULL;
505 }
506
507 if (self->ob_size > 1) {
508 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
509 p < q; p++, q--) {
510 tmp = *p;
511 *p = *q;
512 *q = tmp;
513 }
514 }
515
516 INCREF(None);
517 return None;
518}
519
Guido van Rossum84c76f51990-10-30 13:32:20 +0000520int
521sortlist(v)
522 object *v;
523{
524 if (v == NULL || !is_listobject(v)) {
525 err_badcall();
526 return -1;
527 }
528 v = listsort((listobject *)v, (object *)NULL);
529 if (v == NULL)
530 return -1;
531 DECREF(v);
532 return 0;
533}
534
Guido van Rossumed98d481991-03-06 13:07:53 +0000535static object *
536listindex(self, args)
537 listobject *self;
538 object *args;
539{
540 int i;
541
542 if (args == NULL) {
543 err_badarg();
544 return NULL;
545 }
546 for (i = 0; i < self->ob_size; i++) {
547 if (cmpobject(self->ob_item[i], args) == 0)
548 return newintobject(i);
549 }
550 err_setstr(RuntimeError, "list.index(x): x not in list");
551 return NULL;
552}
553
554static object *
555listremove(self, args)
556 listobject *self;
557 object *args;
558{
559 int i;
560
561 if (args == NULL) {
562 err_badarg();
563 return NULL;
564 }
565 for (i = 0; i < self->ob_size; i++) {
566 if (cmpobject(self->ob_item[i], args) == 0) {
567 if (list_ass_slice(self, i, i+1, (object *)NULL) != 0)
568 return NULL;
569 INCREF(None);
570 return None;
571 }
572
573 }
574 err_setstr(RuntimeError, "list.remove(x): x not in list");
575 return NULL;
576}
577
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000578static struct methodlist list_methods[] = {
579 {"append", listappend},
Guido van Rossumed98d481991-03-06 13:07:53 +0000580 {"index", listindex},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000581 {"insert", listinsert},
582 {"sort", listsort},
Guido van Rossumed98d481991-03-06 13:07:53 +0000583 {"remove", listremove},
584 {"reverse", listreverse},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000585 {NULL, NULL} /* sentinel */
586};
587
588static object *
589list_getattr(f, name)
590 listobject *f;
591 char *name;
592{
593 return findmethod(list_methods, (object *)f, name);
594}
595
596static sequence_methods list_as_sequence = {
597 list_length, /*sq_length*/
598 list_concat, /*sq_concat*/
Guido van Rossumed98d481991-03-06 13:07:53 +0000599 list_repeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000600 list_item, /*sq_item*/
601 list_slice, /*sq_slice*/
602 list_ass_item, /*sq_ass_item*/
603 list_ass_slice, /*sq_ass_slice*/
604};
605
606typeobject Listtype = {
607 OB_HEAD_INIT(&Typetype)
608 0,
609 "list",
610 sizeof(listobject),
611 0,
612 list_dealloc, /*tp_dealloc*/
613 list_print, /*tp_print*/
614 list_getattr, /*tp_getattr*/
615 0, /*tp_setattr*/
616 list_compare, /*tp_compare*/
617 list_repr, /*tp_repr*/
618 0, /*tp_as_number*/
619 &list_as_sequence, /*tp_as_sequence*/
620 0, /*tp_as_mapping*/
621};