re PR libgcj/20389 (BufferedInputStream gets ArrayIndexOutOfBoundsExeception)
authorDavid Daney <ddaney@avtrex.com>
Wed, 9 Mar 2005 22:11:33 +0000 (22:11 +0000)
committerDavid Daney <daney@gcc.gnu.org>
Wed, 9 Mar 2005 22:11:33 +0000 (22:11 +0000)
2005-03-09  David Daney  <ddaney@avtrex.com>

PR libgcj/20389
Merge BufferedInputStream from GNU Classpath.
* java/io/BufferedInputStream.java (marktarget): Field removed.
(CHUNKSIZE): Field removed.
(bufferSize): New field.
(BufferedInputStream): Initialize fields.
(close): Invalidate mark and buffer indexes.
(mark):  Rewritten.
(read()): Move mark handling code to refill.
(read(byte[], int, int)): Ditto.
(skip): Ditto and simplify EOF testing.
(refill): Rewritten.
* java/io/InputStreamReader.java (refill): Removed mark and reset
of internal BufferedInputStream.

From-SVN: r96217

libjava/ChangeLog
libjava/java/io/BufferedInputStream.java
libjava/java/io/InputStreamReader.java

index 680473cb8ac6c69a372f362cc8641db3fc9662b9..e55087ceddb43a56df785b17a76ddf7cf932be97 100644 (file)
@@ -1,3 +1,20 @@
+2005-03-09  David Daney  <ddaney@avtrex.com>
+
+       PR libgcj/20389
+       Merge BufferedInputStream from GNU Classpath.
+       * java/io/BufferedInputStream.java (marktarget): Field removed.
+       (CHUNKSIZE): Field removed.
+       (bufferSize): New field.
+       (BufferedInputStream): Initialize fields.
+       (close): Invalidate mark and buffer indexes.
+       (mark):  Rewritten.
+       (read()): Move mark handling code to refill.
+       (read(byte[], int, int)): Ditto.
+       (skip): Ditto and simplify EOF testing.
+       (refill): Rewritten.
+       * java/io/InputStreamReader.java (refill): Removed mark and reset
+       of internal BufferedInputStream.
+
 2005-03-09  Tom Tromey  <tromey@redhat.com>
 
        * java/lang/natVMClassLoader.cc (defineClass): Reference
index 5343f0762b619eeb461edee53a898c2ecb3b3e45..bbb38c4371995c37be7994bb12c95077db56ab6b 100644 (file)
@@ -65,6 +65,7 @@ package java.io;
  */
 public class BufferedInputStream extends FilterInputStream
 {
+
   /**
    * This is the default buffer size
    */
@@ -103,17 +104,11 @@ public class BufferedInputStream extends FilterInputStream
   protected int marklimit;
 
   /**
-   * This is the maximum size we have to allocate for the mark buffer.
-   * This number may be huge (Integer.MAX_VALUE). The class will continue
-   * to allocate new chunks (specified by <code>CHUNKSIZE</code>) until the
-   * the size specified by this field is achieved.
-   */
-  private int marktarget = 0;
-
-  /**
-   * This is the number of bytes to allocate to reach marktarget.
+   * This is the initial buffer size. When the buffer is grown because
+   * of marking requirements, it will be grown by bufferSize increments.
+   * The underlying stream will be read in chunks of bufferSize.
    */
-  static final private int CHUNKSIZE = 1024;
+  private final int bufferSize;
 
   /**
    * This method initializes a new <code>BufferedInputStream</code> that will
@@ -143,6 +138,9 @@ public class BufferedInputStream extends FilterInputStream
     if (size <= 0)
       throw new IllegalArgumentException();
     buf = new byte[size];
+    // initialize pos & count to bufferSize, to prevent refill from
+    // allocating a new buffer (if the caller starts out by calling mark()).
+    pos = count = bufferSize = size;
   }
 
   /**
@@ -173,6 +171,8 @@ public class BufferedInputStream extends FilterInputStream
   {
     // Free up the array memory.
     buf = null;
+    pos = count = 0;
+    markpos = -1;
     super.close();
   }
 
@@ -196,9 +196,7 @@ public class BufferedInputStream extends FilterInputStream
    */
   public synchronized void mark(int readlimit)
   {
-    marktarget = marklimit = readlimit;
-    if (marklimit > CHUNKSIZE)
-      marklimit = CHUNKSIZE;
+    marklimit = readlimit;
     markpos = pos;
   }
 
@@ -231,9 +229,6 @@ public class BufferedInputStream extends FilterInputStream
     if (pos >= count && !refill())
       return -1;       // EOF
 
-    if (markpos >= 0 && pos - markpos > marktarget)
-      markpos = -1;
-
     return buf[pos++] & 0xFF;
   }
 
@@ -278,9 +273,6 @@ public class BufferedInputStream extends FilterInputStream
     off += totalBytesRead;
     len -= totalBytesRead;
 
-    if (markpos >= 0 && pos - markpos > marktarget)
-      markpos = -1;
-
     while (len > 0 && super.available() > 0 && refill())
       {
        int remain = Math.min(count - pos, len);
@@ -289,9 +281,6 @@ public class BufferedInputStream extends FilterInputStream
        off += remain;
        len -= remain;
        totalBytesRead += remain;
-
-       if (markpos >= 0 && pos - markpos > marktarget)
-         markpos = -1;
       }
 
     return totalBytesRead;
@@ -339,22 +328,17 @@ public class BufferedInputStream extends FilterInputStream
     while (n > 0L)
       {
        if (pos >= count && !refill())
-         if (n < origN)
-           break;
-         else
-           return 0;   // No bytes were read before EOF.
+          break;
 
        int numread = (int) Math.min((long) (count - pos), n);
        pos += numread;
        n -= numread;
-
-        if (markpos >= 0 && pos - markpos > marktarget)
-          markpos = -1;
       }
 
     return origN - n;
   }
 
+  // GCJ LOCAL: package-private for use by InputStreamReader
   /**
    * Called to refill the buffer (when count is equal to pos).
    *
@@ -366,39 +350,31 @@ public class BufferedInputStream extends FilterInputStream
     if (buf == null)
       throw new IOException("Stream closed.");
 
-    if (markpos < 0)
-      count = pos = 0;
-    else if (markpos > 0)
+    if (markpos == -1 || count - markpos >= marklimit)
       {
-        // Shift the marked bytes (if any) to the beginning of the array
-       // but don't grow it.  This saves space in case a reset is done
-       // before we reach the max capacity of this array.
-        System.arraycopy(buf, markpos, buf, 0, count - markpos);
-       count -= markpos;
-       pos -= markpos;
-       markpos = 0;
+       markpos = -1;
+       pos = count = 0;
       }
-    else if (count >= buf.length && count < marktarget)        // BTW, markpos == 0
+    else
       {
-       // Need to grow the buffer now to have room for marklimit bytes.
-       // Note that the new buffer is one greater than marklimit.
-       // This is so that there will be one byte past marklimit to be read
-       // before having to call refill again, thus allowing marklimit to be
-       // invalidated.  That way refill doesn't have to check marklimit.
-       marklimit += CHUNKSIZE;
-       if (marklimit >= marktarget)
-         marklimit = marktarget;
-       byte[] newbuf = new byte[marklimit + 1];
-       System.arraycopy(buf, 0, newbuf, 0, count);
+       byte[] newbuf = buf;
+       if (markpos < bufferSize)
+         {
+           newbuf = new byte[count - markpos + bufferSize];
+         }
+       System.arraycopy(buf, markpos, newbuf, 0, count - markpos);
        buf = newbuf;
+       count -= markpos;
+       pos -= markpos;
+       markpos = 0;
       }
 
-    int numread = super.read(buf, count, buf.length - count);
+    int numread = super.read(buf, count, bufferSize);
 
-    if (numread < 0)   // EOF
+    if (numread <= 0)  // EOF
       return false;
 
     count += numread;
-    return numread > 0;
+    return true;
   }
 }
index ee03a5e617590abcec4b301ad888fafdbb16fcc3..b3f65368ce31d51d66e7df6177707d04b625f3c2 100644 (file)
@@ -282,11 +282,9 @@ public class InputStreamReader extends Reader
       {
        // We have knowledge of the internals of BufferedInputStream
        // here.  Eww.
-       in.mark (0);
        // BufferedInputStream.refill() can only be called when
        // `pos>=count'.
        boolean r = in.pos < in.count || in.refill ();
-       in.reset ();
        if (! r)
          return -1;
        converter.setInput(in.buf, in.pos, in.count);