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