/* DataInput.java -- Interface for reading data from a stream
   Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.io;

/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * "The Java Language Specification", ISBN 0-201-63451-1
 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.  
 * Status:  Believed complete and correct.  */

/**
 * This interface is implemented by classes that can data from streams 
 * into Java primitive types. 
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Warren Levy <warrenl@cygnus.com>
 */
public interface DataInput
{

  /**
   * This method reads a Java boolean value from an input stream.  It does
   * so by reading a single byte of data.  If that byte is zero, then the
   * value returned is <code>false</code>.  If the byte is non-zero, then
   * the value returned is <code>true</code>.
   * <p>
   * This method can read a <code>boolean</code> written by an object
   * implementing the <code>writeBoolean()</code> method in the
   * <code>DataOutput</code> interface.
   *
   * @return The <code>boolean</code> value read
   *
   * @exception EOFException If end of file is reached before 
   * reading the boolean
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeBoolean
   */
  boolean readBoolean() throws EOFException, IOException;

  /**
   * This method reads a Java byte value from an input stream.  The value
   * is in the range of -128 to 127.
   * <p>
   * This method can read a <code>byte</code> written by an object
   * implementing the 
   * <code>writeByte()</code> method in the <code>DataOutput</code> interface.
   * <p>
   * @return The <code>byte</code> value read
   *
   * @exception EOFException If end of file is reached before reading the byte
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeByte
   */
  byte readByte() throws EOFException, IOException;

  /**
   * This method reads 8 unsigned bits into a Java <code>int</code> value from
   * the stream. The value returned is in the range of 0 to 255.
   * <p>
   * This method can read an unsigned byte written by an object 
   * implementing the
   * <code>writeByte()</code> method in the <code>DataOutput</code>
   * interface.
   *
   * @return The unsigned bytes value read as a Java <code>int</code>.
   *
   * @exception EOFException If end of file is reached before reading the value
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeByte
   */
  int readUnsignedByte() throws EOFException, IOException;

  /**
   * This method reads a Java <code>char</code> value from an input stream.  
   * It operates by reading two bytes from the stream and converting them to 
   * a single 16-bit Java <code>char</code>.  The two bytes are stored most
   * significant byte first (i.e., "big endian") regardless of the native
   * host byte ordering. 
   * <p>
   * As an example, if <code>byte1</code> and <code>byte2</code> represent the
   * first and second byte read from the stream respectively, they will be
   * transformed to a <code>char</code> in the following manner:
   * <p>
   * <code>(char)((byte1 << 8) + byte2)</code>
   * <p>
   * This method can read a <code>char</code> written by an object implementing
   * the
   * <code>writeChar()</code> method in the <code>DataOutput</code> interface.
   *
   * @return The <code>char</code> value read 
   *
   * @exception EOFException If end of file is reached before reading the char
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeChar
   */
  char readChar() throws EOFException, IOException;

  /**
   * This method reads a signed 16-bit value into a Java in from the stream.
   * It operates by reading two bytes from the stream and converting them to 
   * a single 16-bit Java <code>short</code>.  The two bytes are stored most
   * significant byte first (i.e., "big endian") regardless of the native
   * host byte ordering. 
   * <p>
   * As an example, if <code>byte1</code> and <code>byte2</code> represent the
   * first and second byte read from the stream respectively, they will be
   * transformed to a <code>short</code> in the following manner:
   * <p>
   * <code>(short)(((byte1 & 0xFF) << 8) + (byte2 & 0xFF))</code>
   * <p>
   * The value returned is in the range of -32768 to 32767.
   * <p>
   * This method can read a <code>short</code> written by an object 
   * implementing
   * the <code>writeShort()</code> method in the <code>DataOutput</code>
   * interface.
   *
   * @return The <code>short</code> value read
   *
   * @exception EOFException If end of file is reached before reading the value
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeShort
   */
  short readShort() throws EOFException, IOException;

  /**
   * This method reads 16 unsigned bits into a Java int value from the stream.
   * It operates by reading two bytes from the stream and converting them to 
   * a single Java <code>int</code>.  The two bytes are stored most
   * significant byte first (i.e., "big endian") regardless of the native
   * host byte ordering. 
   * <p>
   * As an example, if <code>byte1</code> and <code>byte2</code> represent the
   * first and second byte read from the stream respectively, they will be
   * transformed to an <code>int</code> in the following manner:
   * <p>
   * <code>(int)(((byte1 0xFF) << 8) + (byte2 & 0xFF))</code>
   * <p>
   * The value returned is in the range of 0 to 65535.
   * <p>
   * This method can read an unsigned short written by an object implementing
   * the <code>writeShort()</code> method in the 
   * <code>DataOutput</code>
   * interface.
   *
   * @return The unsigned short value read as a Java <code>int</code>.
   *
   * @exception EOFException If end of file is reached before reading 
   * the value
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeShort
   */
  int readUnsignedShort() throws EOFException, IOException;

  /**
   * This method reads a Java <code>int</code> value from an input stream
   * It operates by reading four bytes from the stream and converting them to 
   * a single Java <code>int</code>.  The bytes are stored most
   * significant byte first (i.e., "big endian") regardless of the native
   * host byte ordering. 
   * <p>
   * As an example, if <code>byte1</code> through <code>byte4</code> represent
   * the first four bytes read from the stream, they will be
   * transformed to an <code>int</code> in the following manner:
   * <p>
   * <code>(int)(((byte1 & 0xFF) << 24) + ((byte2 & 0xFF) << 16) + 
   * ((byte3 & 0xFF)<< 8) + (byte4 & 0xFF)))</code>
   * <p>
   * The value returned is in the range of -2147483648 to 2147483647.
   * <p>
   * This method can read an <code>int</code> written by an object 
   * implementing the <code>writeInt()</code> method in the 
   * <code>DataOutput</code> interface.
   *
   * @return The <code>int</code> value read
   *
   * @exception EOFException If end of file is reached before reading the int
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeInt
   */
  int readInt() throws EOFException, IOException;

  /**
   * This method reads a Java <code>long</code> value from an input stream
   * It operates by reading eight bytes from the stream and converting them to 
   * a single Java <code>long</code>.  The bytes are stored most
   * significant byte first (i.e., "big endian") regardless of the native
   * host byte ordering. 
   * <p>
   * As an example, if <code>byte1</code> through <code>byte8</code> represent
   * the first eight bytes read from the stream, they will be
   * transformed to an <code>long</code> in the following manner:
   * <p>
   * <code>(long)(((byte1 & 0xFF) << 56) + ((byte2 & 0xFF) << 48) + 
   * ((byte3 & 0xFF) << 40) + ((byte4 & 0xFF) << 32) + 
   * ((byte5 & 0xFF) << 24) + ((byte6 & 0xFF) << 16) + 
   * ((byte7 & 0xFF) << 8) + (byte8 & 0xFF)))
   * </code>
   * <p>
   * The value returned is in the range of -9223372036854775808 to
   * 9223372036854775807.
   * <p>
   * This method can read an <code>long</code> written by an object 
   * implementing the <code>writeLong()</code> method in the 
   * <code>DataOutput</code> interface.
   *
   * @return The <code>long</code> value read
   *
   * @exception EOFException If end of file is reached before reading the long
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeLong
   */
  long readLong() throws EOFException, IOException;

  /**
   * This method reads a Java float value from an input stream.  It operates
   * by first reading an <code>int</code> value from the stream by calling the
   * <code>readInt()</code> method in this interface, then converts that
   * <code>int</code> to a <code>float</code> using the
   * <code>intBitsToFloat</code> method in the class
   * <code>java.lang.Float</code>.
   * <p>
   * This method can read a <code>float</code> written by an object 
   * implementing
   * the <code>writeFloat()</code> method in the <code>DataOutput</code>
   * interface.
   *
   * @return The <code>float</code> value read
   *
   * @exception EOFException If end of file is reached before reading the 
   * float
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeFloat
   * @see java.lang.Float#intBitsToFloat
   */
  float readFloat() throws EOFException, IOException;

  /**
   * This method reads a Java double value from an input stream.  It operates
   * by first reading a <code>long</code> value from the stream by calling the
   * <code>readLong()</code> method in this interface, then converts that
   * <code>long</code> to a <code>double</code> using the
   * <code>longBitsToDouble</code> method in the class
   * <code>java.lang.Double</code>.
   * <p>
   * This method can read a <code>double</code> written by an object
   * implementing the <code>writeDouble()</code> method in the
   * <code>DataOutput</code> interface.
   *
   * @return The <code>double</code> value read
   *
   * @exception EOFException If end of file is reached before reading the 
   * double
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeDouble
   * @see java.lang.Double#longBitsToDouble
   */
  double readDouble() throws EOFException, IOException;

  /**
   * This method reads the next line of text data from an input stream.
   * It operates by reading bytes and converting those bytes to 
   * <code>char</code>
   * values by treating the byte read as the low eight bits of the
   * <code>char</code> and using 0 as the high eight bits.  Because of this,
   * it does not support the full 16-bit Unicode character set.
   * <P>
   * The reading of bytes ends when either the end of file or a line terminator
   * is encountered.  The bytes read are then returned as a 
   * <code>String</code>.
   * A line terminator is a byte sequence consisting of either 
   * <code>\r</code>, <code>\n</code> or <code>\r\n</code>.  These termination
   * charaters are discarded and are not returned as part of the string.
   * A line is also terminated by an end of file condition.
   * <p>
   *
   * @return The line read as a <code>String</code>
   *
   * @exception IOException If an error occurs
   */
  String readLine() throws IOException;

  /**
   * This method reads a <code>String</code> from an input stream that is
   * encoded in a modified UTF-8 format.  This format has a leading two byte
   * sequence that contains the remaining number of bytes to read.  
   * This two byte
   * sequence is read using the <code>readUnsignedShort()</code> method of this
   * interface.
   *
   * After the number of remaining bytes have been determined, these bytes
   * are read an transformed into <code>char</code> values.  These
   * <code>char</code> values are encoded in the stream using either a one, 
   * two, or three byte format.
   * The particular format in use can be determined by examining the first
   * byte read.  
   * <p>
   * If the first byte has a high order bit of 0, then
   * that character consists on only one byte.  This character value consists
   * of seven bits that are at positions 0 through 6 of the byte.  As an
   * example, if <code>byte1</code> is the byte read from the stream, it would
   * be converted to a <code>char</code> like so:
   * <p>
   * <code>(char)byte1</code>
   * <p>
   * If the first byte has 110 as its high order bits, then the 
   * character consists of two bytes.  The bits that make up the character
   * value are in positions 0 through 4 of the first byte and bit positions
   * 0 through 5 of the second byte.  (The second byte should have 
   * 10 as its high order bits).  These values are in most significant
   * byte first (i.e., "big endian") order.
   * <p>
   * As an example, if <code>byte1</code> and <code>byte2</code> are the first
   * two bytes read respectively, and the high order bits of them match the
   * patterns which indicate a two byte character encoding, then they would be
   * converted to a Java <code>char</code> like so:
   * <p>
   * <code>(char)(((byte1 & 0x1F) << 6) + (byte2 & 0x3F))</code>
   * <p>
   * If the first byte has a 1110 as its high order bits, then the
   * character consists of three bytes.  The bits that make up the character
   * value are in positions 0 through 3 of the first byte and bit positions
   * 0 through 5 of the other two bytes.  (The second and third bytes should
   * have 10 as their high order bits).  These values are in most
   * significant byte first (i.e., "big endian") order.
   * <p>
   * As an example, if <code>byte1</code>, <code>byte2</code>, and
   * <code>byte3</code> are the three bytes read, and the high order bits of
   * them match the patterns which indicate a three byte character encoding,
   * then they would be converted to a Java <code>char</code> like so:
   *
   * <code>
   * (char)(((byte1 & 0x0F) << 12) + ((byte2 & 0x3F) + (byte3 & 0x3F))
   * </code>
   *
   * Note that all characters are encoded in the method that requires the
   * fewest number of bytes with the exception of the character with the
   * value of <code>\<llll>u0000</code> which is encoded as two bytes.  
   * This is a modification of the UTF standard used to prevent C language 
   * style <code>NUL</code> values from appearing in the byte stream.
   * <p>
   * This method can read data that was written by an object implementing the
   * <code>writeUTF()</code> method in <code>DataOutput</code>.
   * 
   * @returns The <code>String</code> read
   *
   * @exception EOFException If end of file is reached before reading the 
   * String
   * @exception UTFDataFormatException If the data is not in UTF-8 format
   * @exception IOException If any other error occurs
   *
   * @see DataOutput#writeUTF
   */
  String readUTF() throws EOFException, UTFDataFormatException, IOException;

  /**
   * This method reads raw bytes into the passed array until the array is
   * full.  Note that this method blocks until the data is available and
   * throws an exception if there is not enough data left in the stream to
   * fill the buffer.  Note also that zero length buffers are permitted.
   * In this case, the method will return immediately without reading any
   * bytes from the stream.
   *
   * @param buf The buffer into which to read the data
   *
   * @exception EOFException If end of file is reached before filling the 
   * buffer
   * @exception IOException If any other error occurs
   */
  void readFully(byte[] buf) throws EOFException, IOException;

  /**
   * This method reads raw bytes into the passed array <code>buf</code> 
   * starting
   * <code>offset</code> bytes into the buffer.  The number of bytes read 
   * will be
   * exactly <code>len</code>.  Note that this method blocks until the data is 
   * available and throws an exception if there is not enough data left in 
   * the stream to read <code>len</code> bytes.  Note also that zero length
   * buffers are permitted.  In this case, the method will return immediately
   * without reading any bytes from the stream.
   *
   * @param buf The buffer into which to read the data
   * @param offset The offset into the buffer to start storing data
   * @param len The number of bytes to read into the buffer
   *
   * @exception EOFException If end of file is reached before filling the 
   * buffer
   * @exception IOException If any other error occurs
   */
  void readFully(byte[] buf, int offset, int len) 
    throws EOFException, IOException;

  /**
   * This method skips and discards the specified number of bytes in an
   * input stream.  Note that this method may skip less than the requested
   * number of bytes.  The actual number of bytes skipped is returned.
   * No bytes are skipped if a negative number is passed to this method.
   *
   * @param numBytes The number of bytes to skip
   *
   * @return The number of bytes actually skipped, which will always be
   *         <code>numBytes</code>
   *
   * @exception EOFException If end of file is reached before all bytes can be
   *                         skipped
   * @exception IOException If any other error occurs
   */
  int skipBytes(int numBytes) throws EOFException, IOException;

} // interface DataInput
