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
20b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughesimport java.util.Arrays;
21b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Wraps an existing {@link Reader} and adds functionality to "push back"
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * characters that have been read, so that they can be read again. Parsers may
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * find this useful. The number of characters which may be pushed back can be
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified during construction. If the buffer of pushed back bytes is empty,
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * characters are read from the underlying reader.
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class PushbackReader extends FilterReader {
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The {@code char} array containing the chars to read.
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char[] buf;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The current position within the char array {@code buf}. A value
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * equal to buf.length indicates no chars available. A value of 0 indicates
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the buffer is full.
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int pos;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code PushbackReader} with the specified reader as
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * source. The size of the pushback buffer is set to the default value of 1
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * character.
46f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param in
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source reader.
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public PushbackReader(Reader in) {
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(in);
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf = new char[1];
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pos = 1;
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code PushbackReader} with {@code in} as source reader.
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The size of the pushback buffer is set to {@code size}.
59f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param in
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source reader.
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param size
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the size of the pushback buffer.
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code size} is negative.
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public PushbackReader(Reader in, int size) {
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(in);
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (size <= 0) {
70b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("size <= 0");
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        buf = new char[size];
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pos = size;
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes this reader. This implementation closes the source reader
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and releases the pushback buffer.
79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs while closing this reader.
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf = null;
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            in.close();
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Marks the current position in this stream. Setting a mark is not
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * supported in this class; this implementation always throws an
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code IOException}.
95f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param readAheadLimit
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of character that can be read from this reader
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            before the mark is invalidated; this parameter is ignored.
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this method is called.
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void mark(int readAheadLimit) throws IOException {
104b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        throw new IOException("mark/reset not supported");
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader supports the {@code mark(int)} and
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code reset()} methods. {@code PushbackReader} does not support them, so
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * it returns {@code false}.
111f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return always {@code false}.
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean markSupported() {
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads a single character from this reader and returns it as an integer
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * with the two higher-order bytes set to 0. Returns -1 if the end of the
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * reader has been reached. If the pushback buffer does not contain any
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * available characters then a character from the source reader is returned.
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Blocks until one character has been read, the end of the source reader is
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * detected or an exception is thrown.
128f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the character read or -1 if the end of the source reader has been
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         reached.
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or an I/O error occurs while reading
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             from this reader.
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read() throws IOException {
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
138b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Is there a pushback character available? */
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (pos < buf.length) {
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return buf[pos++];
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * Assume read() in the InputStream will return 2 lowest-order bytes
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * or -1 if end of stream.
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return in.read();
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
151b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    private void checkNotClosed() throws IOException {
152b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (buf == null) {
153b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("PushbackReader is closed");
154b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        }
155b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    }
156b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads at most {@code length} bytes from this reader and stores them in
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * byte array {@code buffer} starting at {@code offset}. Characters are
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read from the pushback buffer first, then from the source reader if more
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * bytes are required. Blocks until {@code count} characters have been read,
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the end of the source reader is detected or an exception is thrown.
163f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buffer
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the array in which to store the characters read from this
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            reader.
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the initial position in {@code buffer} to store the characters
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            read from this reader.
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param count
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the maximum number of bytes to store in {@code buffer}.
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes read or -1 if the end of the source reader
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         has been reached.
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IndexOutOfBoundsException
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset < 0} or {@code count < 0}, or if
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code offset + count} is greater than the length of
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code buffer}.
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or another I/O error occurs while
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             reading from this reader.
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read(char[] buffer, int offset, int count) throws IOException {
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
185b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
186a1603838fe9e865575c87982e32c6343740e464cElliott Hughes            Arrays.checkOffsetAndCount(buffer.length, offset, count);
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int copiedChars = 0;
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int copyLength = 0;
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int newOffset = offset;
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Are there pushback chars available? */
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (pos < buf.length) {
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copyLength = (buf.length - pos >= count) ? count : buf.length
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        - pos;
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(buf, pos, buffer, newOffset, copyLength);
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newOffset += copyLength;
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copiedChars += copyLength;
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /* Use up the chars in the local buffer */
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                pos += copyLength;
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Have we copied enough? */
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (copyLength == count) {
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return count;
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int inCopied = in.read(buffer, newOffset, count - copiedChars);
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (inCopied > 0) {
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return inCopied + copiedChars;
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (copiedChars == 0) {
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return inCopied;
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return copiedChars;
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader is ready to be read without blocking.
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns {@code true} if this reader will not block when {@code read} is
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * called, {@code false} if unknown or blocking will occur.
220f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the receiver will not block when
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code read()} is called, {@code false} if unknown
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         or blocking will occur.
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or some other I/O error occurs.
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read()
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read(char[], int, int)
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean ready() throws IOException {
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (buf == null) {
233b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IOException("Reader is closed");
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return (buf.length - pos > 0 || in.ready());
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Resets this reader to the last marked position. Resetting the reader is
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * not supported in this class; this implementation always throws an
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code IOException}.
243f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this method is called.
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void reset() throws IOException {
249b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        throw new IOException("mark/reset not supported");
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Pushes all the characters in {@code buffer} back to this reader. The
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * characters are pushed back in such a way that the next character read
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * from this reader is buffer[0], then buffer[1] and so on.
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this reader's internal pushback buffer cannot store the entire
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * contents of {@code buffer}, an {@code IOException} is thrown. Parts of
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code buffer} may have already been copied to the pushback buffer when
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the exception is thrown.
261f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buffer
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the buffer containing the characters to push back to this
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            reader.
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or the free space in the internal
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             pushback buffer is not sufficient to store the contents of
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code buffer}.
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void unread(char[] buffer) throws IOException {
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        unread(buffer, 0, buffer.length);
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Pushes a subset of the characters in {@code buffer} back to this reader.
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The subset is defined by the start position {@code offset} within
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code buffer} and the number of characters specified by {@code length}.
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The bytes are pushed back in such a way that the next byte read from this
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * stream is {@code buffer[offset]}, then {@code buffer[1]} and so on.
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this stream's internal pushback buffer cannot store the selected
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * subset of {@code buffer}, an {@code IOException} is thrown. Parts of
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code buffer} may have already been copied to the pushback buffer when
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the exception is thrown.
285f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buffer
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the buffer containing the characters to push back to this
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            reader.
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the index of the first byte in {@code buffer} to push back.
2915839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson     * @param length
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of bytes to push back.
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IndexOutOfBoundsException
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset < 0} or {@code count < 0}, or if
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code offset + count} is greater than the length of
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code buffer}.
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or the free space in the internal
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             pushback buffer is not sufficient to store the selected
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             contents of {@code buffer}.
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code buffer} is {@code null}.
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
3045839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson    public void unread(char[] buffer, int offset, int length) throws IOException {
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
306b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
3075839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson            if (length > pos) {
308b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IOException("Pushback buffer full");
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
310b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes            Arrays.checkOffsetAndCount(buffer.length, offset, length);
3115839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson            for (int i = offset + length - 1; i >= offset; i--) {
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unread(buffer[i]);
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Pushes the specified character {@code oneChar} back to this reader. This
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is done in such a way that the next character read from this reader is
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code (char) oneChar}.
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * If this reader's internal pushback buffer cannot store the character, an
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code IOException} is thrown.
324f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param oneChar
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the character to push back to this stream.
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or the internal pushback buffer is
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             full.
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void unread(int oneChar) throws IOException {
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
333b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (pos == 0) {
335b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IOException("Pushback buffer full");
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf[--pos] = (char) oneChar;
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
342f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * Skips {@code charCount} characters in this reader. This implementation skips
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * characters in the pushback buffer first and then in the source reader if
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * necessary.
345f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of characters actually skipped.
347f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * @throws IllegalArgumentException if {@code charCount < 0}.
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed or another I/O error occurs.
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
352f9480f317cddcec859025833b748f096247a40aaElliott Hughes    public long skip(long charCount) throws IOException {
353f9480f317cddcec859025833b748f096247a40aaElliott Hughes        if (charCount < 0) {
354a1603838fe9e865575c87982e32c6343740e464cElliott Hughes            throw new IllegalArgumentException("charCount < 0: " + charCount);
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
357b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
358f9480f317cddcec859025833b748f096247a40aaElliott Hughes            if (charCount == 0) {
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return 0;
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long inSkipped;
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int availableFromBuffer = buf.length - pos;
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (availableFromBuffer > 0) {
364f9480f317cddcec859025833b748f096247a40aaElliott Hughes                long requiredFromIn = charCount - availableFromBuffer;
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (requiredFromIn <= 0) {
366f9480f317cddcec859025833b748f096247a40aaElliott Hughes                    pos += charCount;
367f9480f317cddcec859025833b748f096247a40aaElliott Hughes                    return charCount;
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                pos += availableFromBuffer;
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                inSkipped = in.skip(requiredFromIn);
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
372f9480f317cddcec859025833b748f096247a40aaElliott Hughes                inSkipped = in.skip(charCount);
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return inSkipped + availableFromBuffer;
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
378