1 package org.python.core; 3 4 import java.io.ByteArrayInputStream ; 5 import java.io.ByteArrayOutputStream ; 6 import java.io.DataInputStream ; 7 import java.io.DataOutputStream ; 8 import java.io.EOFException ; 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.io.OutputStream ; 12 import java.lang.reflect.Array ; 13 14 22 public class PyArray extends PySequence implements Cloneable , ClassDictInit { 23 24 protected Object data; 25 protected Class type; 26 protected String typecode; 27 protected ArrayDelegate delegate; 28 29 private class ArrayDelegate extends AbstractArray { 31 32 final PyArray pyArray; 33 34 private ArrayDelegate(PyArray pyArray) { 35 super((pyArray.data == null) ? 0 : Array.getLength(pyArray.data)); 36 this.pyArray = pyArray; 37 } 38 39 protected Object getArray() { 40 return pyArray.data; 41 } 42 protected void setArray(Object array) { 43 pyArray.data = array; 44 } 45 46 protected void makeInsertSpace(int index) { 47 super.makeInsertSpace(index, 1); 48 } 49 50 protected void makeInsertSpace(int index, int length) { 51 super.makeInsertSpace(index, length); 52 } 53 54 public void remove(int index) { 55 super.remove(index); 56 } 57 } 58 59 private PyArray() { 60 } 62 63 public PyArray(PyArray toCopy) { 64 65 data = toCopy.delegate.copyArray(); 66 delegate = new ArrayDelegate(this); 67 type = toCopy.type; 68 } 69 70 public PyArray(Class type, Object data) { 71 this.type = type; 72 this.data = data; 73 delegate = new ArrayDelegate(this); 74 } 75 76 public PyArray(Class type, int n) { 77 this(type, Array.newInstance(type, n)); 78 } 79 80 public static PyArray zeros(int n, char typecode) { 81 PyArray array = zeros(n, char2class(typecode)); 82 array.typecode = Character.toString(typecode); 83 return array; 84 } 85 86 public static PyArray zeros(int n, Class ctype) { 87 PyArray array = new PyArray(ctype, n); 88 array.typecode = ctype.getName(); 89 return array; 90 } 91 92 public static PyArray array(PyObject seq, char typecode) { 93 PyArray array = PyArray.array(seq, char2class(typecode)); 94 array.typecode = Character.toString(typecode); 95 return array; 96 } 97 98 107 public static PyArray array(PyObject init, Class ctype) { 108 109 PyArray array = new PyArray(ctype, 0); 110 array.typecode = ctype.getName(); 111 112 array.extendInternal(init); 113 114 return array; 115 } 116 117 123 public PyObject __add__(PyObject other) { 124 PyArray otherArr = null; 125 if (!(other instanceof PyArray)) { 126 throw Py.TypeError("can only append another array to an array"); 127 } 128 otherArr = (PyArray)other; 129 if (!otherArr.type.equals(this.type)) { 130 throw Py.TypeError( 131 "can only append arrays of the same type, " + 132 "expected '" + this.type + ", found " + otherArr.type); 133 } 134 PyArray ret = new PyArray(this); 135 ret.delegate.appendArray(otherArr.delegate.copyArray()); 136 return ret; 137 } 138 139 145 public PyObject __findattr__(String name) { 146 if("typecode".equals(name)) { 147 return new PyString(getTypecode()); 148 } 149 return super.__findattr__(name); 150 } 151 152 157 public int __len__() { 158 return delegate.getSize(); 159 } 160 161 166 public PyString __repr__() { 167 StringBuffer buf = new StringBuffer (128); 168 buf.append("array(").append(class2char(type)).append(",["); 169 for (int i=0; i<__len__()-1; i++) { 170 buf.append(pyget(i).__repr__().toString()); 171 buf.append(", "); 172 } 173 if (__len__() > 0) { 174 buf.append(pyget(__len__()-1).__repr__().toString()); 175 } 176 buf.append("]) "); 177 return new PyString(buf.toString()); 178 } 179 180 185 public Object __tojava__(Class c) { 186 if (c == Object .class || 187 (c.isArray() && c.getComponentType().isAssignableFrom(type))) 188 { 189 return data; 190 } 191 if (c.isInstance(this)) return this; 192 return Py.NoConversion; 193 } 194 195 200 public void append(PyObject value) { 201 207 int afterLast = delegate.getSize(); 208 delegate.makeInsertSpace(afterLast); 209 try { 210 set(afterLast, value); 211 } catch (PyException e) { 212 delegate.setSize(afterLast); 213 throw new PyException(e.type, e.value); 214 } 215 } 216 217 223 public void byteswap() { 224 if (getItemsize() == 0) { 226 throw Py.RuntimeError("don't know how to byteswap this array type"); 227 } 228 229 ByteSwapper.swap(data); 230 } 231 232 235 public static void classDictInit(PyObject dict) throws PyIgnoreMethodTag { 236 PySequence.classDictInit(dict); 237 dict.__setitem__("clone", null); 238 dict.__setitem__("classDictInit", null); 239 } 240 241 246 public Object clone() { 247 return new PyArray(this); 248 } 249 250 273 public static Class char2class(char type) throws PyIgnoreMethodTag { 274 switch (type) { 275 case 'z': 276 return Boolean.TYPE; 277 case 'c': 278 return Character.TYPE; 279 case 'b': 280 return Byte.TYPE; 281 case 'h': 282 return Short.TYPE; 283 case 'i': 284 return Integer.TYPE; 285 case 'l': 286 return Long.TYPE; 287 case 'f': 288 return Float.TYPE; 289 case 'd': 290 return Double.TYPE; 291 default: 292 throw Py.ValueError("typecode must be in [zcbhilfd]"); 293 } 294 } 295 296 private static String class2char(Class cls) { 297 298 if (cls.equals(Boolean.TYPE) ) return "'z'"; 299 else if (cls.equals(Character.TYPE)) return "'c'"; 300 else if (cls.equals(Byte.TYPE) ) return "'b'"; 301 else if (cls.equals(Short.TYPE) ) return "'h'"; 302 else if (cls.equals(Integer.TYPE) ) return "'i'"; 303 else if (cls.equals(Long.TYPE) ) return "'l'"; 304 else if (cls.equals(Float.TYPE) ) return "'f'"; 305 else if (cls.equals(Double.TYPE) ) return "'d'"; 306 else return cls.getName(); 307 } 308 309 315 public PyObject count(PyObject value) { 316 int iCount = 0; 318 for (int i = 0; i < delegate.getSize(); i++) { 319 if (value.equals(Py.java2py(Array.get(data, i)))) iCount++; 320 } 321 return new PyInteger(iCount); 322 } 323 324 329 protected void del(int i) { 330 delegate.remove(i); 333 } 334 335 343 protected void delRange(int start, int stop, int step) { 344 if (step > 0 && stop < start) stop = start; 347 348 if (step == 1) { 349 delegate.remove(start, stop); 350 } else { 351 int n = sliceLength(start, stop, step); 352 353 for (int i = start, j = 0; j < n; i += step, j++) { 354 delegate.remove(i); 355 } 356 } 357 } 358 359 370 public void extend(PyObject iterable) { 371 extendInternal(iterable); 372 } 373 374 383 private void extendInternal(PyObject iterable) { 384 385 if (iterable instanceof PyString) { 387 fromstring( ((PyString)iterable).toString() ); 388 389 } else if (iterable instanceof PyArray) { 391 PyArray source = (PyArray)iterable; 392 393 if(! source.type.equals(this.type)) { 394 throw Py.TypeError( 395 "can only extend with an array of the same kind"); 396 } 397 398 delegate.appendArray(source.delegate.copyArray()); 399 400 } else { 401 extendInternalIter(iterable); 402 } 403 } 404 405 410 private void extendInternalIter(PyObject iterable) { 411 PyObject iter = iterable.__iter__(); 412 PyObject item = null; 413 414 if (iterable.__findattr__("__len__") == null) { 417 for (int i = 0; (item = iter.__iternext__()) != null; i++) { 418 append(item); 419 } 420 } else { 421 422 int last = delegate.getSize(); 424 delegate.ensureCapacity(last + iterable.__len__() ); 425 426 for (int i = last; (item = iter.__iternext__()) != null; i++) { 427 set(i, item); 428 delegate.size++; 429 } 430 } 431 } 432 433 444 public void fromfile(PyObject f, int count) { 445 446 if(!(f instanceof PyFile)) { 448 throw Py.TypeError("arg1 must be open file"); 449 } 450 451 PyFile file = (PyFile)f; 452 453 if (file.mode.indexOf("r") == -1) { 455 throw Py.TypeError("file needs to be in read mode"); 456 } 457 458 459 int readbytes = count * getItemsize(); 461 String buffer = file.read(readbytes).toString(); 462 463 fromstring(buffer); 465 466 if (buffer.length() < readbytes) { 468 int readcount = buffer.length() / getItemsize(); 469 throw Py.EOFError("not enough items in file. "+ 470 Integer.toString(count)+" requested, "+ 471 Integer.toString(readcount)+" actually read" 472 ); 473 } 474 } 475 476 483 public void fromlist(PyObject obj) { 484 if(!(obj instanceof PyList)) 486 throw Py.TypeError("expected list argument"); 487 488 int size = delegate.getSize(); 490 491 try { 492 extendInternalIter(obj); 493 } catch (PyException e) { 494 delegate.setSize(size); 496 throw new PyException(e.type, e.value); 498 } 499 } 500 501 512 private int fromStream(InputStream is) throws IOException , EOFException { 513 return fromStream(is, is.available() / getItemsize()); 514 } 515 516 528 private int fromStream(InputStream is, int count) throws IOException , EOFException { 529 530 DataInputStream dis = new DataInputStream (is); 531 532 int origsize = delegate.getSize(); 534 int index = origsize; 536 537 delegate.ensureCapacity(index + count); 539 540 if (type.isPrimitive()) { 541 542 if (type == Boolean.TYPE) { 543 for (int i = 0; i < count; i++, index++) { 544 Array.setBoolean(data, index, dis.readBoolean()); 545 delegate.size++; 546 } 547 } else if (type == Byte.TYPE) { 548 for (int i = 0; i < count; i++, index++) { 549 Array.setByte(data, index, dis.readByte()); 550 delegate.size++; 551 } 552 } else if (type == Character.TYPE) { 553 for (int i = 0; i < count; i++, index++) { 554 Array.setChar(data, index, (char)dis.readByte()); 555 delegate.size++; 556 } 557 } else if(type == Integer.TYPE) { 558 for (int i = 0; i < count; i++, index++) { 559 Array.setInt(data, index, dis.readInt()); 560 delegate.size++; 561 } 562 } else if (type == Short.TYPE) { 563 for (int i = 0; i < count; i++, index++) { 564 Array.setShort(data, index, dis.readShort()); 565 delegate.size++; 566 } 567 } else if (type == Long.TYPE) { 568 for (int i = 0; i < count; i++, index++) { 569 Array.setLong(data, index, dis.readLong()); 570 delegate.size++; 571 } 572 } else if (type == Float.TYPE) { 573 for (int i = 0; i < count; i++, index++) { 574 Array.setFloat(data, index, dis.readFloat()); 575 delegate.size++; 576 } 577 } else if (type == Double.TYPE) { 578 for (int i = 0; i < count; i++, index++) { 579 Array.setDouble(data, index, dis.readDouble()); 580 delegate.size++; 581 } 582 } 583 } 584 dis.close(); 585 586 587 return (index - origsize); 588 } 589 590 597 public void fromstring(String input) { 598 599 int itemsize = getItemsize(); 600 int strlen = input.length(); 601 if((strlen % itemsize) != 0) { 602 throw Py.ValueError("string length not a multiple of item size"); 603 } 604 605 ByteArrayInputStream bis = new ByteArrayInputStream (input.getBytes()); 606 607 int origsize = delegate.getSize(); 608 609 try { 610 fromStream(bis); 611 } 612 catch(EOFException e) { 613 throw Py.EOFError("not enough items in string"); 615 } 616 catch(IOException e) { 617 delegate.setSize(origsize); 619 throw Py.IOError(e); 620 } 621 } 622 623 628 protected PyObject pyget(int i) { 629 return Py.java2py(Array.get(data, i)); 630 } 631 632 637 public Object getArray() throws PyIgnoreMethodTag { 638 return delegate.copyArray(); 639 } 640 641 667 public int getItemsize() { 668 669 if (type.isPrimitive()) { 670 671 if (type == Boolean.TYPE) 672 return 1; 673 else if (type == Byte.TYPE) 674 return 1; 675 else if (type == Character.TYPE) 676 return 1; 677 else if (type == Short.TYPE) 678 return 2; 679 else if (type == Integer.TYPE) 680 return 4; 681 else if (type == Long.TYPE) 682 return 8; 683 else if (type == Float.TYPE) 684 return 4; 685 else if (type == Double.TYPE) 686 return 8; 687 } 688 689 return 0; 691 } 692 693 702 protected PyObject getslice(int start, int stop, int step) { 703 if (step > 0 && stop < start) stop = start; 704 int n = sliceLength(start, stop, step); 705 706 PyArray ret = new PyArray(type, n); 707 if (step == 1) { 708 System.arraycopy(data, start, ret.data, 0, n); 709 return ret; 710 } 711 for (int i = start, j = 0; j < n; i += step, j++) { 712 Array.set(ret.data, j, Array.get(data, i)); 713 } 714 return ret; 715 } 716 717 724 public String getTypecode() throws PyIgnoreMethodTag { 725 return typecode; 726 } 727 728 735 public PyObject index(PyObject value) { 736 737 int index = indexInternal(value); 738 if(index != -1) return new PyInteger(index); 739 740 throw Py.ValueError("array.index(" + value + "): " + value + 741 " not found in array"); 742 } 743 744 751 private int indexInternal(PyObject value) { 752 for (int i = 0; i < delegate.getSize(); i++) { 754 if (value.equals(Py.java2py(Array.get(data, i)))) { 755 return i; 756 } 757 } 758 return -1; 759 } 760 761 769 public void insert(int index, PyObject value) { 770 delegate.makeInsertSpace(index); 771 Array.set(data, index, Py.tojava(value, type)); 772 } 773 774 779 public PyObject pop() { 780 return pop(-1); 781 } 782 783 791 public PyObject pop(int index) { 792 index = (index < 0) 794 ? delegate.getSize() + index 795 : index; 796 PyObject ret = Py.java2py(Array.get(data, index)); 797 delegate.remove(index); 798 return ret; 799 } 800 801 806 public void remove(PyObject value) { 807 int index = indexInternal(value) ; 808 if(index != -1) { 809 delegate.remove(index); 810 return; 811 } 812 813 throw Py.ValueError("array.remove(" + value + "): " 814 + value + " not found in array"); 815 } 816 817 824 protected PyObject repeat(int count) { 825 Object arraycopy = delegate.copyArray(); 826 827 PyArray ret = new PyArray(type, 0); 828 829 for(int i = 0; i < count; i++) { 830 ret.delegate.appendArray(arraycopy); 831 } 832 833 return ret; 834 } 835 836 840 public void reverse() { 841 Object array = Array.newInstance(type, Array.getLength(data)); 843 for(int i = 0, lastIndex = delegate.getSize() - 1; i <= lastIndex; i++) { 844 Array.set(array, lastIndex - i, Array.get(data, i)); 845 } 846 data = array; 847 } 848 849 862 protected void set(int i, PyObject value) { 863 864 if (type == Byte.TYPE) { 866 long val; 867 868 try { 869 val = ((Long )value.__tojava__(Long.TYPE)).longValue(); 870 } catch (ClassCastException e) { 871 throw Py.TypeError("Type not compatible with array type"); 872 } 873 874 if(val < Byte.MIN_VALUE) { 875 throw Py.OverflowError("value too small for " + type.getName()); 876 } else if (val > Byte.MAX_VALUE) { 877 throw Py.OverflowError("value too large for " + type.getName()); 878 } 879 } else if (type == Short.TYPE) { 880 long val; 881 882 try { 883 val = ((Long )value.__tojava__(Long.TYPE)).longValue(); 884 } catch (ClassCastException e) { 885 throw Py.TypeError("Type not compatible with array type"); 886 } 887 888 if(val < Short.MIN_VALUE) { 889 throw Py.OverflowError("value too small for " + type.getName()); 890 } else if (val > Short.MAX_VALUE) { 891 throw Py.OverflowError("value too large for " + type.getName()); 892 } 893 } else if (type == Integer.TYPE) { 894 long val; 895 896 try { 897 val = ((Long )value.__tojava__(Long.TYPE)).longValue(); 898 } catch (ClassCastException e) { 899 throw Py.TypeError("Type not compatible with array type"); 900 } 901 902 if(val < Integer.MIN_VALUE) { 903 throw Py.OverflowError("value too small for " + type.getName()); 904 } else if (val > Integer.MAX_VALUE) { 905 throw Py.OverflowError("value too large for " + type.getName()); 906 } 907 } else if (type == Long.TYPE) { 908 Object o; 909 try { 910 o = value.__tojava__(Long.TYPE); 911 } catch (ClassCastException e) { 912 throw Py.TypeError("Type not compatible with array type"); 913 } 914 915 if(o == Py.NoConversion) { 916 throw Py.OverflowError("value out of range for long"); 917 } 918 } 919 920 921 Object o = Py.tojava(value, type); 922 if(o == Py.NoConversion) { 923 throw Py.TypeError("Type not compatible with array type"); 924 } 925 926 Array.set(data, i, o); 927 } 928 929 938 protected void setslice(int start, int stop, int step, PyObject value) { 939 if(type == Character.TYPE && value instanceof PyString) { 940 char[] chars = null; 941 if (step != 1) { 943 throw Py.ValueError( 944 "invalid bounds for setting from string"); 945 } 946 chars = value.toString().toCharArray(); 947 948 int insertSpace = chars.length - (stop - start); 955 if(insertSpace > 0) { 957 delegate.makeInsertSpace(start, insertSpace); 958 } else if (insertSpace < 0) { 959 delegate.remove(start, -insertSpace + start - 1); 960 } 961 delegate.replaceSubArray(chars, start); 962 963 } else { 964 if (value instanceof PyString && type == Byte.TYPE) { 965 byte[] chars = value.toString().getBytes(); 966 if (chars.length == stop-start && step == 1) { 967 System.arraycopy(chars, 0, data, start, chars.length); 968 } else { 969 throw Py.ValueError( 970 "invalid bounds for setting from string"); 971 } 972 } else if(value instanceof PyArray){ 973 PyArray array = (PyArray)value; 974 int insertSpace = array.delegate.getSize() - (stop - start); 975 Object arrayCopy = array.delegate.copyArray(); 978 if(insertSpace > 0) { 979 delegate.makeInsertSpace(start, insertSpace); 980 } else if (insertSpace < 0) { 981 delegate.remove(start, -insertSpace + start - 1); 982 } 983 try { 984 delegate.replaceSubArray(arrayCopy, start); 985 } catch (IllegalArgumentException e) { 986 throw Py.TypeError("Slice typecode '" + array.typecode + 987 "' is not compatible with this array (typecode '" 988 + this.typecode + "')"); 989 } 990 } 991 } 992 993 } 994 995 1000 public void tofile(PyObject f) { 1001 1002 if(!(f instanceof PyFile)) 1003 throw Py.TypeError("arg must be open file"); 1004 1005 PyFile file = (PyFile)f; 1006 1007 if (file.mode.indexOf("w") == -1 && file.mode.indexOf("a") == -1) { 1008 throw Py.TypeError("file needs to be in write or append mode"); 1009 } 1010 1011 String buffer = tostring(); 1013 file.write(buffer); 1014 } 1015 1016 1021 public PyObject tolist() { 1022 PyList list = new PyList(); 1023 1024 for (int i = 0; i < delegate.getSize(); i++) { 1025 list.append(Py.java2py(Array.get(data, i))); 1026 } 1027 1028 return list; 1029 } 1030 1031 1041 private int toStream(OutputStream os) throws IOException { 1042 1043 DataOutputStream dos = new DataOutputStream (os); 1044 1045 if (type.isPrimitive()) { 1046 1047 if (type == Boolean.TYPE) { 1048 for (int i = 0; i < delegate.getSize(); i++) 1049 dos.writeBoolean(Array.getBoolean(data, i)); 1050 } 1051 else if (type == Byte.TYPE) { 1052 for (int i = 0; i < delegate.getSize(); i++) 1053 dos.writeByte(Array.getByte(data, i)); 1054 } 1055 else if (type == Character.TYPE) { 1056 for (int i = 0; i < delegate.getSize(); i++) 1057 dos.writeByte((byte)Array.getChar(data, i)); 1058 } 1059 else if(type == Integer.TYPE) { 1060 for (int i = 0; i < delegate.getSize(); i++) 1061 dos.writeInt(Array.getInt(data, i)); 1062 } 1063 else if (type == Short.TYPE) { 1064 for (int i = 0; i < delegate.getSize(); i++) 1065 dos.writeShort(Array.getShort(data, i)); 1066 } 1067 else if (type == Long.TYPE) { 1068 for (int i = 0; i < delegate.getSize(); i++) 1069 dos.writeLong(Array.getLong(data, i)); 1070 } 1071 else if (type == Float.TYPE) { 1072 for (int i = 0; i < delegate.getSize(); i++) 1073 dos.writeFloat(Array.getFloat(data, i)); 1074 } 1075 else if (type == Double.TYPE) { 1076 for (int i = 0; i < delegate.getSize(); i++) 1077 dos.writeDouble(Array.getDouble(data, i)); 1078 } 1079 } 1080 1081 return dos.size(); 1082 } 1083 1084 1089 public String tostring() { 1090 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 1091 1092 try { 1093 toStream(bos); 1094 } catch (IOException e) { 1095 throw Py.IOError(e); 1096 } 1097 1098 return new String (bos.toByteArray()); 1099 } 1100 1101} 1102 | Popular Tags |