1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays;
21a1603838fe9e865575c87982e32c6343740e464cElliott Hughes
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Wraps an existing {@link Reader} and <em>buffers</em> the input. Expensive
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * interaction with the underlying reader is minimized, since most (smaller)
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * requests can be satisfied by accessing the buffer alone. The drawback is that
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * some extra space is required to hold the buffer and that copying takes place
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * when filling that buffer, but this is usually outweighed by the performance
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * benefits.
29f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p/>A typical application pattern for the class looks like this:<p/>
31f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre>
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * BufferedReader buf = new BufferedReader(new FileReader(&quot;file.java&quot;));
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre>
35f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see BufferedWriter
37f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @since 1.1
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class BufferedReader extends Reader {
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Reader in;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
4382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    /**
4482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * The characters that can be read and refilled in bulk. We maintain three
4582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * indices into this buffer:<pre>
4682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *     { X X X X X X X X X X X X - - }
4782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *           ^     ^             ^
4882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *           |     |             |
4982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *         mark   pos           end</pre>
5082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * Pos points to the next readable character. End is one greater than the
5182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * last readable character. When {@code pos == end}, the buffer is empty and
5282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * must be {@link #fillBuf() filled} before characters can be read.
5382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *
5482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * <p>Mark is the value pos will be set to on calls to {@link #reset}. Its
5582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * value is in the range {@code [0...pos]}. If the mark is {@code -1}, the
5682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * buffer cannot be reset.
5782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *
5882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * <p>MarkLimit limits the distance between the mark and the pos. When this
5982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * limit is exceeded, {@link #reset} is permitted (but not required) to
6082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * throw an exception. For shorter distances, {@link #reset} shall not throw
6182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * (unless the reader is closed).
6282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     */
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private char[] buf;
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    private int pos;
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    private int end;
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    private int mark = -1;
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    private int markLimit = -1;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
740409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * readLine returns a line as soon as it sees '\n' or '\r'. In the latter
750409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * case, there might be a following '\n' that should be treated as part of
760409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * the same line ending. Both readLine and all read methods are supposed
770409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * to skip the '\n' (and clear this field) but only readLine looks for '\r'
780409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * and sets it.
790409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     */
800409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    private boolean lastWasCR;
810409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
820409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    /**
830409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * We also need to keep the 'lastWasCR' state for the mark position, in case
840409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * we reset to there.
850409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     */
860409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    private boolean markedLastWasCR;
870409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
880409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    /**
89fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * Constructs a new {@code BufferedReader}, providing {@code in} with a buffer
90fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * of 8192 characters.
91fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     *
92fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @param in the {@code Reader} the buffer reads from.
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public BufferedReader(Reader in) {
95fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes        this(in, 8192);
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
99fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * Constructs a new {@code BufferedReader}, providing {@code in} with {@code size} characters
100fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * of buffer.
101fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     *
102fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @param in the {@code InputStream} the buffer reads from.
103fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @param size the size of buffer in characters.
104fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @throws IllegalArgumentException if {@code size <= 0}.
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public BufferedReader(Reader in, int size) {
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(in);
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size <= 0) {
109b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size <= 0");
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.in = in;
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf = new char[size];
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes this reader. This implementation closes the buffered source reader
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and releases the buffer. Nothing is done if this reader has already been
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * closed.
119f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing this reader.
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isClosed()) {
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                in.close();
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                buf = null;
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
13382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    /**
13482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * Populates the buffer with data. It is an error to call this method when
13582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * the buffer still contains data; ie. if {@code pos < end}.
13682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *
137fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson     * @return the number of chars read into the buffer, or -1 if the end of the
13882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *      source stream has been reached.
13982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     */
14082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    private int fillBuf() throws IOException {
14182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        // assert(pos == end);
14282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
14382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (mark == -1 || (pos - mark >= markLimit)) {
14482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* mark isn't set or has exceeded its limit. use the whole buffer */
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int result = in.read(buf, 0, buf.length);
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (result > 0) {
14782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                mark = -1;
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                pos = 0;
14982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                end = result;
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return result;
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
15382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
15482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (mark == 0 && markLimit > buf.length) {
15582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* the only way to make room when mark=0 is by growing the buffer */
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int newLength = buf.length * 2;
15782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            if (newLength > markLimit) {
15882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                newLength = markLimit;
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            char[] newbuf = new char[newLength];
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(buf, 0, newbuf, 0, buf.length);
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf = newbuf;
16382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        } else if (mark > 0) {
16482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* make room by shifting the buffered data to left mark positions */
16582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            System.arraycopy(buf, mark, buf, 0, buf.length - mark);
16682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            pos -= mark;
16782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            end -= mark;
16882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            mark = 0;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /* Set the new position and mark position */
17282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        int count = in.read(buf, pos, buf.length - pos);
17382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (count != -1) {
17482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            end += count;
17582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        }
17682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        return count;
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether or not this reader is closed.
181f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this reader is closed, {@code false}
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isClosed() {
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return buf == null;
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
19082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * Sets a mark position in this reader. The parameter {@code markLimit}
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * indicates how many characters can be read before the mark is invalidated.
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Calling {@code reset()} will reposition the reader back to the marked
19382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * position if {@code markLimit} has not been surpassed.
194f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
19582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * @param markLimit
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of characters that can be read before the mark is
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            invalidated.
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
19982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *             if {@code markLimit < 0}.
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while setting a mark in this reader.
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
20682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    public void mark(int markLimit) throws IOException {
20782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (markLimit < 0) {
208cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            throw new IllegalArgumentException("markLimit < 0:" + markLimit);
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
211b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
21282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            this.markLimit = markLimit;
2130409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            this.mark = pos;
2140409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            this.markedLastWasCR = lastWasCR;
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
218b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    private void checkNotClosed() throws IOException {
219b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (isClosed()) {
220b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("BufferedReader is closed");
221b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        }
222b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    }
223b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader supports the {@code mark()} and
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code reset()} methods. This implementation returns {@code true}.
227f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} for {@code BufferedReader}.
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean markSupported() {
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return true;
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads a single character from this reader and returns it with the two
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * higher-order bytes set to 0. If possible, BufferedReader returns a
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * character from the buffer. If there are no characters available in the
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * buffer, it fills the buffer and then returns a character. It returns -1
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if there are no more characters in the source reader.
243f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the character read or -1 if the end of the source reader has been
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         reached.
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read() throws IOException {
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
252b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
2530409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            int ch = readChar();
2540409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            if (lastWasCR && ch == '\n') {
2550409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                ch = readChar();
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
2570409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            lastWasCR = false;
2580409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            return ch;
2590409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes        }
2600409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    }
2610409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
2620409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    private int readChar() throws IOException {
2630409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes        if (pos < end || fillBuf() != -1) {
2640409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            return buf[pos++];
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
2660409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes        return -1;
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
270325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * Reads up to {@code length} characters from this reader and stores them
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * at {@code offset} in the character array {@code buffer}. Returns the
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * number of characters actually read or -1 if the end of the source reader
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * has been reached. If all the buffered characters have been used, a mark
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * has not been set and the requested number of characters is larger than
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this readers buffer size, BufferedReader bypasses the buffer and simply
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * places the results directly into {@code buffer}.
277f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IndexOutOfBoundsException
279325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     *     if {@code offset < 0 || length < 0 || offset + length > buffer.length}.
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read(char[] buffer, int offset, int length) throws IOException {
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
286b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
287a1603838fe9e865575c87982e32c6343740e464cElliott Hughes            Arrays.checkOffsetAndCount(buffer.length, offset, length);
2880409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            if (length == 0) {
2890409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                return 0;
2900409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            }
2910409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
2920409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            maybeSwallowLF();
2930409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
29482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            int outstanding = length;
29582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            while (outstanding > 0) {
2960409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                // If there are chars in the buffer, grab those first.
29782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                int available = end - pos;
29882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (available > 0) {
29982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    int count = available >= outstanding ? outstanding : available;
30082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    System.arraycopy(buf, pos, buffer, offset, count);
30182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    pos += count;
30282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    offset += count;
30382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    outstanding -= count;
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /*
30782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * Before attempting to read from the underlying stream, make
30882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * sure we really, really want to. We won't bother if we're
309fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                 * done, or if we've already got some chars and reading from the
31082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * underlying stream would block.
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 */
31282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (outstanding == 0 || (outstanding < length && !in.ready())) {
31382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    break;
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
31582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
31682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                // assert(pos == end);
31782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
31882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                /*
31982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * If we're unmarked and the requested size is greater than our
320fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                 * buffer, read the chars directly into the caller's buffer. We
32182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * don't read into smaller buffers because that could result in
32282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * a many reads.
32382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 */
324344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes                if ((mark == -1 || (pos - mark >= markLimit)) && outstanding >= buf.length) {
32582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    int count = in.read(buffer, offset, outstanding);
32682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    if (count > 0) {
32782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                        outstanding -= count;
32882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                        mark = -1;
32982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    }
33082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    break; // assume the source stream gave us all that it could
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
33282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
33382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (fillBuf() == -1) {
33482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    break; // source is exhausted
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
33782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
33882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            int count = length - outstanding;
3390409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            if (count > 0) {
3400409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                return count;
3410409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            }
3420409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            return -1;
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
34755392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * Peeks at the next input character, refilling the buffer if necessary. If
34855392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * this character is a newline character ("\n"), it is discarded.
34955392539fea537abfb6581b474918f9d611fba27Jesse Wilson     */
35055392539fea537abfb6581b474918f9d611fba27Jesse Wilson    final void chompNewline() throws IOException {
3510409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes        if ((pos != end || fillBuf() != -1) && buf[pos] == '\n') {
3520409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            ++pos;
3530409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes        }
3540409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    }
3550409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
3560409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    // If the last character was CR and the next character is LF, skip it.
3570409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes    private void maybeSwallowLF() throws IOException {
3580409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes        if (lastWasCR) {
3590409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            chompNewline();
3600409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            lastWasCR = false;
36155392539fea537abfb6581b474918f9d611fba27Jesse Wilson        }
36255392539fea537abfb6581b474918f9d611fba27Jesse Wilson    }
36355392539fea537abfb6581b474918f9d611fba27Jesse Wilson
36455392539fea537abfb6581b474918f9d611fba27Jesse Wilson    /**
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the next line of text available from this reader. A line is
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * represented by zero or more characters followed by {@code '\n'},
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does
368a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson     * not include the newline sequence.
369f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the contents of the line or {@code null} if no characters were
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         read before the end of the reader has been reached.
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String readLine() throws IOException {
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
377b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
3780409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
3790409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            maybeSwallowLF();
3800409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
3810409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            // Do we have a whole line in the buffer?
3820409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            for (int i = pos; i < end; ++i) {
3830409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                char ch = buf[i];
3840409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                if (ch == '\n' || ch == '\r') {
3850409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    String line = new String(buf, pos, i - pos);
3860409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    pos = i + 1;
3870409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    lastWasCR = (ch == '\r');
3880409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    return line;
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
3920409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            // Accumulate buffers in a StringBuilder until we've read a whole line.
3930409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            StringBuilder result = new StringBuilder(end - pos + 80);
39482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            result.append(buf, pos, end - pos);
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (true) {
39682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                pos = end;
39782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (fillBuf() == -1) {
3980409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    // If there's no more input, return what we've read so far, if anything.
3990409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    return (result.length() > 0) ? result.toString() : null;
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
4010409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
4020409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                // Do we have a whole line in the buffer now?
4030409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                for (int i = pos; i < end; ++i) {
4040409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    char ch = buf[i];
4050409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                    if (ch == '\n' || ch == '\r') {
4060409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                        result.append(buf, pos, i - pos);
4070409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                        pos = i + 1;
4080409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                        lastWasCR = (ch == '\r');
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return result.toString();
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
4120409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes
4130409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                // Add this whole buffer to the line-in-progress and try again...
4140409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes                result.append(buf, pos, end - pos);
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader is ready to be read without blocking.
421f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this reader will not block when {@code read} is
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         called, {@code false} if unknown or blocking will occur.
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read()
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read(char[], int, int)
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #readLine()
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean ready() throws IOException {
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
433b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
43482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            return ((end - pos) > 0) || in.ready();
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Resets this reader's position to the last {@code mark()} location.
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Invocations of {@code read()} and {@code skip()} will occur from this new
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * location.
442f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or no mark has been set.
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void reset() throws IOException {
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
451b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
45282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            if (mark == -1) {
453b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IOException("Invalid mark");
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
4550409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            this.pos = mark;
4560409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes            this.lastWasCR = this.markedLastWasCR;
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
4610409fa8fe9b1b3cd501931a8c25e109e6ff71be0Elliott Hughes     * Skips at most {@code charCount} chars in this stream. Subsequent calls to
462fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson     * {@code read} will not return these chars unless {@code reset} is
463f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * used.
464fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson     *
465fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson     * <p>Skipping characters may invalidate a mark if {@code markLimit}
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is surpassed.
467f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of characters actually skipped.
469fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson     * @throws IllegalArgumentException if {@code charCount < 0}.
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
474fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson    public long skip(long charCount) throws IOException {
475fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson        if (charCount < 0) {
476fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson            throw new IllegalArgumentException("charCount < 0: " + charCount);
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
479b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
480fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson            if (end - pos >= charCount) {
481fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                pos += charCount;
482fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                return charCount;
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            long read = end - pos;
48682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            pos = end;
487fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson            while (read < charCount) {
48882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (fillBuf() == -1) {
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return read;
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
491fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                if (end - pos >= charCount - read) {
492fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                    pos += charCount - read;
493fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson                    return charCount;
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Couldn't get all the characters, skip what we read
49682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                read += (end - pos);
49782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                pos = end;
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
499fd1bbd5cb70830aaf6639dafc240c4d17181ef75Jesse Wilson            return charCount;
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
503