// A stream for reading basic types from input.
// (c) 1998 McGraw-Hill
package structure;
import java.io.*;
/**
* A ReadStream provides reasonable access to the typewritten
* data on an input stream. Usually, a ReadStream is constructed
* with no parameters, causing the ReadStream to open access to
* System.in.
*
* The access methods allow one to read from the stream, much as is done
* with Pascal.
*
* @version $Id: ReadStream.java,v 2.1.1.1 1999/08/05 16:18:01 bailey Exp bailey $
* @author duane a. bailey
*/
public class ReadStream extends FilterInputStream
{
/**
* The underlying data stream.
*/
protected DataInputStream strm;
/**
* True iff we've seen the end-of-file
*/
protected boolean atEOF; // are we at the end-of-file
/**
* The buffer to hold pushback characters
*/
protected char buffer[]; // pushback buffer
/**
* The number of characters to be stored in buffer.
*/
protected int buffersize; // current size of pushback buffer
/**
*/
protected int buffertop; // top element of pushback stack
/**
* Whether or not accept the CR as part of previous newline.
*/
protected boolean absorbNL = false; // absorb NL if next (part of cr)
/**
* Construct an empty ReadStream, obtaining info from System.in.
*
*
* - Postcondition:
- constructs a pascal-like stream based on System.in
*
*/
public ReadStream()
// post: constructs a pascal-like stream based on System.in
{
this(System.in);
}
/**
* Construct a ReadStream based on pre-existing input stream.
*
*
* - Precondition:
- strm is a valid input stream.
*
- Postcondition:
- constructs a pascal-like stream based on strm
*
*
* @param strm The pre-existing input stream.
*/
public ReadStream(InputStream strm)
// pre: strm is a valid input stream
// post: constructs a pascal-like stream based on strm
{
// This stream filters input from a data input stream
// which filters input from strm
super(new DataInputStream(strm));
this.strm = (DataInputStream)in;
atEOF = false;
buffer = new char[8];
buffersize = 8;
buffertop = -1;
}
/**
* Determine if we've seen end-of-file.
*
*
* - Precondition:
- are we at the end-of-file?
*
*
* @return True if the next character to be read is EOF.
*/
public boolean eof()
// pre: are we at the end-of-file?
{
// have we already detected EOF?
if (atEOF) return true;
// check stream by attempting a read
peek();
return atEOF;
}
static private boolean isWhite(char c)
// post: returns true if char is whitespace
{
return Character.isWhitespace(c); /* JDK 1.1 */
}
/**
* Read (but don't consume) next char in stream.
*
* - Postcondition:
- returns next character in stream, without consuming it
*
*
* @return The next character to be read.
*/
public char peek()
// post: returns next character in stream, without consuming it
{
char c = readChar();
pushbackChar(c);
return c;
}
/**
* Return true if the next character to be read is an end-of-line mark.
*
*
* - Postcondition:
- returns true if next stream char is an eoln char
*
*
* @return True iff the next character is an end-of-line mark.
*/
public boolean eoln()
// post: returns true if next stream char is an eoln char
{
char c = peek();
return eof() || (c == '\n') || (c == '\r');
}
/**
* Read characters up to and including the end-of-line
* mark.
*
*
* - Postcondition:
- reads input stream until end-of-line (\r or \n)
*
*/
public void readln()
// post: reads input stream until end-of-line (\r or \n or \n\r)
{
readLine();
}
/**
* Consume all the white-space characters until EOF or
* other data.
*
*
* - Postcondition:
- input pointer is at EOF, or nonwhitespace char.
*
*/
public void skipWhite()
// post: input pointer is at EOF, or nonwhitespace char
{
char c;
for (c = readChar(); isWhite(c); c = readChar());
pushbackChar(c);
}
/**
* Skip white space and read in the next non-whitespace word
* as a string.
*
*
* - Postcondition:
- reads next word as a string
*
*
* @return The next word on the input.
*/
public String readString()
// post: reads next word as string
{
char buffer[] = new char[512];
char c = 0;
int count = 0;
skipWhite();
while (!eof())
{
c = readChar();
if (isWhite(c))
{
pushbackChar(c);
break;
}
buffer[count++] = c;
}
return new String(buffer,0,count);
}
private boolean acceptChar(char c)
// post: returns true if the next character is upper or lower c
{
char d = readChar();
if (Character.toLowerCase(c) ==
Character.toLowerCase(d)) return true;
pushbackChar(d);
return false;
}
private boolean acceptWord(String s)
// post: returns true if word in s in on input (consumed)
// or false
{
char c;
skipWhite();
for (int i = 0; i < s.length(); i++)
{
if (!acceptChar(s.charAt(i))) {
for (int j = i-1; j>= 0; j--) {
pushbackChar(s.charAt(j));
}
return false;
}
}
return true;
}
/**
* Read the next word "true" or "false" as a boolean.
*
*
* - Postcondition:
- returns next boolean value read from input
*
*
* @return The value true or false, depending on input.
*/
public boolean readBoolean()
// post: returns next boolean value read from input
{
if (acceptWord("true")) return true;
else if (!acceptWord("false")) Assert.fail("Boolean not found on input.");
return false;
}
/**
* Read next character, whitespace or not. Fail on eof.
*
*
* - Postcondition:
- returns next character, or 0 for eof
*
*
* @return The next character, or the value 0 indicating EOF.
*/
public char readChar()
// post: returns next character, or 0 for eof
{
char c = (char)0;
try {
if (atEOF) return (char)0;
if (buffertop >= 0) {
c = buffer[buffertop--];
} else {
c = (char)strm.readByte();
}
}
catch (EOFException e) {
atEOF = true;
}
catch (IOException e) {
Assert.fail("Input error free.");
}
finally {
if (absorbNL && (c == '\n')) {
absorbNL = false;
c = readChar();
}
absorbNL = c == '\r';
return c;
}
}
/**
* Return character to input stream for reading at later time.
*
*
* - Postcondition:
- pushes back character, possibly clearing EOF.
* if c == 0, does nothing
*
*
* @param c The character to push back onto input stream.
*/
public void pushbackChar(char c)
// post: pushes back character, possibly clearing EOF;
// if c == 0, does nothing
{
if (c == (char)0) return;
atEOF = false;
buffertop++;
if (buffertop == buffersize) {
// buffer too small, extend it.
char old[] = buffer;
buffersize = buffersize*2;
buffer = new char[buffersize];
for (int i = 0; i < buffertop; i++)
{
buffer[i] = old[i];
}
}
buffer[buffertop] = c;
absorbNL = false;
}
/**
* Reads the next double value from input stream.
* Whitespace is skipped beforehand.
* CURRENTLY NOT WORKING.
*
*
* - Postcondition:
- reads in double value
*
*
* @return The next double found on input.
*/
public double readDouble()
// post: reads in double value
{
StringBuffer sb = new StringBuffer();
char c;
skipWhite();
if (acceptChar('+')) sb.append('+');
else if (acceptChar('-')) sb.append('-');
c = readChar();
while (Character.isDigit(c))
{
sb.append(c);
c = readChar();
}
pushbackChar(c);
if (acceptChar('.')) {
sb.append('.');
c = readChar();
while (Character.isDigit(c))
{
sb.append(c);
c = readChar();
}
pushbackChar(c);
}
if (acceptChar('E'))
{
sb.append('E');
if (acceptChar('+')) sb.append('+');
else if (acceptChar('-')) sb.append('-');
c = readChar();
while (Character.isDigit(c))
{
sb.append(c);
c = readChar();
}
pushbackChar(c);
}
String s = sb.toString();
// System.out.println("["+s+"]");
return Double.valueOf(s).doubleValue();
}
/**
* Read floating point value from input
* (Currently not working).
* Skips whitespace before reading.
*
*
* - Postcondition:
- reads floating point value and returns value
*
*
* @return Next floating point number.
*/
public float readFloat()
// post: reads floating point value and returns value
{
return (float)readDouble();
}
/**
* Read an array of bytes from input.
*
* @param b The array of bytes; holds result.
*/
public void readFully(byte b[]) throws IOException
// post: reads an array of bytes from stream???
{
strm.readFully(b);
}
/**
* Read input into byte array.
*
* @param b Target array of bytes.
* @param off Offset into byte array to start reading.
* @param len Number of bytes to be read.
*/
public void readFully(byte b[], int off, int len)
throws IOException
// post: reads a portion of an array of bytes from stream
{
strm.readFully(b,off,len);
}
/**
* Reads an integer from input stream.
*
*
* - Postcondition:
- reads a short integer from stream
*
*
* @return The integer read form input.
*/
public short readShort()
// post: reads a short integer from stream
{
return (short)readLong();
}
/**
* Reads an integer from input stream.
*
*
* - Postcondition:
- reads an integer from stream
*
*
* @return The integer read form input.
*/
public int readInt()
// post: reads an integer from stream
{
return (int)readLong();
}
/**
* Read a (potentially long) input.
*
* - Postcondition:
- reads a long integer from stream
*
*
* @return The integer read from input.
*/
public long readLong()
// post: reads a long integer from stream
{
boolean negate = false;
int digitsRead = 0;
long value = 0;
int base = 10;
char c;
int d;
skipWhite();
if (eof()) return 0;
for (;;)
{
if (eof()) break;
c = readChar();
if (digitsRead == 0) {
if (c == '-') {
negate = true;
continue;
}
}
if ((digitsRead == 0) && (c == '0')) {
base = 8;
digitsRead++;
continue;
}
if ((digitsRead == 1) && (base == 8) && ((c == 'x') ||
(c == 'X'))) {
base = 16;
digitsRead++;
continue;
}
d = c - '0';
if ((c >= 'a') && (c <= 'f')) {
d = c - 'a' + 10;
} else if ((c >= 'A') && (c <= 'F')) {
d = c - 'A' + 10;
}
if ((d < 0) || (d >= base)) {
pushbackChar(c);
break;
}
digitsRead++;
value = value*base+d;
}
if (negate) value = -value;
return value;
}
/**
* Read the remainder of line, including end-of-line mark.
*
*
* - Postcondition:
- reads remainder of line, returns as string
*
*
* @return The string containing all the characters to end-of-line.
*/
public String readLine()
// post: reads remainder of line; returns as string
{
StringBuffer result = new StringBuffer();
char c;
while (!eoln())
{
result.append(readChar());
}
readChar();
return result.toString();
}
/**
* Read unicode from input.
*
* @return String version of UTF character.
*/
public String readUTF() throws IOException
// post: not supported. Avoid use.
{
return strm.readUTF();
}
}
/*
* $Log: ReadStream.java,v $
* Revision 2.1.1.1 1999/08/05 16:18:01 bailey
* Includes copyeditor comments.
*
* Revision 3.7 1999/08/05 15:31:12 bailey
* Copyeditor revisions for JavaElements
*
* Revision 3.6 1999/06/10 14:40:50 bailey
* Fixed problem with readln
* .,
*
* Revision 1.3 1999/01/08 16:06:08 bailey
* *** empty log message ***
*
* Revision 1.1 1998/09/25 13:20:19 bailey
* Initial revision
*
* Revision 3.4 1998/09/21 17:37:58 bailey
* Added interface comments.
*
* Revision 3.3 1998/02/02 16:29:16 bailey
* Working mods for PC's.
*
* Revision 2.5.1.1 1998/02/02 15:09:29 bailey
* Mods to beta version to work on PC's
*
* Revision 3.1 1998/02/02 14:35:26 bailey
* Updated to read eoln marks on PC's correctly.
*
* Revision 3.0 1998/01/12 16:03:23 bailey
* Initial JDK 1.2 version.
*
* Revision 2.5 1998/01/12 15:47:04 bailey
* Beta release.
*
* Revision 2.4 1998/01/06 17:55:15 bailey
* Updated copyright for McGraw-Hill
*
* Revision 2.3 1997/08/08 12:45:14 bailey
* Fix versioning problem.
*
* Revision 2.1 1997/08/07 21:11:35 bailey
* Preprint release.
*
* Revision 1.15 1997/08/02 12:24:30 bailey
* Weekly checkpoint
*
* Revision 1.14 1997/07/03 13:17:02 bailey
* Intermediate documentation release.
*
* Revision 1.13 1997/07/02 20:52:32 bailey
* Updated javadoc comments.
*
* Revision 1.12 1997/06/27 01:33:46 bailey
* (Re)added javadoc comments.
*
* Revision 1.11 1997/04/03 18:05:52 bailey
* Mods including toString, documentation, etc.
*
* Revision 1.10 1997/04/03 02:25:42 bailey
* Removed javadoc comments.
*
* Revision 1.9 1997/04/03 02:16:19 bailey
* *** empty log message ***
*
* Revision 1.8 1997/01/09 16:40:06 bailey
* *** empty log message ***
*
* Revision 1.7 1996/08/29 16:59:54 bailey
* Moved from cs136 to structure.
*
* Revision 1.6 1996/08/24 18:16:14 bailey
* *** empty log message ***
*
* Revision 1.5 1996/08/23 02:18:32 bailey
* Added automatically generated javadoc commenting.
*
* Revision 1.4 1996/08/02 12:15:09 bailey
* Added logging comments.
*
* Revision 1.3
* 1996/07/17 03:23:01 bailey
* Modified to accept System.in, and other InputStreams in constructor.
*
* Revision 1.2
* 1996/07/11 02:19:57 bailey
* *** empty log message ***
*
* Revision 1.1
* 1996/07/08 16:32:44 bailey
* Initial revision
*/