2 *******************************************************************************
3 * Copyright (C) 2010-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
10 * Modification History:*
11 * Date Name Description
13 ********************************************************************************
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"
27 #include "numsys_impl.h"
29 #if !UCONFIG_NO_FORMATTING
35 #define DEFAULT_DIGITS UNICODE_STRING_SIMPLE("0123456789");
36 static const char gNumberingSystems
[] = "numberingSystems";
37 static const char gNumberElements
[] = "NumberElements";
38 static const char gDefault
[] = "default";
39 static const char gNative
[] = "native";
40 static const char gTraditional
[] = "traditional";
41 static const char gFinance
[] = "finance";
42 static const char gDesc
[] = "desc";
43 static const char gRadix
[] = "radix";
44 static const char gAlgorithmic
[] = "algorithmic";
45 static const char gLatn
[] = "latn";
48 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumberingSystem
)
49 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NumsysNameEnumeration
)
52 * Default Constructor.
57 NumberingSystem::NumberingSystem() {
60 UnicodeString defaultDigits
= DEFAULT_DIGITS
;
61 desc
.setTo(defaultDigits
);
62 uprv_strcpy(name
,gLatn
);
70 NumberingSystem::NumberingSystem(const NumberingSystem
& other
)
75 NumberingSystem
* U_EXPORT2
76 NumberingSystem::createInstance(int32_t radix_in
, UBool isAlgorithmic_in
, const UnicodeString
& desc_in
, UErrorCode
&status
) {
78 if (U_FAILURE(status
)) {
83 status
= U_ILLEGAL_ARGUMENT_ERROR
;
87 if ( !isAlgorithmic_in
) {
88 if ( desc_in
.countChar32() != radix_in
|| !isValidDigitString(desc_in
)) {
89 status
= U_ILLEGAL_ARGUMENT_ERROR
;
94 NumberingSystem
*ns
= new NumberingSystem();
96 ns
->setRadix(radix_in
);
98 ns
->setAlgorithmic(isAlgorithmic_in
);
105 NumberingSystem
* U_EXPORT2
106 NumberingSystem::createInstance(const Locale
& inLocale
, UErrorCode
& status
) {
108 if (U_FAILURE(status
)) {
112 UBool nsResolved
= TRUE
;
113 UBool usingFallback
= FALSE
;
114 char buffer
[ULOC_KEYWORDS_CAPACITY
];
115 int32_t count
= inLocale
.getKeywordValue("numbers",buffer
, sizeof(buffer
),status
);
116 if ( count
> 0 ) { // @numbers keyword was specified in the locale
117 buffer
[count
] = '\0'; // Make sure it is null terminated.
118 if ( !uprv_strcmp(buffer
,gDefault
) || !uprv_strcmp(buffer
,gNative
) ||
119 !uprv_strcmp(buffer
,gTraditional
) || !uprv_strcmp(buffer
,gFinance
)) {
123 uprv_strcpy(buffer
,gDefault
);
127 if (!nsResolved
) { // Resolve the numbering system ( default, native, traditional or finance ) into a "real" numbering system
128 UErrorCode localStatus
= U_ZERO_ERROR
;
129 UResourceBundle
*resource
= ures_open(NULL
, inLocale
.getName(), &localStatus
);
130 UResourceBundle
*numberElementsRes
= ures_getByKey(resource
,gNumberElements
,NULL
,&localStatus
);
131 while (!nsResolved
) {
132 localStatus
= U_ZERO_ERROR
;
134 const UChar
*nsName
= ures_getStringByKeyWithFallback(numberElementsRes
, buffer
, &count
, &localStatus
);
135 if ( count
> 0 && count
< ULOC_KEYWORDS_CAPACITY
) { // numbering system found
136 u_UCharsToChars(nsName
,buffer
,count
);
137 buffer
[count
] = '\0'; // Make sure it is null terminated.
141 if (!nsResolved
) { // Fallback behavior per TR35 - traditional falls back to native, finance and native fall back to default
142 if (!uprv_strcmp(buffer
,gNative
) || !uprv_strcmp(buffer
,gFinance
)) {
143 uprv_strcpy(buffer
,gDefault
);
144 } else if (!uprv_strcmp(buffer
,gTraditional
)) {
145 uprv_strcpy(buffer
,gNative
);
146 } else { // If we get here we couldn't find even the default numbering system
147 usingFallback
= TRUE
;
152 ures_close(numberElementsRes
);
153 ures_close(resource
);
157 status
= U_USING_FALLBACK_WARNING
;
158 NumberingSystem
*ns
= new NumberingSystem();
161 return NumberingSystem::createInstanceByName(buffer
,status
);
165 NumberingSystem
* U_EXPORT2
166 NumberingSystem::createInstance(UErrorCode
& status
) {
167 return NumberingSystem::createInstance(Locale::getDefault(), status
);
170 NumberingSystem
* U_EXPORT2
171 NumberingSystem::createInstanceByName(const char *name
, UErrorCode
& status
) {
172 UResourceBundle
*numberingSystemsInfo
= NULL
;
173 UResourceBundle
*nsTop
, *nsCurrent
;
175 int32_t algorithmic
= 0;
177 numberingSystemsInfo
= ures_openDirect(NULL
,gNumberingSystems
, &status
);
178 nsCurrent
= ures_getByKey(numberingSystemsInfo
,gNumberingSystems
,NULL
,&status
);
179 nsTop
= ures_getByKey(nsCurrent
,name
,NULL
,&status
);
180 UnicodeString nsd
= ures_getUnicodeStringByKey(nsTop
,gDesc
,&status
);
182 ures_getByKey(nsTop
,gRadix
,nsCurrent
,&status
);
183 radix
= ures_getInt(nsCurrent
,&status
);
185 ures_getByKey(nsTop
,gAlgorithmic
,nsCurrent
,&status
);
186 algorithmic
= ures_getInt(nsCurrent
,&status
);
188 UBool isAlgorithmic
= ( algorithmic
== 1 );
190 ures_close(nsCurrent
);
192 ures_close(numberingSystemsInfo
);
194 if (U_FAILURE(status
)) {
195 status
= U_UNSUPPORTED_ERROR
;
199 NumberingSystem
* ns
= NumberingSystem::createInstance(radix
,isAlgorithmic
,nsd
,status
);
208 NumberingSystem::~NumberingSystem() {
211 int32_t NumberingSystem::getRadix() {
215 UnicodeString
NumberingSystem::getDescription() {
219 const char * NumberingSystem::getName() {
223 void NumberingSystem::setRadix(int32_t r
) {
227 void NumberingSystem::setAlgorithmic(UBool c
) {
231 void NumberingSystem::setDesc(UnicodeString d
) {
234 void NumberingSystem::setName(const char *n
) {
238 uprv_strncpy(name
,n
,NUMSYS_NAME_CAPACITY
);
239 name
[NUMSYS_NAME_CAPACITY
] = (char)0; // Make sure it is null terminated.
242 UBool
NumberingSystem::isAlgorithmic() const {
243 return ( algorithmic
);
246 StringEnumeration
* NumberingSystem::getAvailableNames(UErrorCode
&status
) {
248 static StringEnumeration
* availableNames
= NULL
;
250 if (U_FAILURE(status
)) {
254 if ( availableNames
== NULL
) {
255 UVector
*fNumsysNames
= new UVector(uprv_deleteUObject
, NULL
, status
);
256 if (U_FAILURE(status
)) {
257 status
= U_MEMORY_ALLOCATION_ERROR
;
261 UErrorCode rbstatus
= U_ZERO_ERROR
;
262 UResourceBundle
*numberingSystemsInfo
= ures_openDirect(NULL
, "numberingSystems", &rbstatus
);
263 numberingSystemsInfo
= ures_getByKey(numberingSystemsInfo
,"numberingSystems",numberingSystemsInfo
,&rbstatus
);
264 if(U_FAILURE(rbstatus
)) {
265 status
= U_MISSING_RESOURCE_ERROR
;
266 ures_close(numberingSystemsInfo
);
270 while ( ures_hasNext(numberingSystemsInfo
) ) {
271 UResourceBundle
*nsCurrent
= ures_getNextResource(numberingSystemsInfo
,NULL
,&rbstatus
);
272 const char *nsName
= ures_getKey(nsCurrent
);
273 fNumsysNames
->addElement(new UnicodeString(nsName
, -1, US_INV
),status
);
274 ures_close(nsCurrent
);
277 ures_close(numberingSystemsInfo
);
278 availableNames
= new NumsysNameEnumeration(fNumsysNames
,status
);
282 return availableNames
;
285 UBool
NumberingSystem::isValidDigitString(const UnicodeString
& str
) {
287 StringCharacterIterator
it(str
);
291 for ( it
.setToStart(); it
.hasNext(); ) {
292 c
= it
.next32PostInc();
293 if ( c
> 0xFFFF ) { // Digits outside the BMP are not currently supported
301 NumsysNameEnumeration::NumsysNameEnumeration(UVector
*fNameList
, UErrorCode
& /*status*/) {
303 fNumsysNames
= fNameList
;
307 NumsysNameEnumeration::snext(UErrorCode
& status
) {
308 if (U_SUCCESS(status
) && pos
< fNumsysNames
->size()) {
309 return (const UnicodeString
*)fNumsysNames
->elementAt(pos
++);
315 NumsysNameEnumeration::reset(UErrorCode
& /*status*/) {
320 NumsysNameEnumeration::count(UErrorCode
& /*status*/) const {
321 return (fNumsysNames
==NULL
) ? 0 : fNumsysNames
->size();
324 NumsysNameEnumeration::~NumsysNameEnumeration() {
329 #endif /* #if !UCONFIG_NO_FORMATTING */