blob: 02192a14014b0b1a9c599da563b5a95724559363 [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
321static int
322list_ass_item(a, i, v)
323 listobject *a;
324 int i;
325 object *v;
326{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000327 if (i < 0 || i >= a->ob_size) {
328 err_setstr(IndexError, "list assignment index out of range");
329 return -1;
330 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000331 if (v == NULL)
332 return list_ass_slice(a, i, i+1, v);
333 INCREF(v);
334 DECREF(a->ob_item[i]);
335 a->ob_item[i] = v;
336 return 0;
337}
338
339static int
340list_ass_slice(a, ilow, ihigh, v)
341 listobject *a;
342 int ilow, ihigh;
343 object *v;
344{
345 object **item;
346 int n; /* Size of replacement list */
347 int d; /* Change in size */
348 int k; /* Loop index */
349#define b ((listobject *)v)
350 if (v == NULL)
351 n = 0;
352 else if (is_listobject(v))
353 n = b->ob_size;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000354 else {
355 err_badarg();
356 return -1;
357 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000358 if (ilow < 0)
359 ilow = 0;
360 else if (ilow > a->ob_size)
361 ilow = a->ob_size;
362 if (ihigh < 0)
363 ihigh = 0;
364 if (ihigh < ilow)
365 ihigh = ilow;
366 else if (ihigh > a->ob_size)
367 ihigh = a->ob_size;
368 item = a->ob_item;
369 d = n - (ihigh-ilow);
370 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
371 for (k = ilow; k < ihigh; k++)
372 DECREF(item[k]);
373 if (d < 0) {
374 for (/*k = ihigh*/; k < a->ob_size; k++)
375 item[k+d] = item[k];
376 a->ob_size += d;
377 RESIZE(item, object *, a->ob_size); /* Can't fail */
378 a->ob_item = item;
379 }
380 }
381 else { /* Insert d items; DECREF ihigh-ilow items */
382 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000383 if (item == NULL) {
384 err_nomem();
385 return -1;
386 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000387 for (k = a->ob_size; --k >= ihigh; )
388 item[k+d] = item[k];
389 for (/*k = ihigh-1*/; k >= ilow; --k)
390 DECREF(item[k]);
391 a->ob_item = item;
392 a->ob_size += d;
393 }
394 for (k = 0; k < n; k++, ilow++) {
395 object *w = b->ob_item[k];
396 INCREF(w);
397 item[ilow] = w;
398 }
399 return 0;
400#undef b
401}
402
403static object *
404ins(self, where, v)
405 listobject *self;
406 int where;
407 object *v;
408{
409 if (ins1(self, where, v) != 0)
410 return NULL;
411 INCREF(None);
412 return None;
413}
414
415static object *
416listinsert(self, args)
417 listobject *self;
418 object *args;
419{
420 int i;
421 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000422 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000423 return NULL;
424 }
425 if (!getintarg(gettupleitem(args, 0), &i))
426 return NULL;
427 return ins(self, i, gettupleitem(args, 1));
428}
429
430static object *
431listappend(self, args)
432 listobject *self;
433 object *args;
434{
435 return ins(self, (int) self->ob_size, args);
436}
437
438static int
439cmp(v, w)
440 char *v, *w;
441{
442 return cmpobject(* (object **) v, * (object **) w);
443}
444
445static object *
446listsort(self, args)
447 listobject *self;
448 object *args;
449{
450 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000451 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000452 return NULL;
453 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000454 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000455 if (self->ob_size > 1)
456 qsort((char *)self->ob_item,
457 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000458 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000459 return NULL;
460 INCREF(None);
461 return None;
462}
463
Guido van Rossum84c76f51990-10-30 13:32:20 +0000464int
465sortlist(v)
466 object *v;
467{
468 if (v == NULL || !is_listobject(v)) {
469 err_badcall();
470 return -1;
471 }
472 v = listsort((listobject *)v, (object *)NULL);
473 if (v == NULL)
474 return -1;
475 DECREF(v);
476 return 0;
477}
478
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000479static struct methodlist list_methods[] = {
480 {"append", listappend},
481 {"insert", listinsert},
482 {"sort", listsort},
483 {NULL, NULL} /* sentinel */
484};
485
486static object *
487list_getattr(f, name)
488 listobject *f;
489 char *name;
490{
491 return findmethod(list_methods, (object *)f, name);
492}
493
494static sequence_methods list_as_sequence = {
495 list_length, /*sq_length*/
496 list_concat, /*sq_concat*/
497 0, /*sq_repeat*/
498 list_item, /*sq_item*/
499 list_slice, /*sq_slice*/
500 list_ass_item, /*sq_ass_item*/
501 list_ass_slice, /*sq_ass_slice*/
502};
503
504typeobject Listtype = {
505 OB_HEAD_INIT(&Typetype)
506 0,
507 "list",
508 sizeof(listobject),
509 0,
510 list_dealloc, /*tp_dealloc*/
511 list_print, /*tp_print*/
512 list_getattr, /*tp_getattr*/
513 0, /*tp_setattr*/
514 list_compare, /*tp_compare*/
515 list_repr, /*tp_repr*/
516 0, /*tp_as_number*/
517 &list_as_sequence, /*tp_as_sequence*/
518 0, /*tp_as_mapping*/
519};