ICU-1948 Support for direct resource access and resource level sharing (aliases)

X-SVN-Rev: 8934
This commit is contained in:
Vladimir Weinstein 2002-06-24 20:58:17 +00:00
parent 4aeef61dff
commit dce5b17a3a
5 changed files with 457 additions and 86 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);