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         if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // Default numbering system found
    109            u_UCharsToChars(defaultNSName,buffer,count);
    110            buffer[count] = '\0'; // Make sure it is null terminated.
    111            ures_close(resource);
    112            return NumberingSystem::createInstanceByName(buffer,status);
    113         } else {
    114             status = U_USING_FALLBACK_WARNING;
    115             NumberingSystem *ns = new NumberingSystem();
    116             ures_close(resource);
    117             return ns;
    118         }
    119 
    120     }
    121 }
    122 
    123 NumberingSystem* U_EXPORT2
    124 NumberingSystem::createInstance(UErrorCode& status) {
    125     return NumberingSystem::createInstance(Locale::getDefault(), status);
    126 }
    127 
    128 NumberingSystem* U_EXPORT2
    129 NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) {
    130 
    131      UResourceBundle *numberingSystemsInfo = NULL;
    132      UResourceBundle *nsTop, *nsCurrent;
    133      const UChar* description = NULL;
    134      int32_t radix = 10;
    135      int32_t algorithmic = 0;
    136      int32_t len;
    137 
    138      numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status);
    139      nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status);
    140      nsTop = ures_getByKey(nsCurrent,name,NULL,&status);
    141      description = ures_getStringByKey(nsTop,gDesc,&len,&status);
    142 
    143 	 ures_getByKey(nsTop,gRadix,nsCurrent,&status);
    144      radix = ures_getInt(nsCurrent,&status);
    145 
    146      ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status);
    147      algorithmic = ures_getInt(nsCurrent,&status);
    148 
    149      UBool isAlgorithmic = ( algorithmic == 1 );
    150      UnicodeString nsd;
    151      nsd.setTo(description);
    152 
    153 	 ures_close(nsCurrent);
    154 	 ures_close(nsTop);
    155      ures_close(numberingSystemsInfo);
    156 
    157      if (U_FAILURE(status)) {
    158          status = U_UNSUPPORTED_ERROR;
    159          return NULL;
    160      }
    161 
    162      return NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status);
    163 
    164 }
    165 
    166     /**
    167      * Destructor.
    168      * @draft ICU 4.2
    169      */
    170 NumberingSystem::~NumberingSystem() {
    171 }
    172 
    173 int32_t NumberingSystem::getRadix() {
    174     return radix;
    175 }
    176 
    177 UnicodeString NumberingSystem::getDescription() {
    178     return desc;
    179 }
    180 
    181 void NumberingSystem::setRadix(int32_t r) {
    182     radix = r;
    183 }
    184 
    185 void NumberingSystem::setAlgorithmic(UBool c) {
    186     algorithmic = c;
    187 }
    188 
    189 void NumberingSystem::setDesc(UnicodeString d) {
    190     desc.setTo(d);
    191 }
    192 
    193 UBool NumberingSystem::isAlgorithmic() const {
    194     return ( algorithmic );
    195 }
    196 
    197 
    198 UBool NumberingSystem::isValidDigitString(const UnicodeString& str) {
    199 
    200     StringCharacterIterator it(str);
    201     UChar32 c;
    202     UChar32 prev = 0;
    203     int32_t i = 0;
    204 
    205     for ( it.setToStart(); it.hasNext(); ) {
    206        c = it.next32PostInc();
    207        if ( u_charDigitValue(c) != i ) {  // Digits outside the Unicode decimal digit class are not currently supported
    208            return FALSE;
    209        }
    210        if ( prev != 0 && c != prev + 1 ) { // Non-contiguous digits are not currently supported
    211           return FALSE;
    212        }
    213        if ( c > 0xFFFF ) { // Digits outside the BMP are not currently supported
    214           return FALSE;
    215        }
    216        i++;
    217        prev = c;
    218     }
    219     return TRUE;
    220 }
    221 U_NAMESPACE_END
    222 
    223 #endif /* #if !UCONFIG_NO_FORMATTING */
    224 
    225 //eof
    226