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