You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by gl...@apache.org on 2003/06/26 15:33:48 UTC
cvs commit: jakarta-poi/src/java/org/apache/poi/hssf/record ExtSSTInfoSubRecord.java ExtSSTRecord.java Record.java RecordProcessor.java SSTRecord.java SSTRecordSizeCalculator.java SSTSerializer.java
glens 2003/06/26 06:33:48
Modified: src/java/org/apache/poi/hssf/model Workbook.java
src/java/org/apache/poi/hssf/record ExtSSTInfoSubRecord.java
ExtSSTRecord.java Record.java RecordProcessor.java
SSTRecord.java SSTRecordSizeCalculator.java
SSTSerializer.java
Log:
Same changes as just went to the branch
Revision Changes Path
1.30 +71 -62 jakarta-poi/src/java/org/apache/poi/hssf/model/Workbook.java
Index: Workbook.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/model/Workbook.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- Workbook.java 30 Apr 2003 04:39:16 -0000 1.29
+++ Workbook.java 26 Jun 2003 13:33:47 -0000 1.30
@@ -686,37 +686,37 @@
*
* @return byte array containing the HSSF-only portions of the POIFS file.
*/
-
- public byte [] serialize() {
- log.log(DEBUG, "Serializing Workbook!");
- byte[] retval = null;
-
- // ArrayList bytes = new ArrayList(records.size());
- int arraysize = getSize();
- int pos = 0;
-
- // for (int k = 0; k < records.size(); k++)
- // {
- // bytes.add((( Record ) records.get(k)).serialize());
- // }
- // for (int k = 0; k < bytes.size(); k++)
- // {
- // arraysize += (( byte [] ) bytes.get(k)).length;
- // }
- retval = new byte[ arraysize ];
- for (int k = 0; k < records.size(); k++) {
-
- // byte[] rec = (( byte [] ) bytes.get(k));
- // System.arraycopy(rec, 0, retval, pos, rec.length);
- Record record = records.get(k);
- // Let's skip RECALCID records, as they are only use for optimization
- if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
- pos += record.serialize(pos, retval); // rec.length;
- }
- }
- log.log(DEBUG, "Exiting serialize workbook");
- return retval;
- }
+ // GJS: Not used by system
+// public byte [] serialize() {
+// log.log(DEBUG, "Serializing Workbook!");
+// byte[] retval = null;
+//
+// // ArrayList bytes = new ArrayList(records.size());
+// int arraysize = getSize();
+// int pos = 0;
+//
+// // for (int k = 0; k < records.size(); k++)
+// // {
+// // bytes.add((( Record ) records.get(k)).serialize());
+// // }
+// // for (int k = 0; k < bytes.size(); k++)
+// // {
+// // arraysize += (( byte [] ) bytes.get(k)).length;
+// // }
+// retval = new byte[ arraysize ];
+// for (int k = 0; k < records.size(); k++) {
+//
+// // byte[] rec = (( byte [] ) bytes.get(k));
+// // System.arraycopy(rec, 0, retval, pos, rec.length);
+// Record record = records.get(k);
+// // Let's skip RECALCID records, as they are only use for optimization
+// if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
+// pos += record.serialize(pos, retval); // rec.length;
+// }
+// }
+// log.log(DEBUG, "Exiting serialize workbook");
+// return retval;
+// }
/**
* Serializes all records int the worksheet section into a big byte array. Use
@@ -725,49 +725,58 @@
* @param data array of bytes to write this to
*/
- public int serialize(int offset, byte [] data) {
- log.log(DEBUG, "Serializing Workbook with offsets");
-
- // ArrayList bytes = new ArrayList(records.size());
- // int arraysize = getSize(); // 0;
- int pos = 0;
-
- // for (int k = 0; k < records.size(); k++)
- // {
- // bytes.add((( Record ) records.get(k)).serialize());
- //
- // }
- // for (int k = 0; k < bytes.size(); k++)
- // {
- // arraysize += (( byte [] ) bytes.get(k)).length;
- // }
- for (int k = 0; k < records.size(); k++) {
-
- // byte[] rec = (( byte [] ) bytes.get(k));
- // System.arraycopy(rec, 0, data, offset + pos, rec.length);
- Record record = records.get(k);
+ public int serialize( int offset, byte[] data )
+ {
+ log.log( DEBUG, "Serializing Workbook with offsets" );
+
+ int pos = 0;
+
+ SSTRecord sst = null;
+ int sstPos = 0;
+ for ( int k = 0; k < records.size(); k++ )
+ {
+
+ Record record = records.get( k );
// Let's skip RECALCID records, as they are only use for optimization
- if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
- pos += record.serialize(pos + offset, data); // rec.length;
+ if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
+ {
+ if (record instanceof SSTRecord)
+ {
+ sst = (SSTRecord)record;
+ sstPos = pos;
+ }
+ if (record.getSid() == ExtSSTRecord.sid && sst != null)
+ {
+ record = sst.createExtSSTRecord(sstPos + offset);
+ }
+ pos += record.serialize( pos + offset, data ); // rec.length;
}
}
- log.log(DEBUG, "Exiting serialize workbook");
+ log.log( DEBUG, "Exiting serialize workbook" );
return pos;
}
- public int getSize() {
+ public int getSize()
+ {
int retval = 0;
- for (int k = 0; k < records.size(); k++) {
- Record record = records.get(k);
+ SSTRecord sst = null;
+ for ( int k = 0; k < records.size(); k++ )
+ {
+ Record record = records.get( k );
// Let's skip RECALCID records, as they are only use for optimization
- if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
- retval += record.getRecordSize();
+ if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
+ {
+ if (record instanceof SSTRecord)
+ sst = (SSTRecord)record;
+ if (record.getSid() == ExtSSTRecord.sid && sst != null)
+ retval += sst.calcExtSSTRecordSize();
+ else
+ retval += record.getRecordSize();
}
}
return retval;
- }
-
+ }
/**
* creates the BOF record
* @see org.apache.poi.hssf.record.BOFRecord
1.3 +2 -2 jakarta-poi/src/java/org/apache/poi/hssf/record/ExtSSTInfoSubRecord.java
Index: ExtSSTInfoSubRecord.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/ExtSSTInfoSubRecord.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ExtSSTInfoSubRecord.java 30 Apr 2003 04:38:48 -0000 1.2
+++ ExtSSTInfoSubRecord.java 26 Jun 2003 13:33:47 -0000 1.3
@@ -114,7 +114,7 @@
field_1_stream_pos = pos;
}
- public void setBucketSSTOffset(short offset)
+ public void setBucketRecordOffset(short offset)
{
field_2_bucket_sst_offset = offset;
}
@@ -159,6 +159,6 @@
public short getSid()
{
- return this.sid;
+ return sid;
}
}
1.4 +20 -6 jakarta-poi/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java
Index: ExtSSTRecord.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/ExtSSTRecord.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ExtSSTRecord.java 30 Apr 2003 04:38:47 -0000 1.3
+++ ExtSSTRecord.java 26 Jun 2003 13:33:47 -0000 1.4
@@ -79,6 +79,7 @@
private short field_1_strings_per_bucket;
private ArrayList field_2_sst_info;
+
public ExtSSTRecord()
{
field_2_sst_info = new ArrayList();
@@ -189,26 +190,39 @@
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
-
-// LittleEndian.putShort(data,2,(short)(2 + (getNumInfoRecords() *8)));
- LittleEndian.putShort(data, 2 + offset, ( short ) (2 + (0x3fa - 2)));
- int pos = 4;
+ LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
+ LittleEndian.putShort(data, 4 + offset, field_1_strings_per_bucket);
+ int pos = 6;
for (int k = 0; k < getNumInfoRecords(); k++)
{
System.arraycopy(getInfoRecordAt(k).serialize(), 0, data,
pos + offset, 8);
+ pos += getInfoRecordAt(k).getRecordSize();
}
return getRecordSize();
}
public int getRecordSize()
{
- return 6 + 0x3fa - 2;
+ return 4 + 2 + field_2_sst_info.size() * 8;
}
public short getSid()
{
- return this.sid;
+ return sid;
+ }
+
+ public void setBucketOffsets( int[] bucketAbsoluteOffsets, int[] bucketRelativeOffsets )
+ {
+ this.field_2_sst_info = new ArrayList(bucketAbsoluteOffsets.length);
+ for ( int i = 0; i < bucketAbsoluteOffsets.length; i++ )
+ {
+ ExtSSTInfoSubRecord r = new ExtSSTInfoSubRecord();
+ r.setBucketRecordOffset((short)bucketRelativeOffsets[i]);
+ r.setStreamPos(bucketAbsoluteOffsets[i]);
+ field_2_sst_info.add(r);
+ }
}
+
}
1.6 +0 -16 jakarta-poi/src/java/org/apache/poi/hssf/record/Record.java
Index: Record.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/Record.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Record.java 30 Apr 2003 04:38:47 -0000 1.5
+++ Record.java 26 Jun 2003 13:33:47 -0000 1.6
@@ -71,16 +71,6 @@
{
/**
- * The static ID, subclasses should override this value with the id for the
- * record type they handle.
- */
-
- public short sid = 0;
- private short id = 0;
- private short size = 0;
- private byte[] data = null;
-
- /**
* instantiates a blank record strictly for ID matching
*/
@@ -98,9 +88,6 @@
public Record(short id, short size, byte [] data)
{
- this.id = id;
- this.size = size;
- this.data = data;
validateSid(id);
fillFields(data, size);
}
@@ -115,9 +102,6 @@
public Record(short id, short size, byte [] data, int offset)
{
- this.id = id;
- this.size = size;
- this.data = data;
validateSid(id);
fillFields(data, size, offset);
}
1.5 +5 -0 jakarta-poi/src/java/org/apache/poi/hssf/record/RecordProcessor.java
Index: RecordProcessor.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/RecordProcessor.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- RecordProcessor.java 30 Apr 2003 04:38:48 -0000 1.4
+++ RecordProcessor.java 26 Jun 2003 13:33:47 -0000 1.5
@@ -156,5 +156,10 @@
recordOffset += amount;
available -= amount;
}
+
+ public int getRecordOffset()
+ {
+ return recordOffset;
+ }
}
1.8 +59 -9 jakarta-poi/src/java/org/apache/poi/hssf/record/SSTRecord.java
Index: SSTRecord.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/SSTRecord.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- SSTRecord.java 30 Apr 2003 04:38:48 -0000 1.7
+++ SSTRecord.java 26 Jun 2003 13:33:47 -0000 1.8
@@ -60,7 +60,6 @@
import java.util.Iterator;
import java.util.List;
-import java.util.ArrayList;
/**
* Title: Static String Table Record
@@ -73,7 +72,7 @@
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Marc Johnson (mjohnson at apache dot org)
* @author Glen Stampoultzis (glens at apache.org)
- * @version 2.0-pre
+ *
* @see org.apache.poi.hssf.record.LabelSSTRecord
* @see org.apache.poi.hssf.record.ContinueRecord
*/
@@ -112,10 +111,14 @@
private List _record_lengths = null;
private SSTDeserializer deserializer;
+ /** Offsets from the beginning of the SST record (even across continuations) */
+ int[] bucketAbsoluteOffsets;
+ /** Offsets relative the start of the current SST or continue record */
+ int[] bucketRelativeOffsets;
+
/**
* default constructor
*/
-
public SSTRecord()
{
field_1_num_strings = 0;
@@ -220,7 +223,7 @@
field_1_num_strings++;
String str = ( string == null ) ? ""
: string;
- int rval = -1;
+ int rval;
UnicodeString ucs = new UnicodeString();
ucs.setString( str );
@@ -334,7 +337,7 @@
for ( int k = 0; k < field_3_strings.size(); k++ )
{
buffer.append( " .string_" + k + " = " )
- .append( ( (UnicodeString) field_3_strings
+ .append( ( field_3_strings
.get( new Integer( k ) ) ).toString() ).append( "\n" );
}
buffer.append( "[/SST]\n" );
@@ -394,7 +397,7 @@
* The data consists of sets of string data. This string data is
* arranged as follows:
* <P>
- * <CODE>
+ * <CODE><pre>
* short string_length; // length of string data
* byte string_flag; // flag specifying special string
* // handling
@@ -407,7 +410,7 @@
* // array is run_count)
* byte[] extension; // optional extension (length of array
* // is extend_length)
- * </CODE>
+ * </pre></CODE>
* <P>
* The string_flag is bit mapped as follows:
* <P>
@@ -507,14 +510,22 @@
* Subclasses should implement this so that their data is passed back in a
* byte array.
*
- * @return byte array containing instance data
+ * @return size
*/
public int serialize( int offset, byte[] data )
{
SSTSerializer serializer = new SSTSerializer(
_record_lengths, field_3_strings, getNumStrings(), getNumUniqueStrings() );
- return serializer.serialize( getRecordSize(), offset, data );
+ int bytes = serializer.serialize( getRecordSize(), offset, data );
+ bucketAbsoluteOffsets = serializer.getBucketAbsoluteOffsets();
+ bucketRelativeOffsets = serializer.getBucketRelativeOffsets();
+// for ( int i = 0; i < bucketAbsoluteOffsets.length; i++ )
+// {
+// System.out.println( "bucketAbsoluteOffset = " + bucketAbsoluteOffsets[i] );
+// System.out.println( "bucketRelativeOffset = " + bucketRelativeOffsets[i] );
+// }
+ return bytes;
}
@@ -537,6 +548,45 @@
public void processContinueRecord( byte[] record )
{
deserializer.processContinueRecord( record );
+ }
+
+ /**
+ * Creates an extended string record based on the current contents of
+ * the current SST record. The offset within the stream to the SST record
+ * is required because the extended string record points directly to the
+ * strings in the SST record.
+ * <p>
+ * NOTE: THIS FUNCTION MUST ONLY BE CALLED AFTER THE SST RECORD HAS BEEN
+ * SERIALIZED.
+ *
+ * @param sstOffset The offset in the stream to the start of the
+ * SST record.
+ * @return The new SST record.
+ */
+ public ExtSSTRecord createExtSSTRecord(int sstOffset)
+ {
+ if (bucketAbsoluteOffsets == null || bucketAbsoluteOffsets == null)
+ throw new IllegalStateException("SST record has not yet been serialized.");
+
+ ExtSSTRecord extSST = new ExtSSTRecord();
+ extSST.setNumStringsPerBucket((short)8);
+ int[] absoluteOffsets = (int[]) bucketAbsoluteOffsets.clone();
+ int[] relativeOffsets = (int[]) bucketRelativeOffsets.clone();
+ for ( int i = 0; i < absoluteOffsets.length; i++ )
+ absoluteOffsets[i] += sstOffset;
+ extSST.setBucketOffsets(absoluteOffsets, relativeOffsets);
+ return extSST;
+ }
+
+ /**
+ * Calculates the size in bytes of the EXTSST record as it would be if the
+ * record was serialized.
+ *
+ * @return The size of the ExtSST record in bytes.
+ */
+ public int calcExtSSTRecordSize()
+ {
+ return 4 + 2 + ((field_3_strings.size() / SSTSerializer.DEFAULT_BUCKET_SIZE) + 1) * 8;
}
}
1.4 +3 -1 jakarta-poi/src/java/org/apache/poi/hssf/record/SSTRecordSizeCalculator.java
Index: SSTRecordSizeCalculator.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/SSTRecordSizeCalculator.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SSTRecordSizeCalculator.java 30 Apr 2003 04:38:48 -0000 1.3
+++ SSTRecordSizeCalculator.java 26 Jun 2003 13:33:47 -0000 1.4
@@ -61,7 +61,9 @@
import java.util.Map;
/**
- * Used to calculate the record sizes for a particular record.
+ * Used to calculate the record sizes for a particular record. This kind of
+ * sucks because it's similar to the SST serialization code. In general
+ * the SST serialization code needs to be rewritten.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
1.7 +35 -1 jakarta-poi/src/java/org/apache/poi/hssf/record/SSTSerializer.java
Index: SSTSerializer.java
===================================================================
RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/SSTSerializer.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- SSTSerializer.java 30 Apr 2003 04:38:47 -0000 1.6
+++ SSTSerializer.java 26 Jun 2003 13:33:47 -0000 1.7
@@ -77,6 +77,14 @@
private int numUniqueStrings;
private SSTRecordHeader sstRecordHeader;
+ /** Offsets from the beginning of the SST record (even across continuations) */
+ int[] bucketAbsoluteOffsets;
+ /** Offsets relative the start of the current SST or continue record */
+ int[] bucketRelativeOffsets;
+ int startOfSST, startOfRecord;
+ /** The default bucket size (this is used for ExternSST) */
+ final static int DEFAULT_BUCKET_SIZE = 8;
+
public SSTSerializer( List recordLengths, BinaryTree strings, int numStrings, int numUniqueStrings )
{
this.recordLengths = recordLengths;
@@ -84,6 +92,9 @@
this.numStrings = numStrings;
this.numUniqueStrings = numUniqueStrings;
this.sstRecordHeader = new SSTRecordHeader( numStrings, numUniqueStrings );
+
+ this.bucketAbsoluteOffsets = new int[strings.size()/DEFAULT_BUCKET_SIZE+1];
+ this.bucketRelativeOffsets = new int[strings.size()/DEFAULT_BUCKET_SIZE+1];
}
/**
@@ -133,7 +144,6 @@
/**
* 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 )
{
@@ -144,6 +154,11 @@
for ( int k = 0; k < strings.size(); k++ )
{
+ if (k % DEFAULT_BUCKET_SIZE == 0)
+ {
+ bucketAbsoluteOffsets[k / DEFAULT_BUCKET_SIZE] = pos;
+ bucketRelativeOffsets[k / DEFAULT_BUCKET_SIZE] = pos;
+ }
System.arraycopy( getUnicodeString( k ).serialize(), 0, data, pos + offset, getUnicodeString( k ).getRecordSize() );
pos += getUnicodeString( k ).getRecordSize();
}
@@ -157,6 +172,8 @@
private void serializeLargeRecord( int record_size, int record_length_index, byte[] buffer, int offset )
{
+ startOfSST = offset;
+
byte[] stringReminant = null;
int stringIndex = 0;
boolean lastneedcontinue = false;
@@ -170,6 +187,7 @@
recordLength, numStrings, numUniqueStrings );
// write the appropriate header
+ startOfRecord = offset + totalWritten;
recordProcessor.writeRecordHeader( offset, totalWritten, recordLength, first_record );
first_record = false;
@@ -189,6 +207,12 @@
{
UnicodeString unistr = getUnicodeString( stringIndex );
+ if (stringIndex % DEFAULT_BUCKET_SIZE == 0)
+ {
+ bucketAbsoluteOffsets[stringIndex / DEFAULT_BUCKET_SIZE] = offset + totalWritten + recordProcessor.getRecordOffset() - startOfSST;
+ bucketRelativeOffsets[stringIndex / DEFAULT_BUCKET_SIZE] = offset + totalWritten + recordProcessor.getRecordOffset() - startOfRecord;
+ }
+
if ( unistr.getRecordSize() <= recordProcessor.getAvailable() )
{
recordProcessor.writeWholeString( unistr, offset, totalWritten );
@@ -234,5 +258,15 @@
public List getRecordLengths()
{
return recordLengths;
+ }
+
+ public int[] getBucketAbsoluteOffsets()
+ {
+ return bucketAbsoluteOffsets;
+ }
+
+ public int[] getBucketRelativeOffsets()
+ {
+ return bucketRelativeOffsets;
}
}