Author: niallp Date: Sat Jan 5 07:24:10 2008 New Revision: 609152 URL: http://svn.apache.org/viewvc?rev=609152&view=rev Log: IO-138 new Reader implementation that handles any CharSequence (String, StringBuffer, StringBuilder or CharBuffer)
Added: commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java (with props) commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java (with props) Modified: commons/proper/io/trunk/RELEASE-NOTES.txt commons/proper/io/trunk/build-check-jdk13.xml Modified: commons/proper/io/trunk/RELEASE-NOTES.txt URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/RELEASE-NOTES.txt?rev=609152&r1=609151&r2=609152&view=diff ============================================================================== --- commons/proper/io/trunk/RELEASE-NOTES.txt (original) +++ commons/proper/io/trunk/RELEASE-NOTES.txt Sat Jan 5 07:24:10 2008 @@ -33,6 +33,10 @@ Enhancements from 1.3.2 ----------------------- +- CharSequenceReader [IO-138] + - Add new Reader implementation that handles any CharSequence (String, + StringBuffer, StringBuilder or CharBuffer) + - ThesholdingOuputStream [IO-121] - Add a reset() method which sets the count of the bytes written back to zero. Modified: commons/proper/io/trunk/build-check-jdk13.xml URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/build-check-jdk13.xml?rev=609152&r1=609151&r2=609152&view=diff ============================================================================== --- commons/proper/io/trunk/build-check-jdk13.xml (original) +++ commons/proper/io/trunk/build-check-jdk13.xml Sat Jan 5 07:24:10 2008 @@ -61,6 +61,7 @@ sourcepath=""> <include name="**/*.java"/> + <exclude name="**/CharSequenceReader.java"/> <exclude name="**/RegexFileFilter.java"/> </javac> Added: commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java?rev=609152&view=auto ============================================================================== --- commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java (added) +++ commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java Sat Jan 5 07:24:10 2008 @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.io.input; + +import java.io.Reader; +import java.io.Serializable; + +/** + * [EMAIL PROTECTED] Reader} implementation that can read from String, StringBuffer, + * StringBuilder or CharBuffer. + * <p> + * <strong>Note:</strong> Supports [EMAIL PROTECTED] #mark(int)} and [EMAIL PROTECTED] #reset()}. + * + * @version $Revision$ $Date$ + * @since Commons IO 1.4 + */ +public class CharSequenceReader extends Reader implements Serializable { + + private static final StringBuilder EMPTY_BUILDER = new StringBuilder(0); + private final CharSequence charSequence; + private int idx; + private int mark; + + /** + * Construct a new instance with the specified character sequence. + * + * @param charSequence The character sequence, may be <code>null</code> + */ + public CharSequenceReader(CharSequence charSequence) { + this.charSequence = (charSequence != null ? charSequence : EMPTY_BUILDER); + } + + /** + * Close resets the file back to the start and removes any marked position. + */ + public void close() { + idx = 0; + mark = 0; + } + + /** + * Mark the current position. + * + * @param readAheadLimit ignored + */ + public void mark(int readAheadLimit) { + mark = idx; + } + + /** + * Mark is supported (returns true). + * + * @return <code>true</code> + */ + public boolean markSupported() { + return true; + } + + /** + * Read a single character. + * + * @return the next character from the character sequence + * or -1 if the end has been reached. + */ + public int read() { + if (idx >= charSequence.length()) { + return -1; + } else { + return (int)charSequence.charAt(idx++); + } + } + + /** + * Read the sepcified number of characters into the array. + * + * @param array The array to store the characters in + * @param offset The starting position in the array to store + * @param length The maximum number of characters to read + * @return The number of characters read or -1 if there are + * no more + */ + public int read(char[] array, int offset, int length) { + if (idx >= charSequence.length()) { + return -1; + } + if (array == null) { + throw new NullPointerException("Character array is missing"); + } + if (length < 0 || (offset + length) > array.length) { + throw new IndexOutOfBoundsException("Array Size=" + array.length + + ", offset=" + offset + ", length=" + length); + } + int count = 0; + for (int i = 0; i < length; i++) { + int c = read(); + if (c == -1) { + return count; + } + array[offset + i] = (char)c; + count++; + } + return count; + } + + /** + * Reset the reader to the last marked position (or the beginning if + * mark has not been called). + */ + public void reset() { + idx = mark; + } + + /** + * Skip the specified number of characters. + * + * @param n The number of characters to skip + * @return The actual number of characters skipped + */ + public long skip(long n) { + if (n < 0) { + throw new IllegalArgumentException( + "Number of characters to skip is less than zero: " + n); + } + if (idx >= charSequence.length()) { + return -1; + } + int dest = (int)Math.min(charSequence.length(), (idx + n)); + int count = dest - idx; + idx = dest; + return count; + } + + /** + * Return a String representation of the underlying + * character sequence. + * + * @return The contents of the character sequence + */ + public String toString() { + return charSequence.toString(); + } +} Propchange: commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/io/trunk/src/java/org/apache/commons/io/input/CharSequenceReader.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java?rev=609152&view=auto ============================================================================== --- commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java (added) +++ commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java Sat Jan 5 07:24:10 2008 @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.io.input; + +import java.io.IOException; +import java.io.Reader; + +import junit.framework.TestCase; + +/** + * Test case for [EMAIL PROTECTED] CharSequenceReader}. + * + * @version $Revision$ $Date$ + */ +public class CharSequenceReaderTest extends TestCase { + private static final char NONE = (new char[1])[0]; + + /** + * Contruct a new test case. + * @param name The name of the test + */ + public CharSequenceReaderTest(String name) { + super(name); + } + + /** Test [EMAIL PROTECTED] Reader#close()}. */ + public void testClose() throws IOException { + Reader reader = new CharSequenceReader("FooBar"); + checkRead(reader, "Foo"); + reader.close(); + checkRead(reader, "Foo"); + } + + /** Test [EMAIL PROTECTED] Reader#markSupported()}. */ + public void testMarkSupported() throws IOException { + Reader reader = new CharSequenceReader("FooBar"); + assertTrue(reader.markSupported()); + } + + /** Test [EMAIL PROTECTED] Reader#mark(int)}. */ + public void testMark() throws IOException { + Reader reader = new CharSequenceReader("FooBar"); + checkRead(reader, "Foo"); + reader.mark(0); + checkRead(reader, "Bar"); + reader.reset(); + checkRead(reader, "Bar"); + reader.close(); + checkRead(reader, "Foo"); + reader.reset(); + checkRead(reader, "Foo"); + } + + /** Test [EMAIL PROTECTED] Reader#skip(int)}. */ + public void testSkip() throws IOException { + Reader reader = new CharSequenceReader("FooBar"); + assertEquals(3, reader.skip(3)); + checkRead(reader, "Bar"); + assertEquals(-1, reader.skip(3)); + reader.reset(); + assertEquals(2, reader.skip(2)); + assertEquals(4, reader.skip(10)); + assertEquals(-1, reader.skip(1)); + reader.close(); + assertEquals(6, reader.skip(20)); + assertEquals(-1, reader.read()); + } + + /** Test [EMAIL PROTECTED] Reader#read()}. */ + public void testRead() throws IOException { + Reader reader = new CharSequenceReader("Foo"); + assertEquals('F', reader.read()); + assertEquals('o', reader.read()); + assertEquals('o', reader.read()); + assertEquals(-1, reader.read()); + assertEquals(-1, reader.read()); + } + + /** Test [EMAIL PROTECTED] Reader#read(char[])}. */ + public void testReadCharArray() throws IOException { + Reader reader = new CharSequenceReader("FooBar"); + char[] chars = new char[2]; + assertEquals(2, reader.read(chars)); + checkArray(new char[] {'F', 'o'}, chars); + chars = new char[3]; + assertEquals(3, reader.read(chars)); + checkArray(new char[] {'o', 'B', 'a'}, chars); + chars = new char[3]; + assertEquals(1, reader.read(chars)); + checkArray(new char[] {'r', NONE, NONE}, chars); + assertEquals(-1, reader.read(chars)); + } + + /** Test [EMAIL PROTECTED] Reader#read(char[], int, int)}. */ + public void testReadCharArrayPortion() throws IOException { + char[] chars = new char[10]; + Reader reader = new CharSequenceReader("FooBar"); + assertEquals(3, reader.read(chars, 3, 3)); + checkArray(new char[] {NONE, NONE, NONE, 'F', 'o', 'o'}, chars); + assertEquals(3, reader.read(chars, 0, 3)); + checkArray(new char[] {'B', 'a', 'r', 'F', 'o', 'o', NONE}, chars); + assertEquals(-1, reader.read(chars)); + } + + private void checkRead(Reader reader, String expected) throws IOException { + for (int i = 0; i < expected.length(); i++) { + assertEquals("Read[" + i + "] of '" + expected + "'", + (char)expected.charAt(i), (char)reader.read()); + } + } + private void checkArray(char[] expected, char[] actual) throws IOException { + for (int i = 0; i < expected.length; i++) { + assertEquals("Compare[" +i + "]", expected[i], actual[i]); + } + } +} Propchange: commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/io/trunk/src/test/org/apache/commons/io/input/CharSequenceReaderTest.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL