mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 08:53:20 +00:00
ICU-1948 Support for direct resource access and resource level sharing (aliases)
X-SVN-Rev: 8934
This commit is contained in:
parent
4aeef61dff
commit
dce5b17a3a
5 changed files with 457 additions and 86 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 1997-2001, International Business Machines
|
||||
* Copyright (C) 1997-2002, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*
|
||||
|
@ -16,6 +16,7 @@
|
|||
* 06/14/99 stephen Removed functions taking a filename suffix.
|
||||
* 07/20/99 stephen Language-independent ypedef to void*
|
||||
* 11/09/99 weiv Added ures_getLocale()
|
||||
* 06/24/02 weiv Added support for resource sharing
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -182,15 +183,15 @@ typedef enum {
|
|||
RES_NONE=-1,
|
||||
RES_STRING=0,
|
||||
RES_BINARY=1,
|
||||
RES_TABLE=2,
|
||||
|
||||
RES_INT=7,
|
||||
RES_ARRAY=8,
|
||||
RES_INT=2,
|
||||
/* this resource is an alias - contains a string
|
||||
* that is the name of resource containing data
|
||||
*/
|
||||
RES_ALIAS=13,
|
||||
RES_INT_VECTOR=14,
|
||||
RES_ALIAS=3,
|
||||
RES_INT_VECTOR=4,
|
||||
|
||||
RES_TABLE=7,
|
||||
RES_ARRAY=8,
|
||||
RES_RESERVED=15
|
||||
} UResType;
|
||||
|
||||
|
@ -492,7 +493,8 @@ U_CAPI UBool U_EXPORT2 ures_hasNext(UResourceBundle *resourceBundle);
|
|||
* @return a pointer to a UResourceBundle struct. If fill in param was NULL, caller must delete it
|
||||
* @stable
|
||||
*/
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resourceBundle, UResourceBundle *fillIn, UErrorCode *status);
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resourceBundle,
|
||||
UResourceBundle *fillIn, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns the next string in a given resource or NULL if there are no more resources
|
||||
|
@ -505,7 +507,9 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resource
|
|||
* @return a pointer to a zero-terminated UChar array which lives in a memory mapped/DLL file.
|
||||
* @stable
|
||||
*/
|
||||
U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resourceBundle, int32_t* len, const char ** key, UErrorCode *status);
|
||||
U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resourceBundle,
|
||||
int32_t* len, const char ** key,
|
||||
UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns the resource in a given resource at the specified index. Features a fill-in parameter.
|
||||
|
@ -518,7 +522,9 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resourceBundle
|
|||
* @return a pointer to a UResourceBundle struct. If fill in param was NULL, caller must delete it
|
||||
* @stable
|
||||
*/
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resourceBundle, int32_t indexR, UResourceBundle *fillIn, UErrorCode *status);
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resourceBundle,
|
||||
int32_t indexR,
|
||||
UResourceBundle *fillIn, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns the string in a given resource at the specified index.
|
||||
|
@ -530,7 +536,47 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resourc
|
|||
* @return a pointer to a zero-terminated UChar array which lives in a memory mapped/DLL file.
|
||||
* @stable
|
||||
*/
|
||||
U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB, int32_t indexS, int32_t* len, UErrorCode *status);
|
||||
U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
|
||||
int32_t indexS, int32_t* len,
|
||||
UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns a resource that can be located using the pathToResource argument. One needs optional package, locale
|
||||
* and path inside the locale, for example: "/myData/en/zoneStrings/3". Keys and indexes are supported. Keys
|
||||
* need to reference data in named structures, while indexes can reference both named and anonymous resources.
|
||||
* Features a fill-in parameter.
|
||||
*
|
||||
* @param pathToResource a path that will lead to the requested resource
|
||||
* @param fillIn if NULL a new UResourceBundle struct is allocated and must be deleted by the caller.
|
||||
* Alternatively, you can supply a struct to be filled by this function.
|
||||
* @param status fills in the outgoing error code.
|
||||
* @return a pointer to a UResourceBundle struct. If fill in param was NULL, caller must delete it
|
||||
* @draft ICU 2.2
|
||||
*/
|
||||
U_CAPI UResourceBundle* U_EXPORT2
|
||||
ures_findResource(const char* pathToResource,
|
||||
UResourceBundle *fillIn, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns a sub resource that can be located using the pathToResource argument. One needs a path inside
|
||||
* the supplied resource, for example, if you have "en_US" resource bundle opened, you might ask for
|
||||
* "zoneStrings/3". Keys and indexes are supported. Keys
|
||||
* need to reference data in named structures, while indexes can reference both
|
||||
* named and anonymous resources.
|
||||
* Features a fill-in parameter.
|
||||
*
|
||||
* @param resourceBundle a resource
|
||||
* @param pathToResource a path that will lead to the requested resource
|
||||
* @param fillIn if NULL a new UResourceBundle struct is allocated and must be deleted by the caller.
|
||||
* Alternatively, you can supply a struct to be filled by this function.
|
||||
* @param status fills in the outgoing error code.
|
||||
* @return a pointer to a UResourceBundle struct. If fill in param was NULL, caller must delete it
|
||||
* @draft ICU 2.2
|
||||
*/
|
||||
U_CAPI UResourceBundle* U_EXPORT2
|
||||
ures_findSubResource(const UResourceBundle *resB,
|
||||
const char* pathToResource,
|
||||
UResourceBundle *fillIn, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns a resource in a given resource that has a given key. This procedure works only with table
|
||||
|
@ -544,7 +590,9 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
|
|||
* @return a pointer to a UResourceBundle struct. If fill in param was NULL, caller must delete it
|
||||
* @stable
|
||||
*/
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resourceBundle, const char* key, UResourceBundle *fillIn, UErrorCode *status);
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resourceBundle,
|
||||
const char* key,
|
||||
UResourceBundle *fillIn, UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Returns a string in a given resource that has a given key. This procedure works only with table
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1997-2001, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2002, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -15,6 +15,7 @@
|
|||
* 11/09/99 weiv Added ures_getLocale()
|
||||
* March 2000 weiv Total overhaul - using data in DLLs
|
||||
* 06/20/2000 helena OS/400 port changes; mostly typecast.
|
||||
* 06/24/02 weiv Added support for resource sharing
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -498,78 +499,124 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr
|
|||
static void entryClose(UResourceDataEntry *resB);
|
||||
/* INTERNAL: */
|
||||
static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r,
|
||||
const char *key, UResourceDataEntry *realData,
|
||||
UResourceBundle *resB, UErrorCode *status) {
|
||||
const char *key, int32_t index, UResourceDataEntry *realData,
|
||||
const UResourceBundle *parent, int32_t noAlias,
|
||||
UResourceBundle *resB, UErrorCode *status)
|
||||
{
|
||||
if(status == NULL || U_FAILURE(*status)) {
|
||||
return resB;
|
||||
}
|
||||
if(RES_GET_TYPE(r) == RES_ALIAS) { /* This is an alias, need to exchange with real data */
|
||||
int32_t len = 0;
|
||||
const UChar *alias = res_getAlias(rdata, r, &len);
|
||||
if(len > 0) {
|
||||
/* we have an alias, now let's cut it up */
|
||||
int32_t i = 0;
|
||||
char *chAlias = NULL, *path = NULL, *locale = NULL, *keyPath = NULL;
|
||||
int32_t pathLen = 0, localeLen = 0, keyPathLen = 0;
|
||||
chAlias = (char *)uprv_malloc((len+1)*sizeof(char));
|
||||
u_UCharsToChars(alias, chAlias, len);
|
||||
chAlias[len] = 0;
|
||||
if(noAlias < URES_MAX_ALIAS_LEVEL) {
|
||||
int32_t len = 0;
|
||||
const UChar *alias = res_getAlias(rdata, r, &len);
|
||||
if(len > 0) {
|
||||
/* we have an alias, now let's cut it up */
|
||||
int32_t i = 0;
|
||||
char *chAlias = NULL, *path = NULL, *locale = NULL, *keyPath = NULL;
|
||||
int32_t pathLen = 0, localeLen = 0, keyPathLen = 0;
|
||||
chAlias = (char *)uprv_malloc((len+1)*sizeof(char));
|
||||
u_UCharsToChars(alias, chAlias, len);
|
||||
chAlias[len] = 0;
|
||||
|
||||
locale = uprv_strchr(chAlias, '|');
|
||||
if(locale == NULL) {
|
||||
locale = chAlias;
|
||||
} else {
|
||||
*locale = 0;
|
||||
locale++;
|
||||
path = chAlias;
|
||||
}
|
||||
if(path != NULL && uprv_strlen(path) == 0) {
|
||||
path = realData->fPath;
|
||||
}
|
||||
|
||||
keyPath = uprv_strchr(locale, '/');
|
||||
if(keyPath == NULL) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
*keyPath = 0;
|
||||
keyPath++;
|
||||
}
|
||||
|
||||
{
|
||||
char *kp = NULL;
|
||||
/* got almost everything, let's try to open */
|
||||
UResourceBundle *main = ures_open(path, locale, status);
|
||||
UResourceBundle *res = main;
|
||||
UResourceBundle *res2 = resB;
|
||||
while((kp=uprv_strchr(keyPath, '/')) && U_SUCCESS(*status)) {
|
||||
*kp = 0;
|
||||
res2 = ures_getByKey(res, keyPath, res2, status);
|
||||
/*ures_close(res);*/
|
||||
res = res2;
|
||||
keyPath = kp+1;
|
||||
if(*chAlias == RES_PATH_SEPARATOR) {
|
||||
/* there is a path included */
|
||||
locale = uprv_strchr(chAlias+1, RES_PATH_SEPARATOR);
|
||||
*locale = 0;
|
||||
locale++;
|
||||
path = chAlias+1;
|
||||
if(uprv_strcmp(path, "ICUDATA") == 0) { /* want ICU data */
|
||||
path = NULL;
|
||||
}
|
||||
} else {
|
||||
/* no path, start with a locale */
|
||||
locale = chAlias;
|
||||
path = realData->fPath;
|
||||
}
|
||||
res2 = ures_getByKey(res, keyPath, res2, status);
|
||||
ures_close(main);
|
||||
/*res = res2;*/
|
||||
keyPath = uprv_strchr(locale, RES_PATH_SEPARATOR);
|
||||
if(keyPath) {
|
||||
*keyPath = 0;
|
||||
keyPath++;
|
||||
}
|
||||
{
|
||||
/* got almost everything, let's try to open */
|
||||
/* first, open the bundle with real data */
|
||||
UResourceBundle *main = ures_openDirect(path, locale, status);
|
||||
UResourceBundle *result = NULL;
|
||||
|
||||
/* here we have the wanted resource */
|
||||
/*
|
||||
rdata = &(res->fResData);
|
||||
r = res->fRes;
|
||||
realData = res->fData;
|
||||
*/
|
||||
uprv_free(chAlias);
|
||||
return res2;
|
||||
if(keyPath == NULL) {
|
||||
/* no key path. This means that we are going to
|
||||
* to use the corresponding resource from
|
||||
* another bundle
|
||||
*/
|
||||
/* first, we are going to get a corresponding parent
|
||||
* resource to the one we are searching.
|
||||
*/
|
||||
const char* aKey = parent->fResPath;
|
||||
if(aKey) {
|
||||
r = res_findResource(&(main->fResData), main->fRes, &aKey);
|
||||
} else {
|
||||
r = main->fRes;
|
||||
}
|
||||
if(key) {
|
||||
/* we need to make keyPath from parents fResPath and
|
||||
* current key, if there is a key associated
|
||||
*/
|
||||
aKey = key;
|
||||
r = res_findResource(&(main->fResData), r, &aKey);
|
||||
} else if(index != -1) {
|
||||
/* if there is no key, but there is an index, try to get by the index */
|
||||
/* here we have either a table or an array, so get the element */
|
||||
if(RES_GET_TYPE(r) == RES_TABLE) {
|
||||
r = res_getTableItemByIndex(&(main->fResData), r, index, &aKey);
|
||||
} else { /* array */
|
||||
r = res_getArrayItem(&(main->fResData), r, index);
|
||||
}
|
||||
}
|
||||
if(r != RES_BOGUS) {
|
||||
result = init_resb_result(&(main->fResData), r, key, -1, main->fData, parent, noAlias+1, resB, status);
|
||||
} else {
|
||||
*status = U_MISSING_RESOURCE_ERROR;
|
||||
result = resB;
|
||||
}
|
||||
} else {
|
||||
/* this one is a bit trickier.
|
||||
* we start finding keys, but after we resolve one alias, the path might continue.
|
||||
* Consider:
|
||||
* aliastest:alias { "testtypes/anotheralias/Sequence" }
|
||||
* anotheralias:alias { "/ICUDATA/sh/CollationElements" }
|
||||
* aliastest resource should finally have the sequence, not collation elements.
|
||||
*/
|
||||
result = main;
|
||||
while(*keyPath) {
|
||||
r = res_findResource(&(result->fResData), result->fRes, &keyPath);
|
||||
if(r == RES_BOGUS) {
|
||||
*status = U_MISSING_RESOURCE_ERROR;
|
||||
result = resB;
|
||||
break;
|
||||
}
|
||||
resB = init_resb_result(&(result->fResData), r, key, -1, result->fData, parent, noAlias+1, resB, status);
|
||||
result = resB;
|
||||
}
|
||||
}
|
||||
uprv_free(chAlias);
|
||||
ures_close(main);
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
/* bad alias, should be an error */
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return resB;
|
||||
}
|
||||
} else {
|
||||
/* bad alias, should be an error */
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
*status = U_TOO_MANY_ALIASES_ERROR;
|
||||
return resB;
|
||||
}
|
||||
}
|
||||
if(resB == NULL) {
|
||||
resB = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
|
||||
ures_setIsStackObject(resB, FALSE);
|
||||
resB->fResPath = NULL;
|
||||
} else {
|
||||
if(resB->fData != NULL) {
|
||||
entryClose(resB->fData);
|
||||
|
@ -587,8 +634,23 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r,
|
|||
resB->fIsTopLevel = FALSE;
|
||||
resB->fIndex = -1;
|
||||
resB->fKey = key;
|
||||
ures_freeResPath(resB);
|
||||
if(parent->fResPath) {
|
||||
ures_appendResPath(resB, parent->fResPath);
|
||||
}
|
||||
if(key != NULL) {
|
||||
ures_appendResPath(resB, key);
|
||||
ures_appendResPath(resB, RES_PATH_SEPARATOR_S);
|
||||
} else {
|
||||
char buf[256];
|
||||
T_CString_integerToString(buf, index, 10);
|
||||
ures_appendResPath(resB, buf);
|
||||
ures_appendResPath(resB, RES_PATH_SEPARATOR_S);
|
||||
}
|
||||
|
||||
resB->fVersion = NULL;
|
||||
resB->fRes = r;
|
||||
/*resB->fParent = parent->fRes;*/
|
||||
resB->fResData.data = rdata->data;
|
||||
resB->fResData.pRoot = rdata->pRoot;
|
||||
resB->fResData.rootRes = rdata->rootRes;
|
||||
|
@ -616,6 +678,10 @@ UResourceBundle *ures_copyResb(UResourceBundle *r, const UResourceBundle *origin
|
|||
}
|
||||
}
|
||||
uprv_memcpy(r, original, sizeof(UResourceBundle));
|
||||
r->fResPath = NULL;
|
||||
if(original->fResPath) {
|
||||
ures_appendResPath(r, original->fResPath);
|
||||
}
|
||||
ures_setIsStackObject(r, isStackObject);
|
||||
if(r->fData != NULL) {
|
||||
entryIncrease(r->fData);
|
||||
|
@ -844,13 +910,13 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resB, UR
|
|||
if(r == RES_BOGUS && resB->fHasFallback) {
|
||||
/* TODO: do the fallback */
|
||||
}
|
||||
return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
|
||||
return init_resb_result(&(resB->fResData), r, key, resB->fIndex, resB->fData, resB, 0, fillIn, status);
|
||||
case RES_ARRAY:
|
||||
r = res_getArrayItem(&(resB->fResData), resB->fRes, resB->fIndex);
|
||||
if(r == RES_BOGUS && resB->fHasFallback) {
|
||||
/* TODO: do the fallback */
|
||||
}
|
||||
return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
|
||||
return init_resb_result(&(resB->fResData), r, key, resB->fIndex, resB->fData, resB, 0, fillIn, status);
|
||||
case RES_INT_VECTOR:
|
||||
default:
|
||||
/*return NULL;*/
|
||||
|
@ -886,13 +952,13 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resB, i
|
|||
if(r == RES_BOGUS && resB->fHasFallback) {
|
||||
/* TODO: do the fallback */
|
||||
}
|
||||
return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
|
||||
return init_resb_result(&(resB->fResData), r, key, indexR, resB->fData, resB, 0, fillIn, status);
|
||||
case RES_ARRAY:
|
||||
r = res_getArrayItem(&(resB->fResData), resB->fRes, indexR);
|
||||
if(r == RES_BOGUS && resB->fHasFallback) {
|
||||
/* TODO: do the fallback */
|
||||
}
|
||||
return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
|
||||
return init_resb_result(&(resB->fResData), r, key, indexR, resB->fData, resB, 0, fillIn, status);
|
||||
case RES_INT_VECTOR:
|
||||
default:
|
||||
/*return NULL;*/
|
||||
|
@ -945,6 +1011,80 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
U_CAPI const char *ures_getResPath(UResourceBundle *resB) {
|
||||
return resB->fResPath;
|
||||
}
|
||||
|
||||
U_CAPI UResourceBundle* U_EXPORT2
|
||||
ures_findResource(const char* path, UResourceBundle *fillIn, UErrorCode *status)
|
||||
{
|
||||
UResourceBundle *first = NULL;
|
||||
UResourceBundle *result = fillIn;
|
||||
char *packageName = NULL;
|
||||
char *pathToResource = NULL;
|
||||
char *locale = NULL, *localeEnd = NULL;
|
||||
if(status == NULL || U_FAILURE(*status)) {
|
||||
return result;
|
||||
}
|
||||
pathToResource = (char *)uprv_malloc((uprv_strlen(path)+1)*sizeof(char));
|
||||
uprv_strcpy(pathToResource, path);
|
||||
locale = pathToResource;
|
||||
if(*pathToResource == RES_PATH_SEPARATOR) { /* there is a path specification */
|
||||
pathToResource++;
|
||||
packageName = pathToResource;
|
||||
pathToResource = uprv_strchr(pathToResource, RES_PATH_SEPARATOR);
|
||||
if(pathToResource == NULL) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
*pathToResource = 0;
|
||||
locale = pathToResource+1;
|
||||
}
|
||||
}
|
||||
|
||||
localeEnd = strchr(locale, RES_PATH_SEPARATOR);
|
||||
if(localeEnd != NULL) {
|
||||
*localeEnd = 0;
|
||||
}
|
||||
|
||||
first = ures_open(packageName, locale, status);
|
||||
|
||||
if(U_SUCCESS(*status)) {
|
||||
if(localeEnd) {
|
||||
result = ures_findSubResource(first, localeEnd+1, fillIn, status);
|
||||
} else {
|
||||
result = ures_copyResb(fillIn, first, status);
|
||||
}
|
||||
ures_close(first);
|
||||
}
|
||||
uprv_free(pathToResource);
|
||||
return result;
|
||||
}
|
||||
|
||||
U_CAPI UResourceBundle* U_EXPORT2
|
||||
ures_findSubResource(const UResourceBundle *resB, const char* path, UResourceBundle *fillIn, UErrorCode *status)
|
||||
{
|
||||
Resource res = RES_BOGUS;
|
||||
UResourceBundle *result = fillIn;
|
||||
const char *pathToResource = path;
|
||||
|
||||
if(status == NULL || U_FAILURE(*status)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* here we do looping and circular alias checking */
|
||||
|
||||
res = res_findResource(&(resB->fResData), resB->fRes, &pathToResource);
|
||||
|
||||
if(res != RES_BOGUS) {
|
||||
result = init_resb_result(&(resB->fResData), res, path, -1, resB->fData, resB, 0, fillIn, status);
|
||||
} else {
|
||||
*status = U_MISSING_RESOURCE_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) {
|
||||
Resource res = RES_BOGUS;
|
||||
UResourceDataEntry *realData = NULL;
|
||||
|
@ -966,7 +1106,8 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, con
|
|||
if(resB->fHasFallback == TRUE) {
|
||||
const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
|
||||
if(U_SUCCESS(*status)) {
|
||||
return init_resb_result(rd, res, key, realData, fillIn, status);
|
||||
/* check if resB->fResPath gives the right name here */
|
||||
return init_resb_result(rd, res, key, -1, realData, resB, 0, fillIn, status);
|
||||
} else {
|
||||
*status = U_MISSING_RESOURCE_ERROR;
|
||||
}
|
||||
|
@ -974,7 +1115,7 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, con
|
|||
*status = U_MISSING_RESOURCE_ERROR;
|
||||
}
|
||||
} else {
|
||||
return init_resb_result(&(resB->fResData), res, key, resB->fData, fillIn, status);
|
||||
return init_resb_result(&(resB->fResData), res, key, -1, resB->fData, resB, 0, fillIn, status);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
|
@ -984,7 +1125,7 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, con
|
|||
/* here should go a first attempt to locate the key using index table */
|
||||
const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
|
||||
if(U_SUCCESS(*status)) {
|
||||
return init_resb_result(rd, res, key, realData, fillIn, status);
|
||||
return init_resb_result(rd, res, key, realData, resB, fillIn, status);
|
||||
} else {
|
||||
*status = U_MISSING_RESOURCE_ERROR;
|
||||
}
|
||||
|
@ -1122,7 +1263,48 @@ static void entryClose(UResourceDataEntry *resB) {
|
|||
entryCloseInt(resB);
|
||||
umtx_unlock(&resbMutex);
|
||||
}
|
||||
/*
|
||||
U_CFUNC void ures_setResPath(UResourceBundle *resB, const char* toAdd) {
|
||||
if(resB->fResPath == NULL) {
|
||||
resB->fResPath = resB->fResBuf;
|
||||
*(resB->fResPath) = 0;
|
||||
}
|
||||
resB->fResPathLen = uprv_strlen(toAdd);
|
||||
if(RES_BUFSIZE <= resB->fResPathLen+1) {
|
||||
if(resB->fResPath == resB->fResBuf) {
|
||||
resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char));
|
||||
} else {
|
||||
resB->fResPath = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char));
|
||||
}
|
||||
}
|
||||
uprv_strcpy(resB->fResPath, toAdd);
|
||||
}
|
||||
*/
|
||||
U_CFUNC void ures_appendResPath(UResourceBundle *resB, const char* toAdd) {
|
||||
if(resB->fResPath == NULL) {
|
||||
resB->fResPath = resB->fResBuf;
|
||||
*(resB->fResPath) = 0;
|
||||
resB->fResPathLen = 0;
|
||||
}
|
||||
resB->fResPathLen += uprv_strlen(toAdd);
|
||||
if(RES_BUFSIZE <= resB->fResPathLen+1) {
|
||||
if(resB->fResPath == resB->fResBuf) {
|
||||
resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char));
|
||||
uprv_strcpy(resB->fResPath, resB->fResBuf);
|
||||
} else {
|
||||
resB->fResPath = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char));
|
||||
}
|
||||
}
|
||||
uprv_strcat(resB->fResPath, toAdd);
|
||||
}
|
||||
|
||||
U_CFUNC void ures_freeResPath(UResourceBundle *resB) {
|
||||
if(resB->fResPath != resB->fResBuf) {
|
||||
uprv_free(resB->fResPath);
|
||||
}
|
||||
resB->fResPath = NULL;
|
||||
resB->fResPathLen = 0;
|
||||
}
|
||||
|
||||
U_CFUNC const char* ures_getName(const UResourceBundle* resB) {
|
||||
if(resB == NULL) {
|
||||
|
@ -1176,6 +1358,18 @@ ures_openFillIn(UResourceBundle *r, const char* path,
|
|||
r->fResData.rootRes = firstData->fData.rootRes;
|
||||
r->fRes = r->fResData.rootRes;
|
||||
r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
|
||||
/*r->fParent = RES_BOGUS;*/
|
||||
/*r->fResPath = NULL;*/
|
||||
ures_freeResPath(r);
|
||||
/*
|
||||
if(r->fData->fPath != NULL) {
|
||||
ures_setResPath(r, r->fData->fPath);
|
||||
ures_appendResPath(r, RES_PATH_PACKAGE_S);
|
||||
ures_appendResPath(r, r->fData->fName);
|
||||
} else {
|
||||
ures_setResPath(r, r->fData->fName);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
U_CAPI UResourceBundle* U_EXPORT2
|
||||
|
@ -1234,7 +1428,19 @@ ures_open(const char* path,
|
|||
r->fResData.pRoot = hasData->fData.pRoot;
|
||||
r->fResData.rootRes = hasData->fData.rootRes;
|
||||
r->fRes = r->fResData.rootRes;
|
||||
/*r->fParent = RES_BOGUS;*/
|
||||
r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
|
||||
r->fResPath = NULL;
|
||||
/*
|
||||
if(r->fData->fPath != NULL) {
|
||||
ures_setResPath(r, r->fData->fPath);
|
||||
ures_appendResPath(r, RES_PATH_PACKAGE_S);
|
||||
ures_appendResPath(r, r->fData->fName);
|
||||
} else {
|
||||
ures_setResPath(r, r->fData->fName);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1325,7 +1531,18 @@ ures_openDirect(const char* path, const char* localeID, UErrorCode* status) {
|
|||
r->fResData.pRoot = r->fData->fData.pRoot;
|
||||
r->fResData.rootRes = r->fData->fData.rootRes;
|
||||
r->fRes = r->fResData.rootRes;
|
||||
/*r->fParent = RES_BOGUS;*/
|
||||
r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
|
||||
r->fResPath = NULL;
|
||||
/*
|
||||
if(r->fData->fPath != NULL) {
|
||||
ures_setResPath(r, r->fData->fPath);
|
||||
ures_appendResPath(r, RES_PATH_PACKAGE_S);
|
||||
ures_appendResPath(r, r->fData->fName);
|
||||
} else {
|
||||
ures_setResPath(r, r->fData->fName);
|
||||
}
|
||||
*/
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -1390,6 +1607,7 @@ ures_close(UResourceBundle* resB)
|
|||
if(resB->fVersion != NULL) {
|
||||
uprv_free(resB->fVersion);
|
||||
}
|
||||
ures_freeResPath(resB);
|
||||
|
||||
if(ures_isStackObject(resB) == FALSE) {
|
||||
uprv_free(resB);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 1999-2001, International Business Machines Corporation *
|
||||
* Copyright (C) 1999-2002, International Business Machines Corporation *
|
||||
* and others. All Rights Reserved. *
|
||||
* *
|
||||
*******************************************************************************
|
||||
|
@ -16,6 +16,7 @@
|
|||
*
|
||||
* 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"
|
||||
|
@ -113,6 +114,37 @@ _res_findTableItem(const Resource *pRoot, const Resource res, const char *key) {
|
|||
}
|
||||
}
|
||||
|
||||
static Resource
|
||||
_res_findTableItemN(const Resource *pRoot, const Resource res, const char *key, int32_t keyLen) {
|
||||
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(start<limit-1) {
|
||||
i=(uint16_t)((start+limit)/2);
|
||||
if(uprv_strncmp(key, RES_GET_KEY(pRoot, p[i]), keyLen)<0) {
|
||||
limit=i;
|
||||
} else {
|
||||
start=i;
|
||||
}
|
||||
}
|
||||
|
||||
/* did we really find it? */
|
||||
if(uprv_strncmp(key, RES_GET_KEY(pRoot, p[start]), keyLen)==0) {
|
||||
limit=*(p-1); /* itemCount */
|
||||
return ((Resource *)(p+limit+(~limit&1)))[start];
|
||||
} else {
|
||||
return RES_BOGUS; /* not found */
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
_res_findTableIndex(const Resource *pRoot, const Resource res, const char *key) {
|
||||
uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res);
|
||||
|
@ -280,12 +312,65 @@ res_getResource(const ResourceData *pResData, const char *key) {
|
|||
}
|
||||
|
||||
U_CFUNC Resource
|
||||
res_getArrayItem(const ResourceData *pResData, const Resource array, const int32_t indexR) {
|
||||
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) {
|
||||
/* 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(*pathP && nextSepP && t1 != RES_BOGUS && type >= RES_TABLE) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* try the key based access */
|
||||
t2 = _res_findTableItemN(pResData->pRoot, t1, pathP, keyLen);
|
||||
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(type == RES_TABLE) {
|
||||
/* if we indeed have an index, try to get the item by index */
|
||||
t2 = _res_getTableItem(pResData->pRoot, t1, (uint16_t)indexR);
|
||||
} else { /* if(type == RES_ARRAY) { */
|
||||
t2 = _res_getArrayItem(pResData->pRoot, t1, indexR);
|
||||
}
|
||||
}
|
||||
}
|
||||
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, const Resource table, int32_t* indexR, const char* * key) {
|
||||
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);
|
||||
|
@ -302,7 +387,7 @@ res_getTableItemByKey(const ResourceData *pResData, const Resource table, int32_
|
|||
}
|
||||
|
||||
U_CFUNC Resource
|
||||
res_getTableItemByIndex(const ResourceData *pResData, const Resource table, int32_t indexR, const char * * key) {
|
||||
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);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 1999-2001, International Business Machines *
|
||||
* Copyright (C) 1999-2002, International Business Machines *
|
||||
* Corporation and others. All Rights Reserved. *
|
||||
* *
|
||||
******************************************************************************
|
||||
|
@ -12,6 +12,7 @@
|
|||
*
|
||||
* created on: 1999dec08
|
||||
* created by: Markus W. Scherer
|
||||
* 06/24/02 weiv Added support for resource sharing
|
||||
*/
|
||||
|
||||
#ifndef __RESDATA_H__
|
||||
|
@ -109,8 +110,9 @@ res_countArrayItems(const ResourceData *pResData, const Resource res);
|
|||
|
||||
U_CFUNC int32_t res_getTableSize(const ResourceData *pResData, Resource table);
|
||||
|
||||
U_CFUNC Resource res_getArrayItem(const ResourceData *pResData, const Resource array, const int32_t indexS);
|
||||
U_CFUNC Resource res_getTableItemByIndex(const ResourceData *pResData, const Resource table, int32_t indexS, const char ** key);
|
||||
U_CFUNC Resource res_getTableItemByKey(const ResourceData *pResData, const Resource table, int32_t *indexS, const char* * key);
|
||||
U_CFUNC Resource res_getArrayItem(const ResourceData *pResData, Resource array, const int32_t indexS);
|
||||
U_CFUNC Resource res_getTableItemByIndex(const ResourceData *pResData, Resource table, int32_t indexS, const char ** key);
|
||||
U_CFUNC Resource res_getTableItemByKey(const ResourceData *pResData, Resource table, int32_t *indexS, const char* * key);
|
||||
U_CFUNC Resource res_findResource(const ResourceData *pResData, Resource r, const char** path);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 2000-2001, International Business Machines
|
||||
* Copyright (C) 2000-2002, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*/
|
||||
|
@ -26,6 +26,8 @@
|
|||
#define MAGIC1 19700503
|
||||
#define MAGIC2 19641227
|
||||
|
||||
#define URES_MAX_ALIAS_LEVEL 256
|
||||
|
||||
/*
|
||||
enum UResEntryType {
|
||||
ENTRY_OK = 0,
|
||||
|
@ -51,8 +53,15 @@ struct UResourceDataEntry {
|
|||
int32_t fHashKey; /* for faster access in the hashtable */
|
||||
};
|
||||
|
||||
#define RES_BUFSIZE 256
|
||||
#define RES_PATH_SEPARATOR '/'
|
||||
#define RES_PATH_SEPARATOR_S "/"
|
||||
|
||||
struct UResourceBundle {
|
||||
const char *fKey; /*tag*/
|
||||
char *fResPath; /* full path to the resource: "zh_TW/CollationElements/Sequence" */
|
||||
char fResBuf[RES_BUFSIZE];
|
||||
int32_t fResPathLen;
|
||||
char *fVersion;
|
||||
UBool fHasFallback;
|
||||
UBool fIsTopLevel;
|
||||
|
@ -64,6 +73,12 @@ struct UResourceBundle {
|
|||
int32_t fSize;
|
||||
ResourceData fResData;
|
||||
Resource fRes;
|
||||
|
||||
/* parent of this resource -
|
||||
* lives in the same data entry
|
||||
*/
|
||||
/* This cannot be done right now - need support in genrb */
|
||||
/*Resource fParent; */
|
||||
};
|
||||
|
||||
U_CFUNC void ures_initStackObject(UResourceBundle* resB);
|
||||
|
@ -73,6 +88,9 @@ U_CFUNC UBool ures_isStackObject( UResourceBundle* resB);
|
|||
/* Some getters used by the copy constructor */
|
||||
U_CFUNC const char* ures_getName(const UResourceBundle* resB);
|
||||
U_CFUNC const char* ures_getPath(const UResourceBundle* resB);
|
||||
U_CFUNC void ures_appendResPath(UResourceBundle *resB, const char* toAdd);
|
||||
/*U_CFUNC void ures_setResPath(UResourceBundle *resB, const char* toAdd);*/
|
||||
U_CFUNC void ures_freeResPath(UResourceBundle *resB);
|
||||
|
||||
/* Candidates for export */
|
||||
U_CFUNC UResourceBundle *ures_copyResb(UResourceBundle *r, const UResourceBundle *original, UErrorCode *status);
|
||||
|
|
Loading…
Add table
Reference in a new issue