001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.io.input; 018 019 import java.io.Reader; 020 import java.io.Serializable; 021 022 /** 023 * {@link Reader} implementation that can read from String, StringBuffer, 024 * StringBuilder or CharBuffer. 025 * <p> 026 * <strong>Note:</strong> Supports {@link #mark(int)} and {@link #reset()}. 027 * 028 * @version $Revision: 610516 $ $Date: 2008-01-09 19:05:05 +0000 (Wed, 09 Jan 2008) $ 029 * @since Commons IO 1.4 030 */ 031 public class CharSequenceReader extends Reader implements Serializable { 032 033 private final CharSequence charSequence; 034 private int idx; 035 private int mark; 036 037 /** 038 * Construct a new instance with the specified character sequence. 039 * 040 * @param charSequence The character sequence, may be <code>null</code> 041 */ 042 public CharSequenceReader(CharSequence charSequence) { 043 this.charSequence = (charSequence != null ? charSequence : ""); 044 } 045 046 /** 047 * Close resets the file back to the start and removes any marked position. 048 */ 049 public void close() { 050 idx = 0; 051 mark = 0; 052 } 053 054 /** 055 * Mark the current position. 056 * 057 * @param readAheadLimit ignored 058 */ 059 public void mark(int readAheadLimit) { 060 mark = idx; 061 } 062 063 /** 064 * Mark is supported (returns true). 065 * 066 * @return <code>true</code> 067 */ 068 public boolean markSupported() { 069 return true; 070 } 071 072 /** 073 * Read a single character. 074 * 075 * @return the next character from the character sequence 076 * or -1 if the end has been reached. 077 */ 078 public int read() { 079 if (idx >= charSequence.length()) { 080 return -1; 081 } else { 082 return charSequence.charAt(idx++); 083 } 084 } 085 086 /** 087 * Read the sepcified number of characters into the array. 088 * 089 * @param array The array to store the characters in 090 * @param offset The starting position in the array to store 091 * @param length The maximum number of characters to read 092 * @return The number of characters read or -1 if there are 093 * no more 094 */ 095 public int read(char[] array, int offset, int length) { 096 if (idx >= charSequence.length()) { 097 return -1; 098 } 099 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 }