blob: 2584b03aa1c8bb60e365426c417f1a40581e81f9 [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{
Guido van Rossum778983b1993-02-19 15:55:02 +0000242 arrayobject *op;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000243 size_t nbytes;
Guido van Rossum778983b1993-02-19 15:55:02 +0000244 if (size < 0) {
245 err_badcall();
246 return NULL;
247 }
248 nbytes = size * descr->itemsize;
249 /* Check for overflow */
250 if (nbytes / descr->itemsize != size) {
251 return err_nomem();
252 }
Guido van Rossume77a7571993-11-03 15:01:26 +0000253 op = NEW(arrayobject, 1);
Guido van Rossum778983b1993-02-19 15:55:02 +0000254 if (op == NULL) {
255 return err_nomem();
256 }
257 if (size <= 0) {
258 op->ob_item = NULL;
259 }
260 else {
Guido van Rossume77a7571993-11-03 15:01:26 +0000261 op->ob_item = NEW(char, nbytes);
Guido van Rossum778983b1993-02-19 15:55:02 +0000262 if (op->ob_item == NULL) {
Guido van Rossume77a7571993-11-03 15:01:26 +0000263 DEL(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000264 return err_nomem();
265 }
266 }
Guido van Rossum778983b1993-02-19 15:55:02 +0000267 op->ob_type = &Arraytype;
268 op->ob_size = size;
269 op->ob_descr = descr;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000270 NEWREF(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000271 return (object *) op;
272}
273
274int
275getarraysize(op)
276 object *op;
277{
278 if (!is_arrayobject(op)) {
279 err_badcall();
280 return -1;
281 }
282 return ((arrayobject *)op) -> ob_size;
283}
284
285object *
286getarrayitem(op, i)
287 object *op;
288 int i;
289{
290 register arrayobject *ap;
291 if (!is_arrayobject(op)) {
292 err_badcall();
293 return NULL;
294 }
295 ap = (arrayobject *)op;
296 if (i < 0 || i >= ap->ob_size) {
297 err_setstr(IndexError, "array index out of range");
298 return NULL;
299 }
300 return (*ap->ob_descr->getitem)(ap, i);
301}
302
303static int
304ins1(self, where, v)
305 arrayobject *self;
306 int where;
307 object *v;
308{
Guido van Rossum778983b1993-02-19 15:55:02 +0000309 char *items;
310 if (v == NULL) {
311 err_badcall();
312 return -1;
313 }
314 if ((*self->ob_descr->setitem)(self, -1, v) < 0)
315 return -1;
316 items = self->ob_item;
317 RESIZE(items, char, (self->ob_size+1) * self->ob_descr->itemsize);
318 if (items == NULL) {
319 err_nomem();
320 return -1;
321 }
322 if (where < 0)
323 where = 0;
324 if (where > self->ob_size)
325 where = self->ob_size;
326 memmove(items + (where+1)*self->ob_descr->itemsize,
327 items + where*self->ob_descr->itemsize,
328 (self->ob_size-where)*self->ob_descr->itemsize);
329 self->ob_item = items;
330 self->ob_size++;
331 return (*self->ob_descr->setitem)(self, where, v);
332}
333
334int
335insarrayitem(op, where, newitem)
336 object *op;
337 int where;
338 object *newitem;
339{
340 if (!is_arrayobject(op)) {
341 err_badcall();
342 return -1;
343 }
344 return ins1((arrayobject *)op, where, newitem);
345}
346
347int
348addarrayitem(op, newitem)
349 object *op;
350 object *newitem;
351{
352 if (!is_arrayobject(op)) {
353 err_badcall();
354 return -1;
355 }
356 return ins1((arrayobject *)op,
357 (int) ((arrayobject *)op)->ob_size, newitem);
358}
359
360/* Methods */
361
362static void
363array_dealloc(op)
364 arrayobject *op;
365{
Guido van Rossum778983b1993-02-19 15:55:02 +0000366 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;
Guido van Rossum778983b1993-02-19 15:55:02 +0000421 if (ilow < 0)
422 ilow = 0;
423 else if (ilow > a->ob_size)
424 ilow = a->ob_size;
425 if (ihigh < 0)
426 ihigh = 0;
427 if (ihigh < ilow)
428 ihigh = ilow;
429 else if (ihigh > a->ob_size)
430 ihigh = a->ob_size;
431 np = (arrayobject *) newarrayobject(ihigh - ilow, a->ob_descr);
432 if (np == NULL)
433 return NULL;
434 memcpy(np->ob_item, a->ob_item + ilow * a->ob_descr->itemsize,
435 (ihigh-ilow) * a->ob_descr->itemsize);
436 return (object *)np;
437}
438
439static object *
440array_concat(a, bb)
441 arrayobject *a;
442 object *bb;
443{
444 int size;
Guido van Rossum778983b1993-02-19 15:55:02 +0000445 arrayobject *np;
446 if (!is_arrayobject(bb)) {
447 err_badarg();
448 return NULL;
449 }
450#define b ((arrayobject *)bb)
451 if (a->ob_descr != b->ob_descr) {
452 err_badarg();
453 return NULL;
454 }
455 size = a->ob_size + b->ob_size;
456 np = (arrayobject *) newarrayobject(size, a->ob_descr);
457 if (np == NULL) {
458 return NULL;
459 }
460 memcpy(np->ob_item, a->ob_item, a->ob_size*a->ob_descr->itemsize);
461 memcpy(np->ob_item + a->ob_size*a->ob_descr->itemsize,
Guido van Rossum32be3a71993-11-05 10:16:27 +0000462 b->ob_item, b->ob_size*b->ob_descr->itemsize);
Guido van Rossum778983b1993-02-19 15:55:02 +0000463 return (object *)np;
464#undef b
465}
466
467static object *
468array_repeat(a, n)
469 arrayobject *a;
470 int n;
471{
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000472 int i;
Guido van Rossum778983b1993-02-19 15:55:02 +0000473 int size;
474 arrayobject *np;
475 char *p;
476 int nbytes;
477 if (n < 0)
478 n = 0;
479 size = a->ob_size * n;
480 np = (arrayobject *) newarrayobject(size, a->ob_descr);
481 if (np == NULL)
482 return NULL;
483 p = np->ob_item;
484 nbytes = a->ob_size * a->ob_descr->itemsize;
485 for (i = 0; i < n; i++) {
486 memcpy(p, a->ob_item, nbytes);
487 p += nbytes;
488 }
489 return (object *) np;
490}
491
492static int
493array_ass_slice(a, ilow, ihigh, v)
494 arrayobject *a;
495 int ilow, ihigh;
496 object *v;
497{
498 char *item;
499 int n; /* Size of replacement array */
500 int d; /* Change in size */
Guido van Rossum778983b1993-02-19 15:55:02 +0000501#define b ((arrayobject *)v)
502 if (v == NULL)
503 n = 0;
504 else if (is_arrayobject(v)) {
505 n = b->ob_size;
506 if (a == b) {
507 /* Special case "a[i:j] = a" -- copy b first */
508 int ret;
509 v = array_slice(b, 0, n);
510 ret = array_ass_slice(a, ilow, ihigh, v);
511 DECREF(v);
512 return ret;
513 }
514 if (b->ob_descr != a->ob_descr) {
515 err_badarg();
516 return -1;
517 }
518 }
519 else {
520 err_badarg();
521 return -1;
522 }
523 if (ilow < 0)
524 ilow = 0;
525 else if (ilow > a->ob_size)
526 ilow = a->ob_size;
527 if (ihigh < 0)
528 ihigh = 0;
529 if (ihigh < ilow)
530 ihigh = ilow;
531 else if (ihigh > a->ob_size)
532 ihigh = a->ob_size;
533 item = a->ob_item;
534 d = n - (ihigh-ilow);
535 if (d < 0) { /* Delete -d items */
536 memmove(item + (ihigh+d)*a->ob_descr->itemsize,
537 item + ihigh*a->ob_descr->itemsize,
538 (a->ob_size-ihigh)*a->ob_descr->itemsize);
539 a->ob_size += d;
540 RESIZE(item, char, a->ob_size*a->ob_descr->itemsize);
541 /* Can't fail */
542 a->ob_item = item;
543 }
544 else if (d > 0) { /* Insert d items */
545 RESIZE(item, char, (a->ob_size + d)*a->ob_descr->itemsize);
546 if (item == NULL) {
547 err_nomem();
548 return -1;
549 }
550 memmove(item + (ihigh+d)*a->ob_descr->itemsize,
551 item + ihigh*a->ob_descr->itemsize,
552 (a->ob_size-ihigh)*a->ob_descr->itemsize);
553 a->ob_item = item;
554 a->ob_size += d;
555 }
556 if (n > 0)
557 memcpy(item + ilow*a->ob_descr->itemsize, b->ob_item,
558 n*b->ob_descr->itemsize);
559 return 0;
560#undef b
561}
562
563static int
564array_ass_item(a, i, v)
565 arrayobject *a;
566 int i;
567 object *v;
568{
569 if (i < 0 || i >= a->ob_size) {
570 err_setstr(IndexError, "array assignment index out of range");
571 return -1;
572 }
573 if (v == NULL)
574 return array_ass_slice(a, i, i+1, v);
575 return (*a->ob_descr->setitem)(a, i, v);
576}
577
578static int
579setarrayitem(a, i, v)
580 object *a;
581 int i;
582 object *v;
583{
584 if (!is_arrayobject(a)) {
585 err_badcall();
586 return -1;
587 }
588 return array_ass_item((arrayobject *)a, i, v);
589}
590
591static object *
592ins(self, where, v)
593 arrayobject *self;
594 int where;
595 object *v;
596{
597 if (ins1(self, where, v) != 0)
598 return NULL;
599 INCREF(None);
600 return None;
601}
602
603static object *
604array_insert(self, args)
605 arrayobject *self;
606 object *args;
607{
608 int i;
609 object *v;
610 if (!getargs(args, "(iO)", &i, &v))
611 return NULL;
612 return ins(self, i, v);
613}
614
615static object *
616array_append(self, args)
617 arrayobject *self;
618 object *args;
619{
620 object *v;
621 if (!getargs(args, "O", &v))
622 return NULL;
623 return ins(self, (int) self->ob_size, v);
624}
625
626static object *
627array_byteswap(self, args)
628 arrayobject *self;
629 object *args;
630{
631 char *p;
632 int i;
633 switch (self->ob_descr->itemsize) {
634 case 1:
635 break;
636 case 2:
637 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 2) {
638 char p0 = p[0];
639 p[0] = p[1];
640 p[1] = p0;
641 }
642 break;
643 case 4:
644 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 4) {
645 char p0 = p[0];
646 char p1 = p[1];
647 p[0] = p[3];
648 p[1] = p[2];
649 p[2] = p1;
650 p[3] = p0;
651 }
652 break;
Guido van Rossume77a7571993-11-03 15:01:26 +0000653 case 8:
654 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 8) {
655 char p0 = p[0];
656 char p1 = p[1];
657 char p2 = p[2];
658 char p3 = p[3];
659 p[0] = p[7];
660 p[1] = p[6];
661 p[2] = p[5];
662 p[3] = p[4];
663 p[4] = p3;
664 p[5] = p2;
665 p[6] = p1;
666 p[7] = p0;
667 }
668 break;
Guido van Rossum778983b1993-02-19 15:55:02 +0000669 default:
670 err_setstr(RuntimeError,
671 "don't know how to byteswap this array type");
672 return NULL;
673 }
674 INCREF(None);
675 return None;
676}
677
Guido van Rossum778983b1993-02-19 15:55:02 +0000678static object *
679array_reverse(self, args)
680 arrayobject *self;
681 object *args;
682{
Guido van Rossume77a7571993-11-03 15:01:26 +0000683 register int itemsize = self->ob_descr->itemsize;
684 register char *p, *q;
685 char tmp[sizeof(double)]; /* Assume that's the max item size */
686
Guido van Rossum778983b1993-02-19 15:55:02 +0000687 if (args != NULL) {
688 err_badarg();
689 return NULL;
690 }
691
692 if (self->ob_size > 1) {
Guido van Rossume77a7571993-11-03 15:01:26 +0000693 for (p = self->ob_item,
694 q = self->ob_item + (self->ob_size - 1)*itemsize;
695 p < q;
696 p += itemsize, q -= itemsize) {
697 memmove(tmp, p, itemsize);
698 memmove(p, q, itemsize);
699 memmove(q, tmp, itemsize);
Guido van Rossum778983b1993-02-19 15:55:02 +0000700 }
701 }
702
703 INCREF(None);
704 return None;
705}
Guido van Rossume77a7571993-11-03 15:01:26 +0000706
707/* The following routines were adapted from listobject.c but not converted.
708 To make them work you will have to work! */
Guido van Rossum778983b1993-02-19 15:55:02 +0000709
710#if 0
711static object *
712array_index(self, args)
713 arrayobject *self;
714 object *args;
715{
716 int i;
717
718 if (args == NULL) {
719 err_badarg();
720 return NULL;
721 }
722 for (i = 0; i < self->ob_size; i++) {
723 if (cmpobject(self->ob_item[i], args) == 0)
724 return newintobject((long)i);
725 }
726 err_setstr(ValueError, "array.index(x): x not in array");
727 return NULL;
728}
729#endif
730
731#if 0
732static object *
733array_count(self, args)
734 arrayobject *self;
735 object *args;
736{
737 int count = 0;
738 int i;
739
740 if (args == NULL) {
741 err_badarg();
742 return NULL;
743 }
744 for (i = 0; i < self->ob_size; i++) {
745 if (cmpobject(self->ob_item[i], args) == 0)
746 count++;
747 }
748 return newintobject((long)count);
749}
750#endif
751
752#if 0
753static object *
754array_remove(self, args)
755 arrayobject *self;
756 object *args;
757{
758 int i;
759
760 if (args == NULL) {
761 err_badarg();
762 return NULL;
763 }
764 for (i = 0; i < self->ob_size; i++) {
765 if (cmpobject(self->ob_item[i], args) == 0) {
766 if (array_ass_slice(self, i, i+1, (object *)NULL) != 0)
767 return NULL;
768 INCREF(None);
769 return None;
770 }
771
772 }
773 err_setstr(ValueError, "array.remove(x): x not in array");
774 return NULL;
775}
776#endif
777
778static object *
Guido van Rossume77a7571993-11-03 15:01:26 +0000779array_fromfile(self, args)
Guido van Rossum778983b1993-02-19 15:55:02 +0000780 arrayobject *self;
781 object *args;
782{
783 object *f;
784 int n;
785 FILE *fp;
786 if (!getargs(args, "(Oi)", &f, &n))
787 return NULL;
788 fp = getfilefile(f);
789 if (fp == NULL) {
790 err_setstr(TypeError, "arg1 must be open file");
791 return NULL;
792 }
793 if (n > 0) {
794 char *item = self->ob_item;
795 int itemsize = self->ob_descr->itemsize;
796 int nread;
797 RESIZE(item, char, (self->ob_size + n) * itemsize);
798 if (item == NULL) {
799 err_nomem();
800 return NULL;
801 }
802 self->ob_item = item;
803 self->ob_size += n;
804 nread = fread(item + (self->ob_size - n) * itemsize,
805 itemsize, n, fp);
806 if (nread < n) {
807 self->ob_size -= (n - nread);
808 RESIZE(item, char, self->ob_size*itemsize);
809 self->ob_item = item;
810 err_setstr(EOFError, "not enough items in file");
811 return NULL;
812 }
813 }
814 INCREF(None);
815 return None;
816}
817
818static object *
Guido van Rossume77a7571993-11-03 15:01:26 +0000819array_tofile(self, args)
Guido van Rossum778983b1993-02-19 15:55:02 +0000820 arrayobject *self;
821 object *args;
822{
823 object *f;
824 FILE *fp;
825 if (!getargs(args, "O", &f))
826 return NULL;
827 fp = getfilefile(f);
828 if (fp == NULL) {
829 err_setstr(TypeError, "arg must be open file");
830 return NULL;
831 }
832 if (self->ob_size > 0) {
833 if (fwrite(self->ob_item, self->ob_descr->itemsize,
834 self->ob_size, fp) != self->ob_size) {
835 err_errno(IOError);
836 clearerr(fp);
837 return NULL;
838 }
839 }
840 INCREF(None);
841 return None;
842}
843
844static object *
845array_fromlist(self, args)
846 arrayobject *self;
847 object *args;
848{
849 int n;
850 object *list;
851 int itemsize = self->ob_descr->itemsize;
852 if (!getargs(args, "O", &list))
853 return NULL;
854 if (!is_listobject(list)) {
855 err_setstr(TypeError, "arg must be list");
856 return NULL;
857 }
858 n = getlistsize(list);
859 if (n > 0) {
860 char *item = self->ob_item;
861 int i;
862 RESIZE(item, char, (self->ob_size + n) * itemsize);
863 if (item == NULL) {
864 err_nomem();
865 return NULL;
866 }
867 self->ob_item = item;
868 self->ob_size += n;
869 for (i = 0; i < n; i++) {
870 object *v = getlistitem(list, i);
871 if ((*self->ob_descr->setitem)(self,
872 self->ob_size - n + i, v) != 0) {
873 self->ob_size -= n;
874 RESIZE(item, char, self->ob_size * itemsize);
875 self->ob_item = item;
876 return NULL;
877 }
878 }
879 }
880 INCREF(None);
881 return None;
882}
883
884static object *
885array_tolist(self, args)
886 arrayobject *self;
887 object *args;
888{
889 object *list = newlistobject(self->ob_size);
890 int i;
891 if (list == NULL)
892 return NULL;
893 for (i = 0; i < self->ob_size; i++) {
894 object *v = getarrayitem((object *)self, i);
895 if (v == NULL) {
896 DECREF(list);
897 return NULL;
898 }
899 setlistitem(list, i, v);
900 }
901 return list;
902}
903
904static object *
905array_fromstring(self, args)
906 arrayobject *self;
907 object *args;
908{
909 char *str;
910 int n;
911 int itemsize = self->ob_descr->itemsize;
912 if (!getargs(args, "s#", &str, &n))
913 return NULL;
914 if (n % itemsize != 0) {
915 err_setstr(ValueError,
916 "string length not a multiple of item size");
917 return NULL;
918 }
919 n = n / itemsize;
920 if (n > 0) {
921 char *item = self->ob_item;
922 RESIZE(item, char, (self->ob_size + n) * itemsize);
923 if (item == NULL) {
924 err_nomem();
925 return NULL;
926 }
927 self->ob_item = item;
928 self->ob_size += n;
929 memcpy(item + (self->ob_size - n) * itemsize, str, itemsize*n);
930 }
931 INCREF(None);
932 return None;
933}
934
935static object *
936array_tostring(self, args)
937 arrayobject *self;
938 object *args;
939{
940 if (!getargs(args, ""))
941 return NULL;
942 return newsizedstringobject(self->ob_item,
943 self->ob_size * self->ob_descr->itemsize);
944}
945
946static struct methodlist array_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000947 {"append", (method)array_append},
948 {"byteswap", (method)array_byteswap},
949/* {"count", (method)array_count},*/
950 {"fromfile", (method)array_fromfile},
951 {"fromlist", (method)array_fromlist},
952 {"fromstring", (method)array_fromstring},
953/* {"index", (method)array_index},*/
954 {"insert", (method)array_insert},
955 {"read", (method)array_fromfile},
956/* {"remove", (method)array_remove},*/
957 {"reverse", (method)array_reverse},
958/* {"sort", (method)array_sort},*/
959 {"tofile", (method)array_tofile},
960 {"tolist", (method)array_tolist},
961 {"tostring", (method)array_tostring},
962 {"write", (method)array_tofile},
Guido van Rossum778983b1993-02-19 15:55:02 +0000963 {NULL, NULL} /* sentinel */
964};
965
966static object *
967array_getattr(a, name)
968 arrayobject *a;
969 char *name;
970{
971 if (strcmp(name, "typecode") == 0) {
972 char tc = a->ob_descr->typecode;
973 return newsizedstringobject(&tc, 1);
974 }
975 if (strcmp(name, "itemsize") == 0) {
976 return newintobject((long)a->ob_descr->itemsize);
977 }
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000978 if (strcmp(name, "__members__") == 0) {
979 object *list = newlistobject(2);
980 if (list) {
981 setlistitem(list, 0, newstringobject("typecode"));
982 setlistitem(list, 1, newstringobject("itemsize"));
983 if (err_occurred()) {
984 DECREF(list);
985 list = NULL;
986 }
987 }
988 return list;
989 }
Guido van Rossum778983b1993-02-19 15:55:02 +0000990 return findmethod(array_methods, (object *)a, name);
991}
992
993static int
994array_print(a, fp, flags)
995 arrayobject *a;
996 FILE *fp;
997 int flags;
998{
999 int ok = 0;
1000 int i, len;
1001 object *v;
1002 len = a->ob_size;
1003 if (len == 0) {
1004 fprintf(fp, "array('%c')", a->ob_descr->typecode);
1005 return ok;
1006 }
1007 if (a->ob_descr->typecode == 'c') {
1008 fprintf(fp, "array('c', ");
1009 v = array_tostring(a, (object *)NULL);
Guido van Rossuma3d78fb1993-11-10 09:23:53 +00001010 ok = printobject(v, fp, 0);
Guido van Rossum778983b1993-02-19 15:55:02 +00001011 XDECREF(v);
1012 fprintf(fp, ")");
1013 return ok;
1014 }
1015 fprintf(fp, "array('%c', [", a->ob_descr->typecode);
1016 for (i = 0; i < len && ok == 0; i++) {
1017 if (i > 0)
1018 fprintf(fp, ", ");
1019 v = (a->ob_descr->getitem)(a, i);
Guido van Rossuma3d78fb1993-11-10 09:23:53 +00001020 ok = printobject(v, fp, 0);
Guido van Rossum778983b1993-02-19 15:55:02 +00001021 XDECREF(v);
1022 }
1023 fprintf(fp, "])");
1024 return ok;
1025}
1026
1027static object *
1028array_repr(a)
1029 arrayobject *a;
1030{
1031 char buf[256];
1032 object *s, *t, *comma, *v;
1033 int i, len;
1034 len = a->ob_size;
1035 if (len == 0) {
1036 sprintf(buf, "array('%c')", a->ob_descr->typecode);
1037 return newstringobject(buf);
1038 }
1039 if (a->ob_descr->typecode == 'c') {
1040 sprintf(buf, "array('c', ");
1041 s = newstringobject(buf);
1042 v = array_tostring(a, (object *)NULL);
1043 t = reprobject(v);
1044 XDECREF(v);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001045 joinstring_decref(&s, t);
1046 joinstring_decref(&s, newstringobject(")"));
Guido van Rossum778983b1993-02-19 15:55:02 +00001047 return s;
1048 }
1049 sprintf(buf, "array('%c', [", a->ob_descr->typecode);
1050 s = newstringobject(buf);
1051 comma = newstringobject(", ");
1052 for (i = 0; i < len && !err_occurred(); i++) {
Guido van Rossumb6775db1994-08-01 11:34:53 +00001053 if (i > 0)
1054 joinstring(&s, comma);
Guido van Rossum778983b1993-02-19 15:55:02 +00001055 v = (a->ob_descr->getitem)(a, i);
1056 t = reprobject(v);
1057 XDECREF(v);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001058 joinstring_decref(&s, t);
Guido van Rossum778983b1993-02-19 15:55:02 +00001059 }
1060 XDECREF(comma);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001061 joinstring_decref(&s, newstringobject("])"));
Guido van Rossum778983b1993-02-19 15:55:02 +00001062 return s;
1063}
1064
1065static sequence_methods array_as_sequence = {
Guido van Rossumb6775db1994-08-01 11:34:53 +00001066 (inquiry)array_length, /*sq_length*/
1067 (binaryfunc)array_concat, /*sq_concat*/
1068 (intargfunc)array_repeat, /*sq_repeat*/
1069 (intargfunc)array_item, /*sq_item*/
1070 (intintargfunc)array_slice, /*sq_slice*/
1071 (intobjargproc)array_ass_item, /*sq_ass_item*/
1072 (intintobjargproc)array_ass_slice, /*sq_ass_slice*/
Guido van Rossum778983b1993-02-19 15:55:02 +00001073};
1074
Guido van Rossumb6775db1994-08-01 11:34:53 +00001075static typeobject Arraytype = {
Guido van Rossum778983b1993-02-19 15:55:02 +00001076 OB_HEAD_INIT(&Typetype)
1077 0,
1078 "array",
1079 sizeof(arrayobject),
1080 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +00001081 (destructor)array_dealloc, /*tp_dealloc*/
1082 (printfunc)array_print, /*tp_print*/
1083 (getattrfunc)array_getattr, /*tp_getattr*/
1084 0, /*tp_setattr*/
1085 (cmpfunc)array_compare, /*tp_compare*/
1086 (reprfunc)array_repr, /*tp_repr*/
1087 0, /*tp_as_number*/
1088 &array_as_sequence, /*tp_as_sequence*/
1089 0, /*tp_as_mapping*/
Guido van Rossum778983b1993-02-19 15:55:02 +00001090};
1091
1092
1093static object *
1094a_array(self, args)
1095 object *self;
1096 object *args;
1097{
1098 char c;
1099 object *initial = NULL;
1100 struct arraydescr *descr;
1101 if (!getargs(args, "c", &c)) {
1102 err_clear();
1103 if (!getargs(args, "(cO)", &c, &initial))
1104 return NULL;
1105 if (!is_listobject(initial) && !is_stringobject(initial)) {
1106 err_setstr(TypeError,
1107 "array initializer must be list or string");
1108 return NULL;
1109 }
1110 }
1111 for (descr = descriptors; descr->typecode != '\0'; descr++) {
1112 if (descr->typecode == c) {
1113 object *a;
1114 int len;
1115 if (initial == NULL || !is_listobject(initial))
1116 len = 0;
1117 else
1118 len = getlistsize(initial);
1119 a = newarrayobject(len, descr);
1120 if (a == NULL)
1121 return NULL;
1122 if (len > 0) {
1123 int i;
1124 for (i = 0; i < len; i++) {
1125 object *v = getlistitem(initial, i);
1126 if (setarrayitem(a, i, v) != 0) {
1127 DECREF(a);
1128 return NULL;
1129 }
1130 }
1131 }
1132 if (initial != NULL && is_stringobject(initial)) {
1133 object *v =
1134 array_fromstring((arrayobject *)a, initial);
1135 if (v == NULL) {
1136 DECREF(a);
1137 return NULL;
1138 }
1139 DECREF(v);
1140 }
1141 return a;
1142 }
1143 }
1144 err_setstr(ValueError, "bad typecode (must be c, b, h, l, f or d)");
1145 return NULL;
1146}
1147
1148static struct methodlist a_methods[] = {
1149 {"array", a_array},
1150 {NULL, NULL} /* sentinel */
1151};
1152
1153void
1154initarray()
1155{
1156 initmodule("array", a_methods);
1157}