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;
       }
   }