/[classpath]/classpath/java/io/BufferedInputStream.java
ViewVC logotype

Diff of /classpath/java/io/BufferedInputStream.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.11 by mark, Tue Mar 9 07:48:56 2004 UTC revision 1.12 by jfrijters, Sat Jul 10 08:03:01 2004 UTC
# Line 61  package java.io; Line 61  package java.io;
61   *   *
62   * @author Aaron M. Renn (arenn@urbanophile.com)   * @author Aaron M. Renn (arenn@urbanophile.com)
63   * @author Warren Levy <warrenl@cygnus.com>   * @author Warren Levy <warrenl@cygnus.com>
64     * @author Jeroen Frijters <jeroen@frijters.net>
65   */   */
66  public class BufferedInputStream extends FilterInputStream  public class BufferedInputStream extends FilterInputStream
67  {  {
# Line 79  public class BufferedInputStream extends Line 80  public class BufferedInputStream extends
80     * The number of valid bytes currently in the buffer.  It is also the index     * The number of valid bytes currently in the buffer.  It is also the index
81     * of the buffer position one byte past the end of the valid data.     * of the buffer position one byte past the end of the valid data.
82     */     */
83    protected int count = 0;    protected int count;
84    
85    /**    /**
86     * The index of the next character that will by read from the buffer.     * The index of the next character that will by read from the buffer.
87     * When <code>pos == count</code>, the buffer is empty.     * When <code>pos == count</code>, the buffer is empty.
88     */     */
89    protected int pos = 0;    protected int pos;
90    
91    /**    /**
92     * The value of <code>pos</code> when the <code>mark()</code> method was     * The value of <code>pos</code> when the <code>mark()</code> method was
# Line 100  public class BufferedInputStream extends Line 101  public class BufferedInputStream extends
101     * After this may bytes are read, the <code>reset()</code> method     * After this may bytes are read, the <code>reset()</code> method
102     * may not be called successfully.     * may not be called successfully.
103     */     */
104    protected int marklimit = 0;    protected int marklimit;
105    
106    /**    /**
107     * This is the maximum size we have to allocate for the mark buffer.     * This is the initial buffer size. When the buffer is grown because
108     * This number may be huge (Integer.MAX_VALUE). The class will continue     * of marking requirements, it will be grown by bufferSize increments.
109     * to allocate new chunks (specified by <code>CHUNKSIZE</code>) until the     * The underlying stream will be read in chunks of bufferSize.
    * the size specified by this field is achieved.  
110     */     */
111    private int marktarget = 0;    private final int bufferSize;
   
   /**  
    * This is the number of bytes to allocate to reach marktarget.  
    */  
   static final private int CHUNKSIZE = 1024;  
112    
113    /**    /**
114     * This method initializes a new <code>BufferedInputStream</code> that will     * This method initializes a new <code>BufferedInputStream</code> that will
# Line 143  public class BufferedInputStream extends Line 138  public class BufferedInputStream extends
138      if (size <= 0)      if (size <= 0)
139        throw new IllegalArgumentException();        throw new IllegalArgumentException();
140      buf = new byte[size];      buf = new byte[size];
141        // initialize pos & count to bufferSize, to prevent refill from
142        // allocating a new buffer (if the caller starts out by calling mark()).
143        pos = count = bufferSize = size;
144    }    }
145    
146    /**    /**
# Line 173  public class BufferedInputStream extends Line 171  public class BufferedInputStream extends
171    {    {
172      // Free up the array memory.      // Free up the array memory.
173      buf = null;      buf = null;
174        pos = count = 0;
175        markpos = -1;
176      super.close();      super.close();
177    }    }
178    
# Line 196  public class BufferedInputStream extends Line 196  public class BufferedInputStream extends
196     */     */
197    public synchronized void mark(int readlimit)    public synchronized void mark(int readlimit)
198    {    {
199      marktarget = marklimit = readlimit;      marklimit = readlimit;
     if (marklimit > CHUNKSIZE)  
         marklimit = CHUNKSIZE;  
200      markpos = pos;      markpos = pos;
201    }    }
202    
# Line 231  public class BufferedInputStream extends Line 229  public class BufferedInputStream extends
229      if (pos >= count && !refill())      if (pos >= count && !refill())
230        return -1;        // EOF        return -1;        // EOF
231    
232      if (markpos >= 0 && pos - markpos > marktarget)      return buf[pos++] & 0xFF;
       markpos = -1;  
   
     return ((int) buf[pos++]) & 0xFF;  
233    }    }
234    
235    /**    /**
236     * This method reads bytes from a stream and stores them into a caller     * This method reads bytes from a stream and stores them into a caller
237     * supplied buffer.  It starts storing the data at index <code>off</code>     * supplied buffer.  It starts storing the data at index <code>off</code>
238     * into the buffer and attempts to read <code>len</code> bytes.  This method     * into the buffer and attempts to read <code>len</code> bytes.  This method
239     * can return before reading the number of bytes requested.  The actual     * can return before reading the number of bytes requested, but it will try
240     * number of bytes read is returned as an int.  A -1 is returned to indicate     * to read the requested number of bytes by repeatedly calling the underlying
241     * the end of the stream.     * stream as long as available() for this stream continues to return a
242       * non-zero value (or until the requested number of bytes have been read).
243       * The actual number of bytes read is returned as an int.  A -1 is returned
244       * to indicate the end of the stream.
245     * <p>     * <p>
246     * This method will block until some data can be read.     * This method will block until some data can be read.
247     *     *
# Line 260  public class BufferedInputStream extends Line 258  public class BufferedInputStream extends
258     */     */
259    public synchronized int read(byte[] b, int off, int len) throws IOException    public synchronized int read(byte[] b, int off, int len) throws IOException
260    {    {
261      if (off < 0 || len < 0 || off + len > b.length)      if (off < 0 || len < 0 || b.length - off < len)
262        throw new IndexOutOfBoundsException();        throw new IndexOutOfBoundsException();
263    
264      if (pos >= count && !refill())      if (pos >= count && !refill())
265        return -1;                // No bytes were read before EOF.        return -1;                // No bytes were read before EOF.
266    
267      int remain = Math.min(count - pos, len);      int totalBytesRead = Math.min(count - pos, len);
268      System.arraycopy(buf, pos, b, off, remain);      System.arraycopy(buf, pos, b, off, totalBytesRead);
269      pos += remain;      pos += totalBytesRead;
270        off += totalBytesRead;
271        len -= totalBytesRead;
272    
273      if (markpos >= 0 && pos - markpos > marktarget)      while (len > 0 && super.available() > 0 && refill())
274        markpos = -1;        {
275            int remain = Math.min(count - pos, len);
276            System.arraycopy(buf, pos, b, off, remain);
277            pos += remain;
278            off += remain;
279            len -= remain;
280            totalBytesRead += remain;
281          }
282    
283      return remain;      return totalBytesRead;
284    }    }
285    
286    /**    /**
# Line 286  public class BufferedInputStream extends Line 293  public class BufferedInputStream extends
293     * passed when establishing the mark.     * passed when establishing the mark.
294     *     *
295     * @exception IOException If <code>mark()</code> was never called or more     * @exception IOException If <code>mark()</code> was never called or more
296     *            then <code>markLimit</code> bytes were read since the last     *            then <code>marklimit</code> bytes were read since the last
297     *            call to <code>mark()</code>     *            call to <code>mark()</code>
298     */     */
299    public synchronized void reset() throws IOException    public synchronized void reset() throws IOException
300    {    {
301      if (markpos < 0)      if (markpos == -1)
302        throw new IOException();        throw new IOException(buf == null ? "Stream closed." : "Invalid mark.");
303    
304      pos = markpos;      pos = markpos;
305    }    }
# Line 310  public class BufferedInputStream extends Line 317  public class BufferedInputStream extends
317     */     */
318    public synchronized long skip(long n) throws IOException    public synchronized long skip(long n) throws IOException
319    {    {
320        if (buf == null)
321            throw new IOException("Stream closed.");
322    
323      final long origN = n;      final long origN = n;
324    
325      while (n > 0L)      while (n > 0L)
# Line 323  public class BufferedInputStream extends Line 333  public class BufferedInputStream extends
333          int numread = (int) Math.min((long) (count - pos), n);          int numread = (int) Math.min((long) (count - pos), n);
334          pos += numread;          pos += numread;
335          n -= numread;          n -= numread;
   
         if (markpos >= 0 && pos - markpos > marktarget)  
           markpos = -1;  
336        }        }
337    
338      return origN - n;      return origN - n;
339    }    }
340    
341    /**    /**
342     * Called to refill the buffer (when count is equal or greater the pos).     * Called to refill the buffer (when count is equal to pos).
    * Package local so BufferedReader can call it when needed.  
343     *     *
344     * @return <code>true</code> when <code>buf</code> can be (partly) refilled,     * @return <code>true</code> when at least one additional byte was read
345     *         <code>false</code> otherwise.     *         into <code>buf</code>, <code>false</code> otherwise (at EOF).
346     */     */
347    boolean refill() throws IOException    private boolean refill() throws IOException
348    {    {
349      if (markpos < 0)      if (buf == null)
350        count = pos = 0;          throw new IOException("Stream closed.");
351      else if (markpos > 0)  
352        if (markpos == -1 || count - markpos >= marklimit)
353        {        {
354          // Shift the marked bytes (if any) to the beginning of the array          markpos = -1;
355          // but don't grow it.  This saves space in case a reset is done          pos = count = 0;
         // before we reach the max capacity of this array.  
         System.arraycopy(buf, markpos, buf, 0, count - markpos);  
         count -= markpos;  
         pos -= markpos;  
         markpos = 0;  
356        }        }
357      else if (marktarget >= buf.length && marklimit < marktarget)        // BTW, markpos == 0      else
358        {        {
359          // Need to grow the buffer now to have room for marklimit bytes.          byte[] newbuf = buf;
360          // Note that the new buffer is one greater than marklimit.          if (markpos < bufferSize)
361          // This is so that there will be one byte past marklimit to be read            {
362          // before having to call refill again, thus allowing marklimit to be              newbuf = new byte[count - markpos + bufferSize];
363          // invalidated.  That way refill doesn't have to check marklimit.            }
364          marklimit += CHUNKSIZE;          System.arraycopy(buf, markpos, newbuf, 0, count - markpos);
         if (marklimit >= marktarget)  
           marklimit = marktarget;  
         byte[] newbuf = new byte[marklimit + 1];  
         System.arraycopy(buf, 0, newbuf, 0, count);  
365          buf = newbuf;          buf = newbuf;
366            count -= markpos;
367            pos -= markpos;
368            markpos = 0;
369        }        }
370    
371      int numread = super.read(buf, count, buf.length - count);      int numread = super.read(buf, count, bufferSize);
372    
373      if (numread < 0)    // EOF      if (numread <= 0)   // EOF
374        return false;          return false;
375    
376      count += numread;      count += numread;
377      return true;      return true;

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26