| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package javax.imageio.stream;  | 
 | 
 | 
 | 
import java.io.DataInputStream;  | 
 | 
import java.io.EOFException;  | 
 | 
import java.io.IOException;  | 
 | 
import java.nio.ByteOrder;  | 
 | 
import java.util.Stack;  | 
 | 
import javax.imageio.IIOException;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public abstract class ImageInputStreamImpl implements ImageInputStream { | 
 | 
 | 
 | 
    private Stack markByteStack = new Stack();  | 
 | 
 | 
 | 
    private Stack markBitStack = new Stack();  | 
 | 
 | 
 | 
    private boolean isClosed = false;  | 
 | 
 | 
 | 
      | 
 | 
    private static final int BYTE_BUF_LENGTH = 8192;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    byte[] byteBuf = new byte[BYTE_BUF_LENGTH];  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected long streamPos;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected int bitOffset;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected long flushedPos = 0;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public ImageInputStreamImpl() { | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected final void checkClosed() throws IOException { | 
 | 
        if (isClosed) { | 
 | 
            throw new IOException("closed"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setByteOrder(ByteOrder byteOrder) { | 
 | 
        this.byteOrder = byteOrder;  | 
 | 
    }  | 
 | 
 | 
 | 
    public ByteOrder getByteOrder() { | 
 | 
        return byteOrder;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public abstract int read() throws IOException;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int read(byte[] b) throws IOException { | 
 | 
        return read(b, 0, b.length);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public abstract int read(byte[] b, int off, int len) throws IOException;  | 
 | 
 | 
 | 
    public void readBytes(IIOByteBuffer buf, int len) throws IOException { | 
 | 
        if (len < 0) { | 
 | 
            throw new IndexOutOfBoundsException("len < 0!"); | 
 | 
        }  | 
 | 
        if (buf == null) { | 
 | 
            throw new NullPointerException("buf == null!"); | 
 | 
        }  | 
 | 
 | 
 | 
        byte[] data = new byte[len];  | 
 | 
        len = read(data, 0, len);  | 
 | 
 | 
 | 
        buf.setData(data);  | 
 | 
        buf.setOffset(0);  | 
 | 
        buf.setLength(len);  | 
 | 
    }  | 
 | 
 | 
 | 
    public boolean readBoolean() throws IOException { | 
 | 
        int ch = this.read();  | 
 | 
        if (ch < 0) { | 
 | 
            throw new EOFException();  | 
 | 
        }  | 
 | 
        return (ch != 0);  | 
 | 
    }  | 
 | 
 | 
 | 
    public byte readByte() throws IOException { | 
 | 
        int ch = this.read();  | 
 | 
        if (ch < 0) { | 
 | 
            throw new EOFException();  | 
 | 
        }  | 
 | 
        return (byte)ch;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int readUnsignedByte() throws IOException { | 
 | 
        int ch = this.read();  | 
 | 
        if (ch < 0) { | 
 | 
            throw new EOFException();  | 
 | 
        }  | 
 | 
        return ch;  | 
 | 
    }  | 
 | 
 | 
 | 
    public short readShort() throws IOException { | 
 | 
        if (read(byteBuf, 0, 2) != 2) { | 
 | 
            throw new EOFException();  | 
 | 
        }  | 
 | 
 | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            return (short)  | 
 | 
                (((byteBuf[0] & 0xff) << 8) | ((byteBuf[1] & 0xff) << 0));  | 
 | 
        } else { | 
 | 
            return (short)  | 
 | 
                (((byteBuf[1] & 0xff) << 8) | ((byteBuf[0] & 0xff) << 0));  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public int readUnsignedShort() throws IOException { | 
 | 
        return ((int)readShort()) & 0xffff;  | 
 | 
    }  | 
 | 
 | 
 | 
    public char readChar() throws IOException { | 
 | 
        return (char)readShort();  | 
 | 
    }  | 
 | 
 | 
 | 
    public int readInt() throws IOException { | 
 | 
        if (read(byteBuf, 0, 4) !=  4) { | 
 | 
            throw new EOFException();  | 
 | 
        }  | 
 | 
 | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            return  | 
 | 
                (((byteBuf[0] & 0xff) << 24) | ((byteBuf[1] & 0xff) << 16) |  | 
 | 
                 ((byteBuf[2] & 0xff) <<  8) | ((byteBuf[3] & 0xff) <<  0));  | 
 | 
        } else { | 
 | 
            return  | 
 | 
                (((byteBuf[3] & 0xff) << 24) | ((byteBuf[2] & 0xff) << 16) |  | 
 | 
                 ((byteBuf[1] & 0xff) <<  8) | ((byteBuf[0] & 0xff) <<  0));  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public long readUnsignedInt() throws IOException { | 
 | 
        return ((long)readInt()) & 0xffffffffL;  | 
 | 
    }  | 
 | 
 | 
 | 
    public long readLong() throws IOException { | 
 | 
        // REMIND: Once 6277756 is fixed, we should do a bulk read of all 8  | 
 | 
        // bytes here as we do in readShort() and readInt() for even better  | 
 | 
          | 
 | 
        int i1 = readInt();  | 
 | 
        int i2 = readInt();  | 
 | 
 | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            return ((long)i1 << 32) + (i2 & 0xFFFFFFFFL);  | 
 | 
        } else { | 
 | 
            return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public float readFloat() throws IOException { | 
 | 
        return Float.intBitsToFloat(readInt());  | 
 | 
    }  | 
 | 
 | 
 | 
    public double readDouble() throws IOException { | 
 | 
        return Double.longBitsToDouble(readLong());  | 
 | 
    }  | 
 | 
 | 
 | 
    public String readLine() throws IOException { | 
 | 
        StringBuffer input = new StringBuffer();  | 
 | 
        int c = -1;  | 
 | 
        boolean eol = false;  | 
 | 
 | 
 | 
        while (!eol) { | 
 | 
            switch (c = read()) { | 
 | 
            case -1:  | 
 | 
            case '\n':  | 
 | 
                eol = true;  | 
 | 
                break;  | 
 | 
            case '\r':  | 
 | 
                eol = true;  | 
 | 
                long cur = getStreamPosition();  | 
 | 
                if ((read()) != '\n') { | 
 | 
                    seek(cur);  | 
 | 
                }  | 
 | 
                break;  | 
 | 
            default:  | 
 | 
                input.append((char)c);  | 
 | 
                break;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        if ((c == -1) && (input.length() == 0)) { | 
 | 
            return null;  | 
 | 
        }  | 
 | 
        return input.toString();  | 
 | 
    }  | 
 | 
 | 
 | 
    public String readUTF() throws IOException { | 
 | 
        this.bitOffset = 0;  | 
 | 
 | 
 | 
        // Fix 4494369: method ImageInputStreamImpl.readUTF()  | 
 | 
        // does not work as specified (it should always assume  | 
 | 
          | 
 | 
        ByteOrder oldByteOrder = getByteOrder();  | 
 | 
        setByteOrder(ByteOrder.BIG_ENDIAN);  | 
 | 
 | 
 | 
        String ret;  | 
 | 
        try { | 
 | 
            ret = DataInputStream.readUTF(this);  | 
 | 
        } catch (IOException e) { | 
 | 
              | 
 | 
            setByteOrder(oldByteOrder);  | 
 | 
            throw e;  | 
 | 
        }  | 
 | 
 | 
 | 
        setByteOrder(oldByteOrder);  | 
 | 
        return ret;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(byte[] b, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > b.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > b.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nbytes = read(b, off, len);  | 
 | 
            if (nbytes == -1) { | 
 | 
                throw new EOFException();  | 
 | 
            }  | 
 | 
            off += nbytes;  | 
 | 
            len -= nbytes;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(byte[] b) throws IOException { | 
 | 
        readFully(b, 0, b.length);  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(short[] s, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > s.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > s.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nelts = Math.min(len, byteBuf.length/2);  | 
 | 
            readFully(byteBuf, 0, nelts*2);  | 
 | 
            toShorts(byteBuf, s, off, nelts);  | 
 | 
            off += nelts;  | 
 | 
            len -= nelts;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(char[] c, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > c.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > c.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nelts = Math.min(len, byteBuf.length/2);  | 
 | 
            readFully(byteBuf, 0, nelts*2);  | 
 | 
            toChars(byteBuf, c, off, nelts);  | 
 | 
            off += nelts;  | 
 | 
            len -= nelts;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(int[] i, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > i.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > i.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nelts = Math.min(len, byteBuf.length/4);  | 
 | 
            readFully(byteBuf, 0, nelts*4);  | 
 | 
            toInts(byteBuf, i, off, nelts);  | 
 | 
            off += nelts;  | 
 | 
            len -= nelts;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(long[] l, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > l.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > l.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nelts = Math.min(len, byteBuf.length/8);  | 
 | 
            readFully(byteBuf, 0, nelts*8);  | 
 | 
            toLongs(byteBuf, l, off, nelts);  | 
 | 
            off += nelts;  | 
 | 
            len -= nelts;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(float[] f, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > f.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > f.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nelts = Math.min(len, byteBuf.length/4);  | 
 | 
            readFully(byteBuf, 0, nelts*4);  | 
 | 
            toFloats(byteBuf, f, off, nelts);  | 
 | 
            off += nelts;  | 
 | 
            len -= nelts;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void readFully(double[] d, int off, int len) throws IOException { | 
 | 
          | 
 | 
        if (off < 0 || len < 0 || off + len > d.length || off + len < 0) { | 
 | 
            throw new IndexOutOfBoundsException  | 
 | 
                ("off < 0 || len < 0 || off + len > d.length!"); | 
 | 
        }  | 
 | 
 | 
 | 
        while (len > 0) { | 
 | 
            int nelts = Math.min(len, byteBuf.length/8);  | 
 | 
            readFully(byteBuf, 0, nelts*8);  | 
 | 
            toDoubles(byteBuf, d, off, nelts);  | 
 | 
            off += nelts;  | 
 | 
            len -= nelts;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void toShorts(byte[] b, short[] s, int off, int len) { | 
 | 
        int boff = 0;  | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff];  | 
 | 
                int b1 = b[boff + 1] & 0xff;  | 
 | 
                s[off + j] = (short)((b0 << 8) | b1);  | 
 | 
                boff += 2;  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff + 1];  | 
 | 
                int b1 = b[boff] & 0xff;  | 
 | 
                s[off + j] = (short)((b0 << 8) | b1);  | 
 | 
                boff += 2;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void toChars(byte[] b, char[] c, int off, int len) { | 
 | 
        int boff = 0;  | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff];  | 
 | 
                int b1 = b[boff + 1] & 0xff;  | 
 | 
                c[off + j] = (char)((b0 << 8) | b1);  | 
 | 
                boff += 2;  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff + 1];  | 
 | 
                int b1 = b[boff] & 0xff;  | 
 | 
                c[off + j] = (char)((b0 << 8) | b1);  | 
 | 
                boff += 2;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void toInts(byte[] b, int[] i, int off, int len) { | 
 | 
        int boff = 0;  | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff];  | 
 | 
                int b1 = b[boff + 1] & 0xff;  | 
 | 
                int b2 = b[boff + 2] & 0xff;  | 
 | 
                int b3 = b[boff + 3] & 0xff;  | 
 | 
                i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                boff += 4;  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff + 3];  | 
 | 
                int b1 = b[boff + 2] & 0xff;  | 
 | 
                int b2 = b[boff + 1] & 0xff;  | 
 | 
                int b3 = b[boff] & 0xff;  | 
 | 
                i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                boff += 4;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void toLongs(byte[] b, long[] l, int off, int len) { | 
 | 
        int boff = 0;  | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff];  | 
 | 
                int b1 = b[boff + 1] & 0xff;  | 
 | 
                int b2 = b[boff + 2] & 0xff;  | 
 | 
                int b3 = b[boff + 3] & 0xff;  | 
 | 
                int b4 = b[boff + 4];  | 
 | 
                int b5 = b[boff + 5] & 0xff;  | 
 | 
                int b6 = b[boff + 6] & 0xff;  | 
 | 
                int b7 = b[boff + 7] & 0xff;  | 
 | 
 | 
 | 
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;  | 
 | 
 | 
 | 
                l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);  | 
 | 
                boff += 8;  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff + 7];  | 
 | 
                int b1 = b[boff + 6] & 0xff;  | 
 | 
                int b2 = b[boff + 5] & 0xff;  | 
 | 
                int b3 = b[boff + 4] & 0xff;  | 
 | 
                int b4 = b[boff + 3];  | 
 | 
                int b5 = b[boff + 2] & 0xff;  | 
 | 
                int b6 = b[boff + 1] & 0xff;  | 
 | 
                int b7 = b[boff]     & 0xff;  | 
 | 
 | 
 | 
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;  | 
 | 
 | 
 | 
                l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);  | 
 | 
                boff += 8;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void toFloats(byte[] b, float[] f, int off, int len) { | 
 | 
        int boff = 0;  | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff];  | 
 | 
                int b1 = b[boff + 1] & 0xff;  | 
 | 
                int b2 = b[boff + 2] & 0xff;  | 
 | 
                int b3 = b[boff + 3] & 0xff;  | 
 | 
                int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                f[off + j] = Float.intBitsToFloat(i);  | 
 | 
                boff += 4;  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff + 3];  | 
 | 
                int b1 = b[boff + 2] & 0xff;  | 
 | 
                int b2 = b[boff + 1] & 0xff;  | 
 | 
                int b3 = b[boff + 0] & 0xff;  | 
 | 
                int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                f[off + j] = Float.intBitsToFloat(i);  | 
 | 
                boff += 4;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void toDoubles(byte[] b, double[] d, int off, int len) { | 
 | 
        int boff = 0;  | 
 | 
        if (byteOrder == ByteOrder.BIG_ENDIAN) { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff];  | 
 | 
                int b1 = b[boff + 1] & 0xff;  | 
 | 
                int b2 = b[boff + 2] & 0xff;  | 
 | 
                int b3 = b[boff + 3] & 0xff;  | 
 | 
                int b4 = b[boff + 4];  | 
 | 
                int b5 = b[boff + 5] & 0xff;  | 
 | 
                int b6 = b[boff + 6] & 0xff;  | 
 | 
                int b7 = b[boff + 7] & 0xff;  | 
 | 
 | 
 | 
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;  | 
 | 
                long l = ((long)i0 << 32) | (i1 & 0xffffffffL);  | 
 | 
 | 
 | 
                d[off + j] = Double.longBitsToDouble(l);  | 
 | 
                boff += 8;  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            for (int j = 0; j < len; j++) { | 
 | 
                int b0 = b[boff + 7];  | 
 | 
                int b1 = b[boff + 6] & 0xff;  | 
 | 
                int b2 = b[boff + 5] & 0xff;  | 
 | 
                int b3 = b[boff + 4] & 0xff;  | 
 | 
                int b4 = b[boff + 3];  | 
 | 
                int b5 = b[boff + 2] & 0xff;  | 
 | 
                int b6 = b[boff + 1] & 0xff;  | 
 | 
                int b7 = b[boff] & 0xff;  | 
 | 
 | 
 | 
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;  | 
 | 
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;  | 
 | 
                long l = ((long)i0 << 32) | (i1 & 0xffffffffL);  | 
 | 
 | 
 | 
                d[off + j] = Double.longBitsToDouble(l);  | 
 | 
                boff += 8;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public long getStreamPosition() throws IOException { | 
 | 
        checkClosed();  | 
 | 
        return streamPos;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getBitOffset() throws IOException { | 
 | 
        checkClosed();  | 
 | 
        return bitOffset;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setBitOffset(int bitOffset) throws IOException { | 
 | 
        checkClosed();  | 
 | 
        if (bitOffset < 0 || bitOffset > 7) { | 
 | 
            throw new IllegalArgumentException("bitOffset must be betwwen 0 and 7!"); | 
 | 
        }  | 
 | 
        this.bitOffset = bitOffset;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int readBit() throws IOException { | 
 | 
        checkClosed();  | 
 | 
 | 
 | 
          | 
 | 
        int newBitOffset = (this.bitOffset + 1) & 0x7;  | 
 | 
 | 
 | 
        int val = read();  | 
 | 
        if (val == -1) { | 
 | 
            throw new EOFException();  | 
 | 
        }  | 
 | 
 | 
 | 
        if (newBitOffset != 0) { | 
 | 
              | 
 | 
            seek(getStreamPosition() - 1);  | 
 | 
              | 
 | 
            val >>= 8 - newBitOffset;  | 
 | 
        }  | 
 | 
        this.bitOffset = newBitOffset;  | 
 | 
 | 
 | 
        return val & 0x1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public long readBits(int numBits) throws IOException { | 
 | 
        checkClosed();  | 
 | 
 | 
 | 
        if (numBits < 0 || numBits > 64) { | 
 | 
            throw new IllegalArgumentException();  | 
 | 
        }  | 
 | 
        if (numBits == 0) { | 
 | 
            return 0L;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        int bitsToRead = numBits + bitOffset;  | 
 | 
 | 
 | 
          | 
 | 
        int newBitOffset = (this.bitOffset + numBits) & 0x7;  | 
 | 
 | 
 | 
          | 
 | 
        long accum = 0L;  | 
 | 
        while (bitsToRead > 0) { | 
 | 
            int val = read();  | 
 | 
            if (val == -1) { | 
 | 
                throw new EOFException();  | 
 | 
            }  | 
 | 
 | 
 | 
            accum <<= 8;  | 
 | 
            accum |= val;  | 
 | 
            bitsToRead -= 8;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        if (newBitOffset != 0) { | 
 | 
            seek(getStreamPosition() - 1);  | 
 | 
        }  | 
 | 
        this.bitOffset = newBitOffset;  | 
 | 
 | 
 | 
        // Shift away unwanted bits on the right.  | 
 | 
        accum >>>= (-bitsToRead);   | 
 | 
 | 
 | 
          | 
 | 
        accum &= (-1L >>> (64 - numBits));  | 
 | 
 | 
 | 
        return accum;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public long length() { | 
 | 
        return -1L;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int skipBytes(int n) throws IOException { | 
 | 
        long pos = getStreamPosition();  | 
 | 
        seek(pos + n);  | 
 | 
        return (int)(getStreamPosition() - pos);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public long skipBytes(long n) throws IOException { | 
 | 
        long pos = getStreamPosition();  | 
 | 
        seek(pos + n);  | 
 | 
        return getStreamPosition() - pos;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void seek(long pos) throws IOException { | 
 | 
        checkClosed();  | 
 | 
 | 
 | 
          | 
 | 
        if (pos < flushedPos) { | 
 | 
            throw new IndexOutOfBoundsException("pos < flushedPos!"); | 
 | 
        }  | 
 | 
 | 
 | 
        this.streamPos = pos;  | 
 | 
        this.bitOffset = 0;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void mark() { | 
 | 
        try { | 
 | 
            markByteStack.push(Long.valueOf(getStreamPosition()));  | 
 | 
            markBitStack.push(Integer.valueOf(getBitOffset()));  | 
 | 
        } catch (IOException e) { | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void reset() throws IOException { | 
 | 
        if (markByteStack.empty()) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        long pos = ((Long)markByteStack.pop()).longValue();  | 
 | 
        if (pos < flushedPos) { | 
 | 
            throw new IIOException  | 
 | 
                ("Previous marked position has been discarded!"); | 
 | 
        }  | 
 | 
        seek(pos);  | 
 | 
 | 
 | 
        int offset = ((Integer)markBitStack.pop()).intValue();  | 
 | 
        setBitOffset(offset);  | 
 | 
    }  | 
 | 
 | 
 | 
    public void flushBefore(long pos) throws IOException { | 
 | 
        checkClosed();  | 
 | 
        if (pos < flushedPos) { | 
 | 
            throw new IndexOutOfBoundsException("pos < flushedPos!"); | 
 | 
        }  | 
 | 
        if (pos > getStreamPosition()) { | 
 | 
            throw new IndexOutOfBoundsException("pos > getStreamPosition()!"); | 
 | 
        }  | 
 | 
          | 
 | 
        flushedPos = pos;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void flush() throws IOException { | 
 | 
        flushBefore(getStreamPosition());  | 
 | 
    }  | 
 | 
 | 
 | 
    public long getFlushedPosition() { | 
 | 
        return flushedPos;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean isCached() { | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean isCachedMemory() { | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean isCachedFile() { | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void close() throws IOException { | 
 | 
        checkClosed();  | 
 | 
 | 
 | 
        isClosed = true;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void finalize() throws Throwable { | 
 | 
        if (!isClosed) { | 
 | 
            try { | 
 | 
                close();  | 
 | 
            } catch (IOException e) { | 
 | 
            }  | 
 | 
        }  | 
 | 
        super.finalize();  | 
 | 
    }  | 
 | 
}  |