• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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