ICU-10823 add ures_openNoDefault() and use it from collation data loader and BreakIterator; refactor ures_openXyz() for code sharing

X-SVN-Rev: 36806
This commit is contained in:
Markus Scherer 2014-12-04 21:11:26 +00:00
parent ae0b3bc646
commit 326e9592dc
7 changed files with 269 additions and 295 deletions

View file

@ -69,13 +69,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, int32_t kind,
ures_initStackObject(brkName);
// Get the locale
UResourceBundle *b = ures_open(U_ICUDATA_BRKITR, loc.getName(), &status);
/* this is a hack for now. Should be fixed when the data is fetched from
brk_index.txt */
if(status==U_USING_DEFAULT_WARNING){
status=U_ZERO_ERROR;
ures_openFillIn(b, U_ICUDATA_BRKITR, "", &status);
}
UResourceBundle *b = ures_openNoDefault(U_ICUDATA_BRKITR, loc.getName(), &status);
// Get the "boundaries" array.
if (U_SUCCESS(status)) {

View file

@ -446,7 +446,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 +504,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 +643,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 +655,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 +673,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 +695,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 +2098,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;
}
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;
}
}
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)) {
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;
return NULL;
}
r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
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;
return NULL;
}
entry = entryOpen(path, canonLocaleID, openType, status);
} else {
entry = entryOpenDirect(path, localeID, status);
}
if(U_FAILURE(*status)) {
return NULL;
}
if(entry == NULL) {
*status = U_MISSING_RESOURCE_ERROR;
return NULL;
}
uprv_memcpy(&r->fResData, &hasData->fData, sizeof(ResourceData));
r->fHasFallback=(UBool)!r->fResData.noFallback;
UBool isStackObject;
if(r == NULL) {
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);
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;
return ures_openWithType(NULL, path, localeID, URES_OPEN_DIRECT, status);
}
if(status == NULL || 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(U_SUCCESS(*status) && r == NULL) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
if(r == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
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;
}
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);
}
/**

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2000-2011, International Business Machines
* Copyright (C) 2000-2014, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
@ -32,17 +32,6 @@
#define EMPTY_SET 0x2205
/*
enum UResEntryType {
ENTRY_OK = 0,
ENTRY_GOTO_ROOT = 1,
ENTRY_GOTO_DEFAULT = 2,
ENTRY_INVALID = 3
};
typedef enum UResEntryType UResEntryType;
*/
struct UResourceDataEntry;
typedef struct UResourceDataEntry UResourceDataEntry;
@ -91,6 +80,17 @@ struct UResourceBundle {
U_CAPI void U_EXPORT2 ures_initStackObject(UResourceBundle* resB);
/**
* Opens a resource bundle for the locale;
* if there is not even a base language bundle, then loads the root bundle;
* never falls 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).
*/
U_CAPI UResourceBundle* U_EXPORT2
ures_openNoDefault(const char* path, const char* localeID, UErrorCode* status);
/* Some getters used by the copy constructor */
U_CFUNC const char* ures_getName(const UResourceBundle* resB);
#ifdef URES_DEBUG

View file

@ -224,7 +224,7 @@ const CollationCacheEntry *
CollationLoader::loadFromLocale(UErrorCode &errorCode) {
if(U_FAILURE(errorCode)) { return NULL; }
U_ASSERT(bundle == NULL);
bundle = ures_open(U_ICUDATA_COLL, locale.getBaseName(), &errorCode);
bundle = ures_openNoDefault(U_ICUDATA_COLL, locale.getBaseName(), &errorCode);
if(errorCode == U_MISSING_RESOURCE_ERROR) {
errorCode = U_USING_DEFAULT_WARNING;

View file

@ -1446,7 +1446,7 @@ void TestGetLocale() {
ucol_close(coll);
}
/* completely non-existant locale for collator should get a default collator */
/* completely non-existent locale for collator should get a root collator */
{
UCollator *defaultColl = ucol_open(NULL, &status);
coll = ucol_open("blahaha", &status);
@ -1455,15 +1455,13 @@ void TestGetLocale() {
if(strcmp(ucol_getLocaleByType(coll, ULOC_REQUESTED_LOCALE, &status), "blahaha")) {
log_err("Nonexisting locale didn't preserve the requested locale\n");
} */
if(strcmp(ucol_getLocaleByType(coll, ULOC_VALID_LOCALE, &status),
ucol_getLocaleByType(defaultColl, ULOC_VALID_LOCALE, &status))) {
log_err("Valid locale for nonexisting locale locale collator differs "
"from valid locale for default collator\n");
const char *name = ucol_getLocaleByType(coll, ULOC_VALID_LOCALE, &status);
if(*name != 0 && strcmp(name, "root") != 0) {
log_err("Valid locale for nonexisting-locale collator is \"%s\" not root\n", name);
}
if(strcmp(ucol_getLocaleByType(coll, ULOC_ACTUAL_LOCALE, &status),
ucol_getLocaleByType(defaultColl, ULOC_ACTUAL_LOCALE, &status))) {
log_err("Actual locale for nonexisting locale locale collator differs "
"from actual locale for default collator\n");
name = ucol_getLocaleByType(coll, ULOC_ACTUAL_LOCALE, &status);
if(*name != 0 && strcmp(name, "root") != 0) {
log_err("Actual locale for nonexisting-locale collator is \"%s\" not root\n", name);
}
ucol_close(coll);
ucol_close(defaultColl);

View file

@ -494,6 +494,7 @@ static const char *localeAndIndexCharactersLists[][2] = {
/* English*/ {"en", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
/* Spanish*/ {"es", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:\\u00D1:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
/* Estonian*/ {"et", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:\\u0160:Z:\\u017D:T:U:V:\\u00D5:\\u00C4:\\u00D6:\\u00DC:X:Y"},
/* Basque*/ {"eu", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
/* Finnish*/ {"fi", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:\\u00C5:\\u00C4:\\u00D6"},
/* Filipino*/ {"fil", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
/* French*/ {"fr", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
@ -519,15 +520,6 @@ static const char *localeAndIndexCharactersLists[][2] = {
/* Vietnamese*/ {"vi", "A:\\u0102:\\u00C2:B:C:D:\\u0110:E:\\u00CA:F:G:H:I:J:K:L:M:N:O:\\u00D4:\\u01A0:P:Q:R:S:T:U:\\u01AF:V:W:X:Y:Z"},
/* Chinese*/ {"zh", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
/* Chinese (Traditional Han)*/ {"zh_Hant", "1\\u5283:2\\u5283:3\\u5283:4\\u5283:5\\u5283:6\\u5283:7\\u5283:8\\u5283:9\\u5283:10\\u5283:11\\u5283:12\\u5283:13\\u5283:14\\u5283:15\\u5283:16\\u5283:17\\u5283:18\\u5283:19\\u5283:20\\u5283:21\\u5283:22\\u5283:23\\u5283:24\\u5283:25\\u5283:26\\u5283:27\\u5283:28\\u5283:29\\u5283:30\\u5283:31\\u5283:32\\u5283:33\\u5283:35\\u5283:36\\u5283:39\\u5283:48\\u5283"},
// As of ICU 52, ICU does not have collation data for the following language.
// Therefore, constructing an AlphabeticIndex for it
// ends up with a collator for the default locale
// which makes the test unreliable. (see ticket #10277)
// It exposes a bigger problem in that it may not be desirable for collation
// to fall back to the default locale.
// /* Basque*/ {"eu", "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z"},
};
void AlphabeticIndexTest::TestIndexCharactersList() {

View file

@ -191,6 +191,7 @@ CollationAPITest::TestProperty(/* char* par */)
doAssert((col->getStrength() == Collator::TERTIARY), "collation object's strength is not tertiary difference");
doAssert((col->getStrength() != Collator::PRIMARY), "collation object's strength is primary difference");
doAssert((col->getStrength() != Collator::SECONDARY), "collation object's strength is secondary difference");
delete col;
logln("Create junk collation: ");
Locale abcd("ab", "CD", "");
@ -201,26 +202,15 @@ CollationAPITest::TestProperty(/* char* par */)
if (U_FAILURE(success))
{
errln("Junk collation creation failed, should at least return default.");
delete col;
return;
}
delete col;
col = Collator::createInstance(success);
if (U_FAILURE(success))
{
errln("Creating default collator failed.");
delete junk;
return;
}
doAssert(((RuleBasedCollator *)col)->getRules() == ((RuleBasedCollator *)junk)->getRules(),
"The default collation should be returned.");
doAssert(((RuleBasedCollator *)junk)->getRules().isEmpty(),
"The root collation should be returned for an unsupported language.");
Collator *frCol = Collator::createInstance(Locale::getCanadaFrench(), success);
if (U_FAILURE(success))
{
errln("Creating fr_CA collator failed.");
delete col;
delete junk;
return;
}
@ -234,7 +224,6 @@ CollationAPITest::TestProperty(/* char* par */)
doAssert((*frCol == *aFrCol), "The cloning of a fr_CA collator failed.");
logln("Collator property test ended.");
delete col;
delete frCol;
delete aFrCol;
delete junk;
@ -1707,28 +1696,23 @@ void CollationAPITest::TestGetLocale() {
delete coll;
}
/* completely non-existant locale for collator should get a default collator */
/* completely non-existent locale for collator should get a root collator */
{
Collator *defaultColl = Collator::createInstance((const Locale)NULL, status);
coll = Collator::createInstance("blahaha", status);
LocalPointer<Collator> coll(Collator::createInstance("blahaha", status));
if(U_FAILURE(status)) {
errln("Failed to open collator with %s", u_errorName(status));
delete coll;
delete defaultColl;
return;
}
if(coll->getLocale(ULOC_VALID_LOCALE, status) !=
defaultColl->getLocale(ULOC_VALID_LOCALE, status)) {
errln("Valid locale for nonexisting locale locale collator differs "
"from valid locale for default collator");
Locale valid = coll->getLocale(ULOC_VALID_LOCALE, status);
const char *name = valid.getName();
if(*name != 0 && strcmp(name, "root") != 0) {
errln("Valid locale for nonexisting-locale collator is \"%s\" not root", name);
}
if(coll->getLocale(ULOC_ACTUAL_LOCALE, status) !=
defaultColl->getLocale(ULOC_ACTUAL_LOCALE, status)) {
errln("Actual locale for nonexisting locale locale collator differs "
"from actual locale for default collator");
Locale actual = coll->getLocale(ULOC_ACTUAL_LOCALE, status);
name = actual.getName();
if(*name != 0 && strcmp(name, "root") != 0) {
errln("Actual locale for nonexisting-locale collator is \"%s\" not root", name);
}
delete coll;
delete defaultColl;
}