Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/io/LineNumberReader.java
38829 views
/*1* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.io;262728/**29* A buffered character-input stream that keeps track of line numbers. This30* class defines methods {@link #setLineNumber(int)} and {@link31* #getLineNumber()} for setting and getting the current line number32* respectively.33*34* <p> By default, line numbering begins at 0. This number increments at every35* <a href="#lt">line terminator</a> as the data is read, and can be changed36* with a call to <tt>setLineNumber(int)</tt>. Note however, that37* <tt>setLineNumber(int)</tt> does not actually change the current position in38* the stream; it only changes the value that will be returned by39* <tt>getLineNumber()</tt>.40*41* <p> A line is considered to be <a name="lt">terminated</a> by any one of a42* line feed ('\n'), a carriage return ('\r'), or a carriage return followed43* immediately by a linefeed.44*45* @author Mark Reinhold46* @since JDK1.147*/4849public class LineNumberReader extends BufferedReader {5051/** The current line number */52private int lineNumber = 0;5354/** The line number of the mark, if any */55private int markedLineNumber; // Defaults to 05657/** If the next character is a line feed, skip it */58private boolean skipLF;5960/** The skipLF flag when the mark was set */61private boolean markedSkipLF;6263/**64* Create a new line-numbering reader, using the default input-buffer65* size.66*67* @param in68* A Reader object to provide the underlying stream69*/70public LineNumberReader(Reader in) {71super(in);72}7374/**75* Create a new line-numbering reader, reading characters into a buffer of76* the given size.77*78* @param in79* A Reader object to provide the underlying stream80*81* @param sz82* An int specifying the size of the buffer83*/84public LineNumberReader(Reader in, int sz) {85super(in, sz);86}8788/**89* Set the current line number.90*91* @param lineNumber92* An int specifying the line number93*94* @see #getLineNumber95*/96public void setLineNumber(int lineNumber) {97this.lineNumber = lineNumber;98}99100/**101* Get the current line number.102*103* @return The current line number104*105* @see #setLineNumber106*/107public int getLineNumber() {108return lineNumber;109}110111/**112* Read a single character. <a href="#lt">Line terminators</a> are113* compressed into single newline ('\n') characters. Whenever a line114* terminator is read the current line number is incremented.115*116* @return The character read, or -1 if the end of the stream has been117* reached118*119* @throws IOException120* If an I/O error occurs121*/122@SuppressWarnings("fallthrough")123public int read() throws IOException {124synchronized (lock) {125int c = super.read();126if (skipLF) {127if (c == '\n')128c = super.read();129skipLF = false;130}131switch (c) {132case '\r':133skipLF = true;134case '\n': /* Fall through */135lineNumber++;136return '\n';137}138return c;139}140}141142/**143* Read characters into a portion of an array. Whenever a <a144* href="#lt">line terminator</a> is read the current line number is145* incremented.146*147* @param cbuf148* Destination buffer149*150* @param off151* Offset at which to start storing characters152*153* @param len154* Maximum number of characters to read155*156* @return The number of bytes read, or -1 if the end of the stream has157* already been reached158*159* @throws IOException160* If an I/O error occurs161*/162@SuppressWarnings("fallthrough")163public int read(char cbuf[], int off, int len) throws IOException {164synchronized (lock) {165int n = super.read(cbuf, off, len);166167for (int i = off; i < off + n; i++) {168int c = cbuf[i];169if (skipLF) {170skipLF = false;171if (c == '\n')172continue;173}174switch (c) {175case '\r':176skipLF = true;177case '\n': /* Fall through */178lineNumber++;179break;180}181}182183return n;184}185}186187/**188* Read a line of text. Whenever a <a href="#lt">line terminator</a> is189* read the current line number is incremented.190*191* @return A String containing the contents of the line, not including192* any <a href="#lt">line termination characters</a>, or193* <tt>null</tt> if the end of the stream has been reached194*195* @throws IOException196* If an I/O error occurs197*/198public String readLine() throws IOException {199synchronized (lock) {200String l = super.readLine(skipLF);201skipLF = false;202if (l != null)203lineNumber++;204return l;205}206}207208/** Maximum skip-buffer size */209private static final int maxSkipBufferSize = 8192;210211/** Skip buffer, null until allocated */212private char skipBuffer[] = null;213214/**215* Skip characters.216*217* @param n218* The number of characters to skip219*220* @return The number of characters actually skipped221*222* @throws IOException223* If an I/O error occurs224*225* @throws IllegalArgumentException226* If <tt>n</tt> is negative227*/228public long skip(long n) throws IOException {229if (n < 0)230throw new IllegalArgumentException("skip() value is negative");231int nn = (int) Math.min(n, maxSkipBufferSize);232synchronized (lock) {233if ((skipBuffer == null) || (skipBuffer.length < nn))234skipBuffer = new char[nn];235long r = n;236while (r > 0) {237int nc = read(skipBuffer, 0, (int) Math.min(r, nn));238if (nc == -1)239break;240r -= nc;241}242return n - r;243}244}245246/**247* Mark the present position in the stream. Subsequent calls to reset()248* will attempt to reposition the stream to this point, and will also reset249* the line number appropriately.250*251* @param readAheadLimit252* Limit on the number of characters that may be read while still253* preserving the mark. After reading this many characters,254* attempting to reset the stream may fail.255*256* @throws IOException257* If an I/O error occurs258*/259public void mark(int readAheadLimit) throws IOException {260synchronized (lock) {261// If the most recently read character is '\r', then increment the262// read ahead limit as in this case if the next character is '\n',263// two characters would actually be read by the next read().264if (skipLF)265readAheadLimit++;266super.mark(readAheadLimit);267markedLineNumber = lineNumber;268markedSkipLF = skipLF;269}270}271272/**273* Reset the stream to the most recent mark.274*275* @throws IOException276* If the stream has not been marked, or if the mark has been277* invalidated278*/279public void reset() throws IOException {280synchronized (lock) {281super.reset();282lineNumber = markedLineNumber;283skipLF = markedSkipLF;284}285}286287}288289290