X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/729e4ab9bc6618bc3d8a898e575df7f4019e29ca..08b89b0a244153b9f5bbb2f49c55ab0f7298122e:/icuSources/i18n/numsys.cpp diff --git a/icuSources/i18n/numsys.cpp b/icuSources/i18n/numsys.cpp index 534ed156..288cc563 100644 --- a/icuSources/i18n/numsys.cpp +++ b/icuSources/i18n/numsys.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 2010, International Business Machines Corporation and +* Copyright (C) 2010-2013, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* * @@ -24,6 +24,7 @@ #include "unicode/numsys.h" #include "cstring.h" #include "uresimp.h" +#include "numsys_impl.h" #if !UCONFIG_NO_FORMATTING @@ -35,6 +36,9 @@ U_NAMESPACE_BEGIN static const char gNumberingSystems[] = "numberingSystems"; static const char gNumberElements[] = "NumberElements"; static const char gDefault[] = "default"; +static const char gNative[] = "native"; +static const char gTraditional[] = "traditional"; +static const char gFinance[] = "finance"; static const char gDesc[] = "desc"; static const char gRadix[] = "radix"; static const char gAlgorithmic[] = "algorithmic"; @@ -42,6 +46,7 @@ static const char gLatn[] = "latn"; UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem) +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumsysNameEnumeration) /** * Default Constructor. @@ -102,39 +107,60 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { if (U_FAILURE(status)) { return NULL; - } + } + UBool nsResolved = TRUE; + UBool usingFallback = FALSE; char buffer[ULOC_KEYWORDS_CAPACITY]; int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status); if ( count > 0 ) { // @numbers keyword was specified in the locale buffer[count] = '\0'; // Make sure it is null terminated. - return NumberingSystem::createInstanceByName(buffer,status); - } else { // Find the default numbering system for this locale. - UResourceBundle *resource = ures_open(NULL, inLocale.getName(), &status); - UResourceBundle *numberElementsRes = ures_getByKey(resource,gNumberElements,NULL,&status); - const UChar *defaultNSName = - ures_getStringByKeyWithFallback(numberElementsRes, gDefault, &count, &status); + if ( !uprv_strcmp(buffer,gDefault) || !uprv_strcmp(buffer,gNative) || + !uprv_strcmp(buffer,gTraditional) || !uprv_strcmp(buffer,gFinance)) { + nsResolved = FALSE; + } + } else { + uprv_strcpy(buffer,gDefault); + nsResolved = FALSE; + } + + if (!nsResolved) { // Resolve the numbering system ( default, native, traditional or finance ) into a "real" numbering system + UErrorCode localStatus = U_ZERO_ERROR; + UResourceBundle *resource = ures_open(NULL, inLocale.getName(), &localStatus); + UResourceBundle *numberElementsRes = ures_getByKey(resource,gNumberElements,NULL,&localStatus); + while (!nsResolved) { + localStatus = U_ZERO_ERROR; + count = 0; + const UChar *nsName = ures_getStringByKeyWithFallback(numberElementsRes, buffer, &count, &localStatus); + if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // numbering system found + u_UCharsToChars(nsName,buffer,count); + buffer[count] = '\0'; // Make sure it is null terminated. + nsResolved = TRUE; + } + + if (!nsResolved) { // Fallback behavior per TR35 - traditional falls back to native, finance and native fall back to default + if (!uprv_strcmp(buffer,gNative) || !uprv_strcmp(buffer,gFinance)) { + uprv_strcpy(buffer,gDefault); + } else if (!uprv_strcmp(buffer,gTraditional)) { + uprv_strcpy(buffer,gNative); + } else { // If we get here we couldn't find even the default numbering system + usingFallback = TRUE; + nsResolved = TRUE; + } + } + } ures_close(numberElementsRes); ures_close(resource); + } - if (U_FAILURE(status)) { - status = U_USING_FALLBACK_WARNING; - NumberingSystem *ns = new NumberingSystem(); - return ns; - } - - if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // Default numbering system found - u_UCharsToChars(defaultNSName,buffer,count); - buffer[count] = '\0'; // Make sure it is null terminated. - return NumberingSystem::createInstanceByName(buffer,status); - } else { - status = U_USING_FALLBACK_WARNING; - NumberingSystem *ns = new NumberingSystem(); - return ns; - } - + if (usingFallback) { + status = U_USING_FALLBACK_WARNING; + NumberingSystem *ns = new NumberingSystem(); + return ns; + } else { + return NumberingSystem::createInstanceByName(buffer,status); } -} + } NumberingSystem* U_EXPORT2 NumberingSystem::createInstance(UErrorCode& status) { @@ -143,41 +169,36 @@ NumberingSystem::createInstance(UErrorCode& status) { NumberingSystem* U_EXPORT2 NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) { - - UResourceBundle *numberingSystemsInfo = NULL; - UResourceBundle *nsTop, *nsCurrent; - const UChar* description = NULL; - int32_t radix = 10; - int32_t algorithmic = 0; - int32_t len; + UResourceBundle *numberingSystemsInfo = NULL; + UResourceBundle *nsTop, *nsCurrent; + int32_t radix = 10; + int32_t algorithmic = 0; - numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status); - nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status); - nsTop = ures_getByKey(nsCurrent,name,NULL,&status); - description = ures_getStringByKey(nsTop,gDesc,&len,&status); + numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status); + nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status); + nsTop = ures_getByKey(nsCurrent,name,NULL,&status); + UnicodeString nsd = ures_getUnicodeStringByKey(nsTop,gDesc,&status); - ures_getByKey(nsTop,gRadix,nsCurrent,&status); - radix = ures_getInt(nsCurrent,&status); + ures_getByKey(nsTop,gRadix,nsCurrent,&status); + radix = ures_getInt(nsCurrent,&status); - ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status); - algorithmic = ures_getInt(nsCurrent,&status); + ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status); + algorithmic = ures_getInt(nsCurrent,&status); - UBool isAlgorithmic = ( algorithmic == 1 ); - UnicodeString nsd; - nsd.setTo(description); + UBool isAlgorithmic = ( algorithmic == 1 ); - ures_close(nsCurrent); - ures_close(nsTop); - ures_close(numberingSystemsInfo); + ures_close(nsCurrent); + ures_close(nsTop); + ures_close(numberingSystemsInfo); - if (U_FAILURE(status)) { - status = U_UNSUPPORTED_ERROR; - return NULL; - } + if (U_FAILURE(status)) { + status = U_UNSUPPORTED_ERROR; + return NULL; + } - NumberingSystem* ns = NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status); - ns->setName(name); - return ns; + NumberingSystem* ns = NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status); + ns->setName(name); + return ns; } /** @@ -187,15 +208,15 @@ NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) { NumberingSystem::~NumberingSystem() { } -int32_t NumberingSystem::getRadix() { +int32_t NumberingSystem::getRadix() const { return radix; } -UnicodeString NumberingSystem::getDescription() { +UnicodeString NumberingSystem::getDescription() const { return desc; } -const char * NumberingSystem::getName() { +const char * NumberingSystem::getName() const { return name; } @@ -222,12 +243,49 @@ UBool NumberingSystem::isAlgorithmic() const { return ( algorithmic ); } +StringEnumeration* NumberingSystem::getAvailableNames(UErrorCode &status) { + + static StringEnumeration* availableNames = NULL; + + if (U_FAILURE(status)) { + return NULL; + } + + if ( availableNames == NULL ) { + UVector *fNumsysNames = new UVector(uprv_deleteUObject, NULL, status); + if (U_FAILURE(status)) { + status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + + UErrorCode rbstatus = U_ZERO_ERROR; + UResourceBundle *numberingSystemsInfo = ures_openDirect(NULL, "numberingSystems", &rbstatus); + numberingSystemsInfo = ures_getByKey(numberingSystemsInfo,"numberingSystems",numberingSystemsInfo,&rbstatus); + if(U_FAILURE(rbstatus)) { + status = U_MISSING_RESOURCE_ERROR; + ures_close(numberingSystemsInfo); + return NULL; + } + + while ( ures_hasNext(numberingSystemsInfo) ) { + UResourceBundle *nsCurrent = ures_getNextResource(numberingSystemsInfo,NULL,&rbstatus); + const char *nsName = ures_getKey(nsCurrent); + fNumsysNames->addElement(new UnicodeString(nsName, -1, US_INV),status); + ures_close(nsCurrent); + } + + ures_close(numberingSystemsInfo); + availableNames = new NumsysNameEnumeration(fNumsysNames,status); + + } + + return availableNames; +} UBool NumberingSystem::isValidDigitString(const UnicodeString& str) { StringCharacterIterator it(str); UChar32 c; - UChar32 prev = 0; int32_t i = 0; for ( it.setToStart(); it.hasNext(); ) { @@ -236,10 +294,36 @@ UBool NumberingSystem::isValidDigitString(const UnicodeString& str) { return FALSE; } i++; - prev = c; } return TRUE; } + +NumsysNameEnumeration::NumsysNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) { + pos=0; + fNumsysNames = fNameList; +} + +const UnicodeString* +NumsysNameEnumeration::snext(UErrorCode& status) { + if (U_SUCCESS(status) && pos < fNumsysNames->size()) { + return (const UnicodeString*)fNumsysNames->elementAt(pos++); + } + return NULL; +} + +void +NumsysNameEnumeration::reset(UErrorCode& /*status*/) { + pos=0; +} + +int32_t +NumsysNameEnumeration::count(UErrorCode& /*status*/) const { + return (fNumsysNames==NULL) ? 0 : fNumsysNames->size(); +} + +NumsysNameEnumeration::~NumsysNameEnumeration() { + delete fNumsysNames; +} U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */