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