blob: ce27834d96cc868992874a59350921f2abd55792 [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
188static void
189list_print(op, fp, flags)
190 listobject *op;
191 FILE *fp;
192 int flags;
193{
194 int i;
195 fprintf(fp, "[");
196 for (i = 0; i < op->ob_size && !StopPrint; i++) {
197 if (i > 0) {
198 fprintf(fp, ", ");
199 }
200 printobject(op->ob_item[i], fp, flags);
201 }
202 fprintf(fp, "]");
203}
204
205object *
206list_repr(v)
207 listobject *v;
208{
209 object *s, *t, *comma;
210 int i;
211 s = newstringobject("[");
212 comma = newstringobject(", ");
213 for (i = 0; i < v->ob_size && s != NULL; i++) {
214 if (i > 0)
215 joinstring(&s, comma);
216 t = reprobject(v->ob_item[i]);
217 joinstring(&s, t);
218 DECREF(t);
219 }
220 DECREF(comma);
221 t = newstringobject("]");
222 joinstring(&s, t);
223 DECREF(t);
224 return s;
225}
226
227static int
228list_compare(v, w)
229 listobject *v, *w;
230{
231 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
232 int i;
233 for (i = 0; i < len; i++) {
234 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
235 if (cmp != 0)
236 return cmp;
237 }
238 return v->ob_size - w->ob_size;
239}
240
241static int
242list_length(a)
243 listobject *a;
244{
245 return a->ob_size;
246}
247
248static object *
249list_item(a, i)
250 listobject *a;
251 int i;
252{
253 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000254 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000255 return NULL;
256 }
257 INCREF(a->ob_item[i]);
258 return a->ob_item[i];
259}
260
261static object *
262list_slice(a, ilow, ihigh)
263 listobject *a;
264 int ilow, ihigh;
265{
266 listobject *np;
267 int i;
268 if (ilow < 0)
269 ilow = 0;
270 else if (ilow > a->ob_size)
271 ilow = a->ob_size;
272 if (ihigh < 0)
273 ihigh = 0;
274 if (ihigh < ilow)
275 ihigh = ilow;
276 else if (ihigh > a->ob_size)
277 ihigh = a->ob_size;
278 np = (listobject *) newlistobject(ihigh - ilow);
279 if (np == NULL)
280 return NULL;
281 for (i = ilow; i < ihigh; i++) {
282 object *v = a->ob_item[i];
283 INCREF(v);
284 np->ob_item[i - ilow] = v;
285 }
286 return (object *)np;
287}
288
289static object *
290list_concat(a, bb)
291 listobject *a;
292 object *bb;
293{
294 int size;
295 int i;
296 listobject *np;
297 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000298 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000299 return NULL;
300 }
301#define b ((listobject *)bb)
302 size = a->ob_size + b->ob_size;
303 np = (listobject *) newlistobject(size);
304 if (np == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000305 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000306 }
307 for (i = 0; i < a->ob_size; i++) {
308 object *v = a->ob_item[i];
309 INCREF(v);
310 np->ob_item[i] = v;
311 }
312 for (i = 0; i < b->ob_size; i++) {
313 object *v = b->ob_item[i];
314 INCREF(v);
315 np->ob_item[i + a->ob_size] = v;
316 }
317 return (object *)np;
318#undef b
319}
320
Guido van Rossumed98d481991-03-06 13:07:53 +0000321static object *
322list_repeat(a, n)
323 listobject *a;
324 int n;
325{
326 int i, j;
327 int size;
328 listobject *np;
329 object **p;
330 if (n < 0)
331 n = 0;
332 size = a->ob_size * n;
333 np = (listobject *) newlistobject(size);
334 if (np == NULL)
335 return NULL;
336 p = np->ob_item;
337 for (i = 0; i < n; i++) {
338 for (j = 0; j < a->ob_size; j++) {
339 *p = a->ob_item[j];
340 INCREF(*p);
341 p++;
342 }
343 }
344 return (object *) np;
345}
346
Guido van Rossumbfe14c51991-04-16 08:41:06 +0000347/* XXX The following function has a bug: don't try assigning a
348 XXX list object to a slice of itself (e.g., a[:1] = a). */
349
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000350static int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000351list_ass_slice(a, ilow, ihigh, v)
352 listobject *a;
353 int ilow, ihigh;
354 object *v;
355{
356 object **item;
357 int n; /* Size of replacement list */
358 int d; /* Change in size */
359 int k; /* Loop index */
360#define b ((listobject *)v)
361 if (v == NULL)
362 n = 0;
363 else if (is_listobject(v))
364 n = b->ob_size;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000365 else {
366 err_badarg();
367 return -1;
368 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000369 if (ilow < 0)
370 ilow = 0;
371 else if (ilow > a->ob_size)
372 ilow = a->ob_size;
373 if (ihigh < 0)
374 ihigh = 0;
375 if (ihigh < ilow)
376 ihigh = ilow;
377 else if (ihigh > a->ob_size)
378 ihigh = a->ob_size;
379 item = a->ob_item;
380 d = n - (ihigh-ilow);
381 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
382 for (k = ilow; k < ihigh; k++)
383 DECREF(item[k]);
384 if (d < 0) {
385 for (/*k = ihigh*/; k < a->ob_size; k++)
386 item[k+d] = item[k];
387 a->ob_size += d;
388 RESIZE(item, object *, a->ob_size); /* Can't fail */
389 a->ob_item = item;
390 }
391 }
392 else { /* Insert d items; DECREF ihigh-ilow items */
393 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000394 if (item == NULL) {
395 err_nomem();
396 return -1;
397 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000398 for (k = a->ob_size; --k >= ihigh; )
399 item[k+d] = item[k];
400 for (/*k = ihigh-1*/; k >= ilow; --k)
401 DECREF(item[k]);
402 a->ob_item = item;
403 a->ob_size += d;
404 }
405 for (k = 0; k < n; k++, ilow++) {
406 object *w = b->ob_item[k];
407 INCREF(w);
408 item[ilow] = w;
409 }
410 return 0;
411#undef b
412}
413
Guido van Rossum4a450d01991-04-03 19:05:18 +0000414static int
415list_ass_item(a, i, v)
416 listobject *a;
417 int i;
418 object *v;
419{
420 if (i < 0 || i >= a->ob_size) {
421 err_setstr(IndexError, "list assignment index out of range");
422 return -1;
423 }
424 if (v == NULL)
425 return list_ass_slice(a, i, i+1, v);
426 INCREF(v);
427 DECREF(a->ob_item[i]);
428 a->ob_item[i] = v;
429 return 0;
430}
431
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000432static object *
433ins(self, where, v)
434 listobject *self;
435 int where;
436 object *v;
437{
438 if (ins1(self, where, v) != 0)
439 return NULL;
440 INCREF(None);
441 return None;
442}
443
444static object *
445listinsert(self, args)
446 listobject *self;
447 object *args;
448{
449 int i;
450 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000451 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000452 return NULL;
453 }
454 if (!getintarg(gettupleitem(args, 0), &i))
455 return NULL;
456 return ins(self, i, gettupleitem(args, 1));
457}
458
459static object *
460listappend(self, args)
461 listobject *self;
462 object *args;
463{
464 return ins(self, (int) self->ob_size, args);
465}
466
467static int
468cmp(v, w)
469 char *v, *w;
470{
471 return cmpobject(* (object **) v, * (object **) w);
472}
473
474static object *
475listsort(self, args)
476 listobject *self;
477 object *args;
478{
479 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000480 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000481 return NULL;
482 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000483 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000484 if (self->ob_size > 1)
485 qsort((char *)self->ob_item,
486 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000487 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000488 return NULL;
489 INCREF(None);
490 return None;
491}
492
Guido van Rossumed98d481991-03-06 13:07:53 +0000493static object *
494listreverse(self, args)
495 listobject *self;
496 object *args;
497{
498 register object **p, **q;
499 register object *tmp;
500
501 if (args != NULL) {
502 err_badarg();
503 return NULL;
504 }
505
506 if (self->ob_size > 1) {
507 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
508 p < q; p++, q--) {
509 tmp = *p;
510 *p = *q;
511 *q = tmp;
512 }
513 }
514
515 INCREF(None);
516 return None;
517}
518
Guido van Rossum84c76f51990-10-30 13:32:20 +0000519int
520sortlist(v)
521 object *v;
522{
523 if (v == NULL || !is_listobject(v)) {
524 err_badcall();
525 return -1;
526 }
527 v = listsort((listobject *)v, (object *)NULL);
528 if (v == NULL)
529 return -1;
530 DECREF(v);
531 return 0;
532}
533
Guido van Rossumed98d481991-03-06 13:07:53 +0000534static object *
535listindex(self, args)
536 listobject *self;
537 object *args;
538{
539 int i;
540
541 if (args == NULL) {
542 err_badarg();
543 return NULL;
544 }
545 for (i = 0; i < self->ob_size; i++) {
546 if (cmpobject(self->ob_item[i], args) == 0)
547 return newintobject(i);
548 }
549 err_setstr(RuntimeError, "list.index(x): x not in list");
550 return NULL;
551}
552
553static object *
554listremove(self, args)
555 listobject *self;
556 object *args;
557{
558 int i;
559
560 if (args == NULL) {
561 err_badarg();
562 return NULL;
563 }
564 for (i = 0; i < self->ob_size; i++) {
565 if (cmpobject(self->ob_item[i], args) == 0) {
566 if (list_ass_slice(self, i, i+1, (object *)NULL) != 0)
567 return NULL;
568 INCREF(None);
569 return None;
570 }
571
572 }
573 err_setstr(RuntimeError, "list.remove(x): x not in list");
574 return NULL;
575}
576
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000577static struct methodlist list_methods[] = {
578 {"append", listappend},
Guido van Rossumed98d481991-03-06 13:07:53 +0000579 {"index", listindex},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000580 {"insert", listinsert},
581 {"sort", listsort},
Guido van Rossumed98d481991-03-06 13:07:53 +0000582 {"remove", listremove},
583 {"reverse", listreverse},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000584 {NULL, NULL} /* sentinel */
585};
586
587static object *
588list_getattr(f, name)
589 listobject *f;
590 char *name;
591{
592 return findmethod(list_methods, (object *)f, name);
593}
594
595static sequence_methods list_as_sequence = {
596 list_length, /*sq_length*/
597 list_concat, /*sq_concat*/
Guido van Rossumed98d481991-03-06 13:07:53 +0000598 list_repeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000599 list_item, /*sq_item*/
600 list_slice, /*sq_slice*/
601 list_ass_item, /*sq_ass_item*/
602 list_ass_slice, /*sq_ass_slice*/
603};
604
605typeobject Listtype = {
606 OB_HEAD_INIT(&Typetype)
607 0,
608 "list",
609 sizeof(listobject),
610 0,
611 list_dealloc, /*tp_dealloc*/
612 list_print, /*tp_print*/
613 list_getattr, /*tp_getattr*/
614 0, /*tp_setattr*/
615 list_compare, /*tp_compare*/
616 list_repr, /*tp_repr*/
617 0, /*tp_as_number*/
618 &list_as_sequence, /*tp_as_sequence*/
619 0, /*tp_as_mapping*/
620};