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