intl/icu/source/i18n/numsys.cpp

changeset 0
6474c204b198
     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

mercurial