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