001: /*
002: * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
003: * Copyright (C) 2005 - Javolution (http://javolution.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package javolution.io;
010:
011: import j2me.lang.CharSequence;
012: import j2me.lang.IllegalStateException;
013: import java.io.IOException;
014: import java.io.Reader;
015: import javolution.lang.MathLib;
016: import javolution.lang.Reusable;
017: import javolution.text.Appendable;
018: import javolution.text.CharArray;
019: import javolution.text.Text;
020: import javolution.text.TextBuilder;
021:
022: /**
023: * <p> This class allows any <code>CharSequence</code> to be used as
024: * a reader.</p>
025: *
026: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
027: * @version 3.8, May 8, 2004
028: */
029: public final class CharSequenceReader extends Reader implements
030: Reusable {
031:
032: /**
033: * Holds the character sequence input.
034: */
035: private CharSequence _input;
036:
037: /**
038: * Holds the current index into the character sequence.
039: */
040: private int _index;
041:
042: /**
043: * Creates a new character sequence reader for which the character
044: * sequence input is not set.
045: *
046: * @see #setInput
047: */
048: public CharSequenceReader() {
049: }
050:
051: /**
052: * Sets the character sequence to use for reading.
053: *
054: * @param charSequence the character sequence to be read.
055: * @return this reader.
056: * @throws IllegalStateException if this reader is being reused and
057: * it has not been {@link #close closed} or {@link #reset reset}.
058: */
059: public CharSequenceReader setInput(CharSequence charSequence) {
060: if (_input != null)
061: throw new IllegalStateException(
062: "Reader not closed or reset");
063: _input = charSequence;
064: return this ;
065: }
066:
067: /**
068: * Indicates if this stream is ready to be read.
069: *
070: * @return <code>true</code> if this reader has remaining characters to
071: * read; <code>false</code> otherwise.
072: * @throws IOException if an I/O error occurs.
073: */
074: public boolean ready() throws IOException {
075: if (_input == null)
076: throw new IOException("Reader closed");
077: return true;
078: }
079:
080: /**
081: * Closes and {@link #reset resets} this reader for reuse.
082: */
083: public void close() {
084: if (_input != null) {
085: reset();
086: }
087: }
088:
089: /**
090: * Reads a single character. This method does not block, <code>-1</code>
091: * is returned if the end of the character sequence input has been reached.
092: *
093: * @return the 31-bits Unicode of the character read, or -1 if there is
094: * no more remaining bytes to be read.
095: * @throws IOException if an I/O error occurs (e.g. incomplete
096: * character sequence being read).
097: */
098: public int read() throws IOException {
099: if (_input == null)
100: throw new IOException("Reader closed");
101: return (_index < _input.length()) ? _input.charAt(_index++)
102: : -1;
103: }
104:
105: /**
106: * Reads characters into a portion of an array. This method does not
107: * block.
108: *
109: * @param cbuf the destination buffer.
110: * @param off the offset at which to start storing characters.
111: * @param len the maximum number of characters to read
112: * @return the number of characters read, or -1 if there is no more
113: * character to be read.
114: * @throws IOException if an I/O error occurs.
115: */
116: public int read(char cbuf[], int off, int len) throws IOException {
117: if (_input == null)
118: throw new IOException("Reader closed");
119: final int inputLength = _input.length();
120: if (_index >= inputLength)
121: return -1;
122: final int count = MathLib.min(inputLength - _index, len);
123: final Object csq = _input;
124: if (csq instanceof String) {
125: String str = (String) csq;
126: str.getChars(_index, _index + count, cbuf, off);
127: } else if (csq instanceof Text) {
128: Text txt = (Text) csq;
129: txt.getChars(_index, _index + count, cbuf, off);
130: } else if (csq instanceof TextBuilder) {
131: TextBuilder tb = (TextBuilder) csq;
132: tb.getChars(_index, _index + count, cbuf, off);
133: } else if (csq instanceof CharArray) {
134: CharArray ca = (CharArray) csq;
135: System.arraycopy(ca.array(), _index + ca.offset(), cbuf,
136: off, count);
137: } else { // Generic CharSequence.
138: for (int i = off, n = off + count, j = _index; i < n;) {
139: cbuf[i++] = _input.charAt(j++);
140: }
141: }
142: _index += count;
143: return count;
144: }
145:
146: /**
147: * Reads characters into the specified appendable. This method does not
148: * block.
149: *
150: * @param dest the destination buffer.
151: * @throws IOException if an I/O error occurs.
152: */
153: public void read(Appendable dest) throws IOException {
154: if (_input == null)
155: throw new IOException("Reader closed");
156: dest.append(_input);
157: }
158:
159: // Implements Reusable.
160: public void reset() {
161: _index = 0;
162: _input = null;
163: }
164:
165: }
|