At the release of 1.0.1.
[python/dscho.git] / Modules / arraymodule.c
blob925a52d2ef6b71c563cdabd7d0035d3012a1c5c1
1 /***********************************************************
2 Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Array object implementation */
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 */
30 #include "allobjects.h"
31 #include "modsupport.h"
32 #include "ceval.h"
34 #ifdef i860
35 /* Cray APP doesn't have memmove */
36 #define NEED_MEMMOVE
37 extern char *memcpy();
38 #endif
40 #if defined(sun) && !defined(__STDC__)
41 /* SunOS doesn't have memmove */
42 #define NEED_MEMMOVE
43 extern char *memcpy();
44 #endif
46 #ifdef NEED_MEMMOVE
47 extern char *memmove();
48 #endif
50 struct arrayobject; /* Forward */
52 struct arraydescr {
53 int typecode;
54 int itemsize;
55 object * (*getitem) FPROTO((struct arrayobject *, int));
56 int (*setitem) FPROTO((struct arrayobject *, int, object *));
59 typedef struct arrayobject {
60 OB_VARHEAD
61 char *ob_item;
62 struct arraydescr *ob_descr;
63 } arrayobject;
65 extern typeobject Arraytype;
67 #define is_arrayobject(op) ((op)->ob_type == &Arraytype)
69 /* Forward */
70 extern object *newarrayobject PROTO((int, struct arraydescr *));
71 extern int getarraysize PROTO((object *));
72 extern object *getarrayitem PROTO((object *, int));
73 static int setarrayitem PROTO((object *, int, object *));
74 extern int insarrayitem PROTO((object *, int, object *));
75 extern int addarrayitem PROTO((object *, object *));
77 static object *
78 c_getitem(ap, i)
79 arrayobject *ap;
80 int i;
82 return newsizedstringobject(&((char *)ap->ob_item)[i], 1);
85 static int
86 c_setitem(ap, i, v)
87 arrayobject *ap;
88 int i;
89 object *v;
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;
99 static object *
100 b_getitem(ap, i)
101 arrayobject *ap;
102 int i;
104 long x = ((char *)ap->ob_item)[i];
105 if (x >= 128)
106 x -= 256;
107 return newintobject(x);
110 static int
111 b_setitem(ap, i, v)
112 arrayobject *ap;
113 int i;
114 object *v;
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;
124 static object *
125 h_getitem(ap, i)
126 arrayobject *ap;
127 int i;
129 return newintobject((long) ((short *)ap->ob_item)[i]);
132 static int
133 h_setitem(ap, i, v)
134 arrayobject *ap;
135 int i;
136 object *v;
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;
146 static object *
147 i_getitem(ap, i)
148 arrayobject *ap;
149 int i;
151 return newintobject((long) ((int *)ap->ob_item)[i]);
154 static int
155 i_setitem(ap, i, v)
156 arrayobject *ap;
157 int i;
158 object *v;
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;
168 static object *
169 l_getitem(ap, i)
170 arrayobject *ap;
171 int i;
173 return newintobject(((long *)ap->ob_item)[i]);
176 static int
177 l_setitem(ap, i, v)
178 arrayobject *ap;
179 int i;
180 object *v;
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;
190 static object *
191 f_getitem(ap, i)
192 arrayobject *ap;
193 int i;
195 return newfloatobject((double) ((float *)ap->ob_item)[i]);
198 static int
199 f_setitem(ap, i, v)
200 arrayobject *ap;
201 int i;
202 object *v;
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;
212 static object *
213 d_getitem(ap, i)
214 arrayobject *ap;
215 int i;
217 return newfloatobject(((double *)ap->ob_item)[i]);
220 static int
221 d_setitem(ap, i, v)
222 arrayobject *ap;
223 int i;
224 object *v;
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;
234 /* Description of types */
235 static struct arraydescr descriptors[] = {
236 {'c', sizeof(char), c_getitem, c_setitem},
237 {'b', sizeof(char), b_getitem, b_setitem},
238 {'h', sizeof(short), h_getitem, h_setitem},
239 {'i', sizeof(int), i_getitem, i_setitem},
240 {'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 */
245 /* If we ever allow items larger than double, we must change reverse()! */
248 object *
249 newarrayobject(size, descr)
250 int size;
251 struct arraydescr *descr;
253 int i;
254 arrayobject *op;
255 MALLARG nbytes;
256 int itemsize;
257 if (size < 0) {
258 err_badcall();
259 return NULL;
261 nbytes = size * descr->itemsize;
262 /* Check for overflow */
263 if (nbytes / descr->itemsize != size) {
264 return err_nomem();
266 op = NEW(arrayobject, 1);
267 if (op == NULL) {
268 return err_nomem();
270 if (size <= 0) {
271 op->ob_item = NULL;
273 else {
274 op->ob_item = NEW(char, nbytes);
275 if (op->ob_item == NULL) {
276 DEL(op);
277 return err_nomem();
280 op->ob_type = &Arraytype;
281 op->ob_size = size;
282 op->ob_descr = descr;
283 NEWREF(op);
284 return (object *) op;
288 getarraysize(op)
289 object *op;
291 if (!is_arrayobject(op)) {
292 err_badcall();
293 return -1;
295 return ((arrayobject *)op) -> ob_size;
298 object *
299 getarrayitem(op, i)
300 object *op;
301 int i;
303 register arrayobject *ap;
304 if (!is_arrayobject(op)) {
305 err_badcall();
306 return NULL;
308 ap = (arrayobject *)op;
309 if (i < 0 || i >= ap->ob_size) {
310 err_setstr(IndexError, "array index out of range");
311 return NULL;
313 return (*ap->ob_descr->getitem)(ap, i);
316 static int
317 ins1(self, where, v)
318 arrayobject *self;
319 int where;
320 object *v;
322 int i;
323 char *items;
324 if (v == NULL) {
325 err_badcall();
326 return -1;
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;
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);
349 insarrayitem(op, where, newitem)
350 object *op;
351 int where;
352 object *newitem;
354 if (!is_arrayobject(op)) {
355 err_badcall();
356 return -1;
358 return ins1((arrayobject *)op, where, newitem);
362 addarrayitem(op, newitem)
363 object *op;
364 object *newitem;
366 if (!is_arrayobject(op)) {
367 err_badcall();
368 return -1;
370 return ins1((arrayobject *)op,
371 (int) ((arrayobject *)op)->ob_size, newitem);
374 /* Methods */
376 static void
377 array_dealloc(op)
378 arrayobject *op;
380 int i;
381 if (op->ob_item != NULL)
382 DEL(op->ob_item);
383 DEL(op);
386 static int
387 array_compare(v, w)
388 arrayobject *v, *w;
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;
408 return v->ob_size - w->ob_size;
411 static int
412 array_length(a)
413 arrayobject *a;
415 return a->ob_size;
418 static object *
419 array_item(a, i)
420 arrayobject *a;
421 int i;
423 if (i < 0 || i >= a->ob_size) {
424 err_setstr(IndexError, "array index out of range");
425 return NULL;
427 return getarrayitem((object *)a, i);
430 static object *
431 array_slice(a, ilow, ihigh)
432 arrayobject *a;
433 int ilow, ihigh;
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;
455 static object *
456 array_concat(a, bb)
457 arrayobject *a;
458 object *bb;
460 int size;
461 int i;
462 arrayobject *np;
463 if (!is_arrayobject(bb)) {
464 err_badarg();
465 return NULL;
467 #define b ((arrayobject *)bb)
468 if (a->ob_descr != b->ob_descr) {
469 err_badarg();
470 return NULL;
472 size = a->ob_size + b->ob_size;
473 np = (arrayobject *) newarrayobject(size, a->ob_descr);
474 if (np == NULL) {
475 return NULL;
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,
479 b->ob_item, b->ob_size*b->ob_descr->itemsize);
480 return (object *)np;
481 #undef b
484 static object *
485 array_repeat(a, n)
486 arrayobject *a;
487 int n;
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;
506 return (object *) np;
509 static int
510 array_ass_slice(a, ilow, ihigh, v)
511 arrayobject *a;
512 int ilow, ihigh;
513 object *v;
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;
532 if (b->ob_descr != a->ob_descr) {
533 err_badarg();
534 return -1;
537 else {
538 err_badarg();
539 return -1;
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;
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;
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;
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
581 static int
582 array_ass_item(a, i, v)
583 arrayobject *a;
584 int i;
585 object *v;
587 if (i < 0 || i >= a->ob_size) {
588 err_setstr(IndexError, "array assignment index out of range");
589 return -1;
591 if (v == NULL)
592 return array_ass_slice(a, i, i+1, v);
593 return (*a->ob_descr->setitem)(a, i, v);
596 static int
597 setarrayitem(a, i, v)
598 object *a;
599 int i;
600 object *v;
602 if (!is_arrayobject(a)) {
603 err_badcall();
604 return -1;
606 return array_ass_item((arrayobject *)a, i, v);
609 static object *
610 ins(self, where, v)
611 arrayobject *self;
612 int where;
613 object *v;
615 if (ins1(self, where, v) != 0)
616 return NULL;
617 INCREF(None);
618 return None;
621 static object *
622 array_insert(self, args)
623 arrayobject *self;
624 object *args;
626 int i;
627 object *v;
628 if (!getargs(args, "(iO)", &i, &v))
629 return NULL;
630 return ins(self, i, v);
633 static object *
634 array_append(self, args)
635 arrayobject *self;
636 object *args;
638 object *v;
639 if (!getargs(args, "O", &v))
640 return NULL;
641 return ins(self, (int) self->ob_size, v);
644 static object *
645 array_byteswap(self, args)
646 arrayobject *self;
647 object *args;
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;
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;
670 break;
671 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;
686 break;
687 default:
688 err_setstr(RuntimeError,
689 "don't know how to byteswap this array type");
690 return NULL;
692 INCREF(None);
693 return None;
696 static object *
697 array_reverse(self, args)
698 arrayobject *self;
699 object *args;
701 register int itemsize = self->ob_descr->itemsize;
702 register char *p, *q;
703 char tmp[sizeof(double)]; /* Assume that's the max item size */
705 if (args != NULL) {
706 err_badarg();
707 return NULL;
710 if (self->ob_size > 1) {
711 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);
721 INCREF(None);
722 return None;
725 /* The following routines were adapted from listobject.c but not converted.
726 To make them work you will have to work! */
728 #if 0
729 static object *
730 array_index(self, args)
731 arrayobject *self;
732 object *args;
734 int i;
736 if (args == NULL) {
737 err_badarg();
738 return NULL;
740 for (i = 0; i < self->ob_size; i++) {
741 if (cmpobject(self->ob_item[i], args) == 0)
742 return newintobject((long)i);
744 err_setstr(ValueError, "array.index(x): x not in array");
745 return NULL;
747 #endif
749 #if 0
750 static object *
751 array_count(self, args)
752 arrayobject *self;
753 object *args;
755 int count = 0;
756 int i;
758 if (args == NULL) {
759 err_badarg();
760 return NULL;
762 for (i = 0; i < self->ob_size; i++) {
763 if (cmpobject(self->ob_item[i], args) == 0)
764 count++;
766 return newintobject((long)count);
768 #endif
770 #if 0
771 static object *
772 array_remove(self, args)
773 arrayobject *self;
774 object *args;
776 int i;
778 if (args == NULL) {
779 err_badarg();
780 return NULL;
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;
791 err_setstr(ValueError, "array.remove(x): x not in array");
792 return NULL;
794 #endif
796 static object *
797 array_fromfile(self, args)
798 arrayobject *self;
799 object *args;
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;
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;
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;
832 INCREF(None);
833 return None;
836 static object *
837 array_tofile(self, args)
838 arrayobject *self;
839 object *args;
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;
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;
858 INCREF(None);
859 return None;
862 static object *
863 array_fromlist(self, args)
864 arrayobject *self;
865 object *args;
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;
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;
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;
898 INCREF(None);
899 return None;
902 static object *
903 array_tolist(self, args)
904 arrayobject *self;
905 object *args;
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;
917 setlistitem(list, i, v);
919 return list;
922 static object *
923 array_fromstring(self, args)
924 arrayobject *self;
925 object *args;
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;
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;
945 self->ob_item = item;
946 self->ob_size += n;
947 memcpy(item + (self->ob_size - n) * itemsize, str, itemsize*n);
949 INCREF(None);
950 return None;
953 static object *
954 array_tostring(self, args)
955 arrayobject *self;
956 object *args;
958 if (!getargs(args, ""))
959 return NULL;
960 return newsizedstringobject(self->ob_item,
961 self->ob_size * self->ob_descr->itemsize);
964 static struct methodlist array_methods[] = {
965 {"append", array_append},
966 {"byteswap", array_byteswap},
967 /* {"count", array_count},*/
968 {"fromfile", array_fromfile},
969 {"fromlist", array_fromlist},
970 {"fromstring", array_fromstring},
971 /* {"index", array_index},*/
972 {"insert", array_insert},
973 {"read", array_fromfile},
974 /* {"remove", array_remove},*/
975 {"reverse", array_reverse},
976 /* {"sort", array_sort},*/
977 {"tofile", array_tofile},
978 {"tolist", array_tolist},
979 {"tostring", array_tostring},
980 {"write", array_tofile},
981 {NULL, NULL} /* sentinel */
984 static object *
985 array_getattr(a, name)
986 arrayobject *a;
987 char *name;
989 if (strcmp(name, "typecode") == 0) {
990 char tc = a->ob_descr->typecode;
991 return newsizedstringobject(&tc, 1);
993 if (strcmp(name, "itemsize") == 0) {
994 return newintobject((long)a->ob_descr->itemsize);
996 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;
1006 return list;
1008 return findmethod(array_methods, (object *)a, name);
1011 static int
1012 array_print(a, fp, flags)
1013 arrayobject *a;
1014 FILE *fp;
1015 int flags;
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;
1025 if (a->ob_descr->typecode == 'c') {
1026 fprintf(fp, "array('c', ");
1027 v = array_tostring(a, (object *)NULL);
1028 ok = printobject(v, fp, 0);
1029 XDECREF(v);
1030 fprintf(fp, ")");
1031 return ok;
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);
1038 ok = printobject(v, fp, 0);
1039 XDECREF(v);
1041 fprintf(fp, "])");
1042 return ok;
1045 static object *
1046 array_repr(a)
1047 arrayobject *a;
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);
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;
1072 return s;
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);
1086 XDECREF(comma);
1087 t = newstringobject("])");
1088 joinstring(&s, t);
1089 XDECREF(t);
1090 if (err_occurred()) {
1091 XDECREF(s);
1092 s = NULL;
1094 return s;
1097 static 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*/
1107 typeobject Arraytype = {
1108 OB_HEAD_INIT(&Typetype)
1110 "array",
1111 sizeof(arrayobject),
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*/
1125 static object *
1126 a_array(self, args)
1127 object *self;
1128 object *args;
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;
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;
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;
1171 DECREF(v);
1173 return a;
1176 err_setstr(ValueError, "bad typecode (must be c, b, h, l, f or d)");
1177 return NULL;
1180 static struct methodlist a_methods[] = {
1181 {"array", a_array},
1182 {NULL, NULL} /* sentinel */
1185 void
1186 initarray()
1188 initmodule("array", a_methods);
1192 #ifdef NEED_MEMMOVE
1194 /* A perhaps slow but I hope correct implementation of memmove */
1196 char *memmove(dst, src, n)
1197 char *dst;
1198 char *src;
1199 int n;
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++;
1210 else if (src < dst) {
1211 src += n;
1212 dst += n;
1213 while (--n >= 0)
1214 *--dst = *--src;
1216 return realdst;
1219 #endif