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