blob: 97088c519ba0674624dc65754ea1971164a0349e [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* List object implementation */
2
3#include <stdio.h>
4
5#include "PROTO.h"
6#include "object.h"
7#include "intobject.h"
8#include "stringobject.h"
9#include "tupleobject.h"
10#include "methodobject.h"
11#include "listobject.h"
12#include "objimpl.h"
13#include "modsupport.h"
Guido van Rossum2a9096b1990-10-21 22:15:08 +000014#include "errors.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000015
16typedef struct {
17 OB_VARHEAD
18 object **ob_item;
19} listobject;
20
21object *
22newlistobject(size)
23 int size;
24{
25 int i;
26 listobject *op;
27 if (size < 0) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000028 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000029 return NULL;
30 }
31 op = (listobject *) malloc(sizeof(listobject));
32 if (op == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000033 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000034 }
35 if (size <= 0) {
36 op->ob_item = NULL;
37 }
38 else {
39 op->ob_item = (object **) malloc(size * sizeof(object *));
40 if (op->ob_item == NULL) {
41 free((ANY *)op);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000042 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043 }
44 }
45 NEWREF(op);
46 op->ob_type = &Listtype;
47 op->ob_size = size;
48 for (i = 0; i < size; i++)
49 op->ob_item[i] = NULL;
50 return (object *) op;
51}
52
53int
54getlistsize(op)
55 object *op;
56{
57 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000058 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000059 return -1;
60 }
61 else
62 return ((listobject *)op) -> ob_size;
63}
64
65object *
66getlistitem(op, i)
67 object *op;
68 int i;
69{
70 if (!is_listobject(op)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000071 err_badcall();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000072 return NULL;
73 }
74 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +000075 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076 return NULL;
77 }
78 return ((listobject *)op) -> ob_item[i];
79}
80
81int
82setlistitem(op, i, newitem)
83 register object *op;
84 register int i;
85 register object *newitem;
86{
87 register object *olditem;
88 if (!is_listobject(op)) {
89 if (newitem != NULL)
90 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000091 err_badcall();
92 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000093 }
94 if (i < 0 || i >= ((listobject *)op) -> ob_size) {
95 if (newitem != NULL)
96 DECREF(newitem);
Guido van Rossum2a9096b1990-10-21 22:15:08 +000097 err_setstr(IndexError, "list assignment index out of range");
98 return -1;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000099 }
100 olditem = ((listobject *)op) -> ob_item[i];
101 ((listobject *)op) -> ob_item[i] = newitem;
102 if (olditem != NULL)
103 DECREF(olditem);
104 return 0;
105}
106
107static int
108ins1(self, where, v)
109 listobject *self;
110 int where;
111 object *v;
112{
113 int i;
114 object **items;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000115 if (v == NULL) {
116 err_badcall();
117 return -1;
118 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000119 items = self->ob_item;
120 RESIZE(items, object *, self->ob_size+1);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000121 if (items == NULL) {
122 err_nomem();
123 return -1;
124 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000125 if (where < 0)
126 where = 0;
127 if (where > self->ob_size)
128 where = self->ob_size;
129 for (i = self->ob_size; --i >= where; )
130 items[i+1] = items[i];
131 INCREF(v);
132 items[where] = v;
133 self->ob_item = items;
134 self->ob_size++;
135 return 0;
136}
137
138int
139inslistitem(op, where, newitem)
140 object *op;
141 int where;
142 object *newitem;
143{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000144 if (!is_listobject(op)) {
145 err_badcall();
146 return -1;
147 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000148 return ins1((listobject *)op, where, newitem);
149}
150
151int
152addlistitem(op, newitem)
153 object *op;
154 object *newitem;
155{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000156 if (!is_listobject(op)) {
157 err_badcall();
158 return -1;
159 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000160 return ins1((listobject *)op,
161 (int) ((listobject *)op)->ob_size, newitem);
162}
163
164/* Methods */
165
166static void
167list_dealloc(op)
168 listobject *op;
169{
170 int i;
171 for (i = 0; i < op->ob_size; i++) {
172 if (op->ob_item[i] != NULL)
173 DECREF(op->ob_item[i]);
174 }
175 if (op->ob_item != NULL)
176 free((ANY *)op->ob_item);
177 free((ANY *)op);
178}
179
180static void
181list_print(op, fp, flags)
182 listobject *op;
183 FILE *fp;
184 int flags;
185{
186 int i;
187 fprintf(fp, "[");
188 for (i = 0; i < op->ob_size && !StopPrint; i++) {
189 if (i > 0) {
190 fprintf(fp, ", ");
191 }
192 printobject(op->ob_item[i], fp, flags);
193 }
194 fprintf(fp, "]");
195}
196
197object *
198list_repr(v)
199 listobject *v;
200{
201 object *s, *t, *comma;
202 int i;
203 s = newstringobject("[");
204 comma = newstringobject(", ");
205 for (i = 0; i < v->ob_size && s != NULL; i++) {
206 if (i > 0)
207 joinstring(&s, comma);
208 t = reprobject(v->ob_item[i]);
209 joinstring(&s, t);
210 DECREF(t);
211 }
212 DECREF(comma);
213 t = newstringobject("]");
214 joinstring(&s, t);
215 DECREF(t);
216 return s;
217}
218
219static int
220list_compare(v, w)
221 listobject *v, *w;
222{
223 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
224 int i;
225 for (i = 0; i < len; i++) {
226 int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
227 if (cmp != 0)
228 return cmp;
229 }
230 return v->ob_size - w->ob_size;
231}
232
233static int
234list_length(a)
235 listobject *a;
236{
237 return a->ob_size;
238}
239
240static object *
241list_item(a, i)
242 listobject *a;
243 int i;
244{
245 if (i < 0 || i >= a->ob_size) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000246 err_setstr(IndexError, "list index out of range");
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000247 return NULL;
248 }
249 INCREF(a->ob_item[i]);
250 return a->ob_item[i];
251}
252
253static object *
254list_slice(a, ilow, ihigh)
255 listobject *a;
256 int ilow, ihigh;
257{
258 listobject *np;
259 int i;
260 if (ilow < 0)
261 ilow = 0;
262 else if (ilow > a->ob_size)
263 ilow = a->ob_size;
264 if (ihigh < 0)
265 ihigh = 0;
266 if (ihigh < ilow)
267 ihigh = ilow;
268 else if (ihigh > a->ob_size)
269 ihigh = a->ob_size;
270 np = (listobject *) newlistobject(ihigh - ilow);
271 if (np == NULL)
272 return NULL;
273 for (i = ilow; i < ihigh; i++) {
274 object *v = a->ob_item[i];
275 INCREF(v);
276 np->ob_item[i - ilow] = v;
277 }
278 return (object *)np;
279}
280
281static object *
282list_concat(a, bb)
283 listobject *a;
284 object *bb;
285{
286 int size;
287 int i;
288 listobject *np;
289 if (!is_listobject(bb)) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000290 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000291 return NULL;
292 }
293#define b ((listobject *)bb)
294 size = a->ob_size + b->ob_size;
295 np = (listobject *) newlistobject(size);
296 if (np == NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000297 return err_nomem();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000298 }
299 for (i = 0; i < a->ob_size; i++) {
300 object *v = a->ob_item[i];
301 INCREF(v);
302 np->ob_item[i] = v;
303 }
304 for (i = 0; i < b->ob_size; i++) {
305 object *v = b->ob_item[i];
306 INCREF(v);
307 np->ob_item[i + a->ob_size] = v;
308 }
309 return (object *)np;
310#undef b
311}
312
313static int
314list_ass_item(a, i, v)
315 listobject *a;
316 int i;
317 object *v;
318{
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000319 if (i < 0 || i >= a->ob_size) {
320 err_setstr(IndexError, "list assignment index out of range");
321 return -1;
322 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000323 if (v == NULL)
324 return list_ass_slice(a, i, i+1, v);
325 INCREF(v);
326 DECREF(a->ob_item[i]);
327 a->ob_item[i] = v;
328 return 0;
329}
330
331static int
332list_ass_slice(a, ilow, ihigh, v)
333 listobject *a;
334 int ilow, ihigh;
335 object *v;
336{
337 object **item;
338 int n; /* Size of replacement list */
339 int d; /* Change in size */
340 int k; /* Loop index */
341#define b ((listobject *)v)
342 if (v == NULL)
343 n = 0;
344 else if (is_listobject(v))
345 n = b->ob_size;
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000346 else {
347 err_badarg();
348 return -1;
349 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000350 if (ilow < 0)
351 ilow = 0;
352 else if (ilow > a->ob_size)
353 ilow = a->ob_size;
354 if (ihigh < 0)
355 ihigh = 0;
356 if (ihigh < ilow)
357 ihigh = ilow;
358 else if (ihigh > a->ob_size)
359 ihigh = a->ob_size;
360 item = a->ob_item;
361 d = n - (ihigh-ilow);
362 if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */
363 for (k = ilow; k < ihigh; k++)
364 DECREF(item[k]);
365 if (d < 0) {
366 for (/*k = ihigh*/; k < a->ob_size; k++)
367 item[k+d] = item[k];
368 a->ob_size += d;
369 RESIZE(item, object *, a->ob_size); /* Can't fail */
370 a->ob_item = item;
371 }
372 }
373 else { /* Insert d items; DECREF ihigh-ilow items */
374 RESIZE(item, object *, a->ob_size + d);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000375 if (item == NULL) {
376 err_nomem();
377 return -1;
378 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000379 for (k = a->ob_size; --k >= ihigh; )
380 item[k+d] = item[k];
381 for (/*k = ihigh-1*/; k >= ilow; --k)
382 DECREF(item[k]);
383 a->ob_item = item;
384 a->ob_size += d;
385 }
386 for (k = 0; k < n; k++, ilow++) {
387 object *w = b->ob_item[k];
388 INCREF(w);
389 item[ilow] = w;
390 }
391 return 0;
392#undef b
393}
394
395static object *
396ins(self, where, v)
397 listobject *self;
398 int where;
399 object *v;
400{
401 if (ins1(self, where, v) != 0)
402 return NULL;
403 INCREF(None);
404 return None;
405}
406
407static object *
408listinsert(self, args)
409 listobject *self;
410 object *args;
411{
412 int i;
413 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000414 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000415 return NULL;
416 }
417 if (!getintarg(gettupleitem(args, 0), &i))
418 return NULL;
419 return ins(self, i, gettupleitem(args, 1));
420}
421
422static object *
423listappend(self, args)
424 listobject *self;
425 object *args;
426{
427 return ins(self, (int) self->ob_size, args);
428}
429
430static int
431cmp(v, w)
432 char *v, *w;
433{
434 return cmpobject(* (object **) v, * (object **) w);
435}
436
437static object *
438listsort(self, args)
439 listobject *self;
440 object *args;
441{
442 if (args != NULL) {
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000443 err_badarg();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000444 return NULL;
445 }
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000446 err_clear();
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000447 if (self->ob_size > 1)
448 qsort((char *)self->ob_item,
449 (int) self->ob_size, sizeof(object *), cmp);
Guido van Rossum2a9096b1990-10-21 22:15:08 +0000450 if (err_occurred())
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000451 return NULL;
452 INCREF(None);
453 return None;
454}
455
Guido van Rossum84c76f51990-10-30 13:32:20 +0000456int
457sortlist(v)
458 object *v;
459{
460 if (v == NULL || !is_listobject(v)) {
461 err_badcall();
462 return -1;
463 }
464 v = listsort((listobject *)v, (object *)NULL);
465 if (v == NULL)
466 return -1;
467 DECREF(v);
468 return 0;
469}
470
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000471static struct methodlist list_methods[] = {
472 {"append", listappend},
473 {"insert", listinsert},
474 {"sort", listsort},
475 {NULL, NULL} /* sentinel */
476};
477
478static object *
479list_getattr(f, name)
480 listobject *f;
481 char *name;
482{
483 return findmethod(list_methods, (object *)f, name);
484}
485
486static sequence_methods list_as_sequence = {
487 list_length, /*sq_length*/
488 list_concat, /*sq_concat*/
489 0, /*sq_repeat*/
490 list_item, /*sq_item*/
491 list_slice, /*sq_slice*/
492 list_ass_item, /*sq_ass_item*/
493 list_ass_slice, /*sq_ass_slice*/
494};
495
496typeobject Listtype = {
497 OB_HEAD_INIT(&Typetype)
498 0,
499 "list",
500 sizeof(listobject),
501 0,
502 list_dealloc, /*tp_dealloc*/
503 list_print, /*tp_print*/
504 list_getattr, /*tp_getattr*/
505 0, /*tp_setattr*/
506 list_compare, /*tp_compare*/
507 list_repr, /*tp_repr*/
508 0, /*tp_as_number*/
509 &list_as_sequence, /*tp_as_sequence*/
510 0, /*tp_as_mapping*/
511};