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 30U_NAMESPACE_BEGIN 31 32// Useful constants 33 34#define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789"); 35static const char gNumberingSystems[] = "numberingSystems"; 36static const char gDefaultNumberingSystem[] = "defaultNumberingSystem"; 37static const char gDesc[] = "desc"; 38static const char gRadix[] = "radix"; 39static const char gAlgorithmic[] = "algorithmic"; 40 41 42UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem) 43 44 /** 45 * Default Constructor. 46 * 47 * @draft ICU 4.2 48 */ 49 50NumberingSystem::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 62NumberingSystem::NumberingSystem(const NumberingSystem& other) 63: UObject(other) { 64 *this=other; 65} 66 67NumberingSystem* U_EXPORT2 68NumberingSystem::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 92NumberingSystem* U_EXPORT2 93NumberingSystem::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 125NumberingSystem* U_EXPORT2 126NumberingSystem::createInstance(UErrorCode& status) { 127 return NumberingSystem::createInstance(Locale::getDefault(), status); 128} 129 130NumberingSystem* U_EXPORT2 131NumberingSystem::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 */ 172NumberingSystem::~NumberingSystem() { 173} 174 175int32_t NumberingSystem::getRadix() { 176 return radix; 177} 178 179UnicodeString NumberingSystem::getDescription() { 180 return desc; 181} 182 183void NumberingSystem::setRadix(int32_t r) { 184 radix = r; 185} 186 187void NumberingSystem::setAlgorithmic(UBool c) { 188 algorithmic = c; 189} 190 191void NumberingSystem::setDesc(UnicodeString d) { 192 desc.setTo(d); 193} 194 195UBool NumberingSystem::isAlgorithmic() const { 196 return ( algorithmic ); 197} 198 199 200UBool 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} 223U_NAMESPACE_END 224 225#endif /* #if !UCONFIG_NO_FORMATTING */ 226 227//eof 228