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