1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/numsys.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,331 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 2010-2013, International Business Machines Corporation and 1.7 +* others. All Rights Reserved. 1.8 +******************************************************************************* 1.9 +* 1.10 +* 1.11 +* File NUMSYS.CPP 1.12 +* 1.13 +* Modification History:* 1.14 +* Date Name Description 1.15 +* 1.16 +******************************************************************************** 1.17 +*/ 1.18 + 1.19 +#include "unicode/utypes.h" 1.20 +#include "unicode/localpointer.h" 1.21 +#include "unicode/uchar.h" 1.22 +#include "unicode/unistr.h" 1.23 +#include "unicode/ures.h" 1.24 +#include "unicode/ustring.h" 1.25 +#include "unicode/uloc.h" 1.26 +#include "unicode/schriter.h" 1.27 +#include "unicode/numsys.h" 1.28 +#include "cstring.h" 1.29 +#include "uresimp.h" 1.30 +#include "numsys_impl.h" 1.31 + 1.32 +#if !UCONFIG_NO_FORMATTING 1.33 + 1.34 +U_NAMESPACE_BEGIN 1.35 + 1.36 +// Useful constants 1.37 + 1.38 +#define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789"); 1.39 +static const char gNumberingSystems[] = "numberingSystems"; 1.40 +static const char gNumberElements[] = "NumberElements"; 1.41 +static const char gDefault[] = "default"; 1.42 +static const char gNative[] = "native"; 1.43 +static const char gTraditional[] = "traditional"; 1.44 +static const char gFinance[] = "finance"; 1.45 +static const char gDesc[] = "desc"; 1.46 +static const char gRadix[] = "radix"; 1.47 +static const char gAlgorithmic[] = "algorithmic"; 1.48 +static const char gLatn[] = "latn"; 1.49 + 1.50 + 1.51 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem) 1.52 +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumsysNameEnumeration) 1.53 + 1.54 + /** 1.55 + * Default Constructor. 1.56 + * 1.57 + * @draft ICU 4.2 1.58 + */ 1.59 + 1.60 +NumberingSystem::NumberingSystem() { 1.61 + radix = 10; 1.62 + algorithmic = FALSE; 1.63 + UnicodeString defaultDigits = DEFAULT_DIGITS; 1.64 + desc.setTo(defaultDigits); 1.65 + uprv_strcpy(name,gLatn); 1.66 +} 1.67 + 1.68 + /** 1.69 + * Copy constructor. 1.70 + * @draft ICU 4.2 1.71 + */ 1.72 + 1.73 +NumberingSystem::NumberingSystem(const NumberingSystem& other) 1.74 +: UObject(other) { 1.75 + *this=other; 1.76 +} 1.77 + 1.78 +NumberingSystem* U_EXPORT2 1.79 +NumberingSystem::createInstance(int32_t radix_in, UBool isAlgorithmic_in, const UnicodeString & desc_in, UErrorCode &status) { 1.80 + 1.81 + if (U_FAILURE(status)) { 1.82 + return NULL; 1.83 + } 1.84 + 1.85 + if ( radix_in < 2 ) { 1.86 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.87 + return NULL; 1.88 + } 1.89 + 1.90 + if ( !isAlgorithmic_in ) { 1.91 + if ( desc_in.countChar32() != radix_in || !isValidDigitString(desc_in)) { 1.92 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.93 + return NULL; 1.94 + } 1.95 + } 1.96 + 1.97 + NumberingSystem *ns = new NumberingSystem(); 1.98 + 1.99 + ns->setRadix(radix_in); 1.100 + ns->setDesc(desc_in); 1.101 + ns->setAlgorithmic(isAlgorithmic_in); 1.102 + ns->setName(NULL); 1.103 + return ns; 1.104 + 1.105 +} 1.106 + 1.107 + 1.108 +NumberingSystem* U_EXPORT2 1.109 +NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { 1.110 + 1.111 + if (U_FAILURE(status)) { 1.112 + return NULL; 1.113 + } 1.114 + 1.115 + UBool nsResolved = TRUE; 1.116 + UBool usingFallback = FALSE; 1.117 + char buffer[ULOC_KEYWORDS_CAPACITY]; 1.118 + int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status); 1.119 + if ( count > 0 ) { // @numbers keyword was specified in the locale 1.120 + buffer[count] = '\0'; // Make sure it is null terminated. 1.121 + if ( !uprv_strcmp(buffer,gDefault) || !uprv_strcmp(buffer,gNative) || 1.122 + !uprv_strcmp(buffer,gTraditional) || !uprv_strcmp(buffer,gFinance)) { 1.123 + nsResolved = FALSE; 1.124 + } 1.125 + } else { 1.126 + uprv_strcpy(buffer,gDefault); 1.127 + nsResolved = FALSE; 1.128 + } 1.129 + 1.130 + if (!nsResolved) { // Resolve the numbering system ( default, native, traditional or finance ) into a "real" numbering system 1.131 + UErrorCode localStatus = U_ZERO_ERROR; 1.132 + UResourceBundle *resource = ures_open(NULL, inLocale.getName(), &localStatus); 1.133 + UResourceBundle *numberElementsRes = ures_getByKey(resource,gNumberElements,NULL,&localStatus); 1.134 + while (!nsResolved) { 1.135 + localStatus = U_ZERO_ERROR; 1.136 + count = 0; 1.137 + const UChar *nsName = ures_getStringByKeyWithFallback(numberElementsRes, buffer, &count, &localStatus); 1.138 + if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // numbering system found 1.139 + u_UCharsToChars(nsName,buffer,count); 1.140 + buffer[count] = '\0'; // Make sure it is null terminated. 1.141 + nsResolved = TRUE; 1.142 + } 1.143 + 1.144 + if (!nsResolved) { // Fallback behavior per TR35 - traditional falls back to native, finance and native fall back to default 1.145 + if (!uprv_strcmp(buffer,gNative) || !uprv_strcmp(buffer,gFinance)) { 1.146 + uprv_strcpy(buffer,gDefault); 1.147 + } else if (!uprv_strcmp(buffer,gTraditional)) { 1.148 + uprv_strcpy(buffer,gNative); 1.149 + } else { // If we get here we couldn't find even the default numbering system 1.150 + usingFallback = TRUE; 1.151 + nsResolved = TRUE; 1.152 + } 1.153 + } 1.154 + } 1.155 + ures_close(numberElementsRes); 1.156 + ures_close(resource); 1.157 + } 1.158 + 1.159 + if (usingFallback) { 1.160 + status = U_USING_FALLBACK_WARNING; 1.161 + NumberingSystem *ns = new NumberingSystem(); 1.162 + return ns; 1.163 + } else { 1.164 + return NumberingSystem::createInstanceByName(buffer,status); 1.165 + } 1.166 + } 1.167 + 1.168 +NumberingSystem* U_EXPORT2 1.169 +NumberingSystem::createInstance(UErrorCode& status) { 1.170 + return NumberingSystem::createInstance(Locale::getDefault(), status); 1.171 +} 1.172 + 1.173 +NumberingSystem* U_EXPORT2 1.174 +NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) { 1.175 + UResourceBundle *numberingSystemsInfo = NULL; 1.176 + UResourceBundle *nsTop, *nsCurrent; 1.177 + int32_t radix = 10; 1.178 + int32_t algorithmic = 0; 1.179 + 1.180 + numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status); 1.181 + nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status); 1.182 + nsTop = ures_getByKey(nsCurrent,name,NULL,&status); 1.183 + UnicodeString nsd = ures_getUnicodeStringByKey(nsTop,gDesc,&status); 1.184 + 1.185 + ures_getByKey(nsTop,gRadix,nsCurrent,&status); 1.186 + radix = ures_getInt(nsCurrent,&status); 1.187 + 1.188 + ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status); 1.189 + algorithmic = ures_getInt(nsCurrent,&status); 1.190 + 1.191 + UBool isAlgorithmic = ( algorithmic == 1 ); 1.192 + 1.193 + ures_close(nsCurrent); 1.194 + ures_close(nsTop); 1.195 + ures_close(numberingSystemsInfo); 1.196 + 1.197 + if (U_FAILURE(status)) { 1.198 + status = U_UNSUPPORTED_ERROR; 1.199 + return NULL; 1.200 + } 1.201 + 1.202 + NumberingSystem* ns = NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status); 1.203 + ns->setName(name); 1.204 + return ns; 1.205 +} 1.206 + 1.207 + /** 1.208 + * Destructor. 1.209 + * @draft ICU 4.2 1.210 + */ 1.211 +NumberingSystem::~NumberingSystem() { 1.212 +} 1.213 + 1.214 +int32_t NumberingSystem::getRadix() const { 1.215 + return radix; 1.216 +} 1.217 + 1.218 +UnicodeString NumberingSystem::getDescription() const { 1.219 + return desc; 1.220 +} 1.221 + 1.222 +const char * NumberingSystem::getName() const { 1.223 + return name; 1.224 +} 1.225 + 1.226 +void NumberingSystem::setRadix(int32_t r) { 1.227 + radix = r; 1.228 +} 1.229 + 1.230 +void NumberingSystem::setAlgorithmic(UBool c) { 1.231 + algorithmic = c; 1.232 +} 1.233 + 1.234 +void NumberingSystem::setDesc(UnicodeString d) { 1.235 + desc.setTo(d); 1.236 +} 1.237 +void NumberingSystem::setName(const char *n) { 1.238 + if ( n == NULL ) { 1.239 + name[0] = (char) 0; 1.240 + } else { 1.241 + uprv_strncpy(name,n,NUMSYS_NAME_CAPACITY); 1.242 + name[NUMSYS_NAME_CAPACITY] = (char)0; // Make sure it is null terminated. 1.243 + } 1.244 +} 1.245 +UBool NumberingSystem::isAlgorithmic() const { 1.246 + return ( algorithmic ); 1.247 +} 1.248 + 1.249 +StringEnumeration* NumberingSystem::getAvailableNames(UErrorCode &status) { 1.250 + 1.251 + static StringEnumeration* availableNames = NULL; 1.252 + 1.253 + if (U_FAILURE(status)) { 1.254 + return NULL; 1.255 + } 1.256 + 1.257 + if ( availableNames == NULL ) { 1.258 + UVector *fNumsysNames = new UVector(uprv_deleteUObject, NULL, status); 1.259 + if (U_FAILURE(status)) { 1.260 + status = U_MEMORY_ALLOCATION_ERROR; 1.261 + return NULL; 1.262 + } 1.263 + 1.264 + UErrorCode rbstatus = U_ZERO_ERROR; 1.265 + UResourceBundle *numberingSystemsInfo = ures_openDirect(NULL, "numberingSystems", &rbstatus); 1.266 + numberingSystemsInfo = ures_getByKey(numberingSystemsInfo,"numberingSystems",numberingSystemsInfo,&rbstatus); 1.267 + if(U_FAILURE(rbstatus)) { 1.268 + status = U_MISSING_RESOURCE_ERROR; 1.269 + ures_close(numberingSystemsInfo); 1.270 + return NULL; 1.271 + } 1.272 + 1.273 + while ( ures_hasNext(numberingSystemsInfo) ) { 1.274 + UResourceBundle *nsCurrent = ures_getNextResource(numberingSystemsInfo,NULL,&rbstatus); 1.275 + const char *nsName = ures_getKey(nsCurrent); 1.276 + fNumsysNames->addElement(new UnicodeString(nsName, -1, US_INV),status); 1.277 + ures_close(nsCurrent); 1.278 + } 1.279 + 1.280 + ures_close(numberingSystemsInfo); 1.281 + availableNames = new NumsysNameEnumeration(fNumsysNames,status); 1.282 + 1.283 + } 1.284 + 1.285 + return availableNames; 1.286 +} 1.287 + 1.288 +UBool NumberingSystem::isValidDigitString(const UnicodeString& str) { 1.289 + 1.290 + StringCharacterIterator it(str); 1.291 + UChar32 c; 1.292 + int32_t i = 0; 1.293 + 1.294 + for ( it.setToStart(); it.hasNext(); ) { 1.295 + c = it.next32PostInc(); 1.296 + if ( c > 0xFFFF ) { // Digits outside the BMP are not currently supported 1.297 + return FALSE; 1.298 + } 1.299 + i++; 1.300 + } 1.301 + return TRUE; 1.302 +} 1.303 + 1.304 +NumsysNameEnumeration::NumsysNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) { 1.305 + pos=0; 1.306 + fNumsysNames = fNameList; 1.307 +} 1.308 + 1.309 +const UnicodeString* 1.310 +NumsysNameEnumeration::snext(UErrorCode& status) { 1.311 + if (U_SUCCESS(status) && pos < fNumsysNames->size()) { 1.312 + return (const UnicodeString*)fNumsysNames->elementAt(pos++); 1.313 + } 1.314 + return NULL; 1.315 +} 1.316 + 1.317 +void 1.318 +NumsysNameEnumeration::reset(UErrorCode& /*status*/) { 1.319 + pos=0; 1.320 +} 1.321 + 1.322 +int32_t 1.323 +NumsysNameEnumeration::count(UErrorCode& /*status*/) const { 1.324 + return (fNumsysNames==NULL) ? 0 : fNumsysNames->size(); 1.325 +} 1.326 + 1.327 +NumsysNameEnumeration::~NumsysNameEnumeration() { 1.328 + delete fNumsysNames; 1.329 +} 1.330 +U_NAMESPACE_END 1.331 + 1.332 +#endif /* #if !UCONFIG_NO_FORMATTING */ 1.333 + 1.334 +//eof