You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ni...@apache.org on 2010/12/22 09:41:28 UTC
svn commit: r1051791 - in /poi/trunk/src:
java/org/apache/poi/poifs/storage/BATBlock.java
testcases/org/apache/poi/poifs/storage/TestBATBlock.java
Author: nick
Date: Wed Dec 22 08:41:28 2010
New Revision: 1051791
URL: http://svn.apache.org/viewvc?rev=1051791&view=rev
Log:
More BATBlock related methods for identifying size and list offsets, plus tests
Modified:
poi/trunk/src/java/org/apache/poi/poifs/storage/BATBlock.java
poi/trunk/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java
Modified: poi/trunk/src/java/org/apache/poi/poifs/storage/BATBlock.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/storage/BATBlock.java?rev=1051791&r1=1051790&r2=1051791&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/storage/BATBlock.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/storage/BATBlock.java Wed Dec 22 08:41:28 2010
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.List;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
@@ -194,7 +195,6 @@ public final class BATBlock extends BigB
*
* @return the number of BATBlocks needed
*/
-
public static int calculateStorageRequirements(final POIFSBigBlockSize bigBlockSize, final int entryCount)
{
int _entries_per_block = bigBlockSize.getBATEntriesPerBlock();
@@ -209,14 +209,62 @@ public final class BATBlock extends BigB
*
* @return the number of XBATBlocks needed
*/
-
public static int calculateXBATStorageRequirements(final POIFSBigBlockSize bigBlockSize, final int entryCount)
{
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
return (entryCount + _entries_per_xbat_block - 1)
/ _entries_per_xbat_block;
}
+
+ /**
+ * Calculates the maximum size of a file which is addressable given the
+ * number of FAT (BAT and XBAT) sectors specified.
+ * The actual file size will be between [size of fatCount-1 blocks] and
+ * [size of fatCount blocks].
+ * For 512 byte block sizes, this means we may over-estimate by up to 65kb.
+ * For 4096 byte block sizes, this means we may over-estimate by up to 4mb
+ */
+ public static int calculateMaximumSize(final POIFSBigBlockSize bigBlockSize,
+ final int numBAT, final int numXBAT) {
+ int size = 1; // Header isn't FAT addressed
+ size += (numBAT * bigBlockSize.getBATEntriesPerBlock());
+ size += (numXBAT * bigBlockSize.getXBATEntriesPerBlock());
+ return size * bigBlockSize.getBigBlockSize();
+ }
+ public static int calculateMaximumSize(final HeaderBlock header)
+ {
+ return calculateMaximumSize(header.getBigBlockSize(), header.getBATCount(), header.getXBATCount());
+ }
+ /**
+ * Returns the BATBlock that handles the specified offset,
+ * and the relative index within it.
+ * The List of BATBlocks must be in sequential order
+ */
+ public static BATBlockAndIndex getBATBlockAndIndex(final int offset,
+ final HeaderBlock header, final List<BATBlock> blocks) {
+ POIFSBigBlockSize bigBlockSize = header.getBigBlockSize();
+
+ // Are we in the BAT or XBAT range
+ int batRangeEndsAt = bigBlockSize.getBATEntriesPerBlock() *
+ header.getBATCount();
+
+ if(offset < batRangeEndsAt) {
+ int whichBAT = (int)Math.floor(offset / bigBlockSize.getBATEntriesPerBlock());
+ int index = offset % bigBlockSize.getBATEntriesPerBlock();
+ return new BATBlockAndIndex( index, blocks.get(whichBAT) );
+ }
+
+ // XBATs hold slightly less
+ int relOffset = offset - batRangeEndsAt;
+ int whichXBAT = (int)Math.floor(relOffset / bigBlockSize.getXBATEntriesPerBlock());
+ int index = relOffset % bigBlockSize.getXBATEntriesPerBlock();
+ return new BATBlockAndIndex(
+ index,
+ blocks.get(header.getBATCount() + whichXBAT)
+ );
+ }
+
private void setXBATChain(final POIFSBigBlockSize bigBlockSize, int chainIndex)
{
int _entries_per_xbat_block = bigBlockSize.getXBATEntriesPerBlock();
@@ -277,5 +325,21 @@ public final class BATBlock extends BigB
}
/* ********** END extension of BigBlock ********** */
-} // end public class BATBlock
+
+
+ public static class BATBlockAndIndex {
+ private final int index;
+ private final BATBlock block;
+ private BATBlockAndIndex(int index, BATBlock block) {
+ this.index = index;
+ this.block = block;
+ }
+ public int getIndex() {
+ return index;
+ }
+ public BATBlock getBlock() {
+ return block;
+ }
+ }
+}
Modified: poi/trunk/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java?rev=1051791&r1=1051790&r2=1051791&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java Wed Dec 22 08:41:28 2010
@@ -19,7 +19,10 @@ package org.apache.poi.poifs.storage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import org.apache.poi.poifs.common.POIFSConstants;
@@ -208,4 +211,175 @@ public final class TestBATBlock extends
public void testGetXBATChainOffset() {
assertEquals(508, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS.getNextXBATChainOffset());
}
+
+ public void testCalculateMaximumSize() throws Exception {
+ // Zero fat blocks isn't technically valid, but it'd be header only
+ assertEquals(
+ 512,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 0, 0)
+ );
+ assertEquals(
+ 4096,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 0, 0)
+ );
+
+ // A single FAT block can address 128/1024 blocks
+ assertEquals(
+ 512 + 512*128,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 1, 0)
+ );
+ assertEquals(
+ 4096 + 4096*1024,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 1, 0)
+ );
+
+ assertEquals(
+ 512 + 4*512*128,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 4, 0)
+ );
+ assertEquals(
+ 4096 + 4*4096*1024,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 4, 0)
+ );
+
+ // Once we get into XBAT blocks, they address a little bit less
+ assertEquals(
+ 512 + 109*512*128,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 109, 0)
+ );
+ assertEquals(
+ 4096 + 109*4096*1024,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 109, 0)
+ );
+
+ assertEquals(
+ 512 + 109*512*128 + 512*127,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 109, 1)
+ );
+ assertEquals(
+ 4096 + 109*4096*1024 + 4096*1023,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 109, 1)
+ );
+
+ assertEquals(
+ 512 + 109*512*128 + 3*512*127,
+ BATBlock.calculateMaximumSize(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, 109, 3)
+ );
+ assertEquals(
+ 4096 + 109*4096*1024 + 3*4096*1023,
+ BATBlock.calculateMaximumSize(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS, 109, 3)
+ );
+ }
+
+ public void testGetBATBlockAndIndex() throws Exception {
+ HeaderBlock header = new HeaderBlock(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
+ List<BATBlock> blocks = new ArrayList<BATBlock>();
+ int offset;
+
+
+ // First, try a one BAT block file
+ header.setBATCount(1);
+ blocks.add(
+ BATBlock.createBATBlock(header.getBigBlockSize(), ByteBuffer.allocate(512))
+ );
+
+ offset = 0;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1;
+ assertEquals(1, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 127;
+ assertEquals(127, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+
+ // Now go for one with multiple BAT blocks
+ header.setBATCount(2);
+ blocks.add(
+ BATBlock.createBATBlock(header.getBigBlockSize(), ByteBuffer.allocate(512))
+ );
+
+ offset = 0;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 127;
+ assertEquals(127, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 128;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 129;
+ assertEquals(1, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+
+ // And finally one with XBATs too
+ // This is a naughty file, but we should be able to cope...
+ // (We'll decide everything is XBAT not BAT)
+ header.setBATCount(0);
+ offset = 0;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 126;
+ assertEquals(126, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 127;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 128;
+ assertEquals(1, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 129;
+ assertEquals(2, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+
+ // Check with the bigger block size too
+ header = new HeaderBlock(POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS);
+
+ offset = 0;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1022;
+ assertEquals(1022, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1023;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1024;
+ assertEquals(1, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ // Biggr block size, back to real BATs
+ header.setBATCount(2);
+
+ offset = 0;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1022;
+ assertEquals(1022, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1023;
+ assertEquals(1023, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(0, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+
+ offset = 1024;
+ assertEquals(0, BATBlock.getBATBlockAndIndex(offset, header, blocks).getIndex());
+ assertEquals(1, blocks.indexOf( BATBlock.getBATBlockAndIndex(offset, header, blocks).getBlock() ));
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org