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