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