/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2005 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.io;
import java.io.IOException;
import java.io.Reader;
import java.lang.CharSequence;
import java.lang.IllegalStateException;
import javolution.lang.MathLib;
import javolution.lang.Reusable;
import java.lang.Appendable;
import javolution.text.CharArray;
import javolution.text.Text;
import javolution.text.TextBuilder;
/**
* <p> This class allows any <code>CharSequence</code> to be used as
* a reader.</p>
*
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
* @version 3.8, May 8, 2004
*/
public final class CharSequenceReader extends Reader implements Reusable {
/**
* Holds the character sequence input.
*/
private CharSequence _input;
/**
* Holds the current index into the character sequence.
*/
private int _index;
/**
* Creates a new character sequence reader for which the character
* sequence input is not set.
*
* @see #setInput
*/
public CharSequenceReader() {
}
/**
* Sets the character sequence to use for reading.
*
* @param charSequence the character sequence to be read.
* @return this reader.
* @throws IllegalStateException if this reader is being reused and
* it has not been {@link #close closed} or {@link #reset reset}.
*/
public CharSequenceReader setInput(CharSequence charSequence) {
if (_input != null)
throw new IllegalStateException("Reader not closed or reset");
_input = charSequence;
return this;
}
/**
* Indicates if this stream is ready to be read.
*
* @return <code>true</code> if this reader has remaining characters to
* read; <code>false</code> otherwise.
* @throws IOException if an I/O error occurs.
*/
public boolean ready() throws IOException {
if (_input == null)
throw new IOException("Reader closed");
return true;
}
/**
* Closes and {@link #reset resets} this reader for reuse.
*/
public void close() {
if (_input != null) {
reset();
}
}
/**
* Reads a single character. This method does not block, <code>-1</code>
* is returned if the end of the character sequence input has been reached.
*
* @return the 31-bits Unicode of the character read, or -1 if there is
* no more remaining bytes to be read.
* @throws IOException if an I/O error occurs (e.g. incomplete
* character sequence being read).
*/
public int read() throws IOException {
if (_input == null)
throw new IOException("Reader closed");
return (_index < _input.length()) ? _input.charAt(_index++) : -1;
}
/**
* Reads characters into a portion of an array. This method does not
* block.
*
* @param cbuf the destination buffer.
* @param off the offset at which to start storing characters.
* @param len the maximum number of characters to read
* @return the number of characters read, or -1 if there is no more
* character to be read.
* @throws IOException if an I/O error occurs.
*/
public int read(char cbuf[], int off, int len) throws IOException {
if (_input == null)
throw new IOException("Reader closed");
final int inputLength = _input.length();
if (_index >= inputLength)
return -1;
final int count = MathLib.min(inputLength - _index, len);
final Object csq = _input;
if (csq instanceof String) {
String str = (String) csq;
str.getChars(_index, _index + count, cbuf, off);
} else if (csq instanceof Text) {
Text txt = (Text) csq;
txt.getChars(_index, _index + count, cbuf, off);
} else if (csq instanceof TextBuilder) {
TextBuilder tb = (TextBuilder) csq;
tb.getChars(_index, _index + count, cbuf, off);
} else if (csq instanceof CharArray) {
CharArray ca = (CharArray) csq;
System
.arraycopy(ca.array(), _index + ca.offset(), cbuf, off,
count);
} else { // Generic CharSequence.
for (int i = off, n = off + count, j = _index; i < n;) {
cbuf[i++] = _input.charAt(j++);
}
}
_index += count;
return count;
}
/**
* Reads characters into the specified appendable. This method does not
* block.
*
* @param dest the destination buffer.
* @throws IOException if an I/O error occurs.
*/
public void read(Appendable dest) throws IOException {
if (_input == null)
throw new IOException("Reader closed");
dest.append(_input);
}
// Implements Reusable.
public void reset() {
_index = 0;
_input = null;
}
}