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