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