Frames | No Frames |
1: /* CharArrayReader.java -- Read an array of characters as a stream 2: Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.io; 40: 41: /** 42: * This class permits an array of chars to be read as an input stream. 43: * 44: * @author Aaron M. Renn (arenn@urbanophile.com) 45: * @author Warren Levy (warrenl@cygnus.com) 46: */ 47: public class CharArrayReader extends Reader 48: { 49: /** 50: * The array that contains the data supplied during read operations 51: */ 52: protected char[] buf; 53: 54: /** 55: * The array index of the next char to be read from the buffer 56: * <code>buf</code> 57: */ 58: protected int pos; 59: 60: /** 61: * The currently marked position in the stream. This defaults to 0, so a 62: * reset operation on the stream resets it to read from array index 0 in 63: * the buffer - even if the stream was initially created with an offset 64: * greater than 0 65: */ 66: protected int markedPos; 67: 68: /** 69: * This indicates the maximum number of chars that can be read from this 70: * stream. It is the array index of the position after the last valid 71: * char in the buffer <code>buf</code> 72: */ 73: protected int count; 74: 75: /** 76: * Create a new CharArrayReader that will read chars from the passed 77: * in char array. This stream will read from the beginning to the end 78: * of the array. It is identical to calling an overloaded constructor 79: * as <code>CharArrayReader(buf, 0, buf.length)</code>. 80: * <p> 81: * Note that this array is not copied. If its contents are changed 82: * while this stream is being read, those changes will be reflected in the 83: * chars supplied to the reader. Please use caution in changing the 84: * contents of the buffer while this stream is open. 85: * 86: * @param buffer The char array buffer this stream will read from. 87: */ 88: public CharArrayReader(char[] buffer) 89: { 90: this(buffer, 0, buffer.length); 91: } 92: 93: /** 94: * Create a new CharArrayReader that will read chars from the passed 95: * in char array. This stream will read from position 96: * <code>offset</code> in the array for a length of 97: * <code>length</code> chars past <code>offset</code>. If the 98: * stream is reset to a position before <code>offset</code> then 99: * more than <code>length</code> chars can be read from the stream. 100: * The <code>length</code> value should be viewed as the array index 101: * one greater than the last position in the buffer to read. 102: * <p> 103: * Note that this array is not copied. If its contents are changed 104: * while this stream is being read, those changes will be reflected in the 105: * chars supplied to the reader. Please use caution in changing the 106: * contents of the buffer while this stream is open. 107: * 108: * @param buffer The char array buffer this stream will read from. 109: * @param offset The index into the buffer to start reading chars from 110: * @param length The number of chars to read from the buffer 111: */ 112: public CharArrayReader(char[] buffer, int offset, int length) 113: { 114: super(); 115: if (offset < 0 || length < 0 || offset > buffer.length) 116: throw new IllegalArgumentException(); 117: 118: buf = buffer; 119: 120: count = offset + length; 121: if (count > buf.length) 122: count = buf.length; 123: 124: pos = offset; 125: markedPos = pos; 126: } 127: 128: /** 129: * This method closes the stream. 130: */ 131: public void close() 132: { 133: synchronized (lock) 134: { 135: buf = null; 136: } 137: } 138: 139: /** 140: * This method sets the mark position in this stream to the current 141: * position. Note that the <code>readlimit</code> parameter in this 142: * method does nothing as this stream is always capable of 143: * remembering all the chars int it. 144: * <p> 145: * Note that in this class the mark position is set by default to 146: * position 0 in the stream. This is in constrast to some other 147: * stream types where there is no default mark position. 148: * 149: * @param readAheadLimit The number of chars this stream must 150: * remember. This parameter is ignored. 151: * 152: * @exception IOException If an error occurs 153: */ 154: public void mark(int readAheadLimit) throws IOException 155: { 156: synchronized (lock) 157: { 158: if (buf == null) 159: throw new IOException("Stream closed"); 160: // readAheadLimit is ignored per Java Class Lib. book, p. 318. 161: markedPos = pos; 162: } 163: } 164: 165: /** 166: * This method overrides the <code>markSupported</code> method in 167: * <code>Reader</code> in order to return <code>true</code> - 168: * indicating that this stream class supports mark/reset 169: * functionality. 170: * 171: * @return <code>true</code> to indicate that this class supports 172: * mark/reset. 173: */ 174: public boolean markSupported() 175: { 176: return true; 177: } 178: 179: /** 180: * This method reads one char from the stream. The <code>pos</code> 181: * counter is advanced to the next char to be read. The char read 182: * is returned as an int in the range of 0-65535. If the stream 183: * position is already at the end of the buffer, no char is read and 184: * a -1 is returned in order to indicate the end of the stream. 185: * 186: * @return The char read, or -1 if end of stream 187: */ 188: public int read() throws IOException 189: { 190: synchronized (lock) 191: { 192: if (buf == null) 193: throw new IOException("Stream closed"); 194: 195: if (pos < 0) 196: throw new ArrayIndexOutOfBoundsException(pos); 197: 198: if (pos < count) 199: return ((int) buf[pos++]) & 0xFFFF; 200: return -1; 201: } 202: } 203: 204: /** 205: * This method reads chars from the stream and stores them into a 206: * caller supplied buffer. It starts storing the data at index 207: * <code>offset</code> into the buffer and attempts to read 208: * <code>len</code> chars. This method can return before reading 209: * the number of chars requested if the end of the stream is 210: * encountered first. The actual number of chars read is returned. 211: * If no chars can be read because the stream is already at the end 212: * of stream position, a -1 is returned. 213: * <p> 214: * This method does not block. 215: * 216: * @param b The array into which the chars read should be stored. 217: * @param off The offset into the array to start storing chars 218: * @param len The requested number of chars to read 219: * 220: * @return The actual number of chars read, or -1 if end of stream. 221: */ 222: public int read(char[] b, int off, int len) throws IOException 223: { 224: synchronized (lock) 225: { 226: if (buf == null) 227: throw new IOException("Stream closed"); 228: 229: /* Don't need to check pos value, arraycopy will check it. */ 230: if (off < 0 || len < 0 || off + len > b.length) 231: throw new IndexOutOfBoundsException(); 232: 233: if (pos >= count) 234: return -1; 235: 236: int numChars = Math.min(count - pos, len); 237: System.arraycopy(buf, pos, b, off, numChars); 238: pos += numChars; 239: return numChars; 240: } 241: } 242: 243: /** 244: * Return true if more characters are available to be read. 245: * 246: * @return <code>true</code> to indicate that this stream is ready 247: * to be read. 248: * 249: * @specnote The JDK 1.3 API docs are wrong here. This method will 250: * return false if there are no more characters available. 251: */ 252: public boolean ready() throws IOException 253: { 254: if (buf == null) 255: throw new IOException("Stream closed"); 256: 257: return (pos < count); 258: } 259: 260: /** 261: * This method sets the read position in the stream to the mark 262: * point by setting the <code>pos</code> variable equal to the 263: * <code>mark</code> variable. Since a mark can be set anywhere in 264: * the array, the mark/reset methods int this class can be used to 265: * provide random search capabilities for this type of stream. 266: */ 267: public void reset() throws IOException 268: { 269: synchronized (lock) 270: { 271: if (buf == null) 272: throw new IOException("Stream closed"); 273: 274: pos = markedPos; 275: } 276: } 277: 278: /** 279: * This method attempts to skip the requested number of chars in the 280: * input stream. It does this by advancing the <code>pos</code> value by the 281: * specified number of chars. It this would exceed the length of the 282: * buffer, then only enough chars are skipped to position the stream at 283: * the end of the buffer. The actual number of chars skipped is returned. 284: * 285: * @param n The requested number of chars to skip 286: * 287: * @return The actual number of chars skipped. 288: */ 289: public long skip(long n) throws IOException 290: { 291: synchronized (lock) 292: { 293: if (buf == null) 294: throw new IOException("Stream closed"); 295: 296: // Even though the var numChars is a long, in reality it can never 297: // be larger than an int since the result of subtracting 2 positive 298: // ints will always fit in an int. Since we have to return a long 299: // anyway, numChars might as well just be a long. 300: long numChars = Math.min((long) (count - pos), n < 0 ? 0L : n); 301: pos += numChars; 302: return numChars; 303: } 304: } 305: }