1 19 20 package jxl.read.biff; 21 22 import common.Assert; 23 24 import jxl.WorkbookSettings; 25 import jxl.biff.IntegerHelper; 26 import jxl.biff.RecordData; 27 import jxl.biff.StringHelper; 28 29 32 class SSTRecord extends RecordData 33 { 34 37 private int totalStrings; 38 41 private int uniqueStrings; 42 45 private String [] strings; 46 49 private int[] continuationBreaks; 50 51 54 private static class ByteArrayHolder 55 { 56 59 public byte[] bytes; 60 } 61 62 65 private static class BooleanHolder 66 { 67 70 public boolean value; 71 } 72 73 80 public SSTRecord(Record t, Record[] continuations, WorkbookSettings ws) 81 { 82 super(t); 83 84 87 int totalRecordLength = 0; 89 90 for (int i = 0; i < continuations.length; i++) 91 { 92 totalRecordLength += continuations[i].getLength(); 93 } 94 totalRecordLength += getRecord().getLength(); 95 96 byte[] data = new byte[totalRecordLength]; 97 98 int pos = 0; 100 System.arraycopy(getRecord().getData(), 0, 101 data, 0, getRecord().getLength()); 102 pos += getRecord().getLength(); 103 104 continuationBreaks = new int[continuations.length]; 106 Record r = null; 107 for (int i = 0; i < continuations.length; i++) 108 { 109 r = continuations[i]; 110 System.arraycopy(r.getData(), 0, 111 data, pos, 112 r.getLength()); 113 continuationBreaks[i] = pos; 114 pos += r.getLength(); 115 } 116 117 totalStrings = IntegerHelper.getInt(data[0], data[1], 118 data[2], data[3]); 119 uniqueStrings = IntegerHelper.getInt(data[4], data[5], 120 data[6], data[7]); 121 122 strings = new String [uniqueStrings]; 123 readStrings(data, 8, ws); 124 } 125 126 133 private void readStrings(byte[] data, int offset, WorkbookSettings ws) 134 { 135 int pos = offset; 136 int numChars; 137 byte optionFlags; 138 String s = null; 139 boolean asciiEncoding = false; 140 boolean richString = false; 141 boolean extendedString = false; 142 int formattingRuns = 0; 143 int extendedRunLength = 0; 144 145 for (int i = 0; i < uniqueStrings; i++) 146 { 147 numChars = IntegerHelper.getInt(data[pos], data[pos + 1]); 149 pos += 2; 150 optionFlags = data[pos]; 151 pos++; 152 153 extendedString = ((optionFlags & 0x04) != 0); 155 156 richString = ((optionFlags & 0x08) != 0); 158 159 if (richString) 160 { 161 formattingRuns = IntegerHelper.getInt(data[pos], data[pos + 1]); 163 pos += 2; 164 } 165 166 if (extendedString) 167 { 168 extendedRunLength = IntegerHelper.getInt 170 (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); 171 pos += 4; 172 } 173 174 asciiEncoding = ((optionFlags & 0x01) == 0); 176 177 ByteArrayHolder bah = new ByteArrayHolder(); 178 BooleanHolder bh = new BooleanHolder(); 179 bh.value = asciiEncoding; 180 pos += getChars(data, bah, pos, bh, numChars); 181 asciiEncoding = bh.value; 182 183 if (asciiEncoding) 184 { 185 s = StringHelper.getString(bah.bytes, numChars, 0, ws); 186 } 187 else 188 { 189 s = StringHelper.getUnicodeString(bah.bytes, numChars, 0); 190 } 191 192 strings[i] = s; 193 194 if (richString) 196 { 197 pos += 4 * formattingRuns; 198 } 199 200 if (extendedString) 202 { 203 pos += extendedRunLength; 204 } 205 206 if (pos > data.length) 207 { 208 Assert.verify(false, "pos exceeds record length"); 209 } 210 } 211 } 212 213 224 private int getChars(byte[] source, 225 ByteArrayHolder bah, 226 int pos, 227 BooleanHolder ascii, 228 int numChars) 229 { 230 int i = 0; 231 boolean spansBreak = false; 232 233 if (ascii.value) 234 { 235 bah.bytes = new byte[numChars]; 236 } 237 else 238 { 239 bah.bytes = new byte[numChars * 2]; 240 } 241 242 while (i < continuationBreaks.length && !spansBreak) 243 { 244 spansBreak = pos <= continuationBreaks[i] && 245 (pos + bah.bytes.length > continuationBreaks[i]); 246 247 if (!spansBreak) 248 { 249 i++; 250 } 251 } 252 253 if (!spansBreak) 256 { 257 System.arraycopy(source, pos, bah.bytes, 0, bah.bytes.length); 258 return bah.bytes.length; 259 } 260 261 int breakpos = continuationBreaks[i]; 263 System.arraycopy(source, pos, bah.bytes, 0, breakpos - pos); 264 265 int bytesRead = breakpos - pos; 266 int charsRead; 267 if (ascii.value) 268 { 269 charsRead = bytesRead; 270 } 271 else 272 { 273 charsRead = bytesRead / 2; 274 } 275 276 bytesRead += getContinuedString(source, 277 bah, 278 bytesRead, 279 i, 280 ascii, 281 numChars - charsRead); 282 return bytesRead; 283 } 284 285 296 private int getContinuedString(byte[] source, 297 ByteArrayHolder bah, 298 int destPos, 299 int contBreakIndex, 300 BooleanHolder ascii, 301 int charsLeft) 302 { 303 int breakpos = continuationBreaks[contBreakIndex]; 304 int bytesRead = 0; 305 306 while (charsLeft > 0) 307 { 308 Assert.verify(contBreakIndex < continuationBreaks.length, 309 "continuation break index"); 310 311 if (ascii.value && source[breakpos] == 0) 312 { 313 315 int length = contBreakIndex == continuationBreaks.length - 1 ? 316 charsLeft : 317 Math.min 318 (charsLeft, 319 continuationBreaks[contBreakIndex + 1] - breakpos - 1); 320 321 System.arraycopy(source, 322 breakpos + 1, 323 bah.bytes, 324 destPos, 325 length); 326 destPos += length; 327 bytesRead += length + 1; 328 charsLeft -= length; 329 ascii.value = true; 330 } 331 else if (!ascii.value && source[breakpos] != 0) 332 { 333 335 int length = contBreakIndex == continuationBreaks.length - 1 ? 336 charsLeft * 2 : 337 Math.min 338 (charsLeft * 2, 339 continuationBreaks[contBreakIndex + 1] - breakpos - 1); 340 341 System.arraycopy(source, 343 breakpos + 1, 344 bah.bytes, 345 destPos, 346 length); 347 348 destPos += length; 349 bytesRead += length + 1; 350 charsLeft -= length / 2; 351 ascii.value = false; 352 } 353 else if (!ascii.value && source[breakpos] == 0) 354 { 355 int chars = contBreakIndex == continuationBreaks.length - 1 ? 358 charsLeft: 359 Math.min 360 (charsLeft, 361 continuationBreaks[contBreakIndex + 1] - breakpos - 1); 362 363 for (int j = 0; j < chars; j++) 364 { 365 bah.bytes[destPos] = source[breakpos + j + 1]; 366 destPos += 2; 367 } 368 369 bytesRead += chars + 1; 370 charsLeft -= chars; 371 ascii.value = false; 372 } 373 else 374 { 375 378 byte[] oldBytes = bah.bytes; 381 bah.bytes = new byte[destPos * 2 + charsLeft * 2]; 382 for (int j = 0; j < destPos; j++) 383 { 384 bah.bytes[j * 2] = oldBytes[j]; 385 } 386 387 destPos = destPos * 2; 388 389 int length = contBreakIndex == continuationBreaks.length - 1 ? 390 charsLeft * 2 : 391 Math.min 392 (charsLeft * 2, 393 continuationBreaks[contBreakIndex + 1] - breakpos - 1); 394 395 System.arraycopy(source, 396 breakpos + 1, 397 bah.bytes, 398 destPos, 399 length); 400 401 destPos += length; 402 bytesRead += length + 1; 403 charsLeft -= length / 2; 404 ascii.value = false; 405 } 406 407 contBreakIndex++; 408 409 if (contBreakIndex < continuationBreaks.length) 410 { 411 breakpos = continuationBreaks[contBreakIndex]; 412 } 413 } 414 415 return bytesRead; 416 } 417 418 424 public String getString(int index) 425 { 426 Assert.verify(index < uniqueStrings); 427 return strings[index]; 428 } 429 } 430 431 432 | Popular Tags |