419 lines
11 KiB
Java
419 lines
11 KiB
Java
|
/*
|
||
|
* 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.
|
||
|
*/
|
||
|
/**
|
||
|
* @author Rustem V. Rafikov
|
||
|
* @version $Revision: 1.3 $
|
||
|
*/
|
||
|
|
||
|
package javax.imageio.stream;
|
||
|
|
||
|
import java.io.EOFException;
|
||
|
import java.io.IOException;
|
||
|
import java.nio.ByteOrder;
|
||
|
|
||
|
/**
|
||
|
* The ImageInputStreamImpl abstract class implements the ImageInputStream
|
||
|
* interface.
|
||
|
*
|
||
|
* @since Android 1.0
|
||
|
*/
|
||
|
public abstract class ImageInputStreamImpl implements ImageInputStream {
|
||
|
|
||
|
/**
|
||
|
* The byte order.
|
||
|
*/
|
||
|
protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
|
||
|
|
||
|
/**
|
||
|
* The stream position.
|
||
|
*/
|
||
|
protected long streamPos = 0;
|
||
|
|
||
|
/**
|
||
|
* The flushed position.
|
||
|
*/
|
||
|
protected long flushedPos = 0;
|
||
|
|
||
|
/**
|
||
|
* The bit offset.
|
||
|
*/
|
||
|
protected int bitOffset = 0;
|
||
|
|
||
|
/**
|
||
|
* The closed.
|
||
|
*/
|
||
|
private boolean closed = false;
|
||
|
|
||
|
/**
|
||
|
* The position stack.
|
||
|
*/
|
||
|
private final PositionStack posStack = new PositionStack();
|
||
|
|
||
|
/**
|
||
|
* Instantiates a new ImageInputStreamImpl.
|
||
|
*/
|
||
|
public ImageInputStreamImpl() {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the stream is closed and if true, throws an IOException.
|
||
|
*
|
||
|
* @throws IOException
|
||
|
* if the stream is closed.
|
||
|
*/
|
||
|
protected final void checkClosed() throws IOException {
|
||
|
if (closed) {
|
||
|
throw new IOException("stream is 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 (buf == null) {
|
||
|
throw new NullPointerException("buffer is NULL");
|
||
|
}
|
||
|
|
||
|
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("EOF reached");
|
||
|
}
|
||
|
return b != 0;
|
||
|
}
|
||
|
|
||
|
public byte readByte() throws IOException {
|
||
|
int b = read();
|
||
|
if (b < 0) {
|
||
|
throw new EOFException("EOF reached");
|
||
|
}
|
||
|
return (byte)b;
|
||
|
}
|
||
|
|
||
|
public int readUnsignedByte() throws IOException {
|
||
|
int b = read();
|
||
|
if (b < 0) {
|
||
|
throw new EOFException("EOF reached");
|
||
|
}
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
public short readShort() throws IOException {
|
||
|
int b1 = read();
|
||
|
int b2 = read();
|
||
|
|
||
|
if (b1 < 0 || b2 < 0) {
|
||
|
throw new EOFException("EOF reached");
|
||
|
}
|
||
|
|
||
|
return byteOrder == ByteOrder.BIG_ENDIAN ? (short)((b1 << 8) | (b2 & 0xff))
|
||
|
: (short)((b2 << 8) | (b1 & 0xff));
|
||
|
}
|
||
|
|
||
|
public int readUnsignedShort() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public char readChar() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public int readInt() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public long readUnsignedInt() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public long readLong() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public float readFloat() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public double readDouble() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public String readLine() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public String readUTF() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(byte[] b, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(byte[] b) throws IOException {
|
||
|
readFully(b, 0, b.length);
|
||
|
}
|
||
|
|
||
|
public void readFully(short[] s, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(char[] c, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(int[] i, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(long[] l, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(float[] f, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void readFully(double[] d, int off, int len) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public long getStreamPosition() throws IOException {
|
||
|
checkClosed();
|
||
|
return streamPos;
|
||
|
}
|
||
|
|
||
|
public int getBitOffset() throws IOException {
|
||
|
checkClosed();
|
||
|
return bitOffset;
|
||
|
}
|
||
|
|
||
|
public void setBitOffset(int bitOffset) throws IOException {
|
||
|
checkClosed();
|
||
|
this.bitOffset = bitOffset;
|
||
|
}
|
||
|
|
||
|
public int readBit() throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public long readBits(int numBits) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public long length() {
|
||
|
return -1L;
|
||
|
}
|
||
|
|
||
|
public int skipBytes(int n) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public long skipBytes(long n) throws IOException {
|
||
|
// -- TODO implement
|
||
|
throw new UnsupportedOperationException("Not implemented yet");
|
||
|
}
|
||
|
|
||
|
public void seek(long pos) throws IOException {
|
||
|
checkClosed();
|
||
|
if (pos < getFlushedPosition()) {
|
||
|
throw new IllegalArgumentException("trying to seek before flushed pos");
|
||
|
}
|
||
|
bitOffset = 0;
|
||
|
streamPos = pos;
|
||
|
}
|
||
|
|
||
|
public void mark() {
|
||
|
try {
|
||
|
posStack.push(getStreamPosition());
|
||
|
} catch (IOException e) {
|
||
|
e.printStackTrace();
|
||
|
throw new RuntimeException("Stream marking error");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void reset() throws IOException {
|
||
|
// -- TODO bit pos
|
||
|
if (!posStack.isEmpty()) {
|
||
|
long p = posStack.pop();
|
||
|
if (p < flushedPos) {
|
||
|
throw new IOException("marked position lies in the flushed portion of the stream");
|
||
|
}
|
||
|
seek(p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void flushBefore(long pos) throws IOException {
|
||
|
if (pos > getStreamPosition()) {
|
||
|
throw new IndexOutOfBoundsException("Trying to flush outside of current position");
|
||
|
}
|
||
|
if (pos < flushedPos) {
|
||
|
throw new IndexOutOfBoundsException("Trying to flush within already flushed portion");
|
||
|
}
|
||
|
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;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Finalizes this object.
|
||
|
*
|
||
|
* @throws Throwable
|
||
|
* if an error occurs.
|
||
|
*/
|
||
|
@Override
|
||
|
protected void finalize() throws Throwable {
|
||
|
if (!closed) {
|
||
|
try {
|
||
|
close();
|
||
|
} finally {
|
||
|
super.finalize();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The Class PositionStack.
|
||
|
*/
|
||
|
private static class PositionStack {
|
||
|
|
||
|
/**
|
||
|
* The Constant SIZE.
|
||
|
*/
|
||
|
private static final int SIZE = 10;
|
||
|
|
||
|
/**
|
||
|
* The values.
|
||
|
*/
|
||
|
private long[] values = new long[SIZE];
|
||
|
|
||
|
/**
|
||
|
* The pos.
|
||
|
*/
|
||
|
private int pos = 0;
|
||
|
|
||
|
/**
|
||
|
* Push.
|
||
|
*
|
||
|
* @param v
|
||
|
* the v.
|
||
|
*/
|
||
|
void push(long v) {
|
||
|
if (pos >= values.length) {
|
||
|
ensure(pos + 1);
|
||
|
}
|
||
|
values[pos++] = v;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Pop.
|
||
|
*
|
||
|
* @return the long.
|
||
|
*/
|
||
|
long pop() {
|
||
|
return values[--pos];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if is empty.
|
||
|
*
|
||
|
* @return true, if is empty.
|
||
|
*/
|
||
|
boolean isEmpty() {
|
||
|
return pos == 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ensure.
|
||
|
*
|
||
|
* @param size
|
||
|
* the size.
|
||
|
*/
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|