OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * Copyright (C) 2004-2014, International Business Machines Corporation and | 3 * Copyright (C) 2004-2014, International Business Machines Corporation and |
4 * others. All Rights Reserved. | 4 * others. All Rights Reserved. |
5 ******************************************************************************* | 5 ******************************************************************************* |
6 */ | 6 */ |
7 package com.ibm.icu.impl; | 7 package com.ibm.icu.impl; |
8 | 8 |
9 import java.io.IOException; | 9 import java.io.IOException; |
10 import java.io.InputStream; | 10 import java.io.InputStream; |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 } | 321 } |
322 } | 322 } |
323 | 323 |
324 private static class ReaderCache extends SoftCache<ReaderInfo, ICUResourceBu
ndleReader, ReaderInfo> { | 324 private static class ReaderCache extends SoftCache<ReaderInfo, ICUResourceBu
ndleReader, ReaderInfo> { |
325 /* (non-Javadoc) | 325 /* (non-Javadoc) |
326 * @see com.ibm.icu.impl.CacheBase#createInstance(java.lang.Object, java
.lang.Object) | 326 * @see com.ibm.icu.impl.CacheBase#createInstance(java.lang.Object, java
.lang.Object) |
327 */ | 327 */ |
328 @Override | 328 @Override |
329 protected ICUResourceBundleReader createInstance(ReaderInfo key, ReaderI
nfo data) { | 329 protected ICUResourceBundleReader createInstance(ReaderInfo key, ReaderI
nfo data) { |
330 String fullName = ICUResourceBundleReader.getFullName(data.baseName,
data.localeID); | 330 String fullName = ICUResourceBundleReader.getFullName(data.baseName,
data.localeID); |
331 InputStream stream = ICUData.getStream(data.loader, fullName); | 331 try { |
332 if (stream == null) { | 332 ByteBuffer inBytes; |
333 return NULL_READER; | 333 if (data.baseName != null && data.baseName.startsWith(ICUData.IC
U_BASE_NAME)) { |
| 334 String itemPath = fullName.substring(ICUData.ICU_BASE_NAME.l
ength() + 1); |
| 335 inBytes = ICUBinary.getData(data.loader, fullName, itemPath)
; |
| 336 if (inBytes == null) { |
| 337 return NULL_READER; |
| 338 } |
| 339 } else { |
| 340 InputStream stream = ICUData.getStream(data.loader, fullName
); |
| 341 if (stream == null) { |
| 342 return NULL_READER; |
| 343 } |
| 344 inBytes = ICUBinary.getByteBufferFromInputStream(stream); |
| 345 } |
| 346 return new ICUResourceBundleReader(inBytes, data.baseName, data.
localeID, data.loader); |
| 347 } catch (IOException ex) { |
| 348 throw new ICUUncheckedIOException("Data file " + fullName + " is
corrupt - " + ex.getMessage(), ex); |
334 } | 349 } |
335 return new ICUResourceBundleReader(stream, data.baseName, data.local
eID, data.loader); | |
336 } | 350 } |
337 } | 351 } |
338 | 352 |
339 /* | 353 /* |
340 * Default constructor, just used for NULL_READER. | 354 * Default constructor, just used for NULL_READER. |
341 */ | 355 */ |
342 private ICUResourceBundleReader() { | 356 private ICUResourceBundleReader() { |
343 } | 357 } |
344 | 358 |
345 private ICUResourceBundleReader(InputStream stream, String baseName, String
localeID, ClassLoader loader) { | 359 private ICUResourceBundleReader(ByteBuffer inBytes, |
346 try { | 360 String baseName, String localeID, |
347 ByteBuffer inBytes = ICUBinary.getByteBufferFromInputStream(stream); | 361 ClassLoader loader) throws IOException { |
348 init(inBytes); | 362 init(inBytes); |
349 } catch (IOException ex) { | |
350 String fullName = ICUResourceBundleReader.getFullName(baseName, loca
leID); | |
351 throw new ICUUncheckedIOException("Data file " + fullName + " is cor
rupt - " + ex.getMessage(), ex); | |
352 } | |
353 | 363 |
354 // set pool bundle keys if necessary | 364 // set pool bundle keys if necessary |
355 if (usesPoolBundle) { | 365 if (usesPoolBundle) { |
356 ICUResourceBundleReader poolBundleReader = getReader(baseName, "pool
", loader); | 366 ICUResourceBundleReader poolBundleReader = getReader(baseName, "pool
", loader); |
357 if (!poolBundleReader.isPoolBundle) { | 367 if (!poolBundleReader.isPoolBundle) { |
358 throw new IllegalStateException("pool.res is not a pool bundle")
; | 368 throw new IllegalStateException("pool.res is not a pool bundle")
; |
359 } | 369 } |
360 if (poolBundleReader.poolCheckSum != poolCheckSum) { | 370 if (poolBundleReader.poolCheckSum != poolCheckSum) { |
361 throw new IllegalStateException("pool.res has a different checks
um than this bundle"); | 371 throw new IllegalStateException("pool.res has a different checks
um than this bundle"); |
362 } | 372 } |
363 poolBundleKeys = poolBundleReader.bytes; | 373 poolBundleKeys = poolBundleReader.bytes; |
364 } | 374 } |
365 } | 375 } |
366 | 376 |
367 static ICUResourceBundleReader getReader(String baseName, String localeID, C
lassLoader root) { | 377 static ICUResourceBundleReader getReader(String baseName, String localeID, C
lassLoader root) { |
368 ReaderInfo info = new ReaderInfo(baseName, localeID, root); | 378 ReaderInfo info = new ReaderInfo(baseName, localeID, root); |
369 ICUResourceBundleReader reader = CACHE.getInstance(info, info); | 379 ICUResourceBundleReader reader = CACHE.getInstance(info, info); |
370 if (reader == NULL_READER) { | 380 if (reader == NULL_READER) { |
371 return null; | 381 return null; |
372 } | 382 } |
373 return reader; | 383 return reader; |
374 } | 384 } |
375 | 385 |
376 // See res_init() in ICU4C/source/common/uresdata.c. | 386 // See res_init() in ICU4C/source/common/uresdata.c. |
377 private void init(ByteBuffer inBytes) throws IOException { | 387 private void init(ByteBuffer inBytes) throws IOException { |
378 dataVersion = ICUBinary.readHeader(inBytes, DATA_FORMAT, IS_ACCEPTABLE); | 388 dataVersion = ICUBinary.readHeader(inBytes, DATA_FORMAT, IS_ACCEPTABLE); |
379 boolean isFormatVersion10 = inBytes.get(16) == 1 && inBytes.get(17) == 0
; | 389 boolean isFormatVersion10 = inBytes.get(16) == 1 && inBytes.get(17) == 0
; |
380 bytes = inBytes.slice(); | 390 bytes = ICUBinary.sliceWithOrder(inBytes); |
381 int dataLength = bytes.remaining(); | 391 int dataLength = bytes.remaining(); |
382 | 392 |
383 if(DEBUG) System.out.println("The ByteBuffer is direct (memory-mapped):
" + bytes.isDirect()); | 393 if(DEBUG) System.out.println("The ByteBuffer is direct (memory-mapped):
" + bytes.isDirect()); |
384 if(DEBUG) System.out.println("The available bytes in the buffer before r
eading the data: " + dataLength); | 394 if(DEBUG) System.out.println("The available bytes in the buffer before r
eading the data: " + dataLength); |
385 | 395 |
386 rootRes = bytes.getInt(0); | 396 rootRes = bytes.getInt(0); |
387 | 397 |
388 if(isFormatVersion10) { | 398 if(isFormatVersion10) { |
389 localKeyLimit = 0x10000; /* greater than any 16-bit key string offs
et */ | 399 localKeyLimit = 0x10000; /* greater than any 16-bit key string offs
et */ |
390 resourceCache = new ResourceCache(dataLength / 4 - 1); | 400 resourceCache = new ResourceCache(dataLength / 4 - 1); |
(...skipping 22 matching lines...) Expand all Loading... |
413 usesPoolBundle = (att & URES_ATT_USES_POOL_BUNDLE) != 0; | 423 usesPoolBundle = (att & URES_ATT_USES_POOL_BUNDLE) != 0; |
414 } | 424 } |
415 | 425 |
416 // Read the array of 16-bit units. | 426 // Read the array of 16-bit units. |
417 if(indexLength > URES_INDEX_16BIT_TOP) { | 427 if(indexLength > URES_INDEX_16BIT_TOP) { |
418 int keysTop = getIndexesInt(URES_INDEX_KEYS_TOP); | 428 int keysTop = getIndexesInt(URES_INDEX_KEYS_TOP); |
419 int _16BitTop = getIndexesInt(URES_INDEX_16BIT_TOP); | 429 int _16BitTop = getIndexesInt(URES_INDEX_16BIT_TOP); |
420 if(_16BitTop > keysTop) { | 430 if(_16BitTop > keysTop) { |
421 int num16BitUnits = (_16BitTop - keysTop) * 2; | 431 int num16BitUnits = (_16BitTop - keysTop) * 2; |
422 bytes.position(keysTop << 2); | 432 bytes.position(keysTop << 2); |
423 b16BitUnits = bytes.slice().asCharBuffer(); | 433 b16BitUnits = bytes.asCharBuffer(); |
424 b16BitUnits.limit(num16BitUnits); | 434 b16BitUnits.limit(num16BitUnits); |
425 maxOffset |= num16BitUnits - 1; | 435 maxOffset |= num16BitUnits - 1; |
426 } else { | 436 } else { |
427 b16BitUnits = EMPTY_16_BIT_UNITS; | 437 b16BitUnits = EMPTY_16_BIT_UNITS; |
428 } | 438 } |
429 } else { | 439 } else { |
430 b16BitUnits = EMPTY_16_BIT_UNITS; | 440 b16BitUnits = EMPTY_16_BIT_UNITS; |
431 } | 441 } |
432 | 442 |
433 if(indexLength > URES_INDEX_POOL_CHECKSUM) { | 443 if(indexLength > URES_INDEX_POOL_CHECKSUM) { |
434 poolCheckSum = getIndexesInt(URES_INDEX_POOL_CHECKSUM); | 444 poolCheckSum = getIndexesInt(URES_INDEX_POOL_CHECKSUM); |
435 } | 445 } |
436 | 446 |
437 // Handle key strings last: | 447 // Handle key strings last: |
438 // If this is a pool bundle, then we shift all bytes down, | 448 // If this is a pool bundle, then we shift all bytes down, |
439 // and getIndexesInt() will not work any more. | 449 // and getIndexesInt() will not work any more. |
440 if(getIndexesInt(URES_INDEX_KEYS_TOP) > (1 + indexLength)) { | 450 if(getIndexesInt(URES_INDEX_KEYS_TOP) > (1 + indexLength)) { |
441 if(isPoolBundle) { | 451 if(isPoolBundle) { |
442 // Shift the key strings down: | 452 // Shift the key strings down: |
443 // Pool bundle key strings are used with a 0-based index, | 453 // Pool bundle key strings are used with a 0-based index, |
444 // unlike regular bundles' key strings for which indexes | 454 // unlike regular bundles' key strings for which indexes |
445 // are based on the start of the bundle data. | 455 // are based on the start of the bundle data. |
446 bytes.position((1 + indexLength) << 2); | 456 bytes.position((1 + indexLength) << 2); |
447 bytes = bytes.slice(); | 457 bytes = ICUBinary.sliceWithOrder(bytes); |
448 } else { | 458 } else { |
449 localKeyLimit = getIndexesInt(URES_INDEX_KEYS_TOP) << 2; | 459 localKeyLimit = getIndexesInt(URES_INDEX_KEYS_TOP) << 2; |
450 } | 460 } |
451 } | 461 } |
452 | 462 |
453 if(!isPoolBundle) { | 463 if(!isPoolBundle) { |
454 resourceCache = new ResourceCache(maxOffset); | 464 resourceCache = new ResourceCache(maxOffset); |
455 } | 465 } |
456 } | 466 } |
457 | 467 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 return makeKeyStringFromBytes(poolBundleKeys, keyOffset - localKeyLi
mit); | 585 return makeKeyStringFromBytes(poolBundleKeys, keyOffset - localKeyLi
mit); |
576 } | 586 } |
577 } | 587 } |
578 private String getKey32String(int keyOffset) { | 588 private String getKey32String(int keyOffset) { |
579 if(keyOffset >= 0) { | 589 if(keyOffset >= 0) { |
580 return makeKeyStringFromBytes(bytes, keyOffset); | 590 return makeKeyStringFromBytes(bytes, keyOffset); |
581 } else { | 591 } else { |
582 return makeKeyStringFromBytes(poolBundleKeys, keyOffset & 0x7fffffff
); | 592 return makeKeyStringFromBytes(poolBundleKeys, keyOffset & 0x7fffffff
); |
583 } | 593 } |
584 } | 594 } |
585 // Compare the length-specified input key with the | |
586 // NUL-terminated table key. | |
587 private static int compareKeys(CharSequence key, ByteBuffer keyBytes, int ke
yOffset) { | |
588 for(int i = 0;; ++i, ++keyOffset) { | |
589 int c2 = keyBytes.get(keyOffset); | |
590 if(c2 == 0) { | |
591 if(i == key.length()) { | |
592 return 0; | |
593 } else { | |
594 return 1; // key > table key because key is longer. | |
595 } | |
596 } else if(i == key.length()) { | |
597 return -1; // key < table key because key is shorter. | |
598 } | |
599 int diff = (int)key.charAt(i) - c2; | |
600 if(diff != 0) { | |
601 return diff; | |
602 } | |
603 } | |
604 } | |
605 private int compareKeys(CharSequence key, char keyOffset) { | 595 private int compareKeys(CharSequence key, char keyOffset) { |
606 if(keyOffset < localKeyLimit) { | 596 if(keyOffset < localKeyLimit) { |
607 return compareKeys(key, bytes, keyOffset); | 597 return ICUBinary.compareKeys(key, bytes, keyOffset); |
608 } else { | 598 } else { |
609 return compareKeys(key, poolBundleKeys, keyOffset - localKeyLimit); | 599 return ICUBinary.compareKeys(key, poolBundleKeys, keyOffset - localK
eyLimit); |
610 } | 600 } |
611 } | 601 } |
612 private int compareKeys32(CharSequence key, int keyOffset) { | 602 private int compareKeys32(CharSequence key, int keyOffset) { |
613 if(keyOffset >= 0) { | 603 if(keyOffset >= 0) { |
614 return compareKeys(key, bytes, keyOffset); | 604 return ICUBinary.compareKeys(key, bytes, keyOffset); |
615 } else { | 605 } else { |
616 return compareKeys(key, poolBundleKeys, keyOffset & 0x7fffffff); | 606 return ICUBinary.compareKeys(key, poolBundleKeys, keyOffset & 0x7fff
ffff); |
617 } | 607 } |
618 } | 608 } |
619 | 609 |
620 String getString(int res) { | 610 String getString(int res) { |
621 int offset=RES_GET_OFFSET(res); | 611 int offset=RES_GET_OFFSET(res); |
622 if(res != offset /* RES_GET_TYPE(res) != URES_STRING */ && | 612 if(res != offset /* RES_GET_TYPE(res) != URES_STRING */ && |
623 RES_GET_TYPE(res) != ICUResourceBundle.STRING_V2) { | 613 RES_GET_TYPE(res) != ICUResourceBundle.STRING_V2) { |
624 return null; | 614 return null; |
625 } | 615 } |
626 if(offset == 0) { | 616 if(offset == 0) { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 // Also, even a cached buffer would have to be cloned because it
is mutable | 726 // Also, even a cached buffer would have to be cloned because it
is mutable |
737 // (position & mark). | 727 // (position & mark). |
738 offset=getResourceByteOffset(offset); | 728 offset=getResourceByteOffset(offset); |
739 length=getInt(offset); | 729 length=getInt(offset); |
740 if(length == 0) { | 730 if(length == 0) { |
741 return emptyByteBuffer.duplicate(); | 731 return emptyByteBuffer.duplicate(); |
742 } | 732 } |
743 offset += 4; | 733 offset += 4; |
744 ByteBuffer result = bytes.duplicate(); | 734 ByteBuffer result = bytes.duplicate(); |
745 result.position(offset).limit(offset + length); | 735 result.position(offset).limit(offset + length); |
746 result = result.slice(); | 736 result = ICUBinary.sliceWithOrder(result); |
747 if(!result.isReadOnly()) { | 737 if(!result.isReadOnly()) { |
748 result = result.asReadOnlyBuffer(); | 738 result = result.asReadOnlyBuffer(); |
749 } | 739 } |
750 return result; | 740 return result; |
751 } | 741 } |
752 } else { | 742 } else { |
753 return null; | 743 return null; |
754 } | 744 } |
755 } | 745 } |
756 | 746 |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 baseName = baseName.replace('.', '/'); | 1218 baseName = baseName.replace('.', '/'); |
1229 if (localeName.length() == 0) { | 1219 if (localeName.length() == 0) { |
1230 return baseName + ICU_RESOURCE_SUFFIX; | 1220 return baseName + ICU_RESOURCE_SUFFIX; |
1231 } else { | 1221 } else { |
1232 return baseName + "_" + localeName + ICU_RESOURCE_SUFFIX; | 1222 return baseName + "_" + localeName + ICU_RESOURCE_SUFFIX; |
1233 } | 1223 } |
1234 } | 1224 } |
1235 } | 1225 } |
1236 } | 1226 } |
1237 } | 1227 } |
OLD | NEW |