14ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/*
24ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Licensed to the Apache Software Foundation (ASF) under one or more
34ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * contributor license agreements.  See the NOTICE file distributed with
44ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * this work for additional information regarding copyright ownership.
54ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * The ASF licenses this file to You under the Apache License, Version 2.0
64ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * (the "License"); you may not use this file except in compliance with
74ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * the License.  You may obtain a copy of the License at
84ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
94ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * Unless required by applicable law or agreed to in writing, software
124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * See the License for the specific language governing permissions and
154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * limitations under the License.
164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapackage org.apache.commons.io.input;
184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.Reader;
204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereiraimport java.io.Serializable;
214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira/**
234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * {@link Reader} implementation that can read from String, StringBuffer,
244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * StringBuilder or CharBuffer.
254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <p>
264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * <strong>Note:</strong> Supports {@link #mark(int)} and {@link #reset()}.
274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira *
284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @version $Revision: 610516 $ $Date: 2008-01-09 19:05:05 +0000 (Wed, 09 Jan 2008) $
294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira * @since Commons IO 1.4
304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira */
314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereirapublic class CharSequenceReader extends Reader implements Serializable {
324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private final CharSequence charSequence;
344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private int idx;
354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    private int mark;
364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Construct a new instance with the specified character sequence.
394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param charSequence The character sequence, may be <code>null</code>
414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public CharSequenceReader(CharSequence charSequence) {
434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        this.charSequence = (charSequence != null ? charSequence : "");
444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Close resets the file back to the start and removes any marked position.
484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public void close() {
504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        idx = 0;
514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        mark = 0;
524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Mark the current position.
564ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
574ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param readAheadLimit ignored
584ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
594ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public void mark(int readAheadLimit) {
604ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        mark = idx;
614ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
624ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
634ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
644ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Mark is supported (returns true).
654ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
664ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return <code>true</code>
674ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
684ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public boolean markSupported() {
694ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return true;
704ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
714ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
724ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
734ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Read a single character.
744ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
754ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return the next character from the character sequence
764ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * or -1 if the end has been reached.
774ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
784ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read() {
794ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (idx >= charSequence.length()) {
804ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return -1;
814ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        } else {
824ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return charSequence.charAt(idx++);
834ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
844ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
854ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
864ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
874ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Read the sepcified number of characters into the array.
884ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
894ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param array The array to store the characters in
904ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param offset The starting position in the array to store
914ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param length The maximum number of characters to read
924ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The number of characters read or -1 if there are
934ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * no more
944ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
954ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public int read(char[] array, int offset, int length) {
964ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (idx >= charSequence.length()) {
974ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return -1;
984ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
994ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (array == null) {
1004ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new NullPointerException("Character array is missing");
1014ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1024ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (length < 0 || (offset + length) > array.length) {
1034ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IndexOutOfBoundsException("Array Size=" + array.length +
1044ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    ", offset=" + offset + ", length=" + length);
1054ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1064ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int count = 0;
1074ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        for (int i = 0; i < length; i++) {
1084ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            int c = read();
1094ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            if (c == -1) {
1104ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                return count;
1114ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            }
1124ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            array[offset + i] = (char)c;
1134ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            count++;
1144ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1154ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return count;
1164ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1174ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1184ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1194ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Reset the reader to the last marked position (or the beginning if
1204ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * mark has not been called).
1214ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1224ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public void reset() {
1234ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        idx = mark;
1244ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1254ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1264ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1274ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Skip the specified number of characters.
1284ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1294ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @param n The number of characters to skip
1304ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The actual number of characters skipped
1314ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1324ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public long skip(long n) {
1334ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (n < 0) {
1344ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            throw new IllegalArgumentException(
1354ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira                    "Number of characters to skip is less than zero: " + n);
1364ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1374ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        if (idx >= charSequence.length()) {
1384ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira            return -1;
1394ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        }
1404ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int dest = (int)Math.min(charSequence.length(), (idx + n));
1414ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        int count = dest - idx;
1424ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        idx = dest;
1434ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return count;
1444ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1454ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira
1464ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    /**
1474ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * Return a String representation of the underlying
1484ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * character sequence.
1494ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     *
1504ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     * @return The contents of the character sequence
1514ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira     */
1524ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    public String toString() {
1534ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira        return charSequence.toString();
1544ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira    }
1554ebb916ddca5f59d4f854f104fca0de6e0dda706Mindy Pereira}
156