arraymodule.c revision 62de97f29c90436f967c13050c93fbd1ac1ae88f
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The 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"
33#ifdef STDC_HEADERS
34#include <stddef.h>
35#else
36#include <sys/types.h>		/* For size_t */
37#endif
38
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
54staticforward typeobject Arraytype;
55
56#define is_arrayobject(op) ((op)->ob_type == &Arraytype)
57
58/* Forward */
59static object *newarrayobject PROTO((int, struct arraydescr *));
60static int getarraysize PROTO((object *));
61static object *getarrayitem PROTO((object *, int));
62static int setarrayitem PROTO((object *, int, object *));
63static int insarrayitem PROTO((object *, int, object *));
64static 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 *
136i_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 *
158l_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 */
224static struct arraydescr descriptors[] = {
225	{'c', sizeof(char), c_getitem, c_setitem},
226	{'b', sizeof(char), b_getitem, b_setitem},
227	{'h', sizeof(short), h_getitem, h_setitem},
228	{'i', sizeof(int), i_getitem, i_setitem},
229	{'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};
234/* If we ever allow items larger than double, we must change reverse()! */
235
236
237static object *
238newarrayobject(size, descr)
239	int size;
240	struct arraydescr *descr;
241{
242	arrayobject *op;
243	size_t nbytes;
244	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	}
253	op = NEW(arrayobject, 1);
254	if (op == NULL) {
255		return err_nomem();
256	}
257	if (size <= 0) {
258		op->ob_item = NULL;
259	}
260	else {
261		op->ob_item = NEW(char, nbytes);
262		if (op->ob_item == NULL) {
263			DEL(op);
264			return err_nomem();
265		}
266	}
267	op->ob_type = &Arraytype;
268	op->ob_size = size;
269	op->ob_descr = descr;
270	NEWREF(op);
271	return (object *) op;
272}
273
274static int
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
285static object *
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{
309	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
334static int
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
347static int
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{
366	if (op->ob_item != NULL)
367		DEL(op->ob_item);
368	DEL(op);
369}
370
371static int
372array_compare(v, w)
373	arrayobject *v, *w;
374{
375	int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
376	int i;
377	for (i = 0; i < len; i++) {
378		object *ai, *bi;
379		int cmp;
380		ai = getarrayitem((object *)v, i);
381		bi = getarrayitem((object *)w, i);
382		if (ai && bi)
383			cmp = cmpobject(ai, bi);
384		else
385			cmp = -1;
386		XDECREF(ai);
387		XDECREF(bi);
388		if (cmp != 0) {
389			err_clear(); /* XXX Can't report errors here */
390			return cmp;
391		}
392	}
393	return v->ob_size - w->ob_size;
394}
395
396static int
397array_length(a)
398	arrayobject *a;
399{
400	return a->ob_size;
401}
402
403static object *
404array_item(a, i)
405	arrayobject *a;
406	int i;
407{
408	if (i < 0 || i >= a->ob_size) {
409		err_setstr(IndexError, "array index out of range");
410		return NULL;
411	}
412	return getarrayitem((object *)a, i);
413}
414
415static object *
416array_slice(a, ilow, ihigh)
417	arrayobject *a;
418	int ilow, ihigh;
419{
420	arrayobject *np;
421	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;
445	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,
462	       b->ob_item, b->ob_size*b->ob_descr->itemsize);
463	return (object *)np;
464#undef b
465}
466
467static object *
468array_repeat(a, n)
469	arrayobject *a;
470	int n;
471{
472	int i;
473	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 */
501#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;
653	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;
669	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
678static object *
679array_reverse(self, args)
680	arrayobject *self;
681	object *args;
682{
683	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
687	if (args != NULL) {
688		err_badarg();
689		return NULL;
690	}
691
692	if (self->ob_size > 1) {
693		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);
700		}
701	}
702
703	INCREF(None);
704	return None;
705}
706
707/* The following routines were adapted from listobject.c but not converted.
708   To make them work you will have to work! */
709
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 *
779array_fromfile(self, args)
780	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 *
819array_tofile(self, args)
820	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[] = {
947	{"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},
963	{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	}
978	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	}
990	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);
1010		ok = printobject(v, fp, 0);
1011		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);
1020		ok = printobject(v, fp, 0);
1021		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);
1045		joinstring_decref(&s, t);
1046		joinstring_decref(&s, newstringobject(")"));
1047		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++) {
1053		if (i > 0)
1054			joinstring(&s, comma);
1055		v = (a->ob_descr->getitem)(a, i);
1056		t = reprobject(v);
1057		XDECREF(v);
1058		joinstring_decref(&s, t);
1059	}
1060	XDECREF(comma);
1061	joinstring_decref(&s, newstringobject("])"));
1062	return s;
1063}
1064
1065static sequence_methods array_as_sequence = {
1066	(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*/
1073};
1074
1075static typeobject Arraytype = {
1076	OB_HEAD_INIT(&Typetype)
1077	0,
1078	"array",
1079	sizeof(arrayobject),
1080	0,
1081	(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*/
1090};
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}
1158