blob: 18bdbcacb4679897b55ca8faf18af5da03fced58 [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;
360 else if (is_listobject(v))
361 n = b->ob_size;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000362 else {
363 err_badarg();
364 return -1;
365 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000366 if (ilow < 0)
367 ilow = 0;
368 else if (ilow > a->ob_size)
369 ilow = a->ob_size;
370 if (ihigh < 0)
371 ihigh = 0;
372 if (ihigh < ilow)
373 ihigh = ilow;
374 else if (ihigh > a->ob_size)
375 ihigh = a->ob_size;
376 item = a->ob_item;
377 d = n - (ihigh-ilow);
378 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
379 for (k = ilow; k < ihigh; k++)
380 DECREF(item[k]);
381 if (d < 0) {
382 for (/*k = ihigh*/; k < a->ob_size; k++)
383 item[k+d] = item[k];
384 a->ob_size += d;
385 RESIZE(item, object *, a->ob_size); /* Can't fail */
386 a->ob_item = item;
387 }
388 }
389 else { /* Insert d items; DECREF ihigh-ilow items */
390 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000391 if (item == NULL) {
392 err_nomem();
393 return -1;
394 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000395 for (k = a->ob_size; --k >= ihigh; )
396 item[k+d] = item[k];
397 for (/*k = ihigh-1*/; k >= ilow; --k)
398 DECREF(item[k]);
399 a->ob_item = item;
400 a->ob_size += d;
401 }
402 for (k = 0; k < n; k++, ilow++) {
403 object *w = b->ob_item[k];
404 INCREF(w);
405 item[ilow] = w;
406 }
407 return 0;
408#undef b
409}
410
Guido van Rossum4a450d01991-04-03 19:05:18 +0000411static int
412list_ass_item(a, i, v)
413 listobject *a;
414 int i;
415 object *v;
416{
417 if (i < 0 || i >= a->ob_size) {
418 err_setstr(IndexError, "list assignment index out of range");
419 return -1;
420 }
421 if (v == NULL)
422 return list_ass_slice(a, i, i+1, v);
423 INCREF(v);
424 DECREF(a->ob_item[i]);
425 a->ob_item[i] = v;
426 return 0;
427}
428
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000429static object *
430ins(self, where, v)
431 listobject *self;
432 int where;
433 object *v;
434{
435 if (ins1(self, where, v) != 0)
436 return NULL;
437 INCREF(None);
438 return None;
439}
440
441static object *
442listinsert(self, args)
443 listobject *self;
444 object *args;
445{
446 int i;
447 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000448 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000449 return NULL;
450 }
451 if (!getintarg(gettupleitem(args, 0), &i))
452 return NULL;
453 return ins(self, i, gettupleitem(args, 1));
454}
455
456static object *
457listappend(self, args)
458 listobject *self;
459 object *args;
460{
461 return ins(self, (int) self->ob_size, args);
462}
463
464static int
465cmp(v, w)
466 char *v, *w;
467{
468 return cmpobject(* (object **) v, * (object **) w);
469}
470
471static object *
472listsort(self, args)
473 listobject *self;
474 object *args;
475{
476 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000477 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000478 return NULL;
479 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000480 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000481 if (self->ob_size > 1)
482 qsort((char *)self->ob_item,
483 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000484 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000485 return NULL;
486 INCREF(None);
487 return None;
488}
489
Guido van Rossumed98d481991-03-06 13:07:53 +0000490static object *
491listreverse(self, args)
492 listobject *self;
493 object *args;
494{
495 register object **p, **q;
496 register object *tmp;
497
498 if (args != NULL) {
499 err_badarg();
500 return NULL;
501 }
502
503 if (self->ob_size > 1) {
504 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
505 p < q; p++, q--) {
506 tmp = *p;
507 *p = *q;
508 *q = tmp;
509 }
510 }
511
512 INCREF(None);
513 return None;
514}
515
Guido van Rossum84c76f51990-10-30 13:32:20 +0000516int
517sortlist(v)
518 object *v;
519{
520 if (v == NULL || !is_listobject(v)) {
521 err_badcall();
522 return -1;
523 }
524 v = listsort((listobject *)v, (object *)NULL);
525 if (v == NULL)
526 return -1;
527 DECREF(v);
528 return 0;
529}
530
Guido van Rossumed98d481991-03-06 13:07:53 +0000531static object *
532listindex(self, args)
533 listobject *self;
534 object *args;
535{
536 int i;
537
538 if (args == NULL) {
539 err_badarg();
540 return NULL;
541 }
542 for (i = 0; i < self->ob_size; i++) {
543 if (cmpobject(self->ob_item[i], args) == 0)
544 return newintobject(i);
545 }
546 err_setstr(RuntimeError, "list.index(x): x not in list");
547 return NULL;
548}
549
550static object *
Guido van Rossume6f7d181991-10-20 20:20:40 +0000551listcount(self, args)
552 listobject *self;
553 object *args;
554{
555 int count = 0;
556 int i;
557
558 if (args == NULL) {
559 err_badarg();
560 return NULL;
561 }
562 for (i = 0; i < self->ob_size; i++) {
563 if (cmpobject(self->ob_item[i], args) == 0)
564 count++;
565 }
566 return newintobject((long)count);
567}
568
569static object *
Guido van Rossumed98d481991-03-06 13:07:53 +0000570listremove(self, args)
571 listobject *self;
572 object *args;
573{
574 int i;
575
576 if (args == NULL) {
577 err_badarg();
578 return NULL;
579 }
580 for (i = 0; i < self->ob_size; i++) {
581 if (cmpobject(self->ob_item[i], args) == 0) {
582 if (list_ass_slice(self, i, i+1, (object *)NULL) != 0)
583 return NULL;
584 INCREF(None);
585 return None;
586 }
587
588 }
589 err_setstr(RuntimeError, "list.remove(x): x not in list");
590 return NULL;
591}
592
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000593static struct methodlist list_methods[] = {
594 {"append", listappend},
Guido van Rossume6f7d181991-10-20 20:20:40 +0000595 {"count", listcount},
Guido van Rossumed98d481991-03-06 13:07:53 +0000596 {"index", listindex},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000597 {"insert", listinsert},
598 {"sort", listsort},
Guido van Rossumed98d481991-03-06 13:07:53 +0000599 {"remove", listremove},
600 {"reverse", listreverse},
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000601 {NULL, NULL} /* sentinel */
602};
603
604static object *
605list_getattr(f, name)
606 listobject *f;
607 char *name;
608{
609 return findmethod(list_methods, (object *)f, name);
610}
611
612static sequence_methods list_as_sequence = {
613 list_length, /*sq_length*/
614 list_concat, /*sq_concat*/
Guido van Rossumed98d481991-03-06 13:07:53 +0000615 list_repeat, /*sq_repeat*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000616 list_item, /*sq_item*/
617 list_slice, /*sq_slice*/
618 list_ass_item, /*sq_ass_item*/
619 list_ass_slice, /*sq_ass_slice*/
620};
621
622typeobject Listtype = {
623 OB_HEAD_INIT(&Typetype)
624 0,
625 "list",
626 sizeof(listobject),
627 0,
628 list_dealloc, /*tp_dealloc*/
629 list_print, /*tp_print*/
630 list_getattr, /*tp_getattr*/
631 0, /*tp_setattr*/
632 list_compare, /*tp_compare*/
633 list_repr, /*tp_repr*/
634 0, /*tp_as_number*/
635 &list_as_sequence, /*tp_as_sequence*/
636 0, /*tp_as_mapping*/
637};