From: Nick Burch Date: Wed, 29 Dec 2010 07:28:10 +0000 (+0000) Subject: Refactor DocumentInputStream so that it can transparently handle both old style and... X-Git-Tag: REL_3_8_BETA1~53 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d004673137ef3f80e55f6438ae998b04734ace35;p=poi.git Refactor DocumentInputStream so that it can transparently handle both old style and new style POIFS Documents git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1053562 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/POIDocument.java b/src/java/org/apache/poi/POIDocument.java index 0bd6b1395c..6e1527e858 100644 --- a/src/java/org/apache/poi/POIDocument.java +++ b/src/java/org/apache/poi/POIDocument.java @@ -144,7 +144,7 @@ public abstract class POIDocument { //directory can be null when creating new documents if(directory == null) return null; - InputStream dis; + DocumentInputStream dis; try { // Find the entry, and get an input stream for it dis = directory.createDocumentInputStream( directory.getEntry(setName) ); diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java index 29be005b8b..ea733ea879 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java +++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -171,14 +171,7 @@ public class DirectoryNode final String documentName) throws IOException { - Entry document = getEntry(documentName); - - if (!document.isDocumentEntry()) - { - throw new IOException("Entry '" + documentName - + "' is not a DocumentEntry"); - } - return new DocumentInputStream(( DocumentEntry ) document); + return createDocumentInputStream(getEntry(documentName)); } /** @@ -191,7 +184,7 @@ public class DirectoryNode * @exception IOException if the document does not exist or the * name is that of a DirectoryEntry */ - public InputStream createDocumentInputStream( + public DocumentInputStream createDocumentInputStream( final Entry document) throws IOException { @@ -201,11 +194,7 @@ public class DirectoryNode } DocumentEntry entry = (DocumentEntry)document; - if(_ofilesystem != null) { - return new DocumentInputStream(entry); - } else { - return new NDocumentInputStream(entry); - } + return new DocumentInputStream(entry); } /** diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java index 577f3d93b1..d39582f7ad 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java @@ -20,40 +20,26 @@ package org.apache.poi.poifs.filesystem; import java.io.IOException; import java.io.InputStream; -import org.apache.poi.poifs.storage.DataInputBlock; import org.apache.poi.util.LittleEndianInput; /** * This class provides methods to read a DocumentEntry managed by a - * {@link POIFSFileSystem} instance. - * - * @author Marc Johnson (mjohnson at apache dot org) + * {@link POIFSFileSystem} or {@link NPOIFSFileSystem} instance. + * It creates the appropriate one, and delegates, allowing us to + * work transparently with the two. */ -public final class DocumentInputStream extends InputStream implements LittleEndianInput { +public class DocumentInputStream extends InputStream implements LittleEndianInput { /** returned by read operations if we're at end of document */ - private static final int EOF = -1; + protected static final int EOF = -1; - private static final int SIZE_SHORT = 2; - private static final int SIZE_INT = 4; - private static final int SIZE_LONG = 8; - - /** current offset into the Document */ - private int _current_offset; - - /** current marked offset into the Document (used by mark and reset) */ - private int _marked_offset; - - /** the Document's size */ - private int _document_size; - - /** have we been closed? */ - private boolean _closed; - - /** the actual Document */ - private POIFSDocument _document; - - /** the data block containing the current stream pointer */ - private DataInputBlock _currentBlock; + protected static final int SIZE_SHORT = 2; + protected static final int SIZE_INT = 4; + protected static final int SIZE_LONG = 8; + + private DocumentInputStream delegate; + + /** For use by downstream implementations */ + protected DocumentInputStream() {} /** * Create an InputStream from the specified DocumentEntry @@ -64,20 +50,21 @@ public final class DocumentInputStream extends InputStream implements LittleEndi * been deleted?) */ public DocumentInputStream(DocumentEntry document) throws IOException { - if (!(document instanceof DocumentNode)) { - throw new IOException("Cannot open internal document storage"); - } - DocumentNode documentNode = (DocumentNode)document; - if(documentNode.getDocument() == null) { - throw new IOException("Cannot open internal document storage"); - } - - _current_offset = 0; - _marked_offset = 0; - _document_size = document.getSize(); - _closed = false; - _document = documentNode.getDocument(); - _currentBlock = getDataInputBlock(0); + if (!(document instanceof DocumentNode)) { + throw new IOException("Cannot open internal document storage"); + } + DocumentNode documentNode = (DocumentNode)document; + DirectoryNode parentNode = (DirectoryNode)document.getParent(); + + if(documentNode.getDocument() != null) { + delegate = new ODocumentInputStream(document); + } else if(parentNode.getFileSystem() != null) { + delegate = new ODocumentInputStream(document); + } else if(parentNode.getNFileSystem() != null) { + delegate = new NDocumentInputStream(document); + } else { + throw new IOException("No FileSystem bound on the parent, can't read contents"); + } } /** @@ -86,27 +73,28 @@ public final class DocumentInputStream extends InputStream implements LittleEndi * @param document the Document to be read */ public DocumentInputStream(POIFSDocument document) { - _current_offset = 0; - _marked_offset = 0; - _document_size = document.getSize(); - _closed = false; - _document = document; - _currentBlock = getDataInputBlock(0); + delegate = new ODocumentInputStream(document); } + /** + * Create an InputStream from the specified Document + * + * @param document the Document to be read + */ + public DocumentInputStream(NPOIFSDocument document) { + delegate = new NDocumentInputStream(document); + } + public int available() { - if (_closed) { - throw new IllegalStateException("cannot perform requested operation on a closed stream"); - } - return _document_size - _current_offset; + return delegate.available(); } public void close() { - _closed = true; + delegate.close(); } public void mark(int ignoredReadlimit) { - _marked_offset = _current_offset; + delegate.mark(ignoredReadlimit); } /** @@ -118,21 +106,8 @@ public final class DocumentInputStream extends InputStream implements LittleEndi return true; } - private DataInputBlock getDataInputBlock(int offset) { - return _document.getDataInputBlock(offset); - } - public int read() throws IOException { - dieIfClosed(); - if (atEOD()) { - return EOF; - } - int result = _currentBlock.readUByte(); - _current_offset++; - if (_currentBlock.available() < 1) { - _currentBlock = getDataInputBlock(_current_offset); - } - return result; + return delegate.read(); } public int read(byte[] b) throws IOException { @@ -140,22 +115,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi } public int read(byte[] b, int off, int len) throws IOException { - dieIfClosed(); - if (b == null) { - throw new IllegalArgumentException("buffer must not be null"); - } - if (off < 0 || len < 0 || b.length < off + len) { - throw new IndexOutOfBoundsException("can't read past buffer boundaries"); - } - if (len == 0) { - return 0; - } - if (atEOD()) { - return EOF; - } - int limit = Math.min(available(), len); - readFully(b, off, limit); - return limit; + return delegate.read(b, off, len); } /** @@ -164,169 +124,46 @@ public final class DocumentInputStream extends InputStream implements LittleEndi * method repositions the stream to its beginning. */ public void reset() { - _current_offset = _marked_offset; - _currentBlock = getDataInputBlock(_current_offset); + delegate.reset(); } public long skip(long n) throws IOException { - dieIfClosed(); - if (n < 0) { - return 0; - } - int new_offset = _current_offset + (int) n; - - if (new_offset < _current_offset) { - - // wrap around in converting a VERY large long to an int - new_offset = _document_size; - } else if (new_offset > _document_size) { - new_offset = _document_size; - } - long rval = new_offset - _current_offset; - - _current_offset = new_offset; - _currentBlock = getDataInputBlock(_current_offset); - return rval; - } - - private void dieIfClosed() throws IOException { - if (_closed) { - throw new IOException("cannot perform requested operation on a closed stream"); - } - } - - private boolean atEOD() { - return _current_offset == _document_size; - } - - private void checkAvaliable(int requestedSize) { - if (_closed) { - throw new IllegalStateException("cannot perform requested operation on a closed stream"); - } - if (requestedSize > _document_size - _current_offset) { - throw new RuntimeException("Buffer underrun - requested " + requestedSize - + " bytes but " + (_document_size - _current_offset) + " was available"); - } + return delegate.skip(n); } public byte readByte() { - return (byte) readUByte(); + return delegate.readByte(); } public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - public void readFully(byte[] buf) { - readFully(buf, 0, buf.length); + return delegate.readDouble(); } public short readShort() { return (short) readUShort(); } + public void readFully(byte[] buf) { + readFully(buf, 0, buf.length); + } + public void readFully(byte[] buf, int off, int len) { - checkAvaliable(len); - int blockAvailable = _currentBlock.available(); - if (blockAvailable > len) { - _currentBlock.readFully(buf, off, len); - _current_offset += len; - return; - } - // else read big amount in chunks - int remaining = len; - int writePos = off; - while (remaining > 0) { - boolean blockIsExpiring = remaining >= blockAvailable; - int reqSize; - if (blockIsExpiring) { - reqSize = blockAvailable; - } else { - reqSize = remaining; - } - _currentBlock.readFully(buf, writePos, reqSize); - remaining -= reqSize; - writePos += reqSize; - _current_offset += reqSize; - if (blockIsExpiring) { - if (_current_offset == _document_size) { - if (remaining > 0) { - throw new IllegalStateException( - "reached end of document stream unexpectedly"); - } - _currentBlock = null; - break; - } - _currentBlock = getDataInputBlock(_current_offset); - blockAvailable = _currentBlock.available(); - } - } + delegate.readFully(buf, off, len); } public long readLong() { - checkAvaliable(SIZE_LONG); - int blockAvailable = _currentBlock.available(); - long result; - if (blockAvailable > SIZE_LONG) { - result = _currentBlock.readLongLE(); - } else { - DataInputBlock nextBlock = getDataInputBlock(_current_offset + blockAvailable); - if (blockAvailable == SIZE_LONG) { - result = _currentBlock.readLongLE(); - } else { - result = nextBlock.readLongLE(_currentBlock, blockAvailable); - } - _currentBlock = nextBlock; - } - _current_offset += SIZE_LONG; - return result; + return delegate.readLong(); } public int readInt() { - checkAvaliable(SIZE_INT); - int blockAvailable = _currentBlock.available(); - int result; - if (blockAvailable > SIZE_INT) { - result = _currentBlock.readIntLE(); - } else { - DataInputBlock nextBlock = getDataInputBlock(_current_offset + blockAvailable); - if (blockAvailable == SIZE_INT) { - result = _currentBlock.readIntLE(); - } else { - result = nextBlock.readIntLE(_currentBlock, blockAvailable); - } - _currentBlock = nextBlock; - } - _current_offset += SIZE_INT; - return result; + return delegate.readInt(); } public int readUShort() { - checkAvaliable(SIZE_SHORT); - int blockAvailable = _currentBlock.available(); - int result; - if (blockAvailable > SIZE_SHORT) { - result = _currentBlock.readUShortLE(); - } else { - DataInputBlock nextBlock = getDataInputBlock(_current_offset + blockAvailable); - if (blockAvailable == SIZE_SHORT) { - result = _currentBlock.readUShortLE(); - } else { - result = nextBlock.readUShortLE(_currentBlock); - } - _currentBlock = nextBlock; - } - _current_offset += SIZE_SHORT; - return result; + return delegate.readUShort(); } public int readUByte() { - checkAvaliable(1); - int result = _currentBlock.readUByte(); - _current_offset++; - if (_currentBlock.available() < 1) { - _currentBlock = getDataInputBlock(_current_offset); - } - return result; + return delegate.readUByte(); } } diff --git a/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java index 2595ba0259..602cb5ff56 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/NDocumentInputStream.java @@ -18,26 +18,17 @@ package org.apache.poi.poifs.filesystem; import java.io.IOException; -import java.io.InputStream; import java.nio.ByteBuffer; import java.util.Iterator; import org.apache.poi.poifs.property.DocumentProperty; import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.LittleEndianInput; /** * This class provides methods to read a DocumentEntry managed by a - * {@link POIFSFileSystem} instance. + * {@link NPOIFSFileSystem} instance. */ -public final class NDocumentInputStream extends InputStream implements LittleEndianInput { - /** returned by read operations if we're at end of document */ - private static final int EOF = -1; - - private static final int SIZE_SHORT = 2; - private static final int SIZE_INT = 4; - private static final int SIZE_LONG = 8; - +public final class NDocumentInputStream extends DocumentInputStream { /** current offset into the Document */ private int _current_offset; /** current block count */ @@ -104,6 +95,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd _data = _document.getBlockIterator(); } + @Override public int available() { if (_closed) { throw new IllegalStateException("cannot perform requested operation on a closed stream"); @@ -111,24 +103,18 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd return _document_size - _current_offset; } + @Override public void close() { _closed = true; } + @Override public void mark(int ignoredReadlimit) { _marked_offset = _current_offset; _marked_offset_count = _current_block_count; } - /** - * Tests if this input stream supports the mark and reset methods. - * - * @return true always - */ - public boolean markSupported() { - return true; - } - + @Override public int read() throws IOException { dieIfClosed(); if (atEOD()) { @@ -145,10 +131,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd return result; } - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } - + @Override public int read(byte[] b, int off, int len) throws IOException { dieIfClosed(); if (b == null) { @@ -173,6 +156,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd * last called on this input stream. If mark() has not been called this * method repositions the stream to its beginning. */ + @Override public void reset() { // Special case for reset to the start if(_marked_offset == 0 && _marked_offset_count == 0) { @@ -207,6 +191,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd _current_offset = _marked_offset; } + @Override public long skip(long n) throws IOException { dieIfClosed(); if (n < 0) { @@ -249,22 +234,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd } } - public byte readByte() { - return (byte) readUByte(); - } - - public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - public void readFully(byte[] buf) { - readFully(buf, 0, buf.length); - } - - public short readShort() { - return (short) readUShort(); - } - + @Override public void readFully(byte[] buf, int off, int len) { checkAvaliable(len); @@ -282,6 +252,17 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd } } + @Override + public byte readByte() { + return (byte) readUByte(); + } + + @Override + public double readDouble() { + return Double.longBitsToDouble(readLong()); + } + + @Override public long readLong() { checkAvaliable(SIZE_LONG); byte[] data = new byte[SIZE_LONG]; @@ -289,6 +270,12 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd return LittleEndian.getLong(data, 0); } + @Override + public short readShort() { + return (short) readUShort(); + } + + @Override public int readInt() { checkAvaliable(SIZE_INT); byte[] data = new byte[SIZE_INT]; @@ -296,6 +283,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd return LittleEndian.getInt(data); } + @Override public int readUShort() { checkAvaliable(SIZE_SHORT); byte[] data = new byte[SIZE_SHORT]; @@ -303,6 +291,7 @@ public final class NDocumentInputStream extends InputStream implements LittleEnd return LittleEndian.getShort(data); } + @Override public int readUByte() { checkAvaliable(1); byte[] data = new byte[1]; diff --git a/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java new file mode 100644 index 0000000000..a1bc5da95f --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java @@ -0,0 +1,321 @@ +/* ==================================================================== + 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 org.apache.poi.poifs.filesystem; + +import java.io.IOException; + +import org.apache.poi.poifs.storage.DataInputBlock; + +/** + * This class provides methods to read a DocumentEntry managed by a + * {@link POIFSFileSystem} instance. + * + * @author Marc Johnson (mjohnson at apache dot org) + */ +public final class ODocumentInputStream extends DocumentInputStream { + /** current offset into the Document */ + private int _current_offset; + + /** current marked offset into the Document (used by mark and reset) */ + private int _marked_offset; + + /** the Document's size */ + private int _document_size; + + /** have we been closed? */ + private boolean _closed; + + /** the actual Document */ + private POIFSDocument _document; + + /** the data block containing the current stream pointer */ + private DataInputBlock _currentBlock; + + /** + * Create an InputStream from the specified DocumentEntry + * + * @param document the DocumentEntry to be read + * + * @exception IOException if the DocumentEntry cannot be opened (like, maybe it has + * been deleted?) + */ + public ODocumentInputStream(DocumentEntry document) throws IOException { + if (!(document instanceof DocumentNode)) { + throw new IOException("Cannot open internal document storage"); + } + DocumentNode documentNode = (DocumentNode)document; + if(documentNode.getDocument() == null) { + throw new IOException("Cannot open internal document storage"); + } + + _current_offset = 0; + _marked_offset = 0; + _document_size = document.getSize(); + _closed = false; + _document = documentNode.getDocument(); + _currentBlock = getDataInputBlock(0); + } + + /** + * Create an InputStream from the specified Document + * + * @param document the Document to be read + */ + public ODocumentInputStream(POIFSDocument document) { + _current_offset = 0; + _marked_offset = 0; + _document_size = document.getSize(); + _closed = false; + _document = document; + _currentBlock = getDataInputBlock(0); + } + + @Override + public int available() { + if (_closed) { + throw new IllegalStateException("cannot perform requested operation on a closed stream"); + } + return _document_size - _current_offset; + } + + @Override + public void close() { + _closed = true; + } + + @Override + public void mark(int ignoredReadlimit) { + _marked_offset = _current_offset; + } + + private DataInputBlock getDataInputBlock(int offset) { + return _document.getDataInputBlock(offset); + } + + @Override + public int read() throws IOException { + dieIfClosed(); + if (atEOD()) { + return EOF; + } + int result = _currentBlock.readUByte(); + _current_offset++; + if (_currentBlock.available() < 1) { + _currentBlock = getDataInputBlock(_current_offset); + } + return result; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + dieIfClosed(); + if (b == null) { + throw new IllegalArgumentException("buffer must not be null"); + } + if (off < 0 || len < 0 || b.length < off + len) { + throw new IndexOutOfBoundsException("can't read past buffer boundaries"); + } + if (len == 0) { + return 0; + } + if (atEOD()) { + return EOF; + } + int limit = Math.min(available(), len); + readFully(b, off, limit); + return limit; + } + + /** + * Repositions this stream to the position at the time the mark() method was + * last called on this input stream. If mark() has not been called this + * method repositions the stream to its beginning. + */ + @Override + public void reset() { + _current_offset = _marked_offset; + _currentBlock = getDataInputBlock(_current_offset); + } + + @Override + public long skip(long n) throws IOException { + dieIfClosed(); + if (n < 0) { + return 0; + } + int new_offset = _current_offset + (int) n; + + if (new_offset < _current_offset) { + + // wrap around in converting a VERY large long to an int + new_offset = _document_size; + } else if (new_offset > _document_size) { + new_offset = _document_size; + } + long rval = new_offset - _current_offset; + + _current_offset = new_offset; + _currentBlock = getDataInputBlock(_current_offset); + return rval; + } + + private void dieIfClosed() throws IOException { + if (_closed) { + throw new IOException("cannot perform requested operation on a closed stream"); + } + } + + private boolean atEOD() { + return _current_offset == _document_size; + } + + private void checkAvaliable(int requestedSize) { + if (_closed) { + throw new IllegalStateException("cannot perform requested operation on a closed stream"); + } + if (requestedSize > _document_size - _current_offset) { + throw new RuntimeException("Buffer underrun - requested " + requestedSize + + " bytes but " + (_document_size - _current_offset) + " was available"); + } + } + + @Override + public byte readByte() { + return (byte) readUByte(); + } + + @Override + public double readDouble() { + return Double.longBitsToDouble(readLong()); + } + + @Override + public short readShort() { + return (short) readUShort(); + } + + @Override + public void readFully(byte[] buf, int off, int len) { + checkAvaliable(len); + int blockAvailable = _currentBlock.available(); + if (blockAvailable > len) { + _currentBlock.readFully(buf, off, len); + _current_offset += len; + return; + } + // else read big amount in chunks + int remaining = len; + int writePos = off; + while (remaining > 0) { + boolean blockIsExpiring = remaining >= blockAvailable; + int reqSize; + if (blockIsExpiring) { + reqSize = blockAvailable; + } else { + reqSize = remaining; + } + _currentBlock.readFully(buf, writePos, reqSize); + remaining -= reqSize; + writePos += reqSize; + _current_offset += reqSize; + if (blockIsExpiring) { + if (_current_offset == _document_size) { + if (remaining > 0) { + throw new IllegalStateException( + "reached end of document stream unexpectedly"); + } + _currentBlock = null; + break; + } + _currentBlock = getDataInputBlock(_current_offset); + blockAvailable = _currentBlock.available(); + } + } + } + + @Override + public long readLong() { + checkAvaliable(SIZE_LONG); + int blockAvailable = _currentBlock.available(); + long result; + if (blockAvailable > SIZE_LONG) { + result = _currentBlock.readLongLE(); + } else { + DataInputBlock nextBlock = getDataInputBlock(_current_offset + blockAvailable); + if (blockAvailable == SIZE_LONG) { + result = _currentBlock.readLongLE(); + } else { + result = nextBlock.readLongLE(_currentBlock, blockAvailable); + } + _currentBlock = nextBlock; + } + _current_offset += SIZE_LONG; + return result; + } + + @Override + public int readInt() { + checkAvaliable(SIZE_INT); + int blockAvailable = _currentBlock.available(); + int result; + if (blockAvailable > SIZE_INT) { + result = _currentBlock.readIntLE(); + } else { + DataInputBlock nextBlock = getDataInputBlock(_current_offset + blockAvailable); + if (blockAvailable == SIZE_INT) { + result = _currentBlock.readIntLE(); + } else { + result = nextBlock.readIntLE(_currentBlock, blockAvailable); + } + _currentBlock = nextBlock; + } + _current_offset += SIZE_INT; + return result; + } + + @Override + public int readUShort() { + checkAvaliable(SIZE_SHORT); + int blockAvailable = _currentBlock.available(); + int result; + if (blockAvailable > SIZE_SHORT) { + result = _currentBlock.readUShortLE(); + } else { + DataInputBlock nextBlock = getDataInputBlock(_current_offset + blockAvailable); + if (blockAvailable == SIZE_SHORT) { + result = _currentBlock.readUShortLE(); + } else { + result = nextBlock.readUShortLE(_currentBlock); + } + _currentBlock = nextBlock; + } + _current_offset += SIZE_SHORT; + return result; + } + + @Override + public int readUByte() { + checkAvaliable(1); + int result = _currentBlock.readUByte(); + _current_offset++; + if (_currentBlock.available() < 1) { + _currentBlock = getDataInputBlock(_current_offset); + } + return result; + } +}