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