// 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 */