OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * Copyright (C) 1999-2015, International Business Machines Corporation | 3 * Copyright (C) 1999-2015, International Business Machines Corporation |
4 * and others. All Rights Reserved. | 4 * and others. All Rights Reserved. |
5 ******************************************************************************* | 5 ******************************************************************************* |
6 * file name: uresdata.c | 6 * file name: uresdata.cpp |
7 * encoding: US-ASCII | 7 * encoding: US-ASCII |
8 * tab size: 8 (not used) | 8 * tab size: 8 (not used) |
9 * indentation:4 | 9 * indentation:4 |
10 * | 10 * |
11 * created on: 1999dec08 | 11 * created on: 1999dec08 |
12 * created by: Markus W. Scherer | 12 * created by: Markus W. Scherer |
13 * Modification History: | 13 * Modification History: |
14 * | 14 * |
15 * Date Name Description | 15 * Date Name Description |
16 * 06/20/2000 helena OS/400 port changes; mostly typecast. | 16 * 06/20/2000 helena OS/400 port changes; mostly typecast. |
17 * 06/24/02 weiv Added support for resource sharing | 17 * 06/24/02 weiv Added support for resource sharing |
18 */ | 18 */ |
19 | 19 |
20 #include "unicode/utypes.h" | 20 #include "unicode/utypes.h" |
21 #include "unicode/udata.h" | 21 #include "unicode/udata.h" |
22 #include "unicode/ustring.h" | 22 #include "unicode/ustring.h" |
23 #include "unicode/utf16.h" | 23 #include "unicode/utf16.h" |
24 #include "cmemory.h" | 24 #include "cmemory.h" |
25 #include "cstring.h" | 25 #include "cstring.h" |
| 26 #include "resource.h" |
26 #include "uarrsort.h" | 27 #include "uarrsort.h" |
| 28 #include "uassert.h" |
| 29 #include "ucol_swp.h" |
27 #include "udataswp.h" | 30 #include "udataswp.h" |
28 #include "ucol_swp.h" | |
29 #include "uinvchar.h" | 31 #include "uinvchar.h" |
30 #include "uresdata.h" | 32 #include "uresdata.h" |
31 #include "uresimp.h" | 33 #include "uresimp.h" |
32 #include "uassert.h" | |
33 | 34 |
34 /* | 35 /* |
35 * Resource access helpers | 36 * Resource access helpers |
36 */ | 37 */ |
37 | 38 |
38 /* get a const char* pointer to the key with the keyOffset byte offset from pRoo
t */ | 39 /* get a const char* pointer to the key with the keyOffset byte offset from pRoo
t */ |
39 #define RES_GET_KEY16(pResData, keyOffset) \ | 40 #define RES_GET_KEY16(pResData, keyOffset) \ |
40 ((keyOffset)<(pResData)->localKeyLimit ? \ | 41 ((keyOffset)<(pResData)->localKeyLimit ? \ |
41 (const char *)(pResData)->pRoot+(keyOffset) : \ | 42 (const char *)(pResData)->pRoot+(keyOffset) : \ |
42 (pResData)->poolBundleKeys+(keyOffset)-(pResData)->localKeyLimit) | 43 (pResData)->poolBundleKeys+(keyOffset)-(pResData)->localKeyLimit) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 return mid; | 127 return mid; |
127 } | 128 } |
128 } | 129 } |
129 return URESDATA_ITEM_NOT_FOUND; /* not found or table is empty. */ | 130 return URESDATA_ITEM_NOT_FOUND; /* not found or table is empty. */ |
130 } | 131 } |
131 | 132 |
132 /* helper for res_load() ---------------------------------------------------- */ | 133 /* helper for res_load() ---------------------------------------------------- */ |
133 | 134 |
134 static UBool U_CALLCONV | 135 static UBool U_CALLCONV |
135 isAcceptable(void *context, | 136 isAcceptable(void *context, |
136 const char *type, const char *name, | 137 const char * /*type*/, const char * /*name*/, |
137 const UDataInfo *pInfo) { | 138 const UDataInfo *pInfo) { |
138 uprv_memcpy(context, pInfo->formatVersion, 4); | 139 uprv_memcpy(context, pInfo->formatVersion, 4); |
139 return (UBool)( | 140 return (UBool)( |
140 pInfo->size>=20 && | 141 pInfo->size>=20 && |
141 pInfo->isBigEndian==U_IS_BIG_ENDIAN && | 142 pInfo->isBigEndian==U_IS_BIG_ENDIAN && |
142 pInfo->charsetFamily==U_CHARSET_FAMILY && | 143 pInfo->charsetFamily==U_CHARSET_FAMILY && |
143 pInfo->sizeofUChar==U_SIZEOF_UCHAR && | 144 pInfo->sizeofUChar==U_SIZEOF_UCHAR && |
144 pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ | 145 pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ |
145 pInfo->dataFormat[1]==0x65 && | 146 pInfo->dataFormat[1]==0x65 && |
146 pInfo->dataFormat[2]==0x73 && | 147 pInfo->dataFormat[2]==0x73 && |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 return (UResType)gPublicTypes[RES_GET_TYPE(res)]; | 304 return (UResType)gPublicTypes[RES_GET_TYPE(res)]; |
304 } | 305 } |
305 | 306 |
306 U_CAPI const UChar * U_EXPORT2 | 307 U_CAPI const UChar * U_EXPORT2 |
307 res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { | 308 res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { |
308 const UChar *p; | 309 const UChar *p; |
309 uint32_t offset=RES_GET_OFFSET(res); | 310 uint32_t offset=RES_GET_OFFSET(res); |
310 int32_t length; | 311 int32_t length; |
311 if(RES_GET_TYPE(res)==URES_STRING_V2) { | 312 if(RES_GET_TYPE(res)==URES_STRING_V2) { |
312 int32_t first; | 313 int32_t first; |
313 if(offset<pResData->poolStringIndexLimit) { | 314 if((int32_t)offset<pResData->poolStringIndexLimit) { |
314 p=(const UChar *)pResData->poolBundleStrings+offset; | 315 p=(const UChar *)pResData->poolBundleStrings+offset; |
315 } else { | 316 } else { |
316 p=(const UChar *)pResData->p16BitUnits+(offset-pResData->poolStringI
ndexLimit); | 317 p=(const UChar *)pResData->p16BitUnits+(offset-pResData->poolStringI
ndexLimit); |
317 } | 318 } |
318 first=*p; | 319 first=*p; |
319 if(!U16_IS_TRAIL(first)) { | 320 if(!U16_IS_TRAIL(first)) { |
320 length=u_strlen(p); | 321 length=u_strlen(p); |
321 } else if(first<0xdfef) { | 322 } else if(first<0xdfef) { |
322 length=first&0x3ff; | 323 length=first&0x3ff; |
323 ++p; | 324 ++p; |
(...skipping 11 matching lines...) Expand all Loading... |
335 } else { | 336 } else { |
336 p=NULL; | 337 p=NULL; |
337 length=0; | 338 length=0; |
338 } | 339 } |
339 if(pLength) { | 340 if(pLength) { |
340 *pLength=length; | 341 *pLength=length; |
341 } | 342 } |
342 return p; | 343 return p; |
343 } | 344 } |
344 | 345 |
| 346 namespace { |
| 347 |
| 348 /** |
| 349 * CLDR string value (three empty-set symbols)=={2205, 2205, 2205} |
| 350 * prevents fallback to the parent bundle. |
| 351 * TODO: combine with other code that handles this marker, use EMPTY_SET constan
t. |
| 352 * TODO: maybe move to uresbund.cpp? |
| 353 */ |
| 354 UBool isNoInheritanceMarker(const ResourceData *pResData, Resource res) { |
| 355 uint32_t offset=RES_GET_OFFSET(res); |
| 356 if (offset == 0) { |
| 357 // empty string |
| 358 } else if (res == offset) { |
| 359 const int32_t *p32=pResData->pRoot+res; |
| 360 int32_t length=*p32; |
| 361 const UChar *p=(const UChar *)p32; |
| 362 return length == 3 && p[2] == 0x2205 && p[3] == 0x2205 && p[4] == 0x2205
; |
| 363 } else if (RES_GET_TYPE(res) == URES_STRING_V2) { |
| 364 const UChar *p; |
| 365 if((int32_t)offset<pResData->poolStringIndexLimit) { |
| 366 p=(const UChar *)pResData->poolBundleStrings+offset; |
| 367 } else { |
| 368 p=(const UChar *)pResData->p16BitUnits+(offset-pResData->poolStringI
ndexLimit); |
| 369 } |
| 370 int32_t first=*p; |
| 371 if (first == 0x2205) { // implicit length |
| 372 return p[1] == 0x2205 && p[2] == 0x2205 && p[3] == 0; |
| 373 } else if (first == 0xdc03) { // explicit length 3 (should not occur) |
| 374 return p[1] == 0x2205 && p[2] == 0x2205 && p[3] == 0x2205; |
| 375 } else { |
| 376 // Assume that the string has not been stored with more length units
than necessary. |
| 377 return FALSE; |
| 378 } |
| 379 } |
| 380 return FALSE; |
| 381 } |
| 382 |
| 383 } // namespace |
| 384 |
345 U_CAPI const UChar * U_EXPORT2 | 385 U_CAPI const UChar * U_EXPORT2 |
346 res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength) { | 386 res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength) { |
347 const UChar *p; | 387 const UChar *p; |
348 uint32_t offset=RES_GET_OFFSET(res); | 388 uint32_t offset=RES_GET_OFFSET(res); |
349 int32_t length; | 389 int32_t length; |
350 if(RES_GET_TYPE(res)==URES_ALIAS) { | 390 if(RES_GET_TYPE(res)==URES_ALIAS) { |
351 const int32_t *p32= offset==0 ? &gEmptyString.length : pResData->pRoot+o
ffset; | 391 const int32_t *p32= offset==0 ? &gEmptyString.length : pResData->pRoot+o
ffset; |
352 length=*p32++; | 392 length=*p32++; |
353 p=(const UChar *)p32; | 393 p=(const UChar *)p32; |
354 } else { | 394 } else { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 case URES_TABLE: | 456 case URES_TABLE: |
417 return offset==0 ? 0 : *((const uint16_t *)(pResData->pRoot+offset)); | 457 return offset==0 ? 0 : *((const uint16_t *)(pResData->pRoot+offset)); |
418 case URES_ARRAY16: | 458 case URES_ARRAY16: |
419 case URES_TABLE16: | 459 case URES_TABLE16: |
420 return pResData->p16BitUnits[offset]; | 460 return pResData->p16BitUnits[offset]; |
421 default: | 461 default: |
422 return 0; | 462 return 0; |
423 } | 463 } |
424 } | 464 } |
425 | 465 |
| 466 namespace { |
| 467 |
| 468 int32_t getArrayLength(const ResourceData *pResData, Resource res) { |
| 469 uint32_t offset=RES_GET_OFFSET(res); |
| 470 if(offset == 0) { |
| 471 return 0; |
| 472 } |
| 473 int32_t type = RES_GET_TYPE(res); |
| 474 if(type == URES_ARRAY) { |
| 475 return *(pResData->pRoot+offset); |
| 476 } else if(type == URES_ARRAY16) { |
| 477 return pResData->p16BitUnits[offset]; |
| 478 } else { |
| 479 return 0; |
| 480 } |
| 481 } |
| 482 |
| 483 int32_t getTableLength(const ResourceData *pResData, Resource res) { |
| 484 uint32_t offset=RES_GET_OFFSET(res); |
| 485 if(offset == 0) { |
| 486 return 0; |
| 487 } |
| 488 int32_t type = RES_GET_TYPE(res); |
| 489 if(type == URES_TABLE) { |
| 490 return *((const uint16_t *)(pResData->pRoot+offset)); |
| 491 } else if(type == URES_TABLE16) { |
| 492 return pResData->p16BitUnits[offset]; |
| 493 } else if(type == URES_TABLE32) { |
| 494 return *(pResData->pRoot+offset); |
| 495 } else { |
| 496 return 0; |
| 497 } |
| 498 } |
| 499 |
| 500 } // namespace |
| 501 |
| 502 U_NAMESPACE_BEGIN |
| 503 |
| 504 ResourceDataValue::~ResourceDataValue() {} |
| 505 |
| 506 UResType ResourceDataValue::getType() const { |
| 507 return res_getPublicType(res); |
| 508 } |
| 509 |
| 510 const UChar *ResourceDataValue::getString(int32_t &length, UErrorCode &errorCode
) const { |
| 511 if(U_FAILURE(errorCode)) { |
| 512 return NULL; |
| 513 } |
| 514 const UChar *s = res_getString(pResData, res, &length); |
| 515 if(s == NULL) { |
| 516 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 517 } |
| 518 return s; |
| 519 } |
| 520 |
| 521 const UChar *ResourceDataValue::getAliasString(int32_t &length, UErrorCode &erro
rCode) const { |
| 522 if(U_FAILURE(errorCode)) { |
| 523 return NULL; |
| 524 } |
| 525 const UChar *s = res_getAlias(pResData, res, &length); |
| 526 if(s == NULL) { |
| 527 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 528 } |
| 529 return s; |
| 530 } |
| 531 |
| 532 int32_t ResourceDataValue::getInt(UErrorCode &errorCode) const { |
| 533 if(U_FAILURE(errorCode)) { |
| 534 return 0; |
| 535 } |
| 536 if(RES_GET_TYPE(res) != URES_INT) { |
| 537 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 538 } |
| 539 return RES_GET_INT(res); |
| 540 } |
| 541 |
| 542 uint32_t ResourceDataValue::getUInt(UErrorCode &errorCode) const { |
| 543 if(U_FAILURE(errorCode)) { |
| 544 return 0; |
| 545 } |
| 546 if(RES_GET_TYPE(res) != URES_INT) { |
| 547 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 548 } |
| 549 return RES_GET_UINT(res); |
| 550 } |
| 551 |
| 552 const int32_t *ResourceDataValue::getIntVector(int32_t &length, UErrorCode &erro
rCode) const { |
| 553 if(U_FAILURE(errorCode)) { |
| 554 return NULL; |
| 555 } |
| 556 const int32_t *iv = res_getIntVector(pResData, res, &length); |
| 557 if(iv == NULL) { |
| 558 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 559 } |
| 560 return iv; |
| 561 } |
| 562 |
| 563 const uint8_t *ResourceDataValue::getBinary(int32_t &length, UErrorCode &errorCo
de) const { |
| 564 if(U_FAILURE(errorCode)) { |
| 565 return NULL; |
| 566 } |
| 567 const uint8_t *b = res_getBinary(pResData, res, &length); |
| 568 if(b == NULL) { |
| 569 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 570 } |
| 571 return b; |
| 572 } |
| 573 |
| 574 U_NAMESPACE_END |
| 575 |
426 static Resource | 576 static Resource |
427 makeResourceFrom16(const ResourceData *pResData, int32_t res16) { | 577 makeResourceFrom16(const ResourceData *pResData, int32_t res16) { |
428 if(res16<pResData->poolStringIndex16Limit) { | 578 if(res16<pResData->poolStringIndex16Limit) { |
429 // Pool string, nothing to do. | 579 // Pool string, nothing to do. |
430 } else { | 580 } else { |
431 // Local string, adjust the 16-bit offset to a regular one, | 581 // Local string, adjust the 16-bit offset to a regular one, |
432 // with a larger pool string index limit. | 582 // with a larger pool string index limit. |
433 res16=res16-pResData->poolStringIndex16Limit+pResData->poolStringIndexLi
mit; | 583 res16=res16-pResData->poolStringIndex16Limit+pResData->poolStringIndexLi
mit; |
434 } | 584 } |
435 return URES_MAKE_RESOURCE(URES_STRING_V2, res16); | 585 return URES_MAKE_RESOURCE(URES_STRING_V2, res16); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 return RES_BOGUS; | 684 return RES_BOGUS; |
535 } | 685 } |
536 | 686 |
537 U_CAPI Resource U_EXPORT2 | 687 U_CAPI Resource U_EXPORT2 |
538 res_getResource(const ResourceData *pResData, const char *key) { | 688 res_getResource(const ResourceData *pResData, const char *key) { |
539 const char *realKey=key; | 689 const char *realKey=key; |
540 int32_t idx; | 690 int32_t idx; |
541 return res_getTableItemByKey(pResData, pResData->rootRes, &idx, &realKey); | 691 return res_getTableItemByKey(pResData, pResData->rootRes, &idx, &realKey); |
542 } | 692 } |
543 | 693 |
| 694 // TODO: Ported from Java, but enumerating at this low level may prevent us |
| 695 // from doing necessary things, like resolving aliases, |
| 696 // which need access to higher-level UResourceBundle code. |
| 697 // Consider porting the low-level Container/Array/Table classes from Java, |
| 698 // with getters for keys and values, |
| 699 // and doing the enumeration in the higher-level code on top of those accessors. |
| 700 U_CFUNC void |
| 701 ures_getAllTableItems(const ResourceData *pResData, Resource table, |
| 702 icu::ResourceDataValue &value, icu::ResourceTableSink &sin
k, |
| 703 UErrorCode &errorCode) { |
| 704 if(U_FAILURE(errorCode)) { return; } |
| 705 const uint16_t *keys16 = NULL; |
| 706 const int32_t *keys32 = NULL; |
| 707 const uint16_t *items16 = NULL; |
| 708 const Resource *items32 = NULL; |
| 709 uint32_t offset = RES_GET_OFFSET(table); |
| 710 int32_t length = 0; |
| 711 switch(RES_GET_TYPE(table)) { |
| 712 case URES_TABLE: { |
| 713 if (offset != 0) { /* empty if offset==0 */ |
| 714 keys16 = (const uint16_t *)(pResData->pRoot+offset); |
| 715 length = *keys16++; |
| 716 items32 = (const Resource *)(keys16+length+(~length&1)); |
| 717 } |
| 718 break; |
| 719 } |
| 720 case URES_TABLE16: { |
| 721 keys16 = pResData->p16BitUnits+offset; |
| 722 length = *keys16++; |
| 723 items16 = keys16 + length; |
| 724 break; |
| 725 } |
| 726 case URES_TABLE32: { |
| 727 if (offset != 0) { /* empty if offset==0 */ |
| 728 keys32 = pResData->pRoot+offset; |
| 729 length = *keys32++; |
| 730 items32 = (const Resource *)keys32 + length; |
| 731 } |
| 732 break; |
| 733 } |
| 734 default: |
| 735 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 736 return; |
| 737 } |
| 738 |
| 739 for (int32_t i = 0; i < length; ++i) { |
| 740 const char *key; |
| 741 if (keys16 != NULL) { |
| 742 key=RES_GET_KEY16(pResData, keys16[i]); |
| 743 } else { |
| 744 key=RES_GET_KEY32(pResData, keys32[i]); |
| 745 } |
| 746 Resource res; |
| 747 if (items16 != NULL) { |
| 748 res = makeResourceFrom16(pResData, items16[i]); |
| 749 } else { |
| 750 res = items32[i]; |
| 751 } |
| 752 int32_t type = RES_GET_TYPE(res); |
| 753 if (URES_IS_ARRAY(type)) { |
| 754 int32_t numItems = getArrayLength(pResData, res); |
| 755 icu::ResourceArraySink *subSink = sink.getOrCreateArraySink(key, num
Items, errorCode); |
| 756 if (subSink != NULL) { |
| 757 ures_getAllArrayItems(pResData, res, value, *subSink, errorCode)
; |
| 758 } |
| 759 } else if (URES_IS_TABLE(type)) { |
| 760 int32_t numItems = getTableLength(pResData, res); |
| 761 icu::ResourceTableSink *subSink = sink.getOrCreateTableSink(key, num
Items, errorCode); |
| 762 if (subSink != NULL) { |
| 763 ures_getAllTableItems(pResData, res, value, *subSink, errorCode)
; |
| 764 } |
| 765 /* TODO: settle on how to deal with aliases, port to Java |
| 766 } else if (type == URES_ALIAS) { |
| 767 // aliases not handled in resource enumeration |
| 768 errorCode = U_UNSUPPORTED_ERROR; |
| 769 return; */ |
| 770 } else if (isNoInheritanceMarker(pResData, res)) { |
| 771 sink.putNoFallback(key, errorCode); |
| 772 } else { |
| 773 value.setResource(res); |
| 774 sink.put(key, value, errorCode); |
| 775 } |
| 776 if(U_FAILURE(errorCode)) { return; } |
| 777 } |
| 778 sink.leave(errorCode); |
| 779 } |
| 780 |
544 U_CAPI Resource U_EXPORT2 | 781 U_CAPI Resource U_EXPORT2 |
545 res_getArrayItem(const ResourceData *pResData, Resource array, int32_t indexR) { | 782 res_getArrayItem(const ResourceData *pResData, Resource array, int32_t indexR) { |
546 uint32_t offset=RES_GET_OFFSET(array); | 783 uint32_t offset=RES_GET_OFFSET(array); |
547 U_ASSERT(indexR>=0); /* to ensure the index is not negative */ | 784 U_ASSERT(indexR>=0); /* to ensure the index is not negative */ |
548 switch(RES_GET_TYPE(array)) { | 785 switch(RES_GET_TYPE(array)) { |
549 case URES_ARRAY: { | 786 case URES_ARRAY: { |
550 if (offset!=0) { /* empty if offset==0 */ | 787 if (offset!=0) { /* empty if offset==0 */ |
551 const int32_t *p= pResData->pRoot+offset; | 788 const int32_t *p= pResData->pRoot+offset; |
552 if(indexR<*p) { | 789 if(indexR<*p) { |
553 return (Resource)p[1+indexR]; | 790 return (Resource)p[1+indexR]; |
554 } | 791 } |
555 } | 792 } |
556 break; | 793 break; |
557 } | 794 } |
558 case URES_ARRAY16: { | 795 case URES_ARRAY16: { |
559 const uint16_t *p=pResData->p16BitUnits+offset; | 796 const uint16_t *p=pResData->p16BitUnits+offset; |
560 if(indexR<*p) { | 797 if(indexR<*p) { |
561 return makeResourceFrom16(pResData, p[1+indexR]); | 798 return makeResourceFrom16(pResData, p[1+indexR]); |
562 } | 799 } |
563 break; | 800 break; |
564 } | 801 } |
565 default: | 802 default: |
566 break; | 803 break; |
567 } | 804 } |
568 return RES_BOGUS; | 805 return RES_BOGUS; |
569 } | 806 } |
570 | 807 |
| 808 U_CFUNC void |
| 809 ures_getAllArrayItems(const ResourceData *pResData, Resource array, |
| 810 icu::ResourceDataValue &value, icu::ResourceArraySink &sin
k, |
| 811 UErrorCode &errorCode) { |
| 812 if(U_FAILURE(errorCode)) { return; } |
| 813 const uint16_t *items16 = NULL; |
| 814 const Resource *items32 = NULL; |
| 815 uint32_t offset=RES_GET_OFFSET(array); |
| 816 int32_t length = 0; |
| 817 switch(RES_GET_TYPE(array)) { |
| 818 case URES_ARRAY: { |
| 819 if (offset!=0) { /* empty if offset==0 */ |
| 820 items32 = (const Resource *)pResData->pRoot+offset; |
| 821 length = *items32++; |
| 822 } |
| 823 break; |
| 824 } |
| 825 case URES_ARRAY16: { |
| 826 items16 = pResData->p16BitUnits+offset; |
| 827 length = *items16++; |
| 828 break; |
| 829 } |
| 830 default: |
| 831 errorCode = U_RESOURCE_TYPE_MISMATCH; |
| 832 return; |
| 833 } |
| 834 |
| 835 for (int32_t i = 0; i < length; ++i) { |
| 836 Resource res; |
| 837 if (items16 != NULL) { |
| 838 res = makeResourceFrom16(pResData, items16[i]); |
| 839 } else { |
| 840 res = items32[i]; |
| 841 } |
| 842 int32_t type = RES_GET_TYPE(res); |
| 843 if (URES_IS_ARRAY(type)) { |
| 844 int32_t numItems = getArrayLength(pResData, res); |
| 845 icu::ResourceArraySink *subSink = sink.getOrCreateArraySink(i, numIt
ems, errorCode); |
| 846 if (subSink != NULL) { |
| 847 ures_getAllArrayItems(pResData, res, value, *subSink, errorCode)
; |
| 848 } |
| 849 } else if (URES_IS_TABLE(type)) { |
| 850 int32_t numItems = getTableLength(pResData, res); |
| 851 icu::ResourceTableSink *subSink = sink.getOrCreateTableSink(i, numIt
ems, errorCode); |
| 852 if (subSink != NULL) { |
| 853 ures_getAllTableItems(pResData, res, value, *subSink, errorCode)
; |
| 854 } |
| 855 /* TODO: settle on how to deal with aliases, port to Java |
| 856 } else if (type == URES_ALIAS) { |
| 857 // aliases not handled in resource enumeration |
| 858 errorCode = U_UNSUPPORTED_ERROR; |
| 859 return; */ |
| 860 } else { |
| 861 value.setResource(res); |
| 862 sink.put(i, value, errorCode); |
| 863 } |
| 864 if(U_FAILURE(errorCode)) { return; } |
| 865 } |
| 866 sink.leave(errorCode); |
| 867 } |
| 868 |
571 U_CFUNC Resource | 869 U_CFUNC Resource |
572 res_findResource(const ResourceData *pResData, Resource r, char** path, const ch
ar** key) { | 870 res_findResource(const ResourceData *pResData, Resource r, char** path, const ch
ar** key) { |
573 /* we pass in a path. CollationElements/Sequence or zoneStrings/3/2 etc. | |
574 * iterates over a path and stops when a scalar resource is found. This | |
575 * CAN be an alias. Path gets set to the part that has not yet been processed.
| |
576 */ | |
577 | |
578 char *pathP = *path, *nextSepP = *path; | 871 char *pathP = *path, *nextSepP = *path; |
579 char *closeIndex = NULL; | 872 char *closeIndex = NULL; |
580 Resource t1 = r; | 873 Resource t1 = r; |
581 Resource t2; | 874 Resource t2; |
582 int32_t indexR = 0; | 875 int32_t indexR = 0; |
583 UResType type = (UResType)RES_GET_TYPE(t1); | 876 UResType type = (UResType)RES_GET_TYPE(t1); |
584 | 877 |
585 /* if you come in with an empty path, you'll be getting back the same resource
*/ | 878 /* if you come in with an empty path, you'll be getting back the same resource
*/ |
586 if(!uprv_strlen(pathP)) { | 879 if(!uprv_strlen(pathP)) { |
587 return r; | 880 return r; |
588 } | 881 } |
589 | 882 |
590 /* one needs to have an aggregate resource in order to search in it */ | 883 /* one needs to have an aggregate resource in order to search in it */ |
591 if(!URES_IS_CONTAINER(type)) { | 884 if(!URES_IS_CONTAINER(type)) { |
592 return RES_BOGUS; | 885 return RES_BOGUS; |
593 } | 886 } |
594 | 887 |
595 while(nextSepP && *pathP && t1 != RES_BOGUS && URES_IS_CONTAINER(type)) { | 888 while(nextSepP && *pathP && t1 != RES_BOGUS && URES_IS_CONTAINER(type)) { |
596 /* Iteration stops if: the path has been consumed, we found a non-existing | 889 /* Iteration stops if: the path has been consumed, we found a non-existing |
597 * resource (t1 == RES_BOGUS) or we found a scalar resource (including alias
) | 890 * resource (t1 == RES_BOGUS) or we found a scalar resource (including alias
) |
598 */ | 891 */ |
599 nextSepP = uprv_strchr(pathP, RES_PATH_SEPARATOR); | 892 nextSepP = uprv_strchr(pathP, RES_PATH_SEPARATOR); |
600 /* if there are more separators, terminate string | 893 /* if there are more separators, terminate string |
601 * and set path to the remaining part of the string | 894 * and set path to the remaining part of the string |
602 */ | 895 */ |
603 if(nextSepP != NULL) { | 896 if(nextSepP != NULL) { |
| 897 if(nextSepP == pathP) { |
| 898 // Empty key string. |
| 899 return RES_BOGUS; |
| 900 } |
604 *nextSepP = 0; /* overwrite the separator with a NUL to terminate the key
*/ | 901 *nextSepP = 0; /* overwrite the separator with a NUL to terminate the key
*/ |
605 *path = nextSepP+1; | 902 *path = nextSepP+1; |
606 } else { | 903 } else { |
607 *path = uprv_strchr(pathP, 0); | 904 *path = uprv_strchr(pathP, 0); |
608 } | 905 } |
609 | 906 |
610 /* if the resource is a table */ | 907 /* if the resource is a table */ |
611 /* try the key based access */ | 908 /* try the key based access */ |
612 if(URES_IS_TABLE(type)) { | 909 if(URES_IS_TABLE(type)) { |
613 *key = pathP; | 910 *key = pathP; |
614 t2 = res_getTableItemByKey(pResData, t1, &indexR, key); | 911 t2 = res_getTableItemByKey(pResData, t1, &indexR, key); |
615 if(t2 == RES_BOGUS) { | 912 if(t2 == RES_BOGUS) { |
616 /* if we fail to get the resource by key, maybe we got an index */ | 913 /* if we fail to get the resource by key, maybe we got an index */ |
617 indexR = uprv_strtol(pathP, &closeIndex, 10); | 914 indexR = uprv_strtol(pathP, &closeIndex, 10); |
618 if(closeIndex != pathP) { | 915 if(*closeIndex == 0) { |
619 /* if we indeed have an index, try to get the item by index */ | 916 /* if we indeed have an index, try to get the item by index */ |
620 t2 = res_getTableItemByIndex(pResData, t1, indexR, key); | 917 t2 = res_getTableItemByIndex(pResData, t1, indexR, key); |
621 } | 918 } |
622 } | 919 } |
623 } else if(URES_IS_ARRAY(type)) { | 920 } else if(URES_IS_ARRAY(type)) { |
624 indexR = uprv_strtol(pathP, &closeIndex, 10); | 921 indexR = uprv_strtol(pathP, &closeIndex, 10); |
625 if(closeIndex != pathP) { | 922 if(*closeIndex == 0) { |
626 t2 = res_getArrayItem(pResData, t1, indexR); | 923 t2 = res_getArrayItem(pResData, t1, indexR); |
627 } else { | 924 } else { |
628 t2 = RES_BOGUS; /* have an array, but don't have a valid index */ | 925 t2 = RES_BOGUS; /* have an array, but don't have a valid index */ |
629 } | 926 } |
630 *key = NULL; | 927 *key = NULL; |
631 } else { /* can't do much here, except setting t2 to bogus */ | 928 } else { /* can't do much here, except setting t2 to bogus */ |
632 t2 = RES_BOGUS; | 929 t2 = RES_BOGUS; |
633 } | 930 } |
634 t1 = t2; | 931 t1 = t2; |
635 type = (UResType)RES_GET_TYPE(t1); | 932 type = (UResType)RES_GET_TYPE(t1); |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 /* | 1384 /* |
1088 * We need one bit per 4 resource bundle bytes so that we can track | 1385 * We need one bit per 4 resource bundle bytes so that we can track |
1089 * every possible Resource for whether we have swapped it already. | 1386 * every possible Resource for whether we have swapped it already. |
1090 * Multiple Resource words can refer to the same bundle offsets | 1387 * Multiple Resource words can refer to the same bundle offsets |
1091 * for sharing identical values. | 1388 * for sharing identical values. |
1092 * We could optimize this by allocating only for locations above | 1389 * We could optimize this by allocating only for locations above |
1093 * where Resource values are stored (above keys & strings). | 1390 * where Resource values are stored (above keys & strings). |
1094 */ | 1391 */ |
1095 resFlagsLength=(length+31)>>5; /* number of bytes needed */ | 1392 resFlagsLength=(length+31)>>5; /* number of bytes needed */ |
1096 resFlagsLength=(resFlagsLength+3)&~3; /* multiple of 4 bytes for uint3
2_t */ | 1393 resFlagsLength=(resFlagsLength+3)&~3; /* multiple of 4 bytes for uint3
2_t */ |
1097 if(resFlagsLength<=sizeof(stackResFlags)) { | 1394 if(resFlagsLength<=(int32_t)sizeof(stackResFlags)) { |
1098 tempTable.resFlags=stackResFlags; | 1395 tempTable.resFlags=stackResFlags; |
1099 } else { | 1396 } else { |
1100 tempTable.resFlags=(uint32_t *)uprv_malloc(resFlagsLength); | 1397 tempTable.resFlags=(uint32_t *)uprv_malloc(resFlagsLength); |
1101 if(tempTable.resFlags==NULL) { | 1398 if(tempTable.resFlags==NULL) { |
1102 udata_printError(ds, "ures_swap(): unable to allocate memory for
tracking resources\n"); | 1399 udata_printError(ds, "ures_swap(): unable to allocate memory for
tracking resources\n"); |
1103 *pErrorCode=U_MEMORY_ALLOCATION_ERROR; | 1400 *pErrorCode=U_MEMORY_ALLOCATION_ERROR; |
1104 return 0; | 1401 return 0; |
1105 } | 1402 } |
1106 } | 1403 } |
1107 uprv_memset(tempTable.resFlags, 0, resFlagsLength); | 1404 uprv_memset(tempTable.resFlags, 0, resFlagsLength); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 if(tempTable.resFlags!=stackResFlags) { | 1457 if(tempTable.resFlags!=stackResFlags) { |
1161 uprv_free(tempTable.resFlags); | 1458 uprv_free(tempTable.resFlags); |
1162 } | 1459 } |
1163 | 1460 |
1164 /* swap the root resource and indexes */ | 1461 /* swap the root resource and indexes */ |
1165 ds->swapArray32(ds, inBundle, keysBottom*4, outBundle, pErrorCode); | 1462 ds->swapArray32(ds, inBundle, keysBottom*4, outBundle, pErrorCode); |
1166 } | 1463 } |
1167 | 1464 |
1168 return headerSize+4*top; | 1465 return headerSize+4*top; |
1169 } | 1466 } |
OLD | NEW |