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