blob: 2657528dd51e4b238f63208c6353cd82656ffbdf [file] [log] [blame]
Guido van Rossum778983b1993-02-19 15:55:02 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum778983b1993-02-19 15:55:02 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum778983b1993-02-19 15:55:02 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum778983b1993-02-19 15:55:02 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum778983b1993-02-19 15:55:02 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum778983b1993-02-19 15:55:02 +000029
30******************************************************************/
31
32/* Array object implementation */
33
34/* An array is a uniform list -- all items have the same type.
35 The item type is restricted to simple C types like int or float */
36
37#include "allobjects.h"
38#include "modsupport.h"
39#include "ceval.h"
Guido van Rossum0c709541994-08-19 12:01:32 +000040#ifdef STDC_HEADERS
41#include <stddef.h>
42#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000043#include <sys/types.h> /* For size_t */
Guido van Rossum0c709541994-08-19 12:01:32 +000044#endif
Guido van Rossum778983b1993-02-19 15:55:02 +000045
46struct arrayobject; /* Forward */
47
48struct arraydescr {
49 int typecode;
50 int itemsize;
51 object * (*getitem) FPROTO((struct arrayobject *, int));
52 int (*setitem) FPROTO((struct arrayobject *, int, object *));
53};
54
55typedef struct arrayobject {
56 OB_VARHEAD
57 char *ob_item;
58 struct arraydescr *ob_descr;
59} arrayobject;
60
Guido van Rossumb6775db1994-08-01 11:34:53 +000061staticforward typeobject Arraytype;
Guido van Rossum778983b1993-02-19 15:55:02 +000062
63#define is_arrayobject(op) ((op)->ob_type == &Arraytype)
64
Guido van Rossumb73cc041993-11-01 16:28:59 +000065/* Forward */
Guido van Rossumcd938fc1995-01-17 16:13:48 +000066static object *newarrayobject PROTO((int, struct arraydescr *));
67static int getarraysize PROTO((object *));
68static object *getarrayitem PROTO((object *, int));
Guido van Rossumb73cc041993-11-01 16:28:59 +000069static int setarrayitem PROTO((object *, int, object *));
Guido van Rossumcd938fc1995-01-17 16:13:48 +000070static int insarrayitem PROTO((object *, int, object *));
71static int addarrayitem PROTO((object *, object *));
Guido van Rossum778983b1993-02-19 15:55:02 +000072
73static object *
74c_getitem(ap, i)
75 arrayobject *ap;
76 int i;
77{
78 return newsizedstringobject(&((char *)ap->ob_item)[i], 1);
79}
80
81static int
82c_setitem(ap, i, v)
83 arrayobject *ap;
84 int i;
85 object *v;
86{
87 char x;
88 if (!getargs(v, "c;array item must be char", &x))
89 return -1;
90 if (i >= 0)
91 ((char *)ap->ob_item)[i] = x;
92 return 0;
93}
94
95static object *
96b_getitem(ap, i)
97 arrayobject *ap;
98 int i;
99{
100 long x = ((char *)ap->ob_item)[i];
101 if (x >= 128)
102 x -= 256;
103 return newintobject(x);
104}
105
106static int
107b_setitem(ap, i, v)
108 arrayobject *ap;
109 int i;
110 object *v;
111{
112 char x;
113 if (!getargs(v, "b;array item must be integer", &x))
114 return -1;
115 if (i >= 0)
116 ((char *)ap->ob_item)[i] = x;
117 return 0;
118}
119
120static object *
121h_getitem(ap, i)
122 arrayobject *ap;
123 int i;
124{
125 return newintobject((long) ((short *)ap->ob_item)[i]);
126}
127
128static int
129h_setitem(ap, i, v)
130 arrayobject *ap;
131 int i;
132 object *v;
133{
134 short x;
135 if (!getargs(v, "h;array item must be integer", &x))
136 return -1;
137 if (i >= 0)
138 ((short *)ap->ob_item)[i] = x;
139 return 0;
140}
141
142static object *
Guido van Rossume77a7571993-11-03 15:01:26 +0000143i_getitem(ap, i)
144 arrayobject *ap;
145 int i;
146{
147 return newintobject((long) ((int *)ap->ob_item)[i]);
148}
149
150static int
151i_setitem(ap, i, v)
152 arrayobject *ap;
153 int i;
154 object *v;
155{
156 int x;
157 if (!getargs(v, "i;array item must be integer", &x))
158 return -1;
159 if (i >= 0)
160 ((int *)ap->ob_item)[i] = x;
161 return 0;
162}
163
164static object *
Guido van Rossum778983b1993-02-19 15:55:02 +0000165l_getitem(ap, i)
166 arrayobject *ap;
167 int i;
168{
169 return newintobject(((long *)ap->ob_item)[i]);
170}
171
172static int
173l_setitem(ap, i, v)
174 arrayobject *ap;
175 int i;
176 object *v;
177{
178 long x;
179 if (!getargs(v, "l;array item must be integer", &x))
180 return -1;
181 if (i >= 0)
182 ((long *)ap->ob_item)[i] = x;
183 return 0;
184}
185
186static object *
187f_getitem(ap, i)
188 arrayobject *ap;
189 int i;
190{
191 return newfloatobject((double) ((float *)ap->ob_item)[i]);
192}
193
194static int
195f_setitem(ap, i, v)
196 arrayobject *ap;
197 int i;
198 object *v;
199{
200 float x;
201 if (!getargs(v, "f;array item must be float", &x))
202 return -1;
203 if (i >= 0)
204 ((float *)ap->ob_item)[i] = x;
205 return 0;
206}
207
208static object *
209d_getitem(ap, i)
210 arrayobject *ap;
211 int i;
212{
213 return newfloatobject(((double *)ap->ob_item)[i]);
214}
215
216static int
217d_setitem(ap, i, v)
218 arrayobject *ap;
219 int i;
220 object *v;
221{
222 double x;
223 if (!getargs(v, "d;array item must be float", &x))
224 return -1;
225 if (i >= 0)
226 ((double *)ap->ob_item)[i] = x;
227 return 0;
228}
229
230/* Description of types */
Guido van Rossum234f9421993-06-17 12:35:49 +0000231static struct arraydescr descriptors[] = {
Guido van Rossum778983b1993-02-19 15:55:02 +0000232 {'c', sizeof(char), c_getitem, c_setitem},
233 {'b', sizeof(char), b_getitem, b_setitem},
234 {'h', sizeof(short), h_getitem, h_setitem},
Guido van Rossume77a7571993-11-03 15:01:26 +0000235 {'i', sizeof(int), i_getitem, i_setitem},
Guido van Rossum778983b1993-02-19 15:55:02 +0000236 {'l', sizeof(long), l_getitem, l_setitem},
237 {'f', sizeof(float), f_getitem, f_setitem},
238 {'d', sizeof(double), d_getitem, d_setitem},
239 {'\0', 0, 0, 0} /* Sentinel */
240};
Guido van Rossume77a7571993-11-03 15:01:26 +0000241/* If we ever allow items larger than double, we must change reverse()! */
Guido van Rossum778983b1993-02-19 15:55:02 +0000242
243
Guido van Rossum62de97f1995-01-22 00:48:41 +0000244static object *
Guido van Rossum778983b1993-02-19 15:55:02 +0000245newarrayobject(size, descr)
246 int size;
247 struct arraydescr *descr;
248{
Guido van Rossum778983b1993-02-19 15:55:02 +0000249 arrayobject *op;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000250 size_t nbytes;
Guido van Rossum778983b1993-02-19 15:55:02 +0000251 if (size < 0) {
252 err_badcall();
253 return NULL;
254 }
255 nbytes = size * descr->itemsize;
256 /* Check for overflow */
257 if (nbytes / descr->itemsize != size) {
258 return err_nomem();
259 }
Guido van Rossume77a7571993-11-03 15:01:26 +0000260 op = NEW(arrayobject, 1);
Guido van Rossum778983b1993-02-19 15:55:02 +0000261 if (op == NULL) {
262 return err_nomem();
263 }
264 if (size <= 0) {
265 op->ob_item = NULL;
266 }
267 else {
Guido van Rossume77a7571993-11-03 15:01:26 +0000268 op->ob_item = NEW(char, nbytes);
Guido van Rossum778983b1993-02-19 15:55:02 +0000269 if (op->ob_item == NULL) {
Guido van Rossume77a7571993-11-03 15:01:26 +0000270 DEL(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000271 return err_nomem();
272 }
273 }
Guido van Rossum778983b1993-02-19 15:55:02 +0000274 op->ob_type = &Arraytype;
275 op->ob_size = size;
276 op->ob_descr = descr;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000277 NEWREF(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000278 return (object *) op;
279}
280
Guido van Rossum62de97f1995-01-22 00:48:41 +0000281static int
Guido van Rossum778983b1993-02-19 15:55:02 +0000282getarraysize(op)
283 object *op;
284{
285 if (!is_arrayobject(op)) {
286 err_badcall();
287 return -1;
288 }
289 return ((arrayobject *)op) -> ob_size;
290}
291
Guido van Rossum62de97f1995-01-22 00:48:41 +0000292static object *
Guido van Rossum778983b1993-02-19 15:55:02 +0000293getarrayitem(op, i)
294 object *op;
295 int i;
296{
297 register arrayobject *ap;
298 if (!is_arrayobject(op)) {
299 err_badcall();
300 return NULL;
301 }
302 ap = (arrayobject *)op;
303 if (i < 0 || i >= ap->ob_size) {
304 err_setstr(IndexError, "array index out of range");
305 return NULL;
306 }
307 return (*ap->ob_descr->getitem)(ap, i);
308}
309
310static int
311ins1(self, where, v)
312 arrayobject *self;
313 int where;
314 object *v;
315{
Guido van Rossum778983b1993-02-19 15:55:02 +0000316 char *items;
317 if (v == NULL) {
318 err_badcall();
319 return -1;
320 }
321 if ((*self->ob_descr->setitem)(self, -1, v) < 0)
322 return -1;
323 items = self->ob_item;
324 RESIZE(items, char, (self->ob_size+1) * self->ob_descr->itemsize);
325 if (items == NULL) {
326 err_nomem();
327 return -1;
328 }
329 if (where < 0)
330 where = 0;
331 if (where > self->ob_size)
332 where = self->ob_size;
333 memmove(items + (where+1)*self->ob_descr->itemsize,
334 items + where*self->ob_descr->itemsize,
335 (self->ob_size-where)*self->ob_descr->itemsize);
336 self->ob_item = items;
337 self->ob_size++;
338 return (*self->ob_descr->setitem)(self, where, v);
339}
340
Guido van Rossum62de97f1995-01-22 00:48:41 +0000341static int
Guido van Rossum778983b1993-02-19 15:55:02 +0000342insarrayitem(op, where, newitem)
343 object *op;
344 int where;
345 object *newitem;
346{
347 if (!is_arrayobject(op)) {
348 err_badcall();
349 return -1;
350 }
351 return ins1((arrayobject *)op, where, newitem);
352}
353
Guido van Rossum62de97f1995-01-22 00:48:41 +0000354static int
Guido van Rossum778983b1993-02-19 15:55:02 +0000355addarrayitem(op, newitem)
356 object *op;
357 object *newitem;
358{
359 if (!is_arrayobject(op)) {
360 err_badcall();
361 return -1;
362 }
363 return ins1((arrayobject *)op,
364 (int) ((arrayobject *)op)->ob_size, newitem);
365}
366
367/* Methods */
368
369static void
370array_dealloc(op)
371 arrayobject *op;
372{
Guido van Rossum778983b1993-02-19 15:55:02 +0000373 if (op->ob_item != NULL)
Guido van Rossume77a7571993-11-03 15:01:26 +0000374 DEL(op->ob_item);
375 DEL(op);
Guido van Rossum778983b1993-02-19 15:55:02 +0000376}
377
378static int
379array_compare(v, w)
380 arrayobject *v, *w;
381{
382 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
383 int i;
384 for (i = 0; i < len; i++) {
385 object *ai, *bi;
386 int cmp;
387 ai = getarrayitem((object *)v, i);
388 bi = getarrayitem((object *)w, i);
389 if (ai && bi)
390 cmp = cmpobject(ai, bi);
391 else
392 cmp = -1;
393 XDECREF(ai);
394 XDECREF(bi);
395 if (cmp != 0) {
396 err_clear(); /* XXX Can't report errors here */
397 return cmp;
398 }
399 }
400 return v->ob_size - w->ob_size;
401}
402
403static int
404array_length(a)
405 arrayobject *a;
406{
407 return a->ob_size;
408}
409
410static object *
411array_item(a, i)
412 arrayobject *a;
413 int i;
414{
415 if (i < 0 || i >= a->ob_size) {
416 err_setstr(IndexError, "array index out of range");
417 return NULL;
418 }
419 return getarrayitem((object *)a, i);
420}
421
422static object *
423array_slice(a, ilow, ihigh)
424 arrayobject *a;
425 int ilow, ihigh;
426{
427 arrayobject *np;
Guido van Rossum778983b1993-02-19 15:55:02 +0000428 if (ilow < 0)
429 ilow = 0;
430 else if (ilow > a->ob_size)
431 ilow = a->ob_size;
432 if (ihigh < 0)
433 ihigh = 0;
434 if (ihigh < ilow)
435 ihigh = ilow;
436 else if (ihigh > a->ob_size)
437 ihigh = a->ob_size;
438 np = (arrayobject *) newarrayobject(ihigh - ilow, a->ob_descr);
439 if (np == NULL)
440 return NULL;
441 memcpy(np->ob_item, a->ob_item + ilow * a->ob_descr->itemsize,
442 (ihigh-ilow) * a->ob_descr->itemsize);
443 return (object *)np;
444}
445
446static object *
447array_concat(a, bb)
448 arrayobject *a;
449 object *bb;
450{
451 int size;
Guido van Rossum778983b1993-02-19 15:55:02 +0000452 arrayobject *np;
453 if (!is_arrayobject(bb)) {
454 err_badarg();
455 return NULL;
456 }
457#define b ((arrayobject *)bb)
458 if (a->ob_descr != b->ob_descr) {
459 err_badarg();
460 return NULL;
461 }
462 size = a->ob_size + b->ob_size;
463 np = (arrayobject *) newarrayobject(size, a->ob_descr);
464 if (np == NULL) {
465 return NULL;
466 }
467 memcpy(np->ob_item, a->ob_item, a->ob_size*a->ob_descr->itemsize);
468 memcpy(np->ob_item + a->ob_size*a->ob_descr->itemsize,
Guido van Rossum32be3a71993-11-05 10:16:27 +0000469 b->ob_item, b->ob_size*b->ob_descr->itemsize);
Guido van Rossum778983b1993-02-19 15:55:02 +0000470 return (object *)np;
471#undef b
472}
473
474static object *
475array_repeat(a, n)
476 arrayobject *a;
477 int n;
478{
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000479 int i;
Guido van Rossum778983b1993-02-19 15:55:02 +0000480 int size;
481 arrayobject *np;
482 char *p;
483 int nbytes;
484 if (n < 0)
485 n = 0;
486 size = a->ob_size * n;
487 np = (arrayobject *) newarrayobject(size, a->ob_descr);
488 if (np == NULL)
489 return NULL;
490 p = np->ob_item;
491 nbytes = a->ob_size * a->ob_descr->itemsize;
492 for (i = 0; i < n; i++) {
493 memcpy(p, a->ob_item, nbytes);
494 p += nbytes;
495 }
496 return (object *) np;
497}
498
499static int
500array_ass_slice(a, ilow, ihigh, v)
501 arrayobject *a;
502 int ilow, ihigh;
503 object *v;
504{
505 char *item;
506 int n; /* Size of replacement array */
507 int d; /* Change in size */
Guido van Rossum778983b1993-02-19 15:55:02 +0000508#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 Rossuma320fd31995-03-09 12:14:15 +00001082statichere 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}