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 * A specialized {@link Reader} that reads characters from a {@code String} in
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a sequential manner.
25f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see StringWriter
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class StringReader extends Reader {
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String str;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int markpos = -1;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int pos;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int count;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Construct a new {@code StringReader} with {@code str} as source. The size
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the reader is set to the {@code length()} of the string and the Object
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to synchronize access through is set to {@code str}.
41f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param str
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the source string for this reader.
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public StringReader(String str) {
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.str = str;
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.count = str.length();
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes this reader. Once it is closed, read operations on this reader
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * will throw an {@code IOException}. Only the first invocation of this
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method has any effect.
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() {
57f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        str = null;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a boolean indicating whether this reader is closed.
62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if closed, otherwise {@code false}.
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isClosed() {
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return str == null;
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets a mark position in this reader. The parameter {@code readLimit} is
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * ignored for this class. Calling {@code reset()} will reposition the
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * reader back to the marked position.
73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param readLimit
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            ignored for {@code StringReader} instances.
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code readLimit < 0}.
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed.
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void mark(int readLimit) throws IOException {
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (readLimit < 0) {
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
90b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            markpos = pos;
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
95b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    private void checkNotClosed() throws IOException {
96b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (isClosed()) {
97b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("StringReader is closed");
98b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        }
99b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes    }
100b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader supports the {@code mark()} and {@code
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * reset()} methods. This implementation returns {@code true}.
104f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return always {@code true}.
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean markSupported() {
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return true;
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads a single character from the source string and returns it as an
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * integer with the two higher-order bytes set to 0. Returns -1 if the end
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the source string has been reached.
116f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the character read or -1 if the end of the source string has been
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         reached.
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed.
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read() throws IOException {
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
125b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (pos != count) {
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return str.charAt(pos++);
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads at most {@code len} characters from the source string and stores
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * them at {@code offset} in the character array {@code buf}. Returns the
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * number of characters actually read or -1 if the end of the source string
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * has been reached.
138f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buf
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the character array to store the characters read.
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param offset
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the initial position in {@code buffer} to store the characters
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            read from this reader.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param len
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the maximum number of characters to read.
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of characters read or -1 if the end of the reader has
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         been reached.
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IndexOutOfBoundsException
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code offset < 0} or {@code len < 0}, or if
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             {@code offset + len} is greater than the size of {@code buf}.
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed.
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read(char[] buf, int offset, int len) throws IOException {
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
157b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
158b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes            Arrays.checkOffsetAndCount(buf.length, offset, len);
159f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (len == 0) {
160f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                return 0;
161f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (pos == this.count) {
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return -1;
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int end = pos + len > this.count ? this.count : pos + len;
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            str.getChars(pos, end, buf, offset);
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int read = end - pos;
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            pos = end;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return read;
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this reader is ready to be read without blocking. This
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * implementation always returns {@code true}.
176f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return always {@code true}.
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed.
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read()
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #read(char[], int, int)
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean ready() throws IOException {
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
186b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Resets this reader's position to the last {@code mark()} location.
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Invocations of {@code read()} and {@code skip()} will occur from this new
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * location. If this reader has not been marked, it is reset to the
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * beginning of the source string.
196f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed.
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void reset() throws IOException {
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
205b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            pos = markpos != -1 ? markpos : 0;
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
211f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * Moves {@code charCount} characters in the source string. Unlike the {@link
21255392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * Reader#skip(long) overridden method}, this method may skip negative skip
21355392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * distances: this rewinds the input so that characters may be read again.
21455392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * When the end of the source string has been reached, the input cannot be
21555392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * rewound.
216f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
217f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * @param charCount
21855392539fea537abfb6581b474918f9d611fba27Jesse Wilson     *            the maximum number of characters to skip. Positive values skip
21955392539fea537abfb6581b474918f9d611fba27Jesse Wilson     *            forward; negative values skip backward.
22055392539fea537abfb6581b474918f9d611fba27Jesse Wilson     * @return the number of characters actually skipped. This is bounded below
22155392539fea537abfb6581b474918f9d611fba27Jesse Wilson     *            by the number of characters already read and above by the
22255392539fea537abfb6581b474918f9d611fba27Jesse Wilson     *            number of characters remaining:<br> {@code -(num chars already
22355392539fea537abfb6581b474918f9d611fba27Jesse Wilson     *            read) <= distance skipped <= num chars remaining}.
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this reader is closed.
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mark(int)
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #markSupported()
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #reset()
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
231f9480f317cddcec859025833b748f096247a40aaElliott Hughes    public long skip(long charCount) throws IOException {
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (lock) {
233b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            checkNotClosed();
23455392539fea537abfb6581b474918f9d611fba27Jesse Wilson
23555392539fea537abfb6581b474918f9d611fba27Jesse Wilson            int minSkip = -pos;
23655392539fea537abfb6581b474918f9d611fba27Jesse Wilson            int maxSkip = count - pos;
23755392539fea537abfb6581b474918f9d611fba27Jesse Wilson
238f9480f317cddcec859025833b748f096247a40aaElliott Hughes            if (maxSkip == 0 || charCount > maxSkip) {
239f9480f317cddcec859025833b748f096247a40aaElliott Hughes                charCount = maxSkip; // no rewinding if we're at the end
240f9480f317cddcec859025833b748f096247a40aaElliott Hughes            } else if (charCount < minSkip) {
241f9480f317cddcec859025833b748f096247a40aaElliott Hughes                charCount = minSkip;
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
24355392539fea537abfb6581b474918f9d611fba27Jesse Wilson
244f9480f317cddcec859025833b748f096247a40aaElliott Hughes            pos += charCount;
245f9480f317cddcec859025833b748f096247a40aaElliott Hughes            return charCount;
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
249