001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.internal.image;
011:
012: import java.io.*;
013:
014: final class LEDataInputStream extends InputStream {
015: int position;
016: InputStream in;
017:
018: /**
019: * The byte array containing the bytes to read.
020: */
021: protected byte[] buf;
022:
023: /**
024: * The current position within the byte array <code>buf</code>. A value
025: * equal to buf.length indicates no bytes available. A value of
026: * 0 indicates the buffer is full.
027: */
028: protected int pos;
029:
030: public LEDataInputStream(InputStream input) {
031: this (input, 512);
032: }
033:
034: public LEDataInputStream(InputStream input, int bufferSize) {
035: this .in = input;
036: if (bufferSize > 0) {
037: buf = new byte[bufferSize];
038: pos = bufferSize;
039: } else
040: throw new IllegalArgumentException();
041: }
042:
043: public void close() throws IOException {
044: buf = null;
045: if (in != null) {
046: in.close();
047: in = null;
048: }
049: }
050:
051: /**
052: * Answer how many bytes were read.
053: */
054: public int getPosition() {
055: return position;
056: }
057:
058: /**
059: * Answers how many bytes are available for reading without blocking
060: */
061: public int available() throws IOException {
062: if (buf == null)
063: throw new IOException();
064: return (buf.length - pos) + in.available();
065: }
066:
067: /**
068: * Answer the next byte of the input stream.
069: */
070: public int read() throws IOException {
071: if (buf == null)
072: throw new IOException();
073: if (pos < buf.length) {
074: position++;
075: return (buf[pos++] & 0xFF);
076: }
077: int c = in.read();
078: if (c != -1)
079: position++;
080: return c;
081: }
082:
083: /**
084: * Don't imitate the JDK behaviour of reading a random number
085: * of bytes when you can actually read them all.
086: */
087: public int read(byte b[], int off, int len) throws IOException {
088: int read = 0, count;
089: while (read != len
090: && (count = readData(b, off, len - read)) != -1) {
091: off += count;
092: read += count;
093: }
094: position += read;
095: if (read == 0 && read != len)
096: return -1;
097: return read;
098: }
099:
100: /**
101: * Reads at most <code>length</code> bytes from this LEDataInputStream and
102: * stores them in byte array <code>buffer</code> starting at <code>offset</code>.
103: * <p>
104: * Answer the number of bytes actually read or -1 if no bytes were read and
105: * end of stream was encountered. This implementation reads bytes from
106: * the pushback buffer first, then the target stream if more bytes are required
107: * to satisfy <code>count</code>.
108: * </p>
109: * @param buffer the byte array in which to store the read bytes.
110: * @param offset the offset in <code>buffer</code> to store the read bytes.
111: * @param length the maximum number of bytes to store in <code>buffer</code>.
112: *
113: * @return int the number of bytes actually read or -1 if end of stream.
114: *
115: * @exception java.io.IOException if an IOException occurs.
116: */
117: private int readData(byte[] buffer, int offset, int length)
118: throws IOException {
119: if (buf == null)
120: throw new IOException();
121: if (offset < 0 || offset > buffer.length || length < 0
122: || (length > buffer.length - offset)) {
123: throw new ArrayIndexOutOfBoundsException();
124: }
125:
126: int cacheCopied = 0;
127: int newOffset = offset;
128:
129: // Are there pushback bytes available?
130: int available = buf.length - pos;
131: if (available > 0) {
132: cacheCopied = (available >= length) ? length : available;
133: System.arraycopy(buf, pos, buffer, newOffset, cacheCopied);
134: newOffset += cacheCopied;
135: pos += cacheCopied;
136: }
137:
138: // Have we copied enough?
139: if (cacheCopied == length)
140: return length;
141:
142: int inCopied = in.read(buffer, newOffset, length - cacheCopied);
143:
144: if (inCopied > 0)
145: return inCopied + cacheCopied;
146: if (cacheCopied == 0)
147: return inCopied;
148: return cacheCopied;
149: }
150:
151: /**
152: * Answer an integer comprised of the next
153: * four bytes of the input stream.
154: */
155: public int readInt() throws IOException {
156: byte[] buf = new byte[4];
157: read(buf);
158: return ((((((buf[3] & 0xFF) << 24) | (buf[2] & 0xFF)) << 16) | (buf[1] & 0xFF)) << 8)
159: | (buf[0] & 0xFF);
160: }
161:
162: /**
163: * Answer a short comprised of the next
164: * two bytes of the input stream.
165: */
166: public short readShort() throws IOException {
167: byte[] buf = new byte[2];
168: read(buf);
169: return (short) (((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF));
170: }
171:
172: /**
173: * Push back the entire content of the given buffer <code>b</code>.
174: * <p>
175: * The bytes are pushed so that they would be read back b[0], b[1], etc.
176: * If the push back buffer cannot handle the bytes copied from <code>b</code>,
177: * an IOException will be thrown and no byte will be pushed back.
178: * </p>
179: *
180: * @param b the byte array containing bytes to push back into the stream
181: *
182: * @exception java.io.IOException if the pushback buffer is too small
183: */
184: public void unread(byte[] b) throws IOException {
185: int length = b.length;
186: if (length > pos)
187: throw new IOException();
188: position -= length;
189: pos -= length;
190: System.arraycopy(b, 0, buf, pos, length);
191: }
192: }
|