More refactoring of SST

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352777 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Glen Stampoultzis 2002-07-17 14:18:03 +00:00
parent 37371cc919
commit 9102bc3f39
5 changed files with 66 additions and 48 deletions

View File

@ -233,7 +233,7 @@ public class FormulaViewer
private String composeFormula(FormulaRecord record) private String composeFormula(FormulaRecord record)
{ {
return FormulaParser.toFormulaString((SheetReferences)null,record.getParsedExpression()); return org.apache.poi.hssf.model.FormulaParser.toFormulaString((SheetReferences)null,record.getParsedExpression());
} }
/** /**

View File

@ -60,6 +60,7 @@ import org.apache.poi.util.LittleEndianConsts;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ArrayList;
/** /**
* Title: Static String Table Record * Title: Static String Table Record
@ -513,18 +514,16 @@ public class SSTRecord
{ {
SSTSerializer serializer = new SSTSerializer( SSTSerializer serializer = new SSTSerializer(
_record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() ); _record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() );
return serializer.serialize( offset, data ); return serializer.serialize( getRecordSize(), offset, data );
} }
// we can probably simplify this later...this calculates the size
// w/o serializing but still is a bit slow
public int getRecordSize() public int getRecordSize()
{ {
SSTSerializer serializer = new SSTSerializer( SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(field_3_strings);
_record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() ); int recordSize = calculator.getRecordSize();
_record_lengths = calculator.getRecordLengths();
return serializer.getRecordSize(); return recordSize;
} }
SSTDeserializer getDeserializer() SSTDeserializer getDeserializer()

View File

@ -57,6 +57,8 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** /**
* Used to calculate the record sizes for a particular record. * Used to calculate the record sizes for a particular record.
@ -65,8 +67,6 @@ import java.util.ArrayList;
*/ */
class SSTRecordSizeCalculator class SSTRecordSizeCalculator
{ {
private SSTSerializer serializer;
private UnicodeString unistr = null; private UnicodeString unistr = null;
private int stringReminant = 0; private int stringReminant = 0;
private int unipos = 0; private int unipos = 0;
@ -77,11 +77,13 @@ class SSTRecordSizeCalculator
private boolean firstRecord = true; private boolean firstRecord = true;
private int totalWritten = 0; private int totalWritten = 0;
private int recordSize = 0; private int recordSize = 0;
private List recordLengths = new ArrayList();
private int pos = 0; private int pos = 0;
private Map strings;
public SSTRecordSizeCalculator(SSTSerializer serializer) public SSTRecordSizeCalculator(Map strings)
{ {
this.serializer = serializer; this.strings = strings;
} }
/** /**
@ -94,9 +96,8 @@ class SSTRecordSizeCalculator
{ {
initVars(); initVars();
serializer.recordLengths = new ArrayList(); int retval;
int retval = 0; int totalStringSpaceRequired = SSTSerializer.calculateUnicodeSize(strings);
int totalStringSpaceRequired = serializer.calculateUnicodeSize();
if ( totalStringSpaceRequired > SSTRecord.MAX_DATA_SPACE ) if ( totalStringSpaceRequired > SSTRecord.MAX_DATA_SPACE )
{ {
@ -106,11 +107,16 @@ class SSTRecordSizeCalculator
{ {
// short data: write one simple SST record // short data: write one simple SST record
retval = SSTRecord.SST_RECORD_OVERHEAD + totalStringSpaceRequired; retval = SSTRecord.SST_RECORD_OVERHEAD + totalStringSpaceRequired;
serializer.recordLengths.add( new Integer( totalStringSpaceRequired ) ); recordLengths.add( new Integer( totalStringSpaceRequired ) );
} }
return retval; return retval;
} }
public List getRecordLengths()
{
return recordLengths;
}
private int sizeOverContinuation( int totalStringSpaceRequired ) private int sizeOverContinuation( int totalStringSpaceRequired )
{ {
int retval; int retval;
@ -137,7 +143,7 @@ class SSTRecordSizeCalculator
finished = true; finished = true;
} }
recordSize = size + SSTRecord.STD_RECORD_OVERHEAD; recordSize = size + SSTRecord.STD_RECORD_OVERHEAD;
serializer.recordLengths.add( new Integer( size ) ); recordLengths.add( new Integer( size ) );
pos = 4; pos = 4;
} }
if ( isRemainingString ) if ( isRemainingString )
@ -158,17 +164,17 @@ class SSTRecordSizeCalculator
recordSize = SSTRecord.MAX_RECORD_SIZE; recordSize = SSTRecord.MAX_RECORD_SIZE;
pos = 12; pos = 12;
firstRecord = false; firstRecord = false;
serializer.recordLengths.add( new Integer( recordSize - SSTRecord.STD_RECORD_OVERHEAD ) ); recordLengths.add( new Integer( recordSize - SSTRecord.STD_RECORD_OVERHEAD ) );
} }
private void calcRemainingStrings() private void calcRemainingStrings()
{ {
for ( ; unipos < serializer.strings.size(); unipos++ ) for ( ; unipos < strings.size(); unipos++ )
{ {
int available = SSTRecord.MAX_RECORD_SIZE - pos; int available = SSTRecord.MAX_RECORD_SIZE - pos;
Integer intunipos = new Integer( unipos ); Integer intunipos = new Integer( unipos );
unistr = ( (UnicodeString) serializer.strings.get( intunipos ) ); unistr = ( (UnicodeString) strings.get( intunipos ) );
if ( unistr.getRecordSize() <= available ) if ( unistr.getRecordSize() <= available )
{ {
totalBytesWritten += unistr.getRecordSize(); totalBytesWritten += unistr.getRecordSize();
@ -190,8 +196,8 @@ class SSTRecordSizeCalculator
int shortrecord = recordSize int shortrecord = recordSize
- ( available - toBeWritten ); - ( available - toBeWritten );
serializer.recordLengths.set( recordLengths.set(
serializer.recordLengths.size() - 1, recordLengths.size() - 1,
new Integer( new Integer(
shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) ); shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
recordSize = shortrecord; recordSize = shortrecord;
@ -203,7 +209,7 @@ class SSTRecordSizeCalculator
{ {
int shortrecord = recordSize - available; int shortrecord = recordSize - available;
serializer.recordLengths.set( serializer.recordLengths.size() - 1, recordLengths.set( recordLengths.size() - 1,
new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) ); new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
recordSize = shortrecord; recordSize = shortrecord;
} }
@ -233,7 +239,7 @@ class SSTRecordSizeCalculator
if ( available != toBeWritten ) if ( available != toBeWritten )
{ {
int shortrecord = recordSize - ( available - toBeWritten ); int shortrecord = recordSize - ( available - toBeWritten );
serializer.recordLengths.set( serializer.recordLengths.size() - 1, recordLengths.set( recordLengths.size() - 1,
new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) ); new Integer( shortrecord - SSTRecord.STD_RECORD_OVERHEAD ) );
recordSize = shortrecord; recordSize = shortrecord;
} }

View File

@ -57,6 +57,8 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.BinaryTree; import org.apache.poi.util.BinaryTree;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import java.util.Map;
/** /**
* This class handles serialization of SST records. It utilizes the record processor * This class handles serialization of SST records. It utilizes the record processor
@ -68,8 +70,8 @@ class SSTSerializer
{ {
// todo: make private again // todo: make private again
List recordLengths; private List recordLengths;
BinaryTree strings; private BinaryTree strings;
private int numStrings; private int numStrings;
private int numUniqueStrings; private int numUniqueStrings;
@ -95,9 +97,8 @@ class SSTSerializer
* *
* @return the byte array * @return the byte array
*/ */
public int serialize( int offset, byte[] data ) public int serialize( int record_size, int offset, byte[] data )
{ {
int record_size = getRecordSize();
int record_length_index = 0; int record_length_index = 0;
if ( calculateUnicodeSize() > SSTRecord.MAX_DATA_SPACE ) if ( calculateUnicodeSize() > SSTRecord.MAX_DATA_SPACE )
@ -109,30 +110,34 @@ class SSTSerializer
// todo: make private again
/** /**
* Calculates the total unicode size for all the strings. * Calculates the total unicode size for all the strings.
* *
* @return the total size. * @return the total size.
*/ */
int calculateUnicodeSize() public static int calculateUnicodeSize(Map strings)
{ {
int retval = 0; int retval = 0;
for ( int k = 0; k < strings.size(); k++ ) for ( int k = 0; k < strings.size(); k++ )
{ {
retval += getUnicodeString( k ).getRecordSize(); retval += getUnicodeString( strings, k ).getRecordSize();
} }
return retval; return retval;
} }
public int calculateUnicodeSize()
{
return calculateUnicodeSize(strings);
}
/** /**
* This case is chosen when an SST record does not span over to a continue record. * This case is chosen when an SST record does not span over to a continue record.
* *
*/ */
private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index ) private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index )
{ {
int len = ( (Integer) recordLengths.get( record_length_index++ ) ).intValue(); int len = ( (Integer) recordLengths.get( record_length_index ) ).intValue();
int recordSize = SSTRecord.SST_RECORD_OVERHEAD + len - SSTRecord.STD_RECORD_OVERHEAD; int recordSize = SSTRecord.SST_RECORD_OVERHEAD + len - SSTRecord.STD_RECORD_OVERHEAD;
sstRecordHeader.writeSSTHeader( data, 0 + offset, recordSize ); sstRecordHeader.writeSSTHeader( data, 0 + offset, recordSize );
int pos = SSTRecord.SST_RECORD_OVERHEAD; int pos = SSTRecord.SST_RECORD_OVERHEAD;
@ -208,6 +213,11 @@ class SSTSerializer
} }
private UnicodeString getUnicodeString( int index ) private UnicodeString getUnicodeString( int index )
{
return getUnicodeString(strings, index);
}
private static UnicodeString getUnicodeString( Map strings, int index )
{ {
Integer intunipos = new Integer( index ); Integer intunipos = new Integer( index );
return ( (UnicodeString) strings.get( intunipos ) ); return ( (UnicodeString) strings.get( intunipos ) );
@ -215,7 +225,14 @@ class SSTSerializer
public int getRecordSize() public int getRecordSize()
{ {
return new SSTRecordSizeCalculator(this).getRecordSize(); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
int recordSize = calculator.getRecordSize();
recordLengths = calculator.getRecordLengths();
return recordSize;
} }
public List getRecordLengths()
{
return recordLengths;
}
} }

View File

@ -73,7 +73,7 @@ public class TestSSTRecordSizeCalculator
{ {
private static final String SMALL_STRING = "Small string"; private static final String SMALL_STRING = "Small string";
private static final int COMPRESSED_PLAIN_STRING_OVERHEAD = 3; private static final int COMPRESSED_PLAIN_STRING_OVERHEAD = 3;
private List recordLengths; // private List recordLengths;
private BinaryTree strings; private BinaryTree strings;
private static final int OPTION_FIELD_SIZE = 1; private static final int OPTION_FIELD_SIZE = 1;
@ -86,8 +86,9 @@ public class TestSSTRecordSizeCalculator
throws Exception throws Exception
{ {
strings.put(new Integer(0), makeUnicodeString(SMALL_STRING)); strings.put(new Integer(0), makeUnicodeString(SMALL_STRING));
SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(new SSTSerializer(recordLengths, strings, 1, 1)); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
assertEquals(SSTRecord.SST_RECORD_OVERHEAD + COMPRESSED_PLAIN_STRING_OVERHEAD + SMALL_STRING.length(), calculator.getRecordSize()); assertEquals(SSTRecord.SST_RECORD_OVERHEAD + COMPRESSED_PLAIN_STRING_OVERHEAD + SMALL_STRING.length(),
calculator.getRecordSize());
} }
public void testBigStringAcrossUnicode() public void testBigStringAcrossUnicode()
@ -95,7 +96,7 @@ public class TestSSTRecordSizeCalculator
{ {
String bigString = new String(new char[SSTRecord.MAX_DATA_SPACE + 100]); String bigString = new String(new char[SSTRecord.MAX_DATA_SPACE + 100]);
strings.put(new Integer(0), makeUnicodeString(bigString)); strings.put(new Integer(0), makeUnicodeString(bigString));
SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(new SSTSerializer(recordLengths, strings, 1, 1)); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
assertEquals(SSTRecord.SST_RECORD_OVERHEAD assertEquals(SSTRecord.SST_RECORD_OVERHEAD
+ COMPRESSED_PLAIN_STRING_OVERHEAD + COMPRESSED_PLAIN_STRING_OVERHEAD
+ SSTRecord.MAX_DATA_SPACE + SSTRecord.MAX_DATA_SPACE
@ -111,30 +112,26 @@ public class TestSSTRecordSizeCalculator
{ {
String perfectFit = new String(new char[SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD]); String perfectFit = new String(new char[SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD]);
strings.put(new Integer(0), makeUnicodeString(perfectFit)); strings.put(new Integer(0), makeUnicodeString(perfectFit));
SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(new SSTSerializer(recordLengths, strings, 1, 1)); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
assertEquals(SSTRecord.SST_RECORD_OVERHEAD assertEquals(SSTRecord.SST_RECORD_OVERHEAD
+ COMPRESSED_PLAIN_STRING_OVERHEAD + COMPRESSED_PLAIN_STRING_OVERHEAD
+ perfectFit.length(), + perfectFit.length(),
calculator.getRecordSize()); calculator.getRecordSize());
} }
/**
* Test the case where it's too big by one.
*/
public void testJustOversized() public void testJustOversized()
throws Exception throws Exception
{ {
String tooBig = new String(new char[SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD + 1]); String tooBig = new String(new char[SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD + 1]);
strings.put(new Integer(0), makeUnicodeString(tooBig)); strings.put(new Integer(0), makeUnicodeString(tooBig));
SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(new SSTSerializer(recordLengths, strings, 1, 1)); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
assertEquals(SSTRecord.SST_RECORD_OVERHEAD assertEquals(SSTRecord.SST_RECORD_OVERHEAD
+ COMPRESSED_PLAIN_STRING_OVERHEAD + COMPRESSED_PLAIN_STRING_OVERHEAD
+ tooBig.length() - 1 + tooBig.length() - 1
// continued // continue record
+ SSTRecord.STD_RECORD_OVERHEAD + SSTRecord.STD_RECORD_OVERHEAD
+ OPTION_FIELD_SIZE + OPTION_FIELD_SIZE
+ 1 // 1 char continued + 1,
,
calculator.getRecordSize()); calculator.getRecordSize());
} }
@ -145,7 +142,7 @@ public class TestSSTRecordSizeCalculator
String perfectFit = new String(new char[SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD]); String perfectFit = new String(new char[SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD]);
strings.put(new Integer(0), makeUnicodeString(perfectFit)); strings.put(new Integer(0), makeUnicodeString(perfectFit));
strings.put(new Integer(1), makeUnicodeString(SMALL_STRING)); strings.put(new Integer(1), makeUnicodeString(SMALL_STRING));
SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(new SSTSerializer(recordLengths, strings, 1, 1)); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
assertEquals(SSTRecord.SST_RECORD_OVERHEAD assertEquals(SSTRecord.SST_RECORD_OVERHEAD
+ SSTRecord.MAX_DATA_SPACE + SSTRecord.MAX_DATA_SPACE
// second string // second string
@ -162,7 +159,7 @@ public class TestSSTRecordSizeCalculator
strings.put(new Integer(0), makeUnicodeString(almostPerfectFit)); strings.put(new Integer(0), makeUnicodeString(almostPerfectFit));
String oneCharString = new String(new char[1]); String oneCharString = new String(new char[1]);
strings.put(new Integer(1), makeUnicodeString(oneCharString)); strings.put(new Integer(1), makeUnicodeString(oneCharString));
SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(new SSTSerializer(recordLengths, strings, 1, 1)); SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings);
assertEquals(SSTRecord.SST_RECORD_OVERHEAD assertEquals(SSTRecord.SST_RECORD_OVERHEAD
+ COMPRESSED_PLAIN_STRING_OVERHEAD + COMPRESSED_PLAIN_STRING_OVERHEAD
+ almostPerfectFit.length() + almostPerfectFit.length()
@ -177,7 +174,6 @@ public class TestSSTRecordSizeCalculator
public void setUp() public void setUp()
{ {
recordLengths = new ArrayList();
strings = new BinaryTree(); strings = new BinaryTree();
} }