[Jython-checkins] jython: Implemented bytearray.__mul__() etc., and pop.
frank.wierzbicki
jython-checkins at python.org
Tue Jun 5 06:12:34 CEST 2012
http://hg.python.org/jython/rev/d2b13175bb0e
changeset: 6682:d2b13175bb0e
user: Jeff Allen <ja...py at farowl.co.uk>
date: Sat Jun 02 20:30:28 2012 +0100
summary:
Implemented bytearray.__mul__() etc., and pop.
Wrapped related memory allocations in try-catch. Now scoring 2 failures and 36 errors in test_bytes.py
files:
src/org/python/core/BaseBytes.java | 95 +++++++++----
src/org/python/core/PyByteArray.java | 104 ++++++++++++++-
2 files changed, 166 insertions(+), 33 deletions(-)
diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java
--- a/src/org/python/core/BaseBytes.java
+++ b/src/org/python/core/BaseBytes.java
@@ -511,22 +511,25 @@
Fragment curr = null;
// Allocate series of fragments as needed, while the iterator runs to completion
-
- for (PyObject value : iter) {
- if (curr == null) {
- // Need a new Fragment
- curr = new Fragment(fragSize);
- add(curr);
- if (fragSize < Fragment.MAXSIZE) {
- fragSize <<= 1;
+ try {
+ for (PyObject value : iter) {
+ if (curr == null) {
+ // Need a new Fragment
+ curr = new Fragment(fragSize);
+ add(curr);
+ if (fragSize < Fragment.MAXSIZE) {
+ fragSize <<= 1;
+ }
+ }
+ // Insert next item from iterator.
+ if (curr.isFilledBy(value)) {
+ // Fragment is now full: signal a new one will be needed
+ totalCount += curr.count;
+ curr = null;
}
}
- // Insert next item from iterator.
- if (curr.isFilledBy(value)) {
- // Fragment is now full: signal a new one will be needed
- totalCount += curr.count;
- curr = null;
- }
+ } catch (OutOfMemoryError e) {
+ throw Py.MemoryError(e.getMessage());
}
// Don't forget the bytes in the final Fragment
@@ -623,7 +626,11 @@
protected void newStorage(int needed) {
// The implementation for immutable arrays allocates only as many bytes as needed.
if (needed > 0) {
- setStorage(new byte[needed]); // guaranteed zero (by JLS 2ed para 4.5.5)
+ try {
+ setStorage(new byte[needed]); // guaranteed zero (by JLS 2ed para 4.5.5)
+ } catch (OutOfMemoryError e) {
+ throw Py.MemoryError(e.getMessage());
+ }
} else {
setStorage(emptyStorage);
}
@@ -2520,12 +2527,14 @@
// Calculate length of result and check for too big
long result_len = size + count * (to_len - from_len);
- if (result_len > Integer.MAX_VALUE) {
- Py.OverflowError("replace bytes is too long");
+ byte[] r; // Build result here
+ try {
+ // Good to go. As we know the ultimate size, we can do all our allocation in one
+ r = new byte[(int)result_len];
+ } catch (OutOfMemoryError e) {
+ throw Py.OverflowError("replace bytes is too long");
}
- // Good to go. As we know the ultimate size, we can do all our allocation in one
- byte[] r = new byte[(int)result_len];
int p = offset; // Copy-from index in this.storage
int rp = 0; // Copy-to index in r
@@ -2585,12 +2594,14 @@
// Calculate length of result and check for too big
long result_len = ((long)count) * to_len + size;
- if (result_len > Integer.MAX_VALUE) {
- Py.OverflowError("replace bytes is too long");
+ byte[] r; // Build result here
+ try {
+ // Good to go. As we know the ultimate size, we can do all our allocation in one
+ r = new byte[(int)result_len];
+ } catch (OutOfMemoryError e) {
+ throw Py.OverflowError("replace bytes is too long");
}
- // Good to go. As we know the ultimate size, we can do all our allocation in one
- byte[] r = new byte[(int)result_len];
int p = offset; // Copy-from index in this.storage
int rp = 0; // Copy-to index in r
@@ -2640,8 +2651,14 @@
long result_len = size - (count * from_len);
assert (result_len >= 0);
- // Good to go. As we know the ultimate size, we can do all our allocation in one
- byte[] r = new byte[(int)result_len];
+ byte[] r; // Build result here
+ try {
+ // Good to go. As we know the ultimate size, we can do all our allocation in one
+ r = new byte[(int)result_len];
+ } catch (OutOfMemoryError e) {
+ throw Py.OverflowError("replace bytes is too long");
+ }
+
int p = offset; // Copy-from index in this.storage
int rp = 0; // Copy-to index in r
@@ -2698,7 +2715,13 @@
int count = maxcount;
// The result will be this.size
- byte[] r = new byte[size];
+ byte[] r; // Build result here
+ try {
+ r = new byte[this.size];
+ } catch (OutOfMemoryError e) {
+ throw Py.OverflowError("replace bytes is too long");
+ }
+
System.arraycopy(storage, offset, r, 0, size);
// Change everything in-place: easiest if we search the destination
@@ -3142,11 +3165,23 @@
* @return this byte array repeated count times.
*/
protected synchronized byte[] repeatImpl(int count) {
- byte[] dst = new byte[count * size];
- for (int i = 0, p = 0; i < count; i++, p += size) {
- System.arraycopy(storage, offset, dst, p, size);
+ if (count <= 0) {
+ return emptyStorage;
+ } else {
+ // Allocate new storage, in a guarded way
+ long newSize = ((long)count) * size;
+ byte[] dst;
+ try {
+ dst = new byte[(int)newSize];
+ } catch (OutOfMemoryError e) {
+ throw Py.MemoryError(e.getMessage());
+ }
+ // Now fill with the repetitions needed
+ for (int i = 0, p = 0; i < count; i++, p += size) {
+ System.arraycopy(storage, offset, dst, p, size);
+ }
+ return dst;
}
- return dst;
}
/*
diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java
--- a/src/org/python/core/PyByteArray.java
+++ b/src/org/python/core/PyByteArray.java
@@ -259,6 +259,16 @@
}
/**
+ * Replace the contents of this PyByteArray with the given number of repeats of the original
+ * contents, as in the implementation of <tt>__mul__</tt> for strings.
+ *
+ * @param count the number of times to repeat this.
+ */
+ protected synchronized void irepeat(int count) {
+ this.setStorage(repeatImpl(count));
+ }
+
+ /**
* Sets the indexed element of the bytearray to the given value. This is an extension point
* called by PySequence in its implementation of {@link #__setitem__} It is guaranteed by
* PySequence that the index is within the bounds of the array. Any other clients calling
@@ -781,6 +791,58 @@
}
/**
+ * Equivalent to the standard Python <code>__imul__</code> method, that for a byte array returns
+ * a new byte array containing the same thing n times.
+ */
+ @Override
+ public PyObject __imul__(PyObject n) {
+ return bytearray___imul__(n);
+ }
+
+ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.bytearray___mul___doc)
+ final PyObject bytearray___imul__(PyObject n) {
+ if (!n.isIndex()) {
+ return null;
+ }
+ irepeat(n.asIndex(Py.OverflowError));
+ return this;
+ }
+
+ /**
+ * Equivalent to the standard Python <code>__mul__</code> method, that for a byte array returns
+ * a new byte array containing the same thing n times.
+ */
+ @Override
+ public PyObject __mul__(PyObject n) {
+ return bytearray___mul__(n);
+ }
+
+ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.bytearray___mul___doc)
+ final PyObject bytearray___mul__(PyObject n) {
+ if (!n.isIndex()) {
+ return null;
+ }
+ return repeat(n.asIndex(Py.OverflowError));
+ }
+
+ /**
+ * Equivalent to the standard Python <code>__rmul__</code> method, that for a byte array returns
+ * a new byte array containing the same thing n times.
+ */
+ @Override
+ public PyObject __rmul__(PyObject n) {
+ return bytearray___rmul__(n);
+ }
+
+ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.bytearray___rmul___doc)
+ final PyObject bytearray___rmul__(PyObject n) {
+ if (!n.isIndex()) {
+ return null;
+ }
+ return repeat(n.asIndex(Py.OverflowError));
+ }
+
+ /**
* Append a single element to the end of the array, equivalent to:
* <code>s[len(s):len(s)] = o</code>. The argument must be a PyInteger, PyLong or string of
* length 1.
@@ -1133,6 +1195,38 @@
return basebytes_partition(sep);
}
+ /**
+ * Removes and return the last element in the byte array.
+ * @return PyInteger representing the value
+ */
+ public PyInteger pop() {
+ return bytearray_pop(-1);
+ }
+
+ /**
+ * Remove and return the <code>n</code>th byte element in the array.
+ *
+ * @param i the index of the byte to remove and return.
+ * @return PyInteger representing the value
+ */
+ public PyInteger pop(int i) {
+ return bytearray_pop(i);
+ }
+
+ @ExposedMethod(defaults = "-1", doc = BuiltinDocs.bytearray_pop_doc)
+ final synchronized PyInteger bytearray_pop(int i) {
+ if (size == 0) {
+ throw Py.IndexError("pop from empty list");
+ } else {
+ // Deal with slice interpretation of single index
+ if (i < 0) {
+ i += size;
+ }
+ // Use List.remove(int)
+ return remove(i);
+ }
+ }
+
@ExposedMethod(doc = BuiltinDocs.bytearray___reduce___doc)
final PyObject bytearray___reduce__() {
return basebytes___reduce__();
@@ -1147,7 +1241,7 @@
* @throws PyException ValueError if o not found in bytearray
*/
public void remove(PyObject o) throws PyException {
- bytearray_append(o);
+ bytearray_remove(o);
}
@ExposedMethod(doc = BuiltinDocs.bytearray_remove_doc)
@@ -1525,8 +1619,12 @@
protected void newStorage(int needed) {
if (needed > 0) {
final int L = recLength(needed);
- byte[] s = new byte[L]; // guaranteed zero (by JLS 2ed para 4.5.5)
- setStorage(s, needed, (L - needed) / 2);
+ try {
+ byte[] s = new byte[L]; // guaranteed zero (by JLS 2ed para 4.5.5)
+ setStorage(s, needed, (L - needed) / 2);
+ } catch (OutOfMemoryError e) {
+ throw Py.MemoryError(e.getMessage());
+ }
} else {
setStorage(emptyStorage);
}
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list