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
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem)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
NumberingSystem(const NumberingSystem & other)65 NumberingSystem::NumberingSystem(const NumberingSystem& other)
66 : UObject(other) {
67 *this=other;
68 }
69
70 NumberingSystem* U_EXPORT2
createInstance(int32_t radix_in,UBool isAlgorithmic_in,const UnicodeString & desc_in,UErrorCode & status)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
createInstance(const Locale & inLocale,UErrorCode & status)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
createInstance(UErrorCode & status)140 NumberingSystem::createInstance(UErrorCode& status) {
141 return NumberingSystem::createInstance(Locale::getDefault(), status);
142 }
143
144 NumberingSystem* U_EXPORT2
createInstanceByName(const char * name,UErrorCode & status)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 */
~NumberingSystem()187 NumberingSystem::~NumberingSystem() {
188 }
189
getRadix()190 int32_t NumberingSystem::getRadix() {
191 return radix;
192 }
193
getDescription()194 UnicodeString NumberingSystem::getDescription() {
195 return desc;
196 }
197
getName()198 const char * NumberingSystem::getName() {
199 return name;
200 }
201
setRadix(int32_t r)202 void NumberingSystem::setRadix(int32_t r) {
203 radix = r;
204 }
205
setAlgorithmic(UBool c)206 void NumberingSystem::setAlgorithmic(UBool c) {
207 algorithmic = c;
208 }
209
setDesc(UnicodeString d)210 void NumberingSystem::setDesc(UnicodeString d) {
211 desc.setTo(d);
212 }
setName(const char * n)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 }
isAlgorithmic() const221 UBool NumberingSystem::isAlgorithmic() const {
222 return ( algorithmic );
223 }
224
225
isValidDigitString(const UnicodeString & str)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