/* ******************************************************************************* * * * Copyright (C) 1999-2002, International Business Machines Corporation * * and others. All Rights Reserved. * * * ******************************************************************************* * file name: uresdata.c * encoding: US-ASCII * tab size: 8 (not used) * indentation:4 * * created on: 1999dec08 * created by: Markus W. Scherer * Modification History: * * Date Name Description * 06/20/2000 helena OS/400 port changes; mostly typecast. * 06/24/02 weiv Added support for resource sharing */ #include "unicode/utypes.h" #include "cstring.h" #include "unicode/udata.h" #include "uresdata.h" #include "uresimp.h" /* * Resource access helpers */ /* get a const char* pointer to the key with the keyOffset byte offset from pRoot */ #define RES_GET_KEY(pRoot, keyOffset) ((const char *)(pRoot)+(keyOffset)) #define URESDATA_ITEM_NOT_FOUND 0xFFFF /* * All the type-access functions assume that * the resource is of the expected type. */ /* * Array functions */ static Resource _res_getArrayItem(Resource *pRoot, Resource res, int32_t indexR) { int32_t *p=(int32_t *)RES_GET_POINTER(pRoot, res); if(indexR<*p) { return ((Resource *)(p))[1+indexR]; } else { return RES_BOGUS; /* indexR>itemCount */ } } /* * Table functions * * Important: the key offsets are 16-bit byte offsets from pRoot, * and the itemCount is one more 16-bit, too. * Thus, there are (count+1) uint16_t values. * In order to 4-align the Resource item values, there is a padding * word if count is even, i.e., there is exactly (~count&1) * 16-bit padding words. */ static const char * _res_getTableKey(const Resource *pRoot, const Resource res, uint16_t indexS) { uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res); if(indexS<*p) { return RES_GET_KEY(pRoot, p[indexS+1]); } else { return NULL; /* indexS>itemCount */ } } static Resource _res_getTableItem(const Resource *pRoot, const Resource res, uint16_t indexR) { uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res); uint16_t count=*p; if(indexRitemCount */ } } static Resource _res_findTableItem(const Resource *pRoot, const Resource res, const char *key) { uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res); uint16_t i, start, limit; limit=*p++; /* number of entries */ if(limit == 0) { /* this table is empty */ return RES_BOGUS; } /* do a binary search for the key */ start=0; while(startsize>=20 && pInfo->isBigEndian==U_IS_BIG_ENDIAN && pInfo->charsetFamily==U_CHARSET_FAMILY && pInfo->sizeofUChar==U_SIZEOF_UCHAR && pInfo->dataFormat[0]==0x52 && /* dataFormat="ResB" */ pInfo->dataFormat[1]==0x65 && pInfo->dataFormat[2]==0x73 && pInfo->dataFormat[3]==0x42 && pInfo->formatVersion[0]==1); } /* semi-public functions ---------------------------------------------------- */ U_CFUNC UBool res_load(ResourceData *pResData, const char *path, const char *name, UErrorCode *errorCode) { /* load the ResourceBundle file */ pResData->data=udata_openChoice(path, "res", name, isAcceptable, NULL, errorCode); if(U_FAILURE(*errorCode)) { return FALSE; } /* get its memory and root resource */ pResData->pRoot=(Resource *)udata_getMemory(pResData->data); pResData->rootRes=*pResData->pRoot; /* currently, we accept only resources that have a Table as their roots */ if(RES_GET_TYPE(pResData->rootRes)!=RES_TABLE) { udata_close(pResData->data); pResData->data=NULL; return FALSE; } return TRUE; } U_CFUNC void res_unload(ResourceData *pResData) { if(pResData->data!=NULL) { udata_close(pResData->data); pResData->data=NULL; } } U_CFUNC const UChar * res_getString(const ResourceData *pResData, const Resource res, int32_t *pLength) { if(res!=RES_BOGUS && RES_GET_TYPE(res)==RES_STRING) { int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res); if (pLength) { *pLength=*p; } return (UChar *)++p; } else { if (pLength) { *pLength=0; } return NULL; } } U_CFUNC const UChar * res_getAlias(const ResourceData *pResData, const Resource res, int32_t *pLength) { if(res!=RES_BOGUS && RES_GET_TYPE(res)==RES_ALIAS) { int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res); if (pLength) { *pLength=*p; } return (UChar *)++p; } else { if (pLength) { *pLength=0; } return NULL; } } U_CFUNC const uint8_t * res_getBinary(const ResourceData *pResData, const Resource res, int32_t *pLength) { if(res!=RES_BOGUS) { int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res); *pLength=*p++; if (*pLength == 0) { p = NULL; } return (uint8_t *)p; } else { *pLength=0; return NULL; } } U_CFUNC const int32_t * res_getIntVector(const ResourceData *pResData, const Resource res, int32_t *pLength) { if(res!=RES_BOGUS && RES_GET_TYPE(res)==RES_INT_VECTOR) { int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res); *pLength=*p++; if (*pLength == 0) { p = NULL; } return (const int32_t *)p; } else { *pLength=0; return NULL; } } U_CFUNC int32_t res_countArrayItems(const ResourceData *pResData, const Resource res) { if(res!=RES_BOGUS) { if(RES_GET_TYPE(res)==RES_STRING) { return 1; } else if(RES_GET_TYPE(res)==RES_ARRAY) { Resource *p=RES_GET_POINTER(pResData->pRoot, res); int32_t count=*(int32_t *)p; return count; } else if(RES_GET_TYPE(res)==RES_TABLE) { return res_getTableSize(pResData, res); } } return 0; } U_CFUNC Resource res_getResource(const ResourceData *pResData, const char *key) { return _res_findTableItem(pResData->pRoot, pResData->rootRes, key); } U_CFUNC Resource res_getArrayItem(const ResourceData *pResData, Resource array, const int32_t indexR) { return _res_getArrayItem(pResData->pRoot, array, indexR); } U_CFUNC Resource res_findResource(const ResourceData *pResData, Resource r, const 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. */ const char *pathP = *path, *nextSepP = *path; char *closeIndex = NULL; Resource t1 = r; Resource t2; int32_t indexR = 0, keyLen = 0; UResType type = RES_GET_TYPE(t1); while(nextSepP && *pathP && t1 != RES_BOGUS && (type == RES_TABLE || type == RES_ARRAY)) { /* 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) { keyLen = nextSepP-pathP; *path = nextSepP+1; } else { keyLen = uprv_strlen(pathP); *path += keyLen; } /* if the resource is a table */ /* try the key based access */ if(type == RES_TABLE) { t2 = _res_findTableItemN(pResData->pRoot, t1, pathP, keyLen, 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(type == RES_ARRAY) { t2 = _res_getArrayItem(pResData->pRoot, t1, indexR); *key = NULL; } else { /* can't do much here, except setting t2 to bogus */ t2 = RES_BOGUS; } t1 = t2; type = RES_GET_TYPE(t1); /* position pathP to next resource key/index */ pathP += keyLen+1; } return t1; } U_CFUNC Resource res_getTableItemByKey(const ResourceData *pResData, Resource table, int32_t* indexR, const char* * key) { uint16_t tempIndex; if(key != NULL) { tempIndex = _res_findTableIndex(pResData->pRoot, table, *key); if(tempIndex != URESDATA_ITEM_NOT_FOUND) { *key = _res_getTableKey(pResData->pRoot, table, tempIndex); *indexR = tempIndex; return _res_getTableItem(pResData->pRoot, table, tempIndex); } else { return RES_BOGUS; } } else { return RES_BOGUS; } } U_CFUNC Resource res_getTableItemByIndex(const ResourceData *pResData, Resource table, int32_t indexR, const char * * key) { if(indexR>-1) { if(key != NULL) { *key = _res_getTableKey(pResData->pRoot, table, (uint16_t)indexR); } return _res_getTableItem(pResData->pRoot, table, (uint16_t)indexR); } else { return RES_BOGUS; } } U_CFUNC int32_t res_getTableSize(const ResourceData *pResData, Resource table) { uint16_t *p=(uint16_t *)RES_GET_POINTER(pResData->pRoot, table); return *p; }