static void res_init(ResourceData *pResData, UVersionInfo formatVersion, const void *inBytes, int32_t length, UErrorCode *errorCode) { UResType rootType; /* get the root resource */ pResData->pRoot=(const int32_t *)inBytes; pResData->rootRes=(Resource)*pResData->pRoot; pResData->p16BitUnits=&gEmpty16; /* formatVersion 1.1 must have a root item and at least 5 indexes */ if(length>=0 && (length/4)<((formatVersion[0]==1 && formatVersion[1]==0) ? 1 : 1+5)) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } /* currently, we accept only resources that have a Table as their roots */ rootType=(UResType)RES_GET_TYPE(pResData->rootRes); if(!URES_IS_TABLE(rootType)) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } if(formatVersion[0]==1 && formatVersion[1]==0) { pResData->localKeyLimit=0x10000; /* greater than any 16-bit key string offset */ } else { /* bundles with formatVersion 1.1 and later contain an indexes[] array */ const int32_t *indexes=pResData->pRoot+1; int32_t indexLength=indexes[URES_INDEX_LENGTH]&0xff; if(indexLength<=URES_INDEX_MAX_TABLE_LENGTH) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } if( length>=0 && (length<((1+indexLength)<<2) || length<(indexes[URES_INDEX_BUNDLE_TOP]<<2)) ) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } if(indexes[URES_INDEX_KEYS_TOP]>(1+indexLength)) { pResData->localKeyLimit=indexes[URES_INDEX_KEYS_TOP]<<2; } 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); } if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=URES_INDEX_POOL_CHECKSUM) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } if( indexLength>URES_INDEX_16BIT_TOP && indexes[URES_INDEX_16BIT_TOP]>indexes[URES_INDEX_KEYS_TOP] ) { pResData->p16BitUnits=(const uint16_t *)(pResData->pRoot+indexes[URES_INDEX_KEYS_TOP]); } } if(formatVersion[0]==1 || U_CHARSET_FAMILY==U_ASCII_FAMILY) { /* * formatVersion 1: compare key strings in native-charset order * formatVersion 2 and up: compare key strings in ASCII order */ pResData->useNativeStrcmp=TRUE; } }
U_CFUNC Resource res_findResource(const ResourceData *pResData, Resource r, char** path, const char** key) { /* we pass in a path. CollationElements/Sequence or zoneStrings/3/2 etc. * iterates over a path and stops when a scalar resource is found. This * CAN be an alias. Path gets set to the part that has not yet been processed. */ char *pathP = *path, *nextSepP = *path; char *closeIndex = NULL; Resource t1 = r; Resource t2; int32_t indexR = 0; UResType type = (UResType)RES_GET_TYPE(t1); /* if you come in with an empty path, you'll be getting back the same resource */ if(!uprv_strlen(pathP)) { return r; } /* one needs to have an aggregate resource in order to search in it */ if(!URES_IS_CONTAINER(type)) { return RES_BOGUS; } while(nextSepP && *pathP && t1 != RES_BOGUS && URES_IS_CONTAINER(type)) { /* Iteration stops if: the path has been consumed, we found a non-existing * resource (t1 == RES_BOGUS) or we found a scalar resource (including alias) */ nextSepP = uprv_strchr(pathP, RES_PATH_SEPARATOR); /* if there are more separators, terminate string * and set path to the remaining part of the string */ if(nextSepP != NULL) { *nextSepP = 0; /* overwrite the separator with a NUL to terminate the key */ *path = nextSepP+1; } else { *path = uprv_strchr(pathP, 0); } /* if the resource is a table */ /* try the key based access */ if(URES_IS_TABLE(type)) { *key = pathP; t2 = res_getTableItemByKey(pResData, t1, &indexR, key); if(t2 == RES_BOGUS) { /* if we fail to get the resource by key, maybe we got an index */ indexR = uprv_strtol(pathP, &closeIndex, 10); if(closeIndex != pathP) { /* if we indeed have an index, try to get the item by index */ t2 = res_getTableItemByIndex(pResData, t1, indexR, key); } } } else if(URES_IS_ARRAY(type)) { indexR = uprv_strtol(pathP, &closeIndex, 10); if(closeIndex != pathP) { t2 = res_getArrayItem(pResData, t1, indexR); } else { t2 = RES_BOGUS; /* have an array, but don't have a valid index */ } *key = NULL; } else { /* can't do much here, except setting t2 to bogus */ t2 = RES_BOGUS; } t1 = t2; type = (UResType)RES_GET_TYPE(t1); /* position pathP to next resource key/index */ pathP = *path; } return t1; }
static void res_init(ResourceData *pResData, UVersionInfo formatVersion, const void *inBytes, int32_t length, UErrorCode *errorCode) { UResType rootType; /* get the root resource */ pResData->pRoot=(const int32_t *)inBytes; pResData->rootRes=(Resource)*pResData->pRoot; pResData->p16BitUnits=&gEmpty16; /* formatVersion 1.1 must have a root item and at least 5 indexes */ if(length>=0 && (length/4)<((formatVersion[0]==1 && formatVersion[1]==0) ? 1 : 1+5)) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } /* currently, we accept only resources that have a Table as their roots */ rootType=(UResType)RES_GET_TYPE(pResData->rootRes); if(!URES_IS_TABLE(rootType)) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } if(formatVersion[0]==1 && formatVersion[1]==0) { pResData->localKeyLimit=0x10000; /* greater than any 16-bit key string offset */ } else { /* bundles with formatVersion 1.1 and later contain an indexes[] array */ const int32_t *indexes=pResData->pRoot+1; int32_t indexLength=indexes[URES_INDEX_LENGTH]&0xff; if(indexLength<=URES_INDEX_MAX_TABLE_LENGTH) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } if( length>=0 && (length<((1+indexLength)<<2) || length<(indexes[URES_INDEX_BUNDLE_TOP]<<2)) ) { *errorCode=U_INVALID_FORMAT_ERROR; res_unload(pResData); return; } 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); }