/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.code.appengine.imageio.stream; import java.io.EOFException; import java.io.IOException; import java.nio.ByteOrder; import org.apache.harmony.luni.util.Util; import org.apache.harmony.x.imageio.internal.nls.Messages; import com.google.code.appengine.imageio.stream.IIOByteBuffer; import com.google.code.appengine.imageio.stream.ImageInputStream; public abstract class ImageInputStreamImpl implements ImageInputStream { protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; protected long streamPos = 0; protected long flushedPos = 0; protected int bitOffset = 0; private boolean closed = false; private final PositionStack posStack = new PositionStack(); private final PositionStack offsetStack = new PositionStack(); private final byte[] buff = new byte[8]; public ImageInputStreamImpl() { } protected final void checkClosed() throws IOException { if (closed) { throw new IOException(Messages.getString("imageio.0D")); } } 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 (buf == null) { throw new NullPointerException(Messages.getString("imageio.0E")); } byte[] b = new byte[len]; len = read(b, 0, b.length); buf.setData(b); buf.setOffset(0); buf.setLength(len); } public boolean readBoolean() throws IOException { int b = read(); if (b < 0) { throw new EOFException(Messages.getString("imageio.0F")); } return b != 0; } public byte readByte() throws IOException { int b = read(); if (b < 0) { throw new EOFException(Messages.getString("imageio.0F")); } return (byte) b; } public int readUnsignedByte() throws IOException { int b = read(); if (b < 0) { throw new EOFException(Messages.getString("imageio.0F")); } return b; } public short readShort() throws IOException { if (read(buff, 0, 2) < 0) { throw new EOFException(); } return byteOrder == ByteOrder.BIG_ENDIAN ? (short) ((buff[0] << 8) | (buff[1] & 0xff)) : (short) ((buff[1] << 8) | (buff[0] & 0xff)); } public int readUnsignedShort() throws IOException { return ((int) readShort()) & 0xffff; } public char readChar() throws IOException { return (char) readShort(); } public int readInt() throws IOException { if (read(buff, 0, 4) < 0) { throw new EOFException(); } return byteOrder == ByteOrder.BIG_ENDIAN ? ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) | ((buff[2] & 0xff) << 8) | (buff[3] & 0xff) : ((buff[3] & 0xff) << 24) | ((buff[2] & 0xff) << 16) | ((buff[1] & 0xff) << 8) | (buff[0] & 0xff); } public long readUnsignedInt() throws IOException { return ((long) readInt()) & 0xffffffffL; } public long readLong() throws IOException { if (read(buff, 0, 8) < 0) { throw new EOFException(); } if (byteOrder == ByteOrder.BIG_ENDIAN) { int i1 = ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) | ((buff[2] & 0xff) << 8) | (buff[3] & 0xff); int i2 = ((buff[4] & 0xff) << 24) | ((buff[5] & 0xff) << 16) | ((buff[6] & 0xff) << 8) | (buff[7] & 0xff); return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL); } else { int i1 = ((buff[3] & 0xff) << 24) | ((buff[2] & 0xff) << 16) | ((buff[1] & 0xff) << 8) | (buff[0] & 0xff); int i2 = ((buff[7] & 0xff) << 24) | ((buff[6] & 0xff) << 16) | ((buff[5] & 0xff) << 8) | (buff[4] & 0xff); return ((i2 & 0xffffffffL) << 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 { final StringBuilder line = new StringBuilder(80); boolean isEmpty = true; int c = -1; while ((c = read()) != -1) { isEmpty = false; if (c == '\n') { break; } else if (c == '\r') { c = read(); if ((c != '\n') && (c != -1)) { seek(getStreamPosition() - 1); } break; } line.append((char) c); } return isEmpty ? null : line.toString(); } public String readUTF() throws IOException { ByteOrder byteOrder = getByteOrder(); setByteOrder(ByteOrder.BIG_ENDIAN); final int size = readUnsignedShort(); final byte[] buf = new byte[size]; final char[] out = new char[size]; readFully(buf, 0, size); setByteOrder(byteOrder); //return new DataInputStream(new ByteArrayInputStream(buff)).readUTF(); return Util.convertUTF8WithBuf(buf, out, 0, size); } public void readFully(byte[] b, int off, int len) throws IOException { if ((off < 0) || (len < 0) || (off + len > b.length)) { throw new IndexOutOfBoundsException(); } while (len > 0) { int i = read(b, off, len); if (i == -1) { throw new EOFException(); } off += i; len -= i; } } 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)) { throw new IndexOutOfBoundsException(); } for (int i = 0; i < len; i++) { s[off + i] = readShort(); } } public void readFully(char[] c, int off, int len) throws IOException { if ((off < 0) || (len < 0) || (off + len > c.length)) { throw new IndexOutOfBoundsException(); } for (int i = 0; i < len; i++) { c[off + i] = readChar(); } } public void readFully(int[] i, int off, int len) throws IOException { if ((off < 0) || (len < 0) || (off + len > i.length)) { throw new IndexOutOfBoundsException(); } for (int k = 0; k < len; k++) { i[off + k] = readInt(); } } public void readFully(long[] l, int off, int len) throws IOException { if ((off < 0) || (len < 0) || (off + len > l.length)) { throw new IndexOutOfBoundsException(); } for (int i = 0; i < len; i++) { l[off + i] = readLong(); } } public void readFully(float[] f, int off, int len) throws IOException { if ((off < 0) || (len < 0) || (off + len > f.length)) { throw new IndexOutOfBoundsException(); } for (int i = 0; i < len; i++) { f[off + i] = readFloat(); } } public void readFully(double[] d, int off, int len) throws IOException { if ((off < 0) || (len < 0) || (off + len > d.length)) { throw new IndexOutOfBoundsException(); } for (int i = 0; i < len; i++) { d[off + i] = readFloat(); } } 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(); } this.bitOffset = bitOffset; } int currentByte; public int readBit() throws IOException { checkClosed(); int offset = bitOffset; int currentByte = read(); if (currentByte == -1) { throw new EOFException(); } offset = (offset + 1) & 7; if (offset != 0) { currentByte >>= 8 - offset; seek(getStreamPosition() - 1); } bitOffset = offset; return currentByte & 1; } public long readBits(int numBits) throws IOException { checkClosed(); if ((numBits < 0) || (numBits > 64)) { throw new IllegalArgumentException(); } long res = 0; for (int i = 0; i < numBits; i++) { res <<= 1; res |= readBit(); } return res; } public long length() { return -1L; } public int skipBytes(int n) throws IOException { return (int) skipBytes((long) n); } public long skipBytes(long n) throws IOException { seek(getStreamPosition() + n); return n; } public void seek(long pos) throws IOException { checkClosed(); if (pos < getFlushedPosition()) { throw new IllegalArgumentException( Messages.getString("imageio.10")); } bitOffset = 0; streamPos = pos; } public void mark() { try { posStack.push(getStreamPosition()); offsetStack.push(getBitOffset()); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(Messages.getString("imageio.11")); } } public void reset() throws IOException { if (!posStack.isEmpty() && !offsetStack.isEmpty()) { long p = posStack.pop(); if (p < flushedPos) { throw new IOException( Messages.getString("imageio.12")); } seek(p); setBitOffset((int)offsetStack.pop()); } } public void flushBefore(long pos) throws IOException { if (pos > getStreamPosition()) { throw new IndexOutOfBoundsException( Messages.getString("imageio.13")); } if (pos < flushedPos) { throw new IndexOutOfBoundsException( Messages.getString("imageio.14")); } flushedPos = pos; // -- TODO implement } public void flush() throws IOException { flushBefore(getStreamPosition()); } public long getFlushedPosition() { return flushedPos; } public boolean isCached() { return false; // def } public boolean isCachedMemory() { return false; // def } public boolean isCachedFile() { return false; // def } public void close() throws IOException { checkClosed(); closed = true; } @Override protected void finalize() throws Throwable { if (!closed) { try { close(); } finally { super.finalize(); } } } private static class PositionStack { private static final int SIZE = 10; private long[] values = new long[SIZE]; private int pos = 0; void push(long v) { if (pos >= values.length) { ensure(pos + 1); } values[pos++] = v; } long pop() { return values[--pos]; } boolean isEmpty() { return pos == 0; } private void ensure(int size) { long[] arr = new long[Math.max(2 * values.length, size)]; System.arraycopy(values, 0, arr, 0, values.length); values = arr; } } }