1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one or more
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * contributor license agreements.  See the NOTICE file distributed with
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * this work for additional information regarding copyright ownership.
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The ASF licenses this file to You under the Apache License, Version 2.0
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * (the "License"); you may not use this file except in compliance with
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the License.  You may obtain a copy of the License at
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.commons.io.input;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.Reader;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.Serializable;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * {@link Reader} implementation that can read from String, StringBuffer,
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * StringBuilder or CharBuffer.
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <strong>Note:</strong> Supports {@link #mark(int)} and {@link #reset()}.
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Revision: 610516 $ $Date: 2008-01-09 19:05:05 +0000 (Wed, 09 Jan 2008) $
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @since Commons IO 1.4
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class CharSequenceReader extends Reader implements Serializable {
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final CharSequence charSequence;
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private int idx;
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private int mark;
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Construct a new instance with the specified character sequence.
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param charSequence The character sequence, may be <code>null</code>
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public CharSequenceReader(CharSequence charSequence) {
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.charSequence = (charSequence != null ? charSequence : "");
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Close resets the file back to the start and removes any marked position.
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void close() {
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        idx = 0;
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mark = 0;
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Mark the current position.
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param readAheadLimit ignored
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void mark(int readAheadLimit) {
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mark = idx;
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Mark is supported (returns true).
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return <code>true</code>
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean markSupported() {
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return true;
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Read a single character.
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the next character from the character sequence
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * or -1 if the end has been reached.
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read() {
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (idx >= charSequence.length()) {
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return -1;
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return charSequence.charAt(idx++);
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Read the sepcified number of characters into the array.
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param array The array to store the characters in
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param offset The starting position in the array to store
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param length The maximum number of characters to read
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The number of characters read or -1 if there are
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * no more
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(char[] array, int offset, int length) {
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (idx >= charSequence.length()) {
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return -1;
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (array == null) {
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new NullPointerException("Character array is missing");
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (length < 0 || (offset + length) > array.length) {
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IndexOutOfBoundsException("Array Size=" + array.length +
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    ", offset=" + offset + ", length=" + length);
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int count = 0;
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        for (int i = 0; i < length; i++) {
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            int c = read();
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (c == -1) {
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return count;
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            array[offset + i] = (char)c;
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            count++;
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return count;
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reset the reader to the last marked position (or the beginning if
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * mark has not been called).
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void reset() {
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        idx = mark;
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Skip the specified number of characters.
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param n The number of characters to skip
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The actual number of characters skipped
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public long skip(long n) {
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (n < 0) {
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IllegalArgumentException(
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    "Number of characters to skip is less than zero: " + n);
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (idx >= charSequence.length()) {
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return -1;
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int dest = (int)Math.min(charSequence.length(), (idx + n));
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int count = dest - idx;
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        idx = dest;
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return count;
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Return a String representation of the underlying
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * character sequence.
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The contents of the character sequence
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String toString() {
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return charSequence.toString();
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
156