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