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