From b79ad301cf935e9e734811cdcf9881d4b07cffdb Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Sun, 19 Dec 2010 07:17:14 +0000 Subject: [PATCH] Make BATBlock useful for read (was previously write only) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1050770 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/poifs/storage/BATBlock.java | 151 +++++++++++++----- .../apache/poi/poifs/storage/BigBlock.java | 4 +- 2 files changed, 113 insertions(+), 42 deletions(-) diff --git a/src/java/org/apache/poi/poifs/storage/BATBlock.java b/src/java/org/apache/poi/poifs/storage/BATBlock.java index cfda4da91a..23188c1c02 100644 --- a/src/java/org/apache/poi/poifs/storage/BATBlock.java +++ b/src/java/org/apache/poi/poifs/storage/BATBlock.java @@ -19,13 +19,12 @@ package org.apache.poi.poifs.storage; import java.io.IOException; import java.io.OutputStream; - +import java.nio.ByteBuffer; import java.util.Arrays; import org.apache.poi.poifs.common.POIFSBigBlockSize; import org.apache.poi.poifs.common.POIFSConstants; -import org.apache.poi.util.IntegerField; -import org.apache.poi.util.LittleEndianConsts; +import org.apache.poi.util.LittleEndian; /** * A block of block allocation table entries. BATBlocks are created @@ -34,10 +33,19 @@ import org.apache.poi.util.LittleEndianConsts; * @author Marc Johnson (mjohnson at apache dot org) */ public final class BATBlock extends BigBlock { - private static final byte _default_value = ( byte ) 0xFF; - private IntegerField[] _fields; - private byte[] _data; - + /** + * For a regular fat block, these are 128 / 1024 + * next sector values. + * For a XFat (DIFat) block, these are 127 / 1023 + * next sector values, then a chaining value. + */ + private int[] _values; + + /** + * Does this BATBlock have any free sectors in it? + */ + private boolean _has_free_sectors; + /** * Create a single instance initialized with default values */ @@ -46,18 +54,68 @@ public final class BATBlock extends BigBlock { { super(bigBlockSize); - int _entries_per_block = bigBlockSize.getBATEntriesPerBlock(); - - _data = new byte[ bigBlockSize.getBigBlockSize() ]; - Arrays.fill(_data, _default_value); - _fields = new IntegerField[ _entries_per_block ]; - int offset = 0; + int _entries_per_block = bigBlockSize.getBATEntriesPerBlock(); + _values = new int[_entries_per_block]; + _has_free_sectors = true; - for (int j = 0; j < _entries_per_block; j++) - { - _fields[ j ] = new IntegerField(offset); - offset += LittleEndianConsts.INT_SIZE; + Arrays.fill(_values, POIFSConstants.UNUSED_BLOCK); + } + + /** + * Create a single instance initialized (perhaps partially) with entries + * + * @param entries the array of block allocation table entries + * @param start_index the index of the first entry to be written + * to the block + * @param end_index the index, plus one, of the last entry to be + * written to the block (writing is for all index + * k, start_index <= k < end_index) + */ + + private BATBlock(POIFSBigBlockSize bigBlockSize, final int [] entries, + final int start_index, final int end_index) + { + this(bigBlockSize); + for (int k = start_index; k < end_index; k++) { + _values[k - start_index] = entries[k]; } + + // Do we have any free sectors? + if(end_index - start_index == _values.length) { + recomputeFree(); + } + } + + private void recomputeFree() { + boolean hasFree = false; + for(int k=0; k<_values.length; k++) { + if(_values[k] == POIFSConstants.UNUSED_BLOCK) { + hasFree = true; + break; + } + } + _has_free_sectors = hasFree; + } + + /** + * Create a single BATBlock from the byte buffer, which must hold at least + * one big block of data to be read. + */ + public static BATBlock createBATBlock(final POIFSBigBlockSize bigBlockSize, ByteBuffer data) + { + // Create an empty block + BATBlock block = new BATBlock(bigBlockSize); + + // Fill it + byte[] buffer = new byte[LittleEndian.INT_SIZE]; + for(int i=0; i