You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2008/10/26 08:18:19 UTC
svn commit: r707945 [3/4] - in /poi/branches/ooxml: ./
src/contrib/src/org/apache/poi/contrib/poibrowser/
src/java/org/apache/poi/hssf/model/ src/java/org/apache/poi/hssf/record/
src/java/org/apache/poi/hssf/record/constant/ src/java/org/apache/poi/hss...
Modified: poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java Sun Oct 26 00:18:17 2008
@@ -1,4 +1,3 @@
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,437 +14,314 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.filesystem;
-import java.io.*;
+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
- * Filesystem instance.
+ * {@link POIFSFileSystem} instance.
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
-public class DocumentInputStream
- extends InputStream
-{
-
- // 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;
-
- // buffer used to read one byte at a time
- private byte[] _tiny_buffer;
-
- // returned by read operations if we're at end of document
- static private final int EOD = -1;
-
- /**
- * 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 DocumentInputStream(final DocumentEntry document)
- throws IOException
- {
- _current_offset = 0;
- _marked_offset = 0;
- _document_size = document.getSize();
- _closed = false;
- _tiny_buffer = null;
- if (document instanceof DocumentNode)
- {
- _document = (( DocumentNode ) document).getDocument();
- }
- else
- {
- throw new IOException("Cannot open internal document storage");
- }
- }
-
- /**
- * Create an InputStream from the specified Document
- *
- * @param document the Document to be read
- *
- * @exception IOException if the DocumentEntry cannot be opened
- * (like, maybe it has been deleted?)
- */
-
- public DocumentInputStream(final POIFSDocument document)
- throws IOException
- {
- _current_offset = 0;
- _marked_offset = 0;
- _document_size = document.getSize();
- _closed = false;
- _tiny_buffer = null;
- _document = document;
- }
-
- /**
- * Returns the number of bytes that can be read (or skipped over)
- * from this input stream without blocking by the next caller of a
- * method for this input stream. The next caller might be the same
- * thread or or another thread.
- *
- * @return the number of bytes that can be read from this input
- * stream without blocking.
- *
- * @exception IOException on error (such as the stream has been
- * closed)
- */
-
- public int available()
- throws IOException
- {
- dieIfClosed();
- return _document_size - _current_offset;
- }
-
- /**
- * Closes this input stream and releases any system resources
- * associated with the stream.
- *
- * @exception IOException
- */
-
- public void close()
- throws IOException
- {
- _closed = true;
- }
-
- /**
- * Marks the current position in this input stream. A subsequent
- * call to the reset method repositions this stream at the last
- * marked position so that subsequent reads re-read the same
- * bytes.
- * <p>
- * The readlimit arguments tells this input stream to allow that
- * many bytes to be read before the mark position gets
- * invalidated. This implementation, however, does not care.
- * <p>
- * The general contract of mark is that, if the method
- * markSupported returns true, the stream somehow remembers all
- * the bytes read after the call to mark and stands ready to
- * supply those same bytes again if and whenever the method reset
- * is called. However, the stream is not required to remember any
- * data at all if more than readlimit bytes are read from the
- * stream before reset is called. But this stream will.
- *
- * @param ignoredReadlimit the maximum limit of bytes that can be
- * read before the mark position becomes
- * invalid. Ignored by this
- * implementation.
- */
-
- public void mark(int ignoredReadlimit)
- {
- _marked_offset = _current_offset;
- }
-
- /**
- * Tests if this input stream supports the mark and reset methods.
- *
- * @return true
- */
-
- public boolean markSupported()
- {
- return true;
- }
-
- /**
- * Reads the next byte of data from the input stream. The value
- * byte is returned as an int in the range 0 to 255. If no byte is
- * available because the end of the stream has been reached, the
- * value -1 is returned. The definition of this method in
- * java.io.InputStream allows this method to block, but it won't.
- *
- * @return the next byte of data, or -1 if the end of the stream
- * is reached.
- *
- * @exception IOException
- */
-
- public int read()
- throws IOException
- {
- dieIfClosed();
- if (atEOD())
- {
- return EOD;
- }
- if (_tiny_buffer == null)
- {
- _tiny_buffer = new byte[ 1 ];
- }
- _document.read(_tiny_buffer, _current_offset++);
- return ((int)_tiny_buffer[ 0 ]) & 0x000000FF;
- }
-
- /**
- * Reads some number of bytes from the input stream and stores
- * them into the buffer array b. The number of bytes actually read
- * is returned as an integer. The definition of this method in
- * java.io.InputStream allows this method to block, but it won't.
- * <p>
- * If b is null, a NullPointerException is thrown. If the length
- * of b is zero, then no bytes are read and 0 is returned;
- * otherwise, there is an attempt to read at least one byte. If no
- * byte is available because the stream is at end of file, the
- * value -1 is returned; otherwise, at least one byte is read and
- * stored into b.
- * <p>
- * The first byte read is stored into element b[0], the next one
- * into b[1], and so on. The number of bytes read is, at most,
- * equal to the length of b. Let k be the number of bytes actually
- * read; these bytes will be stored in elements b[0] through
- * b[k-1], leaving elements b[k] through b[b.length-1] unaffected.
- * <p>
- * If the first byte cannot be read for any reason other than end
- * of file, then an IOException is thrown. In particular, an
- * IOException is thrown if the input stream has been closed.
- * <p>
- * The read(b) method for class InputStream has the same effect as:
- * <p>
- * <code>read(b, 0, b.length)</code>
- *
- * @param b the buffer into which the data is read.
- *
- * @return the total number of bytes read into the buffer, or -1
- * if there is no more data because the end of the stream
- * has been reached.
- *
- * @exception IOException
- * @exception NullPointerException
- */
-
- public int read(final byte [] b)
- throws IOException, NullPointerException
- {
- return read(b, 0, b.length);
- }
-
- /**
- * Reads up to len bytes of data from the input stream into an
- * array of bytes. An attempt is made to read as many as len
- * bytes, but a smaller number may be read, possibly zero. The
- * number of bytes actually read is returned as an integer.
- * <p>
- * The definition of this method in java.io.InputStream allows it
- * to block, but it won't.
- * <p>
- * If b is null, a NullPointerException is thrown.
- * <p>
- * If off is negative, or len is negative, or off+len is greater
- * than the length of the array b, then an
- * IndexOutOfBoundsException is thrown.
- * <p>
- * If len is zero, then no bytes are read and 0 is returned;
- * otherwise, there is an attempt to read at least one byte. If no
- * byte is available because the stream is at end of file, the
- * value -1 is returned; otherwise, at least one byte is read and
- * stored into b.
- * <p>
- * The first byte read is stored into element b[off], the next one
- * into b[off+1], and so on. The number of bytes read is, at most,
- * equal to len. Let k be the number of bytes actually read; these
- * bytes will be stored in elements b[off] through b[off+k-1],
- * leaving elements b[off+k] through b[off+len-1] unaffected.
- * <p>
- * In every case, elements b[0] through b[off] and elements
- * b[off+len] through b[b.length-1] are unaffected.
- * <p>
- * If the first byte cannot be read for any reason other than end
- * of file, then an IOException is thrown. In particular, an
- * IOException is thrown if the input stream has been closed.
- *
- * @param b the buffer into which the data is read.
- * @param off the start offset in array b at which the data is
- * written.
- * @param len the maximum number of bytes to read.
- *
- * @return the total number of bytes read into the buffer, or -1
- * if there is no more data because the end of the stream
- * has been reached.
- *
- * @exception IOException
- * @exception NullPointerException
- * @exception IndexOutOfBoundsException
- */
-
- public int read(final byte [] b, final int off, final int len)
- throws IOException, NullPointerException, IndexOutOfBoundsException
- {
- dieIfClosed();
- if (b == null)
- {
- throw new NullPointerException("buffer is 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 EOD;
- }
- int limit = Math.min(available(), len);
-
- if ((off == 0) && (limit == b.length))
- {
- _document.read(b, _current_offset);
- }
- else
- {
- byte[] buffer = new byte[ limit ];
-
- _document.read(buffer, _current_offset);
- System.arraycopy(buffer, 0, b, off, limit);
- }
- _current_offset += limit;
- return limit;
- }
-
- /**
- * Repositions this stream to the position at the time the mark
- * method was last called on this input stream.
- * <p>
- * The general contract of reset is:
- * <p>
- * <ul>
- * <li>
- * If the method markSupported returns true, then:
- * <ul>
- * <li>
- * If the method mark has not been called since the
- * stream was created, or the number of bytes read
- * from the stream since mark was last called is
- * larger than the argument to mark at that last
- * call, then an IOException might be thrown.
- * </li>
- * <li>
- * If such an IOException is not thrown, then the
- * stream is reset to a state such that all the
- * bytes read since the most recent call to mark
- * (or since the start of the file, if mark has not
- * been called) will be resupplied to subsequent
- * callers of the read method, followed by any
- * bytes that otherwise would have been the next
- * input data as of the time of the call to reset.
- * </li>
- * </ul>
- * </li>
- * <li>
- * If the method markSupported returns false, then:
- * <ul>
- * <li>
- * The call to reset may throw an IOException.
- * </li>
- * <li>
- * If an IOException is not thrown, then the
- * stream is reset to a fixed state that depends
- * on the particular type of the input and how it
- * was created. The bytes that will be supplied to
- * subsequent callers of the read method depend on
- * the particular type of the input stream.
- * </li>
- * </ul>
- * </li>
- * </ul>
- * <p>
- * All well and good ... this class's markSupported method returns
- * true and this method does not care whether you've called mark
- * at all, or whether you've exceeded the number of bytes
- * specified in the last call to mark. We're basically walking a
- * byte array ... mark and reset to your heart's content.
- */
-
- public void reset()
- {
- _current_offset = _marked_offset;
- }
-
- /**
- * Skips over and discards n bytes of data from this input
- * stream. The skip method may, for a variety of reasons, end up
- * skipping over some smaller number of bytes, possibly 0. This
- * may result from any of a number of conditions; reaching end of
- * file before n bytes have been skipped is only one
- * possibility. The actual number of bytes skipped is returned. If
- * n is negative, no bytes are skipped.
- *
- * @param n the number of bytes to be skipped.
- *
- * @return the actual number of bytes skipped.
- *
- * @exception IOException
- */
-
- public long skip(final 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;
- 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;
- }
-} // end public class DocumentInputStream
-
+public final class DocumentInputStream 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;
+
+ /** 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 DocumentInputStream(DocumentEntry document) throws IOException {
+ if (!(document instanceof DocumentNode)) {
+ throw new IOException("Cannot open internal document storage");
+ }
+ _current_offset = 0;
+ _marked_offset = 0;
+ _document_size = document.getSize();
+ _closed = false;
+ _document = ((DocumentNode) document).getDocument();
+ _currentBlock = getDataInputBlock(0);
+ }
+
+ /**
+ * Create an InputStream from the specified Document
+ *
+ * @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);
+ }
+
+ public int available() {
+ if (_closed) {
+ throw new IllegalStateException("cannot perform requested operation on a closed stream");
+ }
+ return _document_size - _current_offset;
+ }
+
+ public void close() {
+ _closed = true;
+ }
+
+ public void mark(int ignoredReadlimit) {
+ _marked_offset = _current_offset;
+ }
+
+ /**
+ * Tests if this input stream supports the mark and reset methods.
+ *
+ * @return <code>true</code> always
+ */
+ public boolean markSupported() {
+ 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;
+ }
+
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ 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.
+ */
+ public void reset() {
+ _current_offset = _marked_offset;
+ _currentBlock = getDataInputBlock(_current_offset);
+ }
+
+ 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");
+ }
+ }
+
+ 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();
+ }
+
+ 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();
+ }
+ }
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ public int readUByte() {
+ checkAvaliable(1);
+ int result = _currentBlock.readUByte();
+ _current_offset++;
+ if (_currentBlock.available() < 1) {
+ _currentBlock = getDataInputBlock(_current_offset);
+ }
+ return result;
+ }
+}
Modified: poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java Sun Oct 26 00:18:17 2008
@@ -1,4 +1,3 @@
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,21 +14,26 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.filesystem;
-import java.io.*;
-
-import java.util.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.property.DocumentProperty;
import org.apache.poi.poifs.property.Property;
import org.apache.poi.poifs.storage.BlockWritable;
-import org.apache.poi.poifs.storage.ListManagedBlock;
+import org.apache.poi.poifs.storage.DataInputBlock;
import org.apache.poi.poifs.storage.DocumentBlock;
+import org.apache.poi.poifs.storage.ListManagedBlock;
import org.apache.poi.poifs.storage.RawDataBlock;
import org.apache.poi.poifs.storage.SmallDocumentBlock;
import org.apache.poi.util.HexDump;
@@ -39,595 +43,488 @@
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
-
-public class POIFSDocument
- implements BATManaged, BlockWritable, POIFSViewable
-{
- private DocumentProperty _property;
- private int _size;
-
- // one of these stores will be valid
- private SmallBlockStore _small_store;
- private BigBlockStore _big_store;
-
- /**
- * Constructor from large blocks
- *
- * @param name the name of the POIFSDocument
- * @param blocks the big blocks making up the POIFSDocument
- * @param length the actual length of the POIFSDocument
- *
- * @exception IOException
- */
-
- public POIFSDocument(final String name, final RawDataBlock [] blocks,
- final int length)
- throws IOException
- {
- _size = length;
- _big_store = new BigBlockStore(blocks);
- _property = new DocumentProperty(name, _size);
- _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
- _property.setDocument(this);
- }
-
- /**
- * Constructor from small blocks
- *
- * @param name the name of the POIFSDocument
- * @param blocks the small blocks making up the POIFSDocument
- * @param length the actual length of the POIFSDocument
- */
-
- public POIFSDocument(final String name,
- final SmallDocumentBlock [] blocks, final int length)
- {
- _size = length;
- try
- {
- _big_store = new BigBlockStore(new RawDataBlock[ 0 ]);
- }
- catch (IOException ignored)
- {
-
- // can't happen with that constructor
- }
- _property = new DocumentProperty(name, _size);
- _small_store = new SmallBlockStore(blocks);
- _property.setDocument(this);
- }
-
- /**
- * Constructor from small blocks
- *
- * @param name the name of the POIFSDocument
- * @param blocks the small blocks making up the POIFSDocument
- * @param length the actual length of the POIFSDocument
- *
- * @exception IOException
- */
-
- public POIFSDocument(final String name, final ListManagedBlock [] blocks,
- final int length)
- throws IOException
- {
- _size = length;
- _property = new DocumentProperty(name, _size);
- _property.setDocument(this);
- if (Property.isSmall(_size))
- {
- _big_store = new BigBlockStore(new RawDataBlock[ 0 ]);
- _small_store = new SmallBlockStore(blocks);
- }
- else
- {
- _big_store = new BigBlockStore(blocks);
- _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
- }
- }
-
- /**
- * Constructor
- *
- * @param name the name of the POIFSDocument
- * @param stream the InputStream we read data from
- *
- * @exception IOException thrown on read errors
- */
-
- public POIFSDocument(final String name, final InputStream stream)
- throws IOException
- {
- List blocks = new ArrayList();
-
- _size = 0;
- while (true)
- {
- DocumentBlock block = new DocumentBlock(stream);
- int blockSize = block.size();
-
- if (blockSize > 0)
- {
- blocks.add(block);
- _size += blockSize;
- }
- if (block.partiallyRead())
- {
- break;
- }
- }
- DocumentBlock[] bigBlocks =
- ( DocumentBlock [] ) blocks.toArray(new DocumentBlock[ 0 ]);
-
- _big_store = new BigBlockStore(bigBlocks);
- _property = new DocumentProperty(name, _size);
- _property.setDocument(this);
- if (_property.shouldUseSmallBlocks())
- {
- _small_store =
- new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks,
- _size));
- _big_store = new BigBlockStore(new DocumentBlock[ 0 ]);
- }
- else
- {
- _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
- }
- }
-
- /**
- * Constructor
- *
- * @param name the name of the POIFSDocument
- * @param size the length of the POIFSDocument
- * @param path the path of the POIFSDocument
- * @param writer the writer who will eventually write the document
- * contents
- *
- * @exception IOException thrown on read errors
- */
-
- public POIFSDocument(final String name, final int size,
- final POIFSDocumentPath path,
- final POIFSWriterListener writer)
- throws IOException
- {
- _size = size;
- _property = new DocumentProperty(name, _size);
- _property.setDocument(this);
- if (_property.shouldUseSmallBlocks())
- {
- _small_store = new SmallBlockStore(path, name, size, writer);
- _big_store = new BigBlockStore(new Object[ 0 ]);
- }
- else
- {
- _small_store = new SmallBlockStore(new BlockWritable[ 0 ]);
- _big_store = new BigBlockStore(path, name, size, writer);
- }
- }
-
- /**
- * return the array of SmallDocumentBlocks used
- *
- * @return array of SmallDocumentBlocks; may be empty, cannot be null
- */
-
- public BlockWritable [] getSmallBlocks()
- {
- return _small_store.getBlocks();
- }
-
- /**
- * @return size of the document
- */
-
- public int getSize()
- {
- return _size;
- }
-
- /**
- * read data from the internal stores
- *
- * @param buffer the buffer to write to
- * @param offset the offset into our storage to read from
- */
-
- void read(final byte [] buffer, final int offset)
- {
- if (_property.shouldUseSmallBlocks())
- {
- SmallDocumentBlock.read(_small_store.getBlocks(), buffer, offset);
- }
- else
- {
- DocumentBlock.read(_big_store.getBlocks(), buffer, offset);
- }
- }
-
- /**
- * Get the DocumentProperty
- *
- * @return the instance's DocumentProperty
- */
-
- DocumentProperty getDocumentProperty()
- {
- return _property;
- }
-
- /* ********** START implementation of BlockWritable ********** */
-
- /**
- * Write the storage to an OutputStream
- *
- * @param stream the OutputStream to which the stored data should
- * be written
- *
- * @exception IOException on problems writing to the specified
- * stream
- */
-
- public void writeBlocks(final OutputStream stream)
- throws IOException
- {
- _big_store.writeBlocks(stream);
- }
-
- /* ********** END implementation of BlockWritable ********** */
- /* ********** START implementation of BATManaged ********** */
-
- /**
- * Return the number of BigBlock's this instance uses
- *
- * @return count of BigBlock instances
- */
-
- public int countBlocks()
- {
- return _big_store.countBlocks();
- }
-
- /**
- * Set the start block for this instance
- *
- * @param index index into the array of blocks making up the
- * filesystem
- */
-
- public void setStartBlock(final int index)
- {
- _property.setStartBlock(index);
- }
-
- /* ********** END implementation of BATManaged ********** */
- /* ********** START begin implementation of POIFSViewable ********** */
-
- /**
- * Get an array of objects, some of which may implement
- * POIFSViewable
- *
- * @return an array of Object; may not be null, but may be empty
- */
-
- public Object [] getViewableArray()
- {
- Object[] results = new Object[ 1 ];
- String result;
-
- try
- {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- BlockWritable[] blocks = null;
-
- if (_big_store.isValid())
- {
- blocks = _big_store.getBlocks();
- }
- else if (_small_store.isValid())
- {
- blocks = _small_store.getBlocks();
- }
- if (blocks != null)
- {
- for (int k = 0; k < blocks.length; k++)
- {
- blocks[ k ].writeBlocks(output);
- }
- byte[] data = output.toByteArray();
-
- if (data.length > _property.getSize())
- {
- byte[] tmp = new byte[ _property.getSize() ];
-
- System.arraycopy(data, 0, tmp, 0, tmp.length);
- data = tmp;
- }
- output = new ByteArrayOutputStream();
- HexDump.dump(data, 0, output, 0);
- result = output.toString();
- }
- else
- {
- result = "<NO DATA>";
- }
- }
- catch (IOException e)
- {
- result = e.getMessage();
- }
- results[ 0 ] = result;
- return results;
- }
-
- /**
- * Get an Iterator of objects, some of which may implement
- * POIFSViewable
- *
- * @return an Iterator; may not be null, but may have an empty
- * back end store
- */
-
- public Iterator getViewableIterator()
- {
- return Collections.EMPTY_LIST.iterator();
- }
-
- /**
- * Give viewers a hint as to whether to call getViewableArray or
- * getViewableIterator
- *
- * @return true if a viewer should call getViewableArray, false if
- * a viewer should call getViewableIterator
- */
-
- public boolean preferArray()
- {
- return true;
- }
-
- /**
- * Provides a short description of the object, to be used when a
- * POIFSViewable object has not provided its contents.
- *
- * @return short description
- */
-
- public String getShortDescription()
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("Document: \"").append(_property.getName())
- .append("\"");
- buffer.append(" size = ").append(getSize());
- return buffer.toString();
- }
-
- /* ********** END begin implementation of POIFSViewable ********** */
- private class SmallBlockStore
- {
- private SmallDocumentBlock[] smallBlocks;
- private POIFSDocumentPath path;
- private String name;
- private int size;
- private POIFSWriterListener writer;
-
- /**
- * Constructor
- *
- * @param blocks blocks to construct the store from
- */
-
- SmallBlockStore(final Object [] blocks)
- {
- smallBlocks = new SmallDocumentBlock[ blocks.length ];
- for (int j = 0; j < blocks.length; j++)
- {
- smallBlocks[ j ] = ( SmallDocumentBlock ) blocks[ j ];
- }
- this.path = null;
- this.name = null;
- this.size = -1;
- this.writer = null;
- }
-
- /**
- * Constructor for a small block store that will be written
- * later
- *
- * @param path path of the document
- * @param name name of the document
- * @param size length of the document
- * @param writer the object that will eventually write the document
- */
-
- SmallBlockStore(final POIFSDocumentPath path, final String name,
- final int size, final POIFSWriterListener writer)
- {
- smallBlocks = new SmallDocumentBlock[ 0 ];
- this.path = path;
- this.name = name;
- this.size = size;
- this.writer = writer;
- }
-
- /**
- * @return true if this store is a valid source of data
- */
-
- boolean isValid()
- {
- return ((smallBlocks.length > 0) || (writer != null));
- }
-
- /**
- * @return the SmallDocumentBlocks
- */
-
- BlockWritable [] getBlocks()
- {
- if (isValid() && (writer != null))
- {
- ByteArrayOutputStream stream =
- new ByteArrayOutputStream(size);
- DocumentOutputStream dstream =
- new DocumentOutputStream(stream, size);
-
- writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream,
- path, name, size));
- smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(),
- size);
- }
- return smallBlocks;
- }
- } // end private class SmallBlockStore
-
- private class BigBlockStore
- {
- private DocumentBlock[] bigBlocks;
- private POIFSDocumentPath path;
- private String name;
- private int size;
- private POIFSWriterListener writer;
-
- /**
- * Constructor
- *
- * @param blocks the blocks making up the store
- *
- * @exception IOException on I/O error
- */
-
- BigBlockStore(final Object [] blocks)
- throws IOException
- {
- bigBlocks = new DocumentBlock[ blocks.length ];
- for (int j = 0; j < blocks.length; j++)
- {
- if (blocks[ j ] instanceof DocumentBlock)
- {
- bigBlocks[ j ] = ( DocumentBlock ) blocks[ j ];
- }
- else
- {
- bigBlocks[ j ] =
- new DocumentBlock(( RawDataBlock ) blocks[ j ]);
- }
- }
- this.path = null;
- this.name = null;
- this.size = -1;
- this.writer = null;
- }
-
- /**
- * Constructor for a big block store that will be written
- * later
- *
- * @param path path of the document
- * @param name name of the document
- * @param size length of the document
- * @param writer the object that will eventually write the
- * document
- */
-
- BigBlockStore(final POIFSDocumentPath path, final String name,
- final int size, final POIFSWriterListener writer)
- {
- bigBlocks = new DocumentBlock[ 0 ];
- this.path = path;
- this.name = name;
- this.size = size;
- this.writer = writer;
- }
-
- /**
- * @return true if this store is a valid source of data
- */
-
- boolean isValid()
- {
- return ((bigBlocks.length > 0) || (writer != null));
- }
-
- /**
- * @return the DocumentBlocks
- */
-
- DocumentBlock [] getBlocks()
- {
- if (isValid() && (writer != null))
- {
- ByteArrayOutputStream stream =
- new ByteArrayOutputStream(size);
- DocumentOutputStream dstream =
- new DocumentOutputStream(stream, size);
-
- writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream,
- path, name, size));
- bigBlocks = DocumentBlock.convert(stream.toByteArray(), size);
- }
- return bigBlocks;
- }
-
- /**
- * write the blocks to a stream
- *
- * @param stream the stream to which the data is to be written
- *
- * @exception IOException on error
- */
-
- void writeBlocks(OutputStream stream)
- throws IOException
- {
- if (isValid())
- {
- if (writer != null)
- {
- DocumentOutputStream dstream =
- new DocumentOutputStream(stream, size);
-
- writer.processPOIFSWriterEvent(
- new POIFSWriterEvent(dstream, path, name, size));
- dstream.writeFiller(countBlocks()
- * POIFSConstants
- .BIG_BLOCK_SIZE, DocumentBlock
- .getFillByte());
- }
- else
- {
- for (int k = 0; k < bigBlocks.length; k++)
- {
- bigBlocks[ k ].writeBlocks(stream);
- }
- }
- }
- }
-
- /**
- * @return number of big blocks making up this document
- */
-
- int countBlocks()
- {
- int rval = 0;
-
- if (isValid())
- {
- if (writer != null)
- {
- rval = (size + POIFSConstants.BIG_BLOCK_SIZE - 1)
- / POIFSConstants.BIG_BLOCK_SIZE;
- }
- else
- {
- rval = bigBlocks.length;
- }
- }
- return rval;
- }
- } // end private class BigBlockStore
-} // end class POIFSDocument
-
+public final class POIFSDocument implements BATManaged, BlockWritable, POIFSViewable {
+ private static final DocumentBlock[] EMPTY_BIG_BLOCK_ARRAY = { };
+ private static final SmallDocumentBlock[] EMPTY_SMALL_BLOCK_ARRAY = { };
+ private DocumentProperty _property;
+ private int _size;
+
+ // one of these stores will be valid
+ private SmallBlockStore _small_store;
+ private BigBlockStore _big_store;
+
+ /**
+ * Constructor from large blocks
+ *
+ * @param name the name of the POIFSDocument
+ * @param blocks the big blocks making up the POIFSDocument
+ * @param length the actual length of the POIFSDocument
+ */
+ public POIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException {
+ _size = length;
+ _big_store = new BigBlockStore(convertRawBlocksToBigBlocks(blocks));
+ _property = new DocumentProperty(name, _size);
+ _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
+ _property.setDocument(this);
+ }
+
+ // TODO - awkward typing going on here
+ private static DocumentBlock[] convertRawBlocksToBigBlocks(ListManagedBlock[] blocks) throws IOException {
+ DocumentBlock[] result = new DocumentBlock[blocks.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = new DocumentBlock((RawDataBlock)blocks[i]);
+ }
+ return result;
+ }
+ private static SmallDocumentBlock[] convertRawBlocksToSmallBlocks(ListManagedBlock[] blocks) {
+ if (blocks instanceof SmallDocumentBlock[]) {
+ return (SmallDocumentBlock[]) blocks;
+ }
+ SmallDocumentBlock[] result = new SmallDocumentBlock[blocks.length];
+ System.arraycopy(blocks, 0, result, 0, blocks.length);
+ return result;
+ }
+
+ /**
+ * Constructor from small blocks
+ *
+ * @param name the name of the POIFSDocument
+ * @param blocks the small blocks making up the POIFSDocument
+ * @param length the actual length of the POIFSDocument
+ */
+ public POIFSDocument(String name, SmallDocumentBlock[] blocks, int length) {
+ _size = length;
+ _big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY);
+ _property = new DocumentProperty(name, _size);
+ _small_store = new SmallBlockStore(blocks);
+ _property.setDocument(this);
+ }
+
+ /**
+ * Constructor from small blocks
+ *
+ * @param name the name of the POIFSDocument
+ * @param blocks the small blocks making up the POIFSDocument
+ * @param length the actual length of the POIFSDocument
+ */
+ public POIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException {
+ _size = length;
+ _property = new DocumentProperty(name, _size);
+ _property.setDocument(this);
+ if (Property.isSmall(_size)) {
+ _big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY);
+ _small_store = new SmallBlockStore(convertRawBlocksToSmallBlocks(blocks));
+ } else {
+ _big_store = new BigBlockStore(convertRawBlocksToBigBlocks(blocks));
+ _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name the name of the POIFSDocument
+ * @param stream the InputStream we read data from
+ */
+ public POIFSDocument(String name, InputStream stream) throws IOException {
+ List blocks = new ArrayList();
+
+ _size = 0;
+ while (true) {
+ DocumentBlock block = new DocumentBlock(stream);
+ int blockSize = block.size();
+
+ if (blockSize > 0) {
+ blocks.add(block);
+ _size += blockSize;
+ }
+ if (block.partiallyRead()) {
+ break;
+ }
+ }
+ DocumentBlock[] bigBlocks = (DocumentBlock[]) blocks.toArray(new DocumentBlock[blocks.size()]);
+
+ _big_store = new BigBlockStore(bigBlocks);
+ _property = new DocumentProperty(name, _size);
+ _property.setDocument(this);
+ if (_property.shouldUseSmallBlocks()) {
+ _small_store = new SmallBlockStore(SmallDocumentBlock.convert(bigBlocks, _size));
+ _big_store = new BigBlockStore(new DocumentBlock[0]);
+ } else {
+ _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name the name of the POIFSDocument
+ * @param size the length of the POIFSDocument
+ * @param path the path of the POIFSDocument
+ * @param writer the writer who will eventually write the document contents
+ */
+ public POIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) {
+ _size = size;
+ _property = new DocumentProperty(name, _size);
+ _property.setDocument(this);
+ if (_property.shouldUseSmallBlocks()) {
+ _small_store = new SmallBlockStore(path, name, size, writer);
+ _big_store = new BigBlockStore(EMPTY_BIG_BLOCK_ARRAY);
+ } else {
+ _small_store = new SmallBlockStore(EMPTY_SMALL_BLOCK_ARRAY);
+ _big_store = new BigBlockStore(path, name, size, writer);
+ }
+ }
+
+ /**
+ * @return array of SmallDocumentBlocks; may be empty, cannot be null
+ */
+ public BlockWritable[] getSmallBlocks() {
+ return _small_store.getBlocks();
+ }
+
+ /**
+ * @return size of the document
+ */
+ public int getSize() {
+ return _size;
+ }
+
+ /**
+ * read data from the internal stores
+ *
+ * @param buffer the buffer to write to
+ * @param offset the offset into our storage to read from
+ * This method is currently (Oct 2008) only used by test code. Perhaps it can be deleted
+ */
+ void read(byte[] buffer, int offset) {
+ int len = buffer.length;
+
+ DataInputBlock currentBlock = getDataInputBlock(offset);
+
+ int blockAvailable = currentBlock.available();
+ if (blockAvailable > len) {
+ currentBlock.readFully(buffer, 0, len);
+ return;
+ }
+ // else read big amount in chunks
+ int remaining = len;
+ int writePos = 0;
+ int currentOffset = offset;
+ while (remaining > 0) {
+ boolean blockIsExpiring = remaining >= blockAvailable;
+ int reqSize;
+ if (blockIsExpiring) {
+ reqSize = blockAvailable;
+ } else {
+ reqSize = remaining;
+ }
+ currentBlock.readFully(buffer, writePos, reqSize);
+ remaining-=reqSize;
+ writePos+=reqSize;
+ currentOffset += reqSize;
+ if (blockIsExpiring) {
+ if (currentOffset == _size) {
+ if (remaining > 0) {
+ throw new IllegalStateException("reached end of document stream unexpectedly");
+ }
+ currentBlock = null;
+ break;
+ }
+ currentBlock = getDataInputBlock(currentOffset);
+ blockAvailable = currentBlock.available();
+ }
+ }
+ }
+
+ /**
+ * @return <code>null</code> if <tt>offset</tt> points to the end of the document stream
+ */
+ DataInputBlock getDataInputBlock(int offset) {
+ if (offset >= _size) {
+ if (offset > _size) {
+ throw new RuntimeException("Request for Offset " + offset + " doc size is " + _size);
+ }
+ return null;
+ }
+ if (_property.shouldUseSmallBlocks()) {
+ return SmallDocumentBlock.getDataInputBlock(_small_store.getBlocks(), offset);
+ } else {
+ return DocumentBlock.getDataInputBlock(_big_store.getBlocks(), offset);
+ }
+ }
+
+ /**
+ * @return the instance's DocumentProperty
+ */
+
+ DocumentProperty getDocumentProperty() {
+ return _property;
+ }
+
+ /* ********** START implementation of BlockWritable ********** */
+
+ /**
+ * Write the storage to an OutputStream
+ *
+ * @param stream the OutputStream to which the stored data should be written
+ */
+ public void writeBlocks(OutputStream stream) throws IOException {
+ _big_store.writeBlocks(stream);
+ }
+
+ /* ********** END implementation of BlockWritable ********** */
+ /* ********** START implementation of BATManaged ********** */
+
+ /**
+ * Return the number of BigBlock's this instance uses
+ *
+ * @return count of BigBlock instances
+ */
+ public int countBlocks() {
+ return _big_store.countBlocks();
+ }
+
+ /**
+ * Set the start block for this instance
+ *
+ * @param index index into the array of blocks making up the filesystem
+ */
+ public void setStartBlock(int index) {
+ _property.setStartBlock(index);
+ }
+
+ /* ********** END implementation of BATManaged ********** */
+ /* ********** START begin implementation of POIFSViewable ********** */
+
+ /**
+ * Get an array of objects, some of which may implement POIFSViewable
+ *
+ * @return an array of Object; may not be null, but may be empty
+ */
+ public Object[] getViewableArray() {
+ Object[] results = new Object[1];
+ String result;
+
+ try {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ BlockWritable[] blocks = null;
+
+ if (_big_store.isValid()) {
+ blocks = _big_store.getBlocks();
+ } else if (_small_store.isValid()) {
+ blocks = _small_store.getBlocks();
+ }
+ if (blocks != null) {
+ for (int k = 0; k < blocks.length; k++) {
+ blocks[k].writeBlocks(output);
+ }
+ byte[] data = output.toByteArray();
+
+ if (data.length > _property.getSize()) {
+ byte[] tmp = new byte[_property.getSize()];
+
+ System.arraycopy(data, 0, tmp, 0, tmp.length);
+ data = tmp;
+ }
+ output = new ByteArrayOutputStream();
+ HexDump.dump(data, 0, output, 0);
+ result = output.toString();
+ } else {
+ result = "<NO DATA>";
+ }
+ } catch (IOException e) {
+ result = e.getMessage();
+ }
+ results[0] = result;
+ return results;
+ }
+
+ /**
+ * Get an Iterator of objects, some of which may implement POIFSViewable
+ *
+ * @return an Iterator; may not be null, but may have an empty back end
+ * store
+ */
+ public Iterator getViewableIterator() {
+ return Collections.EMPTY_LIST.iterator();
+ }
+
+ /**
+ * Give viewers a hint as to whether to call getViewableArray or
+ * getViewableIterator
+ *
+ * @return <code>true</code> if a viewer should call getViewableArray,
+ * <code>false</code> if a viewer should call getViewableIterator
+ */
+ public boolean preferArray() {
+ return true;
+ }
+
+ /**
+ * Provides a short description of the object, to be used when a
+ * POIFSViewable object has not provided its contents.
+ *
+ * @return short description
+ */
+ public String getShortDescription() {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("Document: \"").append(_property.getName()).append("\"");
+ buffer.append(" size = ").append(getSize());
+ return buffer.toString();
+ }
+
+ /* ********** END begin implementation of POIFSViewable ********** */
+ private static final class SmallBlockStore {
+ private SmallDocumentBlock[] smallBlocks;
+ private final POIFSDocumentPath path;
+ private final String name;
+ private final int size;
+ private final POIFSWriterListener writer;
+
+ /**
+ * Constructor
+ *
+ * @param blocks blocks to construct the store from
+ */
+ SmallBlockStore(SmallDocumentBlock[] blocks) {
+ smallBlocks = (SmallDocumentBlock[]) blocks.clone();
+ this.path = null;
+ this.name = null;
+ this.size = -1;
+ this.writer = null;
+ }
+
+ /**
+ * Constructor for a small block store that will be written later
+ *
+ * @param path path of the document
+ * @param name name of the document
+ * @param size length of the document
+ * @param writer the object that will eventually write the document
+ */
+ SmallBlockStore(POIFSDocumentPath path, String name, int size, POIFSWriterListener writer) {
+ smallBlocks = new SmallDocumentBlock[0];
+ this.path = path;
+ this.name = name;
+ this.size = size;
+ this.writer = writer;
+ }
+
+ /**
+ * @return <code>true</code> if this store is a valid source of data
+ */
+ boolean isValid() {
+ return smallBlocks.length > 0 || writer != null;
+ }
+
+ /**
+ * @return the SmallDocumentBlocks
+ */
+ SmallDocumentBlock[] getBlocks() {
+ if (isValid() && writer != null) {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream(size);
+ DocumentOutputStream dstream = new DocumentOutputStream(stream, size);
+
+ writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, path, name, size));
+ smallBlocks = SmallDocumentBlock.convert(stream.toByteArray(), size);
+ }
+ return smallBlocks;
+ }
+ } // end private class SmallBlockStore
+
+ private static final class BigBlockStore {
+ private DocumentBlock[] bigBlocks;
+ private final POIFSDocumentPath path;
+ private final String name;
+ private final int size;
+ private final POIFSWriterListener writer;
+
+ /**
+ * Constructor
+ *
+ * @param blocks the blocks making up the store
+ */
+ BigBlockStore(DocumentBlock[] blocks) {
+ bigBlocks = (DocumentBlock[]) blocks.clone();
+ this.path = null;
+ this.name = null;
+ this.size = -1;
+ this.writer = null;
+ }
+
+ /**
+ * Constructor for a big block store that will be written later
+ *
+ * @param path path of the document
+ * @param name name of the document
+ * @param size length of the document
+ * @param writer the object that will eventually write the document
+ */
+ BigBlockStore(POIFSDocumentPath path, String name, int size, POIFSWriterListener writer) {
+ bigBlocks = new DocumentBlock[0];
+ this.path = path;
+ this.name = name;
+ this.size = size;
+ this.writer = writer;
+ }
+
+ /**
+ * @return <code>true</code> if this store is a valid source of data
+ */
+ boolean isValid() {
+ return bigBlocks.length > 0 || writer != null;
+ }
+
+ /**
+ * @return the DocumentBlocks
+ */
+ DocumentBlock[] getBlocks() {
+ if (isValid() && writer != null) {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream(size);
+ DocumentOutputStream dstream = new DocumentOutputStream(stream, size);
+
+ writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, path, name, size));
+ bigBlocks = DocumentBlock.convert(stream.toByteArray(), size);
+ }
+ return bigBlocks;
+ }
+
+ /**
+ * write the blocks to a stream
+ *
+ * @param stream the stream to which the data is to be written
+ */
+ void writeBlocks(OutputStream stream) throws IOException {
+ if (isValid()) {
+ if (writer != null) {
+ DocumentOutputStream dstream = new DocumentOutputStream(stream, size);
+
+ writer.processPOIFSWriterEvent(new POIFSWriterEvent(dstream, path, name, size));
+ dstream.writeFiller(countBlocks() * POIFSConstants.BIG_BLOCK_SIZE,
+ DocumentBlock.getFillByte());
+ } else {
+ for (int k = 0; k < bigBlocks.length; k++) {
+ bigBlocks[k].writeBlocks(stream);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return number of big blocks making up this document
+ */
+ int countBlocks() {
+
+ if (isValid()) {
+ if (writer == null) {
+ return bigBlocks.length;
+ }
+ return (size + POIFSConstants.BIG_BLOCK_SIZE - 1)
+ / POIFSConstants.BIG_BLOCK_SIZE;
+ }
+ return 0;
+ }
+ } // end private class BigBlockStore
+}
Modified: poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/DocumentBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/DocumentBlock.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/DocumentBlock.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/DocumentBlock.java Sun Oct 26 00:18:17 2008
@@ -1,4 +1,3 @@
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,31 +14,27 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-
import java.util.Arrays;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.IntegerField;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.LittleEndianConsts;
/**
* A block of document data.
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
+public final class DocumentBlock extends BigBlock {
+ private static final int BLOCK_SHIFT = 9;
+ private static final int BLOCK_SIZE = 1 << BLOCK_SHIFT;
+ private static final int BLOCK_MASK = BLOCK_SIZE-1;
-public class DocumentBlock
- extends BigBlock
-{
private static final byte _default_value = ( byte ) 0xFF;
private byte[] _data;
private int _bytes_read;
@@ -161,45 +156,10 @@
return rval;
}
- /**
- * read data from an array of DocumentBlocks
- *
- * @param blocks the blocks to read from
- * @param buffer the buffer to write the data into
- * @param offset the offset into the array of blocks to read from
- */
-
- public static void read(final DocumentBlock [] blocks,
- final byte [] buffer, final int offset)
- {
- int firstBlockIndex = offset / POIFSConstants.BIG_BLOCK_SIZE;
- int firstBlockOffset = offset % POIFSConstants.BIG_BLOCK_SIZE;
- int lastBlockIndex = (offset + buffer.length - 1)
- / POIFSConstants.BIG_BLOCK_SIZE;
-
- if (firstBlockIndex == lastBlockIndex)
- {
- System.arraycopy(blocks[ firstBlockIndex ]._data,
- firstBlockOffset, buffer, 0, buffer.length);
- }
- else
- {
- int buffer_offset = 0;
-
- System.arraycopy(blocks[ firstBlockIndex ]._data,
- firstBlockOffset, buffer, buffer_offset,
- POIFSConstants.BIG_BLOCK_SIZE
- - firstBlockOffset);
- buffer_offset += POIFSConstants.BIG_BLOCK_SIZE - firstBlockOffset;
- for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++)
- {
- System.arraycopy(blocks[ j ]._data, 0, buffer, buffer_offset,
- POIFSConstants.BIG_BLOCK_SIZE);
- buffer_offset += POIFSConstants.BIG_BLOCK_SIZE;
- }
- System.arraycopy(blocks[ lastBlockIndex ]._data, 0, buffer,
- buffer_offset, buffer.length - buffer_offset);
- }
+ public static DataInputBlock getDataInputBlock(DocumentBlock[] blocks, int offset) {
+ int firstBlockIndex = offset >> BLOCK_SHIFT;
+ int firstBlockOffset= offset & BLOCK_MASK;
+ return new DataInputBlock(blocks[firstBlockIndex]._data, firstBlockOffset);
}
/* ********** START extension of BigBlock ********** */
Modified: poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java Sun Oct 26 00:18:17 2008
@@ -1,4 +1,3 @@
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,13 +14,15 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.poifs.storage;
-import java.io.*;
-
-import java.util.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.apache.poi.poifs.common.POIFSConstants;
@@ -31,13 +32,14 @@
*
* @author Marc Johnson (mjohnson at apache dot org)
*/
+public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock {
+ private static final int BLOCK_SHIFT = 6;
-public class SmallDocumentBlock
- implements BlockWritable, ListManagedBlock
-{
private byte[] _data;
private static final byte _default_fill = ( byte ) 0xff;
- private static final int _block_size = 64;
+ private static final int _block_size = 1 << BLOCK_SHIFT;
+ private static final int BLOCK_MASK = _block_size-1;
+
private static final int _blocks_per_big_block =
POIFSConstants.BIG_BLOCK_SIZE / _block_size;
@@ -178,46 +180,10 @@
return sdbs;
}
- /**
- * read data from an array of SmallDocumentBlocks
- *
- * @param blocks the blocks to read from
- * @param buffer the buffer to write the data into
- * @param offset the offset into the array of blocks to read from
- */
-
- public static void read(final BlockWritable [] blocks,
- final byte [] buffer, final int offset)
- {
- int firstBlockIndex = offset / _block_size;
- int firstBlockOffset = offset % _block_size;
- int lastBlockIndex = (offset + buffer.length - 1) / _block_size;
-
- if (firstBlockIndex == lastBlockIndex)
- {
- System.arraycopy(
- (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
- firstBlockOffset, buffer, 0, buffer.length);
- }
- else
- {
- int buffer_offset = 0;
-
- System.arraycopy(
- (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
- firstBlockOffset, buffer, buffer_offset,
- _block_size - firstBlockOffset);
- buffer_offset += _block_size - firstBlockOffset;
- for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++)
- {
- System.arraycopy((( SmallDocumentBlock ) blocks[ j ])._data,
- 0, buffer, buffer_offset, _block_size);
- buffer_offset += _block_size;
- }
- System.arraycopy(
- (( SmallDocumentBlock ) blocks[ lastBlockIndex ])._data, 0,
- buffer, buffer_offset, buffer.length - buffer_offset);
- }
+ public static DataInputBlock getDataInputBlock(SmallDocumentBlock[] blocks, int offset) {
+ int firstBlockIndex = offset >> BLOCK_SHIFT;
+ int firstBlockOffset= offset & BLOCK_MASK;
+ return new DataInputBlock(blocks[firstBlockIndex]._data, firstBlockOffset);
}
/**
Propchange: poi/branches/ooxml/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sun Oct 26 00:18:17 2008
@@ -1 +1 @@
-/poi/trunk/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java:703100-706540,706772-707481
+/poi/trunk/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java:703100-706540,706772-707481,707486-707802
Modified: poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java Sun Oct 26 00:18:17 2008
@@ -28,13 +28,12 @@
*@author Marc Johnson (mjohnson at apache dot org)
*@author Andrew Oliver (acoliver at apache dot org)
*/
-public final class LittleEndian implements LittleEndianConsts {
+public class LittleEndian implements LittleEndianConsts {
private LittleEndian() {
- // no instances of this class
+ // no instances of this class
}
-
/**
* get a short value from a byte array
*
@@ -42,9 +41,10 @@
*@param offset a starting offset into the byte array
*@return the short (16-bit) value
*/
-
- public static short getShort(final byte[] data, final int offset) {
- return (short) getNumber(data, offset, SHORT_SIZE);
+ public static short getShort(byte[] data, int offset) {
+ int b0 = data[offset] & 0xFF;
+ int b1 = data[offset+1] & 0xFF;
+ return (short) ((b1 << 8) + (b0 << 0));
}
@@ -55,73 +55,32 @@
*@param offset a starting offset into the byte array
*@return the unsigned short (16-bit) value in an integer
*/
- public static int getUShort(final byte[] data, final int offset) {
- short num = (short) getNumber(data, offset, SHORT_SIZE);
- int retNum;
- if (num < 0) {
- retNum = (Short.MAX_VALUE + 1) * 2 + num;
- } else {
- retNum = num;
- }
- return retNum;
- }
-
-
- /**
- * get a short array from a byte array.
- *
- *@param data Description of the Parameter
- *@param offset Description of the Parameter
- *@param size Description of the Parameter
- *@return The simpleShortArray value
- */
- public static short[] getSimpleShortArray(final byte[] data, final int offset, final int size) {
- short[] results = new short[size];
- for (int i = 0; i < size; i++) {
- results[i] = getShort(data, offset + 2 + (i * 2));
- }
- return results;
- }
-
-
- /**
- * get a short array from a byte array. The short array is assumed to start
- * with a word describing the length of the array.
- *
- *@param data Description of the Parameter
- *@param offset Description of the Parameter
- *@return The shortArray value
- */
- public static short[] getShortArray(final byte[] data, final int offset) {
- int size = (int) getNumber(data, offset, SHORT_SIZE);
- short[] results = getSimpleShortArray(data, offset, size);
- return results;
+ public static int getUShort(byte[] data, int offset) {
+ int b0 = data[offset] & 0xFF;
+ int b1 = data[offset+1] & 0xFF;
+ return (b1 << 8) + (b0 << 0);
}
-
/**
* get a short value from the beginning of a byte array
*
*@param data the byte array
*@return the short (16-bit) value
*/
-
- public static short getShort(final byte[] data) {
+ public static short getShort(byte[] data) {
return getShort(data, 0);
}
-
/**
* get an unsigned short value from the beginning of a byte array
*
*@param data the byte array
*@return the unsigned short (16-bit) value in an int
*/
- public static int getUShort(final byte[] data) {
+ public static int getUShort(byte[] data) {
return getUShort(data, 0);
}
-
/**
* get an int value from a byte array
*
@@ -129,9 +88,13 @@
*@param offset a starting offset into the byte array
*@return the int (32-bit) value
*/
-
- public static int getInt(final byte[] data, final int offset) {
- return (int) getNumber(data, offset, INT_SIZE);
+ public static int getInt(byte[] data, int offset) {
+ int i=offset;
+ int b0 = data[i++] & 0xFF;
+ int b1 = data[i++] & 0xFF;
+ int b2 = data[i++] & 0xFF;
+ int b3 = data[i++] & 0xFF;
+ return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
}
@@ -139,10 +102,9 @@
* get an int value from the beginning of a byte array
*
*@param data the byte array
- *@return the int (32-bit) value
+ *@return the int (32-bit) value
*/
-
- public static int getInt(final byte[] data) {
+ public static int getInt(byte[] data) {
return getInt(data, 0);
}
@@ -154,15 +116,9 @@
*@param offset a starting offset into the byte array
*@return the unsigned int (32-bit) value in a long
*/
- public static long getUInt(final byte[] data, final int offset) {
- int num = (int) getNumber(data, offset, INT_SIZE);
- long retNum;
- if (num < 0) {
- retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
- } else {
- retNum = num;
- }
- return retNum;
+ public static long getUInt(byte[] data, int offset) {
+ long retNum = getInt(data, offset);
+ return retNum & 0x00FFFFFFFF;
}
/**
@@ -171,8 +127,8 @@
*@param data the byte array
*@return the unsigned int (32-bit) value in a long
*/
- public static long getUInt(final byte[] data) {
- return getUInt(data,0);
+ public static long getUInt(byte[] data) {
+ return getUInt(data,0);
}
/**
@@ -182,24 +138,16 @@
*@param offset a starting offset into the byte array
*@return the long (64-bit) value
*/
-
- public static long getLong(final byte[] data, final int offset) {
- return getNumber(data, offset, LONG_SIZE);
- }
-
-
- /**
- * get a long value from the beginning of a byte array
- *
- *@param data the byte array
- *@return the long (64-bit) value
- */
-
- public static long getLong(final byte[] data) {
- return getLong(data, 0);
+ public static long getLong(byte[] data, int offset) {
+ long result = 0;
+
+ for (int j = offset + LONG_SIZE - 1; j >= offset; j--) {
+ result <<= 8;
+ result |= 0xff & data[j];
+ }
+ return result;
}
-
/**
* get a double value from a byte array, reads it in little endian format
* then converts the resulting revolting IEEE 754 (curse them) floating
@@ -209,24 +157,10 @@
*@param offset a starting offset into the byte array
*@return the double (64-bit) value
*/
-
- public static double getDouble(final byte[] data, final int offset) {
- return Double.longBitsToDouble(getNumber(data, offset, DOUBLE_SIZE));
- }
-
-
- /**
- * get a double value from the beginning of a byte array
- *
- *@param data the byte array
- *@return the double (64-bit) value
- */
-
- public static double getDouble(final byte[] data) {
- return getDouble(data, 0);
+ public static double getDouble(byte[] data, int offset) {
+ return Double.longBitsToDouble(getLong(data, offset));
}
-
/**
* put a short value into a byte array
*
@@ -234,9 +168,10 @@
*@param offset a starting offset into the byte array
*@param value the short (16-bit) value
*/
- public static void putShort(final byte[] data, final int offset,
- final short value) {
- putNumber(data, offset, value, SHORT_SIZE);
+ public static void putShort(byte[] data, int offset, short value) {
+ int i = offset;
+ data[i++] = (byte)((value >>> 0) & 0xFF);
+ data[i++] = (byte)((value >>> 8) & 0xFF);
}
/**
@@ -247,7 +182,7 @@
* Added for consistency with other put~() methods
*/
public static void putByte(byte[] data, int offset, int value) {
- putNumber(data, offset, value, LittleEndianConsts.BYTE_SIZE);
+ data[offset] = (byte) value;
}
/**
@@ -259,10 +194,10 @@
*
* @exception ArrayIndexOutOfBoundsException may be thrown
*/
- public static void putUShort(final byte[] data, final int offset,
- final int value)
- {
- putNumber(data, offset, value, SHORT_SIZE);
+ public static void putUShort(byte[] data, int offset, int value) {
+ int i = offset;
+ data[i++] = (byte)((value >>> 0) & 0xFF);
+ data[i++] = (byte)((value >>> 8) & 0xFF);
}
/**
@@ -271,8 +206,7 @@
*@param data the byte array
*@param value the short (16-bit) value
*/
-
- public static void putShort(final byte[] data, final short value) {
+ public static void putShort(byte[] data, short value) {
putShort(data, 0, value);
}
@@ -284,10 +218,12 @@
*@param offset a starting offset into the byte array
*@param value the int (32-bit) value
*/
-
- public static void putInt(final byte[] data, final int offset,
- final int value) {
- putNumber(data, offset, value, INT_SIZE);
+ public static void putInt(byte[] data, int offset, int value) {
+ int i = offset;
+ data[i++] = (byte)((value >>> 0) & 0xFF);
+ data[i++] = (byte)((value >>> 8) & 0xFF);
+ data[i++] = (byte)((value >>> 16) & 0xFF);
+ data[i++] = (byte)((value >>> 24) & 0xFF);
}
@@ -297,8 +233,7 @@
*@param data the byte array
*@param value the int (32-bit) value
*/
-
- public static void putInt(final byte[] data, final int value) {
+ public static void putInt(byte[] data, int value) {
putInt(data, 0, value);
}
@@ -310,22 +245,14 @@
*@param offset a starting offset into the byte array
*@param value the long (64-bit) value
*/
-
- public static void putLong(final byte[] data, final int offset,
- final long value) {
- putNumber(data, offset, value, LONG_SIZE);
- }
-
-
- /**
- * put a long value into beginning of a byte array
- *
- *@param data the byte array
- *@param value the long (64-bit) value
- */
-
- public static void putLong(final byte[] data, final long value) {
- putLong(data, 0, value);
+ public static void putLong(byte[] data, int offset, long value) {
+ int limit = LONG_SIZE + offset;
+ long v = value;
+
+ for (int j = offset; j < limit; j++) {
+ data[j] = (byte) (v & 0xFF);
+ v >>= 8;
+ }
}
@@ -336,26 +263,13 @@
*@param offset a starting offset into the byte array
*@param value the double (64-bit) value
*/
-
- public static void putDouble(final byte[] data, final int offset,
- final double value) {
+ public static void putDouble(byte[] data, int offset, double value) {
// Excel likes NaN to be a specific value.
- if (Double.isNaN(value))
- putNumber(data, offset, -276939487313920L, DOUBLE_SIZE);
- else
- putNumber(data, offset, Double.doubleToLongBits(value), DOUBLE_SIZE);
- }
-
-
- /**
- * put a double value into beginning of a byte array
- *
- *@param data the byte array
- *@param value the double (64-bit) value
- */
-
- public static void putDouble(final byte[] data, final double value) {
- putDouble(data, 0, value);
+ if (Double.isNaN(value)) {
+ putLong(data, offset, -276939487313920L);
+ } else {
+ putLong(data, offset, Double.doubleToLongBits(value));
+ }
}
@@ -364,7 +278,6 @@
*
*@author Marc Johnson (mjohnson at apache dot org)
*/
-
public static final class BufferUnderrunException extends IOException {
BufferUnderrunException() {
@@ -376,79 +289,72 @@
/**
* get a short value from an InputStream
*
- *@param stream the InputStream from which the short
- * is to be read
+ *@param stream the InputStream from which the short is to be read
*@return the short (16-bit) value
*@exception IOException will be propagated back to the caller
- *@exception BufferUnderrunException if the stream cannot provide enough
- * bytes
+ *@exception BufferUnderrunException if the stream cannot provide enough bytes
*/
public static short readShort(InputStream stream) throws IOException, BufferUnderrunException {
- return (short) readUShort(stream);
- }
+ return (short) readUShort(stream);
+ }
- public static int readUShort(InputStream stream) throws IOException, BufferUnderrunException {
+ public static int readUShort(InputStream stream) throws IOException, BufferUnderrunException {
- int ch1 = stream.read();
- int ch2 = stream.read();
- if ((ch1 | ch2) < 0) {
- throw new BufferUnderrunException();
- }
- return ((ch2 << 8) + (ch1 << 0));
- }
+ int ch1 = stream.read();
+ int ch2 = stream.read();
+ if ((ch1 | ch2) < 0) {
+ throw new BufferUnderrunException();
+ }
+ return (ch2 << 8) + (ch1 << 0);
+ }
/**
* get an int value from an InputStream
*
- *@param stream the InputStream from which the int is
- * to be read
- *@return the int (32-bit) value
- *@exception IOException will be propagated back to the caller
- *@exception BufferUnderrunException if the stream cannot provide enough
- * bytes
+ *@param stream the InputStream from which the int is to be read
+ * @return the int (32-bit) value
+ * @exception IOException will be propagated back to the caller
+ * @exception BufferUnderrunException if the stream cannot provide enough bytes
*/
- public static int readInt(final InputStream stream)
+ public static int readInt(InputStream stream)
throws IOException, BufferUnderrunException {
- int ch1 = stream.read();
- int ch2 = stream.read();
- int ch3 = stream.read();
- int ch4 = stream.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0) {
- throw new BufferUnderrunException();
- }
- return ((ch4 << 24) + (ch3<<16) + (ch2 << 8) + (ch1 << 0));
+ int ch1 = stream.read();
+ int ch2 = stream.read();
+ int ch3 = stream.read();
+ int ch4 = stream.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0) {
+ throw new BufferUnderrunException();
+ }
+ return (ch4 << 24) + (ch3<<16) + (ch2 << 8) + (ch1 << 0);
}
/**
* get a long value from an InputStream
*
- *@param stream the InputStream from which the long
- * is to be read
- *@return the long (64-bit) value
- *@exception IOException will be propagated back to the caller
- *@exception BufferUnderrunException if the stream cannot provide enough
- * bytes
+ * @param stream the InputStream from which the long is to be read
+ * @return the long (64-bit) value
+ * @exception IOException will be propagated back to the caller
+ * @exception BufferUnderrunException if the stream cannot provide enough bytes
*/
-
- public static long readLong(final InputStream stream)
+ public static long readLong(InputStream stream)
throws IOException, BufferUnderrunException {
- int ch1 = stream.read();
- int ch2 = stream.read();
- int ch3 = stream.read();
- int ch4 = stream.read();
- int ch5 = stream.read();
- int ch6 = stream.read();
- int ch7 = stream.read();
- int ch8 = stream.read();
- if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) {
- throw new BufferUnderrunException();
- }
-
- return
- ((long)ch8 << 56) +
+ int ch1 = stream.read();
+ int ch2 = stream.read();
+ int ch3 = stream.read();
+ int ch4 = stream.read();
+ int ch5 = stream.read();
+ int ch6 = stream.read();
+ int ch7 = stream.read();
+ int ch8 = stream.read();
+ if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) {
+ throw new BufferUnderrunException();
+ }
+
+ return
+ ((long)ch8 << 56) +
((long)ch7 << 48) +
((long)ch6 << 40) +
((long)ch5 << 32) +
@@ -459,113 +365,43 @@
}
/**
- * Gets the number attribute of the LittleEndian class
- *
- *@param data Description of the Parameter
- *@param offset Description of the Parameter
- *@param size Description of the Parameter
- *@return The number value
- */
- private static long getNumber(final byte[] data, final int offset,
- final int size) {
- long result = 0;
-
- for (int j = offset + size - 1; j >= offset; j--) {
- result <<= 8;
- result |= 0xff & data[j];
- }
- return result;
- }
-
-
- /**
- * Description of the Method
- *
- *@param data Description of the Parameter
- *@param offset Description of the Parameter
- *@param value Description of the Parameter
- *@param size Description of the Parameter
- */
- private static void putNumber(final byte[] data, final int offset,
- final long value, final int size) {
- int limit = size + offset;
- long v = value;
-
- for (int j = offset; j < limit; j++) {
- data[j] = (byte) (v & 0xFF);
- v >>= 8;
- }
- }
-
-
- /**
* Convert an 'unsigned' byte to an integer. ie, don't carry across the
* sign.
*
- *@param b Description of the Parameter
- *@return Description of the Return Value
+ * @param b Description of the Parameter
+ * @return Description of the Return Value
*/
public static int ubyteToInt(byte b) {
- return ((b & 0x80) == 0 ? (int) b : (b & (byte) 0x7f) + 0x80);
+ return b & 0xFF;
}
/**
* get the unsigned value of a byte.
*
- *@param data the byte array.
- *@param offset a starting offset into the byte array.
- *@return the unsigned value of the byte as a 32 bit integer
+ * @param data the byte array.
+ * @param offset a starting offset into the byte array.
+ * @return the unsigned value of the byte as a 32 bit integer
*/
- public static int getUnsignedByte(final byte[] data, final int offset) {
- return (int) getNumber(data, offset, BYTE_SIZE);
- }
-
-
- /**
- * get the unsigned value of a byte.
- *
- *@param data the byte array
- *@return the unsigned value of the byte as a 32 bit integer
- */
- public static int getUnsignedByte(final byte[] data) {
- return getUnsignedByte(data, 0);
+ public static int getUnsignedByte(byte[] data, int offset) {
+ return data[offset] & 0xFF;
}
/**
* Copy a portion of a byte array
*
- *@param data the original byte array
- *@param offset Where to start copying from.
- *@param size Number of bytes to copy.
- *@return The byteArray value
- *@throws IndexOutOfBoundsException - if copying would cause access of
+ * @param data the original byte array
+ * @param offset Where to start copying from.
+ * @param size Number of bytes to copy.
+ * @return The byteArray value
+ * @throws IndexOutOfBoundsException - if copying would cause access of
* data outside array bounds.
*/
- public static byte[] getByteArray(final byte[] data, int offset, int size) {
+ public static byte[] getByteArray(byte[] data, int offset, int size) {
byte[] copy = new byte[size];
System.arraycopy(data, offset, copy, 0, size);
return copy;
}
-
- /**
- * <p>Gets an unsigned int value (8 bytes) from a byte array.</p>
- *
- * @param data the byte array
- * @param offset a starting offset into the byte array
- * @return the unsigned int (32-bit) value in a long
- */
- public static long getULong(final byte[] data, final int offset)
- {
- int num = (int) getNumber(data, offset, LONG_SIZE);
- long retNum;
- if (num < 0)
- retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
- else
- retNum = num;
- return retNum;
- }
-
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianInput.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianInput.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianInput.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianInput.java Sun Oct 26 00:18:17 2008
@@ -21,6 +21,7 @@
* @author Josh Micich
*/
public interface LittleEndianInput {
+ int available();
byte readByte();
int readUByte();
short readShort();
@@ -30,6 +31,4 @@
double readDouble();
void readFully(byte[] buf);
void readFully(byte[] buf, int off, int len);
- String readUnicodeLEString(int nChars);
- String readCompressedUnicode(int nChars);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org