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