| Index: source/common/uresbund.cpp
|
| diff --git a/source/common/uresbund.cpp b/source/common/uresbund.cpp
|
| index 266ed0af13a3a4a1dabf202f5a752c7392d6babe..e74afb8a483db2ed251c39a82de835ca216901f4 100644
|
| --- a/source/common/uresbund.cpp
|
| +++ b/source/common/uresbund.cpp
|
| @@ -1,10 +1,10 @@
|
| /*
|
| ******************************************************************************
|
| -* Copyright (C) 1997-2014, International Business Machines Corporation and
|
| +* Copyright (C) 1997-2015, International Business Machines Corporation and
|
| * others. All Rights Reserved.
|
| ******************************************************************************
|
| *
|
| -* File URESBUND.C
|
| +* File uresbund.cpp
|
| *
|
| * Modification History:
|
| *
|
| @@ -54,7 +54,7 @@ static int32_t U_CALLCONV hashEntry(const UHashTok parm) {
|
| UHashTok namekey, pathkey;
|
| namekey.pointer = b->fName;
|
| pathkey.pointer = b->fPath;
|
| - return uhash_hashChars(namekey)+37*uhash_hashChars(pathkey);
|
| + return uhash_hashChars(namekey)+37u*uhash_hashChars(pathkey);
|
| }
|
|
|
| /* INTERNAL: compares two entries */
|
| @@ -187,7 +187,7 @@ static int32_t ures_flushCache()
|
| do {
|
| deletedMore = FALSE;
|
| /*creates an enumeration to iterate through every element in the table */
|
| - pos = -1;
|
| + pos = UHASH_FIRST;
|
| while ((e = uhash_nextElement(cache, &pos)) != NULL)
|
| {
|
| resB = (UResourceDataEntry *) e->value.pointer;
|
| @@ -222,7 +222,7 @@ static int32_t ures_flushCache()
|
|
|
| U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) {
|
| UBool cacheNotEmpty = FALSE;
|
| - int32_t pos = -1;
|
| + int32_t pos = UHASH_FIRST;
|
| const UHashElement *e;
|
| UResourceDataEntry *resB;
|
|
|
| @@ -377,6 +377,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE
|
| const int32_t *poolIndexes = r->fPool->fData.pRoot + 1;
|
| if(r->fData.pRoot[1 + URES_INDEX_POOL_CHECKSUM] == poolIndexes[URES_INDEX_POOL_CHECKSUM]) {
|
| r->fData.poolBundleKeys = (const char *)(poolIndexes + (poolIndexes[URES_INDEX_LENGTH] & 0xff));
|
| + r->fData.poolBundleStrings = r->fPool->fData.p16BitUnits;
|
| } else {
|
| r->fBogus = *status = U_INVALID_FORMAT_ERROR;
|
| }
|
| @@ -446,7 +447,9 @@ getPoolEntry(const char *path, UErrorCode *status) {
|
|
|
| /* INTERNAL: */
|
| /* CAUTION: resbMutex must be locked when calling this function! */
|
| -static UResourceDataEntry *findFirstExisting(const char* path, char* name, UBool *isRoot, UBool *hasChopped, UBool *isDefault, UErrorCode* status) {
|
| +static UResourceDataEntry *
|
| +findFirstExisting(const char* path, char* name,
|
| + UBool *isRoot, UBool *hasChopped, UBool *isDefault, UErrorCode* status) {
|
| UResourceDataEntry *r = NULL;
|
| UBool hasRealData = FALSE;
|
| const char *defaultLoc = uloc_getDefault();
|
| @@ -502,15 +505,106 @@ U_CFUNC void ures_initStackObject(UResourceBundle* resB) {
|
| ures_setIsStackObject(resB, TRUE);
|
| }
|
|
|
| -static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UErrorCode* status) {
|
| - UErrorCode intStatus = U_ZERO_ERROR;
|
| +static UBool // returns U_SUCCESS(*status)
|
| +loadParentsExceptRoot(UResourceDataEntry *&t1,
|
| + char name[], int32_t nameCapacity,
|
| + UBool usingUSRData, char usrDataPath[], UErrorCode *status) {
|
| + if (U_FAILURE(*status)) { return FALSE; }
|
| + UBool hasChopped = TRUE;
|
| + while (hasChopped && t1->fParent == NULL && !t1->fData.noFallback &&
|
| + res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOGUS) {
|
| + Resource parentRes = res_getResource(&t1->fData, "%%Parent");
|
| + if (parentRes != RES_BOGUS) { // An explicit parent was found.
|
| + int32_t parentLocaleLen = 0;
|
| + const UChar *parentLocaleName = res_getString(&(t1->fData), parentRes, &parentLocaleLen);
|
| + if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLen < nameCapacity) {
|
| + u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1);
|
| + if (uprv_strcmp(name, kRootLocaleName) == 0) {
|
| + return TRUE;
|
| + }
|
| + }
|
| + }
|
| + // Insert regular parents.
|
| + UErrorCode parentStatus = U_ZERO_ERROR;
|
| + UResourceDataEntry *t2 = init_entry(name, t1->fPath, &parentStatus);
|
| + if (U_FAILURE(parentStatus)) {
|
| + *status = parentStatus;
|
| + return FALSE;
|
| + }
|
| + UResourceDataEntry *u2 = NULL;
|
| + UErrorCode usrStatus = U_ZERO_ERROR;
|
| + if (usingUSRData) { // This code inserts user override data into the inheritance chain.
|
| + u2 = init_entry(name, usrDataPath, &usrStatus);
|
| + }
|
| +
|
| + if (usingUSRData && U_SUCCESS(usrStatus) && u2->fBogus == U_ZERO_ERROR) {
|
| + t1->fParent = u2;
|
| + u2->fParent = t2;
|
| + } else {
|
| + t1->fParent = t2;
|
| + if (usingUSRData) {
|
| + // The USR override data wasn't found, set it to be deleted.
|
| + u2->fCountExisting = 0;
|
| + }
|
| + }
|
| + t1 = t2;
|
| + hasChopped = chopLocale(name);
|
| + }
|
| + return TRUE;
|
| +}
|
| +
|
| +static UBool // returns U_SUCCESS(*status)
|
| +insertRootBundle(UResourceDataEntry *&t1, UErrorCode *status) {
|
| + if (U_FAILURE(*status)) { return FALSE; }
|
| UErrorCode parentStatus = U_ZERO_ERROR;
|
| - UErrorCode usrStatus = U_ZERO_ERROR;
|
| + UResourceDataEntry *t2 = init_entry(kRootLocaleName, t1->fPath, &parentStatus);
|
| + if (U_FAILURE(parentStatus)) {
|
| + *status = parentStatus;
|
| + return FALSE;
|
| + }
|
| + t1->fParent = t2;
|
| + t1 = t2;
|
| + return TRUE;
|
| +}
|
| +
|
| +enum UResOpenType {
|
| + /**
|
| + * Open a resource bundle for the locale;
|
| + * if there is not even a base language bundle, then fall back to the default locale;
|
| + * if there is no bundle for that either, then load the root bundle.
|
| + *
|
| + * This is the default bundle loading behavior.
|
| + */
|
| + URES_OPEN_LOCALE_DEFAULT_ROOT,
|
| + // TODO: ICU ticket #11271 "consistent default locale across locale trees"
|
| + // Add an option to look at the main locale tree for whether to
|
| + // fall back to root directly (if the locale has main data) or
|
| + // fall back to the default locale first (if the locale does not even have main data).
|
| + /**
|
| + * Open a resource bundle for the locale;
|
| + * if there is not even a base language bundle, then load the root bundle;
|
| + * never fall back to the default locale.
|
| + *
|
| + * This is used for algorithms that have good pan-Unicode default behavior,
|
| + * such as case mappings, collation, and segmentation (BreakIterator).
|
| + */
|
| + URES_OPEN_LOCALE_ROOT,
|
| + /**
|
| + * Open a resource bundle for the exact bundle name as requested;
|
| + * no fallbacks, do not load parent bundles.
|
| + *
|
| + * This is used for supplemental (non-locale) data.
|
| + */
|
| + URES_OPEN_DIRECT
|
| +};
|
| +typedef enum UResOpenType UResOpenType;
|
| +
|
| +static UResourceDataEntry *entryOpen(const char* path, const char* localeID,
|
| + UResOpenType openType, UErrorCode* status) {
|
| + U_ASSERT(openType != URES_OPEN_DIRECT);
|
| + UErrorCode intStatus = U_ZERO_ERROR;
|
| UResourceDataEntry *r = NULL;
|
| UResourceDataEntry *t1 = NULL;
|
| - UResourceDataEntry *t2 = NULL;
|
| - UResourceDataEntry *u1 = NULL;
|
| - UResourceDataEntry *u2 = NULL;
|
| UBool isDefault = FALSE;
|
| UBool isRoot = FALSE;
|
| UBool hasRealData = FALSE;
|
| @@ -550,7 +644,8 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr
|
| t1 = r;
|
| hasRealData = TRUE;
|
| if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
|
| - u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
|
| + UErrorCode usrStatus = U_ZERO_ERROR;
|
| + UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
|
| if ( u1 != NULL ) {
|
| if(u1->fBogus == U_ZERO_ERROR) {
|
| u1->fParent = t1;
|
| @@ -561,48 +656,16 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr
|
| }
|
| }
|
| }
|
| - while (hasChopped && !isRoot && t1->fParent == NULL && !t1->fData.noFallback) {
|
| - if ( res_getResource(&t1->fData,"%%Parent") != RES_BOGUS) { /* An explicit parent was found */
|
| - int32_t parentLocaleLen = 0;
|
| - const UChar *parentLocaleName = res_getString(&(t1->fData), res_getResource(&t1->fData,"%%Parent") , &parentLocaleLen);
|
| - if(parentLocaleName != NULL && parentLocaleLen > 0) {
|
| - u_UCharsToChars(parentLocaleName, name, parentLocaleLen+1);
|
| - if ( !uprv_strcmp(name,"root") ) { /* If parent is root, we just terminate the loop */
|
| - hasChopped = FALSE;
|
| - continue;
|
| - }
|
| - }
|
| - }
|
| - /* insert regular parents */
|
| - t2 = init_entry(name, t1->fPath, &parentStatus);
|
| - if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
|
| - usrStatus = U_ZERO_ERROR;
|
| - u2 = init_entry(name, usrDataPath, &usrStatus);
|
| - }
|
| - /* Check for null pointer. */
|
| - if (t2 == NULL || ( usingUSRData && u2 == NULL)) {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| + if (hasChopped && !isRoot) {
|
| + if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
|
| goto finishUnlock;
|
| }
|
| -
|
| - if ( usingUSRData && u2->fBogus == U_ZERO_ERROR ) {
|
| - t1->fParent = u2;
|
| - u2->fParent = t2;
|
| - } else {
|
| - t1->fParent = t2;
|
| - if(usingUSRData) {
|
| - /* the USR override data wasn't found, set it to be deleted */
|
| - u2->fCountExisting = 0;
|
| - }
|
| - }
|
| - t1 = t2;
|
| - hasChopped = chopLocale(name);
|
| }
|
| }
|
|
|
| /* we could have reached this point without having any real data */
|
| /* if that is the case, we need to chain in the default locale */
|
| - if(r==NULL && !isDefault && !isRoot /*&& t1->fParent == NULL*/) {
|
| + if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) {
|
| /* insert default locale */
|
| uprv_strcpy(name, uloc_getDefault());
|
| r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
|
| @@ -611,31 +674,11 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr
|
| t1 = r;
|
| hasRealData = TRUE;
|
| isDefault = TRUE;
|
| - while (hasChopped && t1->fParent == NULL) {
|
| - if ( res_getResource(&t1->fData,"%%Parent") != RES_BOGUS) { /* An explicit parent was found */
|
| - int32_t parentLocaleLen = 0;
|
| - const UChar *parentLocaleName = res_getString(&(t1->fData), res_getResource(&t1->fData,"%%Parent") , &parentLocaleLen);
|
| - if(parentLocaleName != NULL && parentLocaleLen > 0) {
|
| - u_UCharsToChars(parentLocaleName, name, parentLocaleLen+1);
|
| - if ( !uprv_strcmp(name,"root") ) { /* If parent is root, we just terminate the loop */
|
| - hasChopped = FALSE;
|
| - continue;
|
| - }
|
| - }
|
| - }
|
| - /* insert chopped defaults */
|
| - t2 = init_entry(name, t1->fPath, &parentStatus);
|
| - /* Check for null pointer. */
|
| - if (t2 == NULL) {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| + // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path?
|
| + if (hasChopped && !isRoot) {
|
| + if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
|
| goto finishUnlock;
|
| }
|
| -
|
| - if ( res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOGUS) {
|
| - t1->fParent = t2;
|
| - t1 = t2;
|
| - }
|
| - hasChopped = chopLocale(name);
|
| }
|
| }
|
| }
|
| @@ -653,46 +696,89 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr
|
| *status = U_MISSING_RESOURCE_ERROR;
|
| goto finishUnlock;
|
| }
|
| - } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && t1->fParent == NULL && !r->fData.noFallback) {
|
| - /* insert root locale */
|
| - t2 = init_entry(kRootLocaleName, t1->fPath, &parentStatus);
|
| - /* Check for null pointer. */
|
| - if (t2 == NULL) {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| + } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 &&
|
| + t1->fParent == NULL && !r->fData.noFallback) {
|
| + if (!insertRootBundle(t1, status)) {
|
| goto finishUnlock;
|
| }
|
| if(!hasRealData) {
|
| r->fBogus = U_USING_DEFAULT_WARNING;
|
| }
|
| - hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) || hasRealData);
|
| - t1->fParent = t2;
|
| - t1 = t2;
|
| }
|
|
|
| + // TODO: Does this ever loop?
|
| while(r != NULL && !isRoot && t1->fParent != NULL) {
|
| t1->fParent->fCountExisting++;
|
| t1 = t1->fParent;
|
| - hasRealData = (UBool)((t1->fBogus == U_ZERO_ERROR) || hasRealData);
|
| }
|
| } /* umtx_lock */
|
| finishUnlock:
|
| umtx_unlock(&resbMutex);
|
|
|
| if(U_SUCCESS(*status)) {
|
| - if(U_SUCCESS(parentStatus)) {
|
| - if(intStatus != U_ZERO_ERROR) {
|
| - *status = intStatus;
|
| - }
|
| - return r;
|
| - } else {
|
| - *status = parentStatus;
|
| - return NULL;
|
| + if(intStatus != U_ZERO_ERROR) {
|
| + *status = intStatus;
|
| }
|
| + return r;
|
| } else {
|
| return NULL;
|
| }
|
| }
|
|
|
| +/**
|
| + * Version of entryOpen() and findFirstExisting() for ures_openDirect(),
|
| + * with no fallbacks.
|
| + * Parent and root locale bundles are loaded if
|
| + * the requested bundle does not have the "nofallback" flag.
|
| + */
|
| +static UResourceDataEntry *
|
| +entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) {
|
| + initCache(status);
|
| + if(U_FAILURE(*status)) {
|
| + return NULL;
|
| + }
|
| +
|
| + umtx_lock(&resbMutex);
|
| + // findFirstExisting() without fallbacks.
|
| + UResourceDataEntry *r = init_entry(localeID, path, status);
|
| + if(U_SUCCESS(*status)) {
|
| + if(r->fBogus != U_ZERO_ERROR) {
|
| + r->fCountExisting--;
|
| + r = NULL;
|
| + }
|
| + } else {
|
| + r = NULL;
|
| + }
|
| +
|
| + // Some code depends on the ures_openDirect() bundle to have a parent bundle chain,
|
| + // unless it is marked with "nofallback".
|
| + UResourceDataEntry *t1 = r;
|
| + if(r != NULL && uprv_strcmp(localeID, kRootLocaleName) != 0 && // not root
|
| + r->fParent == NULL && !r->fData.noFallback &&
|
| + uprv_strlen(localeID) < ULOC_FULLNAME_CAPACITY) {
|
| + char name[ULOC_FULLNAME_CAPACITY];
|
| + uprv_strcpy(name, localeID);
|
| + if(!chopLocale(name) || uprv_strcmp(name, kRootLocaleName) == 0 ||
|
| + loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), FALSE, NULL, status)) {
|
| + if(uprv_strcmp(t1->fName, kRootLocaleName) != 0 && t1->fParent == NULL) {
|
| + insertRootBundle(t1, status);
|
| + }
|
| + }
|
| + if(U_FAILURE(*status)) {
|
| + r = NULL;
|
| + }
|
| + }
|
| +
|
| + if(r != NULL) {
|
| + // TODO: Does this ever loop?
|
| + while(t1->fParent != NULL) {
|
| + t1->fParent->fCountExisting++;
|
| + t1 = t1->fParent;
|
| + }
|
| + }
|
| + umtx_unlock(&resbMutex);
|
| + return r;
|
| +}
|
|
|
| /**
|
| * Functions to create and destroy resource bundles.
|
| @@ -2013,172 +2099,93 @@ U_CFUNC const char* ures_getPath(const UResourceBundle* resB) {
|
| }
|
| #endif
|
|
|
| -/* OLD API implementation */
|
| +static UResourceBundle*
|
| +ures_openWithType(UResourceBundle *r, const char* path, const char* localeID,
|
| + UResOpenType openType, UErrorCode* status) {
|
| + if(U_FAILURE(*status)) {
|
| + return NULL;
|
| + }
|
|
|
| -/**
|
| - * API: This function is used to open a resource bundle
|
| - * proper fallback chaining is executed while initialization.
|
| - * The result is stored in cache for later fallback search.
|
| - */
|
| -U_CAPI void U_EXPORT2
|
| -ures_openFillIn(UResourceBundle *r, const char* path,
|
| - const char* localeID, UErrorCode* status) {
|
| - if(r == NULL) {
|
| - *status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - } else {
|
| - UResourceDataEntry *firstData;
|
| - UBool isStackObject = ures_isStackObject(r);
|
| + UResourceDataEntry *entry;
|
| + if(openType != URES_OPEN_DIRECT) {
|
| + /* first "canonicalize" the locale ID */
|
| char canonLocaleID[ULOC_FULLNAME_CAPACITY];
|
| -
|
| - uloc_getBaseName(localeID, canonLocaleID, sizeof(canonLocaleID), status);
|
| + uloc_getBaseName(localeID, canonLocaleID, UPRV_LENGTHOF(canonLocaleID), status);
|
| if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) {
|
| *status = U_ILLEGAL_ARGUMENT_ERROR;
|
| - return;
|
| - }
|
| -
|
| - ures_closeBundle(r, FALSE);
|
| - uprv_memset(r, 0, sizeof(UResourceBundle));
|
| - ures_setIsStackObject(r, isStackObject);
|
| - r->fHasFallback = TRUE;
|
| - r->fIsTopLevel = TRUE;
|
| - r->fIndex = -1;
|
| - r->fData = entryOpen(path, canonLocaleID, status);
|
| - if(U_FAILURE(*status)) {
|
| - return;
|
| - }
|
| - /* this is a quick fix to get regular data in bundle - until construction is cleaned up */
|
| - firstData = r->fData;
|
| - while(firstData->fBogus != U_ZERO_ERROR && firstData->fParent != NULL) {
|
| - firstData = firstData->fParent;
|
| + return NULL;
|
| }
|
| - uprv_memcpy(&r->fResData, &firstData->fData, sizeof(ResourceData));
|
| - r->fHasFallback=(UBool)!r->fResData.noFallback;
|
| - r->fRes = r->fResData.rootRes;
|
| - r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
|
| - r->fTopLevelData = r->fData;
|
| + entry = entryOpen(path, canonLocaleID, openType, status);
|
| + } else {
|
| + entry = entryOpenDirect(path, localeID, status);
|
| }
|
| -}
|
| -
|
| -U_CAPI UResourceBundle* U_EXPORT2
|
| -ures_open(const char* path,
|
| - const char* localeID,
|
| - UErrorCode* status)
|
| -{
|
| - char canonLocaleID[ULOC_FULLNAME_CAPACITY];
|
| - UResourceDataEntry *hasData = NULL;
|
| - UResourceBundle *r;
|
| -
|
| - if(status == NULL || U_FAILURE(*status)) {
|
| + if(U_FAILURE(*status)) {
|
| return NULL;
|
| }
|
| -
|
| - /* first "canonicalize" the locale ID */
|
| - uloc_getBaseName(localeID, canonLocaleID, sizeof(canonLocaleID), status);
|
| - if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) {
|
| - *status = U_ILLEGAL_ARGUMENT_ERROR;
|
| + if(entry == NULL) {
|
| + *status = U_MISSING_RESOURCE_ERROR;
|
| return NULL;
|
| }
|
|
|
| - r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
|
| + UBool isStackObject;
|
| if(r == NULL) {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| - return NULL;
|
| - }
|
| -
|
| - uprv_memset(r, 0, sizeof(UResourceBundle));
|
| - r->fHasFallback = TRUE;
|
| - r->fIsTopLevel = TRUE;
|
| - ures_setIsStackObject(r, FALSE);
|
| - r->fIndex = -1;
|
| - r->fData = entryOpen(path, canonLocaleID, status);
|
| - if(U_FAILURE(*status)) {
|
| - uprv_free(r);
|
| - return NULL;
|
| - }
|
| - r->fTopLevelData = r->fData;
|
| -
|
| - hasData = r->fData;
|
| - while(hasData->fBogus != U_ZERO_ERROR) {
|
| - hasData = hasData->fParent;
|
| - if(hasData == NULL) {
|
| - /* This can happen only if fallback chain gets broken by an act of God */
|
| - /* TODO: this unlikely to happen, consider removing it */
|
| - entryClose(r->fData);
|
| - uprv_free(r);
|
| - *status = U_MISSING_RESOURCE_ERROR;
|
| + r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
|
| + if(r == NULL) {
|
| + entryClose(entry);
|
| + *status = U_MEMORY_ALLOCATION_ERROR;
|
| return NULL;
|
| }
|
| + isStackObject = FALSE;
|
| + } else { // fill-in
|
| + isStackObject = ures_isStackObject(r);
|
| + ures_closeBundle(r, FALSE);
|
| }
|
| + uprv_memset(r, 0, sizeof(UResourceBundle));
|
| + ures_setIsStackObject(r, isStackObject);
|
|
|
| - uprv_memcpy(&r->fResData, &hasData->fData, sizeof(ResourceData));
|
| - r->fHasFallback=(UBool)!r->fResData.noFallback;
|
| + r->fTopLevelData = r->fData = entry;
|
| + uprv_memcpy(&r->fResData, &entry->fData, sizeof(ResourceData));
|
| + r->fHasFallback = openType != URES_OPEN_DIRECT && !r->fResData.noFallback;
|
| + r->fIsTopLevel = TRUE;
|
| r->fRes = r->fResData.rootRes;
|
| r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
|
| - /*
|
| - 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);
|
| - }
|
| - */
|
| -
|
| + r->fIndex = -1;
|
|
|
| return r;
|
| }
|
|
|
| +U_CAPI UResourceBundle* U_EXPORT2
|
| +ures_open(const char* path, const char* localeID, UErrorCode* status) {
|
| + return ures_openWithType(NULL, path, localeID, URES_OPEN_LOCALE_DEFAULT_ROOT, status);
|
| +}
|
| +
|
| +U_CAPI UResourceBundle* U_EXPORT2
|
| +ures_openNoDefault(const char* path, const char* localeID, UErrorCode* status) {
|
| + return ures_openWithType(NULL, path, localeID, URES_OPEN_LOCALE_ROOT, status);
|
| +}
|
| +
|
| /**
|
| * Opens a resource bundle without "canonicalizing" the locale name. No fallback will be performed
|
| * or sought. However, alias substitution will happen!
|
| */
|
| U_CAPI UResourceBundle* U_EXPORT2
|
| ures_openDirect(const char* path, const char* localeID, UErrorCode* status) {
|
| - UResourceBundle *r;
|
| - UErrorCode subStatus = U_ZERO_ERROR;
|
| -
|
| - if(status == NULL || U_FAILURE(*status)) {
|
| - return NULL;
|
| - }
|
| -
|
| - r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
|
| - if(r == NULL) {
|
| - *status = U_MEMORY_ALLOCATION_ERROR;
|
| - return NULL;
|
| - }
|
| + return ures_openWithType(NULL, path, localeID, URES_OPEN_DIRECT, status);
|
| +}
|
|
|
| - r->fHasFallback = FALSE;
|
| - r->fIsTopLevel = TRUE;
|
| - ures_setIsStackObject(r, FALSE);
|
| - r->fIndex = -1;
|
| - r->fData = entryOpen(path, localeID, &subStatus);
|
| - if(U_FAILURE(subStatus)) {
|
| - *status = subStatus;
|
| - uprv_free(r);
|
| - return NULL;
|
| - }
|
| - if(subStatus != U_ZERO_ERROR /*r->fData->fBogus != U_ZERO_ERROR*/) {
|
| - /* we didn't find one we were looking for - so openDirect */
|
| - /* should fail */
|
| - entryClose(r->fData);
|
| - uprv_free(r);
|
| - *status = U_MISSING_RESOURCE_ERROR;
|
| - return NULL;
|
| +/**
|
| + * API: This function is used to open a resource bundle
|
| + * proper fallback chaining is executed while initialization.
|
| + * The result is stored in cache for later fallback search.
|
| + */
|
| +U_CAPI void U_EXPORT2
|
| +ures_openFillIn(UResourceBundle *r, const char* path,
|
| + const char* localeID, UErrorCode* status) {
|
| + if(U_SUCCESS(*status) && r == NULL) {
|
| + *status = U_ILLEGAL_ARGUMENT_ERROR;
|
| + return;
|
| }
|
| -
|
| - r->fKey = NULL;
|
| - r->fVersion = NULL;
|
| - uprv_memcpy(&r->fResData, &r->fData->fData, sizeof(ResourceData));
|
| - /* r->fHasFallback remains FALSE here in ures_openDirect() */
|
| - r->fRes = r->fResData.rootRes;
|
| - /*r->fParent = RES_BOGUS;*/
|
| - r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
|
| - r->fResPath = NULL;
|
| - r->fResPathLen = 0;
|
| - /*r->fParentRes = NULL;*/
|
| - r->fTopLevelData = r->fData;
|
| -
|
| - return r;
|
| + ures_openWithType(r, path, localeID, URES_OPEN_LOCALE_DEFAULT_ROOT, status);
|
| }
|
|
|
| /**
|
|
|