1ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko/* 2ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Copyright (C) 2012 The Android Open Source Project 3ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 4ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * you may not use this file except in compliance with the License. 6ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * You may obtain a copy of the License at 7ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 8ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 10ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Unless required by applicable law or agreed to in writing, software 11ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * See the License for the specific language governing permissions and 14ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * limitations under the License. 15ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 16ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 17ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markopackage libcore.io; 18ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 19ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markoimport java.io.ByteArrayOutputStream; 20ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markoimport java.io.Closeable; 21ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markoimport java.io.EOFException; 22ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markoimport java.io.InputStream; 23ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markoimport java.io.IOException; 24ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markoimport java.nio.charset.Charset; 252a6f23ff8690ac2f025588a360547ce96cde0943Elliott Hughesimport java.nio.charset.StandardCharsets; 26ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 27ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko/** 28ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Buffers input from an {@link InputStream} for reading lines. 29ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 30ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * This class is used for buffered reading of lines. For purposes of this class, a line ends with 31ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated line at 32ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * end of input is invalid and will be ignored, the caller may use {@code hasUnterminatedLine()} 33ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * to detect it after catching the {@code EOFException}. 34ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 35ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * This class is intended for reading input that strictly consists of lines, such as line-based 36ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * cache entries or cache journal. Unlike the {@link BufferedReader} which in conjunction with 37ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * {@link InputStreamReader} provides similar functionality, this class uses different 38ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * end-of-input reporting and a more restrictive definition of a line. 39ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 40ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * This class supports only charsets that encode '\r' and '\n' as a single byte with value 13 41ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * and 10, respectively, and the representation of no other character contains these values. 42ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1. 43ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * The default charset is US_ASCII. 44ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 45ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Markopublic class StrictLineReader implements Closeable { 46ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private static final byte CR = (byte)'\r'; 47ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private static final byte LF = (byte)'\n'; 48ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 49ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private final InputStream in; 50ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private final Charset charset; 51ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 52ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /* 53ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end 54ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * and the data in the range [pos, end) is buffered for reading. At end of input, if there is 55ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * an unterminated line, we set end == -1, otherwise end == pos. If the underlying 56ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1. 57ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 58ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private byte[] buf; 59ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private int pos; 60ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private int end; 61ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 62ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 63ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Constructs a new {@code StrictLineReader} with the default capacity and charset. 64ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 65ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param in the {@code InputStream} to read data from. 66ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws NullPointerException if {@code in} is null. 67ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 68ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public StrictLineReader(InputStream in) { 69ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko this(in, 8192); 70ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 71ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 72ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 73ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Constructs a new {@code LineReader} with the specified capacity and the default charset. 74ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 75ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param in the {@code InputStream} to read data from. 76ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param capacity the capacity of the buffer. 77ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws NullPointerException if {@code in} is null. 78ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IllegalArgumentException for negative or zero {@code capacity}. 79ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 80ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public StrictLineReader(InputStream in, int capacity) { 812a6f23ff8690ac2f025588a360547ce96cde0943Elliott Hughes this(in, capacity, StandardCharsets.US_ASCII); 82ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 83ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 84ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 85ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Constructs a new {@code LineReader} with the specified charset and the default capacity. 86ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 87ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param in the {@code InputStream} to read data from. 88ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param charset the charset used to decode data. 89ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Only US-ASCII, UTF-8 and ISO-8859-1 is supported. 90ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws NullPointerException if {@code in} or {@code charset} is null. 91ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IllegalArgumentException if the specified charset is not supported. 92ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 93ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public StrictLineReader(InputStream in, Charset charset) { 94ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko this(in, 8192, charset); 95ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 96ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 97ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 98ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Constructs a new {@code LineReader} with the specified capacity and charset. 99ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 100ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param in the {@code InputStream} to read data from. 101ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param capacity the capacity of the buffer. 102ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @param charset the charset used to decode data. 103ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Only US-ASCII, UTF-8 and ISO-8859-1 is supported. 104ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws NullPointerException if {@code in} or {@code charset} is null. 105ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IllegalArgumentException if {@code capacity} is negative or zero 106ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * or the specified charset is not supported. 107ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 108ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public StrictLineReader(InputStream in, int capacity, Charset charset) { 10986acc043d3334651ee26c65467d78d6cefedd397Kenny Root if (in == null) { 11086acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("in == null"); 11186acc043d3334651ee26c65467d78d6cefedd397Kenny Root } else if (charset == null) { 11286acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("charset == null"); 113ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 114ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (capacity < 0) { 115ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko throw new IllegalArgumentException("capacity <= 0"); 116ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 1172a6f23ff8690ac2f025588a360547ce96cde0943Elliott Hughes if (!(charset.equals(StandardCharsets.US_ASCII) || charset.equals(StandardCharsets.UTF_8) || 1182a6f23ff8690ac2f025588a360547ce96cde0943Elliott Hughes charset.equals(StandardCharsets.ISO_8859_1))) { 119ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko throw new IllegalArgumentException("Unsupported encoding"); 120ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 121ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 122ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko this.in = in; 123ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko this.charset = charset; 124ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko buf = new byte[capacity]; 125ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 126ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 127ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 128ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Closes the reader by closing the underlying {@code InputStream} and 129ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * marking this reader as closed. 130ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 131ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IOException for errors when closing the underlying {@code InputStream}. 132ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 133ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko @Override 134ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public void close() throws IOException { 135ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko synchronized (in) { 136ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (buf != null) { 137ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko buf = null; 138ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko in.close(); 139ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 140ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 141ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 142ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 143ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 144ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"}, 145ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * this end of line marker is not included in the result. 146ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 147ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @return the next line from the input. 148ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IOException for underlying {@code InputStream} errors. 149ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws EOFException for the end of source stream. 150ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 151ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public String readLine() throws IOException { 152ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko synchronized (in) { 153ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (buf == null) { 154ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko throw new IOException("LineReader is closed"); 155ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 156ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 157ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // Read more data if we are at the end of the buffered data. 158ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // Though it's an error to read after an exception, we will let {@code fillBuf()} 159ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // throw again if that happens; thus we need to handle end == -1 as well as end == pos. 160ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (pos >= end) { 161ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko fillBuf(); 162ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 163ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // Try to find LF in the buffered data and return the line if successful. 164ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko for (int i = pos; i != end; ++i) { 165ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (buf[i] == LF) { 166ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i; 167ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko String res = new String(buf, pos, lineEnd - pos, charset); 168ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko pos = i + 1; 169ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko return res; 170ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 171ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 172ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 173ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // Let's anticipate up to 80 characters on top of those already read. 174ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) { 175ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko @Override 176ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public String toString() { 177ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count; 178ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko return new String(buf, 0, length, charset); 179ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 180ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko }; 181ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 182ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko while (true) { 183ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko out.write(buf, pos, end - pos); 184ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // Mark unterminated line in case fillBuf throws EOFException or IOException. 185ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko end = -1; 186ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko fillBuf(); 187ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko // Try to find LF in the buffered data and return the line if successful. 188ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko for (int i = pos; i != end; ++i) { 189ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (buf[i] == LF) { 190ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (i != pos) { 191ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko out.write(buf, pos, i - pos); 192ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 193ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko pos = i + 1; 194ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko return out.toString(); 195ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 196ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 197ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 198ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 199ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 200ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 201ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 202ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Read an {@code int} from a line containing its decimal representation. 203ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 204ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @return the value of the {@code int} from the next line. 205ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IOException for underlying {@code InputStream} errors or conversion error. 206ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws EOFException for the end of source stream. 207ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 208ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public int readInt() throws IOException { 209ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko String intString = readLine(); 210ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko try { 211ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko return Integer.parseInt(intString); 212ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } catch (NumberFormatException e) { 213ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko throw new IOException("expected an int but was \"" + intString + "\""); 214ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 215ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 216ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 217ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 218ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Check whether there was an unterminated line at end of input after the line reader reported 219ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * end-of-input with EOFException. The value is meaningless in any other situation. 220ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 221ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @return true if there was an unterminated line at end of input. 222ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 223ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko public boolean hasUnterminatedLine() { 224ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko return end == -1; 225ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 226ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko 227ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko /** 228ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * Reads new input data into the buffer. Call only with pos == end or end == -1, 229ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * depending on the desired outcome if the function throws. 230ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * 231ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws IOException for underlying {@code InputStream} errors. 232ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko * @throws EOFException for the end of source stream. 233ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko */ 234ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko private void fillBuf() throws IOException { 235ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko int result = in.read(buf, 0, buf.length); 236ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko if (result == -1) { 237ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko throw new EOFException(); 238ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 239ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko pos = 0; 240ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko end = result; 241ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko } 242ac665275e161fab8ecd4225e73e159a9edf10501Vladimir Marko} 243