blob: c59604de7e6efa01b195a2f10122430b6d17e484 [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* List object implementation */
2
Guido van Rossum3f5da241990-12-20 15:06:42 +00003#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00004
5object *
6newlistobject(size)
7 int size;
8{
9 int i;
10 listobject *op;
11 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000012 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000013 return NULL;
14 }
15 op = (listobject *) malloc(sizeof(listobject));
16 if (op == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000017 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000018 }
19 if (size <= 0) {
20 op->ob_item = NULL;
21 }
22 else {
23 op->ob_item = (object **) malloc(size * sizeof(object *));
24 if (op->ob_item == NULL) {
25 free((ANY *)op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000026 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000027 }
28 }
29 NEWREF(op);
30 op->ob_type = &Listtype;
31 op->ob_size = size;
32 for (i = 0; i < size; i++)
33 op->ob_item[i] = NULL;
34 return (object *) op;
35}
36
37int
38getlistsize(op)
39 object *op;
40{
41 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000042 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043 return -1;
44 }
45 else
46 return ((listobject *)op) -> ob_size;
47}
48
49object *
50getlistitem(op, i)
51 object *op;
52 int i;
53{
54 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000055 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000056 return NULL;
57 }
58 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000059 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000060 return NULL;
61 }
62 return ((listobject *)op) -> ob_item[i];
63}
64
65int
66setlistitem(op, i, newitem)
67 register object *op;
68 register int i;
69 register object *newitem;
70{
71 register object *olditem;
72 if (!is_listobject(op)) {
73 if (newitem != NULL)
74 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000075 err_badcall();
76 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000077 }
78 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
79 if (newitem != NULL)
80 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000081 err_setstr(IndexError, "list assignment index out of range");
82 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000083 }
84 olditem = ((listobject *)op) -> ob_item[i];
85 ((listobject *)op) -> ob_item[i] = newitem;
86 if (olditem != NULL)
87 DECREF(olditem);
88 return 0;
89}
90
91static int
92ins1(self, where, v)
93 listobject *self;
94 int where;
95 object *v;
96{
97 int i;
98 object **items;
Guido van Rossum2a9096b1990-10-21 22:15:08 +000099 if (v == NULL) {
100 err_badcall();
101 return -1;
102 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000103 items = self->ob_item;
104 RESIZE(items, object *, self->ob_size+1);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000105 if (items == NULL) {
106 err_nomem();
107 return -1;
108 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000109 if (where < 0)
110 where = 0;
111 if (where > self->ob_size)
112 where = self->ob_size;
113 for (i = self->ob_size; --i >= where; )
114 items[i+1] = items[i];
115 INCREF(v);
116 items[where] = v;
117 self->ob_item = items;
118 self->ob_size++;
119 return 0;
120}
121
122int
123inslistitem(op, where, newitem)
124 object *op;
125 int where;
126 object *newitem;
127{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000128 if (!is_listobject(op)) {
129 err_badcall();
130 return -1;
131 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 return ins1((listobject *)op, where, newitem);
133}
134
135int
136addlistitem(op, newitem)
137 object *op;
138 object *newitem;
139{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000140 if (!is_listobject(op)) {
141 err_badcall();
142 return -1;
143 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000144 return ins1((listobject *)op,
145 (int) ((listobject *)op)->ob_size, newitem);
146}
147
148/* Methods */
149
150static void
151list_dealloc(op)
152 listobject *op;
153{
154 int i;
155 for (i = 0; i < op->ob_size; i++) {
156 if (op->ob_item[i] != NULL)
157 DECREF(op->ob_item[i]);
158 }
159 if (op->ob_item != NULL)
160 free((ANY *)op->ob_item);
161 free((ANY *)op);
162}
163
164static void
165list_print(op, fp, flags)
166 listobject *op;
167 FILE *fp;
168 int flags;
169{
170 int i;
171 fprintf(fp, "[");
172 for (i = 0; i < op->ob_size && !StopPrint; i++) {
173 if (i > 0) {
174 fprintf(fp, ", ");
175 }
176 printobject(op->ob_item[i], fp, flags);
177 }
178 fprintf(fp, "]");
179}
180
181object *
182list_repr(v)
183 listobject *v;
184{
185 object *s, *t, *comma;
186 int i;
187 s = newstringobject("[");
188 comma = newstringobject(", ");
189 for (i = 0; i < v->ob_size && s != NULL; i++) {
190 if (i > 0)
191 joinstring(&s, comma);
192 t = reprobject(v->ob_item[i]);
193 joinstring(&s, t);
194 DECREF(t);
195 }
196 DECREF(comma);
197 t = newstringobject("]");
198 joinstring(&s, t);
199 DECREF(t);
200 return s;
201}
202
203static int
204list_compare(v, w)
205 listobject *v, *w;
206{
207 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
208 int i;
209 for (i = 0; i < len; i++) {
210 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
211 if (cmp != 0)
212 return cmp;
213 }
214 return v->ob_size - w->ob_size;
215}
216
217static int
218list_length(a)
219 listobject *a;
220{
221 return a->ob_size;
222}
223
224static object *
225list_item(a, i)
226 listobject *a;
227 int i;
228{
229 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000230 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000231 return NULL;
232 }
233 INCREF(a->ob_item[i]);
234 return a->ob_item[i];
235}
236
237static object *
238list_slice(a, ilow, ihigh)
239 listobject *a;
240 int ilow, ihigh;
241{
242 listobject *np;
243 int i;
244 if (ilow < 0)
245 ilow = 0;
246 else if (ilow > a->ob_size)
247 ilow = a->ob_size;
248 if (ihigh < 0)
249 ihigh = 0;
250 if (ihigh < ilow)
251 ihigh = ilow;
252 else if (ihigh > a->ob_size)
253 ihigh = a->ob_size;
254 np = (listobject *) newlistobject(ihigh - ilow);
255 if (np == NULL)
256 return NULL;
257 for (i = ilow; i < ihigh; i++) {
258 object *v = a->ob_item[i];
259 INCREF(v);
260 np->ob_item[i - ilow] = v;
261 }
262 return (object *)np;
263}
264
265static object *
266list_concat(a, bb)
267 listobject *a;
268 object *bb;
269{
270 int size;
271 int i;
272 listobject *np;
273 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000274 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000275 return NULL;
276 }
277#define b ((listobject *)bb)
278 size = a->ob_size + b->ob_size;
279 np = (listobject *) newlistobject(size);
280 if (np == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000281 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000282 }
283 for (i = 0; i < a->ob_size; i++) {
284 object *v = a->ob_item[i];
285 INCREF(v);
286 np->ob_item[i] = v;
287 }
288 for (i = 0; i < b->ob_size; i++) {
289 object *v = b->ob_item[i];
290 INCREF(v);
291 np->ob_item[i + a->ob_size] = v;
292 }
293 return (object *)np;
294#undef b
295}
296
297static int
298list_ass_item(a, i, v)
299 listobject *a;
300 int i;
301 object *v;
302{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000303 if (i < 0 || i >= a->ob_size) {
304 err_setstr(IndexError, "list assignment index out of range");
305 return -1;
306 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000307 if (v == NULL)
308 return list_ass_slice(a, i, i+1, v);
309 INCREF(v);
310 DECREF(a->ob_item[i]);
311 a->ob_item[i] = v;
312 return 0;
313}
314
315static int
316list_ass_slice(a, ilow, ihigh, v)
317 listobject *a;
318 int ilow, ihigh;
319 object *v;
320{
321 object **item;
322 int n; /* Size of replacement list */
323 int d; /* Change in size */
324 int k; /* Loop index */
325#define b ((listobject *)v)
326 if (v == NULL)
327 n = 0;
328 else if (is_listobject(v))
329 n = b->ob_size;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000330 else {
331 err_badarg();
332 return -1;
333 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000334 if (ilow < 0)
335 ilow = 0;
336 else if (ilow > a->ob_size)
337 ilow = a->ob_size;
338 if (ihigh < 0)
339 ihigh = 0;
340 if (ihigh < ilow)
341 ihigh = ilow;
342 else if (ihigh > a->ob_size)
343 ihigh = a->ob_size;
344 item = a->ob_item;
345 d = n - (ihigh-ilow);
346 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
347 for (k = ilow; k < ihigh; k++)
348 DECREF(item[k]);
349 if (d < 0) {
350 for (/*k = ihigh*/; k < a->ob_size; k++)
351 item[k+d] = item[k];
352 a->ob_size += d;
353 RESIZE(item, object *, a->ob_size); /* Can't fail */
354 a->ob_item = item;
355 }
356 }
357 else { /* Insert d items; DECREF ihigh-ilow items */
358 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000359 if (item == NULL) {
360 err_nomem();
361 return -1;
362 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000363 for (k = a->ob_size; --k >= ihigh; )
364 item[k+d] = item[k];
365 for (/*k = ihigh-1*/; k >= ilow; --k)
366 DECREF(item[k]);
367 a->ob_item = item;
368 a->ob_size += d;
369 }
370 for (k = 0; k < n; k++, ilow++) {
371 object *w = b->ob_item[k];
372 INCREF(w);
373 item[ilow] = w;
374 }
375 return 0;
376#undef b
377}
378
379static object *
380ins(self, where, v)
381 listobject *self;
382 int where;
383 object *v;
384{
385 if (ins1(self, where, v) != 0)
386 return NULL;
387 INCREF(None);
388 return None;
389}
390
391static object *
392listinsert(self, args)
393 listobject *self;
394 object *args;
395{
396 int i;
397 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000398 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000399 return NULL;
400 }
401 if (!getintarg(gettupleitem(args, 0), &i))
402 return NULL;
403 return ins(self, i, gettupleitem(args, 1));
404}
405
406static object *
407listappend(self, args)
408 listobject *self;
409 object *args;
410{
411 return ins(self, (int) self->ob_size, args);
412}
413
414static int
415cmp(v, w)
416 char *v, *w;
417{
418 return cmpobject(* (object **) v, * (object **) w);
419}
420
421static object *
422listsort(self, args)
423 listobject *self;
424 object *args;
425{
426 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000427 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000428 return NULL;
429 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000430 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000431 if (self->ob_size > 1)
432 qsort((char *)self->ob_item,
433 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000434 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000435 return NULL;
436 INCREF(None);
437 return None;
438}
439
Guido van Rossum84c76f51990-10-30 13:32:20 +0000440int
441sortlist(v)
442 object *v;
443{
444 if (v == NULL || !is_listobject(v)) {
445 err_badcall();
446 return -1;
447 }
448 v = listsort((listobject *)v, (object *)NULL);
449 if (v == NULL)
450 return -1;
451 DECREF(v);
452 return 0;
453}
454
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000455static struct methodlist list_methods[] = {
456 {"append", listappend},
457 {"insert", listinsert},
458 {"sort", listsort},
459 {NULL, NULL} /* sentinel */
460};
461
462static object *
463list_getattr(f, name)
464 listobject *f;
465 char *name;
466{
467 return findmethod(list_methods, (object *)f, name);
468}
469
470static sequence_methods list_as_sequence = {
471 list_length, /*sq_length*/
472 list_concat, /*sq_concat*/
473 0, /*sq_repeat*/
474 list_item, /*sq_item*/
475 list_slice, /*sq_slice*/
476 list_ass_item, /*sq_ass_item*/
477 list_ass_slice, /*sq_ass_slice*/
478};
479
480typeobject Listtype = {
481 OB_HEAD_INIT(&Typetype)
482 0,
483 "list",
484 sizeof(listobject),
485 0,
486 list_dealloc, /*tp_dealloc*/
487 list_print, /*tp_print*/
488 list_getattr, /*tp_getattr*/
489 0, /*tp_setattr*/
490 list_compare, /*tp_compare*/
491 list_repr, /*tp_repr*/
492 0, /*tp_as_number*/
493 &list_as_sequence, /*tp_as_sequence*/
494 0, /*tp_as_mapping*/
495};