001: /*
002: * @(#)CharArrayReader.java 1.22 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.io;
029:
030: /**
031: * This class implements a character buffer that can be used as a
032: * character-input stream.
033: *
034: * @author Herb Jellinek
035: * @version 1.15, 02/02/00
036: * @since JDK1.1
037: */
038: public class CharArrayReader extends Reader {
039: /** The character buffer. */
040: protected char buf[];
041:
042: /** The current buffer position. */
043: protected int pos;
044:
045: /** The position of mark in buffer. */
046: protected int markedPos = 0;
047:
048: /**
049: * The index of the end of this buffer. There is not valid
050: * data at or beyond this index.
051: */
052: protected int count;
053:
054: /**
055: * Create an CharArrayReader from the specified array of chars.
056: * @param buf Input buffer (not copied)
057: */
058: public CharArrayReader(char buf[]) {
059: this .buf = buf;
060: this .pos = 0;
061: this .count = buf.length;
062: }
063:
064: /**
065: * Create an CharArrayReader from the specified array of chars.
066: * @param buf Input buffer (not copied)
067: * @param offset Offset of the first char to read
068: * @param length Number of chars to read
069: */
070: public CharArrayReader(char buf[], int offset, int length) {
071: if ((offset < 0) || (offset > buf.length) || (length < 0)
072: || ((offset + length) < 0)) {
073: throw new IllegalArgumentException();
074: }
075: this .buf = buf;
076: this .pos = offset;
077: this .count = Math.min(offset + length, buf.length);
078: this .markedPos = offset;
079: }
080:
081: /** Check to make sure that the stream has not been closed */
082: private void ensureOpen() throws IOException {
083: if (buf == null)
084: throw new IOException("Stream closed");
085: }
086:
087: /**
088: * Read a single character.
089: *
090: * @exception IOException If an I/O error occurs
091: */
092: public int read() throws IOException {
093: synchronized (lock) {
094: ensureOpen();
095: if (pos >= count)
096: return -1;
097: else
098: return buf[pos++];
099: }
100: }
101:
102: /**
103: * Read characters into a portion of an array.
104: * @param b Destination buffer
105: * @param off Offset at which to start storing characters
106: * @param len Maximum number of characters to read
107: * @return The actual number of characters read, or -1 if
108: * the end of the stream has been reached
109: *
110: * @exception IOException If an I/O error occurs
111: */
112: public int read(char b[], int off, int len) throws IOException {
113: synchronized (lock) {
114: ensureOpen();
115: if ((off < 0) || (off > b.length) || (len < 0)
116: || ((off + len) > b.length) || ((off + len) < 0)) {
117: throw new IndexOutOfBoundsException();
118: } else if (len == 0) {
119: return 0;
120: }
121:
122: if (pos >= count) {
123: return -1;
124: }
125: if (pos + len > count) {
126: len = count - pos;
127: }
128: if (len <= 0) {
129: return 0;
130: }
131: System.arraycopy(buf, pos, b, off, len);
132: pos += len;
133: return len;
134: }
135: }
136:
137: /**
138: * Skip characters.
139: * @param n The number of characters to skip
140: * @return The number of characters actually skipped
141: *
142: * @exception IOException If an I/O error occurs
143: */
144: public long skip(long n) throws IOException {
145: synchronized (lock) {
146: ensureOpen();
147: if (pos + n > count) {
148: n = count - pos;
149: }
150: if (n < 0) {
151: return 0;
152: }
153: pos += n;
154: return n;
155: }
156: }
157:
158: /**
159: * Tell whether this stream is ready to be read. Character-array readers
160: * are always ready to be read.
161: *
162: * @exception IOException If an I/O error occurs
163: */
164: public boolean ready() throws IOException {
165: synchronized (lock) {
166: ensureOpen();
167: return (count - pos) > 0;
168: }
169: }
170:
171: /**
172: * Tell whether this stream supports the mark() operation, which it does.
173: */
174: public boolean markSupported() {
175: return true;
176: }
177:
178: /**
179: * Mark the present position in the stream. Subsequent calls to reset()
180: * will reposition the stream to this point.
181: *
182: * @param readAheadLimit Limit on the number of characters that may be
183: * read while still preserving the mark. Because
184: * the stream's input comes from a character array,
185: * there is no actual limit; hence this argument is
186: * ignored.
187: *
188: * @exception IOException If an I/O error occurs
189: */
190: public void mark(int readAheadLimit) throws IOException {
191: synchronized (lock) {
192: ensureOpen();
193: markedPos = pos;
194: }
195: }
196:
197: /**
198: * Reset the stream to the most recent mark, or to the beginning if it has
199: * never been marked.
200: *
201: * @exception IOException If an I/O error occurs
202: */
203: public void reset() throws IOException {
204: synchronized (lock) {
205: ensureOpen();
206: pos = markedPos;
207: }
208: }
209:
210: /**
211: * Close the stream.
212: */
213: public void close() {
214: buf = null;
215: }
216: }
|