mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
- Added SubImageInputStream with test case.
- Changed BufferedImageInputStream to return -1 instead of the hack throwing of unchecked IOException.
This commit is contained in:
parent
2ab9cbadee
commit
effd80d42f
@ -172,14 +172,9 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
try {
|
try {
|
||||||
return mStream.length();
|
return mStream.length();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException ignore) {
|
||||||
throw unchecked(e, RuntimeException.class);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
|
return -1;
|
||||||
private <T extends Throwable> T unchecked(IOException pExcption, Class<T> pClass) {
|
|
||||||
// Ugly hack to fool the compiler..
|
|
||||||
return (T) pExcption;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,102 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.lang.Validate;
|
||||||
|
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import javax.imageio.stream.ImageInputStreamImpl;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for {@link ImageInputStream} to limit the number of bytes that can be read.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: SubImageInputStream.java,v 1.0 Nov 8, 2009 2:50:58 PM haraldk Exp$
|
||||||
|
*/
|
||||||
|
public final class SubImageInputStream extends ImageInputStreamImpl {
|
||||||
|
// NOTE: This class is based on com.sun.imageio.plugins.common.SubImageInputStream, but fixes some of its bugs.
|
||||||
|
|
||||||
|
private final ImageInputStream mStream;
|
||||||
|
private final long mStartPos;
|
||||||
|
private final long mLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
|
||||||
|
*
|
||||||
|
* @param pStream the underlying stream
|
||||||
|
* @param pLength the maximum length to read from the stream.
|
||||||
|
* Note that {@code pStream} may contain less than this maximum number of bytes.
|
||||||
|
*
|
||||||
|
* @throws IOException if {@code pStream}'s position can't be determined.
|
||||||
|
* @throws IllegalArgumentException if {@code pStream == null} or {@code pLength < 0}
|
||||||
|
*/
|
||||||
|
public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
|
||||||
|
Validate.notNull(pStream, "stream");
|
||||||
|
if (pLength < 0) {
|
||||||
|
throw new IllegalArgumentException("length < 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
mStream = pStream;
|
||||||
|
mStartPos = pStream.getStreamPosition();
|
||||||
|
mLength = pLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (streamPos >= mLength) { // Local EOF
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int read = mStream.read();
|
||||||
|
|
||||||
|
if (read >= 0) {
|
||||||
|
streamPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
||||||
|
if (streamPos >= mLength) { // Local EOF
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe cast, as pLength can never cause int overflow
|
||||||
|
int length = (int) Math.min(pLength, mLength - streamPos);
|
||||||
|
int count = mStream.read(pBytes, pOffset, length);
|
||||||
|
|
||||||
|
if (count >= 0) {
|
||||||
|
streamPos += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long length() {
|
||||||
|
try {
|
||||||
|
long length = mStream.length();
|
||||||
|
return length < 0 ? -1 : Math.min(length - mStartPos, mLength);
|
||||||
|
}
|
||||||
|
catch (IOException ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seek(final long pPosition) throws IOException {
|
||||||
|
if (pPosition < getFlushedPosition()) {
|
||||||
|
throw new IndexOutOfBoundsException("pos < flushedPosition");
|
||||||
|
}
|
||||||
|
|
||||||
|
mStream.seek(mStartPos + pPosition);
|
||||||
|
streamPos = pPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import javax.imageio.stream.ImageInputStreamImpl;
|
||||||
|
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SubImageInputStreamTestCase
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: SubImageInputStreamTestCase.java,v 1.0 Nov 8, 2009 3:03:32 PM haraldk Exp$
|
||||||
|
*/
|
||||||
|
public class SubImageInputStreamTestCase extends TestCase {
|
||||||
|
// TODO: Extract super test case for all stream tests
|
||||||
|
private final Random mRandom = new Random(837468l);
|
||||||
|
|
||||||
|
private ImageInputStream createStream(final int pSize) {
|
||||||
|
byte[] bytes = new byte[pSize];
|
||||||
|
|
||||||
|
mRandom.nextBytes(bytes);
|
||||||
|
|
||||||
|
return new MemoryCacheImageInputStream(new ByteArrayInputStream(bytes)) {
|
||||||
|
@Override
|
||||||
|
public long length() {
|
||||||
|
return pSize;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateNullStream() throws IOException {
|
||||||
|
try {
|
||||||
|
new SubImageInputStream(null, 1);
|
||||||
|
fail("Expected IllegalArgumentException with null stream");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateNegativeLength() throws IOException {
|
||||||
|
try {
|
||||||
|
new SubImageInputStream(createStream(0), -1);
|
||||||
|
fail("Expected IllegalArgumentException with negative length");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate() throws IOException {
|
||||||
|
ImageInputStream stream = new SubImageInputStream(createStream(11), 7);
|
||||||
|
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
assertEquals(7, stream.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWraphBeyondWrappedLength() throws IOException {
|
||||||
|
SubImageInputStream stream = new SubImageInputStream(createStream(5), 6);
|
||||||
|
assertEquals(5, stream.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWrapUnknownLength() throws IOException {
|
||||||
|
SubImageInputStream stream = new SubImageInputStream(new ImageInputStreamImpl() {
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Method read not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Method read not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long length() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}, 6);
|
||||||
|
|
||||||
|
assertEquals(-1, stream.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRead() throws IOException {
|
||||||
|
ImageInputStream wrapped = createStream(42);
|
||||||
|
|
||||||
|
wrapped.skipBytes(13);
|
||||||
|
|
||||||
|
ImageInputStream stream = new SubImageInputStream(wrapped, 27);
|
||||||
|
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
assertEquals(27, stream.length());
|
||||||
|
|
||||||
|
stream.read();
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
assertEquals(27, stream.length());
|
||||||
|
|
||||||
|
stream.readFully(new byte[11]);
|
||||||
|
assertEquals(12, stream.getStreamPosition());
|
||||||
|
assertEquals(27, stream.length());
|
||||||
|
|
||||||
|
assertEquals(25, wrapped.getStreamPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReadResetRead() throws IOException {
|
||||||
|
ImageInputStream stream = new SubImageInputStream(createStream(32), 16);
|
||||||
|
stream.mark();
|
||||||
|
|
||||||
|
byte[] first = new byte[16];
|
||||||
|
stream.readFully(first);
|
||||||
|
|
||||||
|
stream.reset();
|
||||||
|
|
||||||
|
byte[] second = new byte[16];
|
||||||
|
stream.readFully(second);
|
||||||
|
|
||||||
|
assertTrue(Arrays.equals(first, second));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSeekNegative() throws IOException {
|
||||||
|
ImageInputStream stream = new SubImageInputStream(createStream(7), 5);
|
||||||
|
try {
|
||||||
|
stream.seek(-2);
|
||||||
|
fail("Expected IndexOutOfBoundsException");
|
||||||
|
}
|
||||||
|
catch (IndexOutOfBoundsException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSeekBeforeFlushedPos() throws IOException {
|
||||||
|
ImageInputStream stream = new SubImageInputStream(createStream(7), 5);
|
||||||
|
stream.seek(3);
|
||||||
|
stream.flushBefore(3);
|
||||||
|
|
||||||
|
assertEquals(3, stream.getStreamPosition());
|
||||||
|
|
||||||
|
try {
|
||||||
|
stream.seek(0);
|
||||||
|
fail("Expected IndexOutOfBoundsException");
|
||||||
|
}
|
||||||
|
catch (IndexOutOfBoundsException expected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(3, stream.getStreamPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSeekAfterEOF() throws IOException {
|
||||||
|
ImageInputStream stream = new SubImageInputStream(createStream(7), 5);
|
||||||
|
stream.seek(6);
|
||||||
|
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSeek() throws IOException {
|
||||||
|
ImageInputStream stream = new SubImageInputStream(createStream(7), 5);
|
||||||
|
stream.seek(5);
|
||||||
|
assertEquals(5, stream.getStreamPosition());
|
||||||
|
|
||||||
|
stream.seek(1);
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user