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