Frames | No Frames |
1: /* ByteArrayInputStream.java -- Read an array as a stream 2: Copyright (C) 1998, 1999, 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 bytes to be read as an input stream. 43: * 44: * @author Warren Levy (warrenl@cygnus.com) 45: * @author Aaron M. Renn (arenn@urbanophile.com) 46: */ 47: public class ByteArrayInputStream extends InputStream 48: { 49: /** 50: * The array that contains the data supplied during read operations 51: */ 52: protected byte[] buf; 53: 54: /** 55: * The array index of the next byte 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 mark; 67: 68: /** 69: * This indicates the maximum number of bytes that can be read from this 70: * stream. It is the array index of the position after the last valid 71: * byte in the buffer <code>buf</code> 72: */ 73: protected int count; 74: 75: /** 76: * Create a new ByteArrayInputStream that will read bytes from the passed 77: * in byte 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>ByteArrayInputStream(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: * bytes 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 byte array buffer this stream will read from. 87: */ 88: public ByteArrayInputStream(byte[] buffer) 89: { 90: this(buffer, 0, buffer.length); 91: } 92: 93: /** 94: * Create a new ByteArrayInputStream that will read bytes from the 95: * passed in byte array. This stream will read from position 96: * <code>offset</code> in the array for a length of 97: * <code>length</code> bytes past <code>offset</code>. If the 98: * stream is reset to a position before <code>offset</code> then 99: * more than <code>length</code> bytes 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: * bytes 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 byte array buffer this stream will read from. 109: * @param offset The index into the buffer to start reading bytes from 110: * @param length The number of bytes to read from the buffer 111: */ 112: public ByteArrayInputStream(byte[] buffer, int offset, int length) 113: { 114: if (offset < 0 || length < 0 || offset > buffer.length) 115: throw new IllegalArgumentException(); 116: 117: buf = buffer; 118: 119: count = offset + length; 120: if (count > buf.length) 121: count = buf.length; 122: 123: pos = offset; 124: mark = pos; 125: } 126: 127: /** 128: * This method returns the number of bytes available to be read from this 129: * stream. The value returned will be equal to <code>count - pos</code>. 130: * 131: * @return The number of bytes that can be read from this stream 132: * before blocking, which is all of them 133: */ 134: public synchronized int available() 135: { 136: return count - pos; 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 bytes 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 readLimit The number of bytes this stream must remember. 150: * This parameter is ignored. 151: */ 152: public synchronized void mark(int readLimit) 153: { 154: // readLimit is ignored per Java Class Lib. book, p.220. 155: mark = pos; 156: } 157: 158: /** 159: * This method overrides the <code>markSupported</code> method in 160: * <code>InputStream</code> in order to return <code>true</code> - 161: * indicating that this stream class supports mark/reset 162: * functionality. 163: * 164: * @return <code>true</code> to indicate that this class supports 165: * mark/reset. 166: */ 167: public boolean markSupported() 168: { 169: return true; 170: } 171: 172: /** 173: * This method reads one byte from the stream. The <code>pos</code> 174: * counter is advanced to the next byte to be read. The byte read is 175: * returned as an int in the range of 0-255. If the stream position 176: * is already at the end of the buffer, no byte is read and a -1 is 177: * returned in order to indicate the end of the stream. 178: * 179: * @return The byte read, or -1 if end of stream 180: */ 181: public synchronized int read() 182: { 183: if (pos < count) 184: return ((int) buf[pos++]) & 0xFF; 185: return -1; 186: } 187: 188: /** 189: * This method reads bytes from the stream and stores them into a 190: * caller supplied buffer. It starts storing the data at index 191: * <code>offset</code> into the buffer and attempts to read 192: * <code>len</code> bytes. This method can return before reading 193: * the number of bytes requested if the end of the stream is 194: * encountered first. The actual number of bytes read is returned. 195: * If no bytes can be read because the stream is already at the end 196: * of stream position, a -1 is returned. 197: * <p> 198: * This method does not block. 199: * 200: * @param buffer The array into which the bytes read should be stored. 201: * @param offset The offset into the array to start storing bytes 202: * @param length The requested number of bytes to read 203: * 204: * @return The actual number of bytes read, or -1 if end of stream. 205: */ 206: public synchronized int read(byte[] buffer, int offset, int length) 207: { 208: if (pos >= count) 209: return -1; 210: 211: int numBytes = Math.min(count - pos, length); 212: System.arraycopy(buf, pos, buffer, offset, numBytes); 213: pos += numBytes; 214: return numBytes; 215: } 216: 217: /** 218: * This method sets the read position in the stream to the mark 219: * point by setting the <code>pos</code> variable equal to the 220: * <code>mark</code> variable. Since a mark can be set anywhere in 221: * the array, the mark/reset methods int this class can be used to 222: * provide random search capabilities for this type of stream. 223: */ 224: public synchronized void reset() 225: { 226: pos = mark; 227: } 228: 229: /** 230: * This method attempts to skip the requested number of bytes in the 231: * input stream. It does this by advancing the <code>pos</code> 232: * value by the specified number of bytes. It this would exceed the 233: * length of the buffer, then only enough bytes are skipped to 234: * position the stream at the end of the buffer. The actual number 235: * of bytes skipped is returned. 236: * 237: * @param num The requested number of bytes to skip 238: * 239: * @return The actual number of bytes skipped. 240: */ 241: public synchronized long skip(long num) 242: { 243: // Even though the var numBytes is a long, in reality it can never 244: // be larger than an int since the result of subtracting 2 positive 245: // ints will always fit in an int. Since we have to return a long 246: // anyway, numBytes might as well just be a long. 247: long numBytes = Math.min((long) (count - pos), num < 0 ? 0L : num); 248: pos += numBytes; 249: return numBytes; 250: } 251: }