comparison Modules/arraymodule.c @ 1235:87ed00a62d31 legacy-trunk

Added new module "array" (for now optional) defining array objects.
author Guido van Rossum <guido@python.org>
date Fri, 19 Feb 1993 15:55:02 +0000
parents
children 2919b448e385
comparison
equal deleted inserted replaced
1234:586c928c65d3 1235:87ed00a62d31
1 /***********************************************************
2 Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
14
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF 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"
33
34 #ifdef sun
35 #define NEED_MEMMOVE
36 #endif
37
38 #ifdef NEED_MEMMOVE
39 extern char *memmove();
40 #endif
41
42 struct arrayobject; /* Forward */
43
44 struct arraydescr {
45 int typecode;
46 int itemsize;
47 object * (*getitem) FPROTO((struct arrayobject *, int));
48 int (*setitem) FPROTO((struct arrayobject *, int, object *));
49 };
50
51 typedef struct arrayobject {
52 OB_VARHEAD
53 char *ob_item;
54 struct arraydescr *ob_descr;
55 } arrayobject;
56
57 extern typeobject Arraytype;
58
59 #define is_arrayobject(op) ((op)->ob_type == &Arraytype)
60
61 extern object *newarrayobject PROTO((int, struct arraydescr *));
62 extern int getarraysize PROTO((object *));
63 extern object *getarrayitem PROTO((object *, int));
64 extern int setarrayitem PROTO((object *, int, object *));
65 extern int insarrayitem PROTO((object *, int, object *));
66 extern int addarrayitem PROTO((object *, object *));
67
68 static object *
69 c_getitem(ap, i)
70 arrayobject *ap;
71 int i;
72 {
73 return newsizedstringobject(&((char *)ap->ob_item)[i], 1);
74 }
75
76 static int
77 c_setitem(ap, i, v)
78 arrayobject *ap;
79 int i;
80 object *v;
81 {
82 char x;
83 if (!getargs(v, "c;array item must be char", &x))
84 return -1;
85 if (i >= 0)
86 ((char *)ap->ob_item)[i] = x;
87 return 0;
88 }
89
90 static object *
91 b_getitem(ap, i)
92 arrayobject *ap;
93 int i;
94 {
95 long x = ((char *)ap->ob_item)[i];
96 if (x >= 128)
97 x -= 256;
98 return newintobject(x);
99 }
100
101 static int
102 b_setitem(ap, i, v)
103 arrayobject *ap;
104 int i;
105 object *v;
106 {
107 char x;
108 if (!getargs(v, "b;array item must be integer", &x))
109 return -1;
110 if (i >= 0)
111 ((char *)ap->ob_item)[i] = x;
112 return 0;
113 }
114
115 static object *
116 h_getitem(ap, i)
117 arrayobject *ap;
118 int i;
119 {
120 return newintobject((long) ((short *)ap->ob_item)[i]);
121 }
122
123 static int
124 h_setitem(ap, i, v)
125 arrayobject *ap;
126 int i;
127 object *v;
128 {
129 short x;
130 if (!getargs(v, "h;array item must be integer", &x))
131 return -1;
132 if (i >= 0)
133 ((short *)ap->ob_item)[i] = x;
134 return 0;
135 }
136
137 static object *
138 l_getitem(ap, i)
139 arrayobject *ap;
140 int i;
141 {
142 return newintobject(((long *)ap->ob_item)[i]);
143 }
144
145 static int
146 l_setitem(ap, i, v)
147 arrayobject *ap;
148 int i;
149 object *v;
150 {
151 long x;
152 if (!getargs(v, "l;array item must be integer", &x))
153 return -1;
154 if (i >= 0)
155 ((long *)ap->ob_item)[i] = x;
156 return 0;
157 }
158
159 static object *
160 f_getitem(ap, i)
161 arrayobject *ap;
162 int i;
163 {
164 return newfloatobject((double) ((float *)ap->ob_item)[i]);
165 }
166
167 static int
168 f_setitem(ap, i, v)
169 arrayobject *ap;
170 int i;
171 object *v;
172 {
173 float x;
174 if (!getargs(v, "f;array item must be float", &x))
175 return -1;
176 if (i >= 0)
177 ((float *)ap->ob_item)[i] = x;
178 return 0;
179 }
180
181 static object *
182 d_getitem(ap, i)
183 arrayobject *ap;
184 int i;
185 {
186 return newfloatobject(((double *)ap->ob_item)[i]);
187 }
188
189 static int
190 d_setitem(ap, i, v)
191 arrayobject *ap;
192 int i;
193 object *v;
194 {
195 double x;
196 if (!getargs(v, "d;array item must be float", &x))
197 return -1;
198 if (i >= 0)
199 ((double *)ap->ob_item)[i] = x;
200 return 0;
201 }
202
203 /* Description of types */
204 struct arraydescr descriptors[] = {
205 {'c', sizeof(char), c_getitem, c_setitem},
206 {'b', sizeof(char), b_getitem, b_setitem},
207 {'h', sizeof(short), h_getitem, h_setitem},
208 {'l', sizeof(long), l_getitem, l_setitem},
209 {'f', sizeof(float), f_getitem, f_setitem},
210 {'d', sizeof(double), d_getitem, d_setitem},
211 {'\0', 0, 0, 0} /* Sentinel */
212 };
213
214
215 object *
216 newarrayobject(size, descr)
217 int size;
218 struct arraydescr *descr;
219 {
220 int i;
221 arrayobject *op;
222 MALLARG nbytes;
223 int itemsize;
224 if (size < 0) {
225 err_badcall();
226 return NULL;
227 }
228 nbytes = size * descr->itemsize;
229 /* Check for overflow */
230 if (nbytes / descr->itemsize != size) {
231 return err_nomem();
232 }
233 op = (arrayobject *) malloc(sizeof(arrayobject));
234 if (op == NULL) {
235 return err_nomem();
236 }
237 if (size <= 0) {
238 op->ob_item = NULL;
239 }
240 else {
241 op->ob_item = malloc(nbytes);
242 if (op->ob_item == NULL) {
243 free((ANY *)op);
244 return err_nomem();
245 }
246 }
247 NEWREF(op);
248 op->ob_type = &Arraytype;
249 op->ob_size = size;
250 op->ob_descr = descr;
251 return (object *) op;
252 }
253
254 int
255 getarraysize(op)
256 object *op;
257 {
258 if (!is_arrayobject(op)) {
259 err_badcall();
260 return -1;
261 }
262 return ((arrayobject *)op) -> ob_size;
263 }
264
265 object *
266 getarrayitem(op, i)
267 object *op;
268 int i;
269 {
270 register arrayobject *ap;
271 if (!is_arrayobject(op)) {
272 err_badcall();
273 return NULL;
274 }
275 ap = (arrayobject *)op;
276 if (i < 0 || i >= ap->ob_size) {
277 err_setstr(IndexError, "array index out of range");
278 return NULL;
279 }
280 return (*ap->ob_descr->getitem)(ap, i);
281 }
282
283 static int
284 ins1(self, where, v)
285 arrayobject *self;
286 int where;
287 object *v;
288 {
289 int i;
290 char *items;
291 if (v == NULL) {
292 err_badcall();
293 return -1;
294 }
295 if ((*self->ob_descr->setitem)(self, -1, v) < 0)
296 return -1;
297 items = self->ob_item;
298 RESIZE(items, char, (self->ob_size+1) * self->ob_descr->itemsize);
299 if (items == NULL) {
300 err_nomem();
301 return -1;
302 }
303 if (where < 0)
304 where = 0;
305 if (where > self->ob_size)
306 where = self->ob_size;
307 memmove(items + (where+1)*self->ob_descr->itemsize,
308 items + where*self->ob_descr->itemsize,
309 (self->ob_size-where)*self->ob_descr->itemsize);
310 self->ob_item = items;
311 self->ob_size++;
312 return (*self->ob_descr->setitem)(self, where, v);
313 }
314
315 int
316 insarrayitem(op, where, newitem)
317 object *op;
318 int where;
319 object *newitem;
320 {
321 if (!is_arrayobject(op)) {
322 err_badcall();
323 return -1;
324 }
325 return ins1((arrayobject *)op, where, newitem);
326 }
327
328 int
329 addarrayitem(op, newitem)
330 object *op;
331 object *newitem;
332 {
333 if (!is_arrayobject(op)) {
334 err_badcall();
335 return -1;
336 }
337 return ins1((arrayobject *)op,
338 (int) ((arrayobject *)op)->ob_size, newitem);
339 }
340
341 /* Methods */
342
343 static void
344 array_dealloc(op)
345 arrayobject *op;
346 {
347 int i;
348 if (op->ob_item != NULL)
349 free((ANY *)op->ob_item);
350 free((ANY *)op);
351 }
352
353 static int
354 array_compare(v, w)
355 arrayobject *v, *w;
356 {
357 int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
358 int i;
359 for (i = 0; i < len; i++) {
360 object *ai, *bi;
361 int cmp;
362 ai = getarrayitem((object *)v, i);
363 bi = getarrayitem((object *)w, i);
364 if (ai && bi)
365 cmp = cmpobject(ai, bi);
366 else
367 cmp = -1;
368 XDECREF(ai);
369 XDECREF(bi);
370 if (cmp != 0) {
371 err_clear(); /* XXX Can't report errors here */
372 return cmp;
373 }
374 }
375 return v->ob_size - w->ob_size;
376 }
377
378 static int
379 array_length(a)
380 arrayobject *a;
381 {
382 return a->ob_size;
383 }
384
385 static object *
386 array_item(a, i)
387 arrayobject *a;
388 int i;
389 {
390 if (i < 0 || i >= a->ob_size) {
391 err_setstr(IndexError, "array index out of range");
392 return NULL;
393 }
394 return getarrayitem((object *)a, i);
395 }
396
397 static object *
398 array_slice(a, ilow, ihigh)
399 arrayobject *a;
400 int ilow, ihigh;
401 {
402 arrayobject *np;
403 int i;
404 if (ilow < 0)
405 ilow = 0;
406 else if (ilow > a->ob_size)
407 ilow = a->ob_size;
408 if (ihigh < 0)
409 ihigh = 0;
410 if (ihigh < ilow)
411 ihigh = ilow;
412 else if (ihigh > a->ob_size)
413 ihigh = a->ob_size;
414 np = (arrayobject *) newarrayobject(ihigh - ilow, a->ob_descr);
415 if (np == NULL)
416 return NULL;
417 memcpy(np->ob_item, a->ob_item + ilow * a->ob_descr->itemsize,
418 (ihigh-ilow) * a->ob_descr->itemsize);
419 return (object *)np;
420 }
421
422 static object *
423 array_concat(a, bb)
424 arrayobject *a;
425 object *bb;
426 {
427 int size;
428 int i;
429 arrayobject *np;
430 if (!is_arrayobject(bb)) {
431 err_badarg();
432 return NULL;
433 }
434 #define b ((arrayobject *)bb)
435 if (a->ob_descr != b->ob_descr) {
436 err_badarg();
437 return NULL;
438 }
439 size = a->ob_size + b->ob_size;
440 np = (arrayobject *) newarrayobject(size, a->ob_descr);
441 if (np == NULL) {
442 return NULL;
443 }
444 memcpy(np->ob_item, a->ob_item, a->ob_size*a->ob_descr->itemsize);
445 memcpy(np->ob_item + a->ob_size*a->ob_descr->itemsize,
446 a->ob_item, a->ob_size*a->ob_descr->itemsize);
447 return (object *)np;
448 #undef b
449 }
450
451 static object *
452 array_repeat(a, n)
453 arrayobject *a;
454 int n;
455 {
456 int i, j;
457 int size;
458 arrayobject *np;
459 char *p;
460 int nbytes;
461 if (n < 0)
462 n = 0;
463 size = a->ob_size * n;
464 np = (arrayobject *) newarrayobject(size, a->ob_descr);
465 if (np == NULL)
466 return NULL;
467 p = np->ob_item;
468 nbytes = a->ob_size * a->ob_descr->itemsize;
469 for (i = 0; i < n; i++) {
470 memcpy(p, a->ob_item, nbytes);
471 p += nbytes;
472 }
473 return (object *) np;
474 }
475
476 static int
477 array_ass_slice(a, ilow, ihigh, v)
478 arrayobject *a;
479 int ilow, ihigh;
480 object *v;
481 {
482 char *item;
483 int n; /* Size of replacement array */
484 int d; /* Change in size */
485 int k; /* Loop index */
486 #define b ((arrayobject *)v)
487 if (v == NULL)
488 n = 0;
489 else if (is_arrayobject(v)) {
490 n = b->ob_size;
491 if (a == b) {
492 /* Special case "a[i:j] = a" -- copy b first */
493 int ret;
494 v = array_slice(b, 0, n);
495 ret = array_ass_slice(a, ilow, ihigh, v);
496 DECREF(v);
497 return ret;
498 }
499 if (b->ob_descr != a->ob_descr) {
500 err_badarg();
501 return -1;
502 }
503 }
504 else {
505 err_badarg();
506 return -1;
507 }
508 if (ilow < 0)
509 ilow = 0;
510 else if (ilow > a->ob_size)
511 ilow = a->ob_size;
512 if (ihigh < 0)
513 ihigh = 0;
514 if (ihigh < ilow)
515 ihigh = ilow;
516 else if (ihigh > a->ob_size)
517 ihigh = a->ob_size;
518 item = a->ob_item;
519 d = n - (ihigh-ilow);
520 if (d < 0) { /* Delete -d items */
521 memmove(item + (ihigh+d)*a->ob_descr->itemsize,
522 item + ihigh*a->ob_descr->itemsize,
523 (a->ob_size-ihigh)*a->ob_descr->itemsize);
524 a->ob_size += d;
525 RESIZE(item, char, a->ob_size*a->ob_descr->itemsize);
526 /* Can't fail */
527 a->ob_item = item;
528 }
529 else if (d > 0) { /* Insert d items */
530 RESIZE(item, char, (a->ob_size + d)*a->ob_descr->itemsize);
531 if (item == NULL) {
532 err_nomem();
533 return -1;
534 }
535 memmove(item + (ihigh+d)*a->ob_descr->itemsize,
536 item + ihigh*a->ob_descr->itemsize,
537 (a->ob_size-ihigh)*a->ob_descr->itemsize);
538 a->ob_item = item;
539 a->ob_size += d;
540 }
541 if (n > 0)
542 memcpy(item + ilow*a->ob_descr->itemsize, b->ob_item,
543 n*b->ob_descr->itemsize);
544 return 0;
545 #undef b
546 }
547
548 static int
549 array_ass_item(a, i, v)
550 arrayobject *a;
551 int i;
552 object *v;
553 {
554 if (i < 0 || i >= a->ob_size) {
555 err_setstr(IndexError, "array assignment index out of range");
556 return -1;
557 }
558 if (v == NULL)
559 return array_ass_slice(a, i, i+1, v);
560 return (*a->ob_descr->setitem)(a, i, v);
561 }
562
563 static int
564 setarrayitem(a, i, v)
565 object *a;
566 int i;
567 object *v;
568 {
569 if (!is_arrayobject(a)) {
570 err_badcall();
571 return -1;
572 }
573 return array_ass_item((arrayobject *)a, i, v);
574 }
575
576 static object *
577 ins(self, where, v)
578 arrayobject *self;
579 int where;
580 object *v;
581 {
582 if (ins1(self, where, v) != 0)
583 return NULL;
584 INCREF(None);
585 return None;
586 }
587
588 static object *
589 array_insert(self, args)
590 arrayobject *self;
591 object *args;
592 {
593 int i;
594 object *v;
595 if (!getargs(args, "(iO)", &i, &v))
596 return NULL;
597 return ins(self, i, v);
598 }
599
600 static object *
601 array_append(self, args)
602 arrayobject *self;
603 object *args;
604 {
605 object *v;
606 if (!getargs(args, "O", &v))
607 return NULL;
608 return ins(self, (int) self->ob_size, v);
609 }
610
611 static object *
612 array_byteswap(self, args)
613 arrayobject *self;
614 object *args;
615 {
616 char *p;
617 int i;
618 switch (self->ob_descr->itemsize) {
619 case 1:
620 break;
621 case 2:
622 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 2) {
623 char p0 = p[0];
624 p[0] = p[1];
625 p[1] = p0;
626 }
627 break;
628 case 4:
629 for (p = self->ob_item, i = self->ob_size; --i >= 0; p += 4) {
630 char p0 = p[0];
631 char p1 = p[1];
632 p[0] = p[3];
633 p[1] = p[2];
634 p[2] = p1;
635 p[3] = p0;
636 }
637 break;
638 default:
639 err_setstr(RuntimeError,
640 "don't know how to byteswap this array type");
641 return NULL;
642 }
643 INCREF(None);
644 return None;
645 }
646
647 #if 0
648 static object *
649 array_reverse(self, args)
650 arrayobject *self;
651 object *args;
652 {
653 register object **p, **q;
654 register object *tmp;
655
656 if (args != NULL) {
657 err_badarg();
658 return NULL;
659 }
660
661 if (self->ob_size > 1) {
662 for (p = self->ob_item, q = self->ob_item + self->ob_size - 1;
663 p < q; p++, q--) {
664 tmp = *p;
665 *p = *q;
666 *q = tmp;
667 }
668 }
669
670 INCREF(None);
671 return None;
672 }
673 #endif
674
675 #if 0
676 static object *
677 array_index(self, args)
678 arrayobject *self;
679 object *args;
680 {
681 int i;
682
683 if (args == NULL) {
684 err_badarg();
685 return NULL;
686 }
687 for (i = 0; i < self->ob_size; i++) {
688 if (cmpobject(self->ob_item[i], args) == 0)
689 return newintobject((long)i);
690 }
691 err_setstr(ValueError, "array.index(x): x not in array");
692 return NULL;
693 }
694 #endif
695
696 #if 0
697 static object *
698 array_count(self, args)
699 arrayobject *self;
700 object *args;
701 {
702 int count = 0;
703 int i;
704
705 if (args == NULL) {
706 err_badarg();
707 return NULL;
708 }
709 for (i = 0; i < self->ob_size; i++) {
710 if (cmpobject(self->ob_item[i], args) == 0)
711 count++;
712 }
713 return newintobject((long)count);
714 }
715 #endif
716
717 #if 0
718 static object *
719 array_remove(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 if (array_ass_slice(self, i, i+1, (object *)NULL) != 0)
732 return NULL;
733 INCREF(None);
734 return None;
735 }
736
737 }
738 err_setstr(ValueError, "array.remove(x): x not in array");
739 return NULL;
740 }
741 #endif
742
743 static object *
744 array_read(self, args)
745 arrayobject *self;
746 object *args;
747 {
748 object *f;
749 int n;
750 FILE *fp;
751 if (!getargs(args, "(Oi)", &f, &n))
752 return NULL;
753 fp = getfilefile(f);
754 if (fp == NULL) {
755 err_setstr(TypeError, "arg1 must be open file");
756 return NULL;
757 }
758 if (n > 0) {
759 char *item = self->ob_item;
760 int itemsize = self->ob_descr->itemsize;
761 int nread;
762 RESIZE(item, char, (self->ob_size + n) * itemsize);
763 if (item == NULL) {
764 err_nomem();
765 return NULL;
766 }
767 self->ob_item = item;
768 self->ob_size += n;
769 nread = fread(item + (self->ob_size - n) * itemsize,
770 itemsize, n, fp);
771 if (nread < n) {
772 self->ob_size -= (n - nread);
773 RESIZE(item, char, self->ob_size*itemsize);
774 self->ob_item = item;
775 err_setstr(EOFError, "not enough items in file");
776 return NULL;
777 }
778 }
779 INCREF(None);
780 return None;
781 }
782
783 static object *
784 array_write(self, args)
785 arrayobject *self;
786 object *args;
787 {
788 object *f;
789 FILE *fp;
790 if (!getargs(args, "O", &f))
791 return NULL;
792 fp = getfilefile(f);
793 if (fp == NULL) {
794 err_setstr(TypeError, "arg must be open file");
795 return NULL;
796 }
797 if (self->ob_size > 0) {
798 if (fwrite(self->ob_item, self->ob_descr->itemsize,
799 self->ob_size, fp) != self->ob_size) {
800 err_errno(IOError);
801 clearerr(fp);
802 return NULL;
803 }
804 }
805 INCREF(None);
806 return None;
807 }
808
809 static object *
810 array_fromlist(self, args)
811 arrayobject *self;
812 object *args;
813 {
814 int n;
815 object *list;
816 int itemsize = self->ob_descr->itemsize;
817 if (!getargs(args, "O", &list))
818 return NULL;
819 if (!is_listobject(list)) {
820 err_setstr(TypeError, "arg must be list");
821 return NULL;
822 }
823 n = getlistsize(list);
824 if (n > 0) {
825 char *item = self->ob_item;
826 int i;
827 RESIZE(item, char, (self->ob_size + n) * itemsize);
828 if (item == NULL) {
829 err_nomem();
830 return NULL;
831 }
832 self->ob_item = item;
833 self->ob_size += n;
834 for (i = 0; i < n; i++) {
835 object *v = getlistitem(list, i);
836 if ((*self->ob_descr->setitem)(self,
837 self->ob_size - n + i, v) != 0) {
838 self->ob_size -= n;
839 RESIZE(item, char, self->ob_size * itemsize);
840 self->ob_item = item;
841 return NULL;
842 }
843 }
844 }
845 INCREF(None);
846 return None;
847 }
848
849 static object *
850 array_tolist(self, args)
851 arrayobject *self;
852 object *args;
853 {
854 object *list = newlistobject(self->ob_size);
855 int i;
856 if (list == NULL)
857 return NULL;
858 for (i = 0; i < self->ob_size; i++) {
859 object *v = getarrayitem((object *)self, i);
860 if (v == NULL) {
861 DECREF(list);
862 return NULL;
863 }
864 setlistitem(list, i, v);
865 }
866 return list;
867 }
868
869 static object *
870 array_fromstring(self, args)
871 arrayobject *self;
872 object *args;
873 {
874 char *str;
875 int n;
876 int itemsize = self->ob_descr->itemsize;
877 if (!getargs(args, "s#", &str, &n))
878 return NULL;
879 if (n % itemsize != 0) {
880 err_setstr(ValueError,
881 "string length not a multiple of item size");
882 return NULL;
883 }
884 n = n / itemsize;
885 if (n > 0) {
886 char *item = self->ob_item;
887 RESIZE(item, char, (self->ob_size + n) * itemsize);
888 if (item == NULL) {
889 err_nomem();
890 return NULL;
891 }
892 self->ob_item = item;
893 self->ob_size += n;
894 memcpy(item + (self->ob_size - n) * itemsize, str, itemsize*n);
895 }
896 INCREF(None);
897 return None;
898 }
899
900 static object *
901 array_tostring(self, args)
902 arrayobject *self;
903 object *args;
904 {
905 if (!getargs(args, ""))
906 return NULL;
907 return newsizedstringobject(self->ob_item,
908 self->ob_size * self->ob_descr->itemsize);
909 }
910
911 static struct methodlist array_methods[] = {
912 {"append", array_append},
913 {"byteswap", array_byteswap},
914 /* {"count", array_count},*/
915 /* {"index", array_index},*/
916 {"insert", array_insert},
917 /* {"sort", array_sort},*/
918 /* {"remove", array_remove},*/
919 /* {"reverse", array_reverse},*/
920 {"read", array_read},
921 {"write", array_write},
922 {"fromlist", array_fromlist},
923 {"tolist", array_tolist},
924 {"fromstring", array_fromstring},
925 {"tostring", array_tostring},
926 {NULL, NULL} /* sentinel */
927 };
928
929 static object *
930 array_getattr(a, name)
931 arrayobject *a;
932 char *name;
933 {
934 if (strcmp(name, "typecode") == 0) {
935 char tc = a->ob_descr->typecode;
936 return newsizedstringobject(&tc, 1);
937 }
938 if (strcmp(name, "itemsize") == 0) {
939 return newintobject((long)a->ob_descr->itemsize);
940 }
941 return findmethod(array_methods, (object *)a, name);
942 }
943
944 static int
945 array_print(a, fp, flags)
946 arrayobject *a;
947 FILE *fp;
948 int flags;
949 {
950 int ok = 0;
951 int i, len;
952 object *v;
953 len = a->ob_size;
954 if (len == 0) {
955 fprintf(fp, "array('%c')", a->ob_descr->typecode);
956 return ok;
957 }
958 if (a->ob_descr->typecode == 'c') {
959 fprintf(fp, "array('c', ");
960 v = array_tostring(a, (object *)NULL);
961 ok = printobject(v, fp, flags);
962 XDECREF(v);
963 fprintf(fp, ")");
964 return ok;
965 }
966 fprintf(fp, "array('%c', [", a->ob_descr->typecode);
967 for (i = 0; i < len && ok == 0; i++) {
968 if (i > 0)
969 fprintf(fp, ", ");
970 v = (a->ob_descr->getitem)(a, i);
971 ok = printobject(v, fp, flags);
972 XDECREF(v);
973 }
974 fprintf(fp, "])");
975 return ok;
976 }
977
978 static object *
979 array_repr(a)
980 arrayobject *a;
981 {
982 char buf[256];
983 object *s, *t, *comma, *v;
984 int i, len;
985 len = a->ob_size;
986 if (len == 0) {
987 sprintf(buf, "array('%c')", a->ob_descr->typecode);
988 return newstringobject(buf);
989 }
990 if (a->ob_descr->typecode == 'c') {
991 sprintf(buf, "array('c', ");
992 s = newstringobject(buf);
993 v = array_tostring(a, (object *)NULL);
994 t = reprobject(v);
995 XDECREF(v);
996 joinstring(&s, t);
997 XDECREF(t);
998 t = newstringobject(")");
999 joinstring(&s, t);
1000 XDECREF(t);
1001 if (err_occurred()) {
1002 XDECREF(s);
1003 s = NULL;
1004 }
1005 return s;
1006 }
1007 sprintf(buf, "array('%c', [", a->ob_descr->typecode);
1008 s = newstringobject(buf);
1009 comma = newstringobject(", ");
1010 for (i = 0; i < len && !err_occurred(); i++) {
1011 v = (a->ob_descr->getitem)(a, i);
1012 t = reprobject(v);
1013 XDECREF(v);
1014 if (i > 0)
1015 joinstring(&s, comma);
1016 joinstring(&s, t);
1017 XDECREF(t);
1018 }
1019 XDECREF(comma);
1020 t = newstringobject("])");
1021 joinstring(&s, t);
1022 XDECREF(t);
1023 if (err_occurred()) {
1024 XDECREF(s);
1025 s = NULL;
1026 }
1027 return s;
1028 }
1029
1030 static sequence_methods array_as_sequence = {
1031 array_length, /*sq_length*/
1032 array_concat, /*sq_concat*/
1033 array_repeat, /*sq_repeat*/
1034 array_item, /*sq_item*/
1035 array_slice, /*sq_slice*/
1036 array_ass_item, /*sq_ass_item*/
1037 array_ass_slice, /*sq_ass_slice*/
1038 };
1039
1040 typeobject Arraytype = {
1041 OB_HEAD_INIT(&Typetype)
1042 0,
1043 "array",
1044 sizeof(arrayobject),
1045 0,
1046 array_dealloc, /*tp_dealloc*/
1047 array_print, /*tp_print*/
1048 array_getattr, /*tp_getattr*/
1049 0, /*tp_setattr*/
1050 array_compare, /*tp_compare*/
1051 array_repr, /*tp_repr*/
1052 0, /*tp_as_number*/
1053 &array_as_sequence, /*tp_as_sequence*/
1054 0, /*tp_as_mapping*/
1055 };
1056
1057
1058 static object *
1059 a_array(self, args)
1060 object *self;
1061 object *args;
1062 {
1063 char c;
1064 object *initial = NULL;
1065 struct arraydescr *descr;
1066 if (!getargs(args, "c", &c)) {
1067 err_clear();
1068 if (!getargs(args, "(cO)", &c, &initial))
1069 return NULL;
1070 if (!is_listobject(initial) && !is_stringobject(initial)) {
1071 err_setstr(TypeError,
1072 "array initializer must be list or string");
1073 return NULL;
1074 }
1075 }
1076 for (descr = descriptors; descr->typecode != '\0'; descr++) {
1077 if (descr->typecode == c) {
1078 object *a;
1079 int len;
1080 if (initial == NULL || !is_listobject(initial))
1081 len = 0;
1082 else
1083 len = getlistsize(initial);
1084 a = newarrayobject(len, descr);
1085 if (a == NULL)
1086 return NULL;
1087 if (len > 0) {
1088 int i;
1089 for (i = 0; i < len; i++) {
1090 object *v = getlistitem(initial, i);
1091 if (setarrayitem(a, i, v) != 0) {
1092 DECREF(a);
1093 return NULL;
1094 }
1095 }
1096 }
1097 if (initial != NULL && is_stringobject(initial)) {
1098 object *v =
1099 array_fromstring((arrayobject *)a, initial);
1100 if (v == NULL) {
1101 DECREF(a);
1102 return NULL;
1103 }
1104 DECREF(v);
1105 }
1106 return a;
1107 }
1108 }
1109 err_setstr(ValueError, "bad typecode (must be c, b, h, l, f or d)");
1110 return NULL;
1111 }
1112
1113 static struct methodlist a_methods[] = {
1114 {"array", a_array},
1115 {NULL, NULL} /* sentinel */
1116 };
1117
1118 void
1119 initarray()
1120 {
1121 initmodule("array", a_methods);
1122 }
1123
1124
1125 #ifdef NEED_MEMMOVE
1126
1127 /* A perhaps slow but I hope correct implementation of memmove */
1128
1129 char *memmove(dst, src, n)
1130 char *dst;
1131 char *src;
1132 int n;
1133 {
1134 char *realdst = dst;
1135 if (n <= 0)
1136 return dst;
1137 if (src >= dst+n || dst >= src+n)
1138 return memcpy(dst, src, n);
1139 if (src > dst) {
1140 while (--n >= 0)
1141 *dst++ = *src++;
1142 }
1143 else if (src < dst) {
1144 src += n;
1145 dst += n;
1146 while (--n >= 0)
1147 *--dst = *--src;
1148 }
1149 return realdst;
1150 }
1151
1152 #endif