DataInputStream.java: Merge classpath docs.
authorBryce McKinlay <bryce@albatross.co.nz>
Tue, 28 Nov 2000 04:50:51 +0000 (04:50 +0000)
committerBryce McKinlay <bryce@gcc.gnu.org>
Tue, 28 Nov 2000 04:50:51 +0000 (04:50 +0000)
2000-11-28  Bryce McKinlay  <bryce@abatross.co.nz>

* java/io/DataInputStream.java: Merge classpath docs. Call in.read()
directly rather than read() in all cases. Make primitive read
implementations more efficient, as defined in JDK online docs.
(skipBytes): Behave like the JDK's implementation.
* java/io/BufferedReader.java: Merge classpath docs. Check for a
closed stream with checkStatus() whenever an IOException can be
thrown.
(checkStatus): New private method.

From-SVN: r37810

libjava/ChangeLog
libjava/java/io/BufferedReader.java
libjava/java/io/DataInputStream.java

index 8176ba9..db3f188 100644 (file)
@@ -1,3 +1,14 @@
+2000-11-28  Bryce McKinlay  <bryce@abatross.co.nz>
+
+       * java/io/DataInputStream.java: Merge classpath docs. Call in.read()
+       directly rather than read() in all cases. Make primitive read 
+       implementations more efficient, as defined in JDK online docs.
+       (skipBytes): Behave like the JDK's implementation.
+       * java/io/BufferedReader.java: Merge classpath docs. Check for a 
+       closed stream with checkStatus() whenever an IOException can be 
+       thrown.
+       (checkStatus): New private method.
+
 2000-11-27  Warren Levy  <warrenl@cygnus.com>
 
        * Makefile.am: Added natTimeZone.cc.
index 73601de..9a293da 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -8,15 +8,25 @@ details.  */
  
 package java.io;
 
-/**
- * @author Per Bothner <bothner@cygnus.com>
- * @date April 22, 1998.  
- */
 /* Written using "Java Class Libraries", 2nd edition, plus online
  * API docs for JDK 1.2 beta from http://www.javasoft.com.
  * Status:  Believed complete and correct.
  */
 
+/**
+  * This subclass of <code>FilterReader</code> buffers input from an 
+  * underlying implementation to provide a possibly more efficient read
+  * mechanism.  It maintains the buffer and buffer state in instance 
+  * variables that are available to subclasses.  The default buffer size
+  * of 512 chars can be overridden by the creator of the stream.
+  * <p>
+  * This class also implements mark/reset functionality.  It is capable
+  * of remembering any number of input chars, to the limits of
+  * system memory or the size of <code>Integer.MAX_VALUE</code>
+  *
+  * @author Per Bothner <bothner@cygnus.com>
+  * @author Aaron M. Renn <arenn@urbanophile.com>
+  */
 public class BufferedReader extends Reader
 {
   Reader in;
@@ -43,11 +53,25 @@ public class BufferedReader extends Reader
      guaranteed to be >= the read-limit requested in the call to mark. */
   int markPos = -1;
 
+  /**
+    * Create a new <code>BufferedReader</code> that will read from the 
+    * specified subordinate stream with a default buffer size of 4096 chars.
+    *
+    * @param in The subordinate stream to read from
+    */
   public BufferedReader(Reader in)
   {
     this(in, 8192);
   }
 
+  /**
+    * Create a new <code>BufferedReader</code> that will read from the 
+    * specified subordinate stream with a buffer size that is specified by the 
+    * caller.
+    *
+    * @param in The subordinate stream to read from
+    * @param bufsize The buffer size to use
+    */
   public BufferedReader(Reader in, int size)
   {
     super(in.lock);
@@ -55,6 +79,11 @@ public class BufferedReader extends Reader
     buffer = new char[size];
   }
 
+  /**
+    * This method closes the stream 
+    *
+    * @exception IOException If an error occurs
+    */
   public void close() throws IOException
   {
     synchronized (lock)
@@ -66,13 +95,40 @@ public class BufferedReader extends Reader
       }
   }
 
+  /**
+    * Returns <code>true</code> to indicate that this class supports mark/reset 
+    * functionality.
+    *
+    * @return <code>true</code>
+    */
   public boolean markSupported()
   {
     return true;
   }
 
+  /**
+    * Mark a position in the input to which the stream can be
+    * "reset" by calling the <code>reset()</code> method.  The parameter
+    * <code>readlimit</code> is the number of chars that can be read from the 
+    * stream after setting the mark before the mark becomes invalid.  For
+    * example, if <code>mark()</code> is called with a read limit of 10, then 
+    * when 11 chars of data are read from the stream before the 
+    * <code>reset()</code> method is called, then the mark is invalid and the 
+    * stream object instance is not required to remember the mark.
+    * <p>
+    * Note that the number of chars that can be remembered by this method
+    * can be greater than the size of the internal read buffer.  It is also
+    * not dependent on the subordinate stream supporting mark/reset
+    * functionality.
+    *
+    * @param readlimit The number of chars that can be read before the mark 
+    *        becomes invalid
+    *
+    * @exception IOException If an error occurs
+    */
   public void mark(int readLimit) throws IOException
   {
+    checkStatus();
     synchronized (lock)
       {
        // In this method we need to be aware of the special case where
@@ -116,8 +172,20 @@ public class BufferedReader extends Reader
       }
   }
 
+  /**
+    * Reset the stream to the point where the <code>mark()</code> method
+    * was called.  Any chars that were read after the mark point was set will
+    * be re-read during subsequent reads.
+    * <p>
+    * This method will throw an IOException if the number of chars read from
+    * the stream since the call to <code>mark()</code> exceeds the mark limit
+    * passed when establishing the mark.
+    *
+    * @exception IOException If an error occurs;
+    */
   public void reset() throws IOException
   {
+    checkStatus();
     synchronized (lock)
       {
        if (markPos < 0)
@@ -136,16 +204,45 @@ public class BufferedReader extends Reader
       }
   }
 
+  /**
+    * This method determines whether or not a stream is ready to be read.  If
+    * This method returns <code>false</code> then this stream could (but is
+    * not guaranteed to) block on the next read attempt.
+    *
+    * @return <code>true</code> if this stream is ready to be read, <code>false</code> otherwise
+    *
+    * @exception IOException If an error occurs
+    */
   public boolean ready() throws IOException
   {
+    checkStatus();
     synchronized (lock)
       {
        return pos < limit || in.ready();
       }
   }
 
+  /**
+    * This method read chars from a stream and stores them into a caller
+    * supplied buffer.  It starts storing the data at index <code>offset</code> into
+    * the buffer and attempts to read <code>len</code> chars.  This method can
+    * return before reading the number of chars requested.  The actual number
+    * of chars read is returned as an int.  A -1 is returned to indicate the
+    * end of the stream.
+    * <p>
+    * This method will block until some data can be read.
+    *
+    * @param buf The array into which the chars read should be stored
+    * @param offset The offset into the array to start storing chars
+    * @param count The requested number of chars to read
+    *
+    * @return The actual number of chars read, or -1 if end of stream.
+    *
+    * @exception IOException If an error occurs.
+    */
   public int read(char[] buf, int offset, int count) throws IOException
   {
+    checkStatus();
     synchronized (lock)
       {
        // Once again, we need to handle the special case of a readLine
@@ -202,6 +299,7 @@ public class BufferedReader extends Reader
      Return number of chars read (never 0), or -1 on eof. */
   private int fill() throws IOException
   {
+    checkStatus();
     // Handle the special case of a readLine that has a '\r' at the end of
     // the buffer.  In this case, we'll need to skip a '\n' if it is the
     // next char to be read.  This special case is indicated by 'pos > limit'.
@@ -228,9 +326,10 @@ public class BufferedReader extends Reader
 
     return count;
   }
-
+  
   public int read() throws IOException
   {
+    checkStatus();
     synchronized (lock)
       {
        if (pos >= limit && fill () <= 0)
@@ -255,8 +354,20 @@ public class BufferedReader extends Reader
     return i;
   }
 
+  /**
+    * This method reads a single line of text from the input stream, returning
+    * it as a <code>String</code>.  A line is terminated by "\n", a "\r", or
+    * an "\r\n" sequence.  The system dependent line separator is not used.
+    * The line termination characters are not returned in the resulting
+    * <code>String</code>.
+    * 
+    * @return The line of text read, or <code>null</code> if end of stream.
+    * 
+    * @exception IOException If an error occurs
+    */
   public String readLine() throws IOException
   {
+    checkStatus();
     // Handle the special case where a previous readLine (with no intervening
     // reads/skips) had a '\r' at the end of the buffer.
     // In this case, we'll need to skip a '\n' if it's the next char to be read.
@@ -317,8 +428,23 @@ public class BufferedReader extends Reader
     return (sbuf.length() == 0 && eof) ? null : sbuf.toString();
   }
 
+  /**
+    * This method skips the specified number of chars in the stream.  It
+    * returns the actual number of chars skipped, which may be less than the
+    * requested amount.
+    * <p>
+    * This method first discards chars in the buffer, then calls the
+    * <code>skip</code> method on the underlying stream to skip the remaining chars.
+    *
+    * @param num_chars The requested number of chars to skip
+    *
+    * @return The actual number of chars skipped.
+    *
+    * @exception IOException If an error occurs
+    */
   public long skip(long count) throws IOException
   {
+    checkStatus();
     if (count <= 0)
       return 0;
     synchronized (lock)
@@ -370,4 +496,10 @@ public class BufferedReader extends Reader
        return count - todo;
       }
   }
+  
+  private void checkStatus() throws IOException
+  {
+    if (in == null)
+      throw new IOException("Stream closed");
+  }  
 }
index edfa1f5..2bcf88d 100644 (file)
@@ -27,7 +27,6 @@ package java.io;
  * @author Aaron M. Renn (arenn@urbanophile.com)
  * @date October 20, 1998.  
  */
-
 public class DataInputStream extends FilterInputStream implements DataInput
 {
   // readLine() hack to ensure that an '\r' not followed by an '\n' is
@@ -61,7 +60,7 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final int read(byte[] b) throws IOException
   {
-    return super.read(b, 0, b.length);
+    return in.read(b, 0, b.length);
   }
 
   /**
@@ -82,10 +81,7 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final int read(byte[] b, int off, int len) throws IOException
   {
-    if (off < 0 || len < 0 || off + len > b.length)
-      throw new ArrayIndexOutOfBoundsException();
-
-    return super.read(b, off, len);
+    return in.read(b, off, len);
   }
 
   /**
@@ -106,7 +102,10 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final boolean readBoolean() throws IOException
   {
-    return (readByte() != 0);
+    int b = in.read();
+    if (b < 0)
+      throw new EOFException();    
+    return (b != 0);
   }
 
   /**
@@ -126,7 +125,7 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final byte readByte() throws IOException
   {
-    int i = read();
+    int i = in.read();
     if (i < 0)
       throw new EOFException();
 
@@ -160,7 +159,11 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final char readChar() throws IOException
   {
-    return (char) ((readByte() << 8) | readUnsignedByte());
+    int a = in.read();
+    int b = in.read();
+    if (b < 0)
+      throw new EOFException();
+    return (char) ((a << 8) | (b & 0xff));
   }
 
   /**
@@ -247,13 +250,10 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final void readFully(byte[] b, int off, int len) throws IOException
   {
-    if (off < 0 || len < 0 || off + len > b.length)
-      throw new ArrayIndexOutOfBoundsException();
-
     while (len > 0)
       {
-       // super.read will block until some data is available.
-       int numread = super.read(b, off, len);
+       // in.read will block until some data is available.
+       int numread = in.read(b, off, len);
        if (numread < 0)
          throw new EOFException();
        len -= numread;
@@ -290,11 +290,15 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final int readInt() throws IOException
   {
-    int retval = 0;
-    for (int i = 0; i < 4; i++)
-      retval |= readUnsignedByte() << (24 - i * 8);
-
-    return retval;
+    int a = in.read();
+    int b = in.read();
+    int c = in.read();
+    int d = in.read();
+    if (d < 0)
+      throw new EOFException();
+    
+    return (((a & 0xff) << 24) | ((b & 0xff) << 16) |
+           ((c & 0xff) << 8) | (d & 0xff));
   }
 
   /**
@@ -335,7 +339,7 @@ public class DataInputStream extends FilterInputStream implements DataInput
         while (getnext)
           {
            getnext = false;
-           c = read();
+           c = in.read();
            if (c < 0)  // got an EOF
              return strb.length() > 0 ? strb.toString() : null;
            ch = (char) c;
@@ -377,7 +381,7 @@ public class DataInputStream extends FilterInputStream implements DataInput
             char next_ch = ' ';
            if (in instanceof BufferedInputStream)
              {
-               next_c = read();
+               next_c = in.read();
                next_ch = (char) (next_c & 0xFF);
                if ((next_ch != '\n') && (next_c >= 0)) 
                  {
@@ -388,12 +392,12 @@ public class DataInputStream extends FilterInputStream implements DataInput
              }
            else if (markSupported())
              {
-               next_c = read();
+               next_c = in.read();
                next_ch = (char) (next_c & 0xFF);
                if ((next_ch != '\n') && (next_c >= 0)) 
                  {
                    mark(1);
-                   if ((read() & 0xFF) != '\n')
+                   if ((in.read() & 0xFF) != '\n')
                      reset();
                  }
              } 
@@ -441,11 +445,25 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final long readLong() throws IOException
   {
-    long retval = 0L;
-    for (int i = 0; i < 8; i++)
-      retval |= (long) readUnsignedByte() << (56 - i * 8);
-
-    return retval;
+    int a = in.read();
+    int b = in.read();
+    int c = in.read();
+    int d = in.read();
+    int e = in.read();
+    int f = in.read();
+    int g = in.read();
+    int h = in.read();
+    if (h < 0)
+      throw new EOFException();
+    
+    return (((long)(a & 0xff) << 56) |
+           ((long)(b & 0xff) << 48) |
+           ((long)(c & 0xff) << 40) |
+           ((long)(d & 0xff) << 32) |
+           ((long)(e & 0xff) << 24) |
+           ((long)(f & 0xff) << 16) |
+           ((long)(g & 0xff) <<  8) |
+           ((long)(h & 0xff)));
   }
 
   /**
@@ -477,7 +495,11 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final short readShort() throws IOException
   {
-    return (short) ((readByte() << 8) | readUnsignedByte());
+    int a = in.read();
+    int b = in.read();
+    if (b < 0)
+      throw new EOFException();
+    return (short) ((a << 8) | (b & 0xff));
   }
 
   /**
@@ -498,7 +520,7 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final int readUnsignedByte() throws IOException
   {
-    int i = read();
+    int i = in.read();
     if (i < 0)
       throw new EOFException();
 
@@ -532,7 +554,11 @@ public class DataInputStream extends FilterInputStream implements DataInput
    */
   public final int readUnsignedShort() throws IOException
   {
-    return (readUnsignedByte() << 8) | readUnsignedByte();
+    int a = in.read();
+    int b = in.read();
+    if (b < 0)
+      throw new EOFException();
+    return (((a & 0xff) << 8) | (b & 0xff));
   }
 
   /**
@@ -664,34 +690,29 @@ public class DataInputStream extends FilterInputStream implements DataInput
   /**
    * This method attempts to skip and discard the specified number of bytes 
    * in the input stream.  It may actually skip fewer bytes than requested. 
-   * The actual number of bytes skipped is returned.  This method will not
-   * skip any bytes if passed a negative number of bytes to skip.
+   * This method will not skip any bytes if passed a negative number of bytes 
+   * to skip. 
    *
    * @param n The requested number of bytes to skip.
-   *
-   * @return The number of bytes actually skipped.
-   *
+   * @return The requested number of bytes to skip.
    * @exception IOException If an error occurs.
+   * @specnote The JDK docs claim that this returns the number of bytes 
+   *  actually skipped. The JCL claims that this method can throw an 
+   *  EOFException. Neither of these appear to be true in the JDK 1.3's
+   *  implementation. This tries to implement the actual JDK behaviour.
    */
   public final int skipBytes(int n) throws IOException
   {
-    // The contract in the Java Lang. Spec. says that this never
-    // throws an EOFException and infers that it doesn't block (since
-    // it may skip less than the requested number of bytes).
-    // BUT, the JCL book specifically says that this method blocks
-    // and can throw an EOFException.  Finally, the Java 1.2 online
-    // doc simply refers to the general contract.  As such, we will
-    // stick to the contract and assume for now that the JCL book
-    // is incorrect.
-
-    // Since we're only skipping at most an int number of bytes, the cast
-    // of return value to an int is fine.
-    if (n > 0)
+    if (n <= 0)
+      return 0;    
+    try
       {
-       n = Math.min(n, available());
-        return (int) super.skip((long) n);
+        return (int) in.skip(n);
       }
-
-    return 0;
+    catch (EOFException x)
+      {
+        // do nothing.
+      }         
+    return n;
   }
 }