OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * Copyright (C) 1999-2014, 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.c |
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: |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 uprv_memcpy(context, pInfo->formatVersion, 4); | 138 uprv_memcpy(context, pInfo->formatVersion, 4); |
139 return (UBool)( | 139 return (UBool)( |
140 pInfo->size>=20 && | 140 pInfo->size>=20 && |
141 pInfo->isBigEndian==U_IS_BIG_ENDIAN && | 141 pInfo->isBigEndian==U_IS_BIG_ENDIAN && |
142 pInfo->charsetFamily==U_CHARSET_FAMILY && | 142 pInfo->charsetFamily==U_CHARSET_FAMILY && |
143 pInfo->sizeofUChar==U_SIZEOF_UCHAR && | 143 pInfo->sizeofUChar==U_SIZEOF_UCHAR && |
144 pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ | 144 pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ |
145 pInfo->dataFormat[1]==0x65 && | 145 pInfo->dataFormat[1]==0x65 && |
146 pInfo->dataFormat[2]==0x73 && | 146 pInfo->dataFormat[2]==0x73 && |
147 pInfo->dataFormat[3]==0x42 && | 147 pInfo->dataFormat[3]==0x42 && |
148 (pInfo->formatVersion[0]==1 || pInfo->formatVersion[0]==2)); | 148 (1<=pInfo->formatVersion[0] && pInfo->formatVersion[0]<=3)); |
149 } | 149 } |
150 | 150 |
151 /* semi-public functions ---------------------------------------------------- */ | 151 /* semi-public functions ---------------------------------------------------- */ |
152 | 152 |
153 static void | 153 static void |
154 res_init(ResourceData *pResData, | 154 res_init(ResourceData *pResData, |
155 UVersionInfo formatVersion, const void *inBytes, int32_t length, | 155 UVersionInfo formatVersion, const void *inBytes, int32_t length, |
156 UErrorCode *errorCode) { | 156 UErrorCode *errorCode) { |
157 UResType rootType; | 157 UResType rootType; |
158 | 158 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 (length<((1+indexLength)<<2) || | 191 (length<((1+indexLength)<<2) || |
192 length<(indexes[URES_INDEX_BUNDLE_TOP]<<2)) | 192 length<(indexes[URES_INDEX_BUNDLE_TOP]<<2)) |
193 ) { | 193 ) { |
194 *errorCode=U_INVALID_FORMAT_ERROR; | 194 *errorCode=U_INVALID_FORMAT_ERROR; |
195 res_unload(pResData); | 195 res_unload(pResData); |
196 return; | 196 return; |
197 } | 197 } |
198 if(indexes[URES_INDEX_KEYS_TOP]>(1+indexLength)) { | 198 if(indexes[URES_INDEX_KEYS_TOP]>(1+indexLength)) { |
199 pResData->localKeyLimit=indexes[URES_INDEX_KEYS_TOP]<<2; | 199 pResData->localKeyLimit=indexes[URES_INDEX_KEYS_TOP]<<2; |
200 } | 200 } |
| 201 if(formatVersion[0]>=3) { |
| 202 // In formatVersion 1, the indexLength took up this whole int. |
| 203 // In version 2, bits 31..8 were reserved and always 0. |
| 204 // In version 3, they contain bits 23..0 of the poolStringIndexLimit
. |
| 205 // Bits 27..24 are in indexes[URES_INDEX_ATTRIBUTES] bits 15..12. |
| 206 pResData->poolStringIndexLimit=(int32_t)((uint32_t)indexes[URES_INDE
X_LENGTH]>>8); |
| 207 } |
201 if(indexLength>URES_INDEX_ATTRIBUTES) { | 208 if(indexLength>URES_INDEX_ATTRIBUTES) { |
202 int32_t att=indexes[URES_INDEX_ATTRIBUTES]; | 209 int32_t att=indexes[URES_INDEX_ATTRIBUTES]; |
203 pResData->noFallback=(UBool)(att&URES_ATT_NO_FALLBACK); | 210 pResData->noFallback=(UBool)(att&URES_ATT_NO_FALLBACK); |
204 pResData->isPoolBundle=(UBool)((att&URES_ATT_IS_POOL_BUNDLE)!=0); | 211 pResData->isPoolBundle=(UBool)((att&URES_ATT_IS_POOL_BUNDLE)!=0); |
205 pResData->usesPoolBundle=(UBool)((att&URES_ATT_USES_POOL_BUNDLE)!=0)
; | 212 pResData->usesPoolBundle=(UBool)((att&URES_ATT_USES_POOL_BUNDLE)!=0)
; |
| 213 pResData->poolStringIndexLimit|=(att&0xf000)<<12; // bits 15..12 ->
27..24 |
| 214 pResData->poolStringIndex16Limit=(int32_t)((uint32_t)att>>16); |
206 } | 215 } |
207 if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=
URES_INDEX_POOL_CHECKSUM) { | 216 if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=
URES_INDEX_POOL_CHECKSUM) { |
208 *errorCode=U_INVALID_FORMAT_ERROR; | 217 *errorCode=U_INVALID_FORMAT_ERROR; |
209 res_unload(pResData); | 218 res_unload(pResData); |
210 return; | 219 return; |
211 } | 220 } |
212 if( indexLength>URES_INDEX_16BIT_TOP && | 221 if( indexLength>URES_INDEX_16BIT_TOP && |
213 indexes[URES_INDEX_16BIT_TOP]>indexes[URES_INDEX_KEYS_TOP] | 222 indexes[URES_INDEX_16BIT_TOP]>indexes[URES_INDEX_KEYS_TOP] |
214 ) { | 223 ) { |
215 pResData->p16BitUnits=(const uint16_t *)(pResData->pRoot+indexes[URE
S_INDEX_KEYS_TOP]); | 224 pResData->p16BitUnits=(const uint16_t *)(pResData->pRoot+indexes[URE
S_INDEX_KEYS_TOP]); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 return (UResType)gPublicTypes[RES_GET_TYPE(res)]; | 303 return (UResType)gPublicTypes[RES_GET_TYPE(res)]; |
295 } | 304 } |
296 | 305 |
297 U_CAPI const UChar * U_EXPORT2 | 306 U_CAPI const UChar * U_EXPORT2 |
298 res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { | 307 res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { |
299 const UChar *p; | 308 const UChar *p; |
300 uint32_t offset=RES_GET_OFFSET(res); | 309 uint32_t offset=RES_GET_OFFSET(res); |
301 int32_t length; | 310 int32_t length; |
302 if(RES_GET_TYPE(res)==URES_STRING_V2) { | 311 if(RES_GET_TYPE(res)==URES_STRING_V2) { |
303 int32_t first; | 312 int32_t first; |
304 p=(const UChar *)(pResData->p16BitUnits+offset); | 313 if(offset<pResData->poolStringIndexLimit) { |
| 314 p=(const UChar *)pResData->poolBundleStrings+offset; |
| 315 } else { |
| 316 p=(const UChar *)pResData->p16BitUnits+(offset-pResData->poolStringI
ndexLimit); |
| 317 } |
305 first=*p; | 318 first=*p; |
306 if(!U16_IS_TRAIL(first)) { | 319 if(!U16_IS_TRAIL(first)) { |
307 length=u_strlen(p); | 320 length=u_strlen(p); |
308 } else if(first<0xdfef) { | 321 } else if(first<0xdfef) { |
309 length=first&0x3ff; | 322 length=first&0x3ff; |
310 ++p; | 323 ++p; |
311 } else if(first<0xdfff) { | 324 } else if(first<0xdfff) { |
312 length=((first-0xdfef)<<16)|p[1]; | 325 length=((first-0xdfef)<<16)|p[1]; |
313 p+=2; | 326 p+=2; |
314 } else { | 327 } else { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 case URES_TABLE: | 416 case URES_TABLE: |
404 return offset==0 ? 0 : *((const uint16_t *)(pResData->pRoot+offset)); | 417 return offset==0 ? 0 : *((const uint16_t *)(pResData->pRoot+offset)); |
405 case URES_ARRAY16: | 418 case URES_ARRAY16: |
406 case URES_TABLE16: | 419 case URES_TABLE16: |
407 return pResData->p16BitUnits[offset]; | 420 return pResData->p16BitUnits[offset]; |
408 default: | 421 default: |
409 return 0; | 422 return 0; |
410 } | 423 } |
411 } | 424 } |
412 | 425 |
| 426 static Resource |
| 427 makeResourceFrom16(const ResourceData *pResData, int32_t res16) { |
| 428 if(res16<pResData->poolStringIndex16Limit) { |
| 429 // Pool string, nothing to do. |
| 430 } else { |
| 431 // Local string, adjust the 16-bit offset to a regular one, |
| 432 // with a larger pool string index limit. |
| 433 res16=res16-pResData->poolStringIndex16Limit+pResData->poolStringIndexLi
mit; |
| 434 } |
| 435 return URES_MAKE_RESOURCE(URES_STRING_V2, res16); |
| 436 } |
| 437 |
413 U_CAPI Resource U_EXPORT2 | 438 U_CAPI Resource U_EXPORT2 |
414 res_getTableItemByKey(const ResourceData *pResData, Resource table, | 439 res_getTableItemByKey(const ResourceData *pResData, Resource table, |
415 int32_t *indexR, const char **key) { | 440 int32_t *indexR, const char **key) { |
416 uint32_t offset=RES_GET_OFFSET(table); | 441 uint32_t offset=RES_GET_OFFSET(table); |
417 int32_t length; | 442 int32_t length; |
418 int32_t idx; | 443 int32_t idx; |
419 if(key == NULL || *key == NULL) { | 444 if(key == NULL || *key == NULL) { |
420 return RES_BOGUS; | 445 return RES_BOGUS; |
421 } | 446 } |
422 switch(RES_GET_TYPE(table)) { | 447 switch(RES_GET_TYPE(table)) { |
423 case URES_TABLE: { | 448 case URES_TABLE: { |
424 if (offset!=0) { /* empty if offset==0 */ | 449 if (offset!=0) { /* empty if offset==0 */ |
425 const uint16_t *p= (const uint16_t *)(pResData->pRoot+offset); | 450 const uint16_t *p= (const uint16_t *)(pResData->pRoot+offset); |
426 length=*p++; | 451 length=*p++; |
427 *indexR=idx=_res_findTableItem(pResData, p, length, *key, key); | 452 *indexR=idx=_res_findTableItem(pResData, p, length, *key, key); |
428 if(idx>=0) { | 453 if(idx>=0) { |
429 const Resource *p32=(const Resource *)(p+length+(~length&1)); | 454 const Resource *p32=(const Resource *)(p+length+(~length&1)); |
430 return p32[idx]; | 455 return p32[idx]; |
431 } | 456 } |
432 } | 457 } |
433 break; | 458 break; |
434 } | 459 } |
435 case URES_TABLE16: { | 460 case URES_TABLE16: { |
436 const uint16_t *p=pResData->p16BitUnits+offset; | 461 const uint16_t *p=pResData->p16BitUnits+offset; |
437 length=*p++; | 462 length=*p++; |
438 *indexR=idx=_res_findTableItem(pResData, p, length, *key, key); | 463 *indexR=idx=_res_findTableItem(pResData, p, length, *key, key); |
439 if(idx>=0) { | 464 if(idx>=0) { |
440 return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+idx]); | 465 return makeResourceFrom16(pResData, p[length+idx]); |
441 } | 466 } |
442 break; | 467 break; |
443 } | 468 } |
444 case URES_TABLE32: { | 469 case URES_TABLE32: { |
445 if (offset!=0) { /* empty if offset==0 */ | 470 if (offset!=0) { /* empty if offset==0 */ |
446 const int32_t *p= pResData->pRoot+offset; | 471 const int32_t *p= pResData->pRoot+offset; |
447 length=*p++; | 472 length=*p++; |
448 *indexR=idx=_res_findTable32Item(pResData, p, length, *key, key); | 473 *indexR=idx=_res_findTable32Item(pResData, p, length, *key, key); |
449 if(idx>=0) { | 474 if(idx>=0) { |
450 return (Resource)p[length+idx]; | 475 return (Resource)p[length+idx]; |
(...skipping 28 matching lines...) Expand all Loading... |
479 } | 504 } |
480 break; | 505 break; |
481 } | 506 } |
482 case URES_TABLE16: { | 507 case URES_TABLE16: { |
483 const uint16_t *p=pResData->p16BitUnits+offset; | 508 const uint16_t *p=pResData->p16BitUnits+offset; |
484 length=*p++; | 509 length=*p++; |
485 if(indexR<length) { | 510 if(indexR<length) { |
486 if(key!=NULL) { | 511 if(key!=NULL) { |
487 *key=RES_GET_KEY16(pResData, p[indexR]); | 512 *key=RES_GET_KEY16(pResData, p[indexR]); |
488 } | 513 } |
489 return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+indexR]); | 514 return makeResourceFrom16(pResData, p[length+indexR]); |
490 } | 515 } |
491 break; | 516 break; |
492 } | 517 } |
493 case URES_TABLE32: { | 518 case URES_TABLE32: { |
494 if (offset != 0) { /* empty if offset==0 */ | 519 if (offset != 0) { /* empty if offset==0 */ |
495 const int32_t *p= pResData->pRoot+offset; | 520 const int32_t *p= pResData->pRoot+offset; |
496 length=*p++; | 521 length=*p++; |
497 if(indexR<length) { | 522 if(indexR<length) { |
498 if(key!=NULL) { | 523 if(key!=NULL) { |
499 *key=RES_GET_KEY32(pResData, p[indexR]); | 524 *key=RES_GET_KEY32(pResData, p[indexR]); |
(...skipping 26 matching lines...) Expand all Loading... |
526 const int32_t *p= pResData->pRoot+offset; | 551 const int32_t *p= pResData->pRoot+offset; |
527 if(indexR<*p) { | 552 if(indexR<*p) { |
528 return (Resource)p[1+indexR]; | 553 return (Resource)p[1+indexR]; |
529 } | 554 } |
530 } | 555 } |
531 break; | 556 break; |
532 } | 557 } |
533 case URES_ARRAY16: { | 558 case URES_ARRAY16: { |
534 const uint16_t *p=pResData->p16BitUnits+offset; | 559 const uint16_t *p=pResData->p16BitUnits+offset; |
535 if(indexR<*p) { | 560 if(indexR<*p) { |
536 return URES_MAKE_RESOURCE(URES_STRING_V2, p[1+indexR]); | 561 return makeResourceFrom16(pResData, p[1+indexR]); |
537 } | 562 } |
538 break; | 563 break; |
539 } | 564 } |
540 default: | 565 default: |
541 break; | 566 break; |
542 } | 567 } |
543 return RES_BOGUS; | 568 return RES_BOGUS; |
544 } | 569 } |
545 | 570 |
546 U_CFUNC Resource | 571 U_CFUNC Resource |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 return 0; | 1008 return 0; |
984 } | 1009 } |
985 | 1010 |
986 /* check data format and format version */ | 1011 /* check data format and format version */ |
987 pInfo=(const UDataInfo *)((const char *)inData+4); | 1012 pInfo=(const UDataInfo *)((const char *)inData+4); |
988 if(!( | 1013 if(!( |
989 pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ | 1014 pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ |
990 pInfo->dataFormat[1]==0x65 && | 1015 pInfo->dataFormat[1]==0x65 && |
991 pInfo->dataFormat[2]==0x73 && | 1016 pInfo->dataFormat[2]==0x73 && |
992 pInfo->dataFormat[3]==0x42 && | 1017 pInfo->dataFormat[3]==0x42 && |
993 ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[1]>=1) || /* forma
tVersion 1.1+ or 2.x */ | 1018 /* formatVersion 1.1+ or 2.x or 3.x */ |
994 pInfo->formatVersion[0]==2) | 1019 ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[1]>=1) || |
| 1020 pInfo->formatVersion[0]==2 || pInfo->formatVersion[0]==3) |
995 )) { | 1021 )) { |
996 udata_printError(ds, "ures_swap(): data format %02x.%02x.%02x.%02x (form
at version %02x.%02x) is not a resource bundle\n", | 1022 udata_printError(ds, "ures_swap(): data format %02x.%02x.%02x.%02x (form
at version %02x.%02x) is not a resource bundle\n", |
997 pInfo->dataFormat[0], pInfo->dataFormat[1], | 1023 pInfo->dataFormat[0], pInfo->dataFormat[1], |
998 pInfo->dataFormat[2], pInfo->dataFormat[3], | 1024 pInfo->dataFormat[2], pInfo->dataFormat[3], |
999 pInfo->formatVersion[0], pInfo->formatVersion[1]); | 1025 pInfo->formatVersion[0], pInfo->formatVersion[1]); |
1000 *pErrorCode=U_UNSUPPORTED_ERROR; | 1026 *pErrorCode=U_UNSUPPORTED_ERROR; |
1001 return 0; | 1027 return 0; |
1002 } | 1028 } |
1003 tempTable.majorFormatVersion=pInfo->formatVersion[0]; | 1029 tempTable.majorFormatVersion=pInfo->formatVersion[0]; |
1004 | 1030 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 if(tempTable.resFlags!=stackResFlags) { | 1160 if(tempTable.resFlags!=stackResFlags) { |
1135 uprv_free(tempTable.resFlags); | 1161 uprv_free(tempTable.resFlags); |
1136 } | 1162 } |
1137 | 1163 |
1138 /* swap the root resource and indexes */ | 1164 /* swap the root resource and indexes */ |
1139 ds->swapArray32(ds, inBundle, keysBottom*4, outBundle, pErrorCode); | 1165 ds->swapArray32(ds, inBundle, keysBottom*4, outBundle, pErrorCode); |
1140 } | 1166 } |
1141 | 1167 |
1142 return headerSize+4*top; | 1168 return headerSize+4*top; |
1143 } | 1169 } |
OLD | NEW |