1 2 17 18 19 package org.apache.poi.hssf.record; 20 21 import org.apache.poi.util.BinaryTree; 22 23 import java.util.List ; 24 import java.util.ArrayList ; 25 import java.util.Map ; 26 27 33 class SSTSerializer 34 { 35 36 private List recordLengths; 38 private BinaryTree strings; 39 40 private int numStrings; 41 private int numUniqueStrings; 42 private SSTRecordHeader sstRecordHeader; 43 44 45 int[] bucketAbsoluteOffsets; 46 47 int[] bucketRelativeOffsets; 48 int startOfSST, startOfRecord; 49 50 public SSTSerializer( List recordLengths, BinaryTree strings, int numStrings, int numUniqueStrings ) 51 { 52 this.recordLengths = recordLengths; 53 this.strings = strings; 54 this.numStrings = numStrings; 55 this.numUniqueStrings = numUniqueStrings; 56 this.sstRecordHeader = new SSTRecordHeader( numStrings, numUniqueStrings ); 57 58 int infoRecs = ExtSSTRecord.getNumberOfInfoRecsForStrings(strings.size()); 59 this.bucketAbsoluteOffsets = new int[infoRecs]; 60 this.bucketRelativeOffsets = new int[infoRecs]; 61 } 62 63 74 public int serialize( int record_size, int offset, byte[] data ) 75 { 76 int record_length_index = 0; 77 78 if ( calculateUnicodeSize() > SSTRecord.MAX_DATA_SPACE ) 79 serializeLargeRecord( record_size, record_length_index, data, offset ); 80 else 81 serializeSingleSSTRecord( data, offset, record_length_index ); 82 return record_size; 83 } 84 85 86 87 92 public static int calculateUnicodeSize(Map strings) 93 { 94 int retval = 0; 95 96 for ( int k = 0; k < strings.size(); k++ ) 97 { 98 retval += getUnicodeString( strings, k ).getRecordSize(); 99 } 100 return retval; 101 } 102 103 public int calculateUnicodeSize() 104 { 105 return calculateUnicodeSize(strings); 106 } 107 108 111 private void serializeSingleSSTRecord( byte[] data, int offset, int record_length_index ) 112 { 113 int len = ( (Integer ) recordLengths.get( record_length_index ) ).intValue(); 114 int recordSize = len - SSTRecord.STD_RECORD_OVERHEAD; 115 sstRecordHeader.writeSSTHeader( data, 0 + offset, recordSize ); 116 int pos = SSTRecord.SST_RECORD_OVERHEAD; 117 118 for ( int k = 0; k < strings.size(); k++ ) 119 { 120 if (k % ExtSSTRecord.DEFAULT_BUCKET_SIZE == 0) 121 { 122 int index = k/ExtSSTRecord.DEFAULT_BUCKET_SIZE; 123 if (index < ExtSSTRecord.MAX_BUCKETS) { 124 bucketAbsoluteOffsets[index] = pos; 126 bucketRelativeOffsets[index] = pos; 127 } 128 } 129 System.arraycopy( getUnicodeString( k ).serialize(), 0, data, pos + offset, getUnicodeString( k ).getRecordSize() ); 130 pos += getUnicodeString( k ).getRecordSize(); 131 } 132 } 133 134 139 private void serializeLargeRecord( int record_size, int record_length_index, byte[] buffer, int offset ) 140 { 141 142 startOfSST = offset; 143 144 byte[] stringReminant = null; 145 int stringIndex = 0; 146 boolean lastneedcontinue = false; 147 boolean first_record = true; 148 int totalWritten = 0; 149 150 while ( totalWritten != record_size ) 151 { 152 final int recordLength = ( (Integer ) recordLengths.get( record_length_index++ ) ).intValue(); 154 final int recordDataLength = recordLength - 4; 156 RecordProcessor recordProcessor = new RecordProcessor( buffer, 157 recordDataLength, numStrings, numUniqueStrings ); 158 159 startOfRecord = offset + totalWritten; 161 recordProcessor.writeRecordHeader( offset, totalWritten, recordDataLength, first_record ); 162 first_record = false; 163 164 if ( lastneedcontinue ) 167 { 168 lastneedcontinue = stringReminant.length > recordProcessor.getAvailable(); 169 stringReminant = recordProcessor.writeStringRemainder( lastneedcontinue, 171 stringReminant, offset, totalWritten ); 172 if (lastneedcontinue) { 174 totalWritten += recordLength; 175 continue; 176 } 177 } 178 179 for ( ; stringIndex < strings.size(); stringIndex++ ) 182 { 183 UnicodeString unistr = getUnicodeString( stringIndex ); 184 185 if (stringIndex % ExtSSTRecord.DEFAULT_BUCKET_SIZE == 0) 186 { 187 int index = stringIndex / ExtSSTRecord.DEFAULT_BUCKET_SIZE; 188 if (index < ExtSSTRecord.MAX_BUCKETS) { 189 bucketAbsoluteOffsets[index] = offset + totalWritten + 190 recordProcessor.getRecordOffset() - startOfSST; 191 bucketRelativeOffsets[index] = offset + totalWritten + 192 recordProcessor.getRecordOffset() - startOfRecord; 193 } 194 } 195 196 if ( unistr.getRecordSize() <= recordProcessor.getAvailable() ) 197 { 198 recordProcessor.writeWholeString( unistr, offset, totalWritten ); 199 } 200 else 201 { 202 203 if ( recordProcessor.getAvailable() >= SSTRecord.STRING_MINIMAL_OVERHEAD ) 205 { 206 207 stringReminant = recordProcessor.writePartString( unistr, offset, totalWritten ); 209 lastneedcontinue = true; 210 stringIndex++; 211 } 212 break; 213 } 214 } 215 totalWritten += recordLength; 216 } 217 } 218 219 private UnicodeString getUnicodeString( int index ) 220 { 221 return getUnicodeString(strings, index); 222 } 223 224 private static UnicodeString getUnicodeString( Map strings, int index ) 225 { 226 Integer intunipos = new Integer ( index ); 227 return ( (UnicodeString) strings.get( intunipos ) ); 228 } 229 230 public int getRecordSize() 231 { 232 SSTRecordSizeCalculator calculator = new SSTRecordSizeCalculator(strings); 233 int recordSize = calculator.getRecordSize(); 234 recordLengths = calculator.getRecordLengths(); 235 return recordSize; 236 } 237 238 public List getRecordLengths() 239 { 240 return recordLengths; 241 } 242 243 public int[] getBucketAbsoluteOffsets() 244 { 245 return bucketAbsoluteOffsets; 246 } 247 248 public int[] getBucketRelativeOffsets() 249 { 250 return bucketRelativeOffsets; 251 } 252 } 253 | Popular Tags |