Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2010, International Business Machines Corporation and
      4 * others. All Rights Reserved.
      5 *******************************************************************************
      6 *
      7 *
      8 * File NUMSYS.CPP
      9 *
     10 * Modification History:*
     11 *   Date        Name        Description
     12 *
     13 ********************************************************************************
     14 */
     15 
     16 #include "unicode/utypes.h"
     17 #include "unicode/localpointer.h"
     18 #include "unicode/uchar.h"
     19 #include "unicode/unistr.h"
     20 #include "unicode/ures.h"
     21 #include "unicode/ustring.h"
     22 #include "unicode/uloc.h"
     23 #include "unicode/schriter.h"
     24 #include "unicode/numsys.h"
     25 #include "cstring.h"
     26 #include "uresimp.h"
     27 
     28 #if !UCONFIG_NO_FORMATTING
     29 
     30 U_NAMESPACE_BEGIN
     31 
     32 // Useful constants
     33 
     34 #define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789");
     35 static const char gNumberingSystems[] = "numberingSystems";
     36 static const char gNumberElements[] = "NumberElements";
     37 static const char gDefault[] = "default";
     38 static const char gDesc[] = "desc";
     39 static const char gRadix[] = "radix";
     40 static const char gAlgorithmic[] = "algorithmic";
     41 static const char gLatn[] = "latn";
     42 
     43 
     44 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem)
     45 
     46     /**
     47      * Default Constructor.
     48      *
     49      * @draft ICU 4.2
     50      */
     51 
     52 NumberingSystem::NumberingSystem() {
     53      radix = 10;
     54      algorithmic = FALSE;
     55      UnicodeString defaultDigits = DEFAULT_DIGITS;
     56      desc.setTo(defaultDigits);
     57      uprv_strcpy(name,gLatn);
     58 }
     59 
     60     /**
     61      * Copy constructor.
     62      * @draft ICU 4.2
     63      */
     64 
     65 NumberingSystem::NumberingSystem(const NumberingSystem& other)
     66 :  UObject(other) {
     67     *this=other;
     68 }
     69 
     70 NumberingSystem* U_EXPORT2
     71 NumberingSystem::createInstance(int32_t radix_in, UBool isAlgorithmic_in, const UnicodeString & desc_in, UErrorCode &status) {
     72 
     73     if (U_FAILURE(status)) {
     74         return NULL;
     75     }
     76 
     77     if ( radix_in < 2 ) {
     78         status = U_ILLEGAL_ARGUMENT_ERROR;
     79         return NULL;
     80     }
     81 
     82     if ( !isAlgorithmic_in ) {
     83        if ( desc_in.countChar32() != radix_in || !isValidDigitString(desc_in)) {
     84            status = U_ILLEGAL_ARGUMENT_ERROR;
     85            return NULL;
     86        }
     87     }
     88 
     89     NumberingSystem *ns = new NumberingSystem();
     90 
     91     ns->setRadix(radix_in);
     92     ns->setDesc(desc_in);
     93     ns->setAlgorithmic(isAlgorithmic_in);
     94     ns->setName(NULL);
     95     return ns;
     96 
     97 }
     98 
     99 
    100 NumberingSystem* U_EXPORT2
    101 NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) {
    102 
    103     if (U_FAILURE(status)) {
    104         return NULL;
    105     }
    106 
    107     char buffer[ULOC_KEYWORDS_CAPACITY];
    108     int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status);
    109     if ( count > 0 ) { // @numbers keyword was specified in the locale
    110         buffer[count] = '\0'; // Make sure it is null terminated.
    111         return NumberingSystem::createInstanceByName(buffer,status);
    112     } else { // Find the default numbering system for this locale.
    113         UResourceBundle *resource = ures_open(NULL, inLocale.getName(), &status);
    114         UResourceBundle *numberElementsRes = ures_getByKey(resource,gNumberElements,NULL,&status);
    115         const UChar *defaultNSName =
    116             ures_getStringByKeyWithFallback(numberElementsRes, gDefault, &count, &status);
    117         ures_close(numberElementsRes);
    118         ures_close(resource);
    119 
    120         if (U_FAILURE(status)) {
    121             status = U_USING_FALLBACK_WARNING;
    122             NumberingSystem *ns = new NumberingSystem();
    123             return ns;
    124         }
    125 
    126         if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // Default numbering system found
    127            u_UCharsToChars(defaultNSName,buffer,count);
    128            buffer[count] = '\0'; // Make sure it is null terminated.
    129            return NumberingSystem::createInstanceByName(buffer,status);
    130         } else {
    131             status = U_USING_FALLBACK_WARNING;
    132             NumberingSystem *ns = new NumberingSystem();
    133             return ns;
    134         }
    135 
    136     }
    137 }
    138 
    139 NumberingSystem* U_EXPORT2
    140 NumberingSystem::createInstance(UErrorCode& status) {
    141     return NumberingSystem::createInstance(Locale::getDefault(), status);
    142 }
    143 
    144 NumberingSystem* U_EXPORT2
    145 NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) {
    146 
    147      UResourceBundle *numberingSystemsInfo = NULL;
    148      UResourceBundle *nsTop, *nsCurrent;
    149      const UChar* description = NULL;
    150      int32_t radix = 10;
    151      int32_t algorithmic = 0;
    152      int32_t len;
    153 
    154      numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status);
    155      nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status);
    156      nsTop = ures_getByKey(nsCurrent,name,NULL,&status);
    157      description = ures_getStringByKey(nsTop,gDesc,&len,&status);
    158 
    159 	 ures_getByKey(nsTop,gRadix,nsCurrent,&status);
    160      radix = ures_getInt(nsCurrent,&status);
    161 
    162      ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status);
    163      algorithmic = ures_getInt(nsCurrent,&status);
    164 
    165      UBool isAlgorithmic = ( algorithmic == 1 );
    166      UnicodeString nsd;
    167      nsd.setTo(description);
    168 
    169 	 ures_close(nsCurrent);
    170 	 ures_close(nsTop);
    171      ures_close(numberingSystemsInfo);
    172 
    173      if (U_FAILURE(status)) {
    174          status = U_UNSUPPORTED_ERROR;
    175          return NULL;
    176      }
    177 
    178      NumberingSystem* ns = NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status);
    179      ns->setName(name);
    180      return ns;
    181 }
    182 
    183     /**
    184      * Destructor.
    185      * @draft ICU 4.2
    186      */
    187 NumberingSystem::~NumberingSystem() {
    188 }
    189 
    190 int32_t NumberingSystem::getRadix() {
    191     return radix;
    192 }
    193 
    194 UnicodeString NumberingSystem::getDescription() {
    195     return desc;
    196 }
    197 
    198 const char * NumberingSystem::getName() {
    199     return name;
    200 }
    201 
    202 void NumberingSystem::setRadix(int32_t r) {
    203     radix = r;
    204 }
    205 
    206 void NumberingSystem::setAlgorithmic(UBool c) {
    207     algorithmic = c;
    208 }
    209 
    210 void NumberingSystem::setDesc(UnicodeString d) {
    211     desc.setTo(d);
    212 }
    213 void NumberingSystem::setName(const char *n) {
    214     if ( n == NULL ) {
    215         name[0] = (char) 0;
    216     } else {
    217         uprv_strncpy(name,n,NUMSYS_NAME_CAPACITY);
    218         name[NUMSYS_NAME_CAPACITY] = (char)0; // Make sure it is null terminated.
    219     }
    220 }
    221 UBool NumberingSystem::isAlgorithmic() const {
    222     return ( algorithmic );
    223 }
    224 
    225 
    226 UBool NumberingSystem::isValidDigitString(const UnicodeString& str) {
    227 
    228     StringCharacterIterator it(str);
    229     UChar32 c;
    230     UChar32 prev = 0;
    231     int32_t i = 0;
    232 
    233     for ( it.setToStart(); it.hasNext(); ) {
    234        c = it.next32PostInc();
    235        if ( c > 0xFFFF ) { // Digits outside the BMP are not currently supported
    236           return FALSE;
    237        }
    238        i++;
    239        prev = c;
    240     }
    241     return TRUE;
    242 }
    243 U_NAMESPACE_END
    244 
    245 #endif /* #if !UCONFIG_NO_FORMATTING */
    246 
    247 //eof
    248