[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