1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/io/BufferedReader.java Tue Feb 26 16:54:16 2013 +0100
1.3 @@ -0,0 +1,523 @@
1.4 +/*
1.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.io;
1.30 +
1.31 +
1.32 +
1.33 +/**
1.34 + * Reads text from a character-input stream, buffering characters so as to
1.35 + * provide for the efficient reading of characters, arrays, and lines.
1.36 + *
1.37 + * <p> The buffer size may be specified, or the default size may be used. The
1.38 + * default is large enough for most purposes.
1.39 + *
1.40 + * <p> In general, each read request made of a Reader causes a corresponding
1.41 + * read request to be made of the underlying character or byte stream. It is
1.42 + * therefore advisable to wrap a BufferedReader around any Reader whose read()
1.43 + * operations may be costly, such as FileReaders and InputStreamReaders. For
1.44 + * example,
1.45 + *
1.46 + * <pre>
1.47 + * BufferedReader in
1.48 + * = new BufferedReader(new FileReader("foo.in"));
1.49 + * </pre>
1.50 + *
1.51 + * will buffer the input from the specified file. Without buffering, each
1.52 + * invocation of read() or readLine() could cause bytes to be read from the
1.53 + * file, converted into characters, and then returned, which can be very
1.54 + * inefficient.
1.55 + *
1.56 + * <p> Programs that use DataInputStreams for textual input can be localized by
1.57 + * replacing each DataInputStream with an appropriate BufferedReader.
1.58 + *
1.59 + * @see FileReader
1.60 + * @see InputStreamReader
1.61 + * @see java.nio.file.Files#newBufferedReader
1.62 + *
1.63 + * @author Mark Reinhold
1.64 + * @since JDK1.1
1.65 + */
1.66 +
1.67 +public class BufferedReader extends Reader {
1.68 +
1.69 + private Reader in;
1.70 +
1.71 + private char cb[];
1.72 + private int nChars, nextChar;
1.73 +
1.74 + private static final int INVALIDATED = -2;
1.75 + private static final int UNMARKED = -1;
1.76 + private int markedChar = UNMARKED;
1.77 + private int readAheadLimit = 0; /* Valid only when markedChar > 0 */
1.78 +
1.79 + /** If the next character is a line feed, skip it */
1.80 + private boolean skipLF = false;
1.81 +
1.82 + /** The skipLF flag when the mark was set */
1.83 + private boolean markedSkipLF = false;
1.84 +
1.85 + private static int defaultCharBufferSize = 8192;
1.86 + private static int defaultExpectedLineLength = 80;
1.87 +
1.88 + /**
1.89 + * Creates a buffering character-input stream that uses an input buffer of
1.90 + * the specified size.
1.91 + *
1.92 + * @param in A Reader
1.93 + * @param sz Input-buffer size
1.94 + *
1.95 + * @exception IllegalArgumentException If sz is <= 0
1.96 + */
1.97 + public BufferedReader(Reader in, int sz) {
1.98 + super(in);
1.99 + if (sz <= 0)
1.100 + throw new IllegalArgumentException("Buffer size <= 0");
1.101 + this.in = in;
1.102 + cb = new char[sz];
1.103 + nextChar = nChars = 0;
1.104 + }
1.105 +
1.106 + /**
1.107 + * Creates a buffering character-input stream that uses a default-sized
1.108 + * input buffer.
1.109 + *
1.110 + * @param in A Reader
1.111 + */
1.112 + public BufferedReader(Reader in) {
1.113 + this(in, defaultCharBufferSize);
1.114 + }
1.115 +
1.116 + /** Checks to make sure that the stream has not been closed */
1.117 + private void ensureOpen() throws IOException {
1.118 + if (in == null)
1.119 + throw new IOException("Stream closed");
1.120 + }
1.121 +
1.122 + /**
1.123 + * Fills the input buffer, taking the mark into account if it is valid.
1.124 + */
1.125 + private void fill() throws IOException {
1.126 + int dst;
1.127 + if (markedChar <= UNMARKED) {
1.128 + /* No mark */
1.129 + dst = 0;
1.130 + } else {
1.131 + /* Marked */
1.132 + int delta = nextChar - markedChar;
1.133 + if (delta >= readAheadLimit) {
1.134 + /* Gone past read-ahead limit: Invalidate mark */
1.135 + markedChar = INVALIDATED;
1.136 + readAheadLimit = 0;
1.137 + dst = 0;
1.138 + } else {
1.139 + if (readAheadLimit <= cb.length) {
1.140 + /* Shuffle in the current buffer */
1.141 + System.arraycopy(cb, markedChar, cb, 0, delta);
1.142 + markedChar = 0;
1.143 + dst = delta;
1.144 + } else {
1.145 + /* Reallocate buffer to accommodate read-ahead limit */
1.146 + char ncb[] = new char[readAheadLimit];
1.147 + System.arraycopy(cb, markedChar, ncb, 0, delta);
1.148 + cb = ncb;
1.149 + markedChar = 0;
1.150 + dst = delta;
1.151 + }
1.152 + nextChar = nChars = delta;
1.153 + }
1.154 + }
1.155 +
1.156 + int n;
1.157 + do {
1.158 + n = in.read(cb, dst, cb.length - dst);
1.159 + } while (n == 0);
1.160 + if (n > 0) {
1.161 + nChars = dst + n;
1.162 + nextChar = dst;
1.163 + }
1.164 + }
1.165 +
1.166 + /**
1.167 + * Reads a single character.
1.168 + *
1.169 + * @return The character read, as an integer in the range
1.170 + * 0 to 65535 (<tt>0x00-0xffff</tt>), or -1 if the
1.171 + * end of the stream has been reached
1.172 + * @exception IOException If an I/O error occurs
1.173 + */
1.174 + public int read() throws IOException {
1.175 + synchronized (lock) {
1.176 + ensureOpen();
1.177 + for (;;) {
1.178 + if (nextChar >= nChars) {
1.179 + fill();
1.180 + if (nextChar >= nChars)
1.181 + return -1;
1.182 + }
1.183 + if (skipLF) {
1.184 + skipLF = false;
1.185 + if (cb[nextChar] == '\n') {
1.186 + nextChar++;
1.187 + continue;
1.188 + }
1.189 + }
1.190 + return cb[nextChar++];
1.191 + }
1.192 + }
1.193 + }
1.194 +
1.195 + /**
1.196 + * Reads characters into a portion of an array, reading from the underlying
1.197 + * stream if necessary.
1.198 + */
1.199 + private int read1(char[] cbuf, int off, int len) throws IOException {
1.200 + if (nextChar >= nChars) {
1.201 + /* If the requested length is at least as large as the buffer, and
1.202 + if there is no mark/reset activity, and if line feeds are not
1.203 + being skipped, do not bother to copy the characters into the
1.204 + local buffer. In this way buffered streams will cascade
1.205 + harmlessly. */
1.206 + if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {
1.207 + return in.read(cbuf, off, len);
1.208 + }
1.209 + fill();
1.210 + }
1.211 + if (nextChar >= nChars) return -1;
1.212 + if (skipLF) {
1.213 + skipLF = false;
1.214 + if (cb[nextChar] == '\n') {
1.215 + nextChar++;
1.216 + if (nextChar >= nChars)
1.217 + fill();
1.218 + if (nextChar >= nChars)
1.219 + return -1;
1.220 + }
1.221 + }
1.222 + int n = Math.min(len, nChars - nextChar);
1.223 + System.arraycopy(cb, nextChar, cbuf, off, n);
1.224 + nextChar += n;
1.225 + return n;
1.226 + }
1.227 +
1.228 + /**
1.229 + * Reads characters into a portion of an array.
1.230 + *
1.231 + * <p> This method implements the general contract of the corresponding
1.232 + * <code>{@link Reader#read(char[], int, int) read}</code> method of the
1.233 + * <code>{@link Reader}</code> class. As an additional convenience, it
1.234 + * attempts to read as many characters as possible by repeatedly invoking
1.235 + * the <code>read</code> method of the underlying stream. This iterated
1.236 + * <code>read</code> continues until one of the following conditions becomes
1.237 + * true: <ul>
1.238 + *
1.239 + * <li> The specified number of characters have been read,
1.240 + *
1.241 + * <li> The <code>read</code> method of the underlying stream returns
1.242 + * <code>-1</code>, indicating end-of-file, or
1.243 + *
1.244 + * <li> The <code>ready</code> method of the underlying stream
1.245 + * returns <code>false</code>, indicating that further input requests
1.246 + * would block.
1.247 + *
1.248 + * </ul> If the first <code>read</code> on the underlying stream returns
1.249 + * <code>-1</code> to indicate end-of-file then this method returns
1.250 + * <code>-1</code>. Otherwise this method returns the number of characters
1.251 + * actually read.
1.252 + *
1.253 + * <p> Subclasses of this class are encouraged, but not required, to
1.254 + * attempt to read as many characters as possible in the same fashion.
1.255 + *
1.256 + * <p> Ordinarily this method takes characters from this stream's character
1.257 + * buffer, filling it from the underlying stream as necessary. If,
1.258 + * however, the buffer is empty, the mark is not valid, and the requested
1.259 + * length is at least as large as the buffer, then this method will read
1.260 + * characters directly from the underlying stream into the given array.
1.261 + * Thus redundant <code>BufferedReader</code>s will not copy data
1.262 + * unnecessarily.
1.263 + *
1.264 + * @param cbuf Destination buffer
1.265 + * @param off Offset at which to start storing characters
1.266 + * @param len Maximum number of characters to read
1.267 + *
1.268 + * @return The number of characters read, or -1 if the end of the
1.269 + * stream has been reached
1.270 + *
1.271 + * @exception IOException If an I/O error occurs
1.272 + */
1.273 + public int read(char cbuf[], int off, int len) throws IOException {
1.274 + synchronized (lock) {
1.275 + ensureOpen();
1.276 + if ((off < 0) || (off > cbuf.length) || (len < 0) ||
1.277 + ((off + len) > cbuf.length) || ((off + len) < 0)) {
1.278 + throw new IndexOutOfBoundsException();
1.279 + } else if (len == 0) {
1.280 + return 0;
1.281 + }
1.282 +
1.283 + int n = read1(cbuf, off, len);
1.284 + if (n <= 0) return n;
1.285 + while ((n < len) && in.ready()) {
1.286 + int n1 = read1(cbuf, off + n, len - n);
1.287 + if (n1 <= 0) break;
1.288 + n += n1;
1.289 + }
1.290 + return n;
1.291 + }
1.292 + }
1.293 +
1.294 + /**
1.295 + * Reads a line of text. A line is considered to be terminated by any one
1.296 + * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
1.297 + * followed immediately by a linefeed.
1.298 + *
1.299 + * @param ignoreLF If true, the next '\n' will be skipped
1.300 + *
1.301 + * @return A String containing the contents of the line, not including
1.302 + * any line-termination characters, or null if the end of the
1.303 + * stream has been reached
1.304 + *
1.305 + * @see java.io.LineNumberReader#readLine()
1.306 + *
1.307 + * @exception IOException If an I/O error occurs
1.308 + */
1.309 + String readLine(boolean ignoreLF) throws IOException {
1.310 + StringBuffer s = null;
1.311 + int startChar;
1.312 +
1.313 + synchronized (lock) {
1.314 + ensureOpen();
1.315 + boolean omitLF = ignoreLF || skipLF;
1.316 +
1.317 + bufferLoop:
1.318 + for (;;) {
1.319 +
1.320 + if (nextChar >= nChars)
1.321 + fill();
1.322 + if (nextChar >= nChars) { /* EOF */
1.323 + if (s != null && s.length() > 0)
1.324 + return s.toString();
1.325 + else
1.326 + return null;
1.327 + }
1.328 + boolean eol = false;
1.329 + char c = 0;
1.330 + int i;
1.331 +
1.332 + /* Skip a leftover '\n', if necessary */
1.333 + if (omitLF && (cb[nextChar] == '\n'))
1.334 + nextChar++;
1.335 + skipLF = false;
1.336 + omitLF = false;
1.337 +
1.338 + charLoop:
1.339 + for (i = nextChar; i < nChars; i++) {
1.340 + c = cb[i];
1.341 + if ((c == '\n') || (c == '\r')) {
1.342 + eol = true;
1.343 + break charLoop;
1.344 + }
1.345 + }
1.346 +
1.347 + startChar = nextChar;
1.348 + nextChar = i;
1.349 +
1.350 + if (eol) {
1.351 + String str;
1.352 + if (s == null) {
1.353 + str = new String(cb, startChar, i - startChar);
1.354 + } else {
1.355 + s.append(cb, startChar, i - startChar);
1.356 + str = s.toString();
1.357 + }
1.358 + nextChar++;
1.359 + if (c == '\r') {
1.360 + skipLF = true;
1.361 + }
1.362 + return str;
1.363 + }
1.364 +
1.365 + if (s == null)
1.366 + s = new StringBuffer(defaultExpectedLineLength);
1.367 + s.append(cb, startChar, i - startChar);
1.368 + }
1.369 + }
1.370 + }
1.371 +
1.372 + /**
1.373 + * Reads a line of text. A line is considered to be terminated by any one
1.374 + * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
1.375 + * followed immediately by a linefeed.
1.376 + *
1.377 + * @return A String containing the contents of the line, not including
1.378 + * any line-termination characters, or null if the end of the
1.379 + * stream has been reached
1.380 + *
1.381 + * @exception IOException If an I/O error occurs
1.382 + *
1.383 + * @see java.nio.file.Files#readAllLines
1.384 + */
1.385 + public String readLine() throws IOException {
1.386 + return readLine(false);
1.387 + }
1.388 +
1.389 + /**
1.390 + * Skips characters.
1.391 + *
1.392 + * @param n The number of characters to skip
1.393 + *
1.394 + * @return The number of characters actually skipped
1.395 + *
1.396 + * @exception IllegalArgumentException If <code>n</code> is negative.
1.397 + * @exception IOException If an I/O error occurs
1.398 + */
1.399 + public long skip(long n) throws IOException {
1.400 + if (n < 0L) {
1.401 + throw new IllegalArgumentException("skip value is negative");
1.402 + }
1.403 + synchronized (lock) {
1.404 + ensureOpen();
1.405 + long r = n;
1.406 + while (r > 0) {
1.407 + if (nextChar >= nChars)
1.408 + fill();
1.409 + if (nextChar >= nChars) /* EOF */
1.410 + break;
1.411 + if (skipLF) {
1.412 + skipLF = false;
1.413 + if (cb[nextChar] == '\n') {
1.414 + nextChar++;
1.415 + }
1.416 + }
1.417 + long d = nChars - nextChar;
1.418 + if (r <= d) {
1.419 + nextChar += r;
1.420 + r = 0;
1.421 + break;
1.422 + }
1.423 + else {
1.424 + r -= d;
1.425 + nextChar = nChars;
1.426 + }
1.427 + }
1.428 + return n - r;
1.429 + }
1.430 + }
1.431 +
1.432 + /**
1.433 + * Tells whether this stream is ready to be read. A buffered character
1.434 + * stream is ready if the buffer is not empty, or if the underlying
1.435 + * character stream is ready.
1.436 + *
1.437 + * @exception IOException If an I/O error occurs
1.438 + */
1.439 + public boolean ready() throws IOException {
1.440 + synchronized (lock) {
1.441 + ensureOpen();
1.442 +
1.443 + /*
1.444 + * If newline needs to be skipped and the next char to be read
1.445 + * is a newline character, then just skip it right away.
1.446 + */
1.447 + if (skipLF) {
1.448 + /* Note that in.ready() will return true if and only if the next
1.449 + * read on the stream will not block.
1.450 + */
1.451 + if (nextChar >= nChars && in.ready()) {
1.452 + fill();
1.453 + }
1.454 + if (nextChar < nChars) {
1.455 + if (cb[nextChar] == '\n')
1.456 + nextChar++;
1.457 + skipLF = false;
1.458 + }
1.459 + }
1.460 + return (nextChar < nChars) || in.ready();
1.461 + }
1.462 + }
1.463 +
1.464 + /**
1.465 + * Tells whether this stream supports the mark() operation, which it does.
1.466 + */
1.467 + public boolean markSupported() {
1.468 + return true;
1.469 + }
1.470 +
1.471 + /**
1.472 + * Marks the present position in the stream. Subsequent calls to reset()
1.473 + * will attempt to reposition the stream to this point.
1.474 + *
1.475 + * @param readAheadLimit Limit on the number of characters that may be
1.476 + * read while still preserving the mark. An attempt
1.477 + * to reset the stream after reading characters
1.478 + * up to this limit or beyond may fail.
1.479 + * A limit value larger than the size of the input
1.480 + * buffer will cause a new buffer to be allocated
1.481 + * whose size is no smaller than limit.
1.482 + * Therefore large values should be used with care.
1.483 + *
1.484 + * @exception IllegalArgumentException If readAheadLimit is < 0
1.485 + * @exception IOException If an I/O error occurs
1.486 + */
1.487 + public void mark(int readAheadLimit) throws IOException {
1.488 + if (readAheadLimit < 0) {
1.489 + throw new IllegalArgumentException("Read-ahead limit < 0");
1.490 + }
1.491 + synchronized (lock) {
1.492 + ensureOpen();
1.493 + this.readAheadLimit = readAheadLimit;
1.494 + markedChar = nextChar;
1.495 + markedSkipLF = skipLF;
1.496 + }
1.497 + }
1.498 +
1.499 + /**
1.500 + * Resets the stream to the most recent mark.
1.501 + *
1.502 + * @exception IOException If the stream has never been marked,
1.503 + * or if the mark has been invalidated
1.504 + */
1.505 + public void reset() throws IOException {
1.506 + synchronized (lock) {
1.507 + ensureOpen();
1.508 + if (markedChar < 0)
1.509 + throw new IOException((markedChar == INVALIDATED)
1.510 + ? "Mark invalid"
1.511 + : "Stream not marked");
1.512 + nextChar = markedChar;
1.513 + skipLF = markedSkipLF;
1.514 + }
1.515 + }
1.516 +
1.517 + public void close() throws IOException {
1.518 + synchronized (lock) {
1.519 + if (in == null)
1.520 + return;
1.521 + in.close();
1.522 + in = null;
1.523 + cb = null;
1.524 + }
1.525 + }
1.526 +}