]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/currpinf.cpp
ICU-461.12.tar.gz
[apple/icu.git] / icuSources / i18n / currpinf.cpp
CommitLineData
729e4ab9
A
1/*
2 *******************************************************************************
3 * Copyright (C) 2009-2011, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
6 */
7
8#include "unicode/currpinf.h"
9
10#if !UCONFIG_NO_FORMATTING
11
12//#define CURRENCY_PLURAL_INFO_DEBUG 1
13
14#ifdef CURRENCY_PLURAL_INFO_DEBUG
15#include <iostream>
16#endif
17
18
19#include "unicode/locid.h"
20#include "unicode/plurrule.h"
21#include "unicode/ures.h"
22#include "cstring.h"
23#include "hash.h"
24#include "uresimp.h"
25#include "ureslocs.h"
26
27U_NAMESPACE_BEGIN
28
29
30static const UChar gNumberPatternSeparator = 0x3B; // ;
31
32U_CDECL_BEGIN
33
34/**
35 * @internal ICU 4.2
36 */
37static UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2);
38
39UBool
40U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) {
41 const UnicodeString* affix_1 = (UnicodeString*)val1.pointer;
42 const UnicodeString* affix_2 = (UnicodeString*)val2.pointer;
43 return *affix_1 == *affix_2;
44}
45
46U_CDECL_END
47
48
49UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo)
50
51static const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0};
52static const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
53static const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0};
54static const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0};
55static const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0};
56
57static const char gNumberElementsTag[]="NumberElements";
58static const char gLatnTag[]="latn";
59static const char gPatternsTag[]="patterns";
60static const char gDecimalFormatTag[]="decimalFormat";
61static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns";
62
63CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status)
64: fPluralCountToCurrencyUnitPattern(NULL),
65 fPluralRules(NULL),
66 fLocale(NULL) {
67 initialize(Locale::getDefault(), status);
68}
69
70CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status)
71: fPluralCountToCurrencyUnitPattern(NULL),
72 fPluralRules(NULL),
73 fLocale(NULL) {
74 initialize(locale, status);
75}
76
77CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info)
78: UObject(info),
79 fPluralCountToCurrencyUnitPattern(NULL),
80 fPluralRules(NULL),
81 fLocale(NULL) {
82 *this = info;
83}
84
85
86CurrencyPluralInfo&
87CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) {
88 if (this == &info) {
89 return *this;
90 }
91
92 deleteHash(fPluralCountToCurrencyUnitPattern);
93 UErrorCode status = U_ZERO_ERROR;
94 fPluralCountToCurrencyUnitPattern = initHash(status);
95 copyHash(info.fPluralCountToCurrencyUnitPattern,
96 fPluralCountToCurrencyUnitPattern, status);
97 if ( U_FAILURE(status) ) {
98 return *this;
99 }
100
101 delete fPluralRules;
102 delete fLocale;
103 if (info.fPluralRules) {
104 fPluralRules = info.fPluralRules->clone();
105 } else {
106 fPluralRules = NULL;
107 }
108 if (info.fLocale) {
109 fLocale = info.fLocale->clone();
110 } else {
111 fLocale = NULL;
112 }
113 return *this;
114}
115
116
117CurrencyPluralInfo::~CurrencyPluralInfo() {
118 deleteHash(fPluralCountToCurrencyUnitPattern);
119 fPluralCountToCurrencyUnitPattern = NULL;
120 delete fPluralRules;
121 delete fLocale;
122 fPluralRules = NULL;
123 fLocale = NULL;
124}
125
126UBool
127CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const {
128#ifdef CURRENCY_PLURAL_INFO_DEBUG
129 if (*fPluralRules == *info.fPluralRules) {
130 std::cout << "same plural rules\n";
131 }
132 if (*fLocale == *info.fLocale) {
133 std::cout << "same locale\n";
134 }
135 if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) {
136 std::cout << "same pattern\n";
137 }
138#endif
139 return *fPluralRules == *info.fPluralRules &&
140 *fLocale == *info.fLocale &&
141 fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern);
142}
143
144
145CurrencyPluralInfo*
146CurrencyPluralInfo::clone() const {
147 return new CurrencyPluralInfo(*this);
148}
149
150const PluralRules*
151CurrencyPluralInfo::getPluralRules() const {
152 return fPluralRules;
153}
154
155UnicodeString&
156CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString& pluralCount,
157 UnicodeString& result) const {
158 const UnicodeString* currencyPluralPattern =
159 (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount);
160 if (currencyPluralPattern == NULL) {
161 // fall back to "other"
162 if (pluralCount.compare(gPluralCountOther)) {
163 currencyPluralPattern =
164 (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(gPluralCountOther);
165 }
166 if (currencyPluralPattern == NULL) {
167 // no currencyUnitPatterns defined,
168 // fallback to predefined defult.
169 // This should never happen when ICU resource files are
170 // available, since currencyUnitPattern of "other" is always
171 // defined in root.
172 result = UnicodeString(gDefaultCurrencyPluralPattern);
173 return result;
174 }
175 }
176 result = *currencyPluralPattern;
177 return result;
178}
179
180const Locale&
181CurrencyPluralInfo::getLocale() const {
182 return *fLocale;
183}
184
185void
186CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription,
187 UErrorCode& status) {
188 if (U_SUCCESS(status)) {
189 if (fPluralRules) {
190 delete fPluralRules;
191 }
192 fPluralRules = PluralRules::createRules(ruleDescription, status);
193 }
194}
195
196
197void
198CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount,
199 const UnicodeString& pattern,
200 UErrorCode& status) {
201 if (U_SUCCESS(status)) {
202 fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status);
203 }
204}
205
206
207void
208CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) {
209 initialize(loc, status);
210}
211
212
213void
214CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) {
215 if (U_FAILURE(status)) {
216 return;
217 }
218 delete fLocale;
219 fLocale = loc.clone();
220 if (fPluralRules) {
221 delete fPluralRules;
222 }
223 fPluralRules = PluralRules::forLocale(loc, status);
224 setupCurrencyPluralPattern(loc, status);
225}
226
227
228void
229CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) {
230 if (U_FAILURE(status)) {
231 return;
232 }
233
234 if (fPluralCountToCurrencyUnitPattern) {
235 deleteHash(fPluralCountToCurrencyUnitPattern);
236 }
237 fPluralCountToCurrencyUnitPattern = initHash(status);
238 if (U_FAILURE(status)) {
239 return;
240 }
241
242 UErrorCode ec = U_ZERO_ERROR;
243 UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec);
244 rb = ures_getByKey(rb, gNumberElementsTag, rb, &ec);
245 rb = ures_getByKey(rb, gLatnTag, rb, &ec);
246 rb = ures_getByKey(rb, gPatternsTag, rb, &ec);
247 int32_t ptnLen;
248 const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec);
249 int32_t numberStylePatternLen = ptnLen;
250 const UChar* negNumberStylePattern = NULL;
251 int32_t negNumberStylePatternLen = 0;
252 // TODO: Java
253 // parse to check whether there is ";" separator in the numberStylePattern
254 UBool hasSeparator = false;
255 if (U_SUCCESS(ec)) {
256 for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) {
257 if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) {
258 hasSeparator = true;
259 // split the number style pattern into positive and negative
260 negNumberStylePattern = numberStylePattern + styleCharIndex + 1;
261 negNumberStylePatternLen = ptnLen - styleCharIndex - 1;
262 numberStylePatternLen = styleCharIndex;
263 }
264 }
265 }
266 ures_close(rb);
267
268 if (U_FAILURE(ec)) {
269 return;
270 }
271
272 UResourceBundle *currRb = ures_open(U_ICUDATA_CURR, loc.getName(), &ec);
273 UResourceBundle *currencyRes = ures_getByKeyWithFallback(currRb, gCurrUnitPtnTag, NULL, &ec);
274
275#ifdef CURRENCY_PLURAL_INFO_DEBUG
276 std::cout << "in set up\n";
277#endif
278 StringEnumeration* keywords = fPluralRules->getKeywords(ec);
279 if (U_SUCCESS(ec)) {
280 const char* pluralCount;
281 while ((pluralCount = keywords->next(NULL, ec)) != NULL) {
282 if ( U_SUCCESS(ec) ) {
283 int32_t ptnLen;
284 UErrorCode err = U_ZERO_ERROR;
285 const UChar* patternChars = ures_getStringByKeyWithFallback(
286 currencyRes, pluralCount, &ptnLen, &err);
287 if (U_SUCCESS(err) && ptnLen > 0) {
288 UnicodeString* pattern = new UnicodeString(patternChars, ptnLen);
289#ifdef CURRENCY_PLURAL_INFO_DEBUG
290 char result_1[1000];
291 pattern->extract(0, pattern->length(), result_1, "UTF-8");
292 std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
293#endif
294 pattern->findAndReplace(gPart0,
295 UnicodeString(numberStylePattern, numberStylePatternLen));
296 pattern->findAndReplace(gPart1, gTripleCurrencySign);
297
298 if (hasSeparator) {
299 UnicodeString negPattern(patternChars, ptnLen);
300 negPattern.findAndReplace(gPart0,
301 UnicodeString(negNumberStylePattern, negNumberStylePatternLen));
302 negPattern.findAndReplace(gPart1, gTripleCurrencySign);
303 pattern->append(gNumberPatternSeparator);
304 pattern->append(negPattern);
305 }
306#ifdef CURRENCY_PLURAL_INFO_DEBUG
307 pattern->extract(0, pattern->length(), result_1, "UTF-8");
308 std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
309#endif
310
311 fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount), pattern, status);
312 }
313 }
314 }
315 }
316 delete keywords;
317 ures_close(currencyRes);
318 ures_close(currRb);
319}
320
321
322
323void
324CurrencyPluralInfo::deleteHash(Hashtable* hTable)
325{
326 if ( hTable == NULL ) {
327 return;
328 }
329 int32_t pos = -1;
330 const UHashElement* element = NULL;
331 while ( (element = hTable->nextElement(pos)) != NULL ) {
332 const UHashTok keyTok = element->key;
333 const UHashTok valueTok = element->value;
334 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
335 delete value;
336 }
337 delete hTable;
338 hTable = NULL;
339}
340
341
342Hashtable*
343CurrencyPluralInfo::initHash(UErrorCode& status) {
344 if ( U_FAILURE(status) ) {
345 return NULL;
346 }
347 Hashtable* hTable;
348 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
349 status = U_MEMORY_ALLOCATION_ERROR;
350 return NULL;
351 }
352 if ( U_FAILURE(status) ) {
353 delete hTable;
354 return NULL;
355 }
356 hTable->setValueComparator(ValueComparator);
357 return hTable;
358}
359
360
361void
362CurrencyPluralInfo::copyHash(const Hashtable* source,
363 Hashtable* target,
364 UErrorCode& status) {
365 if ( U_FAILURE(status) ) {
366 return;
367 }
368 int32_t pos = -1;
369 const UHashElement* element = NULL;
370 if ( source ) {
371 while ( (element = source->nextElement(pos)) != NULL ) {
372 const UHashTok keyTok = element->key;
373 const UnicodeString* key = (UnicodeString*)keyTok.pointer;
374 const UHashTok valueTok = element->value;
375 const UnicodeString* value = (UnicodeString*)valueTok.pointer;
376 UnicodeString* copy = new UnicodeString(*value);
377 target->put(UnicodeString(*key), copy, status);
378 if ( U_FAILURE(status) ) {
379 return;
380 }
381 }
382 }
383}
384
385
386U_NAMESPACE_END
387
388#endif