Index: source/common/uresdata.c |
diff --git a/source/common/uresdata.c b/source/common/uresdata.c |
index a007377762e5d96c10e25c2b60d9e85e1d88498e..53887fbfdc3174584fded6440d5bd932383584ee 100644 |
--- a/source/common/uresdata.c |
+++ b/source/common/uresdata.c |
@@ -1,6 +1,6 @@ |
/* |
******************************************************************************* |
-* Copyright (C) 1999-2014, International Business Machines Corporation |
+* Copyright (C) 1999-2015, International Business Machines Corporation |
* and others. All Rights Reserved. |
******************************************************************************* |
* file name: uresdata.c |
@@ -145,7 +145,7 @@ isAcceptable(void *context, |
pInfo->dataFormat[1]==0x65 && |
pInfo->dataFormat[2]==0x73 && |
pInfo->dataFormat[3]==0x42 && |
- (pInfo->formatVersion[0]==1 || pInfo->formatVersion[0]==2)); |
+ (1<=pInfo->formatVersion[0] && pInfo->formatVersion[0]<=3)); |
} |
/* semi-public functions ---------------------------------------------------- */ |
@@ -198,11 +198,20 @@ res_init(ResourceData *pResData, |
if(indexes[URES_INDEX_KEYS_TOP]>(1+indexLength)) { |
pResData->localKeyLimit=indexes[URES_INDEX_KEYS_TOP]<<2; |
} |
+ if(formatVersion[0]>=3) { |
+ // In formatVersion 1, the indexLength took up this whole int. |
+ // In version 2, bits 31..8 were reserved and always 0. |
+ // In version 3, they contain bits 23..0 of the poolStringIndexLimit. |
+ // Bits 27..24 are in indexes[URES_INDEX_ATTRIBUTES] bits 15..12. |
+ pResData->poolStringIndexLimit=(int32_t)((uint32_t)indexes[URES_INDEX_LENGTH]>>8); |
+ } |
if(indexLength>URES_INDEX_ATTRIBUTES) { |
int32_t att=indexes[URES_INDEX_ATTRIBUTES]; |
pResData->noFallback=(UBool)(att&URES_ATT_NO_FALLBACK); |
pResData->isPoolBundle=(UBool)((att&URES_ATT_IS_POOL_BUNDLE)!=0); |
pResData->usesPoolBundle=(UBool)((att&URES_ATT_USES_POOL_BUNDLE)!=0); |
+ pResData->poolStringIndexLimit|=(att&0xf000)<<12; // bits 15..12 -> 27..24 |
+ pResData->poolStringIndex16Limit=(int32_t)((uint32_t)att>>16); |
} |
if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=URES_INDEX_POOL_CHECKSUM) { |
*errorCode=U_INVALID_FORMAT_ERROR; |
@@ -301,7 +310,11 @@ res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) { |
int32_t length; |
if(RES_GET_TYPE(res)==URES_STRING_V2) { |
int32_t first; |
- p=(const UChar *)(pResData->p16BitUnits+offset); |
+ if(offset<pResData->poolStringIndexLimit) { |
+ p=(const UChar *)pResData->poolBundleStrings+offset; |
+ } else { |
+ p=(const UChar *)pResData->p16BitUnits+(offset-pResData->poolStringIndexLimit); |
+ } |
first=*p; |
if(!U16_IS_TRAIL(first)) { |
length=u_strlen(p); |
@@ -410,6 +423,18 @@ res_countArrayItems(const ResourceData *pResData, Resource res) { |
} |
} |
+static Resource |
+makeResourceFrom16(const ResourceData *pResData, int32_t res16) { |
+ if(res16<pResData->poolStringIndex16Limit) { |
+ // Pool string, nothing to do. |
+ } else { |
+ // Local string, adjust the 16-bit offset to a regular one, |
+ // with a larger pool string index limit. |
+ res16=res16-pResData->poolStringIndex16Limit+pResData->poolStringIndexLimit; |
+ } |
+ return URES_MAKE_RESOURCE(URES_STRING_V2, res16); |
+} |
+ |
U_CAPI Resource U_EXPORT2 |
res_getTableItemByKey(const ResourceData *pResData, Resource table, |
int32_t *indexR, const char **key) { |
@@ -437,7 +462,7 @@ res_getTableItemByKey(const ResourceData *pResData, Resource table, |
length=*p++; |
*indexR=idx=_res_findTableItem(pResData, p, length, *key, key); |
if(idx>=0) { |
- return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+idx]); |
+ return makeResourceFrom16(pResData, p[length+idx]); |
} |
break; |
} |
@@ -486,7 +511,7 @@ res_getTableItemByIndex(const ResourceData *pResData, Resource table, |
if(key!=NULL) { |
*key=RES_GET_KEY16(pResData, p[indexR]); |
} |
- return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+indexR]); |
+ return makeResourceFrom16(pResData, p[length+indexR]); |
} |
break; |
} |
@@ -533,7 +558,7 @@ res_getArrayItem(const ResourceData *pResData, Resource array, int32_t indexR) { |
case URES_ARRAY16: { |
const uint16_t *p=pResData->p16BitUnits+offset; |
if(indexR<*p) { |
- return URES_MAKE_RESOURCE(URES_STRING_V2, p[1+indexR]); |
+ return makeResourceFrom16(pResData, p[1+indexR]); |
} |
break; |
} |
@@ -990,8 +1015,9 @@ ures_swap(const UDataSwapper *ds, |
pInfo->dataFormat[1]==0x65 && |
pInfo->dataFormat[2]==0x73 && |
pInfo->dataFormat[3]==0x42 && |
- ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[1]>=1) || /* formatVersion 1.1+ or 2.x */ |
- pInfo->formatVersion[0]==2) |
+ /* formatVersion 1.1+ or 2.x or 3.x */ |
+ ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[1]>=1) || |
+ pInfo->formatVersion[0]==2 || pInfo->formatVersion[0]==3) |
)) { |
udata_printError(ds, "ures_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not a resource bundle\n", |
pInfo->dataFormat[0], pInfo->dataFormat[1], |