This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: [Patch] Fix PR libgcj/20389
Bryce McKinlay wrote:
David Daney wrote:
BufferedInputStream.java from Classpath breaks InputStreamReader.java.
InputStreamReader.java from Classpath breaks because it needs
gnu.java.io.decode.Decoder.
We either need to merge much of Classpath, or fix the existing
BufferedInputStream.
The Encoder/Decoder mechanisms definitely need to be merged, and I
believe this ie being worked on, but thats probably too much change for
now.
The appropriate fix for InputStreamReader's dependence on
BufferedInputStream will depend on the outcome of that merge.
The Classpath version looks plausible, but I would have to hack on it
to make it fit with InputStreamReader.
Your call I guess.
That sounds ok - whatever results in the least diff's against classpath
without changing things too radically for 4.0. Would making refill()
package-private be sufficient?
The attached patch brings BufferedInputStream over from Classpath with
the only changes being that the copyright in Classpath omits 2004 and
had refill() being private.
refill has to have default visibility because InputStreamReader does
some highly questionable things with it. Since the file was in fact
changed in 2004 I thought the copyright should reflect that.
I added the PR testcase to mauve and did make check in libjava and mauve
with no regressions on the 4.0.0 branch (i686-pc-linux).
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.
OK to commit to the 4.0 branch and mainline?
David Daney.
Index: java/io/BufferedInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/BufferedInputStream.java,v
retrieving revision 1.11
diff -u -p -r1.11 BufferedInputStream.java
--- java/io/BufferedInputStream.java 11 Jan 2005 20:04:33 -0000 1.11
+++ java/io/BufferedInputStream.java 9 Mar 2005 19:24:28 -0000
@@ -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
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
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
{
// Free up the array memory.
buf = null;
+ pos = count = 0;
+ markpos = -1;
super.close();
}
@@ -196,9 +196,7 @@ public class BufferedInputStream extends
*/
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
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
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
off += remain;
len -= remain;
totalBytesRead += remain;
-
- if (markpos >= 0 && pos - markpos > marktarget)
- markpos = -1;
}
return totalBytesRead;
@@ -339,17 +328,11 @@ public class BufferedInputStream extends
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;
@@ -366,39 +349,31 @@ public class BufferedInputStream extends
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: java/io/InputStreamReader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/InputStreamReader.java,v
retrieving revision 1.18
diff -u -p -r1.18 InputStreamReader.java
--- java/io/InputStreamReader.java 21 Feb 2005 08:27:00 -0000 1.18
+++ java/io/InputStreamReader.java 9 Mar 2005 19:24:28 -0000
@@ -282,11 +282,9 @@ public class InputStreamReader extends R
{
// 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);