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