blob: 5b62fee4c0216051b7dbf764263b658429e748f7 [file] [log] [blame]
Guido van Rossum778983b1993-02-19 15:55:02 +00001/***********************************************************
2Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
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
25/* Array object implementation */
26
27/* An array is a uniform list -- all items have the same type.
28 The item type is restricted to simple C types like int or float */
29
30#include "allobjects.h"
31#include "modsupport.h"
32#include "ceval.h"
33
Guido van Rossum9575a441993-04-07 14:06:14 +000034#ifdef i860
35/* Cray APP doesn't have memmove */
Guido van Rossum778983b1993-02-19 15:55:02 +000036#define NEED_MEMMOVE
Guido van Rossum9575a441993-04-07 14:06:14 +000037extern char *memcpy();
38#endif
39
40#ifdef sun
41/* SunOS doesn't have memmove */
42#define NEED_MEMMOVE
43extern char *memcpy();
Guido van Rossum778983b1993-02-19 15:55:02 +000044#endif
45
46#ifdef NEED_MEMMOVE
47extern char *memmove();
48#endif
49
50struct arrayobject; /* Forward */
51
52struct arraydescr {
53 int typecode;
54 int itemsize;
55 object * (*getitem) FPROTO((struct arrayobject *, int));
56 int (*setitem) FPROTO((struct arrayobject *, int, object *));
57};
58
59typedef struct arrayobject {
60 OB_VARHEAD
61 char *ob_item;
62 struct arraydescr *ob_descr;
63} arrayobject;
64
65extern typeobject Arraytype;
66
67#define is_arrayobject(op) ((op)->ob_type == &Arraytype)
68
Guido van Rossumb73cc041993-11-01 16:28:59 +000069/* Forward */
Guido van Rossum778983b1993-02-19 15:55:02 +000070extern object *newarrayobject PROTO((int, struct arraydescr *));
71extern int getarraysize PROTO((object *));
72extern object *getarrayitem PROTO((object *, int));
Guido van Rossumb73cc041993-11-01 16:28:59 +000073static int setarrayitem PROTO((object *, int, object *));
Guido van Rossum778983b1993-02-19 15:55:02 +000074extern int insarrayitem PROTO((object *, int, object *));
75extern int addarrayitem PROTO((object *, object *));
76
77static object *
78c_getitem(ap, i)
79 arrayobject *ap;
80 int i;
81{
82 return newsizedstringobject(&((char *)ap->ob_item)[i], 1);
83}
84
85static int
86c_setitem(ap, i, v)
87 arrayobject *ap;
88 int i;
89 object *v;
90{
91 char x;
92 if (!getargs(v, "c;array item must be char", &x))
93 return -1;
94 if (i >= 0)
95 ((char *)ap->ob_item)[i] = x;
96 return 0;
97}
98
99static object *
100b_getitem(ap, i)
101 arrayobject *ap;
102 int i;
103{
104 long x = ((char *)ap->ob_item)[i];
105 if (x >= 128)
106 x -= 256;
107 return newintobject(x);
108}
109
110static int
111b_setitem(ap, i, v)
112 arrayobject *ap;
113 int i;
114 object *v;
115{
116 char x;
117 if (!getargs(v, "b;array item must be integer", &x))
118 return -1;
119 if (i >= 0)
120 ((char *)ap->ob_item)[i] = x;
121 return 0;
122}
123
124static object *
125h_getitem(ap, i)
126 arrayobject *ap;
127 int i;
128{
129 return newintobject((long) ((short *)ap->ob_item)[i]);
130}
131
132static int
133h_setitem(ap, i, v)
134 arrayobject *ap;
135 int i;
136 object *v;
137{
138 short x;
139 if (!getargs(v, "h;array item must be integer", &x))
140 return -1;
141 if (i >= 0)
142 ((short *)ap->ob_item)[i] = x;
143 return 0;
144}
145
146static object *
Guido van Rossume77a7571993-11-03 15:01:26 +0000147i_getitem(ap, i)
148 arrayobject *ap;
149 int i;
150{
151 return newintobject((long) ((int *)ap->ob_item)[i]);
152}
153
154static int
155i_setitem(ap, i, v)
156 arrayobject *ap;
157 int i;
158 object *v;
159{
160 int x;
161 if (!getargs(v, "i;array item must be integer", &x))
162 return -1;
163 if (i >= 0)
164 ((int *)ap->ob_item)[i] = x;
165 return 0;
166}
167
168static object *
Guido van Rossum778983b1993-02-19 15:55:02 +0000169l_getitem(ap, i)
170 arrayobject *ap;
171 int i;
172{
173 return newintobject(((long *)ap->ob_item)[i]);
174}
175
176static int
177l_setitem(ap, i, v)
178 arrayobject *ap;
179 int i;
180 object *v;
181{
182 long x;
183 if (!getargs(v, "l;array item must be integer", &x))
184 return -1;
185 if (i >= 0)
186 ((long *)ap->ob_item)[i] = x;
187 return 0;
188}
189
190static object *
191f_getitem(ap, i)
192 arrayobject *ap;
193 int i;
194{
195 return newfloatobject((double) ((float *)ap->ob_item)[i]);
196}
197
198static int
199f_setitem(ap, i, v)
200 arrayobject *ap;
201 int i;
202 object *v;
203{
204 float x;
205 if (!getargs(v, "f;array item must be float", &x))
206 return -1;
207 if (i >= 0)
208 ((float *)ap->ob_item)[i] = x;
209 return 0;
210}
211
212static object *
213d_getitem(ap, i)
214 arrayobject *ap;
215 int i;
216{
217 return newfloatobject(((double *)ap->ob_item)[i]);
218}
219
220static int
221d_setitem(ap, i, v)
222 arrayobject *ap;
223 int i;
224 object *v;
225{
226 double x;
227 if (!getargs(v, "d;array item must be float", &x))
228 return -1;
229 if (i >= 0)
230 ((double *)ap->ob_item)[i] = x;
231 return 0;
232}
233
234/* Description of types */
Guido van Rossum234f9421993-06-17 12:35:49 +0000235static struct arraydescr descriptors[] = {
Guido van Rossum778983b1993-02-19 15:55:02 +0000236 {'c', sizeof(char), c_getitem, c_setitem},
237 {'b', sizeof(char), b_getitem, b_setitem},
238 {'h', sizeof(short), h_getitem, h_setitem},
Guido van Rossume77a7571993-11-03 15:01:26 +0000239 {'i', sizeof(int), i_getitem, i_setitem},
Guido van Rossum778983b1993-02-19 15:55:02 +0000240 {'l', sizeof(long), l_getitem, l_setitem},
241 {'f', sizeof(float), f_getitem, f_setitem},
242 {'d', sizeof(double), d_getitem, d_setitem},
243 {'\0', 0, 0, 0} /* Sentinel */
244};
Guido van Rossume77a7571993-11-03 15:01:26 +0000245/* If we ever allow items larger than double, we must change reverse()! */
Guido van Rossum778983b1993-02-19 15:55:02 +0000246
247
248object *
249newarrayobject(size, descr)
250 int size;
251 struct arraydescr *descr;
252{
253 int i;
254 arrayobject *op;
255 MALLARG nbytes;
256 int itemsize;
257 if (size < 0) {
258 err_badcall();
259 return NULL;
260 }
261 nbytes = size * descr->itemsize;
262 /* Check for overflow */
263 if (nbytes / descr->itemsize != size) {
264 return err_nomem();
265 }
Guido van Rossume77a7571993-11-03 15:01:26 +0000266 op = NEW(arrayobject, 1);
Guido van Rossum778983b1993-02-19 15:55:02 +0000267 if (op == NULL) {
268 return err_nomem();
269 }
270 if (size <= 0) {
271 op->ob_item = NULL;
272 }
273 else {
Guido van Rossume77a7571993-11-03 15:01:26 +0000274 op->ob_item = NEW(char, nbytes);
Guido van Rossum778983b1993-02-19 15:55:02 +0000275 if (op->ob_item == NULL) {
Guido van Rossume77a7571993-11-03 15:01:26 +0000276 DEL(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000277 return err_nomem();
278 }
279 }
Guido van Rossum778983b1993-02-19 15:55:02 +0000280 op->ob_type = &Arraytype;
281 op->ob_size = size;
282 op->ob_descr = descr;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000283 NEWREF(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000284 return (object *) op;
285}
286
287int
288getarraysize(op)
289 object *op;
290{
291 if (!is_arrayobject(op)) {
292 err_badcall();
293 return -1;
294 }
295 return ((arrayobject *)op) -> ob_size;
296}
297
298object *
299getarrayitem(op, i)
300 object *op;
301 int i;
302{
303 register arrayobject *ap;
304 if (!is_arrayobject(op)) {
305 err_badcall();
306 return NULL;
307 }
308 ap = (arrayobject *)op;
309 if (i < 0 || i >= ap->ob_size) {
310 err_setstr(IndexError, "array index out of range");
311 return NULL;
312 }
313 return (*ap->ob_descr->getitem)(ap, i);
314}
315
316static int
317ins1(self, where, v)
318 arrayobject *self;
319 int where;
320 object *v;
321{
322 int i;
323 char *items;
324 if (v == NULL) {
325 err_badcall();
326 return -1;
327 }
328 if ((*self->ob_descr->setitem)(self, -1, v) < 0)
329 return -1;
330 items = self->ob_item;
331 RESIZE(items, char, (self->ob_size+1) * self->ob_descr->itemsize);
332 if (items == NULL) {
333 err_nomem();
334 return -1;
335 }
336 if (where < 0)
337 where = 0;
338 if (where > self->ob_size)
339 where = self->ob_size;
340 memmove(items + (where+1)*self->ob_descr->itemsize,
341 items + where*self->ob_descr->itemsize,
342 (self->ob_size-where)*self->ob_descr->itemsize);
343 self->ob_item = items;
344 self->ob_size++;
345 return (*self->ob_descr->setitem)(self, where, v);
346}
347
348int
349insarrayitem(op, where, newitem)
350 object *op;
351 int where;
352 object *newitem;
353{
354 if (!is_arrayobject(op)) {
355 err_badcall();
356 return -1;
357 }
358 return ins1((arrayobject *)op, where, newitem);
359}
360
361int
362addarrayitem(op, newitem)
363 object *op;
364 object *newitem;
365{
366 if (!is_arrayobject(op)) {
367 err_badcall();
368 return -1;
369 }
370 return ins1((arrayobject *)op,
371 (int) ((arrayobject *)op)->ob_size, newitem);
372}
373
374/* Methods */
375
376static void
377array_dealloc(op)
378 arrayobject *op;
379{
380 int i;
381 if (op->ob_item != NULL)
Guido van Rossume77a7571993-11-03 15:01:26 +0000382 DEL(op->ob_item);
383 DEL(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000384}
385
386static int
387array_compare(v, w)
388 arrayobject *v, *w;
389{
390 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
391 int i;
392 for (i = 0; i < len; i++) {
393 object *ai, *bi;
394 int cmp;
395 ai = getarrayitem((object *)v, i);
396 bi = getarrayitem((object *)w, i);
397 if (ai && bi)
398 cmp = cmpobject(ai, bi);
399 else
400 cmp = -1;
401 XDECREF(ai);
402 XDECREF(bi);
403 if (cmp != 0) {
404 err_clear(); /* XXX Can't report errors here */
405 return cmp;
406 }
407 }
408 return v->ob_size - w->ob_size;
409}
410
411static int
412array_length(a)
413 arrayobject *a;
414{
415 return a->ob_size;
416}
417
418static object *
419array_item(a, i)
420 arrayobject *a;
421 int i;
422{
423 if (i < 0 || i >= a->ob_size) {
424 err_setstr(IndexError, "array index out of range");
425 return NULL;
426 }
427 return getarrayitem((object *)a, i);
428}
429
430static object *
431array_slice(a, ilow, ihigh)
432 arrayobject *a;
433 int ilow, ihigh;
434{
435 arrayobject *np;
436 int i;
437 if (ilow < 0)
438 ilow = 0;
439 else if (ilow > a->ob_size)
440 ilow = a->ob_size;
441 if (ihigh < 0)
442 ihigh = 0;
443 if (ihigh < ilow)
444 ihigh = ilow;
445 else if (ihigh > a->ob_size)
446 ihigh = a->ob_size;
447 np = (arrayobject *) newarrayobject(ihigh - ilow, a->ob_descr);
448 if (np == NULL)
449 return NULL;
450 memcpy(np->ob_item, a->ob_item + ilow * a->ob_descr->itemsize,
451 (ihigh-ilow) * a->ob_descr->itemsize);
452 return (object *)np;
453}
454
455static object *
456array_concat(a, bb)
457 arrayobject *a;
458 object *bb;
459{
460 int size;
461 int i;
462 arrayobject *np;
463 if (!is_arrayobject(bb)) {
464 err_badarg();
465 return NULL;
466 }
467#define b ((arrayobject *)bb)
468 if (a->ob_descr != b->ob_descr) {
469 err_badarg();
470 return NULL;
471 }
472 size = a->ob_size + b->ob_size;
473 np = (arrayobject *) newarrayobject(size, a->ob_descr);
474 if (np == NULL) {
475 return NULL;
476 }
477 memcpy(np->ob_item, a->ob_item, a->ob_size*a->ob_descr->itemsize);
478 memcpy(np->ob_item + a->ob_size*a->ob_descr->itemsize,
Guido van Rossum32be3a71993-11-05 10:16:27 +0000479 b->ob_item, b->ob_size*b->ob_descr->itemsize);
Guido van Rossum778983b1993-02-19 15:55:02 +0000480 return (object *)np;
481#undef b
482}
483
484static object *
485array_repeat(a, n)
486 arrayobject *a;
487 int n;
488{
489 int i, j;
490 int size;
491 arrayobject *np;
492 char *p;
493 int nbytes;
494 if (n < 0)
495 n = 0;
496 size = a->ob_size * n;
497 np = (arrayobject *) newarrayobject(size, a->ob_descr);
498 if (np == NULL)
499 return NULL;
500 p = np->ob_item;
501 nbytes = a->ob_size * a->ob_descr->itemsize;
502 for (i = 0; i < n; i++) {
503 memcpy(p, a->ob_item, nbytes);
504 p += nbytes;
505 }
506 return (object *) np;
507}
508
509static int
510array_ass_slice(a, ilow, ihigh, v)
511 arrayobject *a;
512 int ilow, ihigh;
513 object *v;
514{
515 char *item;
516 int n; /* Size of replacement array */
517 int d; /* Change in size */
518 int k; /* Loop index */
519#define b ((arrayobject *)v)
520 if (v == NULL)
521 n = 0;
522 else if (is_arrayobject(v)) {
523 n = b->ob_size;
524 if (a == b) {
525 /* Special case "a[i:j] = a" -- copy b first */
526 int ret;
527 v = array_slice(b, 0, n);
528 ret = array_ass_slice(a, ilow, ihigh, v);
529 DECREF(v);
530 return ret;
531 }
532 if (b->ob_descr != a->ob_descr) {
533 err_badarg();
534 return -1;
535 }
536 }
537 else {
538 err_badarg();
539 return -1;
540 }
541 if (ilow < 0)
542 ilow = 0;
543 else if (ilow > a->ob_size)
544 ilow = a->ob_size;
545 if (ihigh < 0)
546 ihigh = 0;
547 if (ihigh < ilow)
548 ihigh = ilow;
549 else if (ihigh > a->ob_size)
550 ihigh = a->ob_size;
551 item = a->ob_item;
552 d = n - (ihigh-ilow);
553 if (d < 0) { /* Delete -d items */
554 memmove(item + (ihigh+d)*a->ob_descr->itemsize,
555 item + ihigh*a->ob_descr->itemsize,
556 (a->ob_size-ihigh)*a->ob_descr->itemsize);
557 a->ob_size += d;
558 RESIZE(item, char, a->ob_size*a->ob_descr->itemsize);
559 /* Can't fail */
560 a->ob_item = item;
561 }
562 else if (d > 0) { /* Insert d items */
563 RESIZE(item, char, (a->ob_size + d)*a->ob_descr->itemsize);
564 if (item == NULL) {
565 err_nomem();
566 return -1;
567 }
568 memmove(item + (ihigh+d)*a->ob_descr->itemsize,
569 item + ihigh*a->ob_descr->itemsize,
570 (a->ob_size-ihigh)*a->ob_descr->itemsize);
571 a->ob_item = item;
572 a->ob_size += d;
573 }
574 if (n > 0)
575 memcpy(item + ilow*a->ob_descr->itemsize, b->ob_item,
576 n*b->ob_descr->itemsize);
577 return 0;
578#undef b
579}
580
581static int
582array_ass_item(a, i, v)
583 arrayobject *a;
584 int i;
585 object *v;
586{
587 if (i < 0 || i >= a->ob_size) {
588 err_setstr(IndexError, "array assignment index out of range");
589 return -1;
590 }
591 if (v == NULL)
592 return array_ass_slice(a, i, i+1, v);
593 return (*a->ob_descr->setitem)(a, i, v);
594}
595
596static int
597setarrayitem(a, i, v)
598 object *a;
599 int i;
600 object *v;
601{
602 if (!is_arrayobject(a)) {
603 err_badcall();
604 return -1;
605 }
606 return array_ass_item((arrayobject *)a, i, v);
607}
608
609static object *
610ins(self, where, v)
611 arrayobject *self;
612 int where;
613 object *v;
614{
615 if (ins1(self, where, v) != 0)
616 return NULL;
617 INCREF(None);
618 return None;
619}
620
621static object *
622array_insert(self, args)
623 arrayobject *self;
624 object *args;
625{
626 int i;
627 object *v;
628 if (!getargs(args, "(iO)", &i, &v))
629 return NULL;
630 return ins(self, i, v);
631}
632
633static object *
634array_append(self, args)
635 arrayobject *self;
636 object *args;
637{
638 object *v;
639 if (!getargs(args, "O", &v))
640 return NULL;
641 return ins(self, (int) self->ob_size, v);
642}
643
644static object *
645array_byteswap(self, args)
646 arrayobject *self;
647 object *args;
648{
649 char *p;
650 int i;
651 switch (self->ob_descr->itemsize) {
652 case 1:
653 break;
654 case 2:
655 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 2) {
656 char p0 = p[0];
657 p[0] = p[1];
658 p[1] = p0;
659 }
660 break;
661 case 4:
662 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 4) {
663 char p0 = p[0];
664 char p1 = p[1];
665 p[0] = p[3];
666 p[1] = p[2];
667 p[2] = p1;
668 p[3] = p0;
669 }
670 break;
Guido van Rossume77a7571993-11-03 15:01:26 +0000671 case 8:
672 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 8) {
673 char p0 = p[0];
674 char p1 = p[1];
675 char p2 = p[2];
676 char p3 = p[3];
677 p[0] = p[7];
678 p[1] = p[6];
679 p[2] = p[5];
680 p[3] = p[4];
681 p[4] = p3;
682 p[5] = p2;
683 p[6] = p1;
684 p[7] = p0;
685 }
686 break;
Guido van Rossum778983b1993-02-19 15:55:02 +0000687 default:
688 err_setstr(RuntimeError,
689 "don't know how to byteswap this array type");
690 return NULL;
691 }
692 INCREF(None);
693 return None;
694}
695
Guido van Rossum778983b1993-02-19 15:55:02 +0000696static object *
697array_reverse(self, args)
698 arrayobject *self;
699 object *args;
700{
Guido van Rossume77a7571993-11-03 15:01:26 +0000701 register int itemsize = self->ob_descr->itemsize;
702 register char *p, *q;
703 char tmp[sizeof(double)]; /* Assume that's the max item size */
704
Guido van Rossum778983b1993-02-19 15:55:02 +0000705 if (args != NULL) {
706 err_badarg();
707 return NULL;
708 }
709
710 if (self->ob_size > 1) {
Guido van Rossume77a7571993-11-03 15:01:26 +0000711 for (p = self->ob_item,
712 q = self->ob_item + (self->ob_size - 1)*itemsize;
713 p < q;
714 p += itemsize, q -= itemsize) {
715 memmove(tmp, p, itemsize);
716 memmove(p, q, itemsize);
717 memmove(q, tmp, itemsize);
Guido van Rossum778983b1993-02-19 15:55:02 +0000718 }
719 }
720
721 INCREF(None);
722 return None;
723}
Guido van Rossume77a7571993-11-03 15:01:26 +0000724
725/* The following routines were adapted from listobject.c but not converted.
726 To make them work you will have to work! */
Guido van Rossum778983b1993-02-19 15:55:02 +0000727
728#if 0
729static object *
730array_index(self, args)
731 arrayobject *self;
732 object *args;
733{
734 int i;
735
736 if (args == NULL) {
737 err_badarg();
738 return NULL;
739 }
740 for (i = 0; i < self->ob_size; i++) {
741 if (cmpobject(self->ob_item[i], args) == 0)
742 return newintobject((long)i);
743 }
744 err_setstr(ValueError, "array.index(x): x not in array");
745 return NULL;
746}
747#endif
748
749#if 0
750static object *
751array_count(self, args)
752 arrayobject *self;
753 object *args;
754{
755 int count = 0;
756 int i;
757
758 if (args == NULL) {
759 err_badarg();
760 return NULL;
761 }
762 for (i = 0; i < self->ob_size; i++) {
763 if (cmpobject(self->ob_item[i], args) == 0)
764 count++;
765 }
766 return newintobject((long)count);
767}
768#endif
769
770#if 0
771static object *
772array_remove(self, args)
773 arrayobject *self;
774 object *args;
775{
776 int i;
777
778 if (args == NULL) {
779 err_badarg();
780 return NULL;
781 }
782 for (i = 0; i < self->ob_size; i++) {
783 if (cmpobject(self->ob_item[i], args) == 0) {
784 if (array_ass_slice(self, i, i+1, (object *)NULL) != 0)
785 return NULL;
786 INCREF(None);
787 return None;
788 }
789
790 }
791 err_setstr(ValueError, "array.remove(x): x not in array");
792 return NULL;
793}
794#endif
795
796static object *
Guido van Rossume77a7571993-11-03 15:01:26 +0000797array_fromfile(self, args)
Guido van Rossum778983b1993-02-19 15:55:02 +0000798 arrayobject *self;
799 object *args;
800{
801 object *f;
802 int n;
803 FILE *fp;
804 if (!getargs(args, "(Oi)", &f, &n))
805 return NULL;
806 fp = getfilefile(f);
807 if (fp == NULL) {
808 err_setstr(TypeError, "arg1 must be open file");
809 return NULL;
810 }
811 if (n > 0) {
812 char *item = self->ob_item;
813 int itemsize = self->ob_descr->itemsize;
814 int nread;
815 RESIZE(item, char, (self->ob_size + n) * itemsize);
816 if (item == NULL) {
817 err_nomem();
818 return NULL;
819 }
820 self->ob_item = item;
821 self->ob_size += n;
822 nread = fread(item + (self->ob_size - n) * itemsize,
823 itemsize, n, fp);
824 if (nread < n) {
825 self->ob_size -= (n - nread);
826 RESIZE(item, char, self->ob_size*itemsize);
827 self->ob_item = item;
828 err_setstr(EOFError, "not enough items in file");
829 return NULL;
830 }
831 }
832 INCREF(None);
833 return None;
834}
835
836static object *
Guido van Rossume77a7571993-11-03 15:01:26 +0000837array_tofile(self, args)
Guido van Rossum778983b1993-02-19 15:55:02 +0000838 arrayobject *self;
839 object *args;
840{
841 object *f;
842 FILE *fp;
843 if (!getargs(args, "O", &f))
844 return NULL;
845 fp = getfilefile(f);
846 if (fp == NULL) {
847 err_setstr(TypeError, "arg must be open file");
848 return NULL;
849 }
850 if (self->ob_size > 0) {
851 if (fwrite(self->ob_item, self->ob_descr->itemsize,
852 self->ob_size, fp) != self->ob_size) {
853 err_errno(IOError);
854 clearerr(fp);
855 return NULL;
856 }
857 }
858 INCREF(None);
859 return None;
860}
861
862static object *
863array_fromlist(self, args)
864 arrayobject *self;
865 object *args;
866{
867 int n;
868 object *list;
869 int itemsize = self->ob_descr->itemsize;
870 if (!getargs(args, "O", &list))
871 return NULL;
872 if (!is_listobject(list)) {
873 err_setstr(TypeError, "arg must be list");
874 return NULL;
875 }
876 n = getlistsize(list);
877 if (n > 0) {
878 char *item = self->ob_item;
879 int i;
880 RESIZE(item, char, (self->ob_size + n) * itemsize);
881 if (item == NULL) {
882 err_nomem();
883 return NULL;
884 }
885 self->ob_item = item;
886 self->ob_size += n;
887 for (i = 0; i < n; i++) {
888 object *v = getlistitem(list, i);
889 if ((*self->ob_descr->setitem)(self,
890 self->ob_size - n + i, v) != 0) {
891 self->ob_size -= n;
892 RESIZE(item, char, self->ob_size * itemsize);
893 self->ob_item = item;
894 return NULL;
895 }
896 }
897 }
898 INCREF(None);
899 return None;
900}
901
902static object *
903array_tolist(self, args)
904 arrayobject *self;
905 object *args;
906{
907 object *list = newlistobject(self->ob_size);
908 int i;
909 if (list == NULL)
910 return NULL;
911 for (i = 0; i < self->ob_size; i++) {
912 object *v = getarrayitem((object *)self, i);
913 if (v == NULL) {
914 DECREF(list);
915 return NULL;
916 }
917 setlistitem(list, i, v);
918 }
919 return list;
920}
921
922static object *
923array_fromstring(self, args)
924 arrayobject *self;
925 object *args;
926{
927 char *str;
928 int n;
929 int itemsize = self->ob_descr->itemsize;
930 if (!getargs(args, "s#", &str, &n))
931 return NULL;
932 if (n % itemsize != 0) {
933 err_setstr(ValueError,
934 "string length not a multiple of item size");
935 return NULL;
936 }
937 n = n / itemsize;
938 if (n > 0) {
939 char *item = self->ob_item;
940 RESIZE(item, char, (self->ob_size + n) * itemsize);
941 if (item == NULL) {
942 err_nomem();
943 return NULL;
944 }
945 self->ob_item = item;
946 self->ob_size += n;
947 memcpy(item + (self->ob_size - n) * itemsize, str, itemsize*n);
948 }
949 INCREF(None);
950 return None;
951}
952
953static object *
954array_tostring(self, args)
955 arrayobject *self;
956 object *args;
957{
958 if (!getargs(args, ""))
959 return NULL;
960 return newsizedstringobject(self->ob_item,
961 self->ob_size * self->ob_descr->itemsize);
962}
963
964static struct methodlist array_methods[] = {
965 {"append", array_append},
966 {"byteswap", array_byteswap},
967/* {"count", array_count},*/
Guido van Rossume77a7571993-11-03 15:01:26 +0000968 {"fromfile", array_fromfile},
969 {"fromlist", array_fromlist},
970 {"fromstring", array_fromstring},
Guido van Rossum778983b1993-02-19 15:55:02 +0000971/* {"index", array_index},*/
972 {"insert", array_insert},
Guido van Rossume77a7571993-11-03 15:01:26 +0000973 {"read", array_fromfile},
Guido van Rossum778983b1993-02-19 15:55:02 +0000974/* {"remove", array_remove},*/
Guido van Rossume77a7571993-11-03 15:01:26 +0000975 {"reverse", array_reverse},
976/* {"sort", array_sort},*/
977 {"tofile", array_tofile},
Guido van Rossum778983b1993-02-19 15:55:02 +0000978 {"tolist", array_tolist},
Guido van Rossum778983b1993-02-19 15:55:02 +0000979 {"tostring", array_tostring},
Guido van Rossume77a7571993-11-03 15:01:26 +0000980 {"write", array_tofile},
Guido van Rossum778983b1993-02-19 15:55:02 +0000981 {NULL, NULL} /* sentinel */
982};
983
984static object *
985array_getattr(a, name)
986 arrayobject *a;
987 char *name;
988{
989 if (strcmp(name, "typecode") == 0) {
990 char tc = a->ob_descr->typecode;
991 return newsizedstringobject(&tc, 1);
992 }
993 if (strcmp(name, "itemsize") == 0) {
994 return newintobject((long)a->ob_descr->itemsize);
995 }
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000996 if (strcmp(name, "__members__") == 0) {
997 object *list = newlistobject(2);
998 if (list) {
999 setlistitem(list, 0, newstringobject("typecode"));
1000 setlistitem(list, 1, newstringobject("itemsize"));
1001 if (err_occurred()) {
1002 DECREF(list);
1003 list = NULL;
1004 }
1005 }
1006 return list;
1007 }
Guido van Rossum778983b1993-02-19 15:55:02 +00001008 return findmethod(array_methods, (object *)a, name);
1009}
1010
1011static int
1012array_print(a, fp, flags)
1013 arrayobject *a;
1014 FILE *fp;
1015 int flags;
1016{
1017 int ok = 0;
1018 int i, len;
1019 object *v;
1020 len = a->ob_size;
1021 if (len == 0) {
1022 fprintf(fp, "array('%c')", a->ob_descr->typecode);
1023 return ok;
1024 }
1025 if (a->ob_descr->typecode == 'c') {
1026 fprintf(fp, "array('c', ");
1027 v = array_tostring(a, (object *)NULL);
Guido van Rossuma3d78fb1993-11-10 09:23:53 +00001028 ok = printobject(v, fp, 0);
Guido van Rossum778983b1993-02-19 15:55:02 +00001029 XDECREF(v);
1030 fprintf(fp, ")");
1031 return ok;
1032 }
1033 fprintf(fp, "array('%c', [", a->ob_descr->typecode);
1034 for (i = 0; i < len && ok == 0; i++) {
1035 if (i > 0)
1036 fprintf(fp, ", ");
1037 v = (a->ob_descr->getitem)(a, i);
Guido van Rossuma3d78fb1993-11-10 09:23:53 +00001038 ok = printobject(v, fp, 0);
Guido van Rossum778983b1993-02-19 15:55:02 +00001039 XDECREF(v);
1040 }
1041 fprintf(fp, "])");
1042 return ok;
1043}
1044
1045static object *
1046array_repr(a)
1047 arrayobject *a;
1048{
1049 char buf[256];
1050 object *s, *t, *comma, *v;
1051 int i, len;
1052 len = a->ob_size;
1053 if (len == 0) {
1054 sprintf(buf, "array('%c')", a->ob_descr->typecode);
1055 return newstringobject(buf);
1056 }
1057 if (a->ob_descr->typecode == 'c') {
1058 sprintf(buf, "array('c', ");
1059 s = newstringobject(buf);
1060 v = array_tostring(a, (object *)NULL);
1061 t = reprobject(v);
1062 XDECREF(v);
1063 joinstring(&s, t);
1064 XDECREF(t);
1065 t = newstringobject(")");
1066 joinstring(&s, t);
1067 XDECREF(t);
1068 if (err_occurred()) {
1069 XDECREF(s);
1070 s = NULL;
1071 }
1072 return s;
1073 }
1074 sprintf(buf, "array('%c', [", a->ob_descr->typecode);
1075 s = newstringobject(buf);
1076 comma = newstringobject(", ");
1077 for (i = 0; i < len && !err_occurred(); i++) {
1078 v = (a->ob_descr->getitem)(a, i);
1079 t = reprobject(v);
1080 XDECREF(v);
1081 if (i > 0)
1082 joinstring(&s, comma);
1083 joinstring(&s, t);
1084 XDECREF(t);
1085 }
1086 XDECREF(comma);
1087 t = newstringobject("])");
1088 joinstring(&s, t);
1089 XDECREF(t);
1090 if (err_occurred()) {
1091 XDECREF(s);
1092 s = NULL;
1093 }
1094 return s;
1095}
1096
1097static sequence_methods array_as_sequence = {
1098 array_length, /*sq_length*/
1099 array_concat, /*sq_concat*/
1100 array_repeat, /*sq_repeat*/
1101 array_item, /*sq_item*/
1102 array_slice, /*sq_slice*/
1103 array_ass_item, /*sq_ass_item*/
1104 array_ass_slice, /*sq_ass_slice*/
1105};
1106
1107typeobject Arraytype = {
1108 OB_HEAD_INIT(&Typetype)
1109 0,
1110 "array",
1111 sizeof(arrayobject),
1112 0,
1113 array_dealloc, /*tp_dealloc*/
1114 array_print, /*tp_print*/
1115 array_getattr, /*tp_getattr*/
1116 0, /*tp_setattr*/
1117 array_compare, /*tp_compare*/
1118 array_repr, /*tp_repr*/
1119 0, /*tp_as_number*/
1120 &array_as_sequence, /*tp_as_sequence*/
1121 0, /*tp_as_mapping*/
1122};
1123
1124
1125static object *
1126a_array(self, args)
1127 object *self;
1128 object *args;
1129{
1130 char c;
1131 object *initial = NULL;
1132 struct arraydescr *descr;
1133 if (!getargs(args, "c", &c)) {
1134 err_clear();
1135 if (!getargs(args, "(cO)", &c, &initial))
1136 return NULL;
1137 if (!is_listobject(initial) && !is_stringobject(initial)) {
1138 err_setstr(TypeError,
1139 "array initializer must be list or string");
1140 return NULL;
1141 }
1142 }
1143 for (descr = descriptors; descr->typecode != '\0'; descr++) {
1144 if (descr->typecode == c) {
1145 object *a;
1146 int len;
1147 if (initial == NULL || !is_listobject(initial))
1148 len = 0;
1149 else
1150 len = getlistsize(initial);
1151 a = newarrayobject(len, descr);
1152 if (a == NULL)
1153 return NULL;
1154 if (len > 0) {
1155 int i;
1156 for (i = 0; i < len; i++) {
1157 object *v = getlistitem(initial, i);
1158 if (setarrayitem(a, i, v) != 0) {
1159 DECREF(a);
1160 return NULL;
1161 }
1162 }
1163 }
1164 if (initial != NULL && is_stringobject(initial)) {
1165 object *v =
1166 array_fromstring((arrayobject *)a, initial);
1167 if (v == NULL) {
1168 DECREF(a);
1169 return NULL;
1170 }
1171 DECREF(v);
1172 }
1173 return a;
1174 }
1175 }
1176 err_setstr(ValueError, "bad typecode (must be c, b, h, l, f or d)");
1177 return NULL;
1178}
1179
1180static struct methodlist a_methods[] = {
1181 {"array", a_array},
1182 {NULL, NULL} /* sentinel */
1183};
1184
1185void
1186initarray()
1187{
1188 initmodule("array", a_methods);
1189}
1190
1191
1192#ifdef NEED_MEMMOVE
1193
1194/* A perhaps slow but I hope correct implementation of memmove */
1195
1196char *memmove(dst, src, n)
1197 char *dst;
1198 char *src;
1199 int n;
1200{
1201 char *realdst = dst;
1202 if (n <= 0)
1203 return dst;
1204 if (src >= dst+n || dst >= src+n)
1205 return memcpy(dst, src, n);
1206 if (src > dst) {
1207 while (--n >= 0)
1208 *dst++ = *src++;
1209 }
1210 else if (src < dst) {
1211 src += n;
1212 dst += n;
1213 while (--n >= 0)
1214 *--dst = *--src;
1215 }
1216 return realdst;
1217}
1218
1219#endif