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    /**
74fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * Constructs a new {@code BufferedReader}, providing {@code in} with a buffer
75fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * of 8192 characters.
76fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     *
77fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @param in the {@code Reader} the buffer reads from.
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public BufferedReader(Reader in) {
80fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes        this(in, 8192);
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
84fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * Constructs a new {@code BufferedReader}, providing {@code in} with {@code size} characters
85fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * of buffer.
86fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     *
87fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @param in the {@code InputStream} the buffer reads from.
88fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @param size the size of buffer in characters.
89fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes     * @throws IllegalArgumentException if {@code size <= 0}.
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public BufferedReader(Reader in, int size) {
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(in);
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size <= 0) {
94b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size <= 0");
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.in = in;
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf = new char[size];
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes this reader. This implementation closes the buffered source reader
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and releases the buffer. Nothing is done if this reader has already been
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * closed.
104f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing this reader.
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!isClosed()) {
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                in.close();
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                buf = null;
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
11882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    /**
11982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * Populates the buffer with data. It is an error to call this method when
12082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * the buffer still contains data; ie. if {@code pos < end}.
12182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *
12282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * @return the number of bytes read into the buffer, or -1 if the end of the
12382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *      source stream has been reached.
12482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     */
12582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    private int fillBuf() throws IOException {
12682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        // assert(pos == end);
12782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
12882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (mark == -1 || (pos - mark >= markLimit)) {
12982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* mark isn't set or has exceeded its limit. use the whole buffer */
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int result = in.read(buf, 0, buf.length);
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (result > 0) {
13282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                mark = -1;
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                pos = 0;
13482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                end = result;
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return result;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
13882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
13982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (mark == 0 && markLimit > buf.length) {
14082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* the only way to make room when mark=0 is by growing the buffer */
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int newLength = buf.length * 2;
14282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            if (newLength > markLimit) {
14382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                newLength = markLimit;
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            char[] newbuf = new char[newLength];
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(buf, 0, newbuf, 0, buf.length);
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf = newbuf;
14882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        } else if (mark > 0) {
14982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* make room by shifting the buffered data to left mark positions */
15082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            System.arraycopy(buf, mark, buf, 0, buf.length - mark);
15182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            pos -= mark;
15282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            end -= mark;
15382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            mark = 0;
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /* Set the new position and mark position */
15782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        int count = in.read(buf, pos, buf.length - pos);
15882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (count != -1) {
15982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            end += count;
16082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        }
16182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        return count;
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether or not this reader is closed.
166f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this reader is closed, {@code false}
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isClosed() {
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return buf == null;
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
17582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * Sets a mark position in this reader. The parameter {@code markLimit}
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * indicates how many characters can be read before the mark is invalidated.
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Calling {@code reset()} will reposition the reader back to the marked
17882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * position if {@code markLimit} has not been surpassed.
179f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
18082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     * @param markLimit
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of characters that can be read before the mark is
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            invalidated.
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
18482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson     *             if {@code markLimit < 0}.
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while setting a mark in this reader.
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
19182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson    public void mark(int markLimit) throws IOException {
19282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson        if (markLimit < 0) {
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
196b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
19782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            this.markLimit = markLimit;
19882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            mark = pos;
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
202b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    private void checkNotClosed() throws IOException {
203b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (isClosed()) {
204b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("BufferedReader is closed");
205b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        }
206b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    }
207b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader supports the {@code mark()} and
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code reset()} methods. This implementation returns {@code true}.
211f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} for {@code BufferedReader}.
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean markSupported() {
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return true;
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads a single character from this reader and returns it with the two
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * higher-order bytes set to 0. If possible, BufferedReader returns a
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * character from the buffer. If there are no characters available in the
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * buffer, it fills the buffer and then returns a character. It returns -1
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if there are no more characters in the source reader.
227f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the character read or -1 if the end of the source reader has been
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         reached.
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read() throws IOException {
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
236b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Are there buffered characters available? */
23882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            if (pos < end || fillBuf() != -1) {
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return buf[pos++];
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads at most {@code length} characters from this reader and stores them
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * at {@code offset} in the character array {@code buffer}. Returns the
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * number of characters actually read or -1 if the end of the source reader
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * has been reached. If all the buffered characters have been used, a mark
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * has not been set and the requested number of characters is larger than
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * this readers buffer size, BufferedReader bypasses the buffer and simply
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * places the results directly into {@code buffer}.
253f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buffer
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the character array to store the characters read.
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the initial position in {@code buffer} to store the bytes read
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            from this reader.
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param length
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the maximum number of characters to read, must be
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            non-negative.
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return number of characters read or -1 if the end of the source reader
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         has been reached.
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IndexOutOfBoundsException
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset < 0} or {@code length < 0}, or if
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code offset + length} is greater than the size of
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code buffer}.
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read(char[] buffer, int offset, int length) throws IOException {
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
274b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
275a1603838fe9e865575c87982e32c6343740e464cElliott Hughes            Arrays.checkOffsetAndCount(buffer.length, offset, length);
27682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            int outstanding = length;
27782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            while (outstanding > 0) {
27882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
27982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                /*
28082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * If there are bytes in the buffer, grab those first.
28182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 */
28282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                int available = end - pos;
28382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (available > 0) {
28482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    int count = available >= outstanding ? outstanding : available;
28582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    System.arraycopy(buf, pos, buffer, offset, count);
28682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    pos += count;
28782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    offset += count;
28882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    outstanding -= count;
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /*
29282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * Before attempting to read from the underlying stream, make
29382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * sure we really, really want to. We won't bother if we're
29482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * done, or if we've already got some bytes and reading from the
29582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * underlying stream would block.
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 */
29782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (outstanding == 0 || (outstanding < length && !in.ready())) {
29882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    break;
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
30082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
30182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                // assert(pos == end);
30282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
30382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                /*
30482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * If we're unmarked and the requested size is greater than our
30582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * buffer, read the bytes directly into the caller's buffer. We
30682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * don't read into smaller buffers because that could result in
30782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 * a many reads.
30882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                 */
309344110141de805108972f0ad24f16de59ba2aa32Elliott Hughes                if ((mark == -1 || (pos - mark >= markLimit)) && outstanding >= buf.length) {
31082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    int count = in.read(buffer, offset, outstanding);
31182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    if (count > 0) {
31282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                        outstanding -= count;
31382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                        mark = -1;
31482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    }
31582a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    break; // assume the source stream gave us all that it could
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
31782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
31882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (fillBuf() == -1) {
31982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    break; // source is exhausted
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
32282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
32382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            int count = length - outstanding;
32482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            return (count > 0 || count == length) ? count : -1;
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
32955392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * Peeks at the next input character, refilling the buffer if necessary. If
33055392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * this character is a newline character ("\n"), it is discarded.
33155392539fea537abfb6581b474918f9d611fba27Jesse Wilson     */
33255392539fea537abfb6581b474918f9d611fba27Jesse Wilson    final void chompNewline() throws IOException {
33355392539fea537abfb6581b474918f9d611fba27Jesse Wilson        if ((pos != end || fillBuf() != -1)
33455392539fea537abfb6581b474918f9d611fba27Jesse Wilson                && buf[pos] == '\n') {
33555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            pos++;
33655392539fea537abfb6581b474918f9d611fba27Jesse Wilson        }
33755392539fea537abfb6581b474918f9d611fba27Jesse Wilson    }
33855392539fea537abfb6581b474918f9d611fba27Jesse Wilson
33955392539fea537abfb6581b474918f9d611fba27Jesse Wilson    /**
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the next line of text available from this reader. A line is
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * represented by zero or more characters followed by {@code '\n'},
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does
343a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson     * not include the newline sequence.
344f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the contents of the line or {@code null} if no characters were
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         read before the end of the reader has been reached.
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String readLine() throws IOException {
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
352b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
35382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            /* has the underlying stream been exhausted? */
35482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            if (pos == end && fillBuf() == -1) {
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return null;
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
35782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            for (int charPos = pos; charPos < end; charPos++) {
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                char ch = buf[charPos];
359a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson                if (ch > '\r') {
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue;
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (ch == '\n') {
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    String res = new String(buf, pos, charPos - pos);
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    pos = charPos + 1;
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return res;
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (ch == '\r') {
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    String res = new String(buf, pos, charPos - pos);
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    pos = charPos + 1;
36982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    if (((pos < end) || (fillBuf() != -1))
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            && (buf[pos] == '\n')) {
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        pos++;
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return res;
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            char eol = '\0';
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            StringBuilder result = new StringBuilder(80);
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Typical Line Length */
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
38182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            result.append(buf, pos, end - pos);
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (true) {
38382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                pos = end;
38482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /* Are there buffered characters available? */
38682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (eol == '\n') {
38782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    return result.toString();
38882a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                }
38982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                // attempt to fill buffer
39082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (fillBuf() == -1) {
39182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    // characters or null.
39282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    return result.length() > 0 || eol != '\0'
39382a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                            ? result.toString()
39482a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                            : null;
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
39682a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                for (int charPos = pos; charPos < end; charPos++) {
39782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    char c = buf[charPos];
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (eol == '\0') {
39982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                        if ((c == '\n' || c == '\r')) {
40082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                            eol = c;
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
40282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    } else if (eol == '\r' && c == '\n') {
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (charPos > pos) {
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            result.append(buf, pos, charPos - pos - 1);
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        pos = charPos + 1;
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return result.toString();
408a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson                    } else {
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (charPos > pos) {
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            result.append(buf, pos, charPos - pos - 1);
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        pos = charPos;
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return result.toString();
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (eol == '\0') {
41782a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    result.append(buf, pos, end - pos);
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
41982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                    result.append(buf, pos, end - pos - 1);
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader is ready to be read without blocking.
428f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this reader will not block when {@code read} is
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         called, {@code false} if unknown or blocking will occur.
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read()
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read(char[], int, int)
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #readLine()
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean ready() throws IOException {
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
440b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
44182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            return ((end - pos) > 0) || in.ready();
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Resets this reader's position to the last {@code mark()} location.
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Invocations of {@code read()} and {@code skip()} will occur from this new
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * location.
449f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or no mark has been set.
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void reset() throws IOException {
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
458b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
45982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            if (mark == -1) {
460b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IOException("Invalid mark");
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
46282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            pos = mark;
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
467f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * Skips {@code byteCount} bytes in this stream. Subsequent calls to
468f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * {@code read} will not return these bytes unless {@code reset} is
469f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * used.
470f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * Skipping characters may invalidate a mark if {@code markLimit}
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is surpassed.
472f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
473f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * @param byteCount
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the maximum number of characters to skip.
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of characters actually skipped.
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
477f9480f317cddcec859025833b748f096247a40aaElliott Hughes     *             if {@code byteCount < 0}.
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
485f9480f317cddcec859025833b748f096247a40aaElliott Hughes    public long skip(long byteCount) throws IOException {
486f9480f317cddcec859025833b748f096247a40aaElliott Hughes        if (byteCount < 0) {
487a1603838fe9e865575c87982e32c6343740e464cElliott Hughes            throw new IllegalArgumentException("byteCount < 0: " + byteCount);
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
490b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
491f9480f317cddcec859025833b748f096247a40aaElliott Hughes            if (byteCount < 1) {
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return 0;
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
494f9480f317cddcec859025833b748f096247a40aaElliott Hughes            if (end - pos >= byteCount) {
495f9480f317cddcec859025833b748f096247a40aaElliott Hughes                pos += byteCount;
496f9480f317cddcec859025833b748f096247a40aaElliott Hughes                return byteCount;
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49982a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            long read = end - pos;
50082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson            pos = end;
501f9480f317cddcec859025833b748f096247a40aaElliott Hughes            while (read < byteCount) {
50282a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                if (fillBuf() == -1) {
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return read;
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
505f9480f317cddcec859025833b748f096247a40aaElliott Hughes                if (end - pos >= byteCount - read) {
506f9480f317cddcec859025833b748f096247a40aaElliott Hughes                    pos += byteCount - read;
507f9480f317cddcec859025833b748f096247a40aaElliott Hughes                    return byteCount;
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Couldn't get all the characters, skip what we read
51082a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                read += (end - pos);
51182a2dfcd2281c2f8042fd5f09c98bea1e728530fJesse Wilson                pos = end;
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
513f9480f317cddcec859025833b748f096247a40aaElliott Hughes            return byteCount;
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
517