0N/A/*
2362N/A * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.imageio.stream;
0N/A
0N/Aimport java.io.DataInputStream;
0N/Aimport java.io.EOFException;
0N/Aimport java.io.IOException;
0N/Aimport java.nio.ByteOrder;
0N/Aimport java.util.Stack;
0N/Aimport javax.imageio.IIOException;
0N/A
0N/A/**
0N/A * An abstract class implementing the <code>ImageInputStream</code> interface.
0N/A * This class is designed to reduce the number of methods that must
0N/A * be implemented by subclasses.
0N/A *
0N/A * <p> In particular, this class handles most or all of the details of
0N/A * byte order interpretation, buffering, mark/reset, discarding,
0N/A * closing, and disposing.
0N/A */
0N/Apublic abstract class ImageInputStreamImpl implements ImageInputStream {
0N/A
0N/A private Stack markByteStack = new Stack();
0N/A
0N/A private Stack markBitStack = new Stack();
0N/A
0N/A private boolean isClosed = false;
0N/A
0N/A // Length of the buffer used for readFully(type[], int, int)
0N/A private static final int BYTE_BUF_LENGTH = 8192;
0N/A
0N/A /**
0N/A * Byte buffer used for readFully(type[], int, int). Note that this
0N/A * array is also used for bulk reads in readShort(), readInt(), etc, so
0N/A * it should be large enough to hold a primitive value (i.e. >= 8 bytes).
0N/A * Also note that this array is package protected, so that it can be
0N/A * used by ImageOutputStreamImpl in a similar manner.
0N/A */
0N/A byte[] byteBuf = new byte[BYTE_BUF_LENGTH];
0N/A
0N/A /**
0N/A * The byte order of the stream as an instance of the enumeration
0N/A * class <code>java.nio.ByteOrder</code>, where
0N/A * <code>ByteOrder.BIG_ENDIAN</code> indicates network byte order
0N/A * and <code>ByteOrder.LITTLE_ENDIAN</code> indicates the reverse
0N/A * order. By default, the value is
0N/A * <code>ByteOrder.BIG_ENDIAN</code>.
0N/A */
0N/A protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
0N/A
0N/A /**
0N/A * The current read position within the stream. Subclasses are
0N/A * responsible for keeping this value current from any method they
0N/A * override that alters the read position.
0N/A */
0N/A protected long streamPos;
0N/A
0N/A /**
0N/A * The current bit offset within the stream. Subclasses are
0N/A * responsible for keeping this value current from any method they
0N/A * override that alters the bit offset.
0N/A */
0N/A protected int bitOffset;
0N/A
0N/A /**
0N/A * The position prior to which data may be discarded. Seeking
0N/A * to a smaller position is not allowed. <code>flushedPos</code>
0N/A * will always be >= 0.
0N/A */
0N/A protected long flushedPos = 0;
0N/A
0N/A /**
0N/A * Constructs an <code>ImageInputStreamImpl</code>.
0N/A */
0N/A public ImageInputStreamImpl() {
0N/A }
0N/A
0N/A /**
0N/A * Throws an <code>IOException</code> if the stream has been closed.
0N/A * Subclasses may call this method from any of their methods that
0N/A * require the stream not to be closed.
0N/A *
0N/A * @exception IOException if the stream is closed.
0N/A */
0N/A protected final void checkClosed() throws IOException {
0N/A if (isClosed) {
0N/A throw new IOException("closed");
0N/A }
0N/A }
0N/A
0N/A public void setByteOrder(ByteOrder byteOrder) {
0N/A this.byteOrder = byteOrder;
0N/A }
0N/A
0N/A public ByteOrder getByteOrder() {
0N/A return byteOrder;
0N/A }
0N/A
0N/A /**
0N/A * Reads a single byte from the stream and returns it as an
0N/A * <code>int</code> between 0 and 255. If EOF is reached,
0N/A * <code>-1</code> is returned.
0N/A *
0N/A * <p> Subclasses must provide an implementation for this method.
0N/A * The subclass implementation should update the stream position
0N/A * before exiting.
0N/A *
0N/A * <p> The bit offset within the stream must be reset to zero before
0N/A * the read occurs.
0N/A *
0N/A * @return the value of the next byte in the stream, or <code>-1</code>
0N/A * if EOF is reached.
0N/A *
0N/A * @exception IOException if the stream has been closed.
0N/A */
0N/A public abstract int read() throws IOException;
0N/A
0N/A /**
0N/A * A convenience method that calls <code>read(b, 0, b.length)</code>.
0N/A *
0N/A * <p> The bit offset within the stream is reset to zero before
0N/A * the read occurs.
0N/A *
0N/A * @return the number of bytes actually read, or <code>-1</code>
0N/A * to indicate EOF.
0N/A *
0N/A * @exception NullPointerException if <code>b</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if an I/O error occurs.
0N/A */
0N/A public int read(byte[] b) throws IOException {
0N/A return read(b, 0, b.length);
0N/A }
0N/A
0N/A /**
0N/A * Reads up to <code>len</code> bytes from the stream, and stores
0N/A * them into <code>b</code> starting at index <code>off</code>.
0N/A * If no bytes can be read because the end of the stream has been
0N/A * reached, <code>-1</code> is returned.
0N/A *
0N/A * <p> The bit offset within the stream must be reset to zero before
0N/A * the read occurs.
0N/A *
0N/A * <p> Subclasses must provide an implementation for this method.
0N/A * The subclass implementation should update the stream position
0N/A * before exiting.
0N/A *
0N/A * @param b an array of bytes to be written to.
0N/A * @param off the starting position within <code>b</code> to write to.
0N/A * @param len the maximum number of bytes to read.
0N/A *
0N/A * @return the number of bytes actually read, or <code>-1</code>
0N/A * to indicate EOF.
0N/A *
0N/A * @exception IndexOutOfBoundsException if <code>off</code> is
0N/A * negative, <code>len</code> is negative, or <code>off +
0N/A * len</code> is greater than <code>b.length</code>.
0N/A * @exception NullPointerException if <code>b</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if an I/O error occurs.
0N/A */
0N/A public abstract int read(byte[] b, int off, int len) throws IOException;
0N/A
0N/A public void readBytes(IIOByteBuffer buf, int len) throws IOException {
0N/A if (len < 0) {
0N/A throw new IndexOutOfBoundsException("len < 0!");
0N/A }
0N/A if (buf == null) {
0N/A throw new NullPointerException("buf == null!");
0N/A }
0N/A
0N/A byte[] data = new byte[len];
0N/A len = read(data, 0, len);
0N/A
0N/A buf.setData(data);
0N/A buf.setOffset(0);
0N/A buf.setLength(len);
0N/A }
0N/A
0N/A public boolean readBoolean() throws IOException {
0N/A int ch = this.read();
0N/A if (ch < 0) {
0N/A throw new EOFException();
0N/A }
0N/A return (ch != 0);
0N/A }
0N/A
0N/A public byte readByte() throws IOException {
0N/A int ch = this.read();
0N/A if (ch < 0) {
0N/A throw new EOFException();
0N/A }
0N/A return (byte)ch;
0N/A }
0N/A
0N/A public int readUnsignedByte() throws IOException {
0N/A int ch = this.read();
0N/A if (ch < 0) {
0N/A throw new EOFException();
0N/A }
0N/A return ch;
0N/A }
0N/A
0N/A public short readShort() throws IOException {
0N/A if (read(byteBuf, 0, 2) < 0) {
0N/A throw new EOFException();
0N/A }
0N/A
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A return (short)
0N/A (((byteBuf[0] & 0xff) << 8) | ((byteBuf[1] & 0xff) << 0));
0N/A } else {
0N/A return (short)
0N/A (((byteBuf[1] & 0xff) << 8) | ((byteBuf[0] & 0xff) << 0));
0N/A }
0N/A }
0N/A
0N/A public int readUnsignedShort() throws IOException {
0N/A return ((int)readShort()) & 0xffff;
0N/A }
0N/A
0N/A public char readChar() throws IOException {
0N/A return (char)readShort();
0N/A }
0N/A
0N/A public int readInt() throws IOException {
0N/A if (read(byteBuf, 0, 4) < 0) {
0N/A throw new EOFException();
0N/A }
0N/A
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A return
0N/A (((byteBuf[0] & 0xff) << 24) | ((byteBuf[1] & 0xff) << 16) |
0N/A ((byteBuf[2] & 0xff) << 8) | ((byteBuf[3] & 0xff) << 0));
0N/A } else {
0N/A return
0N/A (((byteBuf[3] & 0xff) << 24) | ((byteBuf[2] & 0xff) << 16) |
0N/A ((byteBuf[1] & 0xff) << 8) | ((byteBuf[0] & 0xff) << 0));
0N/A }
0N/A }
0N/A
0N/A public long readUnsignedInt() throws IOException {
0N/A return ((long)readInt()) & 0xffffffffL;
0N/A }
0N/A
0N/A public long readLong() throws IOException {
0N/A // REMIND: Once 6277756 is fixed, we should do a bulk read of all 8
0N/A // bytes here as we do in readShort() and readInt() for even better
0N/A // performance (see 6347575 for details).
0N/A int i1 = readInt();
0N/A int i2 = readInt();
0N/A
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A return ((long)i1 << 32) + (i2 & 0xFFFFFFFFL);
0N/A } else {
0N/A return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
0N/A }
0N/A }
0N/A
0N/A public float readFloat() throws IOException {
0N/A return Float.intBitsToFloat(readInt());
0N/A }
0N/A
0N/A public double readDouble() throws IOException {
0N/A return Double.longBitsToDouble(readLong());
0N/A }
0N/A
0N/A public String readLine() throws IOException {
0N/A StringBuffer input = new StringBuffer();
0N/A int c = -1;
0N/A boolean eol = false;
0N/A
0N/A while (!eol) {
0N/A switch (c = read()) {
0N/A case -1:
0N/A case '\n':
0N/A eol = true;
0N/A break;
0N/A case '\r':
0N/A eol = true;
0N/A long cur = getStreamPosition();
0N/A if ((read()) != '\n') {
0N/A seek(cur);
0N/A }
0N/A break;
0N/A default:
0N/A input.append((char)c);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A if ((c == -1) && (input.length() == 0)) {
0N/A return null;
0N/A }
0N/A return input.toString();
0N/A }
0N/A
0N/A public String readUTF() throws IOException {
0N/A this.bitOffset = 0;
0N/A
0N/A // Fix 4494369: method ImageInputStreamImpl.readUTF()
0N/A // does not work as specified (it should always assume
0N/A // network byte order).
0N/A ByteOrder oldByteOrder = getByteOrder();
0N/A setByteOrder(ByteOrder.BIG_ENDIAN);
0N/A
0N/A String ret;
0N/A try {
0N/A ret = DataInputStream.readUTF(this);
0N/A } catch (IOException e) {
0N/A // Restore the old byte order even if an exception occurs
0N/A setByteOrder(oldByteOrder);
0N/A throw e;
0N/A }
0N/A
0N/A setByteOrder(oldByteOrder);
0N/A return ret;
0N/A }
0N/A
0N/A public void readFully(byte[] b, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > b.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nbytes = read(b, off, len);
0N/A if (nbytes == -1) {
0N/A throw new EOFException();
0N/A }
0N/A off += nbytes;
0N/A len -= nbytes;
0N/A }
0N/A }
0N/A
0N/A public void readFully(byte[] b) throws IOException {
0N/A readFully(b, 0, b.length);
0N/A }
0N/A
0N/A public void readFully(short[] s, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > s.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > s.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nelts = Math.min(len, byteBuf.length/2);
0N/A readFully(byteBuf, 0, nelts*2);
0N/A toShorts(byteBuf, s, off, nelts);
0N/A off += nelts;
0N/A len -= nelts;
0N/A }
0N/A }
0N/A
0N/A public void readFully(char[] c, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > c.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > c.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nelts = Math.min(len, byteBuf.length/2);
0N/A readFully(byteBuf, 0, nelts*2);
0N/A toChars(byteBuf, c, off, nelts);
0N/A off += nelts;
0N/A len -= nelts;
0N/A }
0N/A }
0N/A
0N/A public void readFully(int[] i, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > i.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > i.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nelts = Math.min(len, byteBuf.length/4);
0N/A readFully(byteBuf, 0, nelts*4);
0N/A toInts(byteBuf, i, off, nelts);
0N/A off += nelts;
0N/A len -= nelts;
0N/A }
0N/A }
0N/A
0N/A public void readFully(long[] l, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > l.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > l.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nelts = Math.min(len, byteBuf.length/8);
0N/A readFully(byteBuf, 0, nelts*8);
0N/A toLongs(byteBuf, l, off, nelts);
0N/A off += nelts;
0N/A len -= nelts;
0N/A }
0N/A }
0N/A
0N/A public void readFully(float[] f, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > f.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > f.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nelts = Math.min(len, byteBuf.length/4);
0N/A readFully(byteBuf, 0, nelts*4);
0N/A toFloats(byteBuf, f, off, nelts);
0N/A off += nelts;
0N/A len -= nelts;
0N/A }
0N/A }
0N/A
0N/A public void readFully(double[] d, int off, int len) throws IOException {
0N/A // Fix 4430357 - if off + len < 0, overflow occurred
0N/A if (off < 0 || len < 0 || off + len > d.length || off + len < 0) {
0N/A throw new IndexOutOfBoundsException
0N/A ("off < 0 || len < 0 || off + len > d.length!");
0N/A }
0N/A
0N/A while (len > 0) {
0N/A int nelts = Math.min(len, byteBuf.length/8);
0N/A readFully(byteBuf, 0, nelts*8);
0N/A toDoubles(byteBuf, d, off, nelts);
0N/A off += nelts;
0N/A len -= nelts;
0N/A }
0N/A }
0N/A
0N/A private void toShorts(byte[] b, short[] s, int off, int len) {
0N/A int boff = 0;
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff];
0N/A int b1 = b[boff + 1] & 0xff;
0N/A s[off + j] = (short)((b0 << 8) | b1);
0N/A boff += 2;
0N/A }
0N/A } else {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff + 1];
0N/A int b1 = b[boff] & 0xff;
0N/A s[off + j] = (short)((b0 << 8) | b1);
0N/A boff += 2;
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void toChars(byte[] b, char[] c, int off, int len) {
0N/A int boff = 0;
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff];
0N/A int b1 = b[boff + 1] & 0xff;
0N/A c[off + j] = (char)((b0 << 8) | b1);
0N/A boff += 2;
0N/A }
0N/A } else {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff + 1];
0N/A int b1 = b[boff] & 0xff;
0N/A c[off + j] = (char)((b0 << 8) | b1);
0N/A boff += 2;
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void toInts(byte[] b, int[] i, int off, int len) {
0N/A int boff = 0;
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff];
0N/A int b1 = b[boff + 1] & 0xff;
0N/A int b2 = b[boff + 2] & 0xff;
0N/A int b3 = b[boff + 3] & 0xff;
0N/A i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A boff += 4;
0N/A }
0N/A } else {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff + 3];
0N/A int b1 = b[boff + 2] & 0xff;
0N/A int b2 = b[boff + 1] & 0xff;
0N/A int b3 = b[boff] & 0xff;
0N/A i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A boff += 4;
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void toLongs(byte[] b, long[] l, int off, int len) {
0N/A int boff = 0;
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff];
0N/A int b1 = b[boff + 1] & 0xff;
0N/A int b2 = b[boff + 2] & 0xff;
0N/A int b3 = b[boff + 3] & 0xff;
0N/A int b4 = b[boff + 4];
0N/A int b5 = b[boff + 5] & 0xff;
0N/A int b6 = b[boff + 6] & 0xff;
0N/A int b7 = b[boff + 7] & 0xff;
0N/A
0N/A int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
0N/A
0N/A l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
0N/A boff += 8;
0N/A }
0N/A } else {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff + 7];
0N/A int b1 = b[boff + 6] & 0xff;
0N/A int b2 = b[boff + 5] & 0xff;
0N/A int b3 = b[boff + 4] & 0xff;
0N/A int b4 = b[boff + 3];
0N/A int b5 = b[boff + 2] & 0xff;
0N/A int b6 = b[boff + 1] & 0xff;
0N/A int b7 = b[boff] & 0xff;
0N/A
0N/A int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
0N/A
0N/A l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
0N/A boff += 8;
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void toFloats(byte[] b, float[] f, int off, int len) {
0N/A int boff = 0;
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff];
0N/A int b1 = b[boff + 1] & 0xff;
0N/A int b2 = b[boff + 2] & 0xff;
0N/A int b3 = b[boff + 3] & 0xff;
0N/A int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A f[off + j] = Float.intBitsToFloat(i);
0N/A boff += 4;
0N/A }
0N/A } else {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff + 3];
0N/A int b1 = b[boff + 2] & 0xff;
0N/A int b2 = b[boff + 1] & 0xff;
0N/A int b3 = b[boff + 0] & 0xff;
0N/A int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A f[off + j] = Float.intBitsToFloat(i);
0N/A boff += 4;
0N/A }
0N/A }
0N/A }
0N/A
0N/A private void toDoubles(byte[] b, double[] d, int off, int len) {
0N/A int boff = 0;
0N/A if (byteOrder == ByteOrder.BIG_ENDIAN) {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff];
0N/A int b1 = b[boff + 1] & 0xff;
0N/A int b2 = b[boff + 2] & 0xff;
0N/A int b3 = b[boff + 3] & 0xff;
0N/A int b4 = b[boff + 4];
0N/A int b5 = b[boff + 5] & 0xff;
0N/A int b6 = b[boff + 6] & 0xff;
0N/A int b7 = b[boff + 7] & 0xff;
0N/A
0N/A int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
0N/A long l = ((long)i0 << 32) | (i1 & 0xffffffffL);
0N/A
0N/A d[off + j] = Double.longBitsToDouble(l);
0N/A boff += 8;
0N/A }
0N/A } else {
0N/A for (int j = 0; j < len; j++) {
0N/A int b0 = b[boff + 7];
0N/A int b1 = b[boff + 6] & 0xff;
0N/A int b2 = b[boff + 5] & 0xff;
0N/A int b3 = b[boff + 4] & 0xff;
0N/A int b4 = b[boff + 3];
0N/A int b5 = b[boff + 2] & 0xff;
0N/A int b6 = b[boff + 1] & 0xff;
0N/A int b7 = b[boff] & 0xff;
0N/A
0N/A int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
0N/A int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
0N/A long l = ((long)i0 << 32) | (i1 & 0xffffffffL);
0N/A
0N/A d[off + j] = Double.longBitsToDouble(l);
0N/A boff += 8;
0N/A }
0N/A }
0N/A }
0N/A
0N/A public long getStreamPosition() throws IOException {
0N/A checkClosed();
0N/A return streamPos;
0N/A }
0N/A
0N/A public int getBitOffset() throws IOException {
0N/A checkClosed();
0N/A return bitOffset;
0N/A }
0N/A
0N/A public void setBitOffset(int bitOffset) throws IOException {
0N/A checkClosed();
0N/A if (bitOffset < 0 || bitOffset > 7) {
0N/A throw new IllegalArgumentException("bitOffset must be betwwen 0 and 7!");
0N/A }
0N/A this.bitOffset = bitOffset;
0N/A }
0N/A
0N/A public int readBit() throws IOException {
0N/A checkClosed();
0N/A
0N/A // Compute final bit offset before we call read() and seek()
0N/A int newBitOffset = (this.bitOffset + 1) & 0x7;
0N/A
0N/A int val = read();
0N/A if (val == -1) {
0N/A throw new EOFException();
0N/A }
0N/A
0N/A if (newBitOffset != 0) {
0N/A // Move byte position back if in the middle of a byte
0N/A seek(getStreamPosition() - 1);
0N/A // Shift the bit to be read to the rightmost position
0N/A val >>= 8 - newBitOffset;
0N/A }
0N/A this.bitOffset = newBitOffset;
0N/A
0N/A return val & 0x1;
0N/A }
0N/A
0N/A public long readBits(int numBits) throws IOException {
0N/A checkClosed();
0N/A
0N/A if (numBits < 0 || numBits > 64) {
0N/A throw new IllegalArgumentException();
0N/A }
0N/A if (numBits == 0) {
0N/A return 0L;
0N/A }
0N/A
0N/A // Have to read additional bits on the left equal to the bit offset
0N/A int bitsToRead = numBits + bitOffset;
0N/A
0N/A // Compute final bit offset before we call read() and seek()
0N/A int newBitOffset = (this.bitOffset + numBits) & 0x7;
0N/A
0N/A // Read a byte at a time, accumulate
0N/A long accum = 0L;
0N/A while (bitsToRead > 0) {
0N/A int val = read();
0N/A if (val == -1) {
0N/A throw new EOFException();
0N/A }
0N/A
0N/A accum <<= 8;
0N/A accum |= val;
0N/A bitsToRead -= 8;
0N/A }
0N/A
0N/A // Move byte position back if in the middle of a byte
0N/A if (newBitOffset != 0) {
0N/A seek(getStreamPosition() - 1);
0N/A }
0N/A this.bitOffset = newBitOffset;
0N/A
0N/A // Shift away unwanted bits on the right.
0N/A accum >>>= (-bitsToRead); // Negative of bitsToRead == extra bits read
0N/A
0N/A // Mask out unwanted bits on the left
0N/A accum &= (-1L >>> (64 - numBits));
0N/A
0N/A return accum;
0N/A }
0N/A
0N/A /**
0N/A * Returns <code>-1L</code> to indicate that the stream has unknown
0N/A * length. Subclasses must override this method to provide actual
0N/A * length information.
0N/A *
0N/A * @return -1L to indicate unknown length.
0N/A */
0N/A public long length() {
0N/A return -1L;
0N/A }
0N/A
0N/A /**
0N/A * Advances the current stream position by calling
0N/A * <code>seek(getStreamPosition() + n)</code>.
0N/A *
0N/A * <p> The bit offset is reset to zero.
0N/A *
0N/A * @param n the number of bytes to seek forward.
0N/A *
0N/A * @return an <code>int</code> representing the number of bytes
0N/A * skipped.
0N/A *
0N/A * @exception IOException if <code>getStreamPosition</code>
0N/A * throws an <code>IOException</code> when computing either
0N/A * the starting or ending position.
0N/A */
0N/A public int skipBytes(int n) throws IOException {
0N/A long pos = getStreamPosition();
0N/A seek(pos + n);
0N/A return (int)(getStreamPosition() - pos);
0N/A }
0N/A
0N/A /**
0N/A * Advances the current stream position by calling
0N/A * <code>seek(getStreamPosition() + n)</code>.
0N/A *
0N/A * <p> The bit offset is reset to zero.
0N/A *
0N/A * @param n the number of bytes to seek forward.
0N/A *
0N/A * @return a <code>long</code> representing the number of bytes
0N/A * skipped.
0N/A *
0N/A * @exception IOException if <code>getStreamPosition</code>
0N/A * throws an <code>IOException</code> when computing either
0N/A * the starting or ending position.
0N/A */
0N/A public long skipBytes(long n) throws IOException {
0N/A long pos = getStreamPosition();
0N/A seek(pos + n);
0N/A return getStreamPosition() - pos;
0N/A }
0N/A
0N/A public void seek(long pos) throws IOException {
0N/A checkClosed();
0N/A
0N/A // This test also covers pos < 0
0N/A if (pos < flushedPos) {
0N/A throw new IndexOutOfBoundsException("pos < flushedPos!");
0N/A }
0N/A
0N/A this.streamPos = pos;
0N/A this.bitOffset = 0;
0N/A }
0N/A
0N/A /**
0N/A * Pushes the current stream position onto a stack of marked
0N/A * positions.
0N/A */
0N/A public void mark() {
0N/A try {
215N/A markByteStack.push(Long.valueOf(getStreamPosition()));
215N/A markBitStack.push(Integer.valueOf(getBitOffset()));
0N/A } catch (IOException e) {
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Resets the current stream byte and bit positions from the stack
0N/A * of marked positions.
0N/A *
0N/A * <p> An <code>IOException</code> will be thrown if the previous
0N/A * marked position lies in the discarded portion of the stream.
0N/A *
0N/A * @exception IOException if an I/O error occurs.
0N/A */
0N/A public void reset() throws IOException {
0N/A if (markByteStack.empty()) {
0N/A return;
0N/A }
0N/A
0N/A long pos = ((Long)markByteStack.pop()).longValue();
0N/A if (pos < flushedPos) {
0N/A throw new IIOException
0N/A ("Previous marked position has been discarded!");
0N/A }
0N/A seek(pos);
0N/A
0N/A int offset = ((Integer)markBitStack.pop()).intValue();
0N/A setBitOffset(offset);
0N/A }
0N/A
0N/A public void flushBefore(long pos) throws IOException {
0N/A checkClosed();
0N/A if (pos < flushedPos) {
0N/A throw new IndexOutOfBoundsException("pos < flushedPos!");
0N/A }
0N/A if (pos > getStreamPosition()) {
0N/A throw new IndexOutOfBoundsException("pos > getStreamPosition()!");
0N/A }
0N/A // Invariant: flushedPos >= 0
0N/A flushedPos = pos;
0N/A }
0N/A
0N/A public void flush() throws IOException {
0N/A flushBefore(getStreamPosition());
0N/A }
0N/A
0N/A public long getFlushedPosition() {
0N/A return flushedPos;
0N/A }
0N/A
0N/A /**
0N/A * Default implementation returns false. Subclasses should
0N/A * override this if they cache data.
0N/A */
0N/A public boolean isCached() {
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Default implementation returns false. Subclasses should
0N/A * override this if they cache data in main memory.
0N/A */
0N/A public boolean isCachedMemory() {
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Default implementation returns false. Subclasses should
0N/A * override this if they cache data in a temporary file.
0N/A */
0N/A public boolean isCachedFile() {
0N/A return false;
0N/A }
0N/A
0N/A public void close() throws IOException {
0N/A checkClosed();
0N/A
0N/A isClosed = true;
0N/A }
0N/A
0N/A /**
0N/A * Finalizes this object prior to garbage collection. The
0N/A * <code>close</code> method is called to close any open input
0N/A * source. This method should not be called from application
0N/A * code.
0N/A *
0N/A * @exception Throwable if an error occurs during superclass
0N/A * finalization.
0N/A */
0N/A protected void finalize() throws Throwable {
0N/A if (!isClosed) {
0N/A try {
0N/A close();
0N/A } catch (IOException e) {
0N/A }
0N/A }
0N/A super.finalize();
0N/A }
0N/A}