blob: 7f271cb3f662b067cb0022d253ee26b66a1e2147 [file] [log] [blame]
Frank Tang3e05d9d2021-11-08 14:04:04 -08001// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8/* Modification History:
9* Date Name Description
10* 07/15/99 helena Ported to HPUX 10/11 CC.
11*/
12
13#include "unicode/utypes.h"
14
15#if !UCONFIG_NO_FORMATTING
16
17#include "numfmtst.h"
18#include "unicode/currpinf.h"
19#include "unicode/dcfmtsym.h"
20#include "unicode/decimfmt.h"
21#include "unicode/localpointer.h"
22#include "unicode/ucurr.h"
23#include "unicode/ustring.h"
24#include "unicode/measfmt.h"
25#include "unicode/curramt.h"
26#include "unicode/strenum.h"
27#include "textfile.h"
28#include "tokiter.h"
29#include "charstr.h"
30#include "cstr.h"
31#include "putilimp.h"
32#include "winnmtst.h"
33#include <cmath>
34#include <float.h>
35#include <string.h>
36#include <stdlib.h>
37#include "cmemory.h"
38#include "cstring.h"
39#include "unicode/numsys.h"
40#include "fmtableimp.h"
41#include "numberformattesttuple.h"
42#include "unicode/msgfmt.h"
43#include "number_decimalquantity.h"
44#include "unicode/numberformatter.h"
45
46#if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
47// These should not be macros. If they are,
48// replace them with std::isnan and std::isinf
49#if defined(isnan)
50#undef isnan
51namespace std {
52 bool isnan(double x) {
53 return _isnan(x);
54 }
55}
56#endif
57#if defined(isinf)
58#undef isinf
59namespace std {
60 bool isinf(double x) {
61 return _isinf(x);
62 }
63}
64#endif
65#endif
66
67using icu::number::impl::DecimalQuantity;
68using namespace icu::number;
69
70//#define NUMFMTST_CACHE_DEBUG 1
71#include "stdio.h" /* for sprintf */
72// #include "iostream" // for cout
73
74//#define NUMFMTST_DEBUG 1
75
76static const UChar EUR[] = {69,85,82,0}; // "EUR"
77static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
78
79
80// *****************************************************************************
81// class NumberFormatTest
82// *****************************************************************************
83
84#define CHECK(status,str) UPRV_BLOCK_MACRO_BEGIN { \
85 if (U_FAILURE(status)) { \
86 errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
87 return; \
88 } \
89} UPRV_BLOCK_MACRO_END
90#define CHECK_DATA(status,str) UPRV_BLOCK_MACRO_BEGIN { \
91 if (U_FAILURE(status)) { \
92 dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); \
93 return; \
94 } \
95} UPRV_BLOCK_MACRO_END
96
97void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
98{
99 TESTCASE_AUTO_BEGIN;
100 TESTCASE_AUTO(TestCurrencySign);
101 TESTCASE_AUTO(TestCurrency);
102 TESTCASE_AUTO(TestParse);
103 TESTCASE_AUTO(TestRounding487);
104 TESTCASE_AUTO(TestQuotes);
105 TESTCASE_AUTO(TestExponential);
106 TESTCASE_AUTO(TestPatterns);
107 TESTCASE_AUTO(Test20186_SpacesAroundSemicolon);
108
109 // Upgrade to alphaWorks - liu 5/99
110 TESTCASE_AUTO(TestExponent);
111 TESTCASE_AUTO(TestScientific);
112 TESTCASE_AUTO(TestPad);
113 TESTCASE_AUTO(TestPatterns2);
114 TESTCASE_AUTO(TestSecondaryGrouping);
115 TESTCASE_AUTO(TestSurrogateSupport);
116 TESTCASE_AUTO(TestAPI);
117
118 TESTCASE_AUTO(TestCurrencyObject);
119 TESTCASE_AUTO(TestCurrencyPatterns);
120 //TESTCASE_AUTO(TestDigitList);
121 TESTCASE_AUTO(TestWhiteSpaceParsing);
122 TESTCASE_AUTO(TestComplexCurrency); // This test removed because CLDR no longer uses choice formats in currency symbols.
123 TESTCASE_AUTO(TestRegCurrency);
124 TESTCASE_AUTO(TestSymbolsWithBadLocale);
125 TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
126
127 TESTCASE_AUTO(TestScientific2);
128 TESTCASE_AUTO(TestScientificGrouping);
129 TESTCASE_AUTO(TestInt64);
130
131 TESTCASE_AUTO(TestPerMill);
132 TESTCASE_AUTO(TestIllegalPatterns);
133 TESTCASE_AUTO(TestCases);
134
135 TESTCASE_AUTO(TestCurrencyNames);
136 TESTCASE_AUTO(TestCurrencyVariants);
137 TESTCASE_AUTO(TestCurrencyAmount);
138 TESTCASE_AUTO(TestCurrencyUnit);
139 TESTCASE_AUTO(TestCoverage);
140 TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
141 TESTCASE_AUTO(TestJB3832);
142 TESTCASE_AUTO(TestHost);
143 TESTCASE_AUTO(TestHostClone);
144 TESTCASE_AUTO(TestCurrencyFormat);
145 TESTCASE_AUTO(TestRounding);
146 TESTCASE_AUTO(TestNonpositiveMultiplier);
147 TESTCASE_AUTO(TestNumberingSystems);
148 TESTCASE_AUTO(TestSpaceParsing);
149 TESTCASE_AUTO(TestMultiCurrencySign);
150 TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
151 TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
152 TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
153 TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
154 TESTCASE_AUTO(TestCurrencyParsing);
155 TESTCASE_AUTO(TestParseCurrencyInUCurr);
156 TESTCASE_AUTO(TestFormatAttributes);
157 TESTCASE_AUTO(TestFieldPositionIterator);
158 TESTCASE_AUTO(TestDecimal);
159 TESTCASE_AUTO(TestCurrencyFractionDigits);
160 TESTCASE_AUTO(TestExponentParse);
161 TESTCASE_AUTO(TestExplicitParents);
162 TESTCASE_AUTO(TestLenientParse);
163 TESTCASE_AUTO(TestAvailableNumberingSystems);
164 TESTCASE_AUTO(TestRoundingPattern);
165 TESTCASE_AUTO(Test9087);
166 TESTCASE_AUTO(TestFormatFastpaths);
167 TESTCASE_AUTO(TestFormattableSize);
168 TESTCASE_AUTO(TestUFormattable);
169 TESTCASE_AUTO(TestSignificantDigits);
170 TESTCASE_AUTO(TestShowZero);
171 TESTCASE_AUTO(TestCompatibleCurrencies);
172 TESTCASE_AUTO(TestBug9936);
173 TESTCASE_AUTO(TestParseNegativeWithFaLocale);
174 TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
175 TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
176 TESTCASE_AUTO(TestParseSignsAndMarks);
177 TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
178 TESTCASE_AUTO(Test10468ApplyPattern);
179 TESTCASE_AUTO(TestRoundingScientific10542);
180 TESTCASE_AUTO(TestZeroScientific10547);
181 TESTCASE_AUTO(TestAccountingCurrency);
182 TESTCASE_AUTO(TestCurrencyFormatForMissingLocale);
183 TESTCASE_AUTO(TestEquality);
184 TESTCASE_AUTO(TestCurrencyUsage);
185 TESTCASE_AUTO(TestDoubleLimit11439);
186 TESTCASE_AUTO(TestGetAffixes);
187 TESTCASE_AUTO(TestToPatternScientific11648);
188 TESTCASE_AUTO(TestBenchmark);
189 TESTCASE_AUTO(TestCtorApplyPatternDifference);
190 TESTCASE_AUTO(TestFractionalDigitsForCurrency);
191 TESTCASE_AUTO(TestFormatCurrencyPlural);
192 TESTCASE_AUTO(Test11868);
193 TESTCASE_AUTO(Test11739_ParseLongCurrency);
194 TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
195 TESTCASE_AUTO(Test13737_ParseScientificStrict);
196 TESTCASE_AUTO(Test10727_RoundingZero);
197 TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
198 TESTCASE_AUTO(Test11475_signRecognition);
199 TESTCASE_AUTO(Test11640_getAffixes);
200 TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
201 TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
202 TESTCASE_AUTO(Test13391_chakmaParsing);
203 TESTCASE_AUTO(Test11735_ExceptionIssue);
204 TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
205 TESTCASE_AUTO(Test11318_DoubleConversion);
206 TESTCASE_AUTO(TestParsePercentRegression);
207 TESTCASE_AUTO(TestMultiplierWithScale);
208 TESTCASE_AUTO(TestFastFormatInt32);
209 TESTCASE_AUTO(Test11646_Equality);
210 TESTCASE_AUTO(TestParseNaN);
211 TESTCASE_AUTO(TestFormatFailIfMoreThanMaxDigits);
212 TESTCASE_AUTO(TestParseCaseSensitive);
213 TESTCASE_AUTO(TestParseNoExponent);
214 TESTCASE_AUTO(TestSignAlwaysShown);
215 TESTCASE_AUTO(TestMinimumGroupingDigits);
216 TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
217 TESTCASE_AUTO(Test13055_PercentageRounding);
218 TESTCASE_AUTO(Test11839);
219 TESTCASE_AUTO(Test10354);
220 TESTCASE_AUTO(Test11645_ApplyPatternEquality);
221 TESTCASE_AUTO(Test12567);
222 TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
223 TESTCASE_AUTO(Test20073_StrictPercentParseErrorIndex);
224 TESTCASE_AUTO(Test13056_GroupingSize);
225 TESTCASE_AUTO(Test11025_CurrencyPadding);
226 TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
227 TESTCASE_AUTO(Test11649_DecFmtCurrencies);
228 TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
229 TESTCASE_AUTO(Test12753_PatternDecimalPoint);
230 TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
231 TESTCASE_AUTO(Test11913_BigDecimal);
232 TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
233 TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
234 TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
235 TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
236 TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
237 TESTCASE_AUTO(Test20037_ScientificIntegerOverflow);
238 TESTCASE_AUTO(Test13840_ParseLongStringCrash);
239 TESTCASE_AUTO(Test13850_EmptyStringCurrency);
240 TESTCASE_AUTO(Test20348_CurrencyPrefixOverride);
241 TESTCASE_AUTO(Test20956_MonetarySymbolGetters);
242 TESTCASE_AUTO(Test20358_GroupingInPattern);
243 TESTCASE_AUTO(Test13731_DefaultCurrency);
244 TESTCASE_AUTO(Test20499_CurrencyVisibleDigitsPlural);
245 TESTCASE_AUTO(Test13735_GroupingSizeGetter);
246 TESTCASE_AUTO(Test13734_StrictFlexibleWhitespace);
247 TESTCASE_AUTO(Test20961_CurrencyPluralPattern);
248 TESTCASE_AUTO(Test21134_ToNumberFormatter);
249 TESTCASE_AUTO(Test13733_StrictAndLenient);
250 TESTCASE_AUTO(Test20425_IntegerIncrement);
251 TESTCASE_AUTO(Test20425_FractionWithIntegerIncrement);
252 TESTCASE_AUTO(Test21232_ParseTimeout);
253 TESTCASE_AUTO(Test10997_FormatCurrency);
254 TESTCASE_AUTO(Test21556_CurrencyAsDecimal);
255 TESTCASE_AUTO_END;
256}
257
258// -------------------------------------
259
260// Test API (increase code coverage)
261void
262NumberFormatTest::TestAPI(void)
263{
264 logln("Test API");
265 UErrorCode status = U_ZERO_ERROR;
266 NumberFormat *test = NumberFormat::createInstance("root", status);
267 if(U_FAILURE(status)) {
268 dataerrln("unable to create format object - %s", u_errorName(status));
269 }
270 if(test != NULL) {
271 test->setMinimumIntegerDigits(10);
272 test->setMaximumIntegerDigits(1);
273
274 test->setMinimumFractionDigits(10);
275 test->setMaximumFractionDigits(1);
276
277 UnicodeString result;
278 FieldPosition pos;
279 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
280 test->format(bla, result, pos, status);
281 if(U_SUCCESS(status)) {
282 errln("Yuck... Formatted a duck... As a number!");
283 } else {
284 status = U_ZERO_ERROR;
285 }
286
287 result.remove();
288 int64_t ll = 12;
289 test->format(ll, result);
290 assertEquals("format int64_t error", u"2.0", result);
291
292 test->setMinimumIntegerDigits(4);
293 test->setMinimumFractionDigits(4);
294
295 result.remove();
296 test->format(ll, result);
297 assertEquals("format int64_t error", u"0,012.0000", result);
298
299 ParsePosition ppos;
300 LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
301 // old test for (U_FAILURE(status)) was bogus here, method does not set status!
302 if (ppos.getIndex()) {
303 errln("Parsed empty string as currency");
304 }
305
306 delete test;
307 }
308}
309
310class StubNumberFormat :public NumberFormat{
311public:
312 StubNumberFormat(){}
313 virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const override {
314 return appendTo;
315 }
316 virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const override {
317 return appendTo.append((UChar)0x0033);
318 }
319 virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const override {
320 return NumberFormat::format(number, appendTo, pos);
321 }
322 virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const override {
323 return appendTo;
324 }
325 virtual void parse(const UnicodeString& ,
326 Formattable& ,
327 ParsePosition& ) const override {}
328 virtual void parse( const UnicodeString& ,
329 Formattable& ,
330 UErrorCode& ) const override {}
331 virtual UClassID getDynamicClassID(void) const override {
332 static char classID = 0;
333 return (UClassID)&classID;
334 }
335 virtual StubNumberFormat* clone() const override {return NULL;}
336};
337
338void
339NumberFormatTest::TestCoverage(void){
340 StubNumberFormat stub;
341 UnicodeString agent("agent");
342 FieldPosition pos;
343 int64_t num = 4;
344 if (stub.format(num, agent, pos) != UnicodeString("agent3")){
345 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
346 }
347}
348
349void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
350 IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
351 // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
352 DecimalFormatSymbols dfs(errorCode);
353 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
354 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
355 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
356 dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
357 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
358 dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
359 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
360 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
361 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
362 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
363 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
364 dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
365
366 {
367 UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
368 UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
369
370 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
371 df1.applyPattern(standardPattern, errorCode);
372 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
373 df2.applyLocalizedPattern(localizedPattern, errorCode);
374 assertTrue("DecimalFormat instances should be equal", df1 == df2);
375 UnicodeString p2;
376 assertEquals("toPattern should match on localizedPattern instance",
377 standardPattern, df2.toPattern(p2));
378 UnicodeString lp1;
379 assertEquals("toLocalizedPattern should match on standardPattern instance",
380 localizedPattern, df1.toLocalizedPattern(lp1));
381 }
382
383 {
384 UnicodeString standardPattern(u"* @@@E0‰");
385 UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
386
387 DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
388 df1.applyPattern(standardPattern, errorCode);
389 DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
390 df2.applyLocalizedPattern(localizedPattern, errorCode);
391 assertTrue("DecimalFormat instances should be equal", df1 == df2);
392 UnicodeString p2;
393 assertEquals("toPattern should match on localizedPattern instance",
394 standardPattern, df2.toPattern(p2));
395 UnicodeString lp1;
396 assertEquals("toLocalizedPattern should match on standardPattern instance",
397 localizedPattern, df1.toLocalizedPattern(lp1));
398 }
399}
400
401// Test various patterns
402void
403NumberFormatTest::TestPatterns(void)
404{
405 UErrorCode status = U_ZERO_ERROR;
406 DecimalFormatSymbols sym(Locale::getUS(), status);
407 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
408
409 const char* pat[] = { "#.#", "#.", ".#", "#" };
410 int32_t pat_length = UPRV_LENGTHOF(pat);
411 const char* newpat[] = { "0.#", "0.", "#.0", "0" };
412 const char* num[] = { "0", "0.", ".0", "0" };
413 for (int32_t i=0; i<pat_length; ++i)
414 {
415 status = U_ZERO_ERROR;
416 DecimalFormat fmt(pat[i], sym, status);
417 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
418 UnicodeString newp; fmt.toPattern(newp);
419 if (!(newp == newpat[i]))
420 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
421 "; " + newp + " seen instead");
422
423 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
424 if (!(s == num[i]))
425 {
426 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
427 "; " + s + " seen instead");
428 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
429 }
430 }
431}
432
433void NumberFormatTest::Test20186_SpacesAroundSemicolon() {
434 IcuTestErrorCode status(*this, "Test20186_SpacesAroundSemicolon");
435 DecimalFormat df(u"0.00 ; -0.00", {"en-us", status}, status);
436 expect2(df, 1, u"1.00 ");
437 expect2(df, -1, u" -1.00");
438
439 df = DecimalFormat(u"0.00;", {"en-us", status}, status);
440 expect2(df, 1, u"1.00");
441 expect2(df, -1, u"-1.00");
442
443 df = DecimalFormat(u"0.00;0.00", {"en-us", status}, status);
444 expect2(df, 1, u"1.00");
445 expect(df, -1, u"1.00"); // parses as 1, not -1
446
447 df = DecimalFormat(u" 0.00 ; -0.00 ", {"en-us", status}, status);
448 expect2(df, 1, u" 1.00 ");
449 expect2(df, -1, u" -1.00 ");
450}
451
452/*
453icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
454icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
455icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
456*/
457/*
458void
459NumberFormatTest::TestDigitList(void)
460{
461 // API coverage for DigitList
462 DigitList list1;
463 list1.append('1');
464 list1.fDecimalAt = 1;
465 DigitList list2;
466 list2.set((int32_t)1);
467 if (list1 != list2) {
468 errln("digitlist append, operator!= or set failed ");
469 }
470 if (!(list1 == list2)) {
471 errln("digitlist append, operator== or set failed ");
472 }
473}
474*/
475
476// -------------------------------------
477
478// Test exponential pattern
479void
480NumberFormatTest::TestExponential(void)
481{
482 UErrorCode status = U_ZERO_ERROR;
483 DecimalFormatSymbols sym(Locale::getUS(), status);
484 if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
485 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
486 int32_t pat_length = UPRV_LENGTHOF(pat);
487
488// The following #if statements allow this test to be built and run on
489// platforms that do not have standard IEEE numerics. For example,
490// S/390 doubles have an exponent range of -78 to +75. For the
491// following #if statements to work, float.h must define
492// DBL_MAX_10_EXP to be a compile-time constant.
493
494// This section may be expanded as needed.
495
496#if DBL_MAX_10_EXP > 300
497 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
498 int32_t val_length = UPRV_LENGTHOF(val);
499 const char* valFormat[] =
500 {
501 // 0.####E0
502 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
503 // 00.000E00
504 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
505 // ##0.######E000
506 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
507 // 0.###E0;[0.###E0]
508 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
509 };
510 double valParse[] =
511 {
512 0.01234, 123460000, 1.23E300, -3.1416E-271,
513 0.01234, 123460000, 1.23E300, -3.1416E-271,
514 0.01234, 123456800, 1.23E300, -3.141593E-271,
515 0.01234, 123500000, 1.23E300, -3.142E-271,
516 };
517#elif DBL_MAX_10_EXP > 70
518 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
519 int32_t val_length = UPRV_LENGTHOF(val);
520 char* valFormat[] =
521 {
522 // 0.####E0
523 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
524 // 00.000E00
525 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
526 // ##0.######E000
527 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
528 // 0.###E0;[0.###E0]
529 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
530 };
531 double valParse[] =
532 {
533 0.01234, 123460000, 1.23E70, -3.1416E-71,
534 0.01234, 123460000, 1.23E70, -3.1416E-71,
535 0.01234, 123456800, 1.23E70, -3.141593E-71,
536 0.01234, 123500000, 1.23E70, -3.142E-71,
537 };
538#else
539 // Don't test double conversion
540 double* val = 0;
541 int32_t val_length = 0;
542 char** valFormat = 0;
543 double* valParse = 0;
544 logln("Warning: Skipping double conversion tests");
545#endif
546
547 int32_t lval[] = { 0, -1, 1, 123456789 };
548 int32_t lval_length = UPRV_LENGTHOF(lval);
549 const char* lvalFormat[] =
550 {
551 // 0.####E0
552 "0E0", "-1E0", "1E0", "1.2346E8",
553 // 00.000E00
554 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
555 // ##0.######E000
556 "0E000", "-1E000", "1E000", "123.4568E006",
557 // 0.###E0;[0.###E0]
558 "0E0", "[1E0]", "1E0", "1.235E8"
559 };
560 int32_t lvalParse[] =
561 {
562 0, -1, 1, 123460000,
563 0, -1, 1, 123460000,
564 0, -1, 1, 123456800,
565 0, -1, 1, 123500000,
566 };
567 int32_t ival = 0, ilval = 0;
568 for (int32_t p=0; p<pat_length; ++p)
569 {
570 DecimalFormat fmt(pat[p], sym, status);
571 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
572 UnicodeString pattern;
573 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
574 fmt.toPattern(pattern) + "\"");
575 int32_t v;
576 for (v=0; v<val_length; ++v)
577 {
578 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
579 logln((UnicodeString)" " + val[v] + " -format-> " + s);
580 if (s != valFormat[v+ival])
581 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
582
583 ParsePosition pos(0);
584 Formattable af;
585 fmt.parse(s, af, pos);
586 double a;
587 UBool useEpsilon = FALSE;
588 if (af.getType() == Formattable::kLong)
589 a = af.getLong();
590 else if (af.getType() == Formattable::kDouble) {
591 a = af.getDouble();
592#if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
593 // S/390 will show a failure like this:
594 //| -3.141592652999999e-271 -format-> -3.1416E-271
595 //| -parse-> -3.1416e-271
596 //| FAIL: Expected -3.141599999999999e-271
597 // To compensate, we use an epsilon-based equality
598 // test on S/390 only. We don't want to do this in
599 // general because it's less exacting.
600 useEpsilon = TRUE;
601#endif
602 }
603 else {
604 errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
605 continue;
606 }
607 if (pos.getIndex() == s.length())
608 {
609 logln((UnicodeString)" -parse-> " + a);
610 // Use epsilon comparison as necessary
611 if ((useEpsilon &&
612 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
613 (!useEpsilon && a != valParse[v+ival]))
614 {
615 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
616 + " on input " + s);
617 }
618 }
619 else {
620 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
621 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
622 }
623 }
624 for (v=0; v<lval_length; ++v)
625 {
626 UnicodeString s;
627 (*(NumberFormat*)&fmt).format(lval[v], s);
628 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
629 if (s != lvalFormat[v+ilval])
630 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
631
632 ParsePosition pos(0);
633 Formattable af;
634 fmt.parse(s, af, pos);
635 if (af.getType() == Formattable::kLong ||
636 af.getType() == Formattable::kInt64) {
637 UErrorCode status = U_ZERO_ERROR;
638 int32_t a = af.getLong(status);
639 if (pos.getIndex() == s.length())
640 {
641 logln((UnicodeString)" -parse-> " + a);
642 if (a != lvalParse[v+ilval])
643 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
644 }
645 else
646 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
647 }
648 else
649 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
650 + " Double: " + af.getDouble()
651 + ", Long: " + af.getLong());
652 }
653 ival += val_length;
654 ilval += lval_length;
655 }
656}
657
658void
659NumberFormatTest::TestScientific2() {
660 // jb 2552
661 UErrorCode status = U_ZERO_ERROR;
662 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
663 if (U_SUCCESS(status)) {
664 double num = 12.34;
665 expect(*fmt, num, "$12.34");
666 fmt->setScientificNotation(TRUE);
667 expect(*fmt, num, "$1.23E1");
668 fmt->setScientificNotation(FALSE);
669 expect(*fmt, num, "$12.34");
670 }
671 delete fmt;
672}
673
674void
675NumberFormatTest::TestScientificGrouping() {
676 // jb 2552
677 UErrorCode status = U_ZERO_ERROR;
678 DecimalFormat fmt("##0.00E0",status);
679 if (assertSuccess("", status, true, __FILE__, __LINE__)) {
680 expect(fmt, .01234, "12.3E-3");
681 expect(fmt, .1234, "123E-3");
682 expect(fmt, 1.234, "1.23E0");
683 expect(fmt, 12.34, "12.3E0");
684 expect(fmt, 123.4, "123E0");
685 expect(fmt, 1234., "1.23E3");
686 }
687}
688
689/*static void setFromString(DigitList& dl, const char* str) {
690 char c;
691 UBool decimalSet = FALSE;
692 dl.clear();
693 while ((c = *str++)) {
694 if (c == '-') {
695 dl.fIsPositive = FALSE;
696 } else if (c == '+') {
697 dl.fIsPositive = TRUE;
698 } else if (c == '.') {
699 dl.fDecimalAt = dl.fCount;
700 decimalSet = TRUE;
701 } else {
702 dl.append(c);
703 }
704 }
705 if (!decimalSet) {
706 dl.fDecimalAt = dl.fCount;
707 }
708}*/
709
710void
711NumberFormatTest::TestInt64() {
712 UErrorCode status = U_ZERO_ERROR;
713 DecimalFormat fmt("#.#E0",status);
714 if (U_FAILURE(status)) {
715 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
716 return;
717 }
718 fmt.setMaximumFractionDigits(20);
719 if (U_SUCCESS(status)) {
720 expect(fmt, (Formattable)(int64_t)0, "0E0");
721 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
722 expect(fmt, (Formattable)(int64_t)1, "1E0");
723 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
724 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
725 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
726 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
727 }
728
729 // also test digitlist
730/* int64_t int64max = U_INT64_MAX;
731 int64_t int64min = U_INT64_MIN;
732 const char* int64maxstr = "9223372036854775807";
733 const char* int64minstr = "-9223372036854775808";
734 UnicodeString fail("fail: ");
735
736 // test max int64 value
737 DigitList dl;
738 setFromString(dl, int64maxstr);
739 {
740 if (!dl.fitsIntoInt64(FALSE)) {
741 errln(fail + int64maxstr + " didn't fit");
742 }
743 int64_t int64Value = dl.getInt64();
744 if (int64Value != int64max) {
745 errln(fail + int64maxstr);
746 }
747 dl.set(int64Value);
748 int64Value = dl.getInt64();
749 if (int64Value != int64max) {
750 errln(fail + int64maxstr);
751 }
752 }
753 // test negative of max int64 value (1 shy of min int64 value)
754 dl.fIsPositive = FALSE;
755 {
756 if (!dl.fitsIntoInt64(FALSE)) {
757 errln(fail + "-" + int64maxstr + " didn't fit");
758 }
759 int64_t int64Value = dl.getInt64();
760 if (int64Value != -int64max) {
761 errln(fail + "-" + int64maxstr);
762 }
763 dl.set(int64Value);
764 int64Value = dl.getInt64();
765 if (int64Value != -int64max) {
766 errln(fail + "-" + int64maxstr);
767 }
768 }
769 // test min int64 value
770 setFromString(dl, int64minstr);
771 {
772 if (!dl.fitsIntoInt64(FALSE)) {
773 errln(fail + "-" + int64minstr + " didn't fit");
774 }
775 int64_t int64Value = dl.getInt64();
776 if (int64Value != int64min) {
777 errln(fail + int64minstr);
778 }
779 dl.set(int64Value);
780 int64Value = dl.getInt64();
781 if (int64Value != int64min) {
782 errln(fail + int64minstr);
783 }
784 }
785 // test negative of min int 64 value (1 more than max int64 value)
786 dl.fIsPositive = TRUE; // won't fit
787 {
788 if (dl.fitsIntoInt64(FALSE)) {
789 errln(fail + "-(" + int64minstr + ") didn't fit");
790 }
791 }*/
792}
793
794// -------------------------------------
795
796// Test the handling of quotes
797void
798NumberFormatTest::TestQuotes(void)
799{
800 UErrorCode status = U_ZERO_ERROR;
801 UnicodeString *pat;
802 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
803 if (U_FAILURE(status)) {
804 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
805 delete sym;
806 return;
807 }
808 pat = new UnicodeString("a'fo''o'b#");
809 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
810 UnicodeString s;
811 ((NumberFormat*)fmt)->format((int32_t)123, s);
812 logln((UnicodeString)"Pattern \"" + *pat + "\"");
813 logln((UnicodeString)" Format 123 -> " + escape(s));
814 if (!(s=="afo'ob123"))
815 errln((UnicodeString)"FAIL: Expected afo'ob123");
816
817 s.truncate(0);
818 delete fmt;
819 delete pat;
820
821 pat = new UnicodeString("a''b#");
822 fmt = new DecimalFormat(*pat, *sym, status);
823 ((NumberFormat*)fmt)->format((int32_t)123, s);
824 logln((UnicodeString)"Pattern \"" + *pat + "\"");
825 logln((UnicodeString)" Format 123 -> " + escape(s));
826 if (!(s=="a'b123"))
827 errln((UnicodeString)"FAIL: Expected a'b123");
828 delete fmt;
829 delete pat;
830 delete sym;
831}
832
833/**
834 * Test the handling of the currency symbol in patterns.
835 */
836void
837NumberFormatTest::TestCurrencySign(void)
838{
839 UErrorCode status = U_ZERO_ERROR;
840 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
841 UnicodeString pat;
842 UChar currency = 0x00A4;
843 if (U_FAILURE(status)) {
844 errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
845 delete sym;
846 return;
847 }
848 // "\xA4#,##0.00;-\xA4#,##0.00"
849 pat.append(currency).append("#,##0.00;-").
850 append(currency).append("#,##0.00");
851 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
852 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
853 pat.truncate(0);
854 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
855 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
856 if (s != "$1,234.56") dataerrln((UnicodeString)"FAIL: Expected $1,234.56");
857 s.truncate(0);
858 ((NumberFormat*)fmt)->format(- 1234.56, s);
859 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
860 if (s != "-$1,234.56") dataerrln((UnicodeString)"FAIL: Expected -$1,234.56");
861 delete fmt;
862 pat.truncate(0);
863 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
864 pat.append(currency).append(currency).
865 append(" #,##0.00;").
866 append(currency).append(currency).
867 append(" -#,##0.00");
868 fmt = new DecimalFormat(pat, *sym, status);
869 s.truncate(0);
870 ((NumberFormat*)fmt)->format(1234.56, s);
871 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
872 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
873 if (s != "USD 1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD 1,234.56");
874 s.truncate(0);
875 ((NumberFormat*)fmt)->format(-1234.56, s);
876 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
877 if (s != "USD -1,234.56") dataerrln((UnicodeString)"FAIL: Expected USD -1,234.56");
878 delete fmt;
879 delete sym;
880 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + u_errorName(status));
881}
882
883// -------------------------------------
884
885static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
886
887UnicodeString&
888NumberFormatTest::escape(UnicodeString& s)
889{
890 UnicodeString buf;
891 for (int32_t i=0; i<s.length(); ++i)
892 {
893 UChar c = s[(int32_t)i];
894 if (c <= (UChar)0x7F) buf += c;
895 else {
896 buf += (UChar)0x5c; buf += (UChar)0x55;
897 buf += toHexString((c & 0xF000) >> 12);
898 buf += toHexString((c & 0x0F00) >> 8);
899 buf += toHexString((c & 0x00F0) >> 4);
900 buf += toHexString(c & 0x000F);
901 }
902 }
903 return (s = buf);
904}
905
906
907// -------------------------------------
908static const char* testCases[][2]= {
909 /* locale ID */ /* expected */
910 {"ca_ES@currency=ESP", "\\u20A7\\u00A01.150" },
911 {"de_LU@currency=LUF", "1,150\\u00A0F" },
912 {"el_GR@currency=GRD", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
913 {"en_BE@currency=BEF", "1.150,50\\u00A0BEF" },
914 {"es_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
915 {"eu_ES@currency=ESP", "\\u20A7\\u00A01.150" },
916 {"gl_ES@currency=ESP", "1.150\\u00A0\\u20A7" },
917 {"it_IT@currency=ITL", "ITL\\u00A01.150" },
918 {"pt_PT@currency=PTE", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
919 {"en_US@currency=JPY", "\\u00A51,150"},
920 {"en_US@currency=jpy", "\\u00A51,150"},
921 {"en-US-u-cu-jpy", "\\u00A51,150"}
922};
923/**
924 * Test localized currency patterns.
925 */
926void
927NumberFormatTest::TestCurrency(void)
928{
929 UErrorCode status = U_ZERO_ERROR;
930 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
931 if (U_FAILURE(status)) {
932 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
933 return;
934 }
935
936 UnicodeString s; currencyFmt->format(1.50, s);
937 logln((UnicodeString)"Un pauvre ici a..........." + s);
938 if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
939 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
940 delete currencyFmt;
941 s.truncate(0);
942 char loc[256]={0};
943 int len = uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
944 (void)len; // Suppress unused variable warning.
945 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
946 currencyFmt->format(1.50, s);
947 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
948 if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
949 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
950 delete currencyFmt;
951 s.truncate(0);
952 len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
953 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
954 currencyFmt->format(1.50, s);
955 logln((UnicodeString)"Un pauvre en France a....." + s);
956 if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
957 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
958 delete currencyFmt;
959 if (U_FAILURE(status))
960 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
961
962 for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
963 status = U_ZERO_ERROR;
964 const char *localeID = testCases[i][0];
965 UnicodeString expected(testCases[i][1], -1, US_INV);
966 expected = expected.unescape();
967 s.truncate(0);
968 char loc[256]={0};
969 uloc_canonicalize(localeID, loc, 256, &status);
970 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
971 if(U_FAILURE(status)){
972 errln("Could not create currency formatter for locale %s",localeID);
973 continue;
974 }
975 currencyFmt->format(1150.50, s);
976 if(s!=expected){
977 errln(UnicodeString("FAIL: Expected: ")+expected
978 + UnicodeString(" Got: ") + s
979 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
980 }
981 if (U_FAILURE(status)){
982 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
983 }
984 delete currencyFmt;
985 }
986}
987
988// -------------------------------------
989
990/**
991 * Test the Currency object handling, new as of ICU 2.2.
992 */
993void NumberFormatTest::TestCurrencyObject() {
994 UErrorCode ec = U_ZERO_ERROR;
995 NumberFormat* fmt =
996 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
997
998 if (U_FAILURE(ec)) {
999 dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
1000 delete fmt;
1001 return;
1002 }
1003
1004 Locale null("", "", "");
1005
1006 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
1007
1008 expectCurrency(*fmt, Locale::getFrance(),
1009 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
1010
1011 expectCurrency(*fmt, Locale::getJapan(),
1012 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
1013
1014 expectCurrency(*fmt, Locale("fr", "CH", ""),
1015 1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
1016
1017 expectCurrency(*fmt, Locale::getUS(),
1018 1234.56, "$1,234.56");
1019
1020 delete fmt;
1021 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
1022
1023 if (U_FAILURE(ec)) {
1024 errln("FAIL: getCurrencyInstance(FRANCE)");
1025 delete fmt;
1026 return;
1027 }
1028
1029 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));
1030
1031 expectCurrency(*fmt, Locale::getJapan(),
1032 1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen
1033
1034 expectCurrency(*fmt, Locale("fr", "CH", ""),
1035 1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548
1036
1037 expectCurrency(*fmt, Locale::getUS(),
1038 1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));
1039
1040 expectCurrency(*fmt, Locale::getFrance(),
1041 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro
1042
1043 delete fmt;
1044}
1045
1046// -------------------------------------
1047
1048/**
1049 * Do rudimentary testing of parsing.
1050 */
1051void
1052NumberFormatTest::TestParse(void)
1053{
1054 UErrorCode status = U_ZERO_ERROR;
1055 UnicodeString arg("0");
1056 DecimalFormat* format = new DecimalFormat("00", status);
1057 //try {
1058 Formattable n; format->parse(arg, n, status);
1059 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
1060 if (n.getType() != Formattable::kLong ||
1061 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
1062 delete format;
1063 if (U_FAILURE(status)) errcheckln(status, (UnicodeString)"FAIL: Status " + u_errorName(status));
1064 //}
1065 //catch(Exception e) {
1066 // errln((UnicodeString)"Exception caught: " + e);
1067 //}
1068}
1069
1070// -------------------------------------
1071
1072static const char *lenientAffixTestCases[] = {
1073 "(1)",
1074 "( 1)",
1075 "(1 )",
1076 "( 1 )"
1077};
1078
1079static const char *lenientMinusTestCases[] = {
1080 "-5",
1081 "\\u22125",
1082 "\\u27965"
1083};
1084
1085static const char *lenientCurrencyTestCases[] = {
1086 "$1,000",
1087 "$ 1,000",
1088 "$1000",
1089 "$ 1000",
1090 "$1 000.00",
1091 "$ 1 000.00",
1092 "$ 1\\u00A0000.00",
1093 "1000.00"
1094};
1095
1096// changed from () to - per cldrbug 5674
1097static const char *lenientNegativeCurrencyTestCases[] = {
1098 "-$1,000",
1099 "-$ 1,000",
1100 "-$1000",
1101 "-$ 1000",
1102 "-$1 000.00",
1103 "-$ 1 000.00",
1104 "- $ 1,000.00 ",
1105 "-$ 1\\u00A0000.00",
1106 "-1000.00"
1107};
1108
1109static const char *lenientPercentTestCases[] = {
1110 "25%",
1111 " 25%",
1112 " 25 %",
1113 "25 %",
1114 "25\\u00A0%",
1115 "25"
1116};
1117
1118static const char *lenientNegativePercentTestCases[] = {
1119 "-25%",
1120 " -25%",
1121 " - 25%",
1122 "- 25 %",
1123 " - 25 %",
1124 "-25 %",
1125 "-25\\u00A0%",
1126 "-25",
1127 "- 25"
1128};
1129
1130static const char *strictFailureTestCases[] = {
1131 " 1000",
1132 "10,00",
1133 "1,000,.0"
1134};
1135
1136/**
1137 * Test lenient parsing.
1138 */
1139void
1140NumberFormatTest::TestLenientParse(void)
1141{
1142 UErrorCode status = U_ZERO_ERROR;
1143 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
1144 Formattable n;
1145
1146 if (format == NULL || U_FAILURE(status)) {
1147 dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
1148 } else {
1149 format->setLenient(TRUE);
1150 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
1151 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
1152
1153 format->parse(testCase, n, status);
1154 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1155
1156 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
1157 n.getLong() != 1) {
1158 dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
1159 + (UnicodeString) "\"; error code = " + u_errorName(status));
1160 status = U_ZERO_ERROR;
1161 }
1162 }
1163 delete format;
1164 }
1165
1166 Locale en_US("en_US");
1167 Locale sv_SE("sv_SE");
1168
1169 NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
1170
1171 if (mFormat == NULL || U_FAILURE(status)) {
1172 dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
1173 } else {
1174 mFormat->setLenient(TRUE);
1175 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1176 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1177
1178 mFormat->parse(testCase, n, status);
1179 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1180
1181 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1182 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1183 + (UnicodeString) "\"; error code = " + u_errorName(status));
1184 status = U_ZERO_ERROR;
1185 }
1186 }
1187 delete mFormat;
1188 }
1189
1190 mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
1191
1192 if (mFormat == NULL || U_FAILURE(status)) {
1193 dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
1194 } else {
1195 mFormat->setLenient(TRUE);
1196 for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
1197 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
1198
1199 mFormat->parse(testCase, n, status);
1200 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1201
1202 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
1203 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
1204 + (UnicodeString) "\"; error code = " + u_errorName(status));
1205 status = U_ZERO_ERROR;
1206 }
1207 }
1208 delete mFormat;
1209 }
1210
1211 NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
1212
1213 if (cFormat == NULL || U_FAILURE(status)) {
1214 dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
1215 } else {
1216 cFormat->setLenient(TRUE);
1217 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
1218 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
1219
1220 cFormat->parse(testCase, n, status);
1221 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1222
1223 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1224 n.getLong() != 1000) {
1225 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
1226 + (UnicodeString) "\"; error code = " + u_errorName(status));
1227 status = U_ZERO_ERROR;
1228 }
1229 }
1230
1231 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
1232 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
1233
1234 cFormat->parse(testCase, n, status);
1235 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1236
1237 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1238 n.getLong() != -1000) {
1239 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
1240 + (UnicodeString) "\"; error code = " + u_errorName(status));
1241 status = U_ZERO_ERROR;
1242 }
1243 }
1244
1245 delete cFormat;
1246 }
1247
1248 NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
1249
1250 if (pFormat == NULL || U_FAILURE(status)) {
1251 dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
1252 } else {
1253 pFormat->setLenient(TRUE);
1254 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
1255 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
1256
1257 pFormat->parse(testCase, n, status);
1258 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1259
1260 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1261 n.getDouble() != 0.25) {
1262 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
1263 + (UnicodeString) "\"; error code = " + u_errorName(status)
1264 + "; got: " + n.getDouble(status));
1265 status = U_ZERO_ERROR;
1266 }
1267 }
1268
1269 for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
1270 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
1271
1272 pFormat->parse(testCase, n, status);
1273 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
1274
1275 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1276 n.getDouble() != -0.25) {
1277 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
1278 + (UnicodeString) "\"; error code = " + u_errorName(status)
1279 + "; got: " + n.getDouble(status));
1280 status = U_ZERO_ERROR;
1281 }
1282 }
1283
1284 delete pFormat;
1285 }
1286
1287 // Test cases that should fail with a strict parse and pass with a
1288 // lenient parse.
1289 NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1290
1291 if (nFormat == NULL || U_FAILURE(status)) {
1292 dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
1293 } else {
1294 // first, make sure that they fail with a strict parse
1295 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1296 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1297
1298 nFormat->parse(testCase, n, status);
1299 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1300
1301 if (! U_FAILURE(status)) {
1302 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
1303 + (UnicodeString) "\"; error code = " + u_errorName(status));
1304 }
1305
1306 status = U_ZERO_ERROR;
1307 }
1308
1309 // then, make sure that they pass with a lenient parse
1310 nFormat->setLenient(TRUE);
1311 for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
1312 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1313
1314 nFormat->parse(testCase, n, status);
1315 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1316
1317 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1318 n.getLong() != 1000) {
1319 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
1320 + (UnicodeString) "\"; error code = " + u_errorName(status));
1321 status = U_ZERO_ERROR;
1322 }
1323 }
1324
1325 delete nFormat;
1326 }
1327}
1328
1329// -------------------------------------
1330
1331/**
1332 * Test proper rounding by the format method.
1333 */
1334void
1335NumberFormatTest::TestRounding487(void)
1336{
1337 UErrorCode status = U_ZERO_ERROR;
1338 NumberFormat *nf = NumberFormat::createInstance(status);
1339 if (U_FAILURE(status)) {
1340 dataerrln("Error calling NumberFormat::createInstance()");
1341 return;
1342 }
1343
1344 roundingTest(*nf, 0.00159999, 4, "0.0016");
1345 roundingTest(*nf, 0.00995, 4, "0.01");
1346
1347 roundingTest(*nf, 12.3995, 3, "12.4");
1348
1349 roundingTest(*nf, 12.4999, 0, "12");
1350 roundingTest(*nf, - 19.5, 0, "-20");
1351 delete nf;
1352 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1353}
1354
1355/**
1356 * Test the functioning of the secondary grouping value.
1357 */
1358void NumberFormatTest::TestSecondaryGrouping(void) {
1359 UErrorCode status = U_ZERO_ERROR;
1360 DecimalFormatSymbols US(Locale::getUS(), status);
1361 CHECK(status, "DecimalFormatSymbols ct");
1362
1363 DecimalFormat f("#,##,###", US, status);
1364 CHECK(status, "DecimalFormat ct");
1365
1366 expect2(f, (int32_t)123456789L, "12,34,56,789");
1367 expectPat(f, "#,##,##0");
1368 f.applyPattern("#,###", status);
1369 CHECK(status, "applyPattern");
1370
1371 f.setSecondaryGroupingSize(4);
1372 expect2(f, (int32_t)123456789L, "12,3456,789");
1373 expectPat(f, "#,####,##0");
1374 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1375 CHECK_DATA(status, "createInstance(hi_IN)");
1376
1377 UnicodeString out;
1378 int32_t l = (int32_t)1876543210L;
1379 g->format(l, out);
1380 delete g;
1381 // expect "1,87,65,43,210", but with Hindi digits
1382 // 01234567890123
1383 UBool ok = TRUE;
1384 if (out.length() != 14) {
1385 ok = FALSE;
1386 } else {
1387 for (int32_t i=0; i<out.length(); ++i) {
1388 UBool expectGroup = FALSE;
1389 switch (i) {
1390 case 1:
1391 case 4:
1392 case 7:
1393 case 10:
1394 expectGroup = TRUE;
1395 break;
1396 }
1397 // Later -- fix this to get the actual grouping
1398 // character from the resource bundle.
1399 UBool isGroup = (out.charAt(i) == 0x002C);
1400 if (isGroup != expectGroup) {
1401 ok = FALSE;
1402 break;
1403 }
1404 }
1405 }
1406 if (!ok) {
1407 errln((UnicodeString)"FAIL Expected " + l +
1408 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1409 escape(out) + "\"");
1410 } else {
1411 logln((UnicodeString)"Ok " + l +
1412 " x hi_IN -> \"" +
1413 escape(out) + "\"");
1414 }
1415}
1416
1417void NumberFormatTest::TestWhiteSpaceParsing(void) {
1418 UErrorCode ec = U_ZERO_ERROR;
1419 DecimalFormatSymbols US(Locale::getUS(), ec);
1420 DecimalFormat fmt("a b#0c ", US, ec);
1421 if (U_FAILURE(ec)) {
1422 errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
1423 return;
1424 }
1425 // From ICU 62, flexible whitespace needs lenient mode
1426 fmt.setLenient(TRUE);
1427 int32_t n = 1234;
1428 expect(fmt, "a b1234c ", n);
1429 expect(fmt, "a b1234c ", n);
1430}
1431
1432/**
1433 * Test currencies whose display name is a ChoiceFormat.
1434 */
1435void NumberFormatTest::TestComplexCurrency() {
1436
1437// UErrorCode ec = U_ZERO_ERROR;
1438// Locale loc("kn", "IN", "");
1439// NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1440// if (U_SUCCESS(ec)) {
1441// expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
1442// Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1443// expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
1444// expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1445// expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1446// expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
1447// expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1448// } else {
1449// errln("FAIL: getCurrencyInstance(kn_IN)");
1450// }
1451// delete fmt;
1452
1453}
1454
1455// -------------------------------------
1456
1457void
1458NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1459{
1460 nf.setMaximumFractionDigits(maxFractionDigits);
1461 UnicodeString out; nf.format(x, out);
1462 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1463 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1464}
1465
1466/**
1467 * Upgrade to alphaWorks
1468 */
1469void NumberFormatTest::TestExponent(void) {
1470 UErrorCode status = U_ZERO_ERROR;
1471 DecimalFormatSymbols US(Locale::getUS(), status);
1472 CHECK(status, "DecimalFormatSymbols constructor");
1473 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1474 CHECK(status, "DecimalFormat(0.###E0)");
1475 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1476 CHECK(status, "DecimalFormat(0.###E+0)");
1477 int32_t n = 1234;
1478 expect2(fmt1, n, "1.234E3");
1479 expect2(fmt2, n, "1.234E+3");
1480 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1481}
1482
1483/**
1484 * Upgrade to alphaWorks
1485 */
1486void NumberFormatTest::TestScientific(void) {
1487 UErrorCode status = U_ZERO_ERROR;
1488 DecimalFormatSymbols US(Locale::getUS(), status);
1489 CHECK(status, "DecimalFormatSymbols constructor");
1490
1491 // Test pattern round-trip
1492 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1493 "0.###E0;[0.###E0]" };
1494 int32_t PAT_length = UPRV_LENGTHOF(PAT);
1495 int32_t DIGITS[] = {
1496 // min int, max int, min frac, max frac
1497 1, 1, 0, 0, // "#E0"
1498 1, 1, 0, 4, // "0.####E0"
1499 2, 2, 3, 3, // "00.000E00"
1500 1, 3, 0, 4, // "##0.####E000"
1501 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1502 };
1503 for (int32_t i=0; i<PAT_length; ++i) {
1504 UnicodeString pat(PAT[i]);
1505 DecimalFormat df(pat, US, status);
1506 CHECK(status, "DecimalFormat constructor");
1507 UnicodeString pat2;
1508 df.toPattern(pat2);
1509 if (pat == pat2) {
1510 logln(UnicodeString("Ok Pattern rt \"") +
1511 pat + "\" -> \"" +
1512 pat2 + "\"");
1513 } else {
1514 errln(UnicodeString("FAIL Pattern rt \"") +
1515 pat + "\" -> \"" +
1516 pat2 + "\"");
1517 }
1518 // Make sure digit counts match what we expect
1519 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1520 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1521 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1522 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1523 errln(UnicodeString("FAIL \"" + pat +
1524 "\" min/max int; min/max frac = ") +
1525 df.getMinimumIntegerDigits() + "/" +
1526 df.getMaximumIntegerDigits() + ";" +
1527 df.getMinimumFractionDigits() + "/" +
1528 df.getMaximumFractionDigits() + ", expect " +
1529 DIGITS[4*i] + "/" +
1530 DIGITS[4*i+1] + ";" +
1531 DIGITS[4*i+2] + "/" +
1532 DIGITS[4*i+3]);
1533 }
1534 }
1535
1536
1537 // Test the constructor for default locale. We have to
1538 // manually set the default locale, as there is no
1539 // guarantee that the default locale has the same
1540 // scientific format.
1541 Locale def = Locale::getDefault();
1542 Locale::setDefault(Locale::getUS(), status);
1543 expect2(NumberFormat::createScientificInstance(status),
1544 12345.678901,
1545 "1.2345678901E4", status);
1546 Locale::setDefault(def, status);
1547
1548 expect2(new DecimalFormat("#E0", US, status),
1549 12345.0,
1550 "1.2345E4", status);
1551 expect(new DecimalFormat("0E0", US, status),
1552 12345.0,
1553 "1E4", status);
1554 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1555 12345.678901,
1556 "1.2345678901E4", status);
1557 expect(new DecimalFormat("##0.###E0", US, status),
1558 12345.0,
1559 "12.34E3", status);
1560 expect(new DecimalFormat("##0.###E0", US, status),
1561 12345.00001,
1562 "12.35E3", status);
1563 expect2(new DecimalFormat("##0.####E0", US, status),
1564 (int32_t) 12345,
1565 "12.345E3", status);
1566 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1567 12345.678901,
1568 "1,2345678901E4", status);
1569 expect(new DecimalFormat("##0.####E0", US, status),
1570 789.12345e-9,
1571 "789.12E-9", status);
1572 expect2(new DecimalFormat("##0.####E0", US, status),
1573 780.e-9,
1574 "780E-9", status);
1575 expect(new DecimalFormat(".###E0", US, status),
1576 45678.0,
1577 ".457E5", status);
1578 expect2(new DecimalFormat(".###E0", US, status),
1579 (int32_t) 0,
1580 ".0E0", status);
1581 /*
1582 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1583 new DecimalFormat("##E0", US),
1584 new DecimalFormat("####E0", US),
1585 new DecimalFormat("0E0", US),
1586 new DecimalFormat("00E0", US),
1587 new DecimalFormat("000E0", US),
1588 },
1589 new Long(45678000),
1590 new String[] { "4.5678E7",
1591 "45.678E6",
1592 "4567.8E4",
1593 "5E7",
1594 "46E6",
1595 "457E5",
1596 }
1597 );
1598 !
1599 ! Unroll this test into individual tests below...
1600 !
1601 */
1602 expect2(new DecimalFormat("#E0", US, status),
1603 (int32_t) 45678000, "4.5678E7", status);
1604 expect2(new DecimalFormat("##E0", US, status),
1605 (int32_t) 45678000, "45.678E6", status);
1606 expect2(new DecimalFormat("####E0", US, status),
1607 (int32_t) 45678000, "4567.8E4", status);
1608 expect(new DecimalFormat("0E0", US, status),
1609 (int32_t) 45678000, "5E7", status);
1610 expect(new DecimalFormat("00E0", US, status),
1611 (int32_t) 45678000, "46E6", status);
1612 expect(new DecimalFormat("000E0", US, status),
1613 (int32_t) 45678000, "457E5", status);
1614 /*
1615 expect(new DecimalFormat("###E0", US, status),
1616 new Object[] { new Double(0.0000123), "12.3E-6",
1617 new Double(0.000123), "123E-6",
1618 new Double(0.00123), "1.23E-3",
1619 new Double(0.0123), "12.3E-3",
1620 new Double(0.123), "123E-3",
1621 new Double(1.23), "1.23E0",
1622 new Double(12.3), "12.3E0",
1623 new Double(123), "123E0",
1624 new Double(1230), "1.23E3",
1625 });
1626 !
1627 ! Unroll this test into individual tests below...
1628 !
1629 */
1630 expect2(new DecimalFormat("###E0", US, status),
1631 0.0000123, "12.3E-6", status);
1632 expect2(new DecimalFormat("###E0", US, status),
1633 0.000123, "123E-6", status);
1634 expect2(new DecimalFormat("###E0", US, status),
1635 0.00123, "1.23E-3", status);
1636 expect2(new DecimalFormat("###E0", US, status),
1637 0.0123, "12.3E-3", status);
1638 expect2(new DecimalFormat("###E0", US, status),
1639 0.123, "123E-3", status);
1640 expect2(new DecimalFormat("###E0", US, status),
1641 1.23, "1.23E0", status);
1642 expect2(new DecimalFormat("###E0", US, status),
1643 12.3, "12.3E0", status);
1644 expect2(new DecimalFormat("###E0", US, status),
1645 123.0, "123E0", status);
1646 expect2(new DecimalFormat("###E0", US, status),
1647 1230.0, "1.23E3", status);
1648 /*
1649 expect(new DecimalFormat("0.#E+00", US, status),
1650 new Object[] { new Double(0.00012), "1.2E-04",
1651 new Long(12000), "1.2E+04",
1652 });
1653 !
1654 ! Unroll this test into individual tests below...
1655 !
1656 */
1657 expect2(new DecimalFormat("0.#E+00", US, status),
1658 0.00012, "1.2E-04", status);
1659 expect2(new DecimalFormat("0.#E+00", US, status),
1660 (int32_t) 12000, "1.2E+04", status);
1661}
1662
1663/**
1664 * Upgrade to alphaWorks
1665 */
1666void NumberFormatTest::TestPad(void) {
1667 UErrorCode status = U_ZERO_ERROR;
1668 DecimalFormatSymbols US(Locale::getUS(), status);
1669 CHECK(status, "DecimalFormatSymbols constructor");
1670
1671 expect2(new DecimalFormat("*^##.##", US, status),
1672 int32_t(0), "^^^^0", status);
1673 expect2(new DecimalFormat("*^##.##", US, status),
1674 -1.3, "^-1.3", status);
1675 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1676 int32_t(0), "0.0E0______ g-m/s^2", status);
1677 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1678 1.0/3, "333.333E-3_ g-m/s^2", status);
1679 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1680 int32_t(0), "0.0______ g-m/s^2", status);
1681 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1682 1.0/3, "0.33333__ g-m/s^2", status);
1683
1684 // Test padding before a sign
1685 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1686 expect2(new DecimalFormat(formatStr, US, status),
1687 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1688 expect2(new DecimalFormat(formatStr, US, status),
1689 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1690 expect2(new DecimalFormat(formatStr, US, status),
1691 int32_t(-1000000),"xxx(1,000,000.0)", status);
1692 expect2(new DecimalFormat(formatStr, US, status),
1693 -100.37, "xxxxxxxx(100.37)", status);
1694 expect2(new DecimalFormat(formatStr, US, status),
1695 -10456.37, "xxxxx(10,456.37)", status);
1696 expect2(new DecimalFormat(formatStr, US, status),
1697 -1120456.37, "xx(1,120,456.37)", status);
1698 expect2(new DecimalFormat(formatStr, US, status),
1699 -112045600.37, "(112,045,600.37)", status);
1700 expect2(new DecimalFormat(formatStr, US, status),
1701 -1252045600.37,"(1,252,045,600.37)", status);
1702
1703 expect2(new DecimalFormat(formatStr, US, status),
1704 int32_t(10), "xxxxxxxxxxxx10.0", status);
1705 expect2(new DecimalFormat(formatStr, US, status),
1706 int32_t(1000),"xxxxxxxxx1,000.0", status);
1707 expect2(new DecimalFormat(formatStr, US, status),
1708 int32_t(1000000),"xxxxx1,000,000.0", status);
1709 expect2(new DecimalFormat(formatStr, US, status),
1710 100.37, "xxxxxxxxxx100.37", status);
1711 expect2(new DecimalFormat(formatStr, US, status),
1712 10456.37, "xxxxxxx10,456.37", status);
1713 expect2(new DecimalFormat(formatStr, US, status),
1714 1120456.37, "xxxx1,120,456.37", status);
1715 expect2(new DecimalFormat(formatStr, US, status),
1716 112045600.37, "xx112,045,600.37", status);
1717 expect2(new DecimalFormat(formatStr, US, status),
1718 10252045600.37,"10,252,045,600.37", status);
1719
1720
1721 // Test padding between a sign and a number
1722 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1723 expect2(new DecimalFormat(formatStr2, US, status),
1724 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1725 expect2(new DecimalFormat(formatStr2, US, status),
1726 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1727 expect2(new DecimalFormat(formatStr2, US, status),
1728 int32_t(-1000000),"(1,000,000.0xxx)", status);
1729 expect2(new DecimalFormat(formatStr2, US, status),
1730 -100.37, "(100.37xxxxxxxx)", status);
1731 expect2(new DecimalFormat(formatStr2, US, status),
1732 -10456.37, "(10,456.37xxxxx)", status);
1733 expect2(new DecimalFormat(formatStr2, US, status),
1734 -1120456.37, "(1,120,456.37xx)", status);
1735 expect2(new DecimalFormat(formatStr2, US, status),
1736 -112045600.37, "(112,045,600.37)", status);
1737 expect2(new DecimalFormat(formatStr2, US, status),
1738 -1252045600.37,"(1,252,045,600.37)", status);
1739
1740 expect2(new DecimalFormat(formatStr2, US, status),
1741 int32_t(10), "10.0xxxxxxxxxxxx", status);
1742 expect2(new DecimalFormat(formatStr2, US, status),
1743 int32_t(1000),"1,000.0xxxxxxxxx", status);
1744 expect2(new DecimalFormat(formatStr2, US, status),
1745 int32_t(1000000),"1,000,000.0xxxxx", status);
1746 expect2(new DecimalFormat(formatStr2, US, status),
1747 100.37, "100.37xxxxxxxxxx", status);
1748 expect2(new DecimalFormat(formatStr2, US, status),
1749 10456.37, "10,456.37xxxxxxx", status);
1750 expect2(new DecimalFormat(formatStr2, US, status),
1751 1120456.37, "1,120,456.37xxxx", status);
1752 expect2(new DecimalFormat(formatStr2, US, status),
1753 112045600.37, "112,045,600.37xx", status);
1754 expect2(new DecimalFormat(formatStr2, US, status),
1755 10252045600.37,"10,252,045,600.37", status);
1756
1757 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1758 DecimalFormat fmt("#", US, status);
1759 CHECK(status, "DecimalFormat constructor");
1760 UnicodeString padString("P");
1761 fmt.setPadCharacter(padString);
1762 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1763 fmt.setPadCharacter((UnicodeString)"^");
1764 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1765 //commented until implementation is complete
1766 /* fmt.setPadCharacter((UnicodeString)"^^^");
1767 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1768 padString.remove();
1769 padString.append((UChar)0x0061);
1770 padString.append((UChar)0x0302);
1771 fmt.setPadCharacter(padString);
1772 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1773 UnicodeString pattern(patternChars);
1774 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1775 */
1776
1777}
1778
1779/**
1780 * Upgrade to alphaWorks
1781 */
1782void NumberFormatTest::TestPatterns2(void) {
1783 UErrorCode status = U_ZERO_ERROR;
1784 DecimalFormatSymbols US(Locale::getUS(), status);
1785 CHECK(status, "DecimalFormatSymbols constructor");
1786
1787 DecimalFormat fmt("#", US, status);
1788 CHECK(status, "DecimalFormat constructor");
1789
1790 UChar hat = 0x005E; /*^*/
1791
1792 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1793 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1794 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1795 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1796 expectPad(fmt, "$*^$#", ILLEGAL);
1797 expectPad(fmt, "#$*^$", ILLEGAL);
1798 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1799 12, (UChar)0x0078 /*x*/);
1800 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1801 3, (UChar)0x0078 /*x*/);
1802 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1803 10, (UChar)0x0061 /*a*/);
1804
1805 fmt.applyPattern("AA#,##0.00ZZ", status);
1806 CHECK(status, "applyPattern");
1807 fmt.setPadCharacter(hat);
1808
1809 fmt.setFormatWidth(10);
1810
1811 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1812 expectPat(fmt, "*^AA#,##0.00ZZ");
1813
1814 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1815 expectPat(fmt, "AA#,##0.00*^ZZ");
1816
1817 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1818 expectPat(fmt, "AA#,##0.00ZZ*^");
1819
1820 // 12 3456789012
1821 UnicodeString exp("AA*^#,##0.00ZZ", "");
1822 fmt.setFormatWidth(12);
1823 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1824 expectPat(fmt, exp);
1825
1826 fmt.setFormatWidth(13);
1827 // 12 34567890123
1828 expectPat(fmt, "AA*^##,##0.00ZZ");
1829
1830 fmt.setFormatWidth(14);
1831 // 12 345678901234
1832 expectPat(fmt, "AA*^###,##0.00ZZ");
1833
1834 fmt.setFormatWidth(15);
1835 // 12 3456789012345
1836 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1837
1838 fmt.setFormatWidth(16);
1839 // 12 34567890123456
1840 expectPat(fmt, "AA*^#####,##0.00ZZ");
1841}
1842
1843void NumberFormatTest::TestSurrogateSupport(void) {
1844 UErrorCode status = U_ZERO_ERROR;
1845 DecimalFormatSymbols custom(Locale::getUS(), status);
1846 CHECK(status, "DecimalFormatSymbols constructor");
1847
1848 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1849 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1850 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1851 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1852
1853 UnicodeString patternStr("*\\U00010000##.##", "");
1854 patternStr = patternStr.unescape();
1855 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1856 expStr = expStr.unescape();
1857 expect2(new DecimalFormat(patternStr, custom, status),
1858 int32_t(0), expStr, status);
1859
1860 status = U_ZERO_ERROR;
1861 expect2(new DecimalFormat("*^##.##", custom, status),
1862 int32_t(0), "^^^^0", status);
1863 status = U_ZERO_ERROR;
1864 expect2(new DecimalFormat("##.##", custom, status),
1865 -1.3, " minus 1decimal3", status);
1866 status = U_ZERO_ERROR;
1867 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1868 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1869 status = U_ZERO_ERROR;
1870 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1871 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1872 status = U_ZERO_ERROR;
1873 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1874 int32_t(0), "0decimal0 g-m/s^2", status);
1875 status = U_ZERO_ERROR;
1876 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1877 1.0/3, "0decimal33333 g-m/s^2", status);
1878
1879 UnicodeString zero((UChar32)0x10000);
1880 UnicodeString one((UChar32)0x10001);
1881 UnicodeString two((UChar32)0x10002);
1882 UnicodeString five((UChar32)0x10005);
1883 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1884 custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
1885 custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
1886 custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
1887 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1888 expStr = expStr.unescape();
1889 status = U_ZERO_ERROR;
1890 expect2(new DecimalFormat("##0.000", custom, status),
1891 1.25, expStr, status);
1892
1893 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1894 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1895 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1896 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1897 patternStr = patternStr.unescape();
1898 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1899 status = U_ZERO_ERROR;
1900 expect2(new DecimalFormat(patternStr, custom, status),
1901 int32_t(-20), expStr, status);
1902
1903 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1904 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1905 patternStr = patternStr.unescape();
1906 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1907 status = U_ZERO_ERROR;
1908 expect2(new DecimalFormat(patternStr, custom, status),
1909 int32_t(-20), expStr, status);
1910}
1911
1912void NumberFormatTest::TestCurrencyPatterns(void) {
1913 int32_t i, locCount;
1914 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1915 for (i=0; i<locCount; ++i) {
1916 UErrorCode ec = U_ZERO_ERROR;
1917 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1918 if (U_FAILURE(ec)) {
1919 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1920 } else {
1921 // Make sure currency formats do not have a variable number
1922 // of fraction digits
1923 int32_t min = nf->getMinimumFractionDigits();
1924 int32_t max = nf->getMaximumFractionDigits();
1925 if (min != max) {
1926 UnicodeString a, b;
1927 nf->format(1.0, a);
1928 nf->format(1.125, b);
1929 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1930 " min fraction digits != max fraction digits; "
1931 "x 1.0 => " + escape(a) +
1932 "; x 1.125 => " + escape(b));
1933 }
1934
1935 // Make sure EURO currency formats have exactly 2 fraction digits
1936 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
1937 if (df != NULL) {
1938 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1939 if (min != 2 || max != 2) {
1940 UnicodeString a;
1941 nf->format(1.0, a);
1942 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1943 " is a EURO format but it does not have 2 fraction digits; "
1944 "x 1.0 => " +
1945 escape(a));
1946 }
1947 }
1948 }
1949 }
1950 delete nf;
1951 }
1952}
1953
1954void NumberFormatTest::TestRegCurrency(void) {
1955#if !UCONFIG_NO_SERVICE
1956 UErrorCode status = U_ZERO_ERROR;
1957 UChar USD[4];
1958 ucurr_forLocale("en_US", USD, 4, &status);
1959 UChar YEN[4];
1960 ucurr_forLocale("ja_JP", YEN, 4, &status);
1961 UChar TMP[4];
1962
1963 if(U_FAILURE(status)) {
1964 errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
1965 return;
1966 }
1967
1968 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1969
1970 ucurr_forLocale("en_US", TMP, 4, &status);
1971 if (u_strcmp(YEN, TMP) != 0) {
1972 errln("FAIL: didn't return YEN registered for en_US");
1973 }
1974
1975 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1976 if (fallbackLen) {
1977 errln("FAIL: tried to fallback en_XX_BAR");
1978 }
1979 status = U_ZERO_ERROR; // reset
1980
1981 if (!ucurr_unregister(enkey, &status)) {
1982 errln("FAIL: couldn't unregister enkey");
1983 }
1984
1985 ucurr_forLocale("en_US", TMP, 4, &status);
1986 if (u_strcmp(USD, TMP) != 0) {
1987 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1988 }
1989 status = U_ZERO_ERROR; // reset
1990
1991 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1992 if (u_strcmp(USD, TMP) != 0) {
1993 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1994 }
1995 status = U_ZERO_ERROR; // reset
1996#endif
1997}
1998
1999void NumberFormatTest::TestCurrencyNames(void) {
2000 // Do a basic check of getName()
2001 // USD { "US$", "US Dollar" } // 04/04/1792-
2002 UErrorCode ec = U_ZERO_ERROR;
2003 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
2004 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
2005 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
2006 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
2007 UBool isChoiceFormat;
2008 int32_t len;
2009 const UBool possibleDataError = TRUE;
2010 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
2011 // THE LOCALE DATA before diving into the code.
2012 assertEquals("USD.getName(SYMBOL_NAME, en)",
2013 UnicodeString("$"),
2014 UnicodeString(ucurr_getName(USD, "en",
2015 UCURR_SYMBOL_NAME,
2016 &isChoiceFormat, &len, &ec)),
2017 possibleDataError);
2018 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
2019 UnicodeString("$"),
2020 UnicodeString(ucurr_getName(USD, "en",
2021 UCURR_NARROW_SYMBOL_NAME,
2022 &isChoiceFormat, &len, &ec)),
2023 possibleDataError);
2024 assertEquals("USD.getName(LONG_NAME, en)",
2025 UnicodeString("US Dollar"),
2026 UnicodeString(ucurr_getName(USD, "en",
2027 UCURR_LONG_NAME,
2028 &isChoiceFormat, &len, &ec)),
2029 possibleDataError);
2030 assertEquals("CAD.getName(SYMBOL_NAME, en)",
2031 UnicodeString("CA$"),
2032 UnicodeString(ucurr_getName(CAD, "en",
2033 UCURR_SYMBOL_NAME,
2034 &isChoiceFormat, &len, &ec)),
2035 possibleDataError);
2036 assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
2037 UnicodeString("$"),
2038 UnicodeString(ucurr_getName(CAD, "en",
2039 UCURR_NARROW_SYMBOL_NAME,
2040 &isChoiceFormat, &len, &ec)),
2041 possibleDataError);
2042 assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
2043 UnicodeString("$"),
2044 UnicodeString(ucurr_getName(CAD, "en_CA",
2045 UCURR_SYMBOL_NAME,
2046 &isChoiceFormat, &len, &ec)),
2047 possibleDataError);
2048 assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
2049 UnicodeString("US$"),
2050 UnicodeString(ucurr_getName(USD, "en_CA",
2051 UCURR_SYMBOL_NAME,
2052 &isChoiceFormat, &len, &ec)),
2053 possibleDataError);
2054 assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
2055 UnicodeString("$"),
2056 UnicodeString(ucurr_getName(USD, "en_CA",
2057 UCURR_NARROW_SYMBOL_NAME,
2058 &isChoiceFormat, &len, &ec)),
2059 possibleDataError);
2060 assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
2061 UnicodeString("US$"),
2062 UnicodeString(ucurr_getName(USD, "en_NZ",
2063 UCURR_SYMBOL_NAME,
2064 &isChoiceFormat, &len, &ec)),
2065 possibleDataError);
2066 assertEquals("CAD.getName(SYMBOL_NAME)",
2067 UnicodeString("CA$"),
2068 UnicodeString(ucurr_getName(CAD, "en_NZ",
2069 UCURR_SYMBOL_NAME,
2070 &isChoiceFormat, &len, &ec)),
2071 possibleDataError);
2072 assertEquals("USX.getName(SYMBOL_NAME)",
2073 UnicodeString("USX"),
2074 UnicodeString(ucurr_getName(USX, "en_US",
2075 UCURR_SYMBOL_NAME,
2076 &isChoiceFormat, &len, &ec)),
2077 possibleDataError);
2078 assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
2079 UnicodeString("USX"),
2080 UnicodeString(ucurr_getName(USX, "en_US",
2081 UCURR_NARROW_SYMBOL_NAME,
2082 &isChoiceFormat, &len, &ec)),
2083 possibleDataError);
2084 assertEquals("USX.getName(LONG_NAME)",
2085 UnicodeString("USX"),
2086 UnicodeString(ucurr_getName(USX, "en_US",
2087 UCURR_LONG_NAME,
2088 &isChoiceFormat, &len, &ec)),
2089 possibleDataError);
2090 assertSuccess("ucurr_getName", ec);
2091
2092 ec = U_ZERO_ERROR;
2093
2094 // Test that a default or fallback warning is being returned. JB 4239.
2095 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
2096 &len, &ec);
2097 assertTrue("ucurr_getName (es_ES fallback)",
2098 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2099
2100 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
2101 &len, &ec);
2102 assertTrue("ucurr_getName (zh_TW fallback)",
2103 U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);
2104
2105 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
2106 &len, &ec);
2107 assertTrue("ucurr_getName (en_US default)",
2108 U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);
2109
2110 ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
2111 &len, &ec);
2112 assertTrue("ucurr_getName (ti default)",
2113 U_USING_DEFAULT_WARNING == ec, TRUE);
2114
2115 // Test that a default warning is being returned when falling back to root. JB 4536.
2116 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
2117 &len, &ec);
2118 assertTrue("ucurr_getName (cy default to root)",
2119 U_USING_DEFAULT_WARNING == ec, TRUE);
2120
2121 // TODO add more tests later
2122}
2123
2124void NumberFormatTest::TestCurrencyVariants(){
2125 IcuTestErrorCode status(*this, "TestCurrencyVariants");
2126
2127 struct TestCase {
2128 const char* locale;
2129 const char16_t* isoCode;
2130 const char16_t* expectedShort;
2131 const char16_t* expectedNarrow;
2132 const char16_t* expectedFormal;
2133 const char16_t* expectedVariant;
2134 UErrorCode expectedNarrowError;
2135 } cases[] = {
2136 {"en-US", u"CAD", u"CA$", u"$", u"CA$", u"CA$", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2137 {"en-US", u"CDF", u"CDF", u"CDF", u"CDF", u"CDF", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2138 {"sw-CD", u"CDF", u"FC", u"FC", u"FC", u"FC", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2139 {"en-US", u"GEL", u"GEL", u"₾", u"GEL", u"GEL", U_USING_DEFAULT_WARNING}, // narrow: fallback to root
2140 {"ka-GE", u"GEL", u"₾", u"₾", u"₾", u"₾", U_USING_FALLBACK_WARNING}, // narrow: fallback to ka
2141 {"ka", u"GEL", u"₾", u"₾", u"₾", u"₾", U_ZERO_ERROR}, // no fallback on narrow
2142 {"zh-TW", u"TWD", u"$", u"$", u"NT$", u"$", U_USING_FALLBACK_WARNING}, // narrow: fallback to short
2143 {"ccp", u"TRY", u"TRY", u"₺", u"TRY", u"TL", U_ZERO_ERROR}, // no fallback on variant
2144 };
2145 for (const auto& cas : cases) {
2146 status.setScope(cas.isoCode);
2147 UBool choiceFormatIgnored;
2148 int32_t lengthIgnored;
2149 const UChar* actualShort = ucurr_getName(
2150 cas.isoCode,
2151 cas.locale,
2152 UCURR_SYMBOL_NAME,
2153 &choiceFormatIgnored,
2154 &lengthIgnored,
2155 status);
2156 const UChar* actualFormal = ucurr_getName(
2157 cas.isoCode,
2158 cas.locale,
2159 UCURR_FORMAL_SYMBOL_NAME,
2160 &choiceFormatIgnored,
2161 &lengthIgnored,
2162 status);
2163 const UChar* actualVarant = ucurr_getName(
2164 cas.isoCode,
2165 cas.locale,
2166 UCURR_VARIANT_SYMBOL_NAME,
2167 &choiceFormatIgnored,
2168 &lengthIgnored,
2169 status);
2170 status.errIfFailureAndReset();
2171 const UChar* actualNarrow = ucurr_getName(
2172 cas.isoCode,
2173 cas.locale,
2174 UCURR_NARROW_SYMBOL_NAME,
2175 &choiceFormatIgnored,
2176 &lengthIgnored,
2177 status);
2178 status.expectErrorAndReset(cas.expectedNarrowError);
2179 assertEquals(UnicodeString("Short symbol: ") + cas.locale + u": " + cas.isoCode,
2180 cas.expectedShort, actualShort);
2181 assertEquals(UnicodeString("Narrow symbol: ") + cas.locale + u": " + cas.isoCode,
2182 cas.expectedNarrow, actualNarrow);
2183 assertEquals(UnicodeString("Formal symbol: ") + cas.locale + u": " + cas.isoCode,
2184 cas.expectedFormal, actualFormal);
2185 assertEquals(UnicodeString("Variant symbol: ") + cas.locale + u": " + cas.isoCode,
2186 cas.expectedVariant, actualVarant);
2187 }
2188}
2189
2190void NumberFormatTest::TestCurrencyUnit(void){
2191 UErrorCode ec = U_ZERO_ERROR;
2192 static const UChar USD[] = u"USD";
2193 static const char USD8[] = "USD";
2194 static const UChar BAD[] = u"???";
2195 static const UChar BAD2[] = u"??A";
2196 static const UChar XXX[] = u"XXX";
2197 static const char XXX8[] = "XXX";
2198 static const UChar XYZ[] = u"XYZ";
2199 static const char XYZ8[] = "XYZ";
2200 static const UChar INV[] = u"{$%";
2201 static const char INV8[] = "{$%";
2202 static const UChar ZZZ[] = u"zz";
2203 static const char ZZZ8[] = "zz";
2204 static const UChar JPY[] = u"JPY";
2205 static const char JPY8[] = "JPY";
2206 static const UChar jpy[] = u"jpy";
2207 static const char jpy8[] = "jpy";
2208
2209 UChar* EUR = (UChar*) malloc(6);
2210 EUR[0] = u'E';
2211 EUR[1] = u'U';
2212 EUR[2] = u'R';
2213 char* EUR8 = (char*) malloc(3);
2214 EUR8[0] = 'E';
2215 EUR8[1] = 'U';
2216 EUR8[2] = 'R';
2217
2218 CurrencyUnit cu(USD, ec);
2219 assertSuccess("CurrencyUnit", ec);
2220 assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
2221 assertEquals("getSubtype()", USD8, cu.getSubtype());
2222
2223 // Test XYZ, a valid but non-standard currency.
2224 // Note: Country code XY is private-use, so XYZ should remain unallocated.
2225 CurrencyUnit extended(XYZ, ec);
2226 assertSuccess("non-standard", ec);
2227 assertEquals("non-standard", XYZ, extended.getISOCurrency());
2228 assertEquals("non-standard", XYZ8, extended.getSubtype());
2229
2230 CurrencyUnit inv(INV, ec);
2231 assertEquals("non-invariant", U_INVARIANT_CONVERSION_ERROR, ec);
2232 assertEquals("non-invariant", XXX, inv.getISOCurrency());
2233 ec = U_ZERO_ERROR;
2234
2235 CurrencyUnit zzz(ZZZ, ec);
2236 assertEquals("too short", U_ILLEGAL_ARGUMENT_ERROR, ec);
2237 assertEquals("too short", XXX, zzz.getISOCurrency());
2238 ec = U_ZERO_ERROR;
2239
2240 CurrencyUnit eur(EUR, ec);
2241 assertEquals("non-nul-terminated", u"EUR", eur.getISOCurrency());
2242 assertEquals("non-nul-terminated", "EUR", eur.getSubtype());
2243
2244 // Test StringPiece constructor
2245 CurrencyUnit cu8(USD8, ec);
2246 assertEquals("StringPiece constructor", USD, cu8.getISOCurrency());
2247
2248 CurrencyUnit inv8(INV8, ec);
2249 assertEquals("non-invariant 8", U_INVARIANT_CONVERSION_ERROR, ec);
2250 assertEquals("non-invariant 8", XXX, inv8.getISOCurrency());
2251 ec = U_ZERO_ERROR;
2252
2253 CurrencyUnit zzz8(ZZZ8, ec);
2254 assertEquals("too short 8", U_ILLEGAL_ARGUMENT_ERROR, ec);
2255 assertEquals("too short 8", XXX, zzz8.getISOCurrency());
2256 ec = U_ZERO_ERROR;
2257
2258 CurrencyUnit zzz8b({ZZZ8, 3}, ec);
2259 assertEquals("too short 8b", U_ILLEGAL_ARGUMENT_ERROR, ec);
2260 assertEquals("too short 8b", XXX, zzz8b.getISOCurrency());
2261 ec = U_ZERO_ERROR;
2262
2263 CurrencyUnit eur8({EUR8, 3}, ec);
2264 assertEquals("non-nul-terminated 8", u"EUR", eur8.getISOCurrency());
2265 assertEquals("non-nul-terminated 8", "EUR", eur8.getSubtype());
2266
2267 CurrencyUnit cu2(cu);
2268 if (!(cu2 == cu)){
2269 errln("CurrencyUnit copy constructed object should be same");
2270 }
2271
2272 CurrencyUnit * cu3 = cu.clone();
2273 if (!(*cu3 == cu)){
2274 errln("CurrencyUnit cloned object should be same");
2275 }
2276 CurrencyUnit bad(BAD, ec);
2277 assertSuccess("CurrencyUnit", ec);
2278 if (cu.getOffset() == bad.getOffset()) {
2279 errln("Indexes of different currencies should differ.");
2280 }
2281 CurrencyUnit bad2(BAD2, ec);
2282 assertSuccess("CurrencyUnit", ec);
2283 if (bad2.getOffset() != bad.getOffset()) {
2284 errln("Indexes of unrecognized currencies should be the same.");
2285 }
2286 if (bad == bad2) {
2287 errln("Different unrecognized currencies should not be equal.");
2288 }
2289 bad = bad2;
2290 if (bad != bad2) {
2291 errln("Currency unit assignment should be the same.");
2292 }
2293 delete cu3;
2294
2295 // Test default constructor
2296 CurrencyUnit def;
2297 assertEquals("Default currency", XXX, def.getISOCurrency());
2298 assertEquals("Default currency as subtype", XXX8, def.getSubtype());
2299
2300 // Test slicing
2301 MeasureUnit sliced1 = cu;
2302 MeasureUnit sliced2 = cu;
2303 MeasureUnit sliced3 = extended;
2304 assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
2305 assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
2306 assertEquals("Subtype after slicing 3", XYZ8, sliced3.getSubtype());
2307 CurrencyUnit restored1(sliced1, ec);
2308 CurrencyUnit restored2(sliced2, ec);
2309 CurrencyUnit restored3(sliced3, ec);
2310 assertSuccess("Restoring from MeasureUnit", ec);
2311 assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
2312 assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
2313 assertEquals("Subtype after restoring 3", XYZ8, restored3.getSubtype());
2314 assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
2315 assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
2316 assertEquals("ISO Code after restoring 3", XYZ, restored3.getISOCurrency());
2317
2318 // Test copy constructor failure
2319 LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
2320 assertSuccess("Creating meter", ec);
2321 CurrencyUnit failure(*meter, ec);
2322 assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
2323 assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
2324
2325 // Test equality
2326 ec = U_ZERO_ERROR;
2327 assertFalse("FAIL: USD == JPY", CurrencyUnit(USD, ec) == CurrencyUnit(JPY, ec));
2328 assertTrue("FAIL: USD != USD", CurrencyUnit(USD, ec) == CurrencyUnit(USD, ec));
2329 assertTrue("FAIL: JPY != jpy", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy, ec));
2330 assertTrue("FAIL: jpy != JPY", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY, ec));
2331
2332 // Test equality with system charset instances
2333 assertFalse("FAIL: USD8 == JPY8", CurrencyUnit(USD8, ec) == CurrencyUnit(JPY8, ec));
2334 assertTrue("FAIL: USD8 != USD8", CurrencyUnit(USD8, ec) == CurrencyUnit(USD8, ec));
2335 assertTrue("FAIL: JPY8 != jpy8", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy8, ec));
2336 assertTrue("FAIL: jpy8 != JPY8", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY8, ec));
2337
2338 // Test equality between UTF-16 and system charset instances
2339 assertTrue("FAIL: USD != USD8", CurrencyUnit(USD, ec) == CurrencyUnit(USD8, ec));
2340 assertTrue("FAIL: USD8 != USD", CurrencyUnit(USD8, ec) == CurrencyUnit(USD, ec));
2341 assertTrue("FAIL: JPY != jpy8", CurrencyUnit(JPY, ec) == CurrencyUnit(jpy8, ec));
2342 assertTrue("FAIL: JPY8 != jpy", CurrencyUnit(JPY8, ec) == CurrencyUnit(jpy, ec));
2343 assertTrue("FAIL: jpy != JPY8", CurrencyUnit(jpy, ec) == CurrencyUnit(JPY8, ec));
2344 assertTrue("FAIL: jpy8 != JPY", CurrencyUnit(jpy8, ec) == CurrencyUnit(JPY, ec));
2345
2346 free(EUR);
2347 free(EUR8);
2348}
2349
2350void NumberFormatTest::TestCurrencyAmount(void){
2351 UErrorCode ec = U_ZERO_ERROR;
2352 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
2353 CurrencyAmount ca(9, USD, ec);
2354 assertSuccess("CurrencyAmount", ec);
2355
2356 CurrencyAmount ca2(ca);
2357 if (!(ca2 == ca)){
2358 errln("CurrencyAmount copy constructed object should be same");
2359 }
2360
2361 ca2=ca;
2362 if (!(ca2 == ca)){
2363 errln("CurrencyAmount assigned object should be same");
2364 }
2365
2366 CurrencyAmount *ca3 = ca.clone();
2367 if (!(*ca3 == ca)){
2368 errln("CurrencyAmount cloned object should be same");
2369 }
2370 delete ca3;
2371}
2372
2373void NumberFormatTest::TestSymbolsWithBadLocale(void) {
2374 Locale locDefault;
2375 static const char *badLocales[] = {
2376 // length < ULOC_FULLNAME_CAPACITY
2377 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME",
2378
2379 // length > ULOC_FULLNAME_CAPACITY
2380 "x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME"
2381 }; // expect U_USING_DEFAULT_WARNING for both
2382
2383 unsigned int i;
2384 for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
2385 const char *localeName = badLocales[i];
2386 Locale locBad(localeName);
2387 assertTrue(WHERE, !locBad.isBogus());
2388 UErrorCode status = U_ZERO_ERROR;
2389 UnicodeString intlCurrencySymbol((UChar)0xa4);
2390
2391 intlCurrencySymbol.append((UChar)0xa4);
2392
2393 logln("Current locale is %s", Locale::getDefault().getName());
2394 Locale::setDefault(locBad, status);
2395 logln("Current locale is %s", Locale::getDefault().getName());
2396 DecimalFormatSymbols mySymbols(status);
2397 if (status != U_USING_DEFAULT_WARNING) {
2398 errln("DecimalFormatSymbols should return U_USING_DEFAULT_WARNING.");
2399 }
2400 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
2401 errln("DecimalFormatSymbols does not have the right locale.", locBad.getName());
2402 }
2403 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
2404 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
2405 UnicodeString symbolString = mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum);
2406 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ") + prettify(symbolString));
2407 if (symbolString.length() == 0
2408 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
2409 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
2410 {
2411 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
2412 }
2413 }
2414
2415 status = U_ZERO_ERROR;
2416 Locale::setDefault(locDefault, status);
2417 logln("Current locale is %s", Locale::getDefault().getName());
2418 }
2419}
2420
2421/**
2422 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
2423 * behave the same, except for memory ownership semantics. (No
2424 * version of this test on Java, since Java has only one method.)
2425 */
2426void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
2427 UErrorCode ec = U_ZERO_ERROR;
2428 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2429 if (U_FAILURE(ec)) {
2430 errcheckln(ec, "Fail: DecimalFormatSymbols constructor - %s", u_errorName(ec));
2431 delete sym;
2432 return;
2433 }
2434 UnicodeString pat(" #,##0.00");
2435 pat.insert(0, (UChar)0x00A4);
2436 DecimalFormat fmt(pat, sym, ec);
2437 if (U_FAILURE(ec)) {
2438 errln("Fail: DecimalFormat constructor");
2439 return;
2440 }
2441
2442 UnicodeString str;
2443 fmt.format(2350.75, str);
2444 if (str == "$ 2,350.75") {
2445 logln(str);
2446 } else {
2447 dataerrln("Fail: " + str + ", expected $ 2,350.75");
2448 }
2449
2450 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2451 if (U_FAILURE(ec)) {
2452 errln("Fail: DecimalFormatSymbols constructor");
2453 delete sym;
2454 return;
2455 }
2456 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2457 fmt.adoptDecimalFormatSymbols(sym);
2458
2459 str.truncate(0);
2460 fmt.format(2350.75, str);
2461 if (str == "Q 2,350.75") {
2462 logln(str);
2463 } else {
2464 dataerrln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2465 }
2466
2467 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
2468 if (U_FAILURE(ec)) {
2469 errln("Fail: DecimalFormatSymbols constructor");
2470 delete sym;
2471 return;
2472 }
2473 DecimalFormat fmt2(pat, sym, ec);
2474 if (U_FAILURE(ec)) {
2475 errln("Fail: DecimalFormat constructor");
2476 return;
2477 }
2478
2479 DecimalFormatSymbols sym2(Locale::getUS(), ec);
2480 if (U_FAILURE(ec)) {
2481 errln("Fail: DecimalFormatSymbols constructor");
2482 return;
2483 }
2484 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
2485 fmt2.setDecimalFormatSymbols(sym2);
2486
2487 str.truncate(0);
2488 fmt2.format(2350.75, str);
2489 if (str == "Q 2,350.75") {
2490 logln(str);
2491 } else {
2492 dataerrln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
2493 }
2494}
2495
2496void NumberFormatTest::TestPerMill() {
2497 UErrorCode ec = U_ZERO_ERROR;
2498 UnicodeString str;
2499 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
2500 if (!assertSuccess("DecimalFormat ct", ec)) return;
2501 assertEquals("0.4857 x ###.###\\u2030",
2502 ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
2503
2504 DecimalFormatSymbols sym(Locale::getUS(), ec);
2505 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2506 return;
2507 }
2508 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
2509 DecimalFormat fmt2("", sym, ec);
2510 if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
2511 return;
2512 }
2513 fmt2.applyLocalizedPattern("###.###m", ec);
2514 if (!assertSuccess("setup", ec)) return;
2515 str.truncate(0);
2516 assertEquals("0.4857 x ###.###m",
2517 "485.7m", fmt2.format(0.4857, str));
2518}
2519
2520/**
2521 * Generic test for patterns that should be legal/illegal.
2522 */
2523void NumberFormatTest::TestIllegalPatterns() {
2524 // Test cases:
2525 // Prefix with "-:" for illegal patterns
2526 // Prefix with "+:" for legal patterns
2527 const char* DATA[] = {
2528 // Unquoted special characters in the suffix are illegal
2529 "-:000.000|###",
2530 "+:000.000'|###'",
2531 0
2532 };
2533 for (int32_t i=0; DATA[i]; ++i) {
2534 const char* pat=DATA[i];
2535 UBool valid = (*pat) == '+';
2536 pat += 2;
2537 UErrorCode ec = U_ZERO_ERROR;
2538 DecimalFormat fmt(pat, ec); // locale doesn't matter here
2539 if (U_SUCCESS(ec) == valid) {
2540 logln("Ok: pattern \"%s\": %s",
2541 pat, u_errorName(ec));
2542 } else {
2543 errcheckln(ec, "FAIL: pattern \"%s\" should have %s; got %s",
2544 pat, (valid?"succeeded":"failed"),
2545 u_errorName(ec));
2546 }
2547 }
2548}
2549
2550//----------------------------------------------------------------------
2551
2552static const char* KEYWORDS[] = {
2553 /*0*/ "ref=", // <reference pattern to parse numbers>
2554 /*1*/ "loc=", // <locale for formats>
2555 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2556 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2557 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2558 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2559 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2560 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2561 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2562 0
2563};
2564
2565/**
2566 * Return an integer representing the next token from this
2567 * iterator. The integer will be an index into the given list, or
2568 * -1 if there are no more tokens, or -2 if the token is not on
2569 * the list.
2570 */
2571static int32_t keywordIndex(const UnicodeString& tok) {
2572 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2573 if (tok==KEYWORDS[i]) {
2574 return i;
2575 }
2576 }
2577 return -1;
2578}
2579
2580/**
2581 * Parse a CurrencyAmount using the given NumberFormat, with
2582 * the 'delim' character separating the number and the currency.
2583 */
2584static void parseCurrencyAmount(const UnicodeString& str,
2585 const NumberFormat& fmt,
2586 UChar delim,
2587 Formattable& result,
2588 UErrorCode& ec) {
2589 UnicodeString num, cur;
2590 int32_t i = str.indexOf(delim);
2591 str.extractBetween(0, i, num);
2592 str.extractBetween(i+1, INT32_MAX, cur);
2593 Formattable n;
2594 fmt.parse(num, n, ec);
2595 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2596}
2597
2598void NumberFormatTest::TestCases() {
2599 UErrorCode ec = U_ZERO_ERROR;
2600 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2601 if (U_FAILURE(ec)) {
2602 dataerrln("Couldn't open NumberFormatTestCases.txt");
2603 return;
2604 }
2605 TokenIterator tokens(&reader);
2606
2607 Locale loc("en", "US", "");
2608 DecimalFormat *ref = 0, *fmt = 0;
2609 MeasureFormat *mfmt = 0;
2610 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2611 Formattable n;
2612
2613 for (;;) {
2614 ec = U_ZERO_ERROR;
2615 if (!tokens.next(tok, ec)) {
2616 break;
2617 }
2618 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2619 int32_t cmd = keywordIndex(tok);
2620 switch (cmd) {
2621 case 0:
2622 // ref= <reference pattern>
2623 if (!tokens.next(tok, ec)) goto error;
2624 delete ref;
2625 ref = new DecimalFormat(tok,
2626 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2627 if (U_FAILURE(ec)) {
2628 dataerrln("Error constructing DecimalFormat");
2629 goto error;
2630 }
2631 break;
2632 case 1:
2633 // loc= <locale>
2634 if (!tokens.next(tok, ec)) goto error;
2635 loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
2636 break;
2637 case 2: // f:
2638 case 3: // fp:
2639 case 4: // rt:
2640 case 5: // p:
2641 if (!tokens.next(tok, ec)) goto error;
2642 if (tok != "-") {
2643 pat = tok;
2644 delete fmt;
2645 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2646 if (U_FAILURE(ec)) {
2647 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2648 ec = U_ZERO_ERROR;
2649 if (!tokens.next(tok, ec)) goto error;
2650 if (!tokens.next(tok, ec)) goto error;
2651 if (cmd == 3) {
2652 if (!tokens.next(tok, ec)) goto error;
2653 }
2654 continue;
2655 }
2656 }
2657 if (cmd == 2 || cmd == 3 || cmd == 4) {
2658 // f: <pattern or '-'> <number> <exp. string>
2659 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2660 // rt: <pattern or '-'> <number> <string>
2661 UnicodeString num;
2662 if (!tokens.next(num, ec)) goto error;
2663 if (!tokens.next(str, ec)) goto error;
2664 ref->parse(num, n, ec);
2665 assertSuccess("parse", ec);
2666 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2667 str, fmt->format(n, out.remove(), ec));
2668 assertSuccess("format", ec);
2669 if (cmd == 3) { // fp:
2670 if (!tokens.next(num, ec)) goto error;
2671 ref->parse(num, n, ec);
2672 assertSuccess("parse", ec);
2673 }
2674 if (cmd != 2) { // != f:
2675 Formattable m;
2676 fmt->parse(str, m, ec);
2677 assertSuccess("parse", ec);
2678 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2679 n, m);
2680 }
2681 }
2682 // p: <pattern or '-'> <string to parse> <exp. number>
2683 else {
2684 UnicodeString expstr;
2685 if (!tokens.next(str, ec)) goto error;
2686 if (!tokens.next(expstr, ec)) goto error;
2687 Formattable exp, n;
2688 ref->parse(expstr, exp, ec);
2689 assertSuccess("parse", ec);
2690 fmt->parse(str, n, ec);
2691 assertSuccess("parse", ec);
2692 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2693 exp, n);
2694 }
2695 break;
2696 case 8: // fpc:
2697 if (!tokens.next(tok, ec)) goto error;
2698 if (tok != "-") {
2699 mloc = tok;
2700 delete mfmt;
2701 mfmt = MeasureFormat::createCurrencyFormat(
2702 Locale::createFromName(
2703 CharString().appendInvariantChars(mloc, ec).data()), ec);
2704 if (U_FAILURE(ec)) {
2705 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2706 ec = U_ZERO_ERROR;
2707 if (!tokens.next(tok, ec)) goto error;
2708 if (!tokens.next(tok, ec)) goto error;
2709 if (!tokens.next(tok, ec)) goto error;
2710 continue;
2711 }
2712 } else if (mfmt == NULL) {
2713 errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
2714 if (!tokens.next(tok, ec)) goto error;
2715 if (!tokens.next(tok, ec)) goto error;
2716 if (!tokens.next(tok, ec)) goto error;
2717 continue;
2718 }
2719 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2720 if (!tokens.next(currAmt, ec)) goto error;
2721 if (!tokens.next(str, ec)) goto error;
2722 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2723 if (assertSuccess("parseCurrencyAmount", ec)) {
2724 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2725 str, mfmt->format(n, out.remove(), ec));
2726 assertSuccess("format", ec);
2727 }
2728 if (!tokens.next(currAmt, ec)) goto error;
2729 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2730 if (assertSuccess("parseCurrencyAmount", ec)) {
2731 Formattable m;
2732
2733 mfmt->parseObject(str, m, ec);
2734 if (assertSuccess("parseCurrency", ec)) {
2735 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2736 n, m);
2737 } else {
2738 errln("FAIL: source " + str);
2739 }
2740 }
2741 break;
2742 case 6:
2743 // perr: <pattern or '-'> <invalid string>
2744 errln("FAIL: Under construction");
2745 goto done;
2746 case 7: {
2747 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2748 UnicodeString testpat;
2749 UnicodeString exppat;
2750 if (!tokens.next(testpat, ec)) goto error;
2751 if (!tokens.next(exppat, ec)) goto error;
2752 UBool err = exppat == "err";
2753 UBool existingPat = FALSE;
2754 if (testpat == "-") {
2755 if (err) {
2756 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2757 continue;
2758 }
2759 existingPat = TRUE;
2760 testpat = pat;
2761 }
2762 if (exppat == "-") exppat = testpat;
2763 DecimalFormat* f = 0;
2764 UErrorCode ec2 = U_ZERO_ERROR;
2765 if (existingPat) {
2766 f = fmt;
2767 } else {
2768 f = new DecimalFormat(testpat, ec2);
2769 }
2770 if (U_SUCCESS(ec2)) {
2771 if (err) {
2772 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2773 "\" was accepted");
2774 } else {
2775 UnicodeString pat2;
2776 assertEquals(where + "\"" + testpat + "\".toPattern()",
2777 exppat, f->toPattern(pat2));
2778 }
2779 } else {
2780 if (err) {
2781 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2782 "\" failed: " + u_errorName(ec2));
2783 } else {
2784 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2785 "\" failed: " + u_errorName(ec2));
2786 }
2787 }
2788 if (!existingPat) delete f;
2789 } break;
2790 case -1:
2791 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2792 goto done;
2793 }
2794 }
2795 goto done;
2796
2797 error:
2798 if (U_SUCCESS(ec)) {
2799 errln("FAIL: Unexpected EOF");
2800 } else {
2801 errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
2802 }
2803
2804 done:
2805 delete mfmt;
2806 delete fmt;
2807 delete ref;
2808}
2809
2810
2811//----------------------------------------------------------------------
2812// Support methods
2813//----------------------------------------------------------------------
2814
2815UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2816 if (a.getType() == b.getType()) {
2817 return a == b;
2818 }
2819
2820 if (a.getType() == Formattable::kLong) {
2821 if (b.getType() == Formattable::kInt64) {
2822 return a.getLong() == b.getLong();
2823 } else if (b.getType() == Formattable::kDouble) {
2824 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2825 }
2826 } else if (a.getType() == Formattable::kDouble) {
2827 if (b.getType() == Formattable::kLong) {
2828 return a.getDouble() == (double) b.getLong();
2829 } else if (b.getType() == Formattable::kInt64) {
2830 return a.getDouble() == (double)b.getInt64();
2831 }
2832 } else if (a.getType() == Formattable::kInt64) {
2833 if (b.getType() == Formattable::kLong) {
2834 return a.getInt64() == (int64_t)b.getLong();
2835 } else if (b.getType() == Formattable::kDouble) {
2836 return a.getInt64() == (int64_t)b.getDouble();
2837 }
2838 }
2839 return FALSE;
2840}
2841
2842void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2843 // Don't round-trip format test, since we explicitly do it
2844 expect_rbnf(fmt, n, str, FALSE);
2845 expect_rbnf(fmt, str, n);
2846}
2847
2848void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2849 // Don't round-trip format test, since we explicitly do it
2850 expect(fmt, n, str, FALSE);
2851 expect(fmt, str, n);
2852}
2853
2854void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2855 const UnicodeString& exp,
2856 UErrorCode status) {
2857 if (fmt == NULL || U_FAILURE(status)) {
2858 dataerrln("FAIL: NumberFormat constructor");
2859 } else {
2860 expect2(*fmt, n, exp);
2861 }
2862 delete fmt;
2863}
2864
2865void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2866 UErrorCode status = U_ZERO_ERROR;
2867 Formattable num;
2868 fmt.parse(str, num, status);
2869 if (U_FAILURE(status)) {
2870 dataerrln(UnicodeString("FAIL: Parse failed for \"") + str + "\" - " + u_errorName(status));
2871 return;
2872 }
2873 UnicodeString pat;
2874 ((DecimalFormat*) &fmt)->toPattern(pat);
2875 if (equalValue(num, n)) {
2876 logln(UnicodeString("Ok \"") + str + "\" x " +
2877 pat + " = " +
2878 toString(num));
2879 } else {
2880 dataerrln(UnicodeString("FAIL \"") + str + "\" x " +
2881 pat + " = " +
2882 toString(num) + ", expected " + toString(n));
2883 }
2884}
2885
2886void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2887 UErrorCode status = U_ZERO_ERROR;
2888 Formattable num;
2889 fmt.parse(str, num, status);
2890 if (U_FAILURE(status)) {
2891 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2892 return;
2893 }
2894 if (equalValue(num, n)) {
2895 logln(UnicodeString("Ok \"") + str + " = " +
2896 toString(num));
2897 } else {
2898 errln(UnicodeString("FAIL \"") + str + " = " +
2899 toString(num) + ", expected " + toString(n));
2900 }
2901}
2902
2903void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
2904 const UnicodeString& exp, UBool rt) {
2905 UnicodeString saw;
2906 FieldPosition pos;
2907 UErrorCode status = U_ZERO_ERROR;
2908 fmt.format(n, saw, pos, status);
2909 CHECK(status, "NumberFormat::format");
2910 if (saw == exp) {
2911 logln(UnicodeString("Ok ") + toString(n) +
2912 " = \"" +
2913 escape(saw) + "\"");
2914 // We should be able to round-trip the formatted string =>
2915 // number => string (but not the other way around: number
2916 // => string => number2, might have number2 != number):
2917 if (rt) {
2918 Formattable n2;
2919 fmt.parse(exp, n2, status);
2920 if (U_FAILURE(status)) {
2921 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2922 return;
2923 }
2924 UnicodeString saw2;
2925 fmt.format(n2, saw2, pos, status);
2926 CHECK(status, "NumberFormat::format");
2927 if (saw2 != exp) {
2928 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2929 " => \"" + saw2 + "\"");
2930 }
2931 }
2932 } else {
2933 errln(UnicodeString("FAIL ") + toString(n) +
2934 " = \"" +
2935 escape(saw) + "\", expected \"" + exp + "\"");
2936 }
2937}
2938
2939void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2940 const UnicodeString& exp, UBool rt) {
2941 UnicodeString saw;
2942 FieldPosition pos;
2943 UErrorCode status = U_ZERO_ERROR;
2944 fmt.format(n, saw, pos, status);
2945 CHECK(status, "NumberFormat::format");
2946 UnicodeString pat;
2947 ((DecimalFormat*) &fmt)->toPattern(pat);
2948 if (saw == exp) {
2949 logln(UnicodeString("Ok ") + toString(n) + " x " +
2950 escape(pat) + " = \"" +
2951 escape(saw) + "\"");
2952 // We should be able to round-trip the formatted string =>
2953 // number => string (but not the other way around: number
2954 // => string => number2, might have number2 != number):
2955 if (rt) {
2956 Formattable n2;
2957 fmt.parse(exp, n2, status);
2958 if (U_FAILURE(status)) {
2959 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
2960 return;
2961 }
2962 UnicodeString saw2;
2963 fmt.format(n2, saw2, pos, status);
2964 CHECK(status, "NumberFormat::format");
2965 if (saw2 != exp) {
2966 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2967 " => \"" + saw2 + "\"");
2968 }
2969 }
2970 } else {
2971 dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
2972 escape(pat) + " = \"" +
2973 escape(saw) + "\", expected \"" + exp + "\"");
2974 }
2975}
2976
2977void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2978 const UnicodeString& exp, UBool rt,
2979 UErrorCode status) {
2980 if (fmt == NULL || U_FAILURE(status)) {
2981 dataerrln("FAIL: NumberFormat constructor");
2982 } else {
2983 expect(*fmt, n, exp, rt);
2984 }
2985 delete fmt;
2986}
2987
2988void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2989 double value, const UnicodeString& string) {
2990 UErrorCode ec = U_ZERO_ERROR;
2991 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2992 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2993 UChar curr[4];
2994 u_strcpy(curr, DEFAULT_CURR);
2995 if (*locale.getLanguage() != 0) {
2996 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2997 assertSuccess("ucurr_forLocale", ec);
2998 fmt.setCurrency(curr, ec);
2999 assertSuccess("DecimalFormat::setCurrency", ec);
3000 fmt.setCurrency(curr); //Deprecated variant, for coverage only
3001 }
3002 UnicodeString s;
3003 fmt.format(value, s);
3004 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
3005
3006 // Default display of the number yields "1234.5599999999999"
3007 // instead of "1234.56". Use a formatter to fix this.
3008 NumberFormat* f =
3009 NumberFormat::createInstance(Locale::getUS(), ec);
3010 UnicodeString v;
3011 if (U_FAILURE(ec)) {
3012 // Oops; bad formatter. Use default op+= display.
3013 v = (UnicodeString)"" + value;
3014 } else {
3015 f->setMaximumFractionDigits(4);
3016 f->setGroupingUsed(FALSE);
3017 f->format(value, v);
3018 }
3019 delete f;
3020
3021 if (s == string) {
3022 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
3023 } else {
3024 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
3025 ", expected " + prettify(string));
3026 }
3027}
3028
3029void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
3030 UnicodeString pat;
3031 fmt.toPattern(pat);
3032 if (pat == exp) {
3033 logln(UnicodeString("Ok \"") + pat + "\"");
3034 } else {
3035 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
3036 }
3037}
3038
3039void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3040 int32_t pos) {
3041 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
3042}
3043void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3044 int32_t pos, int32_t width, UChar pad) {
3045 expectPad(fmt, pat, pos, width, UnicodeString(pad));
3046}
3047void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
3048 int32_t pos, int32_t width, const UnicodeString& pad) {
3049 int32_t apos = 0, awidth = 0;
3050 UnicodeString apadStr;
3051 UErrorCode status = U_ZERO_ERROR;
3052 fmt.applyPattern(pat, status);
3053 if (U_SUCCESS(status)) {
3054 apos = fmt.getPadPosition();
3055 awidth = fmt.getFormatWidth();
3056 apadStr=fmt.getPadCharacterString();
3057 } else {
3058 apos = -1;
3059 awidth = width;
3060 apadStr = pad;
3061 }
3062 if (apos == pos && awidth == width && apadStr == pad) {
3063 UnicodeString infoStr;
3064 if (pos == ILLEGAL) {
3065 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
3066 }
3067 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
3068 } else {
3069 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
3070 " width=" + awidth + " pad=" + apadStr +
3071 ", expected " + pos + " " + width + " " + pad);
3072 }
3073}
3074
3075// This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale - FIXME
3076void NumberFormatTest::TestCompatibleCurrencies() {
3077/*
3078 static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
3079 static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
3080 UErrorCode status = U_ZERO_ERROR;
3081 LocalPointer<NumberFormat> fmt(
3082 NumberFormat::createCurrencyInstance(Locale::getUS(), status));
3083 if (U_FAILURE(status)) {
3084 errln("Could not create number format instance.");
3085 return;
3086 }
3087 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3088 expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235");
3089 logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
3090 expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235");
3091 logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
3092 expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235");
3093
3094 LocalPointer<NumberFormat> fmtTW(
3095 NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
3096
3097 logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
3098 expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235");
3099 logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
3100 expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235");
3101
3102 LocalPointer<NumberFormat> fmtJP(
3103 NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
3104
3105 logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
3106 expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
3107 logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
3108 expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
3109
3110 // more..
3111*/
3112}
3113
3114void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
3115 ParsePosition ppos;
3116 UnicodeString utext = ctou(text);
3117 LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
3118 if (!ppos.getIndex()) {
3119 errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
3120 return;
3121 }
3122 UErrorCode status = U_ZERO_ERROR;
3123
3124 char theInfo[100];
3125 sprintf(theInfo, "For locale %s, string \"%s\", currency ",
3126 fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
3127 text);
3128 u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
3129
3130 char theOperation[100];
3131
3132 uprv_strcpy(theOperation, theInfo);
3133 uprv_strcat(theOperation, ", check amount:");
3134 assertTrue(theOperation, amount == currencyAmount->getNumber().getDouble(status));
3135
3136 uprv_strcpy(theOperation, theInfo);
3137 uprv_strcat(theOperation, ", check currency:");
3138 assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
3139}
3140
3141
3142void NumberFormatTest::TestJB3832(){
3143 const char* localeID = "pt_PT@currency=PTE";
3144 Locale loc(localeID);
3145 UErrorCode status = U_ZERO_ERROR;
3146 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
3147 UnicodeString s;
3148 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
3149 if(U_FAILURE(status)){
3150 dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
3151 return;
3152 }
3153 currencyFmt->format(1150.50, s);
3154 if(s!=expected){
3155 errln(UnicodeString("FAIL: Expected: ")+expected
3156 + UnicodeString(" Got: ") + s
3157 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
3158 }
3159 if (U_FAILURE(status)){
3160 errln("FAIL: Status %s", u_errorName(status));
3161 }
3162 delete currencyFmt;
3163}
3164
3165void NumberFormatTest::TestHost()
3166{
3167#if U_PLATFORM_USES_ONLY_WIN32_API
3168 Win32NumberTest::testLocales(this);
3169#endif
3170 Locale loc("en_US@compat=host");
3171 for (UNumberFormatStyle k = UNUM_DECIMAL;
3172 k < UNUM_FORMAT_STYLE_COUNT; k = (UNumberFormatStyle)(k+1)) {
3173 UErrorCode status = U_ZERO_ERROR;
3174 LocalPointer<NumberFormat> full(NumberFormat::createInstance(loc, k, status));
3175 if (!NumberFormat::isStyleSupported(k)) {
3176 if (status != U_UNSUPPORTED_ERROR) {
3177 errln("FAIL: expected style %d to be unsupported - %s",
3178 k, u_errorName(status));
3179 }
3180 continue;
3181 }
3182 if (full.isNull() || U_FAILURE(status)) {
3183 dataerrln("FAIL: Can't create number instance of style %d for host - %s",
3184 k, u_errorName(status));
3185 return;
3186 }
3187 UnicodeString result1;
3188 Formattable number(10.00);
3189 full->format(number, result1, status);
3190 if (U_FAILURE(status)) {
3191 errln("FAIL: Can't format for host");
3192 return;
3193 }
3194 Formattable formattable;
3195 full->parse(result1, formattable, status);
3196 if (U_FAILURE(status)) {
3197 errln("FAIL: Can't parse for host");
3198 return;
3199 }
3200 }
3201}
3202
3203void NumberFormatTest::TestHostClone()
3204{
3205 /*
3206 Verify that a cloned formatter gives the same results
3207 and is useable after the original has been deleted.
3208 */
3209 // This is mainly important on Windows.
3210 UErrorCode status = U_ZERO_ERROR;
3211 Locale loc("en_US@compat=host");
3212 UDate now = Calendar::getNow();
3213 NumberFormat *full = NumberFormat::createInstance(loc, status);
3214 if (full == NULL || U_FAILURE(status)) {
3215 dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
3216 return;
3217 }
3218 UnicodeString result1;
3219 full->format(now, result1, status);
3220 Format *fullClone = full->clone();
3221 delete full;
3222 full = NULL;
3223
3224 UnicodeString result2;
3225 fullClone->format(now, result2, status);
3226 if (U_FAILURE(status)) {
3227 errln("FAIL: format failure.");
3228 }
3229 if (result1 != result2) {
3230 errln("FAIL: Clone returned different result from non-clone.");
3231 }
3232 delete fullClone;
3233}
3234
3235void NumberFormatTest::TestCurrencyFormat()
3236{
3237 // This test is here to increase code coverage.
3238 UErrorCode status = U_ZERO_ERROR;
3239 MeasureFormat *cloneObj;
3240 UnicodeString str;
3241 Formattable toFormat, result;
3242 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
3243
3244 Locale saveDefaultLocale = Locale::getDefault();
3245 Locale::setDefault( Locale::getUK(), status );
3246 if (U_FAILURE(status)) {
3247 errln("couldn't set default Locale!");
3248 return;
3249 }
3250
3251 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
3252 Locale::setDefault( saveDefaultLocale, status );
3253 if (U_FAILURE(status)){
3254 dataerrln("FAIL: Status %s", u_errorName(status));
3255 return;
3256 }
3257 cloneObj = measureObj->clone();
3258 if (cloneObj == NULL) {
3259 errln("Clone doesn't work");
3260 return;
3261 }
3262 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
3263 measureObj->format(toFormat, str, status);
3264 measureObj->parseObject(str, result, status);
3265 if (U_FAILURE(status)){
3266 errln("FAIL: Status %s", u_errorName(status));
3267 }
3268 if (result != toFormat) {
3269 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3270 }
3271 status = U_ZERO_ERROR;
3272 str.truncate(0);
3273 cloneObj->format(toFormat, str, status);
3274 cloneObj->parseObject(str, result, status);
3275 if (U_FAILURE(status)){
3276 errln("FAIL: Status %s", u_errorName(status));
3277 }
3278 if (result != toFormat) {
3279 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
3280 }
3281 if (*measureObj != *cloneObj) {
3282 errln("Cloned object is not equal to the original object");
3283 }
3284 delete measureObj;
3285 delete cloneObj;
3286
3287 status = U_USELESS_COLLATOR_ERROR;
3288 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
3289 errln("createCurrencyFormat should have returned NULL.");
3290 }
3291}
3292
3293/* Port of ICU4J rounding test. */
3294void NumberFormatTest::TestRounding() {
3295 UErrorCode status = U_ZERO_ERROR;
3296 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3297
3298 if (U_FAILURE(status)) {
3299 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3300 return;
3301 }
3302
3303 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
3304 int testValues[]={0, 300};
3305
3306 for (int j=0; j<2; j++) {
3307 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
3308 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
3309 for (int increment=0; increment<6; increment++) {
3310 double base=testValues[j];
3311 double rInc=roundingIncrements[increment];
3312 checkRounding(df, base, 20, rInc);
3313 rInc=1.000000000/rInc;
3314 checkRounding(df, base, 20, rInc);
3315 }
3316 }
3317 }
3318 delete df;
3319}
3320
3321void NumberFormatTest::TestRoundingPattern() {
3322 UErrorCode status = U_ZERO_ERROR;
3323 struct {
3324 UnicodeString pattern;
3325 double testCase;
3326 UnicodeString expected;
3327 } tests[] = {
3328 { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
3329 { (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
3330 };
3331 int32_t numOfTests = UPRV_LENGTHOF(tests);
3332 UnicodeString result;
3333
3334 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
3335 if (U_FAILURE(status)) {
3336 dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
3337 return;
3338 }
3339
3340 for (int32_t i = 0; i < numOfTests; i++) {
3341 result.remove();
3342
3343 df->applyPattern(tests[i].pattern, status);
3344 if (U_FAILURE(status)) {
3345 errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
3346 }
3347
3348 df->format(tests[i].testCase, result);
3349
3350 if (result != tests[i].expected) {
3351 errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
3352 }
3353 }
3354
3355 delete df;
3356}
3357
3358void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
3359 df->setRoundingIncrement(increment);
Frank Tangd2858cb2022-04-08 20:34:12 -07003360 assertEquals("Rounding increment round-trip", increment, df->getRoundingIncrement());
Frank Tang3e05d9d2021-11-08 14:04:04 -08003361 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
3362 for (int i=-iterations; i<=iterations;i++) {
3363 double iValue=base+(increment*(i*0.1));
3364 double smallIncrement=0.00000001;
3365 if (iValue!=0) {
3366 smallIncrement*=iValue;
3367 }
3368 //we not only test the value, but some values in a small range around it
3369 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
3370 lastParsed=checkRound(df, iValue, lastParsed);
3371 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
3372 }
3373}
3374
3375double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
3376 UErrorCode status=U_ZERO_ERROR;
3377 UnicodeString formattedDecimal;
3378 double parsed;
3379 Formattable result;
3380 df->format(iValue, formattedDecimal, status);
3381
3382 if (U_FAILURE(status)) {
3383 errln("Error formatting number.");
3384 }
3385
3386 df->parse(formattedDecimal, result, status);
3387
3388 if (U_FAILURE(status)) {
3389 errln("Error parsing number.");
3390 }
3391
3392 parsed=result.getDouble();
3393
3394 if (lastParsed>parsed) {
3395 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
3396 }
3397
3398 return lastParsed;
3399}
3400
3401void NumberFormatTest::TestNonpositiveMultiplier() {
3402 UErrorCode status = U_ZERO_ERROR;
3403 DecimalFormatSymbols US(Locale::getUS(), status);
3404 CHECK(status, "DecimalFormatSymbols constructor");
3405 DecimalFormat df(UnicodeString("0"), US, status);
3406 CHECK(status, "DecimalFormat(0)");
3407
3408 // test zero multiplier
3409
3410 int32_t mult = df.getMultiplier();
3411 df.setMultiplier(0);
3412 if (df.getMultiplier() != mult) {
3413 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
3414 }
3415
3416 // test negative multiplier
3417
3418 df.setMultiplier(-1);
3419 if (df.getMultiplier() != -1) {
3420 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
3421 return;
3422 }
3423
3424 expect(df, "1122.123", -1122.123);
3425 expect(df, "-1122.123", 1122.123);
3426 expect(df, "1.2", -1.2);
3427 expect(df, "-1.2", 1.2);
3428
3429 // Note: the tests with the final parameter of FALSE will not round trip.
3430 // The initial numeric value will format correctly, after the multiplier.
3431 // Parsing the formatted text will be out-of-range for an int64, however.
3432 // The expect() function could be modified to detect this and fall back
3433 // to looking at the decimal parsed value, but it doesn't.
3434 expect(df, U_INT64_MIN, "9223372036854775808", FALSE);
3435 expect(df, U_INT64_MIN+1, "9223372036854775807");
3436 expect(df, (int64_t)-123, "123");
3437 expect(df, (int64_t)123, "-123");
3438 expect(df, U_INT64_MAX-1, "-9223372036854775806");
3439 expect(df, U_INT64_MAX, "-9223372036854775807");
3440
3441 df.setMultiplier(-2);
3442 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
3443 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
3444 expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);
3445
3446 df.setMultiplier(-7);
3447 expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
3448 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
3449 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
3450
3451 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
3452 // (right now the big numbers get turned into doubles and lose tons of accuracy)
3453 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
3454 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
3455 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
3456 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
3457
3458 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
3459 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3460 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3461 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
3462 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
3463}
3464
3465typedef struct {
3466 const char * stringToParse;
3467 int parsedPos;
3468 int errorIndex;
3469 UBool lenient;
3470} TestSpaceParsingItem;
3471
3472void
3473NumberFormatTest::TestSpaceParsing() {
3474 // the data are:
3475 // the string to be parsed, parsed position, parsed error index
3476 const TestSpaceParsingItem DATA[] = {
3477 {"$124", 4, -1, FALSE},
3478 {"$124 $124", 4, -1, FALSE},
3479 {"$124 ", 4, -1, FALSE},
3480 {"$ 124 ", 0, 1, FALSE},
3481 {"$\\u00A0124 ", 5, -1, FALSE},
3482 {" $ 124 ", 0, 0, FALSE},
3483 {"124$", 0, 4, FALSE},
3484 {"124 $", 0, 3, FALSE},
3485 {"$124", 4, -1, TRUE},
3486 {"$124 $124", 4, -1, TRUE},
3487 {"$124 ", 4, -1, TRUE},
3488 {"$ 124 ", 5, -1, TRUE},
3489 {"$\\u00A0124 ", 5, -1, TRUE},
3490 {" $ 124 ", 6, -1, TRUE},
3491 {"124$", 4, -1, TRUE},
3492 {"124$", 4, -1, TRUE},
3493 {"124 $", 5, -1, TRUE},
3494 {"124 $", 5, -1, TRUE},
3495 };
3496 UErrorCode status = U_ZERO_ERROR;
3497 Locale locale("en_US");
3498 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
3499
3500 if (U_FAILURE(status)) {
3501 delete foo;
3502 return;
3503 }
3504 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3505 ParsePosition parsePosition(0);
3506 UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
3507 int parsedPosition = DATA[i].parsedPos;
3508 int errorIndex = DATA[i].errorIndex;
3509 foo->setLenient(DATA[i].lenient);
3510 Formattable result;
3511 foo->parse(stringToBeParsed, result, parsePosition);
3512 logln("Parsing: " + stringToBeParsed);
3513 if (parsePosition.getIndex() != parsedPosition ||
3514 parsePosition.getErrorIndex() != errorIndex) {
3515 errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
3516 }
3517 if (parsePosition.getErrorIndex() == -1 &&
3518 result.getType() == Formattable::kLong &&
3519 result.getLong() != 124) {
3520 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
3521 }
3522 }
3523 delete foo;
3524}
3525
3526/**
3527 * Test using various numbering systems and numbering system keyword.
3528 */
3529typedef struct {
3530 const char *localeName;
3531 double value;
3532 UBool isRBNF;
3533 const char *expectedResult;
3534} TestNumberingSystemItem;
3535
3536void NumberFormatTest::TestNumberingSystems() {
3537
3538 const TestNumberingSystemItem DATA[] = {
3539 { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
3540 { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
3541 { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
3542 { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
3543 { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
3544 { "ar_MA", 1234.567, FALSE, "1.234,567" },
3545 { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3546 { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
3547 { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
3548 { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
3549 { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
3550 { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
3551 { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
3552 { NULL, 0, FALSE, NULL }
3553 };
3554
3555 UErrorCode ec;
3556
3557 const TestNumberingSystemItem *item;
3558 for (item = DATA; item->localeName != NULL; item++) {
3559 ec = U_ZERO_ERROR;
3560 Locale loc = Locale::createFromName(item->localeName);
3561
3562 NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
3563 if (U_FAILURE(ec)) {
3564 dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
3565 continue;
3566 }
3567 // Clone to test ticket #10682
3568 NumberFormat *fmt = origFmt->clone();
3569 delete origFmt;
3570
3571
3572 if (item->isRBNF) {
3573 expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3574 } else {
3575 expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
3576 }
3577 delete fmt;
3578 }
3579
3580
3581 // Test bogus keyword value
3582 ec = U_ZERO_ERROR;
3583 Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
3584 NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
3585 if ( ec != U_UNSUPPORTED_ERROR ) {
3586 errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
3587 delete fmt4;
3588 }
3589
3590 ec = U_ZERO_ERROR;
3591 NumberingSystem *ns = NumberingSystem::createInstance(ec);
3592 if (U_FAILURE(ec)) {
3593 dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
3594 }
3595
3596 if ( ns != NULL ) {
3597 ns->getDynamicClassID();
3598 ns->getStaticClassID();
3599 } else {
3600 errln("FAIL: getInstance() returned NULL.");
3601 }
3602
3603 NumberingSystem *ns1 = new NumberingSystem(*ns);
3604 if (ns1 == NULL) {
3605 errln("FAIL: NumberSystem copy constructor returned NULL.");
3606 }
3607
3608 delete ns1;
3609 delete ns;
3610
3611}
3612
3613
3614void
3615NumberFormatTest::TestMultiCurrencySign() {
3616 const char* DATA[][6] = {
3617 // the fields in the following test are:
3618 // locale,
3619 // currency pattern (with negative pattern),
3620 // currency number to be formatted,
3621 // currency format using currency symbol name, such as "$" for USD,
3622 // currency format using currency ISO name, such as "USD",
3623 // currency format using plural name, such as "US dollars".
3624 // for US locale
3625 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
3626 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
3627 {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
3628 // for CHINA locale
3629 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
3630 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
3631 {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
3632 };
3633
3634 const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
3635 UnicodeString doubleCurrencyStr(doubleCurrencySign);
3636 const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
3637 UnicodeString tripleCurrencyStr(tripleCurrencySign);
3638
3639 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3640 const char* locale = DATA[i][0];
3641 UnicodeString pat = ctou(DATA[i][1]);
3642 double numberToBeFormat = atof(DATA[i][2]);
3643 UErrorCode status = U_ZERO_ERROR;
3644 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
3645 if (U_FAILURE(status)) {
3646 delete sym;
3647 continue;
3648 }
3649 for (int j=1; j<=3; ++j) {
3650 // j represents the number of currency sign in the pattern.
3651 if (j == 2) {
3652 pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
3653 } else if (j == 3) {
3654 pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
3655 }
3656
3657 DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
3658 if (U_FAILURE(status)) {
3659 errln("FAILED init DecimalFormat ");
3660 delete fmt;
3661 continue;
3662 }
3663 UnicodeString s;
3664 ((NumberFormat*) fmt)->format(numberToBeFormat, s);
3665 // DATA[i][3] is the currency format result using a
3666 // single currency sign.
3667 // DATA[i][4] is the currency format result using
3668 // double currency sign.
3669 // DATA[i][5] is the currency format result using
3670 // triple currency sign.
3671 // DATA[i][j+2] is the currency format result using
3672 // 'j' number of currency sign.
3673 UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
3674 if (s.compare(currencyFormatResult)) {
3675 errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
3676 }
3677 // mix style parsing
3678 for (int k=3; k<=5; ++k) {
3679 // DATA[i][3] is the currency format result using a
3680 // single currency sign.
3681 // DATA[i][4] is the currency format result using
3682 // double currency sign.
3683 // DATA[i][5] is the currency format result using
3684 // triple currency sign.
3685 UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
3686 UErrorCode status = U_ZERO_ERROR;
3687 Formattable parseRes;
3688 fmt->parse(oneCurrencyFormat, parseRes, status);
3689 if (U_FAILURE(status) ||
3690 (parseRes.getType() == Formattable::kDouble &&
3691 parseRes.getDouble() != numberToBeFormat) ||
3692 (parseRes.getType() == Formattable::kLong &&
3693 parseRes.getLong() != numberToBeFormat)) {
3694 errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
3695 i + ", " + j + ", " + k);
3696 }
3697 }
3698 delete fmt;
3699 }
3700 delete sym;
3701 }
3702}
3703
3704
3705void
3706NumberFormatTest::TestCurrencyFormatForMixParsing() {
3707 UErrorCode status = U_ZERO_ERROR;
3708 MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
3709 if (U_FAILURE(status)) {
3710 delete curFmt;
3711 return;
3712 }
3713 const char* formats[] = {
3714 "$1,234.56", // string to be parsed
3715 "USD1,234.56",
3716 "US dollars1,234.56",
3717 // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
3718 };
3719 const CurrencyAmount* curramt = NULL;
3720 for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
3721 UnicodeString stringToBeParsed = ctou(formats[i]);
3722 logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
3723 Formattable result;
3724 UErrorCode status = U_ZERO_ERROR;
3725 curFmt->parseObject(stringToBeParsed, result, status);
3726 if (U_FAILURE(status)) {
3727 errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
3728 } else if (result.getType() != Formattable::kObject ||
3729 (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
3730 curramt->getNumber().getDouble() != 1234.56 ||
3731 UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
3732 ) {
3733 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
3734 if (curramt->getNumber().getDouble() != 1234.56) {
3735 errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
3736 }
3737 if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
3738 errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
3739 }
3740 }
3741 }
3742 delete curFmt;
3743}
3744
3745
3746/** Starting in ICU 62, strict mode is actually strict with currency formats. */
3747void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
3748 IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
3749 LocalPointer<DecimalFormat> df(
3750 dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
3751 if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
3752 UnicodeString pattern;
3753 assertEquals("Test assumes that currency sign is at the beginning",
3754 u"\u00A4#,##0.00",
3755 df->toPattern(pattern));
3756 // Should round-trip on the correct currency format:
3757 expect2(*df, 1.23, u"\u00A41.23");
3758 df->setCurrency(u"EUR", status);
3759 expect2(*df, 1.23, u"\u20AC1.23");
3760 // Should parse with currency in the wrong place in lenient mode
3761 df->setLenient(TRUE);
3762 expect(*df, u"1.23\u20AC", 1.23);
3763 expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
3764 // Should NOT parse with currency in the wrong place in STRICT mode
3765 df->setLenient(FALSE);
3766 {
3767 Formattable result;
3768 ErrorCode failStatus;
3769 df->parse(u"1.23\u20AC", result, failStatus);
3770 assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
3771 }
3772 {
3773 ParsePosition ppos;
3774 df->parseCurrency(u"1.23\u20AC", ppos);
3775 assertEquals("Should fail to parse currency", 0, ppos.getIndex());
3776 }
3777}
3778
3779
3780void
3781NumberFormatTest::TestDecimalFormatCurrencyParse() {
3782 // Locale.US
3783 UErrorCode status = U_ZERO_ERROR;
3784 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
3785 if (U_FAILURE(status)) {
3786 delete sym;
3787 return;
3788 }
3789 UnicodeString pat;
3790 UChar currency = 0x00A4;
3791 // "\xA4#,##0.00;-\xA4#,##0.00"
3792 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
3793 DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
3794 if (U_FAILURE(status)) {
3795 delete fmt;
3796 errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
3797 return;
3798 }
3799 const char* DATA[][2] = {
3800 // the data are:
3801 // string to be parsed, the parsed result (number)
3802 {"$1.00", "1"},
3803 {"USD1.00", "1"},
3804 {"1.00 US dollar", "1"},
3805 {"$1,234.56", "1234.56"},
3806 {"USD1,234.56", "1234.56"},
3807 {"1,234.56 US dollar", "1234.56"},
3808 };
3809 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3810 fmt->setLenient(TRUE);
3811 for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
3812 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
3813 double parsedResult = atof(DATA[i][1]);
3814 UErrorCode status = U_ZERO_ERROR;
3815 Formattable result;
3816 fmt->parse(stringToBeParsed, result, status);
3817 logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
3818 if (U_FAILURE(status) ||
3819 (result.getType() == Formattable::kDouble &&
3820 result.getDouble() != parsedResult) ||
3821 (result.getType() == Formattable::kLong &&
3822 result.getLong() != parsedResult)) {
3823 errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
3824 }
3825 }
3826 delete fmt;
3827}
3828
3829
3830void
3831NumberFormatTest::TestCurrencyIsoPluralFormat() {
3832 static const char* DATA[][6] = {
3833 // the data are:
3834 // locale,
3835 // currency amount to be formatted,
3836 // currency ISO code to be formatted,
3837 // format result using CURRENCYSTYLE,
3838 // format result using ISOCURRENCYSTYLE,
3839 // format result using PLURALCURRENCYSTYLE,
3840
3841 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3842 {"en_US", "1234.56", "USD", "$1,234.56", "USD\\u00A01,234.56", "1,234.56 US dollars"},
3843 {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD\\u00A01,234.56", "-1,234.56 US dollars"},
3844 {"zh_CN", "1", "USD", "US$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7F8E\\u5143"},
3845 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD\\u00A01,234.56", "1,234.56\\u00A0\\u7F8E\\u5143"},
3846 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A01.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3847 {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY\\u00A01,234.56", "1,234.56\\u00A0\\u4EBA\\u6C11\\u5E01"},
3848 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3849 {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3850 {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
3851 // test locale without currency information
3852 {"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
3853 // test choice format
3854 {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
3855 };
3856 static const UNumberFormatStyle currencyStyles[] = {
3857 UNUM_CURRENCY,
3858 UNUM_CURRENCY_ISO,
3859 UNUM_CURRENCY_PLURAL
3860 };
3861
3862 for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
3863 const char* localeString = DATA[i][0];
3864 double numberToBeFormat = atof(DATA[i][1]);
3865 const char* currencyISOCode = DATA[i][2];
3866 logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
3867 Locale locale(localeString);
3868 for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3869 UNumberFormatStyle k = currencyStyles[kIndex];
3870 logln(UnicodeString(u"UNumberFormatStyle: ") + k);
3871 UErrorCode status = U_ZERO_ERROR;
3872 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3873 if (U_FAILURE(status)) {
3874 delete numFmt;
3875 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3876 continue;
3877 }
3878 UChar currencyCode[4];
3879 u_charsToUChars(currencyISOCode, currencyCode, 4);
3880 numFmt->setCurrency(currencyCode, status);
3881 if (U_FAILURE(status)) {
3882 delete numFmt;
3883 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3884 continue;
3885 }
3886
3887 UnicodeString strBuf;
3888 numFmt->format(numberToBeFormat, strBuf);
3889 int resultDataIndex = 3 + kIndex;
3890 // DATA[i][resultDataIndex] is the currency format result
3891 // using 'k' currency style.
3892 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
3893 if (strBuf.compare(formatResult)) {
3894 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
3895 }
3896 // test parsing, and test parsing for all currency formats.
3897 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
3898 numFmt->setLenient(TRUE);
3899 for (int j = 3; j < 6; ++j) {
3900 // DATA[i][3] is the currency format result using
3901 // CURRENCYSTYLE formatter.
3902 // DATA[i][4] is the currency format result using
3903 // ISOCURRENCYSTYLE formatter.
3904 // DATA[i][5] is the currency format result using
3905 // PLURALCURRENCYSTYLE formatter.
3906 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
3907 UErrorCode status = U_ZERO_ERROR;
3908 Formattable parseResult;
3909 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
3910 if (U_FAILURE(status) ||
3911 (parseResult.getType() == Formattable::kDouble &&
3912 parseResult.getDouble() != numberToBeFormat) ||
3913 (parseResult.getType() == Formattable::kLong &&
3914 parseResult.getLong() != numberToBeFormat)) {
3915 errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
3916 localeString + " failed roundtripping the number");
3917 if (parseResult.getType() == Formattable::kDouble) {
3918 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
3919 } else {
3920 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
3921 }
3922 }
3923 }
3924 delete numFmt;
3925 }
3926 }
3927}
3928
3929void
3930NumberFormatTest::TestCurrencyParsing() {
3931 static const char* DATA[][6] = {
3932 // the data are:
3933 // locale,
3934 // currency amount to be formatted,
3935 // currency ISO code to be formatted,
3936 // format result using CURRENCYSTYLE,
3937 // format result using ISOCURRENCYSTYLE,
3938 // format result using PLURALCURRENCYSTYLE,
3939 {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
3940 {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
3941 {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
3942 {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
3943 {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0622\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
3944 {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
3945 {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
3946 {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
3947 {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
3948 {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
3949 {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
3950 {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
3951 {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3952 {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
3953 {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
3954 {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3955 // ICU 62 requires #parseCurrency() to recognize variants when parsing
3956 // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
3957 {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
3958 };
3959 static const UNumberFormatStyle currencyStyles[] = {
3960 UNUM_CURRENCY,
3961 UNUM_CURRENCY_ISO,
3962 UNUM_CURRENCY_PLURAL
3963 };
3964 static const char* currencyStyleNames[] = {
3965 "UNUM_CURRENCY",
3966 "UNUM_CURRENCY_ISO",
3967 "UNUM_CURRENCY_PLURAL"
3968 };
3969
3970#ifdef NUMFMTST_CACHE_DEBUG
3971int deadloop = 0;
3972for (;;) {
3973 printf("loop: %d\n", deadloop++);
3974#endif
3975 for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
3976 for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
3977 UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
3978 const char* localeString = DATA[i][0];
3979 double numberToBeFormat = atof(DATA[i][1]);
3980 const char* currencyISOCode = DATA[i][2];
3981 Locale locale(localeString);
3982 UErrorCode status = U_ZERO_ERROR;
3983 NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
3984 logln("#%d NumberFormat(%s, %s) Currency=%s\n",
3985 i, localeString, currencyStyleNames[kIndex],
3986 currencyISOCode);
3987
3988 if (U_FAILURE(status)) {
3989 delete numFmt;
3990 dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
3991 continue;
3992 }
3993 UChar currencyCode[4];
3994 u_charsToUChars(currencyISOCode, currencyCode, 4);
3995 numFmt->setCurrency(currencyCode, status);
3996 if (U_FAILURE(status)) {
3997 delete numFmt;
3998 errln((UnicodeString)"can not set currency:" + currencyISOCode);
3999 continue;
4000 }
4001
4002 UnicodeString strBuf;
4003 numFmt->format(numberToBeFormat, strBuf);
4004 int resultDataIndex = 3 + kIndex;
4005 // DATA[i][resultDataIndex] is the currency format result
4006 // using 'k' currency style.
4007 UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
4008 if (strBuf.compare(formatResult)) {
4009 errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
4010 }
4011 // test parsing, and test parsing for all currency formats.
4012 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
4013 numFmt->setLenient(TRUE);
4014 for (int j = 3; j < 6; ++j) {
4015 // DATA[i][3] is the currency format result using
4016 // CURRENCYSTYLE formatter.
4017 // DATA[i][4] is the currency format result using
4018 // ISOCURRENCYSTYLE formatter.
4019 // DATA[i][5] is the currency format result using
4020 // PLURALCURRENCYSTYLE formatter.
4021 UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
4022 UErrorCode status = U_ZERO_ERROR;
4023 Formattable parseResult;
4024 logln("parse(%s)", DATA[i][j]);
4025 numFmt->parse(oneCurrencyFormatResult, parseResult, status);
4026 if (U_FAILURE(status) ||
4027 (parseResult.getType() == Formattable::kDouble &&
4028 parseResult.getDouble() != numberToBeFormat) ||
4029 (parseResult.getType() == Formattable::kLong &&
4030 parseResult.getLong() != numberToBeFormat)) {
4031 errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
4032 "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
4033 if (parseResult.getType() == Formattable::kDouble) {
4034 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
4035 } else {
4036 errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
4037 }
4038 errln((UnicodeString)" round-trip would be: " + strBuf);
4039 }
4040 }
4041 delete numFmt;
4042 }
4043 }
4044#ifdef NUMFMTST_CACHE_DEBUG
4045}
4046#endif
4047}
4048
4049
4050void
4051NumberFormatTest::TestParseCurrencyInUCurr() {
4052 const char* DATA[] = {
4053 "1.00 US DOLLAR", // case in-sensitive
4054 "$1.00",
4055 "USD1.00",
4056 "usd1.00", // case in-sensitive: #13696
4057 "US dollar1.00",
4058 "US dollars1.00",
4059 "$1.00",
4060 "A$1.00",
4061 "ADP1.00",
4062 "ADP1.00",
4063 "AED1.00",
4064 "AED1.00",
4065 "AFA1.00",
4066 "AFA1.00",
4067 "AFN1.00",
4068 "ALL1.00",
4069 "AMD1.00",
4070 "ANG1.00",
4071 "AOA1.00",
4072 "AOK1.00",
4073 "AOK1.00",
4074 "AON1.00",
4075 "AON1.00",
4076 "AOR1.00",
4077 "AOR1.00",
4078 "ARS1.00",
4079 "ARA1.00",
4080 "ARA1.00",
4081 "ARP1.00",
4082 "ARP1.00",
4083 "ARS1.00",
4084 "ATS1.00",
4085 "ATS1.00",
4086 "AUD1.00",
4087 "AWG1.00",
4088 "AZM1.00",
4089 "AZM1.00",
4090 "AZN1.00",
4091 "Afghan Afghani (1927\\u20132002)1.00",
4092 "Afghan afghani (1927\\u20132002)1.00",
4093 "Afghan Afghani1.00",
4094 "Afghan Afghanis1.00",
4095 "Albanian Lek1.00",
4096 "Albanian lek1.00",
4097 "Albanian lek\\u00eb1.00",
4098 "Algerian Dinar1.00",
4099 "Algerian dinar1.00",
4100 "Algerian dinars1.00",
4101 "Andorran Peseta1.00",
4102 "Andorran peseta1.00",
4103 "Andorran pesetas1.00",
4104 "Angolan Kwanza (1977\\u20131991)1.00",
4105 "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
4106 "Angolan Kwanza1.00",
4107 "Angolan New Kwanza (1990\\u20132000)1.00",
4108 "Angolan kwanza (1977\\u20131991)1.00",
4109 "Angolan readjusted kwanza (1995\\u20131999)1.00",
4110 "Angolan kwanza1.00",
4111 "Angolan kwanzas (1977\\u20131991)1.00",
4112 "Angolan readjusted kwanzas (1995\\u20131999)1.00",
4113 "Angolan kwanzas1.00",
4114 "Angolan new kwanza (1990\\u20132000)1.00",
4115 "Angolan new kwanzas (1990\\u20132000)1.00",
4116 "Argentine Austral1.00",
4117 "Argentine Peso (1983\\u20131985)1.00",
4118 "Argentine Peso1.00",
4119 "Argentine austral1.00",
4120 "Argentine australs1.00",
4121 "Argentine peso (1983\\u20131985)1.00",
4122 "Argentine peso1.00",
4123 "Argentine pesos (1983\\u20131985)1.00",
4124 "Argentine pesos1.00",
4125 "Armenian Dram1.00",
4126 "Armenian dram1.00",
4127 "Armenian drams1.00",
4128 "Aruban Florin1.00",
4129 "Aruban florin1.00",
4130 "Australian Dollar1.00",
4131 "Australian dollar1.00",
4132 "Australian dollars1.00",
4133 "Austrian Schilling1.00",
4134 "Austrian schilling1.00",
4135 "Austrian schillings1.00",
4136 "Azerbaijani Manat (1993\\u20132006)1.00",
4137 "Azerbaijani Manat1.00",
4138 "Azerbaijani manat (1993\\u20132006)1.00",
4139 "Azerbaijani manat1.00",
4140 "Azerbaijani manats (1993\\u20132006)1.00",
4141 "Azerbaijani manats1.00",
4142 "BAD1.00",
4143 "BAD1.00",
4144 "BAM1.00",
4145 "BBD1.00",
4146 "BDT1.00",
4147 "BEC1.00",
4148 "BEC1.00",
4149 "BEF1.00",
4150 "BEL1.00",
4151 "BEL1.00",
4152 "BGL1.00",
4153 "BGN1.00",
4154 "BGN1.00",
4155 "BHD1.00",
4156 "BIF1.00",
4157 "BMD1.00",
4158 "BND1.00",
4159 "BOB1.00",
4160 "BOP1.00",
4161 "BOP1.00",
4162 "BOV1.00",
4163 "BOV1.00",
4164 "BRB1.00",
4165 "BRB1.00",
4166 "BRC1.00",
4167 "BRC1.00",
4168 "BRE1.00",
4169 "BRE1.00",
4170 "BRL1.00",
4171 "BRN1.00",
4172 "BRN1.00",
4173 "BRR1.00",
4174 "BRR1.00",
4175 "BSD1.00",
4176 "BSD1.00",
4177 "BTN1.00",
4178 "BUK1.00",
4179 "BUK1.00",
4180 "BWP1.00",
4181 "BYB1.00",
4182 "BYB1.00",
4183 "BYR1.00",
4184 "BZD1.00",
4185 "Bahamian Dollar1.00",
4186 "Bahamian dollar1.00",
4187 "Bahamian dollars1.00",
4188 "Bahraini Dinar1.00",
4189 "Bahraini dinar1.00",
4190 "Bahraini dinars1.00",
4191 "Bangladeshi Taka1.00",
4192 "Bangladeshi taka1.00",
4193 "Bangladeshi takas1.00",
4194 "Barbadian Dollar1.00",
4195 "Barbadian dollar1.00",
4196 "Barbadian dollars1.00",
4197 "Belarusian Ruble (1994\\u20131999)1.00",
4198 "Belarusian Ruble1.00",
4199 "Belarusian ruble (1994\\u20131999)1.00",
4200 "Belarusian rubles (1994\\u20131999)1.00",
4201 "Belarusian ruble1.00",
4202 "Belarusian rubles1.00",
4203 "Belgian Franc (convertible)1.00",
4204 "Belgian Franc (financial)1.00",
4205 "Belgian Franc1.00",
4206 "Belgian franc (convertible)1.00",
4207 "Belgian franc (financial)1.00",
4208 "Belgian franc1.00",
4209 "Belgian francs (convertible)1.00",
4210 "Belgian francs (financial)1.00",
4211 "Belgian francs1.00",
4212 "Belize Dollar1.00",
4213 "Belize dollar1.00",
4214 "Belize dollars1.00",
4215 "Bermudan Dollar1.00",
4216 "Bermudan dollar1.00",
4217 "Bermudan dollars1.00",
4218 "Bhutanese Ngultrum1.00",
4219 "Bhutanese ngultrum1.00",
4220 "Bhutanese ngultrums1.00",
4221 "Bolivian Mvdol1.00",
4222 "Bolivian Peso1.00",
4223 "Bolivian mvdol1.00",
4224 "Bolivian mvdols1.00",
4225 "Bolivian peso1.00",
4226 "Bolivian pesos1.00",
4227 "Bolivian Boliviano1.00",
4228 "Bolivian Boliviano1.00",
4229 "Bolivian Bolivianos1.00",
4230 "Bosnia-Herzegovina Convertible Mark1.00",
4231 "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
4232 "Bosnia-Herzegovina convertible mark1.00",
4233 "Bosnia-Herzegovina convertible marks1.00",
4234 "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
4235 "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
4236 "Botswanan Pula1.00",
4237 "Botswanan pula1.00",
4238 "Botswanan pulas1.00",
4239 "Brazilian New Cruzado (1989\\u20131990)1.00",
4240 "Brazilian Cruzado (1986\\u20131989)1.00",
4241 "Brazilian Cruzeiro (1990\\u20131993)1.00",
4242 "Brazilian New Cruzeiro (1967\\u20131986)1.00",
4243 "Brazilian Cruzeiro (1993\\u20131994)1.00",
4244 "Brazilian Real1.00",
4245 "Brazilian new cruzado (1989\\u20131990)1.00",
4246 "Brazilian new cruzados (1989\\u20131990)1.00",
4247 "Brazilian cruzado (1986\\u20131989)1.00",
4248 "Brazilian cruzados (1986\\u20131989)1.00",
4249 "Brazilian cruzeiro (1990\\u20131993)1.00",
4250 "Brazilian new cruzeiro (1967\\u20131986)1.00",
4251 "Brazilian cruzeiro (1993\\u20131994)1.00",
4252 "Brazilian cruzeiros (1990\\u20131993)1.00",
4253 "Brazilian new cruzeiros (1967\\u20131986)1.00",
4254 "Brazilian cruzeiros (1993\\u20131994)1.00",
4255 "Brazilian real1.00",
4256 "Brazilian reals1.00",
4257 "British Pound1.00",
4258 "British pound1.00",
4259 "British pounds1.00",
4260 "Brunei Dollar1.00",
4261 "Brunei dollar1.00",
4262 "Brunei dollars1.00",
4263 "Bulgarian Hard Lev1.00",
4264 "Bulgarian Lev1.00",
4265 "Bulgarian Leva1.00",
4266 "Bulgarian hard lev1.00",
4267 "Bulgarian hard leva1.00",
4268 "Bulgarian lev1.00",
4269 "Burmese Kyat1.00",
4270 "Burmese kyat1.00",
4271 "Burmese kyats1.00",
4272 "Burundian Franc1.00",
4273 "Burundian franc1.00",
4274 "Burundian francs1.00",
4275 "CA$1.00",
4276 "CAD1.00",
4277 "CDF1.00",
4278 "CDF1.00",
4279 "West African CFA Franc1.00",
4280 "Central African CFA Franc1.00",
4281 "West African CFA franc1.00",
4282 "Central African CFA franc1.00",
4283 "West African CFA francs1.00",
4284 "Central African CFA francs1.00",
4285 "CFP Franc1.00",
4286 "CFP franc1.00",
4287 "CFP francs1.00",
4288 "CFPF1.00",
4289 "CHE1.00",
4290 "CHE1.00",
4291 "CHF1.00",
4292 "CHW1.00",
4293 "CHW1.00",
4294 "CLF1.00",
4295 "CLF1.00",
4296 "CLP1.00",
4297 "CNY1.00",
4298 "COP1.00",
4299 "COU1.00",
4300 "COU1.00",
4301 "CRC1.00",
4302 "CSD1.00",
4303 "CSD1.00",
4304 "CSK1.00",
4305 "CSK1.00",
4306 "CUP1.00",
4307 "CUP1.00",
4308 "CVE1.00",
4309 "CYP1.00",
4310 "CZK1.00",
4311 "Cambodian Riel1.00",
4312 "Cambodian riel1.00",
4313 "Cambodian riels1.00",
4314 "Canadian Dollar1.00",
4315 "Canadian dollar1.00",
4316 "Canadian dollars1.00",
4317 "Cape Verdean Escudo1.00",
4318 "Cape Verdean escudo1.00",
4319 "Cape Verdean escudos1.00",
4320 "Cayman Islands Dollar1.00",
4321 "Cayman Islands dollar1.00",
4322 "Cayman Islands dollars1.00",
4323 "Chilean Peso1.00",
4324 "Chilean Unit of Account (UF)1.00",
4325 "Chilean peso1.00",
4326 "Chilean pesos1.00",
4327 "Chilean unit of account (UF)1.00",
4328 "Chilean units of account (UF)1.00",
4329 "Chinese Yuan1.00",
4330 "Chinese yuan1.00",
4331 "Colombian Peso1.00",
4332 "Colombian peso1.00",
4333 "Colombian pesos1.00",
4334 "Comorian Franc1.00",
4335 "Comorian franc1.00",
4336 "Comorian francs1.00",
4337 "Congolese Franc1.00",
4338 "Congolese franc1.00",
4339 "Congolese francs1.00",
4340 "Costa Rican Col\\u00f3n1.00",
4341 "Costa Rican col\\u00f3n1.00",
4342 "Costa Rican col\\u00f3ns1.00",
4343 "Croatian Dinar1.00",
4344 "Croatian Kuna1.00",
4345 "Croatian dinar1.00",
4346 "Croatian dinars1.00",
4347 "Croatian kuna1.00",
4348 "Croatian kunas1.00",
4349 "Cuban Peso1.00",
4350 "Cuban peso1.00",
4351 "Cuban pesos1.00",
4352 "Cypriot Pound1.00",
4353 "Cypriot pound1.00",
4354 "Cypriot pounds1.00",
4355 "Czech Koruna1.00",
4356 "Czech koruna1.00",
4357 "Czech korunas1.00",
4358 "Czechoslovak Hard Koruna1.00",
4359 "Czechoslovak hard koruna1.00",
4360 "Czechoslovak hard korunas1.00",
4361 "DDM1.00",
4362 "DDM1.00",
4363 "DEM1.00",
4364 "DEM1.00",
4365 "DJF1.00",
4366 "DKK1.00",
4367 "DOP1.00",
4368 "DZD1.00",
4369 "Danish Krone1.00",
4370 "Danish krone1.00",
4371 "Danish kroner1.00",
4372 "German Mark1.00",
4373 "German mark1.00",
4374 "German marks1.00",
4375 "Djiboutian Franc1.00",
4376 "Djiboutian franc1.00",
4377 "Djiboutian francs1.00",
4378 "Dominican Peso1.00",
4379 "Dominican peso1.00",
4380 "Dominican pesos1.00",
4381 "EC$1.00",
4382 "ECS1.00",
4383 "ECS1.00",
4384 "ECV1.00",
4385 "ECV1.00",
4386 "EEK1.00",
4387 "EEK1.00",
4388 "EGP1.00",
4389 "EGP1.00",
4390 "ERN1.00",
4391 "ERN1.00",
4392 "ESA1.00",
4393 "ESA1.00",
4394 "ESB1.00",
4395 "ESB1.00",
4396 "ESP1.00",
4397 "ETB1.00",
4398 "EUR1.00",
4399 "East Caribbean Dollar1.00",
4400 "East Caribbean dollar1.00",
4401 "East Caribbean dollars1.00",
4402 "East German Mark1.00",
4403 "East German mark1.00",
4404 "East German marks1.00",
4405 "Ecuadorian Sucre1.00",
4406 "Ecuadorian Unit of Constant Value1.00",
4407 "Ecuadorian sucre1.00",
4408 "Ecuadorian sucres1.00",
4409 "Ecuadorian unit of constant value1.00",
4410 "Ecuadorian units of constant value1.00",
4411 "Egyptian Pound1.00",
4412 "Egyptian pound1.00",
4413 "Egyptian pounds1.00",
4414 "Salvadoran Col\\u00f3n1.00",
4415 "Salvadoran col\\u00f3n1.00",
4416 "Salvadoran colones1.00",
4417 "Equatorial Guinean Ekwele1.00",
4418 "Equatorial Guinean ekwele1.00",
4419 "Eritrean Nakfa1.00",
4420 "Eritrean nakfa1.00",
4421 "Eritrean nakfas1.00",
4422 "Estonian Kroon1.00",
4423 "Estonian kroon1.00",
4424 "Estonian kroons1.00",
4425 "Ethiopian Birr1.00",
4426 "Ethiopian birr1.00",
4427 "Ethiopian birrs1.00",
4428 "Euro1.00",
4429 "European Composite Unit1.00",
4430 "European Currency Unit1.00",
4431 "European Monetary Unit1.00",
4432 "European Unit of Account (XBC)1.00",
4433 "European Unit of Account (XBD)1.00",
4434 "European composite unit1.00",
4435 "European composite units1.00",
4436 "European currency unit1.00",
4437 "European currency units1.00",
4438 "European monetary unit1.00",
4439 "European monetary units1.00",
4440 "European unit of account (XBC)1.00",
4441 "European unit of account (XBD)1.00",
4442 "European units of account (XBC)1.00",
4443 "European units of account (XBD)1.00",
4444 "FIM1.00",
4445 "FIM1.00",
4446 "FJD1.00",
4447 "FKP1.00",
4448 "FKP1.00",
4449 "FRF1.00",
4450 "FRF1.00",
4451 "Falkland Islands Pound1.00",
4452 "Falkland Islands pound1.00",
4453 "Falkland Islands pounds1.00",
4454 "Fijian Dollar1.00",
4455 "Fijian dollar1.00",
4456 "Fijian dollars1.00",
4457 "Finnish Markka1.00",
4458 "Finnish markka1.00",
4459 "Finnish markkas1.00",
4460 "CHF1.00",
4461 "French Franc1.00",
4462 "French Gold Franc1.00",
4463 "French UIC-Franc1.00",
4464 "French UIC-franc1.00",
4465 "French UIC-francs1.00",
4466 "French franc1.00",
4467 "French francs1.00",
4468 "French gold franc1.00",
4469 "French gold francs1.00",
4470 "GBP1.00",
4471 "GEK1.00",
4472 "GEK1.00",
4473 "GEL1.00",
4474 "GHC1.00",
4475 "GHC1.00",
4476 "GHS1.00",
4477 "GIP1.00",
4478 "GIP1.00",
4479 "GMD1.00",
4480 "GMD1.00",
4481 "GNF1.00",
4482 "GNS1.00",
4483 "GNS1.00",
4484 "GQE1.00",
4485 "GQE1.00",
4486 "GRD1.00",
4487 "GRD1.00",
4488 "GTQ1.00",
4489 "GWE1.00",
4490 "GWE1.00",
4491 "GWP1.00",
4492 "GWP1.00",
4493 "GYD1.00",
4494 "Gambian Dalasi1.00",
4495 "Gambian dalasi1.00",
4496 "Gambian dalasis1.00",
4497 "Georgian Kupon Larit1.00",
4498 "Georgian Lari1.00",
4499 "Georgian kupon larit1.00",
4500 "Georgian kupon larits1.00",
4501 "Georgian lari1.00",
4502 "Georgian laris1.00",
4503 "Ghanaian Cedi (1979\\u20132007)1.00",
4504 "Ghanaian Cedi1.00",
4505 "Ghanaian cedi (1979\\u20132007)1.00",
4506 "Ghanaian cedi1.00",
4507 "Ghanaian cedis (1979\\u20132007)1.00",
4508 "Ghanaian cedis1.00",
4509 "Gibraltar Pound1.00",
4510 "Gibraltar pound1.00",
4511 "Gibraltar pounds1.00",
4512 "Gold1.00",
4513 "Gold1.00",
4514 "Greek Drachma1.00",
4515 "Greek drachma1.00",
4516 "Greek drachmas1.00",
4517 "Guatemalan Quetzal1.00",
4518 "Guatemalan quetzal1.00",
4519 "Guatemalan quetzals1.00",
4520 "Guinean Franc1.00",
4521 "Guinean Syli1.00",
4522 "Guinean franc1.00",
4523 "Guinean francs1.00",
4524 "Guinean syli1.00",
4525 "Guinean sylis1.00",
4526 "Guinea-Bissau Peso1.00",
4527 "Guinea-Bissau peso1.00",
4528 "Guinea-Bissau pesos1.00",
4529 "Guyanaese Dollar1.00",
4530 "Guyanaese dollar1.00",
4531 "Guyanaese dollars1.00",
4532 "HK$1.00",
4533 "HKD1.00",
4534 "HNL1.00",
4535 "HRD1.00",
4536 "HRD1.00",
4537 "HRK1.00",
4538 "HRK1.00",
4539 "HTG1.00",
4540 "HTG1.00",
4541 "HUF1.00",
4542 "Haitian Gourde1.00",
4543 "Haitian gourde1.00",
4544 "Haitian gourdes1.00",
4545 "Honduran Lempira1.00",
4546 "Honduran lempira1.00",
4547 "Honduran lempiras1.00",
4548 "Hong Kong Dollar1.00",
4549 "Hong Kong dollar1.00",
4550 "Hong Kong dollars1.00",
4551 "Hungarian Forint1.00",
4552 "Hungarian forint1.00",
4553 "Hungarian forints1.00",
4554 "IDR1.00",
4555 "IEP1.00",
4556 "ILP1.00",
4557 "ILP1.00",
4558 "ILS1.00",
4559 "INR1.00",
4560 "IQD1.00",
4561 "IRR1.00",
4562 "ISK1.00",
4563 "ISK1.00",
4564 "ITL1.00",
4565 "Icelandic Kr\\u00f3na1.00",
4566 "Icelandic kr\\u00f3na1.00",
4567 "Icelandic kr\\u00f3nur1.00",
4568 "Indian Rupee1.00",
4569 "Indian rupee1.00",
4570 "Indian rupees1.00",
4571 "Indonesian Rupiah1.00",
4572 "Indonesian rupiah1.00",
4573 "Indonesian rupiahs1.00",
4574 "Iranian Rial1.00",
4575 "Iranian rial1.00",
4576 "Iranian rials1.00",
4577 "Iraqi Dinar1.00",
4578 "Iraqi dinar1.00",
4579 "Iraqi dinars1.00",
4580 "Irish Pound1.00",
4581 "Irish pound1.00",
4582 "Irish pounds1.00",
4583 "Israeli Pound1.00",
4584 "Israeli new shekel1.00",
4585 "Israeli pound1.00",
4586 "Israeli pounds1.00",
4587 "Italian Lira1.00",
4588 "Italian lira1.00",
4589 "Italian liras1.00",
4590 "JMD1.00",
4591 "JOD1.00",
4592 "JPY1.00",
4593 "Jamaican Dollar1.00",
4594 "Jamaican dollar1.00",
4595 "Jamaican dollars1.00",
4596 "Japanese Yen1.00",
4597 "Japanese yen1.00",
4598 "Jordanian Dinar1.00",
4599 "Jordanian dinar1.00",
4600 "Jordanian dinars1.00",
4601 "KES1.00",
4602 "KGS1.00",
4603 "KHR1.00",
4604 "KMF1.00",
4605 "KPW1.00",
4606 "KPW1.00",
4607 "KRW1.00",
4608 "KWD1.00",
4609 "KYD1.00",
4610 "KYD1.00",
4611 "KZT1.00",
4612 "Kazakhstani Tenge1.00",
4613 "Kazakhstani tenge1.00",
4614 "Kazakhstani tenges1.00",
4615 "Kenyan Shilling1.00",
4616 "Kenyan shilling1.00",
4617 "Kenyan shillings1.00",
4618 "Kuwaiti Dinar1.00",
4619 "Kuwaiti dinar1.00",
4620 "Kuwaiti dinars1.00",
4621 "Kyrgystani Som1.00",
4622 "Kyrgystani som1.00",
4623 "Kyrgystani soms1.00",
4624 "HNL1.00",
4625 "LAK1.00",
4626 "LAK1.00",
4627 "LBP1.00",
4628 "LKR1.00",
4629 "LRD1.00",
4630 "LRD1.00",
4631 "LSL1.00",
4632 "LTL1.00",
4633 "LTL1.00",
4634 "LTT1.00",
4635 "LTT1.00",
4636 "LUC1.00",
4637 "LUC1.00",
4638 "LUF1.00",
4639 "LUF1.00",
4640 "LUL1.00",
4641 "LUL1.00",
4642 "LVL1.00",
4643 "LVL1.00",
4644 "LVR1.00",
4645 "LVR1.00",
4646 "LYD1.00",
4647 "Laotian Kip1.00",
4648 "Laotian kip1.00",
4649 "Laotian kips1.00",
4650 "Latvian Lats1.00",
4651 "Latvian Ruble1.00",
4652 "Latvian lats1.00",
4653 "Latvian lati1.00",
4654 "Latvian ruble1.00",
4655 "Latvian rubles1.00",
4656 "Lebanese Pound1.00",
4657 "Lebanese pound1.00",
4658 "Lebanese pounds1.00",
4659 "Lesotho Loti1.00",
4660 "Lesotho loti1.00",
4661 "Lesotho lotis1.00",
4662 "Liberian Dollar1.00",
4663 "Liberian dollar1.00",
4664 "Liberian dollars1.00",
4665 "Libyan Dinar1.00",
4666 "Libyan dinar1.00",
4667 "Libyan dinars1.00",
4668 "Lithuanian Litas1.00",
4669 "Lithuanian Talonas1.00",
4670 "Lithuanian litas1.00",
4671 "Lithuanian litai1.00",
4672 "Lithuanian talonas1.00",
4673 "Lithuanian talonases1.00",
4674 "Luxembourgian Convertible Franc1.00",
4675 "Luxembourg Financial Franc1.00",
4676 "Luxembourgian Franc1.00",
4677 "Luxembourgian convertible franc1.00",
4678 "Luxembourgian convertible francs1.00",
4679 "Luxembourg financial franc1.00",
4680 "Luxembourg financial francs1.00",
4681 "Luxembourgian franc1.00",
4682 "Luxembourgian francs1.00",
4683 "MAD1.00",
4684 "MAD1.00",
4685 "MAF1.00",
4686 "MAF1.00",
4687 "MDL1.00",
4688 "MDL1.00",
4689 "MX$1.00",
4690 "MGA1.00",
4691 "MGA1.00",
4692 "MGF1.00",
4693 "MGF1.00",
4694 "MKD1.00",
4695 "MLF1.00",
4696 "MLF1.00",
4697 "MMK1.00",
4698 "MMK1.00",
4699 "MNT1.00",
4700 "MOP1.00",
4701 "MOP1.00",
4702 "MRO1.00",
4703 "MTL1.00",
4704 "MTP1.00",
4705 "MTP1.00",
4706 "MUR1.00",
4707 "MUR1.00",
4708 "MVR1.00",
4709 "MVR1.00",
4710 "MWK1.00",
4711 "MXN1.00",
4712 "MXP1.00",
4713 "MXP1.00",
4714 "MXV1.00",
4715 "MXV1.00",
4716 "MYR1.00",
4717 "MZE1.00",
4718 "MZE1.00",
4719 "MZM1.00",
4720 "MZN1.00",
4721 "Macanese Pataca1.00",
4722 "Macanese pataca1.00",
4723 "Macanese patacas1.00",
4724 "Macedonian Denar1.00",
4725 "Macedonian denar1.00",
4726 "Macedonian denari1.00",
4727 "Malagasy Ariaries1.00",
4728 "Malagasy Ariary1.00",
4729 "Malagasy Ariary1.00",
4730 "Malagasy Franc1.00",
4731 "Malagasy franc1.00",
4732 "Malagasy francs1.00",
4733 "Malawian Kwacha1.00",
4734 "Malawian Kwacha1.00",
4735 "Malawian Kwachas1.00",
4736 "Malaysian Ringgit1.00",
4737 "Malaysian ringgit1.00",
4738 "Malaysian ringgits1.00",
4739 "Maldivian Rufiyaa1.00",
4740 "Maldivian rufiyaa1.00",
4741 "Maldivian rufiyaas1.00",
4742 "Malian Franc1.00",
4743 "Malian franc1.00",
4744 "Malian francs1.00",
4745 "Maltese Lira1.00",
4746 "Maltese Pound1.00",
4747 "Maltese lira1.00",
4748 "Maltese lira1.00",
4749 "Maltese pound1.00",
4750 "Maltese pounds1.00",
4751 "Mauritanian Ouguiya1.00",
4752 "Mauritanian ouguiya1.00",
4753 "Mauritanian ouguiyas1.00",
4754 "Mauritian Rupee1.00",
4755 "Mauritian rupee1.00",
4756 "Mauritian rupees1.00",
4757 "Mexican Peso1.00",
4758 "Mexican Silver Peso (1861\\u20131992)1.00",
4759 "Mexican Investment Unit1.00",
4760 "Mexican peso1.00",
4761 "Mexican pesos1.00",
4762 "Mexican silver peso (1861\\u20131992)1.00",
4763 "Mexican silver pesos (1861\\u20131992)1.00",
4764 "Mexican investment unit1.00",
4765 "Mexican investment units1.00",
4766 "Moldovan Leu1.00",
4767 "Moldovan leu1.00",
4768 "Moldovan lei1.00",
4769 "Mongolian Tugrik1.00",
4770 "Mongolian tugrik1.00",
4771 "Mongolian tugriks1.00",
4772 "Moroccan Dirham1.00",
4773 "Moroccan Franc1.00",
4774 "Moroccan dirham1.00",
4775 "Moroccan dirhams1.00",
4776 "Moroccan franc1.00",
4777 "Moroccan francs1.00",
4778 "Mozambican Escudo1.00",
4779 "Mozambican Metical1.00",
4780 "Mozambican escudo1.00",
4781 "Mozambican escudos1.00",
4782 "Mozambican metical1.00",
4783 "Mozambican meticals1.00",
4784 "Myanmar Kyat1.00",
4785 "Myanmar kyat1.00",
4786 "Myanmar kyats1.00",
4787 "NAD1.00",
4788 "NGN1.00",
4789 "NIC1.00",
4790 "NIO1.00",
4791 "NIO1.00",
4792 "NLG1.00",
4793 "NLG1.00",
4794 "NOK1.00",
4795 "NPR1.00",
4796 "NT$1.00",
4797 "NZ$1.00",
4798 "NZD1.00",
4799 "Namibian Dollar1.00",
4800 "Namibian dollar1.00",
4801 "Namibian dollars1.00",
4802 "Nepalese Rupee1.00",
4803 "Nepalese rupee1.00",
4804 "Nepalese rupees1.00",
4805 "Netherlands Antillean Guilder1.00",
4806 "Netherlands Antillean guilder1.00",
4807 "Netherlands Antillean guilders1.00",
4808 "Dutch Guilder1.00",
4809 "Dutch guilder1.00",
4810 "Dutch guilders1.00",
4811 "Israeli New Shekel1.00",
4812 "Israeli New Shekels1.00",
4813 "New Zealand Dollar1.00",
4814 "New Zealand dollar1.00",
4815 "New Zealand dollars1.00",
4816 "Nicaraguan C\\u00f3rdoba1.00",
4817 "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
4818 "Nicaraguan c\\u00f3rdoba1.00",
4819 "Nicaraguan c\\u00f3rdobas1.00",
4820 "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
4821 "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
4822 "Nigerian Naira1.00",
4823 "Nigerian naira1.00",
4824 "Nigerian nairas1.00",
4825 "North Korean Won1.00",
4826 "North Korean won1.00",
4827 "North Korean won1.00",
4828 "Norwegian Krone1.00",
4829 "Norwegian krone1.00",
4830 "Norwegian kroner1.00",
4831 "OMR1.00",
4832 "Mozambican Metical (1980\\u20132006)1.00",
4833 "Mozambican metical (1980\\u20132006)1.00",
4834 "Mozambican meticals (1980\\u20132006)1.00",
4835 "Romanian Lei (1952\\u20132006)1.00",
4836 "Romanian Leu (1952\\u20132006)1.00",
4837 "Romanian leu (1952\\u20132006)1.00",
4838 "Serbian Dinar (2002\\u20132006)1.00",
4839 "Serbian dinar (2002\\u20132006)1.00",
4840 "Serbian dinars (2002\\u20132006)1.00",
4841 "Sudanese Dinar (1992\\u20132007)1.00",
4842 "Sudanese Pound (1957\\u20131998)1.00",
4843 "Sudanese dinar (1992\\u20132007)1.00",
4844 "Sudanese dinars (1992\\u20132007)1.00",
4845 "Sudanese pound (1957\\u20131998)1.00",
4846 "Sudanese pounds (1957\\u20131998)1.00",
4847 "Turkish Lira (1922\\u20132005)1.00",
4848 "Turkish Lira (1922\\u20132005)1.00",
4849 "Omani Rial1.00",
4850 "Omani rial1.00",
4851 "Omani rials1.00",
4852 "PAB1.00",
4853 "PAB1.00",
4854 "PEI1.00",
4855 "PEI1.00",
4856 "PEN1.00",
4857 "PEN1.00",
4858 "PES1.00",
4859 "PES1.00",
4860 "PGK1.00",
4861 "PGK1.00",
4862 "PHP1.00",
4863 "PKR1.00",
4864 "PLN1.00",
4865 "PLZ1.00",
4866 "PLZ1.00",
4867 "PTE1.00",
4868 "PTE1.00",
4869 "PYG1.00",
4870 "Pakistani Rupee1.00",
4871 "Pakistani rupee1.00",
4872 "Pakistani rupees1.00",
4873 "Palladium1.00",
4874 "Palladium1.00",
4875 "Panamanian Balboa1.00",
4876 "Panamanian balboa1.00",
4877 "Panamanian balboas1.00",
4878 "Papua New Guinean Kina1.00",
4879 "Papua New Guinean kina1.00",
4880 "Papua New Guinean kina1.00",
4881 "Paraguayan Guarani1.00",
4882 "Paraguayan guarani1.00",
4883 "Paraguayan guaranis1.00",
4884 "Peruvian Inti1.00",
4885 "Peruvian Sol1.00",
4886 "Peruvian Sol (1863\\u20131965)1.00",
4887 "Peruvian inti1.00",
4888 "Peruvian intis1.00",
4889 "Peruvian sol1.00",
4890 "Peruvian soles1.00",
4891 "Peruvian sol (1863\\u20131965)1.00",
4892 "Peruvian soles (1863\\u20131965)1.00",
Frank Tangd2858cb2022-04-08 20:34:12 -07004893 "Philippine Peso1.00",
4894 "Philippine peso1.00",
4895 "Philippine pesos1.00",
Frank Tang3e05d9d2021-11-08 14:04:04 -08004896 "Platinum1.00",
4897 "Platinum1.00",
4898 "Polish Zloty (1950\\u20131995)1.00",
4899 "Polish Zloty1.00",
4900 "Polish zlotys1.00",
4901 "Polish zloty (PLZ)1.00",
4902 "Polish zloty1.00",
4903 "Polish zlotys (PLZ)1.00",
4904 "Portuguese Escudo1.00",
4905 "Portuguese Guinea Escudo1.00",
4906 "Portuguese Guinea escudo1.00",
4907 "Portuguese Guinea escudos1.00",
4908 "Portuguese escudo1.00",
4909 "Portuguese escudos1.00",
4910 "GTQ1.00",
4911 "QAR1.00",
4912 "Qatari Rial1.00",
4913 "Qatari rial1.00",
4914 "Qatari rials1.00",
4915 "RHD1.00",
4916 "RHD1.00",
4917 "RINET Funds1.00",
4918 "RINET Funds1.00",
4919 "CN\\u00a51.00",
4920 "ROL1.00",
4921 "ROL1.00",
4922 "RON1.00",
4923 "RON1.00",
4924 "RSD1.00",
4925 "RSD1.00",
4926 "RUB1.00",
4927 "RUR1.00",
4928 "RUR1.00",
4929 "RWF1.00",
4930 "RWF1.00",
4931 "Rhodesian Dollar1.00",
4932 "Rhodesian dollar1.00",
4933 "Rhodesian dollars1.00",
4934 "Romanian Leu1.00",
4935 "Romanian lei1.00",
4936 "Romanian leu1.00",
4937 "Russian Ruble (1991\\u20131998)1.00",
4938 "Russian Ruble1.00",
4939 "Russian ruble (1991\\u20131998)1.00",
4940 "Russian ruble1.00",
4941 "Russian rubles (1991\\u20131998)1.00",
4942 "Russian rubles1.00",
4943 "Rwandan Franc1.00",
4944 "Rwandan franc1.00",
4945 "Rwandan francs1.00",
4946 "SAR1.00",
4947 "SBD1.00",
4948 "SCR1.00",
4949 "SDD1.00",
4950 "SDD1.00",
4951 "SDG1.00",
4952 "SDG1.00",
4953 "SDP1.00",
4954 "SDP1.00",
4955 "SEK1.00",
4956 "SGD1.00",
4957 "SHP1.00",
4958 "SHP1.00",
4959 "SIT1.00",
4960 "SIT1.00",
4961 "SKK1.00",
4962 "SLL1.00",
4963 "SLL1.00",
4964 "SOS1.00",
4965 "SRD1.00",
4966 "SRD1.00",
4967 "SRG1.00",
4968 "STD1.00",
4969 "SUR1.00",
4970 "SUR1.00",
4971 "SVC1.00",
4972 "SVC1.00",
4973 "SYP1.00",
4974 "SZL1.00",
4975 "St. Helena Pound1.00",
4976 "St. Helena pound1.00",
4977 "St. Helena pounds1.00",
4978 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
4979 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
4980 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
4981 "Saudi Riyal1.00",
4982 "Saudi riyal1.00",
4983 "Saudi riyals1.00",
4984 "Serbian Dinar1.00",
4985 "Serbian dinar1.00",
4986 "Serbian dinars1.00",
4987 "Seychellois Rupee1.00",
4988 "Seychellois rupee1.00",
4989 "Seychellois rupees1.00",
4990 "Sierra Leonean Leone1.00",
4991 "Sierra Leonean leone1.00",
4992 "Sierra Leonean leones1.00",
4993 "Silver1.00",
4994 "Silver1.00",
4995 "Singapore Dollar1.00",
4996 "Singapore dollar1.00",
4997 "Singapore dollars1.00",
4998 "Slovak Koruna1.00",
4999 "Slovak koruna1.00",
5000 "Slovak korunas1.00",
5001 "Slovenian Tolar1.00",
5002 "Slovenian tolar1.00",
5003 "Slovenian tolars1.00",
5004 "Solomon Islands Dollar1.00",
5005 "Solomon Islands dollar1.00",
5006 "Solomon Islands dollars1.00",
5007 "Somali Shilling1.00",
5008 "Somali shilling1.00",
5009 "Somali shillings1.00",
5010 "South African Rand (financial)1.00",
5011 "South African Rand1.00",
5012 "South African rand (financial)1.00",
5013 "South African rand1.00",
5014 "South African rands (financial)1.00",
5015 "South African rand1.00",
5016 "South Korean Won1.00",
5017 "South Korean won1.00",
5018 "South Korean won1.00",
5019 "Soviet Rouble1.00",
5020 "Soviet rouble1.00",
5021 "Soviet roubles1.00",
5022 "Spanish Peseta (A account)1.00",
5023 "Spanish Peseta (convertible account)1.00",
5024 "Spanish Peseta1.00",
5025 "Spanish peseta (A account)1.00",
5026 "Spanish peseta (convertible account)1.00",
5027 "Spanish peseta1.00",
5028 "Spanish pesetas (A account)1.00",
5029 "Spanish pesetas (convertible account)1.00",
5030 "Spanish pesetas1.00",
5031 "Special Drawing Rights1.00",
5032 "Sri Lankan Rupee1.00",
5033 "Sri Lankan rupee1.00",
5034 "Sri Lankan rupees1.00",
5035 "Sudanese Pound1.00",
5036 "Sudanese pound1.00",
5037 "Sudanese pounds1.00",
5038 "Surinamese Dollar1.00",
5039 "Surinamese dollar1.00",
5040 "Surinamese dollars1.00",
5041 "Surinamese Guilder1.00",
5042 "Surinamese guilder1.00",
5043 "Surinamese guilders1.00",
5044 "Swazi Lilangeni1.00",
5045 "Swazi lilangeni1.00",
5046 "Swazi emalangeni1.00",
5047 "Swedish Krona1.00",
5048 "Swedish krona1.00",
5049 "Swedish kronor1.00",
5050 "Swiss Franc1.00",
5051 "Swiss franc1.00",
5052 "Swiss francs1.00",
5053 "Syrian Pound1.00",
5054 "Syrian pound1.00",
5055 "Syrian pounds1.00",
5056 "THB1.00",
5057 "TJR1.00",
5058 "TJR1.00",
5059 "TJS1.00",
5060 "TJS1.00",
5061 "TMM1.00",
5062 "TMM1.00",
5063 "TND1.00",
5064 "TND1.00",
5065 "TOP1.00",
5066 "TPE1.00",
5067 "TPE1.00",
5068 "TRL1.00",
5069 "TRY1.00",
5070 "TRY1.00",
5071 "TTD1.00",
5072 "TWD1.00",
5073 "TZS1.00",
5074 "New Taiwan Dollar1.00",
5075 "New Taiwan dollar1.00",
5076 "New Taiwan dollars1.00",
5077 "Tajikistani Ruble1.00",
5078 "Tajikistani Somoni1.00",
5079 "Tajikistani ruble1.00",
5080 "Tajikistani rubles1.00",
5081 "Tajikistani somoni1.00",
5082 "Tajikistani somonis1.00",
5083 "Tanzanian Shilling1.00",
5084 "Tanzanian shilling1.00",
5085 "Tanzanian shillings1.00",
5086 "Testing Currency Code1.00",
5087 "Testing Currency Code1.00",
5088 "Thai Baht1.00",
5089 "Thai baht1.00",
5090 "Thai baht1.00",
5091 "Timorese Escudo1.00",
5092 "Timorese escudo1.00",
5093 "Timorese escudos1.00",
5094 "Tongan Pa\\u02bbanga1.00",
5095 "Tongan pa\\u02bbanga1.00",
5096 "Tongan pa\\u02bbanga1.00",
5097 "Trinidad & Tobago Dollar1.00",
5098 "Trinidad & Tobago dollar1.00",
5099 "Trinidad & Tobago dollars1.00",
5100 "Tunisian Dinar1.00",
5101 "Tunisian dinar1.00",
5102 "Tunisian dinars1.00",
5103 "Turkish Lira1.00",
5104 "Turkish Lira1.00",
5105 "Turkish lira1.00",
5106 "Turkmenistani Manat1.00",
5107 "Turkmenistani manat1.00",
5108 "Turkmenistani manat1.00",
5109 "UAE dirham1.00",
5110 "UAE dirhams1.00",
5111 "UAH1.00",
5112 "UAK1.00",
5113 "UAK1.00",
5114 "UGS1.00",
5115 "UGS1.00",
5116 "UGX1.00",
5117 "US Dollar (Next day)1.00",
5118 "US Dollar (Same day)1.00",
5119 "US Dollar1.00",
5120 "US dollar (next day)1.00",
5121 "US dollar (same day)1.00",
5122 "US dollar1.00",
5123 "US dollars (next day)1.00",
5124 "US dollars (same day)1.00",
5125 "US dollars1.00",
5126 "USD1.00",
5127 "USN1.00",
5128 "USN1.00",
5129 "USS1.00",
5130 "USS1.00",
5131 "UYI1.00",
5132 "UYI1.00",
5133 "UYP1.00",
5134 "UYP1.00",
5135 "UYU1.00",
5136 "UZS1.00",
5137 "UZS1.00",
5138 "Ugandan Shilling (1966\\u20131987)1.00",
5139 "Ugandan Shilling1.00",
5140 "Ugandan shilling (1966\\u20131987)1.00",
5141 "Ugandan shilling1.00",
5142 "Ugandan shillings (1966\\u20131987)1.00",
5143 "Ugandan shillings1.00",
5144 "Ukrainian Hryvnia1.00",
5145 "Ukrainian Karbovanets1.00",
5146 "Ukrainian hryvnia1.00",
5147 "Ukrainian hryvnias1.00",
5148 "Ukrainian karbovanets1.00",
5149 "Ukrainian karbovantsiv1.00",
5150 "Colombian Real Value Unit1.00",
5151 "United Arab Emirates Dirham1.00",
5152 "Unknown Currency1.00",
5153 "Uruguayan Peso (1975\\u20131993)1.00",
5154 "Uruguayan Peso1.00",
5155 "Uruguayan Peso (Indexed Units)1.00",
5156 "Uruguayan peso (1975\\u20131993)1.00",
5157 "Uruguayan peso (indexed units)1.00",
5158 "Uruguayan peso1.00",
5159 "Uruguayan pesos (1975\\u20131993)1.00",
5160 "Uruguayan pesos (indexed units)1.00",
5161 "Uruguayan pesos1.00",
5162 "Uzbekistani Som1.00",
5163 "Uzbekistani som1.00",
5164 "Uzbekistani som1.00",
5165 "VEB1.00",
5166 "VEF1.00",
5167 "VND1.00",
5168 "VUV1.00",
5169 "Vanuatu Vatu1.00",
5170 "Vanuatu vatu1.00",
5171 "Vanuatu vatus1.00",
5172 "Venezuelan Bol\\u00edvar1.00",
5173 "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
5174 "Venezuelan bol\\u00edvar1.00",
5175 "Venezuelan bol\\u00edvars1.00",
5176 "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
5177 "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
5178 "Vietnamese Dong1.00",
5179 "Vietnamese dong1.00",
5180 "Vietnamese dong1.00",
5181 "WIR Euro1.00",
5182 "WIR Franc1.00",
5183 "WIR euro1.00",
5184 "WIR euros1.00",
5185 "WIR franc1.00",
5186 "WIR francs1.00",
5187 "WST1.00",
5188 "WST1.00",
5189 "Samoan Tala1.00",
5190 "Samoan tala1.00",
5191 "Samoan tala1.00",
5192 "XAF1.00",
5193 "XAF1.00",
5194 "XAG1.00",
5195 "XAG1.00",
5196 "XAU1.00",
5197 "XAU1.00",
5198 "XBA1.00",
5199 "XBA1.00",
5200 "XBB1.00",
5201 "XBB1.00",
5202 "XBC1.00",
5203 "XBC1.00",
5204 "XBD1.00",
5205 "XBD1.00",
5206 "XCD1.00",
5207 "XDR1.00",
5208 "XDR1.00",
5209 "XEU1.00",
5210 "XEU1.00",
5211 "XFO1.00",
5212 "XFO1.00",
5213 "XFU1.00",
5214 "XFU1.00",
5215 "XOF1.00",
5216 "XOF1.00",
5217 "XPD1.00",
5218 "XPD1.00",
5219 "XPF1.00",
5220 "XPT1.00",
5221 "XPT1.00",
5222 "XRE1.00",
5223 "XRE1.00",
5224 "XTS1.00",
5225 "XTS1.00",
5226 "XXX1.00",
5227 "XXX1.00",
5228 "YDD1.00",
5229 "YDD1.00",
5230 "YER1.00",
5231 "YUD1.00",
5232 "YUD1.00",
5233 "YUM1.00",
5234 "YUM1.00",
5235 "YUN1.00",
5236 "YUN1.00",
5237 "Yemeni Dinar1.00",
5238 "Yemeni Rial1.00",
5239 "Yemeni dinar1.00",
5240 "Yemeni dinars1.00",
5241 "Yemeni rial1.00",
5242 "Yemeni rials1.00",
5243 "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
5244 "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
5245 "Yugoslavian New Dinar (1994\\u20132002)1.00",
5246 "Yugoslavian convertible dinar (1990\\u20131992)1.00",
5247 "Yugoslavian convertible dinars (1990\\u20131992)1.00",
5248 "Yugoslavian hard dinar (1966\\u20131990)1.00",
5249 "Yugoslavian hard dinars (1966\\u20131990)1.00",
5250 "Yugoslavian new dinar (1994\\u20132002)1.00",
5251 "Yugoslavian new dinars (1994\\u20132002)1.00",
5252 "ZAL1.00",
5253 "ZAL1.00",
5254 "ZAR1.00",
5255 "ZMK1.00",
5256 "ZMK1.00",
5257 "ZRN1.00",
5258 "ZRN1.00",
5259 "ZRZ1.00",
5260 "ZRZ1.00",
5261 "ZWD1.00",
5262 "Zairean New Zaire (1993\\u20131998)1.00",
5263 "Zairean Zaire (1971\\u20131993)1.00",
5264 "Zairean new zaire (1993\\u20131998)1.00",
5265 "Zairean new zaires (1993\\u20131998)1.00",
5266 "Zairean zaire (1971\\u20131993)1.00",
5267 "Zairean zaires (1971\\u20131993)1.00",
5268 "Zambian Kwacha1.00",
5269 "Zambian kwacha1.00",
5270 "Zambian kwachas1.00",
5271 "Zimbabwean Dollar (1980\\u20132008)1.00",
5272 "Zimbabwean dollar (1980\\u20132008)1.00",
5273 "Zimbabwean dollars (1980\\u20132008)1.00",
5274 "euro1.00",
5275 "euros1.00",
5276 "Turkish lira (1922\\u20132005)1.00",
5277 "special drawing rights1.00",
5278 "Colombian real value unit1.00",
5279 "Colombian real value units1.00",
5280 "unknown currency1.00",
5281 "\\u00a31.00",
5282 "\\u00a51.00",
5283 "\\u20ab1.00",
5284 "\\u20aa1.00",
5285 "\\u20ac1.00",
5286 "\\u20b91.00",
5287 //
5288 // Following has extra text, should be parsed correctly too
5289 "$1.00 random",
5290 "USD1.00 random",
5291 "1.00 US dollar random",
5292 "1.00 US dollars random",
5293 "1.00 Afghan Afghani random",
5294 "1.00 Afghan Afghani random",
5295 "1.00 Afghan Afghanis (1927\\u20131992) random",
5296 "1.00 Afghan Afghanis random",
5297 "1.00 Albanian Lek random",
5298 "1.00 Albanian lek random",
5299 "1.00 Albanian lek\\u00eb random",
5300 "1.00 Algerian Dinar random",
5301 "1.00 Algerian dinar random",
5302 "1.00 Algerian dinars random",
5303 "1.00 Andorran Peseta random",
5304 "1.00 Andorran peseta random",
5305 "1.00 Andorran pesetas random",
5306 "1.00 Angolan Kwanza (1977\\u20131990) random",
5307 "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
5308 "1.00 Angolan Kwanza random",
5309 "1.00 Angolan New Kwanza (1990\\u20132000) random",
5310 "1.00 Angolan kwanza (1977\\u20131991) random",
5311 "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
5312 "1.00 Angolan kwanza random",
5313 "1.00 Angolan kwanzas (1977\\u20131991) random",
5314 "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
5315 "1.00 Angolan kwanzas random",
5316 "1.00 Angolan new kwanza (1990\\u20132000) random",
5317 "1.00 Angolan new kwanzas (1990\\u20132000) random",
5318 "1.00 Argentine Austral random",
5319 "1.00 Argentine Peso (1983\\u20131985) random",
5320 "1.00 Argentine Peso random",
5321 "1.00 Argentine austral random",
5322 "1.00 Argentine australs random",
5323 "1.00 Argentine peso (1983\\u20131985) random",
5324 "1.00 Argentine peso random",
5325 "1.00 Argentine pesos (1983\\u20131985) random",
5326 "1.00 Argentine pesos random",
5327 "1.00 Armenian Dram random",
5328 "1.00 Armenian dram random",
5329 "1.00 Armenian drams random",
5330 "1.00 Aruban Florin random",
5331 "1.00 Aruban florin random",
5332 "1.00 Australian Dollar random",
5333 "1.00 Australian dollar random",
5334 "1.00 Australian dollars random",
5335 "1.00 Austrian Schilling random",
5336 "1.00 Austrian schilling random",
5337 "1.00 Austrian schillings random",
5338 "1.00 Azerbaijani Manat (1993\\u20132006) random",
5339 "1.00 Azerbaijani Manat random",
5340 "1.00 Azerbaijani manat (1993\\u20132006) random",
5341 "1.00 Azerbaijani manat random",
5342 "1.00 Azerbaijani manats (1993\\u20132006) random",
5343 "1.00 Azerbaijani manats random",
5344 "1.00 Bahamian Dollar random",
5345 "1.00 Bahamian dollar random",
5346 "1.00 Bahamian dollars random",
5347 "1.00 Bahraini Dinar random",
5348 "1.00 Bahraini dinar random",
5349 "1.00 Bahraini dinars random",
5350 "1.00 Bangladeshi Taka random",
5351 "1.00 Bangladeshi taka random",
5352 "1.00 Bangladeshi takas random",
5353 "1.00 Barbadian Dollar random",
5354 "1.00 Barbadian dollar random",
5355 "1.00 Barbadian dollars random",
5356 "1.00 Belarusian Ruble (1994\\u20131999) random",
5357 "1.00 Belarusian Ruble random",
5358 "1.00 Belarusian ruble (1994\\u20131999) random",
5359 "1.00 Belarusian rubles (1994\\u20131999) random",
5360 "1.00 Belarusian ruble random",
5361 "1.00 Belarusian rubles random",
5362 "1.00 Belgian Franc (convertible) random",
5363 "1.00 Belgian Franc (financial) random",
5364 "1.00 Belgian Franc random",
5365 "1.00 Belgian franc (convertible) random",
5366 "1.00 Belgian franc (financial) random",
5367 "1.00 Belgian franc random",
5368 "1.00 Belgian francs (convertible) random",
5369 "1.00 Belgian francs (financial) random",
5370 "1.00 Belgian francs random",
5371 "1.00 Belize Dollar random",
5372 "1.00 Belize dollar random",
5373 "1.00 Belize dollars random",
5374 "1.00 Bermudan Dollar random",
5375 "1.00 Bermudan dollar random",
5376 "1.00 Bermudan dollars random",
5377 "1.00 Bhutanese Ngultrum random",
5378 "1.00 Bhutanese ngultrum random",
5379 "1.00 Bhutanese ngultrums random",
5380 "1.00 Bolivian Mvdol random",
5381 "1.00 Bolivian Peso random",
5382 "1.00 Bolivian mvdol random",
5383 "1.00 Bolivian mvdols random",
5384 "1.00 Bolivian peso random",
5385 "1.00 Bolivian pesos random",
5386 "1.00 Bolivian Boliviano random",
5387 "1.00 Bolivian Boliviano random",
5388 "1.00 Bolivian Bolivianos random",
5389 "1.00 Bosnia-Herzegovina Convertible Mark random",
5390 "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
5391 "1.00 Bosnia-Herzegovina convertible mark random",
5392 "1.00 Bosnia-Herzegovina convertible marks random",
5393 "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
5394 "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
5395 "1.00 Botswanan Pula random",
5396 "1.00 Botswanan pula random",
5397 "1.00 Botswanan pulas random",
5398 "1.00 Brazilian New Cruzado (1989\\u20131990) random",
5399 "1.00 Brazilian Cruzado (1986\\u20131989) random",
5400 "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
5401 "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
5402 "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
5403 "1.00 Brazilian Real random",
5404 "1.00 Brazilian new cruzado (1989\\u20131990) random",
5405 "1.00 Brazilian new cruzados (1989\\u20131990) random",
5406 "1.00 Brazilian cruzado (1986\\u20131989) random",
5407 "1.00 Brazilian cruzados (1986\\u20131989) random",
5408 "1.00 Brazilian cruzeiro (1990\\u20131993) random",
5409 "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
5410 "1.00 Brazilian cruzeiro (1993\\u20131994) random",
5411 "1.00 Brazilian cruzeiros (1990\\u20131993) random",
5412 "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
5413 "1.00 Brazilian cruzeiros (1993\\u20131994) random",
5414 "1.00 Brazilian real random",
5415 "1.00 Brazilian reals random",
5416 "1.00 British Pound random",
5417 "1.00 British pound random",
5418 "1.00 British pounds random",
5419 "1.00 Brunei Dollar random",
5420 "1.00 Brunei dollar random",
5421 "1.00 Brunei dollars random",
5422 "1.00 Bulgarian Hard Lev random",
5423 "1.00 Bulgarian Lev random",
5424 "1.00 Bulgarian Leva random",
5425 "1.00 Bulgarian hard lev random",
5426 "1.00 Bulgarian hard leva random",
5427 "1.00 Bulgarian lev random",
5428 "1.00 Burmese Kyat random",
5429 "1.00 Burmese kyat random",
5430 "1.00 Burmese kyats random",
5431 "1.00 Burundian Franc random",
5432 "1.00 Burundian franc random",
5433 "1.00 Burundian francs random",
5434 "1.00 Cambodian Riel random",
5435 "1.00 Cambodian riel random",
5436 "1.00 Cambodian riels random",
5437 "1.00 Canadian Dollar random",
5438 "1.00 Canadian dollar random",
5439 "1.00 Canadian dollars random",
5440 "1.00 Cape Verdean Escudo random",
5441 "1.00 Cape Verdean escudo random",
5442 "1.00 Cape Verdean escudos random",
5443 "1.00 Cayman Islands Dollar random",
5444 "1.00 Cayman Islands dollar random",
5445 "1.00 Cayman Islands dollars random",
5446 "1.00 Chilean Peso random",
5447 "1.00 Chilean Unit of Account (UF) random",
5448 "1.00 Chilean peso random",
5449 "1.00 Chilean pesos random",
5450 "1.00 Chilean unit of account (UF) random",
5451 "1.00 Chilean units of account (UF) random",
5452 "1.00 Chinese Yuan random",
5453 "1.00 Chinese yuan random",
5454 "1.00 Colombian Peso random",
5455 "1.00 Colombian peso random",
5456 "1.00 Colombian pesos random",
5457 "1.00 Comorian Franc random",
5458 "1.00 Comorian franc random",
5459 "1.00 Comorian francs random",
5460 "1.00 Congolese Franc Congolais random",
5461 "1.00 Congolese franc Congolais random",
5462 "1.00 Congolese francs Congolais random",
5463 "1.00 Costa Rican Col\\u00f3n random",
5464 "1.00 Costa Rican col\\u00f3n random",
5465 "1.00 Costa Rican col\\u00f3ns random",
5466 "1.00 Croatian Dinar random",
5467 "1.00 Croatian Kuna random",
5468 "1.00 Croatian dinar random",
5469 "1.00 Croatian dinars random",
5470 "1.00 Croatian kuna random",
5471 "1.00 Croatian kunas random",
5472 "1.00 Cuban Peso random",
5473 "1.00 Cuban peso random",
5474 "1.00 Cuban pesos random",
5475 "1.00 Cypriot Pound random",
5476 "1.00 Cypriot pound random",
5477 "1.00 Cypriot pounds random",
5478 "1.00 Czech Koruna random",
5479 "1.00 Czech koruna random",
5480 "1.00 Czech korunas random",
5481 "1.00 Czechoslovak Hard Koruna random",
5482 "1.00 Czechoslovak hard koruna random",
5483 "1.00 Czechoslovak hard korunas random",
5484 "1.00 Danish Krone random",
5485 "1.00 Danish krone random",
5486 "1.00 Danish kroner random",
5487 "1.00 German Mark random",
5488 "1.00 German mark random",
5489 "1.00 German marks random",
5490 "1.00 Djiboutian Franc random",
5491 "1.00 Djiboutian franc random",
5492 "1.00 Djiboutian francs random",
5493 "1.00 Dominican Peso random",
5494 "1.00 Dominican peso random",
5495 "1.00 Dominican pesos random",
5496 "1.00 East Caribbean Dollar random",
5497 "1.00 East Caribbean dollar random",
5498 "1.00 East Caribbean dollars random",
5499 "1.00 East German Mark random",
5500 "1.00 East German mark random",
5501 "1.00 East German marks random",
5502 "1.00 Ecuadorian Sucre random",
5503 "1.00 Ecuadorian Unit of Constant Value random",
5504 "1.00 Ecuadorian sucre random",
5505 "1.00 Ecuadorian sucres random",
5506 "1.00 Ecuadorian unit of constant value random",
5507 "1.00 Ecuadorian units of constant value random",
5508 "1.00 Egyptian Pound random",
5509 "1.00 Egyptian pound random",
5510 "1.00 Egyptian pounds random",
5511 "1.00 Salvadoran Col\\u00f3n random",
5512 "1.00 Salvadoran col\\u00f3n random",
5513 "1.00 Salvadoran colones random",
5514 "1.00 Equatorial Guinean Ekwele random",
5515 "1.00 Equatorial Guinean ekwele random",
5516 "1.00 Eritrean Nakfa random",
5517 "1.00 Eritrean nakfa random",
5518 "1.00 Eritrean nakfas random",
5519 "1.00 Estonian Kroon random",
5520 "1.00 Estonian kroon random",
5521 "1.00 Estonian kroons random",
5522 "1.00 Ethiopian Birr random",
5523 "1.00 Ethiopian birr random",
5524 "1.00 Ethiopian birrs random",
5525 "1.00 European Composite Unit random",
5526 "1.00 European Currency Unit random",
5527 "1.00 European Monetary Unit random",
5528 "1.00 European Unit of Account (XBC) random",
5529 "1.00 European Unit of Account (XBD) random",
5530 "1.00 European composite unit random",
5531 "1.00 European composite units random",
5532 "1.00 European currency unit random",
5533 "1.00 European currency units random",
5534 "1.00 European monetary unit random",
5535 "1.00 European monetary units random",
5536 "1.00 European unit of account (XBC) random",
5537 "1.00 European unit of account (XBD) random",
5538 "1.00 European units of account (XBC) random",
5539 "1.00 European units of account (XBD) random",
5540 "1.00 Falkland Islands Pound random",
5541 "1.00 Falkland Islands pound random",
5542 "1.00 Falkland Islands pounds random",
5543 "1.00 Fijian Dollar random",
5544 "1.00 Fijian dollar random",
5545 "1.00 Fijian dollars random",
5546 "1.00 Finnish Markka random",
5547 "1.00 Finnish markka random",
5548 "1.00 Finnish markkas random",
5549 "1.00 French Franc random",
5550 "1.00 French Gold Franc random",
5551 "1.00 French UIC-Franc random",
5552 "1.00 French UIC-franc random",
5553 "1.00 French UIC-francs random",
5554 "1.00 French franc random",
5555 "1.00 French francs random",
5556 "1.00 French gold franc random",
5557 "1.00 French gold francs random",
5558 "1.00 Gambian Dalasi random",
5559 "1.00 Gambian dalasi random",
5560 "1.00 Gambian dalasis random",
5561 "1.00 Georgian Kupon Larit random",
5562 "1.00 Georgian Lari random",
5563 "1.00 Georgian kupon larit random",
5564 "1.00 Georgian kupon larits random",
5565 "1.00 Georgian lari random",
5566 "1.00 Georgian laris random",
5567 "1.00 Ghanaian Cedi (1979\\u20132007) random",
5568 "1.00 Ghanaian Cedi random",
5569 "1.00 Ghanaian cedi (1979\\u20132007) random",
5570 "1.00 Ghanaian cedi random",
5571 "1.00 Ghanaian cedis (1979\\u20132007) random",
5572 "1.00 Ghanaian cedis random",
5573 "1.00 Gibraltar Pound random",
5574 "1.00 Gibraltar pound random",
5575 "1.00 Gibraltar pounds random",
5576 "1.00 Gold random",
5577 "1.00 Gold random",
5578 "1.00 Greek Drachma random",
5579 "1.00 Greek drachma random",
5580 "1.00 Greek drachmas random",
5581 "1.00 Guatemalan Quetzal random",
5582 "1.00 Guatemalan quetzal random",
5583 "1.00 Guatemalan quetzals random",
5584 "1.00 Guinean Franc random",
5585 "1.00 Guinean Syli random",
5586 "1.00 Guinean franc random",
5587 "1.00 Guinean francs random",
5588 "1.00 Guinean syli random",
5589 "1.00 Guinean sylis random",
5590 "1.00 Guinea-Bissau Peso random",
5591 "1.00 Guinea-Bissau peso random",
5592 "1.00 Guinea-Bissau pesos random",
5593 "1.00 Guyanaese Dollar random",
5594 "1.00 Guyanaese dollar random",
5595 "1.00 Guyanaese dollars random",
5596 "1.00 Haitian Gourde random",
5597 "1.00 Haitian gourde random",
5598 "1.00 Haitian gourdes random",
5599 "1.00 Honduran Lempira random",
5600 "1.00 Honduran lempira random",
5601 "1.00 Honduran lempiras random",
5602 "1.00 Hong Kong Dollar random",
5603 "1.00 Hong Kong dollar random",
5604 "1.00 Hong Kong dollars random",
5605 "1.00 Hungarian Forint random",
5606 "1.00 Hungarian forint random",
5607 "1.00 Hungarian forints random",
5608 "1.00 Icelandic Kr\\u00f3na random",
5609 "1.00 Icelandic kr\\u00f3na random",
5610 "1.00 Icelandic kr\\u00f3nur random",
5611 "1.00 Indian Rupee random",
5612 "1.00 Indian rupee random",
5613 "1.00 Indian rupees random",
5614 "1.00 Indonesian Rupiah random",
5615 "1.00 Indonesian rupiah random",
5616 "1.00 Indonesian rupiahs random",
5617 "1.00 Iranian Rial random",
5618 "1.00 Iranian rial random",
5619 "1.00 Iranian rials random",
5620 "1.00 Iraqi Dinar random",
5621 "1.00 Iraqi dinar random",
5622 "1.00 Iraqi dinars random",
5623 "1.00 Irish Pound random",
5624 "1.00 Irish pound random",
5625 "1.00 Irish pounds random",
5626 "1.00 Israeli Pound random",
5627 "1.00 Israeli new shekel random",
5628 "1.00 Israeli pound random",
5629 "1.00 Israeli pounds random",
5630 "1.00 Italian Lira random",
5631 "1.00 Italian lira random",
5632 "1.00 Italian liras random",
5633 "1.00 Jamaican Dollar random",
5634 "1.00 Jamaican dollar random",
5635 "1.00 Jamaican dollars random",
5636 "1.00 Japanese Yen random",
5637 "1.00 Japanese yen random",
5638 "1.00 Jordanian Dinar random",
5639 "1.00 Jordanian dinar random",
5640 "1.00 Jordanian dinars random",
5641 "1.00 Kazakhstani Tenge random",
5642 "1.00 Kazakhstani tenge random",
5643 "1.00 Kazakhstani tenges random",
5644 "1.00 Kenyan Shilling random",
5645 "1.00 Kenyan shilling random",
5646 "1.00 Kenyan shillings random",
5647 "1.00 Kuwaiti Dinar random",
5648 "1.00 Kuwaiti dinar random",
5649 "1.00 Kuwaiti dinars random",
5650 "1.00 Kyrgystani Som random",
5651 "1.00 Kyrgystani som random",
5652 "1.00 Kyrgystani soms random",
5653 "1.00 Laotian Kip random",
5654 "1.00 Laotian kip random",
5655 "1.00 Laotian kips random",
5656 "1.00 Latvian Lats random",
5657 "1.00 Latvian Ruble random",
5658 "1.00 Latvian lats random",
5659 "1.00 Latvian lati random",
5660 "1.00 Latvian ruble random",
5661 "1.00 Latvian rubles random",
5662 "1.00 Lebanese Pound random",
5663 "1.00 Lebanese pound random",
5664 "1.00 Lebanese pounds random",
5665 "1.00 Lesotho Loti random",
5666 "1.00 Lesotho loti random",
5667 "1.00 Lesotho lotis random",
5668 "1.00 Liberian Dollar random",
5669 "1.00 Liberian dollar random",
5670 "1.00 Liberian dollars random",
5671 "1.00 Libyan Dinar random",
5672 "1.00 Libyan dinar random",
5673 "1.00 Libyan dinars random",
5674 "1.00 Lithuanian Litas random",
5675 "1.00 Lithuanian Talonas random",
5676 "1.00 Lithuanian litas random",
5677 "1.00 Lithuanian litai random",
5678 "1.00 Lithuanian talonas random",
5679 "1.00 Lithuanian talonases random",
5680 "1.00 Luxembourgian Convertible Franc random",
5681 "1.00 Luxembourg Financial Franc random",
5682 "1.00 Luxembourgian Franc random",
5683 "1.00 Luxembourgian convertible franc random",
5684 "1.00 Luxembourgian convertible francs random",
5685 "1.00 Luxembourg financial franc random",
5686 "1.00 Luxembourg financial francs random",
5687 "1.00 Luxembourgian franc random",
5688 "1.00 Luxembourgian francs random",
5689 "1.00 Macanese Pataca random",
5690 "1.00 Macanese pataca random",
5691 "1.00 Macanese patacas random",
5692 "1.00 Macedonian Denar random",
5693 "1.00 Macedonian denar random",
5694 "1.00 Macedonian denari random",
5695 "1.00 Malagasy Ariaries random",
5696 "1.00 Malagasy Ariary random",
5697 "1.00 Malagasy Ariary random",
5698 "1.00 Malagasy Franc random",
5699 "1.00 Malagasy franc random",
5700 "1.00 Malagasy francs random",
5701 "1.00 Malawian Kwacha random",
5702 "1.00 Malawian Kwacha random",
5703 "1.00 Malawian Kwachas random",
5704 "1.00 Malaysian Ringgit random",
5705 "1.00 Malaysian ringgit random",
5706 "1.00 Malaysian ringgits random",
5707 "1.00 Maldivian Rufiyaa random",
5708 "1.00 Maldivian rufiyaa random",
5709 "1.00 Maldivian rufiyaas random",
5710 "1.00 Malian Franc random",
5711 "1.00 Malian franc random",
5712 "1.00 Malian francs random",
5713 "1.00 Maltese Lira random",
5714 "1.00 Maltese Pound random",
5715 "1.00 Maltese lira random",
5716 "1.00 Maltese liras random",
5717 "1.00 Maltese pound random",
5718 "1.00 Maltese pounds random",
5719 "1.00 Mauritanian Ouguiya random",
5720 "1.00 Mauritanian ouguiya random",
5721 "1.00 Mauritanian ouguiyas random",
5722 "1.00 Mauritian Rupee random",
5723 "1.00 Mauritian rupee random",
5724 "1.00 Mauritian rupees random",
5725 "1.00 Mexican Peso random",
5726 "1.00 Mexican Silver Peso (1861\\u20131992) random",
5727 "1.00 Mexican Investment Unit random",
5728 "1.00 Mexican peso random",
5729 "1.00 Mexican pesos random",
5730 "1.00 Mexican silver peso (1861\\u20131992) random",
5731 "1.00 Mexican silver pesos (1861\\u20131992) random",
5732 "1.00 Mexican investment unit random",
5733 "1.00 Mexican investment units random",
5734 "1.00 Moldovan Leu random",
5735 "1.00 Moldovan leu random",
5736 "1.00 Moldovan lei random",
5737 "1.00 Mongolian Tugrik random",
5738 "1.00 Mongolian tugrik random",
5739 "1.00 Mongolian tugriks random",
5740 "1.00 Moroccan Dirham random",
5741 "1.00 Moroccan Franc random",
5742 "1.00 Moroccan dirham random",
5743 "1.00 Moroccan dirhams random",
5744 "1.00 Moroccan franc random",
5745 "1.00 Moroccan francs random",
5746 "1.00 Mozambican Escudo random",
5747 "1.00 Mozambican Metical random",
5748 "1.00 Mozambican escudo random",
5749 "1.00 Mozambican escudos random",
5750 "1.00 Mozambican metical random",
5751 "1.00 Mozambican meticals random",
5752 "1.00 Myanmar Kyat random",
5753 "1.00 Myanmar kyat random",
5754 "1.00 Myanmar kyats random",
5755 "1.00 Namibian Dollar random",
5756 "1.00 Namibian dollar random",
5757 "1.00 Namibian dollars random",
5758 "1.00 Nepalese Rupee random",
5759 "1.00 Nepalese rupee random",
5760 "1.00 Nepalese rupees random",
5761 "1.00 Netherlands Antillean Guilder random",
5762 "1.00 Netherlands Antillean guilder random",
5763 "1.00 Netherlands Antillean guilders random",
5764 "1.00 Dutch Guilder random",
5765 "1.00 Dutch guilder random",
5766 "1.00 Dutch guilders random",
5767 "1.00 Israeli New Shekel random",
5768 "1.00 Israeli new shekels random",
5769 "1.00 New Zealand Dollar random",
5770 "1.00 New Zealand dollar random",
5771 "1.00 New Zealand dollars random",
5772 "1.00 Nicaraguan C\\u00f3rdoba random",
5773 "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
5774 "1.00 Nicaraguan c\\u00f3rdoba random",
5775 "1.00 Nicaraguan c\\u00f3rdoba random",
5776 "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
5777 "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
5778 "1.00 Nigerian Naira random",
5779 "1.00 Nigerian naira random",
5780 "1.00 Nigerian nairas random",
5781 "1.00 North Korean Won random",
5782 "1.00 North Korean won random",
5783 "1.00 North Korean won random",
5784 "1.00 Norwegian Krone random",
5785 "1.00 Norwegian krone random",
5786 "1.00 Norwegian kroner random",
5787 "1.00 Mozambican Metical (1980\\u20132006) random",
5788 "1.00 Mozambican metical (1980\\u20132006) random",
5789 "1.00 Mozambican meticals (1980\\u20132006) random",
5790 "1.00 Romanian Lei (1952\\u20132006) random",
5791 "1.00 Romanian Leu (1952\\u20132006) random",
5792 "1.00 Romanian leu (1952\\u20132006) random",
5793 "1.00 Serbian Dinar (2002\\u20132006) random",
5794 "1.00 Serbian dinar (2002\\u20132006) random",
5795 "1.00 Serbian dinars (2002\\u20132006) random",
5796 "1.00 Sudanese Dinar (1992\\u20132007) random",
5797 "1.00 Sudanese Pound (1957\\u20131998) random",
5798 "1.00 Sudanese dinar (1992\\u20132007) random",
5799 "1.00 Sudanese dinars (1992\\u20132007) random",
5800 "1.00 Sudanese pound (1957\\u20131998) random",
5801 "1.00 Sudanese pounds (1957\\u20131998) random",
5802 "1.00 Turkish Lira (1922\\u20132005) random",
5803 "1.00 Turkish Lira (1922\\u20132005) random",
5804 "1.00 Omani Rial random",
5805 "1.00 Omani rial random",
5806 "1.00 Omani rials random",
5807 "1.00 Pakistani Rupee random",
5808 "1.00 Pakistani rupee random",
5809 "1.00 Pakistani rupees random",
5810 "1.00 Palladium random",
5811 "1.00 Palladium random",
5812 "1.00 Panamanian Balboa random",
5813 "1.00 Panamanian balboa random",
5814 "1.00 Panamanian balboas random",
5815 "1.00 Papua New Guinean Kina random",
5816 "1.00 Papua New Guinean kina random",
5817 "1.00 Papua New Guinean kina random",
5818 "1.00 Paraguayan Guarani random",
5819 "1.00 Paraguayan guarani random",
5820 "1.00 Paraguayan guaranis random",
5821 "1.00 Peruvian Inti random",
5822 "1.00 Peruvian Sol random",
5823 "1.00 Peruvian Sol (1863\\u20131965) random",
5824 "1.00 Peruvian inti random",
5825 "1.00 Peruvian intis random",
5826 "1.00 Peruvian sol random",
5827 "1.00 Peruvian soles random",
5828 "1.00 Peruvian sol (1863\\u20131965) random",
5829 "1.00 Peruvian soles (1863\\u20131965) random",
Frank Tangd2858cb2022-04-08 20:34:12 -07005830 "1.00 Philippine Peso random",
5831 "1.00 Philippine peso random",
5832 "1.00 Philippine pesos random",
Frank Tang3e05d9d2021-11-08 14:04:04 -08005833 "1.00 Platinum random",
5834 "1.00 Platinum random",
5835 "1.00 Polish Zloty (1950\\u20131995) random",
5836 "1.00 Polish Zloty random",
5837 "1.00 Polish zlotys random",
5838 "1.00 Polish zloty (PLZ) random",
5839 "1.00 Polish zloty random",
5840 "1.00 Polish zlotys (PLZ) random",
5841 "1.00 Portuguese Escudo random",
5842 "1.00 Portuguese Guinea Escudo random",
5843 "1.00 Portuguese Guinea escudo random",
5844 "1.00 Portuguese Guinea escudos random",
5845 "1.00 Portuguese escudo random",
5846 "1.00 Portuguese escudos random",
5847 "1.00 Qatari Rial random",
5848 "1.00 Qatari rial random",
5849 "1.00 Qatari rials random",
5850 "1.00 RINET Funds random",
5851 "1.00 RINET Funds random",
5852 "1.00 Rhodesian Dollar random",
5853 "1.00 Rhodesian dollar random",
5854 "1.00 Rhodesian dollars random",
5855 "1.00 Romanian Leu random",
5856 "1.00 Romanian lei random",
5857 "1.00 Romanian leu random",
5858 "1.00 Russian Ruble (1991\\u20131998) random",
5859 "1.00 Russian Ruble random",
5860 "1.00 Russian ruble (1991\\u20131998) random",
5861 "1.00 Russian ruble random",
5862 "1.00 Russian rubles (1991\\u20131998) random",
5863 "1.00 Russian rubles random",
5864 "1.00 Rwandan Franc random",
5865 "1.00 Rwandan franc random",
5866 "1.00 Rwandan francs random",
5867 "1.00 St. Helena Pound random",
5868 "1.00 St. Helena pound random",
5869 "1.00 St. Helena pounds random",
5870 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
5871 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
5872 "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
5873 "1.00 Saudi Riyal random",
5874 "1.00 Saudi riyal random",
5875 "1.00 Saudi riyals random",
5876 "1.00 Serbian Dinar random",
5877 "1.00 Serbian dinar random",
5878 "1.00 Serbian dinars random",
5879 "1.00 Seychellois Rupee random",
5880 "1.00 Seychellois rupee random",
5881 "1.00 Seychellois rupees random",
5882 "1.00 Sierra Leonean Leone random",
5883 "1.00 Sierra Leonean leone random",
5884 "1.00 Sierra Leonean leones random",
5885 "1.00 Singapore Dollar random",
5886 "1.00 Singapore dollar random",
5887 "1.00 Singapore dollars random",
5888 "1.00 Slovak Koruna random",
5889 "1.00 Slovak koruna random",
5890 "1.00 Slovak korunas random",
5891 "1.00 Slovenian Tolar random",
5892 "1.00 Slovenian tolar random",
5893 "1.00 Slovenian tolars random",
5894 "1.00 Solomon Islands Dollar random",
5895 "1.00 Solomon Islands dollar random",
5896 "1.00 Solomon Islands dollars random",
5897 "1.00 Somali Shilling random",
5898 "1.00 Somali shilling random",
5899 "1.00 Somali shillings random",
5900 "1.00 South African Rand (financial) random",
5901 "1.00 South African Rand random",
5902 "1.00 South African rand (financial) random",
5903 "1.00 South African rand random",
5904 "1.00 South African rands (financial) random",
5905 "1.00 South African rand random",
5906 "1.00 South Korean Won random",
5907 "1.00 South Korean won random",
5908 "1.00 South Korean won random",
5909 "1.00 Soviet Rouble random",
5910 "1.00 Soviet rouble random",
5911 "1.00 Soviet roubles random",
5912 "1.00 Spanish Peseta (A account) random",
5913 "1.00 Spanish Peseta (convertible account) random",
5914 "1.00 Spanish Peseta random",
5915 "1.00 Spanish peseta (A account) random",
5916 "1.00 Spanish peseta (convertible account) random",
5917 "1.00 Spanish peseta random",
5918 "1.00 Spanish pesetas (A account) random",
5919 "1.00 Spanish pesetas (convertible account) random",
5920 "1.00 Spanish pesetas random",
5921 "1.00 Special Drawing Rights random",
5922 "1.00 Sri Lankan Rupee random",
5923 "1.00 Sri Lankan rupee random",
5924 "1.00 Sri Lankan rupees random",
5925 "1.00 Sudanese Pound random",
5926 "1.00 Sudanese pound random",
5927 "1.00 Sudanese pounds random",
5928 "1.00 Surinamese Dollar random",
5929 "1.00 Surinamese dollar random",
5930 "1.00 Surinamese dollars random",
5931 "1.00 Surinamese Guilder random",
5932 "1.00 Surinamese guilder random",
5933 "1.00 Surinamese guilders random",
5934 "1.00 Swazi Lilangeni random",
5935 "1.00 Swazi lilangeni random",
5936 "1.00 Swazi emalangeni random",
5937 "1.00 Swedish Krona random",
5938 "1.00 Swedish krona random",
5939 "1.00 Swedish kronor random",
5940 "1.00 Swiss Franc random",
5941 "1.00 Swiss franc random",
5942 "1.00 Swiss francs random",
5943 "1.00 Syrian Pound random",
5944 "1.00 Syrian pound random",
5945 "1.00 Syrian pounds random",
5946 "1.00 New Taiwan Dollar random",
5947 "1.00 New Taiwan dollar random",
5948 "1.00 New Taiwan dollars random",
5949 "1.00 Tajikistani Ruble random",
5950 "1.00 Tajikistani Somoni random",
5951 "1.00 Tajikistani ruble random",
5952 "1.00 Tajikistani rubles random",
5953 "1.00 Tajikistani somoni random",
5954 "1.00 Tajikistani somonis random",
5955 "1.00 Tanzanian Shilling random",
5956 "1.00 Tanzanian shilling random",
5957 "1.00 Tanzanian shillings random",
5958 "1.00 Testing Currency Code random",
5959 "1.00 Testing Currency Code random",
5960 "1.00 Thai Baht random",
5961 "1.00 Thai baht random",
5962 "1.00 Thai baht random",
5963 "1.00 Timorese Escudo random",
5964 "1.00 Timorese escudo random",
5965 "1.00 Timorese escudos random",
5966 "1.00 Trinidad & Tobago Dollar random",
5967 "1.00 Trinidad & Tobago dollar random",
5968 "1.00 Trinidad & Tobago dollars random",
5969 "1.00 Tunisian Dinar random",
5970 "1.00 Tunisian dinar random",
5971 "1.00 Tunisian dinars random",
5972 "1.00 Turkish Lira random",
5973 "1.00 Turkish Lira random",
5974 "1.00 Turkish lira random",
5975 "1.00 Turkmenistani Manat random",
5976 "1.00 Turkmenistani manat random",
5977 "1.00 Turkmenistani manat random",
5978 "1.00 US Dollar (Next day) random",
5979 "1.00 US Dollar (Same day) random",
5980 "1.00 US Dollar random",
5981 "1.00 US dollar (next day) random",
5982 "1.00 US dollar (same day) random",
5983 "1.00 US dollar random",
5984 "1.00 US dollars (next day) random",
5985 "1.00 US dollars (same day) random",
5986 "1.00 US dollars random",
5987 "1.00 Ugandan Shilling (1966\\u20131987) random",
5988 "1.00 Ugandan Shilling random",
5989 "1.00 Ugandan shilling (1966\\u20131987) random",
5990 "1.00 Ugandan shilling random",
5991 "1.00 Ugandan shillings (1966\\u20131987) random",
5992 "1.00 Ugandan shillings random",
5993 "1.00 Ukrainian Hryvnia random",
5994 "1.00 Ukrainian Karbovanets random",
5995 "1.00 Ukrainian hryvnia random",
5996 "1.00 Ukrainian hryvnias random",
5997 "1.00 Ukrainian karbovanets random",
5998 "1.00 Ukrainian karbovantsiv random",
5999 "1.00 Colombian Real Value Unit random",
6000 "1.00 United Arab Emirates Dirham random",
6001 "1.00 Unknown Currency random",
6002 "1.00 Uruguayan Peso (1975\\u20131993) random",
6003 "1.00 Uruguayan Peso random",
6004 "1.00 Uruguayan Peso (Indexed Units) random",
6005 "1.00 Uruguayan peso (1975\\u20131993) random",
6006 "1.00 Uruguayan peso (indexed units) random",
6007 "1.00 Uruguayan peso random",
6008 "1.00 Uruguayan pesos (1975\\u20131993) random",
6009 "1.00 Uruguayan pesos (indexed units) random",
6010 "1.00 Uzbekistani Som random",
6011 "1.00 Uzbekistani som random",
6012 "1.00 Uzbekistani som random",
6013 "1.00 Vanuatu Vatu random",
6014 "1.00 Vanuatu vatu random",
6015 "1.00 Vanuatu vatus random",
6016 "1.00 Venezuelan Bol\\u00edvar random",
6017 "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
6018 "1.00 Venezuelan bol\\u00edvar random",
6019 "1.00 Venezuelan bol\\u00edvars random",
6020 "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
6021 "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
6022 "1.00 Vietnamese Dong random",
6023 "1.00 Vietnamese dong random",
6024 "1.00 Vietnamese dong random",
6025 "1.00 WIR Euro random",
6026 "1.00 WIR Franc random",
6027 "1.00 WIR euro random",
6028 "1.00 WIR euros random",
6029 "1.00 WIR franc random",
6030 "1.00 WIR francs random",
6031 "1.00 Samoan Tala random",
6032 "1.00 Samoan tala random",
6033 "1.00 Samoan tala random",
6034 "1.00 Yemeni Dinar random",
6035 "1.00 Yemeni Rial random",
6036 "1.00 Yemeni dinar random",
6037 "1.00 Yemeni dinars random",
6038 "1.00 Yemeni rial random",
6039 "1.00 Yemeni rials random",
6040 "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
6041 "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
6042 "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
6043 "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
6044 "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
6045 "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
6046 "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
6047 "1.00 Yugoslavian new dinar (1994\\u20132002) random",
6048 "1.00 Yugoslavian new dinars (1994\\u20132002) random",
6049 "1.00 Zairean New Zaire (1993\\u20131998) random",
6050 "1.00 Zairean Zaire (1971\\u20131993) random",
6051 "1.00 Zairean new zaire (1993\\u20131998) random",
6052 "1.00 Zairean new zaires (1993\\u20131998) random",
6053 "1.00 Zairean zaire (1971\\u20131993) random",
6054 "1.00 Zairean zaires (1971\\u20131993) random",
6055 "1.00 Zambian Kwacha random",
6056 "1.00 Zambian kwacha random",
6057 "1.00 Zambian kwachas random",
6058 "1.00 Zimbabwean Dollar (1980\\u20132008) random",
6059 "1.00 Zimbabwean dollar (1980\\u20132008) random",
6060 "1.00 Zimbabwean dollars (1980\\u20132008) random",
6061 "1.00 euro random",
6062 "1.00 euros random",
6063 "1.00 Turkish lira (1922\\u20132005) random",
6064 "1.00 special drawing rights random",
6065 "1.00 Colombian real value unit random",
6066 "1.00 Colombian real value units random",
6067 "1.00 unknown currency random",
6068 };
6069
6070 const char* WRONG_DATA[] = {
6071 // Following are missing one last char in the currency name
6072 "1.00 Nicaraguan Cordob",
6073 "1.00 Namibian Dolla",
6074 "1.00 Namibian dolla",
6075 "1.00 Nepalese Rupe",
6076 "1.00 Nepalese rupe",
6077 "1.00 Netherlands Antillean Guilde",
6078 "1.00 Netherlands Antillean guilde",
6079 "1.00 Dutch Guilde",
6080 "1.00 Dutch guilde",
6081 "1.00 Israeli New Sheqe",
6082 "1.00 New Zealand Dolla",
6083 "1.00 New Zealand dolla",
6084 "1.00 Nicaraguan cordob",
6085 "1.00 Nigerian Nair",
6086 "1.00 Nigerian nair",
6087 "1.00 North Korean Wo",
6088 "1.00 North Korean wo",
6089 "1.00 Norwegian Kron",
6090 "1.00 Norwegian kron",
6091 "1.00 US dolla",
6092 "1.00",
6093 "A1.00",
6094 "AD1.00",
6095 "AE1.00",
6096 "AF1.00",
6097 "AL1.00",
6098 "AM1.00",
6099 "AN1.00",
6100 "AO1.00",
6101 "AR1.00",
6102 "AT1.00",
6103 "AU1.00",
6104 "AW1.00",
6105 "AZ1.00",
6106 "Afghan Afghan1.00",
6107 "Afghan Afghani (1927\\u201320021.00",
6108 "Afl1.00",
6109 "Albanian Le1.00",
6110 "Algerian Dina1.00",
6111 "Andorran Peset1.00",
6112 "Angolan Kwanz1.00",
6113 "Angolan Kwanza (1977\\u201319901.00",
6114 "Angolan Readjusted Kwanza (1995\\u201319991.00",
6115 "Angolan New Kwanza (1990\\u201320001.00",
6116 "Argentine Austra1.00",
6117 "Argentine Pes1.00",
6118 "Argentine Peso (1983\\u201319851.00",
6119 "Armenian Dra1.00",
6120 "Aruban Flori1.00",
6121 "Australian Dolla1.00",
6122 "Austrian Schillin1.00",
6123 "Azerbaijani Mana1.00",
6124 "Azerbaijani Manat (1993\\u201320061.00",
6125 "B1.00",
6126 "BA1.00",
6127 "BB1.00",
6128 "BE1.00",
6129 "BG1.00",
6130 "BH1.00",
6131 "BI1.00",
6132 "BM1.00",
6133 "BN1.00",
6134 "BO1.00",
6135 "BR1.00",
6136 "BS1.00",
6137 "BT1.00",
6138 "BU1.00",
6139 "BW1.00",
6140 "BY1.00",
6141 "BZ1.00",
6142 "Bahamian Dolla1.00",
6143 "Bahraini Dina1.00",
6144 "Bangladeshi Tak1.00",
6145 "Barbadian Dolla1.00",
6146 "Bds1.00",
6147 "Belarusian Ruble (1994\\u201319991.00",
6148 "Belarusian Rubl1.00",
6149 "Belgian Fran1.00",
6150 "Belgian Franc (convertible1.00",
6151 "Belgian Franc (financial1.00",
6152 "Belize Dolla1.00",
6153 "Bermudan Dolla1.00",
6154 "Bhutanese Ngultru1.00",
6155 "Bolivian Mvdo1.00",
6156 "Bolivian Pes1.00",
6157 "Bolivian Bolivian1.00",
6158 "Bosnia-Herzegovina Convertible Mar1.00",
6159 "Bosnia-Herzegovina Dina1.00",
6160 "Botswanan Pul1.00",
6161 "Brazilian Cruzad1.00",
6162 "Brazilian Cruzado Nov1.00",
6163 "Brazilian Cruzeir1.00",
6164 "Brazilian Cruzeiro (1990\\u201319931.00",
6165 "Brazilian New Cruzeiro (1967\\u201319861.00",
6166 "Brazilian Rea1.00",
6167 "British Pound Sterlin1.00",
6168 "Brunei Dolla1.00",
6169 "Bulgarian Hard Le1.00",
6170 "Bulgarian Le1.00",
6171 "Burmese Kya1.00",
6172 "Burundian Fran1.00",
6173 "C1.00",
6174 "CA1.00",
6175 "CD1.00",
6176 "CFP Fran1.00",
6177 "CFP1.00",
6178 "CH1.00",
6179 "CL1.00",
6180 "CN1.00",
6181 "CO1.00",
6182 "CS1.00",
6183 "CU1.00",
6184 "CV1.00",
6185 "CY1.00",
6186 "CZ1.00",
6187 "Cambodian Rie1.00",
6188 "Canadian Dolla1.00",
6189 "Cape Verdean Escud1.00",
6190 "Cayman Islands Dolla1.00",
6191 "Chilean Pes1.00",
6192 "Chilean Unit of Accoun1.00",
6193 "Chinese Yua1.00",
6194 "Colombian Pes1.00",
6195 "Comoro Fran1.00",
6196 "Congolese Fran1.00",
6197 "Costa Rican Col\\u00f31.00",
6198 "Croatian Dina1.00",
6199 "Croatian Kun1.00",
6200 "Cuban Pes1.00",
6201 "Cypriot Poun1.00",
6202 "Czech Republic Korun1.00",
6203 "Czechoslovak Hard Korun1.00",
6204 "D1.00",
6205 "DD1.00",
6206 "DE1.00",
6207 "DJ1.00",
6208 "DK1.00",
6209 "DO1.00",
6210 "DZ1.00",
6211 "Danish Kron1.00",
6212 "German Mar1.00",
6213 "Djiboutian Fran1.00",
6214 "Dk1.00",
6215 "Dominican Pes1.00",
6216 "EC1.00",
6217 "EE1.00",
6218 "EG1.00",
6219 "EQ1.00",
6220 "ER1.00",
6221 "ES1.00",
6222 "ET1.00",
6223 "EU1.00",
6224 "East Caribbean Dolla1.00",
6225 "East German Ostmar1.00",
6226 "Ecuadorian Sucr1.00",
6227 "Ecuadorian Unit of Constant Valu1.00",
6228 "Egyptian Poun1.00",
6229 "Ekwel1.00",
6230 "Salvadoran Col\\u00f31.00",
6231 "Equatorial Guinean Ekwel1.00",
6232 "Eritrean Nakf1.00",
6233 "Es1.00",
6234 "Estonian Kroo1.00",
6235 "Ethiopian Bir1.00",
6236 "Eur1.00",
6237 "European Composite Uni1.00",
6238 "European Currency Uni1.00",
6239 "European Monetary Uni1.00",
6240 "European Unit of Account (XBC1.00",
6241 "European Unit of Account (XBD1.00",
6242 "F1.00",
6243 "FB1.00",
6244 "FI1.00",
6245 "FJ1.00",
6246 "FK1.00",
6247 "FR1.00",
6248 "Falkland Islands Poun1.00",
6249 "Fd1.00",
6250 "Fijian Dolla1.00",
6251 "Finnish Markk1.00",
6252 "Fr1.00",
6253 "French Fran1.00",
6254 "French Gold Fran1.00",
6255 "French UIC-Fran1.00",
6256 "G1.00",
6257 "GB1.00",
6258 "GE1.00",
6259 "GH1.00",
6260 "GI1.00",
6261 "GM1.00",
6262 "GN1.00",
6263 "GQ1.00",
6264 "GR1.00",
6265 "GT1.00",
6266 "GW1.00",
6267 "GY1.00",
6268 "Gambian Dalas1.00",
6269 "Georgian Kupon Lari1.00",
6270 "Georgian Lar1.00",
6271 "Ghanaian Ced1.00",
6272 "Ghanaian Cedi (1979\\u201320071.00",
6273 "Gibraltar Poun1.00",
6274 "Gol1.00",
6275 "Greek Drachm1.00",
6276 "Guatemalan Quetza1.00",
6277 "Guinean Fran1.00",
6278 "Guinean Syl1.00",
6279 "Guinea-Bissau Pes1.00",
6280 "Guyanaese Dolla1.00",
6281 "HK1.00",
6282 "HN1.00",
6283 "HR1.00",
6284 "HT1.00",
6285 "HU1.00",
6286 "Haitian Gourd1.00",
6287 "Honduran Lempir1.00",
6288 "Hong Kong Dolla1.00",
6289 "Hungarian Forin1.00",
6290 "I1.00",
6291 "IE1.00",
6292 "IL1.00",
6293 "IN1.00",
6294 "IQ1.00",
6295 "IR1.00",
6296 "IS1.00",
6297 "IT1.00",
6298 "Icelandic Kron1.00",
6299 "Indian Rupe1.00",
6300 "Indonesian Rupia1.00",
6301 "Iranian Ria1.00",
6302 "Iraqi Dina1.00",
6303 "Irish Poun1.00",
6304 "Israeli Poun1.00",
6305 "Italian Lir1.00",
6306 "J1.00",
6307 "JM1.00",
6308 "JO1.00",
6309 "JP1.00",
6310 "Jamaican Dolla1.00",
6311 "Japanese Ye1.00",
6312 "Jordanian Dina1.00",
6313 "K S1.00",
6314 "K1.00",
6315 "KE1.00",
6316 "KG1.00",
6317 "KH1.00",
6318 "KP1.00",
6319 "KR1.00",
6320 "KW1.00",
6321 "KY1.00",
6322 "KZ1.00",
6323 "Kazakhstani Teng1.00",
6324 "Kenyan Shillin1.00",
6325 "Kuwaiti Dina1.00",
6326 "Kyrgystani So1.00",
6327 "LA1.00",
6328 "LB1.00",
6329 "LK1.00",
6330 "LR1.00",
6331 "LT1.00",
6332 "LU1.00",
6333 "LV1.00",
6334 "LY1.00",
6335 "Laotian Ki1.00",
6336 "Latvian Lat1.00",
6337 "Latvian Rubl1.00",
6338 "Lebanese Poun1.00",
6339 "Lesotho Lot1.00",
6340 "Liberian Dolla1.00",
6341 "Libyan Dina1.00",
6342 "Lithuanian Lit1.00",
6343 "Lithuanian Talona1.00",
6344 "Luxembourgian Convertible Fran1.00",
6345 "Luxembourg Financial Fran1.00",
6346 "Luxembourgian Fran1.00",
6347 "MA1.00",
6348 "MD1.00",
6349 "MDe1.00",
6350 "MEX1.00",
6351 "MG1.00",
6352 "ML1.00",
6353 "MM1.00",
6354 "MN1.00",
6355 "MO1.00",
6356 "MR1.00",
6357 "MT1.00",
6358 "MU1.00",
6359 "MV1.00",
6360 "MW1.00",
6361 "MX1.00",
6362 "MY1.00",
6363 "MZ1.00",
6364 "Macanese Patac1.00",
6365 "Macedonian Dena1.00",
6366 "Malagasy Ariar1.00",
6367 "Malagasy Fran1.00",
6368 "Malawian Kwach1.00",
6369 "Malaysian Ringgi1.00",
6370 "Maldivian Rufiya1.00",
6371 "Malian Fran1.00",
6372 "Malot1.00",
6373 "Maltese Lir1.00",
6374 "Maltese Poun1.00",
6375 "Mauritanian Ouguiy1.00",
6376 "Mauritian Rupe1.00",
6377 "Mexican Pes1.00",
6378 "Mexican Silver Peso (1861\\u201319921.00",
6379 "Mexican Investment Uni1.00",
6380 "Moldovan Le1.00",
6381 "Mongolian Tugri1.00",
6382 "Moroccan Dirha1.00",
6383 "Moroccan Fran1.00",
6384 "Mozambican Escud1.00",
6385 "Mozambican Metica1.00",
6386 "Myanmar Kya1.00",
6387 "N1.00",
6388 "NA1.00",
6389 "NAf1.00",
6390 "NG1.00",
6391 "NI1.00",
6392 "NK1.00",
6393 "NL1.00",
6394 "NO1.00",
6395 "NP1.00",
6396 "NT1.00",
6397 "Namibian Dolla1.00",
6398 "Nepalese Rupe1.00",
6399 "Netherlands Antillean Guilde1.00",
6400 "Dutch Guilde1.00",
6401 "Israeli New Sheqe1.00",
6402 "New Zealand Dolla1.00",
6403 "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
6404 "Nicaraguan C\\u00f3rdob1.00",
6405 "Nigerian Nair1.00",
6406 "North Korean Wo1.00",
6407 "Norwegian Kron1.00",
6408 "Nr1.00",
6409 "OM1.00",
6410 "Old Mozambican Metica1.00",
6411 "Romanian Leu (1952\\u201320061.00",
6412 "Serbian Dinar (2002\\u201320061.00",
6413 "Sudanese Dinar (1992\\u201320071.00",
6414 "Sudanese Pound (1957\\u201319981.00",
6415 "Turkish Lira (1922\\u201320051.00",
6416 "Omani Ria1.00",
6417 "PA1.00",
6418 "PE1.00",
6419 "PG1.00",
6420 "PH1.00",
6421 "PK1.00",
6422 "PL1.00",
6423 "PT1.00",
6424 "PY1.00",
6425 "Pakistani Rupe1.00",
6426 "Palladiu1.00",
6427 "Panamanian Balbo1.00",
6428 "Papua New Guinean Kin1.00",
6429 "Paraguayan Guaran1.00",
6430 "Peruvian Int1.00",
6431 "Peruvian Sol (1863\\u201319651.00",
6432 "Peruvian Sol Nuev1.00",
6433 "Philippine Pes1.00",
6434 "Platinu1.00",
6435 "Polish Zlot1.00",
6436 "Polish Zloty (1950\\u201319951.00",
6437 "Portuguese Escud1.00",
6438 "Portuguese Guinea Escud1.00",
6439 "Pr1.00",
6440 "QA1.00",
6441 "Qatari Ria1.00",
6442 "RD1.00",
6443 "RH1.00",
6444 "RINET Fund1.00",
6445 "RS1.00",
6446 "RU1.00",
6447 "RW1.00",
6448 "Rb1.00",
6449 "Rhodesian Dolla1.00",
6450 "Romanian Le1.00",
6451 "Russian Rubl1.00",
6452 "Russian Ruble (1991\\u201319981.00",
6453 "Rwandan Fran1.00",
6454 "S1.00",
6455 "SA1.00",
6456 "SB1.00",
6457 "SC1.00",
6458 "SD1.00",
6459 "SE1.00",
6460 "SG1.00",
6461 "SH1.00",
6462 "SI1.00",
6463 "SK1.00",
6464 "SL R1.00",
6465 "SL1.00",
6466 "SO1.00",
6467 "ST1.00",
6468 "SU1.00",
6469 "SV1.00",
6470 "SY1.00",
6471 "SZ1.00",
6472 "St. Helena Poun1.00",
6473 "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
6474 "Saudi Riya1.00",
6475 "Serbian Dina1.00",
6476 "Seychellois Rupe1.00",
6477 "Sh1.00",
6478 "Sierra Leonean Leon1.00",
6479 "Silve1.00",
6480 "Singapore Dolla1.00",
6481 "Slovak Korun1.00",
6482 "Slovenian Tola1.00",
6483 "Solomon Islands Dolla1.00",
6484 "Somali Shillin1.00",
6485 "South African Ran1.00",
6486 "South African Rand (financial1.00",
6487 "South Korean Wo1.00",
6488 "Soviet Roubl1.00",
6489 "Spanish Peset1.00",
6490 "Spanish Peseta (A account1.00",
6491 "Spanish Peseta (convertible account1.00",
6492 "Special Drawing Right1.00",
6493 "Sri Lankan Rupe1.00",
6494 "Sudanese Poun1.00",
6495 "Surinamese Dolla1.00",
6496 "Surinamese Guilde1.00",
6497 "Swazi Lilangen1.00",
6498 "Swedish Kron1.00",
6499 "Swiss Fran1.00",
6500 "Syrian Poun1.00",
6501 "T S1.00",
6502 "TH1.00",
6503 "TJ1.00",
6504 "TM1.00",
6505 "TN1.00",
6506 "TO1.00",
6507 "TP1.00",
6508 "TR1.00",
6509 "TT1.00",
6510 "TW1.00",
6511 "TZ1.00",
6512 "New Taiwan Dolla1.00",
6513 "Tajikistani Rubl1.00",
6514 "Tajikistani Somon1.00",
6515 "Tanzanian Shillin1.00",
6516 "Testing Currency Cod1.00",
6517 "Thai Bah1.00",
6518 "Timorese Escud1.00",
6519 "Tongan Pa\\u20bbang1.00",
6520 "Trinidad & Tobago Dolla1.00",
6521 "Tunisian Dina1.00",
6522 "Turkish Lir1.00",
6523 "Turkmenistani Mana1.00",
6524 "U S1.00",
6525 "U1.00",
6526 "UA1.00",
6527 "UG1.00",
6528 "US Dolla1.00",
6529 "US Dollar (Next day1.00",
6530 "US Dollar (Same day1.00",
6531 "US1.00",
6532 "UY1.00",
6533 "UZ1.00",
6534 "Ugandan Shillin1.00",
6535 "Ugandan Shilling (1966\\u201319871.00",
6536 "Ukrainian Hryvni1.00",
6537 "Ukrainian Karbovanet1.00",
6538 "Colombian Real Value Uni1.00",
6539 "United Arab Emirates Dirha1.00",
6540 "Unknown Currenc1.00",
6541 "Ur1.00",
6542 "Uruguay Peso (1975\\u201319931.00",
6543 "Uruguay Peso Uruguay1.00",
6544 "Uruguay Peso (Indexed Units1.00",
6545 "Uzbekistani So1.00",
6546 "V1.00",
6547 "VE1.00",
6548 "VN1.00",
6549 "VU1.00",
6550 "Vanuatu Vat1.00",
6551 "Venezuelan Bol\\u00edva1.00",
6552 "Venezuelan Bol\\u00edvar Fuert1.00",
6553 "Vietnamese Don1.00",
6554 "West African CFA Fran1.00",
6555 "Central African CFA Fran1.00",
6556 "WIR Eur1.00",
6557 "WIR Fran1.00",
6558 "WS1.00",
6559 "Samoa Tal1.00",
6560 "XA1.00",
6561 "XB1.00",
6562 "XC1.00",
6563 "XD1.00",
6564 "XE1.00",
6565 "XF1.00",
6566 "XO1.00",
6567 "XP1.00",
6568 "XR1.00",
6569 "XT1.00",
6570 "XX1.00",
6571 "YD1.00",
6572 "YE1.00",
6573 "YU1.00",
6574 "Yemeni Dina1.00",
6575 "Yemeni Ria1.00",
6576 "Yugoslavian Convertible Dina1.00",
6577 "Yugoslavian Hard Dinar (1966\\u201319901.00",
6578 "Yugoslavian New Dina1.00",
6579 "Z1.00",
6580 "ZA1.00",
6581 "ZM1.00",
6582 "ZR1.00",
6583 "ZW1.00",
6584 "Zairean New Zaire (1993\\u201319981.00",
6585 "Zairean Zair1.00",
6586 "Zambian Kwach1.00",
6587 "Zimbabwean Dollar (1980\\u201320081.00",
6588 "dra1.00",
6589 "lar1.00",
6590 "le1.00",
6591 "man1.00",
6592 "so1.00",
6593 };
6594
6595 Locale locale("en_US");
6596 for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
6597 UnicodeString formatted = ctou(DATA[i]);
6598 UErrorCode status = U_ZERO_ERROR;
6599 LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
6600 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
6601 return;
6602 }
6603 // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
6604 numFmt->setLenient(TRUE);
6605 ParsePosition parsePos;
6606 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6607 if (parsePos.getIndex() > 0) {
6608 double doubleVal = currAmt->getNumber().getDouble(status);
6609 if ( doubleVal != 1.0 ) {
6610 errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
6611 }
6612 } else {
6613 errln("Failed to parse as currency: " + formatted);
6614 }
6615 }
6616
6617 for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
6618 UnicodeString formatted = ctou(WRONG_DATA[i]);
6619 UErrorCode status = U_ZERO_ERROR;
6620 NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6621 if (numFmt != NULL && U_SUCCESS(status)) {
6622 ParsePosition parsePos;
6623 LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
6624 if (parsePos.getIndex() > 0) {
6625 double doubleVal = currAmt->getNumber().getDouble(status);
6626 errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
6627 }
6628 } else {
6629 dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
6630 delete numFmt;
6631 break;
6632 }
6633 delete numFmt;
6634 }
6635}
6636
6637const char* attrString(int32_t);
6638
6639// UnicodeString s;
6640// std::string ss;
6641// std::cout << s.toUTF8String(ss)
6642void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
6643 const UnicodeString& str) {
6644 UBool found[10];
6645 FieldPosition fp;
6646
6647 if (tupleCount > 10) {
6648 assertTrue("internal error, tupleCount too large", FALSE);
6649 } else {
6650 for (int i = 0; i < tupleCount; ++i) {
6651 found[i] = FALSE;
6652 }
6653 }
6654
6655 logln(str);
6656 while (iter.next(fp)) {
6657 UBool ok = FALSE;
6658 int32_t id = fp.getField();
6659 int32_t start = fp.getBeginIndex();
6660 int32_t limit = fp.getEndIndex();
6661
6662 // is there a logln using printf?
6663 char buf[128];
6664 sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
6665 logln(buf);
6666
6667 for (int i = 0; i < tupleCount; ++i) {
6668 if (found[i]) {
6669 continue;
6670 }
6671 if (values[i*3] == id &&
6672 values[i*3+1] == start &&
6673 values[i*3+2] == limit) {
6674 found[i] = ok = TRUE;
6675 break;
6676 }
6677 }
6678
6679 assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
6680 }
6681
6682 // check that all were found
6683 UBool ok = TRUE;
6684 for (int i = 0; i < tupleCount; ++i) {
6685 if (!found[i]) {
6686 ok = FALSE;
6687 assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
6688 }
6689 }
6690 assertTrue("no expected values were missing", ok);
6691}
6692
6693void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
6694 const UnicodeString& str) {
6695 logln(str);
6696 assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
6697 assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
6698 assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
6699}
6700
6701void NumberFormatTest::TestFieldPositionIterator() {
6702 // bug 7372
6703 UErrorCode status = U_ZERO_ERROR;
6704 FieldPositionIterator iter1;
6705 FieldPositionIterator iter2;
6706 FieldPosition pos;
6707
6708 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
6709 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6710
6711 double num = 1234.56;
6712 UnicodeString str1;
6713 UnicodeString str2;
6714
6715 assertTrue((UnicodeString)"self==", iter1 == iter1);
6716 assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);
6717
6718 decFmt->format(num, str1, &iter1, status);
6719 assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
6720 decFmt->format(num, str2, &iter2, status);
6721 assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
6722 iter1.next(pos);
6723 assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
6724 iter2.next(pos);
6725 assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);
6726
6727 // should format ok with no iterator
6728 str2.remove();
6729 decFmt->format(num, str2, NULL, status);
6730 assertEquals("null fpiter", str1, str2);
6731
6732 delete decFmt;
6733}
6734
6735void NumberFormatTest::TestFormatAttributes() {
6736 Locale locale("en_US");
6737 UErrorCode status = U_ZERO_ERROR;
6738 DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
6739 if (failure(status, "NumberFormat::createInstance", TRUE)) return;
6740 double val = 12345.67;
6741
6742 {
6743 int32_t expected[] = {
6744 UNUM_CURRENCY_FIELD, 0, 1,
6745 UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
6746 UNUM_INTEGER_FIELD, 1, 7,
6747 UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
6748 UNUM_FRACTION_FIELD, 8, 10,
6749 };
6750 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6751
6752 FieldPositionIterator posIter;
6753 UnicodeString result;
6754 decFmt->format(val, result, &posIter, status);
6755 expectPositions(posIter, expected, tupleCount, result);
6756 }
6757 {
6758 FieldPosition fp(UNUM_INTEGER_FIELD);
6759 UnicodeString result;
6760 decFmt->format(val, result, fp);
6761 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
6762 }
6763 {
6764 FieldPosition fp(UNUM_FRACTION_FIELD);
6765 UnicodeString result;
6766 decFmt->format(val, result, fp);
6767 expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
6768 }
6769 delete decFmt;
6770
6771 decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
6772 val = -0.0000123;
6773 {
6774 int32_t expected[] = {
6775 UNUM_SIGN_FIELD, 0, 1,
6776 UNUM_INTEGER_FIELD, 1, 2,
6777 UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
6778 UNUM_FRACTION_FIELD, 3, 5,
6779 UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
6780 UNUM_EXPONENT_SIGN_FIELD, 6, 7,
6781 UNUM_EXPONENT_FIELD, 7, 8
6782 };
6783 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
6784
6785 FieldPositionIterator posIter;
6786 UnicodeString result;
6787 decFmt->format(val, result, &posIter, status);
6788 expectPositions(posIter, expected, tupleCount, result);
6789 }
6790 {
6791 FieldPosition fp(UNUM_INTEGER_FIELD);
6792 UnicodeString result;
6793 decFmt->format(val, result, fp);
6794 expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
6795 }
6796 {
6797 FieldPosition fp(UNUM_FRACTION_FIELD);
6798 UnicodeString result;
6799 decFmt->format(val, result, fp);
6800 expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
6801 }
6802 delete decFmt;
6803
6804 fflush(stderr);
6805}
6806
6807const char* attrString(int32_t attrId) {
6808 switch (attrId) {
6809 case UNUM_INTEGER_FIELD: return "integer";
6810 case UNUM_FRACTION_FIELD: return "fraction";
6811 case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
6812 case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
6813 case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
6814 case UNUM_EXPONENT_FIELD: return "exponent";
6815 case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
6816 case UNUM_CURRENCY_FIELD: return "currency";
6817 case UNUM_PERCENT_FIELD: return "percent";
6818 case UNUM_PERMILL_FIELD: return "permille";
6819 case UNUM_SIGN_FIELD: return "sign";
6820 default: return "";
6821 }
6822}
6823
6824//
6825// Test formatting & parsing of big decimals.
6826// API test, not a comprehensive test.
6827// See DecimalFormatTest/DataDrivenTests
6828//
6829#define ASSERT_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
6830 assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
6831} UPRV_BLOCK_MACRO_END
6832#define ASSERT_EQUALS(expected, actual) UPRV_BLOCK_MACRO_BEGIN { \
6833 assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
6834} UPRV_BLOCK_MACRO_END
6835
6836void NumberFormatTest::TestDecimal() {
6837 {
6838 UErrorCode status = U_ZERO_ERROR;
6839 Formattable f("12.345678999987654321E666", status);
6840 ASSERT_SUCCESS(status);
6841 StringPiece s = f.getDecimalNumber(status);
6842 ASSERT_SUCCESS(status);
6843 ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
6844 //printf("%s\n", s.data());
6845 }
6846
6847 {
6848 UErrorCode status = U_ZERO_ERROR;
6849 Formattable f1("this is not a number", status);
6850 ASSERT_EQUALS(U_DECIMAL_NUMBER_SYNTAX_ERROR, status);
6851 }
6852
6853 {
6854 UErrorCode status = U_ZERO_ERROR;
6855 Formattable f;
6856 f.setDecimalNumber("123.45", status);
6857 ASSERT_SUCCESS(status);
6858 ASSERT_EQUALS( Formattable::kDouble, f.getType());
6859 ASSERT_EQUALS(123.45, f.getDouble());
6860 ASSERT_EQUALS(123.45, f.getDouble(status));
6861 ASSERT_SUCCESS(status);
6862 ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
6863 ASSERT_SUCCESS(status);
6864
6865 f.setDecimalNumber("4.5678E7", status);
6866 int32_t n;
6867 n = f.getLong();
6868 ASSERT_EQUALS(45678000, n);
6869
6870 status = U_ZERO_ERROR;
6871 f.setDecimalNumber("-123", status);
6872 ASSERT_SUCCESS(status);
6873 ASSERT_EQUALS( Formattable::kLong, f.getType());
6874 ASSERT_EQUALS(-123, f.getLong());
6875 ASSERT_EQUALS(-123, f.getLong(status));
6876 ASSERT_SUCCESS(status);
6877 ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
6878 ASSERT_SUCCESS(status);
6879
6880 status = U_ZERO_ERROR;
6881 f.setDecimalNumber("1234567890123", status); // Number too big for 32 bits
6882 ASSERT_SUCCESS(status);
6883 ASSERT_EQUALS( Formattable::kInt64, f.getType());
6884 ASSERT_EQUALS(1234567890123LL, f.getInt64());
6885 ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
6886 ASSERT_SUCCESS(status);
6887 ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
6888 ASSERT_SUCCESS(status);
6889 }
6890
6891 {
6892 UErrorCode status = U_ZERO_ERROR;
6893 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6894 if (U_FAILURE(status) || fmtr == NULL) {
6895 dataerrln("Unable to create NumberFormat");
6896 } else {
6897 UnicodeString formattedResult;
6898 StringPiece num("244444444444444444444444444444444444446.4");
6899 fmtr->format(num, formattedResult, NULL, status);
6900 ASSERT_SUCCESS(status);
6901 ASSERT_EQUALS("244,444,444,444,444,444,444,444,444,444,444,444,446.4", formattedResult);
6902 //std::string ss; std::cout << formattedResult.toUTF8String(ss);
6903 delete fmtr;
6904 }
6905 }
6906
6907 {
6908 // Check formatting a DigitList. DigitList is internal, but this is
6909 // a critical interface that must work.
6910 UErrorCode status = U_ZERO_ERROR;
6911 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6912 if (U_FAILURE(status) || fmtr == NULL) {
6913 dataerrln("Unable to create NumberFormat");
6914 } else {
6915 UnicodeString formattedResult;
6916 DecimalQuantity dl;
6917 StringPiece num("123.4566666666666666666666666666666666621E+40");
6918 dl.setToDecNumber(num, status);
6919 ASSERT_SUCCESS(status);
6920 fmtr->format(dl, formattedResult, NULL, status);
6921 ASSERT_SUCCESS(status);
6922 ASSERT_EQUALS("1,234,566,666,666,666,666,666,666,666,666,666,666,621,000", formattedResult);
6923
6924 status = U_ZERO_ERROR;
6925 num.set("666.666");
6926 dl.setToDecNumber(num, status);
6927 FieldPosition pos(NumberFormat::FRACTION_FIELD);
6928 ASSERT_SUCCESS(status);
6929 formattedResult.remove();
6930 fmtr->format(dl, formattedResult, pos, status);
6931 ASSERT_SUCCESS(status);
6932 ASSERT_EQUALS("666.666", formattedResult);
6933 ASSERT_EQUALS(4, pos.getBeginIndex());
6934 ASSERT_EQUALS(7, pos.getEndIndex());
6935 delete fmtr;
6936 }
6937 }
6938
6939 {
6940 // Check a parse with a formatter with a multiplier.
6941 UErrorCode status = U_ZERO_ERROR;
6942 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_PERCENT, status);
6943 if (U_FAILURE(status) || fmtr == NULL) {
6944 dataerrln("Unable to create NumberFormat");
6945 } else {
6946 UnicodeString input = "1.84%";
6947 Formattable result;
6948 fmtr->parse(input, result, status);
6949 ASSERT_SUCCESS(status);
6950 ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
6951 //std::cout << result.getDecimalNumber(status).data();
6952 delete fmtr;
6953 }
6954 }
6955
6956#if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
6957 /*
6958 * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
6959 * See #9463
6960 */
6961 {
6962 // Check that a parse returns a decimal number with full accuracy
6963 UErrorCode status = U_ZERO_ERROR;
6964 NumberFormat *fmtr = NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, status);
6965 if (U_FAILURE(status) || fmtr == NULL) {
6966 dataerrln("Unable to create NumberFormat");
6967 } else {
6968 UnicodeString input = "1.002200044400088880000070000";
6969 Formattable result;
6970 fmtr->parse(input, result, status);
6971 ASSERT_SUCCESS(status);
6972 ASSERT_EQUALS(0, strcmp("1.00220004440008888000007", result.getDecimalNumber(status).data()));
6973 ASSERT_EQUALS(1.00220004440008888, result.getDouble());
6974 //std::cout << result.getDecimalNumber(status).data();
6975 delete fmtr;
6976 }
6977 }
6978#endif
6979
6980}
6981
6982void NumberFormatTest::TestCurrencyFractionDigits() {
6983 UErrorCode status = U_ZERO_ERROR;
6984 UnicodeString text1, text2;
6985 double value = 99.12345;
6986
6987 // Create currenct instance
6988 NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
6989 if (U_FAILURE(status) || fmt == NULL) {
6990 dataerrln("Unable to create NumberFormat");
6991 } else {
6992 fmt->format(value, text1);
6993
6994 // Reset the same currency and format the test value again
6995 fmt->setCurrency(fmt->getCurrency(), status);
6996 ASSERT_SUCCESS(status);
6997 fmt->format(value, text2);
6998
6999 if (text1 != text2) {
7000 errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
7001 + text1 + " text2=" + text2);
7002 }
7003 }
7004 delete fmt;
7005}
7006
7007void NumberFormatTest::TestExponentParse() {
7008
7009 UErrorCode status = U_ZERO_ERROR;
7010 Formattable result;
7011 ParsePosition parsePos(0);
7012
7013 // set the exponent symbol
7014 status = U_ZERO_ERROR;
7015 DecimalFormatSymbols symbols(Locale::getDefault(), status);
7016 if(U_FAILURE(status)) {
7017 dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
7018 return;
7019 }
7020
7021 // create format instance
7022 status = U_ZERO_ERROR;
7023 DecimalFormat fmt(u"#####", symbols, status);
7024 if(U_FAILURE(status)) {
7025 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
7026 }
7027
7028 // parse the text
7029 fmt.parse("5.06e-27", result, parsePos);
7030 if(result.getType() != Formattable::kDouble &&
7031 result.getDouble() != 5.06E-27 &&
7032 parsePos.getIndex() != 8
7033 )
7034 {
7035 errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
7036 result.getDouble(), parsePos.getIndex());
7037 }
7038}
7039
7040void NumberFormatTest::TestExplicitParents() {
7041
7042 /* Test that number formats are properly inherited from es_419 */
7043 /* These could be subject to change if the CLDR data changes */
7044 static const char* parentLocaleTests[][2]= {
7045 /* locale ID */ /* expected */
7046 {"es_CO", "1.250,75" },
7047 {"es_ES", "1.250,75" },
7048 {"es_GQ", "1.250,75" },
7049 {"es_MX", "1,250.75" },
7050 {"es_US", "1,250.75" },
7051 {"es_VE", "1.250,75" },
7052 };
7053
7054 UnicodeString s;
7055
7056 for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
7057 UErrorCode status = U_ZERO_ERROR;
7058 const char *localeID = parentLocaleTests[i][0];
7059 UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
7060 expected = expected.unescape();
7061 char loc[256]={0};
7062 uloc_canonicalize(localeID, loc, 256, &status);
7063 NumberFormat *fmt= NumberFormat::createInstance(Locale(loc), status);
7064 if(U_FAILURE(status)){
7065 dataerrln("Could not create number formatter for locale %s - %s",localeID, u_errorName(status));
7066 continue;
7067 }
7068 s.remove();
7069 fmt->format(1250.75, s);
7070 if(s!=expected){
7071 errln(UnicodeString("FAIL: Expected: ")+expected
7072 + UnicodeString(" Got: ") + s
7073 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
7074 }
7075 if (U_FAILURE(status)){
7076 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
7077 }
7078 delete fmt;
7079 }
7080
7081}
7082
7083/**
7084 * Test available numbering systems API.
7085 */
7086void NumberFormatTest::TestAvailableNumberingSystems() {
7087 IcuTestErrorCode status(*this, "TestAvailableNumberingSystems");
7088 StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
7089 CHECK_DATA(status, "NumberingSystem::getAvailableNames()");
7090
7091 int32_t nsCount = availableNumberingSystems->count(status);
7092 if ( nsCount < 74 ) {
7093 errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
7094 }
7095
7096 /* A relatively simple test of the API. We call getAvailableNames() and cycle through */
7097 /* each name returned, attempting to create a numbering system based on that name and */
7098 /* verifying that the name returned from the resulting numbering system is the same */
7099 /* one that we initially thought. */
7100
7101 int32_t len;
7102 const char* prevName = nullptr;
7103 for ( int32_t i = 0 ; i < nsCount ; i++ ) {
7104 const char *nsname = availableNumberingSystems->next(&len,status);
7105 NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
7106 logln("OK for ns = %s",nsname);
7107 if ( uprv_strcmp(nsname,ns->getName()) ) {
7108 errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
7109 }
7110 if (prevName != nullptr) {
7111 int comp = uprv_strcmp(prevName, nsname);
7112 assertTrue(
7113 UnicodeString(u"NS names should be in alphabetical order: ")
7114 + prevName + u" vs " + nsname,
7115 // TODO: Why are there duplicates? This doesn't work if comp < 0
7116 comp <= 0);
7117 }
7118 prevName = nsname;
7119
7120 delete ns;
7121 }
7122
7123 LocalPointer<NumberingSystem> dummy(NumberingSystem::createInstanceByName("dummy", status), status);
7124 status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
7125 assertTrue("Non-existent numbering system should return null", dummy.isNull());
7126
7127 delete availableNumberingSystems;
7128}
7129
7130void
7131NumberFormatTest::Test9087(void)
7132{
7133 U_STRING_DECL(pattern,"#",1);
7134 U_STRING_INIT(pattern,"#",1);
7135
7136 U_STRING_DECL(infstr,"INF",3);
7137 U_STRING_INIT(infstr,"INF",3);
7138
7139 U_STRING_DECL(nanstr,"NAN",3);
7140 U_STRING_INIT(nanstr,"NAN",3);
7141
7142 UChar outputbuf[50] = {0};
7143 UErrorCode status = U_ZERO_ERROR;
7144 UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
7145 if ( U_FAILURE(status) ) {
7146 dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
7147 return;
7148 }
7149
7150 unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
7151 unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
7152 if ( U_FAILURE(status) ) {
7153 errln("FAIL: error setting symbols");
7154 }
7155
7156 double inf = uprv_getInfinity();
7157
7158 unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
7159 unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);
7160
7161 UFieldPosition position = { 0, 0, 0};
7162 unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
7163
7164 if ( u_strcmp(infstr, outputbuf)) {
7165 errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
7166 }
7167
7168 unum_close(fmt);
7169}
7170
7171void NumberFormatTest::TestFormatFastpaths() {
7172 // get some additional case
7173 {
7174 UErrorCode status=U_ZERO_ERROR;
7175 DecimalFormat df(UnicodeString(u"0000"),status);
7176 if (U_FAILURE(status)) {
7177 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7178 } else {
7179 int64_t long_number = 1;
7180 UnicodeString expect = "0001";
7181 UnicodeString result;
7182 FieldPosition pos;
7183 df.format(long_number, result, pos);
7184 if(U_FAILURE(status)||expect!=result) {
7185 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
7186 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7187 } else {
7188 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
7189 }
7190 }
7191 }
7192 {
7193 UErrorCode status=U_ZERO_ERROR;
7194 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7195 if (U_FAILURE(status)) {
7196 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7197 } else {
7198 int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
7199 // uint8_t bits[8];
7200 // memcpy(bits,&long_number,8);
7201 // for(int i=0;i<8;i++) {
7202 // logln("bits: %02X", (unsigned int)bits[i]);
7203 // }
7204 UnicodeString expect = "-9223372036854775808";
7205 UnicodeString result;
7206 FieldPosition pos;
7207 df.format(long_number, result, pos);
7208 if(U_FAILURE(status)||expect!=result) {
7209 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
7210 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7211 } else {
7212 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
7213 }
7214 }
7215 }
7216 {
7217 UErrorCode status=U_ZERO_ERROR;
7218 DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
7219 if (U_FAILURE(status)) {
7220 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7221 } else {
7222 int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
7223 // uint8_t bits[8];
7224 // memcpy(bits,&long_number,8);
7225 // for(int i=0;i<8;i++) {
7226 // logln("bits: %02X", (unsigned int)bits[i]);
7227 // }
7228 UnicodeString expect = "9223372036854775807";
7229 UnicodeString result;
7230 FieldPosition pos;
7231 df.format(long_number, result, pos);
7232 if(U_FAILURE(status)||expect!=result) {
7233 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
7234 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7235 } else {
7236 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
7237 }
7238 }
7239 }
7240 {
7241 UErrorCode status=U_ZERO_ERROR;
7242 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7243 if (U_FAILURE(status)) {
7244 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7245 } else {
7246 int64_t long_number = 0;
7247 // uint8_t bits[8];
7248 // memcpy(bits,&long_number,8);
7249 // for(int i=0;i<8;i++) {
7250 // logln("bits: %02X", (unsigned int)bits[i]);
7251 // }
7252 UnicodeString expect = "0000000000000000000";
7253 UnicodeString result;
7254 FieldPosition pos;
7255 df.format(long_number, result, pos);
7256 if(U_FAILURE(status)||expect!=result) {
7257 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
7258 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7259 } else {
7260 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
7261 }
7262 }
7263 }
7264 {
7265 UErrorCode status=U_ZERO_ERROR;
7266 DecimalFormat df(UnicodeString("0000000000000000000",""),status);
7267 if (U_FAILURE(status)) {
7268 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
7269 } else {
7270 int64_t long_number = U_INT64_MIN + 1;
7271 UnicodeString expect = "-9223372036854775807";
7272 UnicodeString result;
7273 FieldPosition pos;
7274 df.format(long_number, result, pos);
7275 if(U_FAILURE(status)||expect!=result) {
7276 dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
7277 __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
7278 } else {
7279 logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
7280 }
7281 }
7282 }
7283}
7284
7285
7286void NumberFormatTest::TestFormattableSize(void) {
7287 if(sizeof(Formattable) > 112) {
7288 errln("Error: sizeof(Formattable)=%d, 112=%d\n",
7289 sizeof(Formattable), 112);
7290 } else if(sizeof(Formattable) < 112) {
7291 logln("Warning: sizeof(Formattable)=%d, 112=%d\n",
7292 sizeof(Formattable), 112);
7293 } else {
7294 logln("sizeof(Formattable)=%d, 112=%d\n",
7295 sizeof(Formattable), 112);
7296 }
7297}
7298
7299UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
7300 UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
7301
7302 UFormattable *u = f.toUFormattable();
7303 logln();
7304 if (u == NULL) {
7305 errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
7306 return FALSE;
7307 }
7308 logln("%s:%d: comparing Formattable with UFormattable", file, line);
7309 logln(fileLine + toString(f));
7310
7311 UErrorCode status = U_ZERO_ERROR;
7312 UErrorCode valueStatus = U_ZERO_ERROR;
7313 UFormattableType expectUType = UFMT_COUNT; // invalid
7314
7315 UBool triedExact = FALSE; // did we attempt an exact comparison?
7316 UBool exactMatch = FALSE; // was the exact comparison true?
7317
7318 switch( f.getType() ) {
7319 case Formattable::kDate:
7320 expectUType = UFMT_DATE;
7321 exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
7322 triedExact = TRUE;
7323 break;
7324 case Formattable::kDouble:
7325 expectUType = UFMT_DOUBLE;
7326 exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
7327 triedExact = TRUE;
7328 break;
7329 case Formattable::kLong:
7330 expectUType = UFMT_LONG;
7331 exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
7332 triedExact = TRUE;
7333 break;
7334 case Formattable::kString:
7335 expectUType = UFMT_STRING;
7336 {
7337 UnicodeString str;
7338 f.getString(str);
7339 int32_t len;
7340 const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
7341 if(U_SUCCESS(valueStatus)) {
7342 UnicodeString str2(uch, len);
7343 assertTrue("UChar* NULL-terminated", uch[len]==0);
7344 exactMatch = (str == str2);
7345 }
7346 triedExact = TRUE;
7347 }
7348 break;
7349 case Formattable::kArray:
7350 expectUType = UFMT_ARRAY;
7351 triedExact = TRUE;
7352 {
7353 int32_t count = ufmt_getArrayLength(u, &valueStatus);
7354 int32_t count2;
7355 const Formattable *array2 = f.getArray(count2);
7356 exactMatch = assertEquals(fileLine + " array count", count, count2);
7357
7358 if(exactMatch) {
7359 for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
7360 UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
7361 if(*Formattable::fromUFormattable(uu) != (array2[i])) {
7362 errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
7363 (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
7364 exactMatch = FALSE;
7365 } else {
7366 if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
7367 exactMatch = FALSE;
7368 }
7369 }
7370 }
7371 }
7372 }
7373 break;
7374 case Formattable::kInt64:
7375 expectUType = UFMT_INT64;
7376 exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
7377 triedExact = TRUE;
7378 break;
7379 case Formattable::kObject:
7380 expectUType = UFMT_OBJECT;
7381 exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
7382 triedExact = TRUE;
7383 break;
7384 }
7385 UFormattableType uType = ufmt_getType(u, &status);
7386
7387 if(U_FAILURE(status)) {
7388 errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
7389 return FALSE;
7390 }
7391
7392 if(uType != expectUType) {
7393 errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
7394 }
7395
7396 if(triedExact) {
7397 if(U_FAILURE(valueStatus)) {
7398 errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
7399 } else if(!exactMatch) {
7400 errln("%s:%d: failed exact match for the Formattable type", file, line);
7401 } else {
7402 logln("%s:%d: exact match OK", file, line);
7403 }
7404 } else {
7405 logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
7406 }
7407
7408 if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
7409 && f.isNumeric()) {
7410 UErrorCode convStatus = U_ZERO_ERROR;
7411
7412 if(uType != UFMT_INT64) { // may fail to compare
7413 assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
7414 }
7415
7416 if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
7417 StringPiece fDecNum = f.getDecimalNumber(convStatus);
7418#if 1
7419 int32_t len;
7420 const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
7421#else
7422 // copy version
7423 char decNumChars[200];
7424 int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
7425#endif
7426
7427 if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
7428 logln(fileLine + decNumChars);
7429 assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
7430 assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
7431 }
7432
7433 UErrorCode int64ConversionF = U_ZERO_ERROR;
7434 int64_t l = f.getInt64(int64ConversionF);
7435 UErrorCode int64ConversionU = U_ZERO_ERROR;
7436 int64_t r = ufmt_getInt64(u, &int64ConversionU);
7437
7438 if( (l==r)
7439 && ( uType != UFMT_INT64 ) // int64 better not overflow
7440 && (U_INVALID_FORMAT_ERROR==int64ConversionU)
7441 && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
7442 logln("%s:%d: OK: 64 bit overflow", file, line);
7443 } else {
7444 assertEquals(fileLine + " as int64 ==", l, r);
7445 assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
7446 assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
7447 }
7448 }
7449 }
7450 return exactMatch || !triedExact;
7451}
7452
7453void NumberFormatTest::TestUFormattable(void) {
7454 {
7455 // test that a default formattable is equal to Formattable()
7456 UErrorCode status = U_ZERO_ERROR;
7457 LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
7458 assertSuccess("calling umt_open", status);
7459 Formattable defaultFormattable;
7460 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7461 (defaultFormattable
7462 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7463 assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
7464 (defaultFormattable
7465 == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
7466 assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
7467 (defaultFormattable
7468 == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
7469 assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
7470 ((&defaultFormattable)
7471 == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
7472 assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
7473 ((&defaultFormattable)
7474 == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
7475 testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
7476 }
7477 // test some random Formattables
7478 {
7479 Formattable f(ucal_getNow(), Formattable::kIsDate);
7480 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7481 }
7482 {
7483 Formattable f((double)1.61803398874989484820); // golden ratio
7484 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7485 }
7486 {
7487 Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
7488 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7489 }
7490 {
7491 Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
7492 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7493 }
7494 {
7495 Formattable f("Hello world."); // should be invariant?
7496 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7497 }
7498 {
7499 UErrorCode status2 = U_ZERO_ERROR;
7500 Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
7501 assertSuccess("Constructing a StringPiece", status2);
7502 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7503 }
7504 {
7505 UErrorCode status2 = U_ZERO_ERROR;
7506 UObject *obj = new Locale();
7507 Formattable f(obj);
7508 assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
7509 testFormattableAsUFormattable(__FILE__, __LINE__, f);
7510 }
7511 {
7512 const Formattable array[] = {
7513 Formattable(ucal_getNow(), Formattable::kIsDate),
7514 Formattable((int32_t)4),
7515 Formattable((double)1.234),
7516 };
7517
7518 Formattable fa(array, 3);
7519 testFormattableAsUFormattable(__FILE__, __LINE__, fa);
7520 }
7521}
7522
7523void NumberFormatTest::TestSignificantDigits(void) {
7524 double input[] = {
7525 0, 0,
7526 0.1, -0.1,
7527 123, -123,
7528 12345, -12345,
7529 123.45, -123.45,
7530 123.44501, -123.44501,
7531 0.001234, -0.001234,
7532 0.00000000123, -0.00000000123,
7533 0.0000000000000000000123, -0.0000000000000000000123,
7534 1.2, -1.2,
7535 0.0000000012344501, -0.0000000012344501,
7536 123445.01, -123445.01,
7537 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
7538 };
7539 const char* expected[] = {
7540 "0.00", "0.00",
7541 "0.100", "-0.100",
7542 "123", "-123",
7543 "12345", "-12345",
7544 "123.45", "-123.45",
7545 "123.45", "-123.45",
7546 "0.001234", "-0.001234",
7547 "0.00000000123", "-0.00000000123",
7548 "0.0000000000000000000123", "-0.0000000000000000000123",
7549 "1.20", "-1.20",
7550 "0.0000000012345", "-0.0000000012345",
7551 "123450", "-123450",
7552 "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
7553 };
7554
7555 UErrorCode status = U_ZERO_ERROR;
7556 Locale locale("en_US");
7557 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7558 NumberFormat::createInstance(locale, status)));
7559 CHECK_DATA(status,"NumberFormat::createInstance");
7560
7561 numberFormat->setSignificantDigitsUsed(TRUE);
7562 numberFormat->setMinimumSignificantDigits(3);
7563 numberFormat->setMaximumSignificantDigits(5);
7564 numberFormat->setGroupingUsed(false);
7565
7566 UnicodeString result;
7567 UnicodeString expectedResult;
7568 for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
7569 numberFormat->format(input[i], result);
7570 UnicodeString expectedResult(expected[i]);
7571 if (result != expectedResult) {
7572 errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
7573 }
7574 result.remove();
7575 }
7576
7577 // Test for ICU-20063
7578 {
7579 DecimalFormat df({"en-us", status}, status);
7580 df.setSignificantDigitsUsed(TRUE);
7581 expect(df, 9.87654321, u"9.87654");
7582 df.setMaximumSignificantDigits(3);
7583 expect(df, 9.87654321, u"9.88");
7584 // setSignificantDigitsUsed with maxSig only
7585 df.setSignificantDigitsUsed(TRUE);
7586 expect(df, 9.87654321, u"9.88");
7587 df.setMinimumSignificantDigits(2);
7588 expect(df, 9, u"9.0");
7589 // setSignificantDigitsUsed with both minSig and maxSig
7590 df.setSignificantDigitsUsed(TRUE);
7591 expect(df, 9, u"9.0");
7592 // setSignificantDigitsUsed to false: should revert to fraction rounding
7593 df.setSignificantDigitsUsed(FALSE);
7594 expect(df, 9.87654321, u"9.876543");
7595 expect(df, 9, u"9");
7596 df.setSignificantDigitsUsed(TRUE);
7597 df.setMinimumSignificantDigits(2);
7598 expect(df, 9.87654321, u"9.87654");
7599 expect(df, 9, u"9.0");
7600 // setSignificantDigitsUsed with minSig only
7601 df.setSignificantDigitsUsed(TRUE);
7602 expect(df, 9.87654321, u"9.87654");
7603 expect(df, 9, u"9.0");
7604 }
7605}
7606
7607void NumberFormatTest::TestShowZero() {
7608 UErrorCode status = U_ZERO_ERROR;
7609 Locale locale("en_US");
7610 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7611 NumberFormat::createInstance(locale, status)));
7612 CHECK_DATA(status, "NumberFormat::createInstance");
7613
7614 numberFormat->setSignificantDigitsUsed(TRUE);
7615 numberFormat->setMaximumSignificantDigits(3);
7616
7617 UnicodeString result;
7618 numberFormat->format(0.0, result);
7619 if (result != "0") {
7620 errln((UnicodeString)"Expected: 0, got " + result);
7621 }
7622}
7623
7624void NumberFormatTest::TestBug9936() {
7625 UErrorCode status = U_ZERO_ERROR;
7626 Locale locale("en_US");
7627 LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
7628 NumberFormat::createInstance(locale, status)));
7629 if (U_FAILURE(status)) {
7630 dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
7631 return;
7632 }
7633
7634 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7635 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7636 }
7637 numberFormat->setSignificantDigitsUsed(TRUE);
7638 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7639 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7640 }
7641
7642 numberFormat->setSignificantDigitsUsed(FALSE);
7643 if (numberFormat->areSignificantDigitsUsed() == TRUE) {
7644 errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
7645 }
7646
7647 numberFormat->setMinimumSignificantDigits(3);
7648 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7649 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7650 }
7651
7652 numberFormat->setSignificantDigitsUsed(FALSE);
7653 numberFormat->setMaximumSignificantDigits(6);
7654 if (numberFormat->areSignificantDigitsUsed() == FALSE) {
7655 errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
7656 }
7657
7658}
7659
7660void NumberFormatTest::TestParseNegativeWithFaLocale() {
7661 UErrorCode status = U_ZERO_ERROR;
7662 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
7663 CHECK_DATA(status, "NumberFormat::createInstance");
7664 test->setLenient(TRUE);
7665 Formattable af;
7666 ParsePosition ppos;
7667 UnicodeString value("\\u200e-0,5");
7668 value = value.unescape();
7669 test->parse(value, af, ppos);
7670 if (ppos.getIndex() == 0) {
7671 errln("Expected -0,5 to parse for Farsi.");
7672 }
7673 delete test;
7674}
7675
7676void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
7677 UErrorCode status = U_ZERO_ERROR;
7678 DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
7679 CHECK_DATA(status, "NumberFormat::createInstance");
7680 test->setLenient(TRUE);
7681 Formattable af;
7682 ParsePosition ppos;
7683 UnicodeString value("\\u208B0.5");
7684 value = value.unescape();
7685 test->parse(value, af, ppos);
7686 if (ppos.getIndex() == 0) {
7687 errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
7688 }
7689 delete test;
7690}
7691
7692void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
7693 UErrorCode status = U_ZERO_ERROR;
7694 DecimalFormatSymbols custom(Locale::getUS(), status);
7695 CHECK(status, "DecimalFormatSymbols constructor");
7696
7697 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
7698 custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
7699 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
7700
7701 UnicodeString pat(" #,##0.00");
7702 pat.insert(0, (UChar)0x00A4);
7703
7704 DecimalFormat fmt(pat, custom, status);
7705 CHECK(status, "DecimalFormat constructor");
7706
7707 UnicodeString numstr("* 1^234:56");
7708 expect2(fmt, (Formattable)((double)1234.56), numstr);
7709}
7710
7711typedef struct {
7712 const char * locale;
7713 UBool lenient;
7714 UnicodeString numString;
7715 double value;
7716} SignsAndMarksItem;
7717
7718
7719void NumberFormatTest::TestParseSignsAndMarks() {
7720 const SignsAndMarksItem items[] = {
7721 // locale lenient numString value
7722 { "en", FALSE, CharsToUnicodeString("12"), 12 },
7723 { "en", TRUE, CharsToUnicodeString("12"), 12 },
7724 { "en", FALSE, CharsToUnicodeString("-23"), -23 },
7725 { "en", TRUE, CharsToUnicodeString("-23"), -23 },
7726 { "en", TRUE, CharsToUnicodeString("- 23"), -23 },
7727 { "en", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7728 { "en", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7729 { "en", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7730
7731 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7732 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7733 { "en@numbers=arab", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7734 { "en@numbers=arab", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7735 { "en@numbers=arab", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7736 { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7737 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7738 { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7739
7740 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7741 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7742 { "en@numbers=arabext", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7743 { "en@numbers=arabext", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7744 { "en@numbers=arabext", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7745 { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7746 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7747 { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7748
7749 { "he", FALSE, CharsToUnicodeString("12"), 12 },
7750 { "he", TRUE, CharsToUnicodeString("12"), 12 },
7751 { "he", FALSE, CharsToUnicodeString("-23"), -23 },
7752 { "he", TRUE, CharsToUnicodeString("-23"), -23 },
7753 { "he", TRUE, CharsToUnicodeString("- 23"), -23 },
7754 { "he", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7755 { "he", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7756 { "he", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7757
7758 { "ar", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7759 { "ar", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
7760 { "ar", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7761 { "ar", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
7762 { "ar", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
7763 { "ar", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7764 { "ar", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
7765 { "ar", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
7766
7767 { "ar_MA", FALSE, CharsToUnicodeString("12"), 12 },
7768 { "ar_MA", TRUE, CharsToUnicodeString("12"), 12 },
7769 { "ar_MA", FALSE, CharsToUnicodeString("-23"), -23 },
7770 { "ar_MA", TRUE, CharsToUnicodeString("-23"), -23 },
7771 { "ar_MA", TRUE, CharsToUnicodeString("- 23"), -23 },
7772 { "ar_MA", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
7773 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
7774 { "ar_MA", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
7775
7776 { "fa", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7777 { "fa", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7778 { "fa", FALSE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7779 { "fa", TRUE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
7780 { "fa", TRUE, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
7781 { "fa", FALSE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7782 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
7783 { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
7784
7785 { "ps", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7786 { "ps", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
7787 { "ps", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7788 { "ps", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
7789 { "ps", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
7790 { "ps", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7791 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
7792 { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
7793 { "ps", FALSE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7794 { "ps", TRUE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
7795 { "ps", TRUE, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
7796 // terminator
7797 { NULL, 0, UnicodeString(""), 0 },
7798 };
7799
7800 const SignsAndMarksItem * itemPtr;
7801 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
7802 UErrorCode status = U_ZERO_ERROR;
7803 NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
7804 if (U_SUCCESS(status)) {
7805 numfmt->setLenient(itemPtr->lenient);
7806 Formattable fmtobj;
7807 ParsePosition ppos;
7808 numfmt->parse(itemPtr->numString, fmtobj, ppos);
7809 if (ppos.getIndex() == itemPtr->numString.length()) {
7810 double parsedValue = fmtobj.getDouble(status);
7811 if (U_FAILURE(status) || parsedValue != itemPtr->value) {
7812 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
7813 }
7814 } else {
7815 errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
7816 }
7817 } else {
7818 dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
7819 }
7820 delete numfmt;
7821 }
7822}
7823
7824typedef struct {
7825 DecimalFormat::ERoundingMode mode;
7826 double value;
7827 UnicodeString expected;
7828} Test10419Data;
7829
7830
7831// Tests that rounding works right when fractional digits is set to 0.
7832void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
7833 const Test10419Data items[] = {
7834 { DecimalFormat::kRoundCeiling, 1.488, "2"},
7835 { DecimalFormat::kRoundDown, 1.588, "1"},
7836 { DecimalFormat::kRoundFloor, 1.888, "1"},
7837 { DecimalFormat::kRoundHalfDown, 1.5, "1"},
7838 { DecimalFormat::kRoundHalfEven, 2.5, "2"},
7839 { DecimalFormat::kRoundHalfUp, 2.5, "3"},
7840 { DecimalFormat::kRoundUp, 1.5, "2"},
7841 };
7842 UErrorCode status = U_ZERO_ERROR;
7843 LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
7844 if (U_FAILURE(status)) {
7845 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
7846 return;
7847 }
7848 for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
7849 decfmt->setRoundingMode(items[i].mode);
7850 decfmt->setMaximumFractionDigits(0);
7851 UnicodeString actual;
7852 if (items[i].expected != decfmt->format(items[i].value, actual)) {
7853 errln("Expected " + items[i].expected + ", got " + actual);
7854 }
7855 }
7856}
7857
7858void NumberFormatTest::Test10468ApplyPattern() {
7859 // Padding char of fmt is now 'a'
7860 UErrorCode status = U_ZERO_ERROR;
7861 DecimalFormat fmt("'I''ll'*a###.##", status);
7862
7863 if (U_FAILURE(status)) {
7864 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7865 return;
7866 }
7867
7868 assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
7869
7870 // Padding char of fmt ought to be '*' since that is the default and no
7871 // explicit padding char is specified in the new pattern.
7872 fmt.applyPattern("AA#,##0.00ZZ", status);
7873
7874 // Oops this still prints 'a' even though we changed the pattern.
7875 assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
7876}
7877
7878void NumberFormatTest::TestRoundingScientific10542() {
7879 UErrorCode status = U_ZERO_ERROR;
7880 DecimalFormat format("0.00E0", status);
7881 if (U_FAILURE(status)) {
7882 errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
7883 return;
7884 }
7885
7886 DecimalFormat::ERoundingMode roundingModes[] = {
7887 DecimalFormat::kRoundCeiling,
7888 DecimalFormat::kRoundDown,
7889 DecimalFormat::kRoundFloor,
7890 DecimalFormat::kRoundHalfDown,
7891 DecimalFormat::kRoundHalfEven,
7892 DecimalFormat::kRoundHalfUp,
7893 DecimalFormat::kRoundUp};
7894 const char *descriptions[] = {
7895 "Round Ceiling",
7896 "Round Down",
7897 "Round Floor",
7898 "Round half down",
7899 "Round half even",
7900 "Round half up",
7901 "Round up"};
7902
7903 {
7904 double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
7905 // The order of these expected values correspond to the order of roundingModes and the order of values.
7906 const char *expected[] = {
7907 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
7908 "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7909 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
7910 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
7911 "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7912 "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
7913 "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
7914 verifyRounding(
7915 format,
7916 values,
7917 expected,
7918 roundingModes,
7919 descriptions,
7920 UPRV_LENGTHOF(values),
7921 UPRV_LENGTHOF(roundingModes));
7922 }
7923 {
7924 double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
7925 // The order of these expected values correspond to the order of roundingModes and the order of values.
7926 const char *expected[] = {
7927 "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
7928 "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
7929 "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
7930 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
7931 "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7932 "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
7933 "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
7934 verifyRounding(
7935 format,
7936 values,
7937 expected,
7938 roundingModes,
7939 descriptions,
7940 UPRV_LENGTHOF(values),
7941 UPRV_LENGTHOF(roundingModes));
7942 }
7943/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
7944 {
7945 double values[] = {0.0, -0.0};
7946 // The order of these expected values correspond to the order of roundingModes and the order of values.
7947 const char *expected[] = {
7948 "0.00E0", "-0.00E0",
7949 "0.00E0", "-0.00E0",
7950 "0.00E0", "-0.00E0",
7951 "0.00E0", "-0.00E0",
7952 "0.00E0", "-0.00E0",
7953 "0.00E0", "-0.00E0",
7954 "0.00E0", "-0.00E0"};
7955 verifyRounding(
7956 format,
7957 values,
7958 expected,
7959 roundingModes,
7960 descriptions,
7961 UPRV_LENGTHOF(values),
7962 UPRV_LENGTHOF(roundingModes));
7963 }
7964*/
7965 {
7966
7967 double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
7968 // The order of these expected values correspond to the order of roundingModes and the order of values.
7969 const char *expected[] = {
7970 "1.00E25", "1.01E25", "1.00E25",
7971 "1.00E25", "1.00E25", "9.99E24",
7972 "1.00E25", "1.00E25", "9.99E24",
7973 "1.00E25", "1.00E25", "1.00E25",
7974 "1.00E25", "1.00E25", "1.00E25",
7975 "1.00E25", "1.00E25", "1.00E25",
7976 "1.00E25", "1.01E25", "1.00E25"};
7977 verifyRounding(
7978 format,
7979 values,
7980 expected,
7981 roundingModes,
7982 descriptions,
7983 UPRV_LENGTHOF(values),
7984 UPRV_LENGTHOF(roundingModes));
7985 }
7986 {
7987 double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
7988 // The order of these expected values correspond to the order of roundingModes and the order of values.
7989 const char *expected[] = {
7990 "-1.00E25", "-9.99E24", "-1.00E25",
7991 "-1.00E25", "-9.99E24", "-1.00E25",
7992 "-1.00E25", "-1.00E25", "-1.01E25",
7993 "-1.00E25", "-1.00E25", "-1.00E25",
7994 "-1.00E25", "-1.00E25", "-1.00E25",
7995 "-1.00E25", "-1.00E25", "-1.00E25",
7996 "-1.00E25", "-1.00E25", "-1.01E25"};
7997 verifyRounding(
7998 format,
7999 values,
8000 expected,
8001 roundingModes,
8002 descriptions,
8003 UPRV_LENGTHOF(values),
8004 UPRV_LENGTHOF(roundingModes));
8005 }
8006 {
8007 double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
8008 // The order of these expected values correspond to the order of roundingModes and the order of values.
8009 const char *expected[] = {
8010 "1.00E-25", "1.01E-25", "1.00E-25",
8011 "1.00E-25", "1.00E-25", "9.99E-26",
8012 "1.00E-25", "1.00E-25", "9.99E-26",
8013 "1.00E-25", "1.00E-25", "1.00E-25",
8014 "1.00E-25", "1.00E-25", "1.00E-25",
8015 "1.00E-25", "1.00E-25", "1.00E-25",
8016 "1.00E-25", "1.01E-25", "1.00E-25"};
8017 verifyRounding(
8018 format,
8019 values,
8020 expected,
8021 roundingModes,
8022 descriptions,
8023 UPRV_LENGTHOF(values),
8024 UPRV_LENGTHOF(roundingModes));
8025 }
8026 {
8027 double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
8028 // The order of these expected values correspond to the order of roundingModes and the order of values.
8029 const char *expected[] = {
8030 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8031 "-1.00E-25", "-9.99E-26", "-1.00E-25",
8032 "-1.00E-25", "-1.00E-25", "-1.01E-25",
8033 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8034 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8035 "-1.00E-25", "-1.00E-25", "-1.00E-25",
8036 "-1.00E-25", "-1.00E-25", "-1.01E-25"};
8037 verifyRounding(
8038 format,
8039 values,
8040 expected,
8041 roundingModes,
8042 descriptions,
8043 UPRV_LENGTHOF(values),
8044 UPRV_LENGTHOF(roundingModes));
8045 }
8046}
8047
8048void NumberFormatTest::TestZeroScientific10547() {
8049 UErrorCode status = U_ZERO_ERROR;
8050 DecimalFormat fmt("0.00E0", status);
8051 if (!assertSuccess("Format creation", status)) {
8052 return;
8053 }
8054 UnicodeString out;
8055 fmt.format(-0.0, out);
8056 assertEquals("format", "-0.00E0", out, true);
8057}
8058
8059void NumberFormatTest::verifyRounding(
8060 DecimalFormat& format,
8061 const double *values,
8062 const char * const *expected,
8063 const DecimalFormat::ERoundingMode *roundingModes,
8064 const char * const *descriptions,
8065 int32_t valueSize,
8066 int32_t roundingModeSize) {
8067 for (int32_t i = 0; i < roundingModeSize; ++i) {
8068 format.setRoundingMode(roundingModes[i]);
8069 for (int32_t j = 0; j < valueSize; j++) {
8070 UnicodeString currentExpected(expected[i * valueSize + j]);
8071 currentExpected = currentExpected.unescape();
8072 UnicodeString actual;
8073 format.format(values[j], actual);
8074 if (currentExpected != actual) {
8075 dataerrln("For %s value %f, expected '%s', got '%s'",
8076 descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
8077 }
8078 }
8079 }
8080}
8081
8082void NumberFormatTest::TestAccountingCurrency() {
8083 UErrorCode status = U_ZERO_ERROR;
8084 UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
8085
8086 expect(NumberFormat::createInstance("en_US", style, status),
8087 (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
8088 expect(NumberFormat::createInstance("en_US", style, status),
8089 (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
8090 expect(NumberFormat::createInstance("en_US", style, status),
8091 (Formattable)(double)0, "$0.00", TRUE, status);
8092 expect(NumberFormat::createInstance("en_US", style, status),
8093 (Formattable)(double)-0.2, "($0.20)", TRUE, status);
8094 expect(NumberFormat::createInstance("ja_JP", style, status),
8095 (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
8096 expect(NumberFormat::createInstance("ja_JP", style, status),
8097 (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
8098 expect(NumberFormat::createInstance("de_DE", style, status),
8099 (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
8100 expect(NumberFormat::createInstance("en_ID", style, status),
8101 (Formattable)(double)0, UnicodeString("IDR\\u00A00.00").unescape(), TRUE, status);
8102 expect(NumberFormat::createInstance("en_ID", style, status),
8103 (Formattable)(double)-0.2, UnicodeString("(IDR\\u00A00.20)").unescape(), TRUE, status);
8104 expect(NumberFormat::createInstance("sh_ME", style, status),
8105 (Formattable)(double)0, UnicodeString("0,00\\u00A0\\u20AC").unescape(), TRUE, status);
8106 expect(NumberFormat::createInstance("sh_ME", style, status),
8107 (Formattable)(double)-0.2, UnicodeString("(0,20\\u00A0\\u20AC)").unescape(), TRUE, status);
8108}
8109
8110/**
8111 * ICU4J has the behavior explained below, but ICU4C is not affected. Test is added to prevent regression.
8112 *
8113 * en_ID/sh_ME uses language only locales en/sh which requires NumberFormatServiceShim to fill in the currency, but
8114 * prior to ICU-20631, currency was not filled in for accounting, cash and standard, so currency placeholder was
8115 * used instead of the desired locale's currency.
8116 */
8117void NumberFormatTest::TestCurrencyFormatForMissingLocale() {
8118 IcuTestErrorCode status(*this, "TestCurrencyFormatForMissingLocale");
8119 Locale locale = Locale::createCanonical("sh_ME");
8120
8121 LocalPointer<NumberFormat> curFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status));
8122 // Fail here with missing data.
8123 if (!assertTrue(WHERE, curFmt.isValid(), false, true)) {return;};
8124 assertEquals("Currency instance is not for the desired locale for CURRENCYSTYLE", curFmt->getCurrency(), "EUR");
8125 UnicodeString currBuf;
8126 curFmt->format(-1234.5, currBuf);
8127 assertEquals("NumberFormat format outputs wrong value for CURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", currBuf);
8128
8129 LocalPointer<NumberFormat> accFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_ACCOUNTING, status));
8130 assertEquals("Currency instance is not for the desired locale for ACCOUNTINGCURRENCYSTYLE", accFmt->getCurrency(), "EUR");
8131 UnicodeString accBuf;
8132 accFmt->format(-1234.5, accBuf);
8133 assertEquals("NumberFormat format outputs wrong value for ACCOUNTINGCURRENCYSTYLE", u"(1.234,50\u00A0\u20AC)", accBuf);
8134
8135 LocalPointer<NumberFormat> cashFmt(NumberFormat::createInstance(locale, UNUM_CASH_CURRENCY, status));
8136 assertEquals("Currency instance is not for the desired locale for CASHCURRENCYSTYLE", cashFmt->getCurrency(), "EUR");
8137 UnicodeString cashBuf;
8138 cashFmt->format(-1234.5, cashBuf);
8139 assertEquals("NumberFormat format outputs wrong value for CASHCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", cashBuf);
8140
8141 LocalPointer<NumberFormat> stdFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY_STANDARD, status));
8142 assertEquals("Currency instance is not for the desired locale for STANDARDCURRENCYSTYLE", stdFmt->getCurrency(), "EUR");
8143 UnicodeString stdBuf;
8144 stdFmt->format(-1234.5, stdBuf);
8145 assertEquals("NumberFormat format outputs wrong value for STANDARDCURRENCYSTYLE", u"-1.234,50\u00A0\u20AC", stdBuf);
8146}
8147
8148// for #5186
8149void NumberFormatTest::TestEquality() {
8150 UErrorCode status = U_ZERO_ERROR;
8151 DecimalFormatSymbols symbols(Locale("root"), status);
8152 if (U_FAILURE(status)) {
8153 dataerrln("Fail: can't create DecimalFormatSymbols for root");
8154 return;
8155 }
8156 UnicodeString pattern("#,##0.###");
8157 DecimalFormat fmtBase(pattern, symbols, status);
8158 if (U_FAILURE(status)) {
8159 dataerrln("Fail: can't create DecimalFormat using root symbols");
8160 return;
8161 }
8162
8163 DecimalFormat* fmtClone = fmtBase.clone();
8164 fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
8165 if (*fmtClone == fmtBase) {
8166 errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
8167 }
8168 delete fmtClone;
8169}
8170
8171void NumberFormatTest::TestCurrencyUsage() {
8172 double agent = 123.567;
8173
8174 UErrorCode status;
8175 DecimalFormat *fmt;
8176
8177 // compare the Currency and Currency Cash Digits
8178 // Note that as of CLDR 26:
8179 // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
8180 // * CAD rounds to .05 in cash mode only
8181 // 1st time for getter/setter, 2nd time for factory method
8182 Locale enUS_ISK("en_US@currency=ISK");
8183
8184 for(int i=0; i<2; i++){
8185 status = U_ZERO_ERROR;
8186 if(i == 0){
8187 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
8188 if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
8189 continue;
8190 }
8191
8192 UnicodeString original;
8193 fmt->format(agent,original);
8194 assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);
8195
8196 // test the getter here
8197 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8198 assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
8199
8200 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8201 }else{
8202 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
8203 if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
8204 continue;
8205 }
8206 }
8207
8208 // must be usage = cash
8209 UCurrencyUsage curUsage = fmt->getCurrencyUsage();
8210 assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
8211
8212 UnicodeString cash_currency;
8213 fmt->format(agent,cash_currency);
8214 assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
8215 delete fmt;
8216 }
8217
8218 // compare the Currency and Currency Cash Rounding
8219 // 1st time for getter/setter, 2nd time for factory method
8220 Locale enUS_CAD("en_US@currency=CAD");
8221 for(int i=0; i<2; i++){
8222 status = U_ZERO_ERROR;
8223 if(i == 0){
8224 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8225 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8226 continue;
8227 }
8228
8229 UnicodeString original_rounding;
8230 fmt->format(agent, original_rounding);
8231 assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
8232 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8233 }else{
8234 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8235 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8236 continue;
8237 }
8238 }
8239
8240 UnicodeString cash_rounding_currency;
8241 fmt->format(agent, cash_rounding_currency);
8242 assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
8243 delete fmt;
8244 }
8245
8246 // Test the currency change
8247 // 1st time for getter/setter, 2nd time for factory method
8248 const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
8249 for(int i=0; i<2; i++){
8250 status = U_ZERO_ERROR;
8251 if(i == 0){
8252 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
8253 if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
8254 continue;
8255 }
8256 fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
8257 }else{
8258 fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
8259 if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
8260 continue;
8261 }
8262 }
8263
8264 UnicodeString cur_original;
8265 fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
8266 fmt->format(agent, cur_original);
8267 assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
8268
8269 fmt->setCurrency(CUR_PKR, status);
8270 assertSuccess("Set currency to PKR", status);
8271
8272 UnicodeString PKR_changed;
8273 fmt->format(agent, PKR_changed);
8274 assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
8275 delete fmt;
8276 }
8277}
8278
8279
8280// Check the constant MAX_INT64_IN_DOUBLE.
8281// The value should convert to a double with no loss of precision.
8282// A failure may indicate a platform with a different double format, requiring
8283// a revision to the constant.
8284//
8285// Note that this is actually hard to test, because the language standard gives
8286// compilers considerable flexibility to do unexpected things with rounding and
8287// with overflow in simple int to/from float conversions. Some compilers will completely optimize
8288// away a simple round-trip conversion from int64_t -> double -> int64_t.
8289
8290void NumberFormatTest::TestDoubleLimit11439() {
8291 char buf[50];
8292 for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
8293 sprintf(buf, "%lld", (long long)num);
8294 double fNum = 0.0;
8295 sscanf(buf, "%lf", &fNum);
8296 int64_t rtNum = static_cast<int64_t>(fNum);
8297 if (num != rtNum) {
8298 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8299 return;
8300 }
8301 }
8302 for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
8303 sprintf(buf, "%lld", (long long)num);
8304 double fNum = 0.0;
8305 sscanf(buf, "%lf", &fNum);
8306 int64_t rtNum = static_cast<int64_t>(fNum);
8307 if (num != rtNum) {
8308 errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
8309 return;
8310 }
8311 }
8312}
8313
8314void NumberFormatTest::TestGetAffixes() {
8315 UErrorCode status = U_ZERO_ERROR;
8316 DecimalFormatSymbols sym("en_US", status);
8317 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8318 pattern = pattern.unescape();
8319 DecimalFormat fmt(pattern, sym, status);
8320 if (U_FAILURE(status)) {
8321 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8322 return;
8323 }
8324 UnicodeString affixStr;
8325 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8326 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8327 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8328 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8329
8330 // Test equality with affixes. set affix methods can't capture special
8331 // characters which is why equality should fail.
8332 {
8333 DecimalFormat fmtCopy(fmt);
8334 assertTrue("", fmt == fmtCopy);
8335 UnicodeString someAffix;
8336 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
8337 assertTrue("", fmt != fmtCopy);
8338 }
8339 {
8340 DecimalFormat fmtCopy(fmt);
8341 assertTrue("", fmt == fmtCopy);
8342 UnicodeString someAffix;
8343 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
8344 assertTrue("", fmt != fmtCopy);
8345 }
8346 {
8347 DecimalFormat fmtCopy(fmt);
8348 assertTrue("", fmt == fmtCopy);
8349 UnicodeString someAffix;
8350 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
8351 assertTrue("", fmt != fmtCopy);
8352 }
8353 {
8354 DecimalFormat fmtCopy(fmt);
8355 assertTrue("", fmt == fmtCopy);
8356 UnicodeString someAffix;
8357 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
8358 assertTrue("", fmt != fmtCopy);
8359 }
8360 fmt.setPositivePrefix("Don't");
8361 fmt.setPositiveSuffix("do");
8362 UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
8363 someAffix = someAffix.unescape();
8364 fmt.setNegativePrefix(someAffix);
8365 fmt.setNegativeSuffix("%");
8366 assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
8367 assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
8368 assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
8369 assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
8370}
8371
8372void NumberFormatTest::TestToPatternScientific11648() {
8373 UErrorCode status = U_ZERO_ERROR;
8374 Locale en("en");
8375 DecimalFormatSymbols sym(en, status);
8376 DecimalFormat fmt("0.00", sym, status);
8377 if (U_FAILURE(status)) {
8378 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8379 return;
8380 }
8381 fmt.setScientificNotation(TRUE);
8382 UnicodeString pattern;
8383 assertEquals("", "0.00E0", fmt.toPattern(pattern));
8384 DecimalFormat fmt2(pattern, sym, status);
8385 assertSuccess("", status);
8386}
8387
8388void NumberFormatTest::TestBenchmark() {
8389/*
8390 UErrorCode status = U_ZERO_ERROR;
8391 Locale en("en");
8392 DecimalFormatSymbols sym(en, status);
8393 DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
8394// DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
8395// DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
8396 FieldPosition fpos(FieldPosition::DONT_CARE);
8397 clock_t start = clock();
8398 for (int32_t i = 0; i < 1000000; ++i) {
8399 UnicodeString append;
8400 fmt.format(3.0, append, fpos, status);
8401// fmt.format(4.6692016, append, fpos, status);
8402// fmt.format(1234567.8901, append, fpos, status);
8403// fmt.format(2.99792458E8, append, fpos, status);
8404// fmt.format(31, append);
8405 }
8406 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8407 assertSuccess("", status);
8408
8409 UErrorCode status = U_ZERO_ERROR;
8410 MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
8411 FieldPosition fpos(FieldPosition::DONT_CARE);
8412 Formattable one(1.0);
8413 Formattable three(3.0);
8414 clock_t start = clock();
8415 for (int32_t i = 0; i < 500000; ++i) {
8416 UnicodeString append;
8417 fmt.format(&one, 1, append, fpos, status);
8418 UnicodeString append2;
8419 fmt.format(&three, 1, append2, fpos, status);
8420 }
8421 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8422 assertSuccess("", status);
8423
8424 UErrorCode status = U_ZERO_ERROR;
8425 Locale en("en");
8426 Measure measureC(23, MeasureUnit::createCelsius(status), status);
8427 MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
8428 FieldPosition fpos(FieldPosition::DONT_CARE);
8429 clock_t start = clock();
8430 for (int32_t i = 0; i < 1000000; ++i) {
8431 UnicodeString appendTo;
8432 fmt.formatMeasures(
8433 &measureC, 1, appendTo, fpos, status);
8434 }
8435 errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
8436 assertSuccess("", status);
8437*/
8438}
8439
8440void NumberFormatTest::TestFractionalDigitsForCurrency() {
8441 UErrorCode status = U_ZERO_ERROR;
8442 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
8443 if (U_FAILURE(status)) {
8444 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8445 return;
8446 }
8447 UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
8448 fmt->setCurrency(JPY, status);
8449 if (!assertSuccess("", status)) {
8450 return;
8451 }
8452 assertEquals("", 0, fmt->getMaximumFractionDigits());
8453}
8454
8455
8456void NumberFormatTest::TestFormatCurrencyPlural() {
8457 UErrorCode status = U_ZERO_ERROR;
8458 Locale locale = Locale::createCanonical("en_US");
8459 NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
8460 if (U_FAILURE(status)) {
8461 dataerrln("Error creating NumberFormat - %s", u_errorName(status));
8462 return;
8463 }
8464 UnicodeString formattedNum;
8465 fmt->format(11234.567, formattedNum, NULL, status);
8466 assertEquals("", "11,234.57 US dollars", formattedNum);
8467 delete fmt;
8468}
8469
8470void NumberFormatTest::TestCtorApplyPatternDifference() {
8471 UErrorCode status = U_ZERO_ERROR;
8472 DecimalFormatSymbols sym("en_US", status);
8473 UnicodeString pattern("\\u00a40");
8474 DecimalFormat fmt(pattern.unescape(), sym, status);
8475 if (U_FAILURE(status)) {
8476 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
8477 return;
8478 }
8479 UnicodeString result;
8480 assertEquals(
8481 "ctor favors precision of currency",
8482 "$5.00",
8483 fmt.format((double)5, result));
8484 result.remove();
8485 fmt.applyPattern(pattern.unescape(), status);
8486 assertEquals(
8487 "applyPattern favors precision of pattern",
8488 "$5",
8489 fmt.format((double)5, result));
8490}
8491
8492void NumberFormatTest::Test11868() {
8493 double posAmt = 34.567;
8494 double negAmt = -9876.543;
8495
8496 Locale selectedLocale("en_US");
8497 UErrorCode status = U_ZERO_ERROR;
8498
8499 UnicodeString result;
8500 FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
8501 LocalPointer<NumberFormat> fmt(
8502 NumberFormat::createInstance(
8503 selectedLocale, UNUM_CURRENCY_PLURAL, status));
8504 if (!assertSuccess("Format creation", status)) {
8505 return;
8506 }
8507 fmt->format(posAmt, result, fpCurr, status);
8508 assertEquals("", "34.57 US dollars", result);
8509 assertEquals("begin index", 6, fpCurr.getBeginIndex());
8510 assertEquals("end index", 16, fpCurr.getEndIndex());
8511
8512 // Test field position iterator
8513 {
8514 NumberFormatTest_Attributes attributes[] = {
8515 {UNUM_INTEGER_FIELD, 0, 2},
8516 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8517 {UNUM_FRACTION_FIELD, 3, 5},
8518 {UNUM_CURRENCY_FIELD, 6, 16},
8519 {0, -1, 0}};
8520 UnicodeString result;
8521 FieldPositionIterator iter;
8522 fmt->format(posAmt, result, &iter, status);
8523 assertEquals("", "34.57 US dollars", result);
8524 verifyFieldPositionIterator(attributes, iter);
8525 }
8526
8527 result.remove();
8528 fmt->format(negAmt, result, fpCurr, status);
8529 assertEquals("", "-9,876.54 US dollars", result);
8530 assertEquals("begin index", 10, fpCurr.getBeginIndex());
8531 assertEquals("end index", 20, fpCurr.getEndIndex());
8532
8533 // Test field position iterator
8534 {
8535 NumberFormatTest_Attributes attributes[] = {
8536 {UNUM_SIGN_FIELD, 0, 1},
8537 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
8538 {UNUM_INTEGER_FIELD, 1, 6},
8539 {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
8540 {UNUM_FRACTION_FIELD, 7, 9},
8541 {UNUM_CURRENCY_FIELD, 10, 20},
8542 {0, -1, 0}};
8543 UnicodeString result;
8544 FieldPositionIterator iter;
8545 fmt->format(negAmt, result, &iter, status);
8546 assertEquals("", "-9,876.54 US dollars", result);
8547 verifyFieldPositionIterator(attributes, iter);
8548 }
8549}
8550
8551void NumberFormatTest::Test10727_RoundingZero() {
8552 IcuTestErrorCode status(*this, "Test10727_RoundingZero");
8553 DecimalQuantity dq;
8554 dq.setToDouble(-0.0);
8555 assertTrue("", dq.isNegative());
8556 dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
8557 assertTrue("", dq.isNegative());
8558}
8559
8560void NumberFormatTest::Test11739_ParseLongCurrency() {
8561 IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
8562 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
8563 if (status.errDataIfFailureAndReset()) { return; }
8564 ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
8565 ParsePosition ppos(0);
8566 LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
8567 assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
8568 if (ppos.getErrorIndex() != -1) {
8569 return;
8570 }
8571 assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
8572 assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
8573}
8574
8575void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
8576 IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
8577 DecimalFormat df(u"a*'நி'###0b", status);
8578 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8579 UnicodeString result;
8580 df.format(12, result.remove());
8581 // TODO(13034): Re-enable this test when support is added in ICU4C.
8582 //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
8583 df = DecimalFormat(u"a*\U0001F601###0b", status);
8584 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8585 result = df.format(12, result.remove());
8586 assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
8587 df = DecimalFormat(u"a*''###0b", status);
8588 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
8589 result = df.format(12, result.remove());
8590 assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
8591}
8592
8593void NumberFormatTest::Test13737_ParseScientificStrict() {
8594 IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
8595 LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
8596 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8597 df->setLenient(FALSE);
8598 // Parse Test
8599 expect(*df, u"1.2", 1.2);
8600}
8601
8602void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
8603 {
8604 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8605 UErrorCode status = U_ZERO_ERROR;
8606 LocalPointer<NumberFormat> fmt(
8607 NumberFormat::createCurrencyInstance("en", status));
8608 if (!assertSuccess("", status)) {
8609 return;
8610 }
8611 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8612 dfmt->setCurrency(USD);
8613 UnicodeString result;
8614
8615 // This line should be a no-op. I am setting the positive prefix
8616 // to be the same thing it was before.
8617 dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
8618
8619 UnicodeString appendTo;
8620 assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
8621 assertSuccess("", status);
8622 }
8623 {
8624 const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8625 UErrorCode status = U_ZERO_ERROR;
8626 LocalPointer<NumberFormat> fmt(
8627 NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
8628 if (!assertSuccess("", status)) {
8629 return;
8630 }
8631 DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
8632 UnicodeString result;
8633 assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
8634 dfmt->setCurrency(USD);
8635
8636 // getPositiveSuffix() always returns the suffix for the
8637 // "other" plural category
8638 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8639 UnicodeString appendTo;
8640 assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
8641 assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
8642 dfmt->setPositiveSuffix("booya");
8643 appendTo.remove();
8644 assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
8645 assertEquals("", "booya", dfmt->getPositiveSuffix(result));
8646 }
8647}
8648
8649void NumberFormatTest::Test11475_signRecognition() {
8650 UErrorCode status = U_ZERO_ERROR;
8651 DecimalFormatSymbols sym("en", status);
8652 UnicodeString result;
8653 {
8654 DecimalFormat fmt("+0.00", sym, status);
8655 if (!assertSuccess("", status)) {
8656 return;
8657 }
8658 NumberFormatTest_Attributes attributes[] = {
8659 {UNUM_SIGN_FIELD, 0, 1},
8660 {UNUM_INTEGER_FIELD, 1, 2},
8661 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
8662 {UNUM_FRACTION_FIELD, 3, 5},
8663 {0, -1, 0}};
8664 UnicodeString result;
8665 FieldPositionIterator iter;
8666 fmt.format(2.3, result, &iter, status);
8667 assertEquals("", "+2.30", result);
8668 verifyFieldPositionIterator(attributes, iter);
8669 }
8670 {
8671 DecimalFormat fmt("++0.00+;-(#)--", sym, status);
8672 if (!assertSuccess("", status)) {
8673 return;
8674 }
8675 {
8676 NumberFormatTest_Attributes attributes[] = {
8677 {UNUM_SIGN_FIELD, 0, 2},
8678 {UNUM_INTEGER_FIELD, 2, 3},
8679 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8680 {UNUM_FRACTION_FIELD, 4, 6},
8681 {UNUM_SIGN_FIELD, 6, 7},
8682 {0, -1, 0}};
8683 UnicodeString result;
8684 FieldPositionIterator iter;
8685 fmt.format(2.3, result, &iter, status);
8686 assertEquals("", "++2.30+", result);
8687 verifyFieldPositionIterator(attributes, iter);
8688 }
8689 {
8690 NumberFormatTest_Attributes attributes[] = {
8691 {UNUM_SIGN_FIELD, 0, 1},
8692 {UNUM_INTEGER_FIELD, 2, 3},
8693 {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
8694 {UNUM_FRACTION_FIELD, 4, 6},
8695 {UNUM_SIGN_FIELD, 7, 9},
8696 {0, -1, 0}};
8697 UnicodeString result;
8698 FieldPositionIterator iter;
8699 fmt.format(-2.3, result, &iter, status);
8700 assertEquals("", "-(2.30)--", result);
8701 verifyFieldPositionIterator(attributes, iter);
8702 }
8703 }
8704}
8705
8706void NumberFormatTest::Test11640_getAffixes() {
8707 UErrorCode status = U_ZERO_ERROR;
8708 DecimalFormatSymbols symbols("en_US", status);
8709 if (!assertSuccess("", status)) {
8710 return;
8711 }
8712 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
8713 pattern = pattern.unescape();
8714 DecimalFormat fmt(pattern, symbols, status);
8715 if (!assertSuccess("", status)) {
8716 return;
8717 }
8718 UnicodeString affixStr;
8719 assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
8720 assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
8721 assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
8722 assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
8723}
8724
8725void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
8726 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
8727 pattern = pattern.unescape();
8728 UErrorCode status = U_ZERO_ERROR;
8729 DecimalFormat fmt(pattern, status);
8730 if (!assertSuccess("", status)) {
8731 return;
8732 }
8733 static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
8734 fmt.setCurrency(USD);
8735 UnicodeString appendTo;
8736
8737 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
8738
8739 UnicodeString topattern;
8740 fmt.toPattern(topattern);
8741 DecimalFormat fmt2(topattern, status);
8742 if (!assertSuccess("", status)) {
8743 return;
8744 }
8745 fmt2.setCurrency(USD);
8746
8747 appendTo.remove();
8748 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
8749}
8750
8751void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
8752 UErrorCode status = U_ZERO_ERROR;
8753 for (int runId = 0; runId < 2; runId++) {
8754 // Construct a locale string with a very long "numbers" value.
8755 // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
8756 // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
8757 int extraLength = (runId == 0) ? 0 : 5;
8758
8759 CharString localeId("en@numbers=", status);
8760 for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
8761 localeId.append('x', status);
8762 }
8763 assertSuccess("Constructing locale string", status);
8764 Locale locale(localeId.data());
8765
8766 LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
8767 assertFalse("Should not be null", ns.getAlias() == nullptr);
8768 assertSuccess("Should create with no error", status);
8769 }
8770}
8771
8772void NumberFormatTest::Test13391_chakmaParsing() {
8773 UErrorCode status = U_ZERO_ERROR;
8774 LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
8775 NumberFormat::createInstance(Locale("ccp"), status)));
8776 if (df == nullptr) {
8777 dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
8778 return;
8779 }
8780 const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
8781 UnicodeString actual;
8782 df->format(12345, actual, status);
8783 assertSuccess("Should not fail when formatting in ccp", status);
8784 assertEquals("Should produce expected output in ccp", expected, actual);
8785
8786 Formattable result;
8787 df->parse(expected, result, status);
8788 assertSuccess("Should not fail when parsing in ccp", status);
8789 assertEquals("Should parse to 12345 in ccp", 12345, result);
8790
8791 const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
8792 UnicodeString actualScientific;
8793 df.adoptInstead(static_cast<DecimalFormat*>(
8794 NumberFormat::createScientificInstance(Locale("ccp"), status)));
8795 df->format(130, actualScientific, status);
8796 assertSuccess("Should not fail when formatting scientific in ccp", status);
8797 assertEquals("Should produce expected scientific output in ccp",
8798 expectedScientific, actualScientific);
8799
8800 Formattable resultScientific;
8801 df->parse(expectedScientific, resultScientific, status);
8802 assertSuccess("Should not fail when parsing scientific in ccp", status);
8803 assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
8804}
8805
8806
8807void NumberFormatTest::verifyFieldPositionIterator(
8808 NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
8809 int32_t idx = 0;
8810 FieldPosition fp;
8811 while (iter.next(fp)) {
8812 if (expected[idx].spos == -1) {
8813 errln("Iterator should have ended. got %d", fp.getField());
8814 return;
8815 }
8816 assertEquals("id", expected[idx].id, fp.getField());
8817 assertEquals("start", expected[idx].spos, fp.getBeginIndex());
8818 assertEquals("end", expected[idx].epos, fp.getEndIndex());
8819 ++idx;
8820 }
8821 if (expected[idx].spos != -1) {
8822 errln("Premature end of iterator. expected %d", expected[idx].id);
8823 }
8824}
8825
8826void NumberFormatTest::Test11735_ExceptionIssue() {
8827 IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
8828 Locale enLocale("en");
8829 DecimalFormatSymbols symbols(enLocale, status);
8830 if (status.isSuccess()) {
8831 DecimalFormat fmt("0", symbols, status);
8832 assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
8833 ParsePosition ppos(0);
8834 fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
8835 assertEquals("Issue11735 ppos", 0, ppos.getIndex());
8836 }
8837}
8838
8839void NumberFormatTest::Test11035_FormatCurrencyAmount() {
8840 UErrorCode status = U_ZERO_ERROR;
8841 double amount = 12345.67;
8842 const char16_t* expected = u"12,345$67 ​";
8843
8844 // Test two ways to set a currency via API
8845
8846 Locale loc1 = Locale("pt_PT");
8847 LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance(loc1, status),
8848 status);
8849 if (U_FAILURE(status)) {
8850 dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
8851 return;
8852 }
8853 fmt1->setCurrency(u"PTE", status);
8854 assertSuccess("Setting currency on fmt1", status);
8855 UnicodeString actualSetCurrency;
8856 fmt1->format(amount, actualSetCurrency);
8857
8858 Locale loc2 = Locale("pt_PT@currency=PTE");
8859 LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
8860 assertSuccess("Creating fmt2", status);
8861 UnicodeString actualLocaleString;
8862 fmt2->format(amount, actualLocaleString);
8863
8864 assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
8865 assertEquals("Custom Currency Pattern, Locale String", expected, actualLocaleString);
8866}
8867
8868void NumberFormatTest::Test11318_DoubleConversion() {
8869 IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
8870 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
8871 if (U_FAILURE(status)) {
8872 dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
8873 return;
8874 }
8875 nf->setMaximumFractionDigits(40);
8876 nf->setMaximumIntegerDigits(40);
8877 UnicodeString appendTo;
8878 nf->format(999999999999999.9, appendTo);
8879 assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
8880}
8881
8882void NumberFormatTest::TestParsePercentRegression() {
8883 IcuTestErrorCode status(*this, "TestParsePercentRegression");
8884 LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
8885 LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
8886 if (status.isFailure()) {return; }
8887 df1->setLenient(TRUE);
8888 df2->setLenient(TRUE);
8889
8890 {
8891 ParsePosition ppos;
8892 Formattable result;
8893 df1->parse("50%", result, ppos);
8894 assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
8895 assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
8896 }
8897 {
8898 ParsePosition ppos;
8899 Formattable result;
8900 df2->parse("50%", result, ppos);
8901 assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
8902 assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
8903 }
8904 {
8905 ParsePosition ppos;
8906 Formattable result;
8907 df2->parse("50", result, ppos);
8908 assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
8909 0.5,
8910 result.getDouble(status));
8911 }
8912}
8913
8914void NumberFormatTest::TestMultiplierWithScale() {
8915 IcuTestErrorCode status(*this, "TestMultiplierWithScale");
8916
8917 // Test magnitude combined with multiplier, as shown in API docs
8918 DecimalFormat df("0", {"en", status}, status);
8919 if (status.isSuccess()) {
8920 df.setMultiplier(5);
8921 df.setMultiplierScale(-1);
8922 expect2(df, 100, u"50"); // round-trip test
8923 }
8924}
8925
8926void NumberFormatTest::TestFastFormatInt32() {
8927 IcuTestErrorCode status(*this, "TestFastFormatInt32");
8928
8929 // The two simplest formatters, old API and new API.
8930 // Old API should use the fastpath for ints.
8931 LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
8932 LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
8933 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
8934
8935 double nums[] = {
8936 0.0,
8937 -0.0,
8938 NAN,
8939 INFINITY,
8940 0.1,
8941 1.0,
8942 1.1,
8943 2.0,
8944 3.0,
8945 9.0,
8946 10.0,
8947 99.0,
8948 100.0,
8949 999.0,
8950 1000.0,
8951 9999.0,
8952 10000.0,
8953 99999.0,
8954 100000.0,
8955 999999.0,
8956 1000000.0,
8957 static_cast<double>(INT32_MAX) - 1,
8958 static_cast<double>(INT32_MAX),
8959 static_cast<double>(INT32_MAX) + 1,
8960 static_cast<double>(INT32_MIN) - 1,
8961 static_cast<double>(INT32_MIN),
8962 static_cast<double>(INT32_MIN) + 1};
8963
8964 for (auto num : nums) {
8965 UnicodeString expected = lnf.formatDouble(num, status).toString(status);
8966 UnicodeString actual;
8967 df->format(num, actual);
8968 assertEquals(UnicodeString("d = ") + num, expected, actual);
8969 }
8970}
8971
8972void NumberFormatTest::Test11646_Equality() {
8973 UErrorCode status = U_ZERO_ERROR;
8974 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
8975 UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
8976 DecimalFormat fmt(pattern, symbols, status);
8977 if (!assertSuccess("", status)) return;
8978
8979 // Test equality with affixes. set affix methods can't capture special
8980 // characters which is why equality should fail.
8981 {
8982 DecimalFormat fmtCopy(fmt);
8983 assertTrue("", fmt == fmtCopy);
8984 UnicodeString positivePrefix;
8985 fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
8986 assertFalse("", fmt == fmtCopy);
8987 }
8988 {
8989 DecimalFormat fmtCopy = DecimalFormat(fmt);
8990 assertTrue("", fmt == fmtCopy);
8991 UnicodeString positivePrefix;
8992 fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
8993 assertFalse("", fmt == fmtCopy);
8994 }
8995 {
8996 DecimalFormat fmtCopy(fmt);
8997 assertTrue("", fmt == fmtCopy);
8998 UnicodeString negativePrefix;
8999 fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
9000 assertFalse("", fmt == fmtCopy);
9001 }
9002 {
9003 DecimalFormat fmtCopy(fmt);
9004 assertTrue("", fmt == fmtCopy);
9005 UnicodeString negativePrefix;
9006 fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
9007 assertFalse("", fmt == fmtCopy);
9008 }
9009}
9010
9011void NumberFormatTest::TestParseNaN() {
9012 IcuTestErrorCode status(*this, "TestParseNaN");
9013
9014 DecimalFormat df("0", { "en", status }, status);
9015 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9016 Formattable parseResult;
9017 df.parse(u"NaN", parseResult, status);
9018 assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
9019 assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
9020 UnicodeString formatResult;
9021 df.format(parseResult.getDouble(), formatResult);
9022 assertEquals("NaN should round-trip", u"NaN", formatResult);
9023}
9024
9025void NumberFormatTest::TestFormatFailIfMoreThanMaxDigits() {
9026 IcuTestErrorCode status(*this, "TestFormatFailIfMoreThanMaxDigits");
9027
9028 DecimalFormat df("0", {"en-US", status}, status);
9029 if (status.errDataIfFailureAndReset()) {
9030 return;
9031 }
9032 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isFormatFailIfMoreThanMaxDigits());
9033 df.setFormatFailIfMoreThanMaxDigits(TRUE);
9034 assertEquals("Coverage for getter 2", (UBool) TRUE, df.isFormatFailIfMoreThanMaxDigits());
9035 df.setMaximumIntegerDigits(2);
9036 UnicodeString result;
9037 df.format(1234, result, status);
9038 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
9039}
9040
9041void NumberFormatTest::TestParseCaseSensitive() {
9042 IcuTestErrorCode status(*this, "TestParseCaseSensitive");
9043
9044 DecimalFormat df(u"0", {"en-US", status}, status);
9045 if (status.errDataIfFailureAndReset()) {
9046 return;
9047 }
9048 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseCaseSensitive());
9049 df.setParseCaseSensitive(TRUE);
9050 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseCaseSensitive());
9051 Formattable result;
9052 ParsePosition ppos;
9053 df.parse(u"1e2", result, ppos);
9054 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9055 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9056}
9057
9058void NumberFormatTest::TestParseNoExponent() {
9059 IcuTestErrorCode status(*this, "TestParseNoExponent");
9060
9061 DecimalFormat df(u"0", {"en-US", status}, status);
9062 if (status.errDataIfFailureAndReset()) {
9063 return;
9064 }
9065 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isParseNoExponent());
9066 df.setParseNoExponent(TRUE);
9067 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isParseNoExponent());
9068 Formattable result;
9069 ParsePosition ppos;
9070 df.parse(u"1E2", result, ppos);
9071 assertEquals("Should parse only 1 digit", 1, ppos.getIndex());
9072 assertEquals("Result should be 1", 1.0, result.getDouble(status));
9073}
9074
9075void NumberFormatTest::TestSignAlwaysShown() {
9076 IcuTestErrorCode status(*this, "TestSignAlwaysShown");
9077
9078 DecimalFormat df(u"0", {"en-US", status}, status);
9079 if (status.errDataIfFailureAndReset()) {
9080 return;
9081 }
9082 assertEquals("Coverage for getter 1", (UBool) FALSE, df.isSignAlwaysShown());
9083 df.setSignAlwaysShown(TRUE);
9084 assertEquals("Coverage for getter 1", (UBool) TRUE, df.isSignAlwaysShown());
9085 UnicodeString result;
9086 df.format(1234, result, status);
9087 status.errIfFailureAndReset();
9088 assertEquals("Should show sign on positive number", u"+1234", result);
9089}
9090
9091void NumberFormatTest::TestMinimumGroupingDigits() {
9092 IcuTestErrorCode status(*this, "TestMinimumGroupingDigits");
9093
9094 DecimalFormat df(u"#,##0", {"en-US", status}, status);
9095 if (status.errDataIfFailureAndReset()) {
9096 return;
9097 }
9098 assertEquals("Coverage for getter 1", -1, df.getMinimumGroupingDigits());
9099 df.setMinimumGroupingDigits(2);
9100 assertEquals("Coverage for getter 1", 2, df.getMinimumGroupingDigits());
9101 UnicodeString result;
9102 df.format(1234, result, status);
9103 status.errIfFailureAndReset();
9104 assertEquals("Should not have grouping", u"1234", result);
9105 df.format(12345, result.remove(), status);
9106 status.errIfFailureAndReset();
9107 assertEquals("Should have grouping", u"12,345", result);
9108
9109
9110 // Test special values -1, UNUM_MINIMUM_GROUPING_DIGITS_AUTO and
9111 // UNUM_MINIMUM_GROUPING_DIGITS_MIN2
9112 struct TestCase {
9113 const char* locale;
9114 int32_t minGroup;
9115 double input;
9116 const char16_t* expected;
9117 } cases[] = {
9118 { "en-US", 1, 1000, u"1,000" },
9119 { "en-US", 1, 10000, u"10,000" },
9120 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1,000" },
9121 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10,000" },
9122 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9123 { "en-US", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10,000" },
9124
9125 { "es", 1, 1000, u"1.000" },
9126 { "es", 1, 10000, u"10.000" },
9127 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 1000, u"1000" },
9128 { "es", UNUM_MINIMUM_GROUPING_DIGITS_AUTO, 10000, u"10.000" },
9129 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 1000, u"1000" },
9130 { "es", UNUM_MINIMUM_GROUPING_DIGITS_MIN2, 10000, u"10.000" },
9131 };
9132 for (const auto& cas : cases) {
9133 UnicodeString message = UnicodeString(cas.locale)
9134 + u" " + Int64ToUnicodeString(cas.minGroup)
9135 + u" " + DoubleToUnicodeString(cas.input);
9136 status.setScope(message);
9137 DecimalFormat df(u"#,##0", {cas.locale, status}, status);
9138 if (status.errIfFailureAndReset()) { continue; }
9139 df.setMinimumGroupingDigits(cas.minGroup);
9140 UnicodeString actual;
9141 df.format(cas.input, actual, status);
9142 if (status.errIfFailureAndReset()) { continue; }
9143 assertEquals(message, cas.expected, actual);
9144 }
9145}
9146
9147void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
9148 IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
9149
9150 // In a locale with a different <list> symbol, like arabic,
9151 // kPatternSeparatorSymbol should still be ';'
9152 {
9153 DecimalFormatSymbols dfs("ar", status);
9154 assertEquals("pattern separator symbol should be ;",
9155 u";",
9156 dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
9157 }
9158
9159 // However, the custom symbol should be used in localized notation
9160 // when set manually via API
9161 {
9162 DecimalFormatSymbols dfs("en", status);
9163 dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
9164 DecimalFormat df(u"0", dfs, status);
9165 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9166 df.applyPattern("a0;b0", status); // should not throw
9167 UnicodeString result;
9168 assertEquals("should apply the normal pattern",
9169 df.getNegativePrefix(result.remove()),
9170 "b");
9171 df.applyLocalizedPattern(u"c0!d0", status); // should not throw
9172 assertEquals("should apply the localized pattern",
9173 df.getNegativePrefix(result.remove()),
9174 "d");
9175 }
9176}
9177
9178void NumberFormatTest::Test13055_PercentageRounding() {
9179 IcuTestErrorCode status(*this, "PercentageRounding");
9180 UnicodeString actual;
9181 LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
9182 if (U_FAILURE(status)) {
9183 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9184 return;
9185 }
9186 pFormat->setMaximumFractionDigits(0);
9187 pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
9188 pFormat->format(2.155, actual);
9189 assertEquals("Should round percent toward even number", "216%", actual);
9190}
9191
9192void NumberFormatTest::Test11839() {
9193 IcuTestErrorCode errorCode(*this, "Test11839");
9194 // Ticket #11839: DecimalFormat does not respect custom plus sign
9195 LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
9196 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9197 dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
9198 dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
9199 DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
9200 UnicodeString result;
9201 df.format(-1.234, result, errorCode);
9202 assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
9203 df.format(1.234, result.remove(), errorCode);
9204 assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
9205 // Test round-trip with parse
9206 expect2(df, -456, u"456.00a∸");
9207 expect2(df, 456, u"456.00b∔");
9208}
9209
9210void NumberFormatTest::Test10354() {
9211 IcuTestErrorCode errorCode(*this, "Test10354");
9212 // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
9213 DecimalFormatSymbols dfs(errorCode);
9214 UnicodeString empty;
9215 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
9216 DecimalFormat df(errorCode);
9217 df.setDecimalFormatSymbols(dfs);
9218 UnicodeString result;
9219 FieldPositionIterator positions;
9220 df.format(NAN, result, &positions, errorCode);
9221 errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
9222 FieldPosition fp;
9223 while (positions.next(fp)) {
9224 // Should not loop forever
9225 }
9226}
9227
9228void NumberFormatTest::Test11645_ApplyPatternEquality() {
9229 IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
9230 const char16_t* pattern = u"#,##0.0#";
9231 LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
9232 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9233 fmt->applyPattern(pattern, status);
9234 LocalPointer<DecimalFormat> fmtCopy;
9235
9236 static const int32_t newMultiplier = 37;
9237 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9238 assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
9239 fmtCopy->setMultiplier(newMultiplier);
9240 assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
9241 fmtCopy->applyPattern(pattern, status);
9242 assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
9243 assertFalse("multiplier", *fmt == *fmtCopy);
9244
9245 static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
9246 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9247 assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
9248 fmtCopy->setRoundingMode(newRoundingMode);
9249 assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
9250 fmtCopy->applyPattern(pattern, status);
9251 assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
9252 assertFalse("roundingMode", *fmt == *fmtCopy);
9253
9254 static const char16_t *const newCurrency = u"EAT";
9255 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9256 assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
9257 fmtCopy->setCurrency(newCurrency);
9258 assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
9259 fmtCopy->applyPattern(pattern, status);
9260 assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
9261 assertFalse("currency", *fmt == *fmtCopy);
9262
9263 static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
9264 fmtCopy.adoptInstead(new DecimalFormat(*fmt));
9265 assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
9266 fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
9267 assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9268 fmtCopy->applyPattern(pattern, status);
9269 assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
9270 assertFalse("currencyUsage", *fmt == *fmtCopy);
9271}
9272
9273void NumberFormatTest::Test12567() {
9274 IcuTestErrorCode errorCode(*this, "Test12567");
9275 // Ticket #12567: DecimalFormat.equals() may not be symmetric
9276 LocalPointer<DecimalFormat> df1((DecimalFormat *)
9277 NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
9278 LocalPointer<DecimalFormat> df2((DecimalFormat *)
9279 NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
9280 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9281 // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
9282 df1->applyPattern(u"0.00", errorCode);
9283 df2->applyPattern(u"0.00", errorCode);
9284 assertTrue("df1 == df2", *df1 == *df2);
9285 assertTrue("df2 == df1", *df2 == *df1);
9286 df2->setPositivePrefix(u"abc");
9287 assertTrue("df1 != df2", *df1 != *df2);
9288 assertTrue("df2 != df1", *df2 != *df1);
9289}
9290
9291void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
9292 IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
9293 // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
9294 // change formatting spelled out currencies
9295 // Use locale sr because it has interesting plural rules.
9296 Locale locale("sr");
9297 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
9298 CurrencyPluralInfo info(locale, errorCode);
9299 if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
9300 info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
9301 info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
9302 DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
9303 df.setCurrencyPluralInfo(info);
9304 df.setCurrency(u"USD");
9305 df.setMaximumFractionDigits(0);
9306
9307 UnicodeString result;
9308 assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
9309 assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
9310 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9311
9312 info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
9313 df.setCurrencyPluralInfo(info);
9314 assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
9315 assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
9316 assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
9317}
9318
9319void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
9320 IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
9321 ParsePosition parsePosition(0);
9322 DecimalFormat df(u"0%", {"en-us", status}, status);
9323 if (U_FAILURE(status)) {
9324 dataerrln("Unable to create DecimalFormat instance.");
9325 return;
9326 }
9327 df.setLenient(FALSE);
9328 Formattable result;
9329 df.parse(u"%2%", result, parsePosition);
9330 assertEquals("", 0, parsePosition.getIndex());
9331 assertEquals("", 0, parsePosition.getErrorIndex());
9332}
9333
9334void NumberFormatTest::Test13056_GroupingSize() {
9335 UErrorCode status = U_ZERO_ERROR;
9336 DecimalFormat df(u"#,##0", status);
9337 if (!assertSuccess("", status)) return;
9338 assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
9339 assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
9340 df.setSecondaryGroupingSize(3);
9341 assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
9342 assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
9343 df.setGroupingSize(4);
9344 assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
9345 assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
9346}
9347
9348
9349void NumberFormatTest::Test11025_CurrencyPadding() {
9350 UErrorCode status = U_ZERO_ERROR;
9351 UnicodeString pattern(u"¤¤ **####0.00");
9352 DecimalFormatSymbols sym(Locale::getFrance(), status);
9353 if (!assertSuccess("", status)) return;
9354 DecimalFormat fmt(pattern, sym, status);
9355 if (!assertSuccess("", status)) return;
9356 UnicodeString result;
9357 fmt.format(433.0, result);
9358 assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
9359}
9360
9361void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
9362 UErrorCode status = U_ZERO_ERROR;
9363
9364 DecimalFormat fmt("0.00", {"en", status}, status);
9365 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9366 fmt.setScientificNotation(TRUE);
9367 UnicodeString pattern;
9368
9369 assertEquals("A valid scientific notation pattern should be produced",
9370 "0.00E0",
9371 fmt.toPattern(pattern));
9372
9373 DecimalFormat fmt2(pattern, status);
9374 assertSuccess("", status);
9375}
9376
9377void NumberFormatTest::Test11649_DecFmtCurrencies() {
9378 IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
9379 UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
9380 pattern = pattern.unescape();
9381 DecimalFormat fmt(pattern, status);
9382 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9383 static const UChar USD[] = u"USD";
9384 fmt.setCurrency(USD);
9385 UnicodeString appendTo;
9386
9387 assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
9388 UnicodeString topattern;
9389
9390 assertEquals("", pattern, fmt.toPattern(topattern));
9391 DecimalFormat fmt2(topattern, status);
9392 fmt2.setCurrency(USD);
9393
9394 appendTo.remove();
9395 assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
9396}
9397
9398void NumberFormatTest::Test13148_ParseGroupingSeparators() {
9399 IcuTestErrorCode status(*this, "Test13148");
9400 LocalPointer<DecimalFormat> fmt(
9401 (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
9402 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9403
9404 DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
9405
9406 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
9407 symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
9408 fmt->setDecimalFormatSymbols(symbols);
9409 Formattable number;
9410 fmt->parse(u"300,000", number, status);
9411 assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
9412}
9413
9414void NumberFormatTest::Test12753_PatternDecimalPoint() {
9415 UErrorCode status = U_ZERO_ERROR;
9416 DecimalFormatSymbols symbols(Locale::getUS(), status);
9417 symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
9418 DecimalFormat df(u"0.00", symbols, status);
9419 if (!assertSuccess("", status)) return;
9420 df.setDecimalPatternMatchRequired(true);
9421 Formattable result;
9422 df.parse(u"123",result, status);
9423 assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
9424 U_INVALID_FORMAT_ERROR, status);
9425 }
9426
9427 void NumberFormatTest::Test11647_PatternCurrencySymbols() {
9428 UErrorCode status = U_ZERO_ERROR;
9429 DecimalFormat df(status);
9430 df.applyPattern(u"¤¤¤¤#", status);
9431 if (!assertSuccess("", status)) return;
9432 UnicodeString actual;
9433 df.format(123, actual);
9434 assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
9435}
9436
9437void NumberFormatTest::Test11913_BigDecimal() {
9438 UErrorCode status = U_ZERO_ERROR;
9439 LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
9440 if (!assertSuccess("", status)) return;
9441 UnicodeString result;
9442 df->format(StringPiece("1.23456789E400"), result, nullptr, status);
9443 assertSuccess("", status);
9444 assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
9445 assertEquals("Should format more than 309 digits", 534, result.length());
9446}
9447
9448void NumberFormatTest::Test11020_RoundingInScientificNotation() {
9449 UErrorCode status = U_ZERO_ERROR;
9450 DecimalFormatSymbols sym(Locale::getFrance(), status);
9451 DecimalFormat fmt(u"0.05E0", sym, status);
9452 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9453 assertSuccess("", status);
9454 UnicodeString result;
9455 fmt.format(12301.2, result);
9456 assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
9457}
9458
9459void NumberFormatTest::Test11640_TripleCurrencySymbol() {
9460 IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
9461 UnicodeString actual;
9462 DecimalFormat dFormat(u"¤¤¤ 0", status);
9463 if (U_FAILURE(status)) {
9464 dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
9465 return;
9466 }
9467 dFormat.setCurrency(u"USD");
9468 UnicodeString result;
9469 dFormat.getPositivePrefix(result);
9470 assertEquals("Triple-currency should give long name on getPositivePrefix",
9471 "US dollars ", result);
9472}
9473
9474
9475void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
9476 IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
9477 FieldPositionIterator fpi;
9478 UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
9479 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9480 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9481 nf->format(5142.3, result, &fpi, status);
9482
9483 int32_t expected[] = {
9484 UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
9485 UNUM_INTEGER_FIELD, 8, 13,
9486 UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
9487 UNUM_FRACTION_FIELD, 14, 15,
9488 };
9489 int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
9490 expectPositions(fpi, expected, tupleCount, result);
9491}
9492
9493void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
9494 IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
9495
9496 LocalPointer<NumberFormat> df(
9497 NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9498 if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
9499 expect2(*df, 1.5, u"1.50 US dollars");
9500}
9501
9502void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
9503 IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
9504
9505 DecimalFormatSymbols dfs("en", status);
9506 if (status.errIfFailureAndReset()) {
9507 return;
9508 }
9509 dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
9510 dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
9511 dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
9512 dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
9513 dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
9514 dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
9515 dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
9516 dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
9517 dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
9518 dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
9519 dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
9520 dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
9521 dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
9522 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
9523 dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
9524 dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
9525 dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
9526 dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
9527 dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
9528 dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
9529 dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
9530 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
9531 dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
9532 dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
9533 dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
9534 dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
9535
9536 DecimalFormat df("0", dfs, status);
9537 if (status.errIfFailureAndReset()) {
9538 return;
9539 }
9540 df.setGroupingUsed(TRUE);
9541 df.setScientificNotation(TRUE);
9542 df.setLenient(TRUE); // enable all matchers
9543 {
9544 UnicodeString result;
9545 df.format(0, result); // should not crash or hit infinite loop
9546 }
9547 const char16_t* samples[] = {
9548 u"",
9549 u"123",
9550 u"$123",
9551 u"-",
9552 u"+",
9553 u"44%",
9554 u"1E+2.3"
9555 };
9556 for (auto& sample : samples) {
9557 logln(UnicodeString(u"Attempting parse on: ") + sample);
9558 status.setScope(sample);
9559 // We don't care about the results, only that we don't crash and don't loop.
9560 Formattable result;
9561 ParsePosition ppos(0);
9562 df.parse(sample, result, ppos);
9563 ppos = ParsePosition(0);
9564 LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
9565 status.errIfFailureAndReset();
9566 }
9567
9568 // Test with a nonempty exponent separator symbol to cover more code
9569 dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
9570 df.setDecimalFormatSymbols(dfs);
9571 {
9572 Formattable result;
9573 ParsePosition ppos(0);
9574 df.parse(u"1E+2.3", result, ppos);
9575 }
9576}
9577
9578void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
9579 IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");
9580
9581 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
9582 if (U_FAILURE(status)) {
9583 dataerrln("Unable to create NumberFormat instance.");
9584 return;
9585 }
9586 Formattable result;
9587
9588 // Test overflow of exponent
9589 nf->parse(u"1E-2147483648", result, status);
9590 StringPiece sp = result.getDecimalNumber(status);
9591 assertEquals(u"Should snap to zero",
9592 u"0",
9593 {sp.data(), sp.length(), US_INV});
9594
9595 // Test edge case overflow of exponent
9596 result = Formattable();
9597 nf->parse(u"1E-2147483647E-1", result, status);
9598 sp = result.getDecimalNumber(status);
9599 assertEquals(u"Should not overflow and should parse only the first exponent",
9600 u"1E-2147483647",
9601 {sp.data(), sp.length(), US_INV});
9602
9603 // Test edge case overflow of exponent
9604 result = Formattable();
9605 nf->parse(u".0003e-2147483644", result, status);
9606 sp = result.getDecimalNumber(status);
9607 assertEquals(u"Should not overflow",
9608 u"3E-2147483648",
9609 {sp.data(), sp.length(), US_INV});
9610
9611 // Test largest parseable exponent
9612 result = Formattable();
9613 nf->parse(u"9876e2147483643", result, status);
9614 sp = result.getDecimalNumber(status);
9615 assertEquals(u"Should not overflow",
9616 u"9.876E+2147483646",
9617 {sp.data(), sp.length(), US_INV});
9618
9619 // Test max value as well
9620 const char16_t* infinityInputs[] = {
9621 u"9876e2147483644",
9622 u"9876e2147483645",
9623 u"9876e2147483646",
9624 u"9876e2147483647",
9625 u"9876e2147483648",
9626 u"9876e2147483649",
9627 };
9628 for (const auto& input : infinityInputs) {
9629 result = Formattable();
9630 nf->parse(input, result, status);
9631 sp = result.getDecimalNumber(status);
9632 assertEquals(UnicodeString("Should become Infinity: ") + input,
9633 u"Infinity",
9634 {sp.data(), sp.length(), US_INV});
9635 }
9636}
9637
9638void NumberFormatTest::Test13840_ParseLongStringCrash() {
9639 IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
9640
9641 LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
9642 if (status.errIfFailureAndReset()) { return; }
9643
9644 Formattable result;
9645 static const char16_t* bigString =
9646 u"111111111111111111111111111111111111111111111111111111111111111111111"
9647 u"111111111111111111111111111111111111111111111111111111111111111111111"
9648 u"111111111111111111111111111111111111111111111111111111111111111111111"
9649 u"111111111111111111111111111111111111111111111111111111111111111111111"
9650 u"111111111111111111111111111111111111111111111111111111111111111111111"
9651 u"111111111111111111111111111111111111111111111111111111111111111111111";
9652 nf->parse(bigString, result, status);
9653
9654 // Normalize the input string:
9655 CharString expectedChars;
9656 expectedChars.appendInvariantChars(bigString, status);
9657 DecimalQuantity expectedDQ;
9658 expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
9659 UnicodeString expectedUString = expectedDQ.toScientificString();
9660
9661 // Get the output string:
9662 StringPiece actualChars = result.getDecimalNumber(status);
9663 UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
9664
9665 assertEquals("Should round-trip without crashing", expectedUString, actualUString);
9666}
9667
9668void NumberFormatTest::Test13850_EmptyStringCurrency() {
9669 IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
9670
9671 struct TestCase {
9672 const char16_t* currencyArg;
9673 UErrorCode expectedError;
9674 } cases[] = {
9675 {u"", U_USING_FALLBACK_WARNING},
9676 {u"U", U_ILLEGAL_ARGUMENT_ERROR},
9677 {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
9678 {nullptr, U_USING_FALLBACK_WARNING},
9679 {u"U$D", U_INVARIANT_CONVERSION_ERROR},
9680 {u"Xxx", U_USING_FALLBACK_WARNING}
9681 };
9682 for (const auto& cas : cases) {
9683 UnicodeString message(u"with currency arg: ");
9684 if (cas.currencyArg == nullptr) {
9685 message += u"nullptr";
9686 } else {
9687 message += UnicodeString(cas.currencyArg);
9688 }
9689 status.setScope(message);
9690 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
9691 if (status.errIfFailureAndReset()) { return; }
9692 UnicodeString actual;
9693 nf->format(1, actual, status);
9694 status.errIfFailureAndReset();
9695 assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
9696 nf->setCurrency(cas.currencyArg, status);
9697 if (status.expectErrorAndReset(cas.expectedError)) {
9698 // If an error occurred, do not check formatting.
9699 continue;
9700 }
9701 nf->format(1, actual.remove(), status);
9702 assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
9703 status.errIfFailureAndReset();
9704 }
9705}
9706
9707void NumberFormatTest::Test20348_CurrencyPrefixOverride() {
9708 IcuTestErrorCode status(*this, "Test20348_CurrencyPrefixOverride");
9709 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9710 NumberFormat::createCurrencyInstance("en", status)));
9711 if (status.errIfFailureAndReset()) { return; }
9712 UnicodeString result;
9713 assertEquals("Initial pattern",
9714 u"¤#,##0.00", fmt->toPattern(result.remove()));
9715 assertEquals("Initial prefix",
9716 u"¤", fmt->getPositivePrefix(result.remove()));
9717 assertEquals("Initial suffix",
9718 u"-¤", fmt->getNegativePrefix(result.remove()));
9719 assertEquals("Initial format",
9720 u"\u00A4100.00", fmt->format(100, result.remove(), NULL, status));
9721
9722 fmt->setPositivePrefix(u"$");
9723 assertEquals("Set positive prefix pattern",
9724 u"$#,##0.00;-\u00A4#,##0.00", fmt->toPattern(result.remove()));
9725 assertEquals("Set positive prefix prefix",
9726 u"$", fmt->getPositivePrefix(result.remove()));
9727 assertEquals("Set positive prefix suffix",
9728 u"-¤", fmt->getNegativePrefix(result.remove()));
9729 assertEquals("Set positive prefix format",
9730 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9731
9732 fmt->setNegativePrefix(u"-$");
9733 assertEquals("Set negative prefix pattern",
9734 u"$#,##0.00;'-'$#,##0.00", fmt->toPattern(result.remove()));
9735 assertEquals("Set negative prefix prefix",
9736 u"$", fmt->getPositivePrefix(result.remove()));
9737 assertEquals("Set negative prefix suffix",
9738 u"-$", fmt->getNegativePrefix(result.remove()));
9739 assertEquals("Set negative prefix format",
9740 u"$100.00", fmt->format(100, result.remove(), NULL, status));
9741}
9742
9743void NumberFormatTest::Test20956_MonetarySymbolGetters() {
9744 IcuTestErrorCode status(*this, "Test20956_MonetarySymbolGetters");
9745 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9746 NumberFormat::createCurrencyInstance("et", status)));
9747 if (status.errDataIfFailureAndReset()) {
9748 return;
9749 }
9750
9751 decimalFormat->setCurrency(u"EEK");
9752
9753 const DecimalFormatSymbols* decimalFormatSymbols = decimalFormat->getDecimalFormatSymbols();
9754 assertEquals("MONETARY DECIMAL SEPARATOR",
9755 u".",
9756 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
9757 assertEquals("DECIMAL SEPARATOR",
9758 u",",
9759 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
9760 assertEquals("MONETARY GROUPING SEPARATOR",
9761 u" ",
9762 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
9763 assertEquals("GROUPING SEPARATOR",
9764 u" ",
9765 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
9766 assertEquals("CURRENCY SYMBOL",
9767 u"kr",
9768 decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
9769
9770 UnicodeString sb;
9771 decimalFormat->format(12345.12, sb, status);
9772 assertEquals("OUTPUT", u"12 345.12 kr", sb);
9773}
9774
9775void NumberFormatTest::Test20358_GroupingInPattern() {
9776 IcuTestErrorCode status(*this, "Test20358_GroupingInPattern");
9777 LocalPointer<DecimalFormat> fmt(static_cast<DecimalFormat*>(
9778 NumberFormat::createInstance("en", status)));
9779 if (status.errIfFailureAndReset()) { return; }
9780 UnicodeString result;
9781 assertEquals("Initial pattern",
9782 u"#,##0.###", fmt->toPattern(result.remove()));
9783 assertTrue("Initial grouping",
9784 fmt->isGroupingUsed());
9785 assertEquals("Initial format",
9786 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9787
9788 fmt->setGroupingUsed(false);
9789 assertEquals("Set grouping false",
9790 u"0.###", fmt->toPattern(result.remove()));
9791 assertFalse("Set grouping false grouping",
9792 fmt->isGroupingUsed());
9793 assertEquals("Set grouping false format",
9794 u"54321", fmt->format(54321, result.remove(), NULL, status));
9795
9796 fmt->setGroupingUsed(true);
9797 assertEquals("Set grouping true",
9798 u"#,##0.###", fmt->toPattern(result.remove()));
9799 assertTrue("Set grouping true grouping",
9800 fmt->isGroupingUsed());
9801 assertEquals("Set grouping true format",
9802 u"54,321", fmt->format(54321, result.remove(), NULL, status));
9803}
9804
9805void NumberFormatTest::Test13731_DefaultCurrency() {
9806 IcuTestErrorCode status(*this, "Test13731_DefaultCurrency");
9807 UnicodeString result;
9808 {
9809 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9810 "en", UNumberFormatStyle::UNUM_CURRENCY, status), status);
9811 if (status.errIfFailureAndReset()) { return; }
9812 assertEquals("symbol", u"¤1.10",
9813 nf->format(1.1, result.remove(), status));
9814 assertEquals("currency", u"XXX", nf->getCurrency());
9815 }
9816 {
9817 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9818 "en", UNumberFormatStyle::UNUM_CURRENCY_ISO, status), status);
9819 if (status.errIfFailureAndReset()) { return; }
9820 assertEquals("iso_code", u"XXX 1.10",
9821 nf->format(1.1, result.remove(), status));
9822 assertEquals("currency", u"XXX", nf->getCurrency());
9823 }
9824 {
9825 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9826 "en", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9827 if (status.errIfFailureAndReset()) { return; }
9828 assertEquals("plural", u"1.10 (unknown currency)",
9829 nf->format(1.1, result.remove(), status));
9830 assertEquals("currency", u"XXX", nf->getCurrency());
9831 }
9832}
9833
9834void NumberFormatTest::Test20499_CurrencyVisibleDigitsPlural() {
9835 IcuTestErrorCode status(*this, "Test20499_CurrencyVisibleDigitsPlural");
9836 LocalPointer<NumberFormat> nf(NumberFormat::createInstance(
9837 "ro-RO", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
9838 const char16_t* expected = u"24,00 lei românești";
9839 for (int32_t i=0; i<5; i++) {
9840 UnicodeString actual;
9841 nf->format(24, actual, status);
9842 assertEquals(UnicodeString(u"iteration ") + Int64ToUnicodeString(i),
9843 expected, actual);
9844 }
9845}
9846
9847void NumberFormatTest::Test13735_GroupingSizeGetter() {
9848 IcuTestErrorCode status(*this, "Test13735_GroupingSizeGetter");
9849 {
9850 DecimalFormat df("0", {"en", status}, status);
9851 assertEquals("pat 0: ", 0, df.getGroupingSize());
9852 df.setGroupingUsed(false);
9853 assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
9854 df.setGroupingUsed(true);
9855 assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
9856 }
9857 {
9858 DecimalFormat df("#,##0", {"en", status}, status);
9859 assertEquals("pat #,##0: ", 3, df.getGroupingSize());
9860 df.setGroupingUsed(false);
9861 assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
9862 df.setGroupingUsed(true);
9863 assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
9864 }
9865}
9866
9867void NumberFormatTest::Test13734_StrictFlexibleWhitespace() {
9868 IcuTestErrorCode status(*this, "Test13734_StrictFlexibleWhitespace");
9869 {
9870 DecimalFormat df("+0", {"en", status}, status);
9871 df.setLenient(FALSE);
9872 Formattable result;
9873 ParsePosition ppos;
9874 df.parse("+ 33", result, ppos);
9875 assertEquals("ppos : ", 0, ppos.getIndex());
9876 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9877 }
9878 {
9879 DecimalFormat df("+ 0", {"en", status}, status);
9880 df.setLenient(FALSE);
9881 Formattable result;
9882 ParsePosition ppos;
9883 df.parse("+ 33", result, ppos);
9884 assertEquals("ppos : ", 0, ppos.getIndex());
9885 assertEquals("result : ", "0", result.getDecimalNumber(status).data());
9886 }
9887}
9888
9889void NumberFormatTest::Test20961_CurrencyPluralPattern() {
9890 IcuTestErrorCode status(*this, "Test20961_CurrencyPluralPattern");
9891 {
9892 LocalPointer<DecimalFormat> decimalFormat(static_cast<DecimalFormat*>(
9893 NumberFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9894 if (status.errDataIfFailureAndReset()) {
9895 return;
9896 }
9897 UnicodeString result;
9898 decimalFormat->toPattern(result);
9899 assertEquals("Currency pattern", u"#,##0.00 ¤¤¤", result);
9900 }
9901}
9902
9903void NumberFormatTest::Test21134_ToNumberFormatter() {
9904 IcuTestErrorCode status(*this, "Test21134_ToNumberFormatter");
9905 LocalizedNumberFormatter outer1;
9906 LocalizedNumberFormatter outer2;
9907 LocalPointer<LocalizedNumberFormatter> outer3;
9908 {
9909 // Case 1: new formatter object
9910 DecimalFormat inner(u"a0b", {"en", status}, status);
9911 if (auto ptr = inner.toNumberFormatter(status)) {
9912 // Copy assignment
9913 outer1 = *ptr;
9914 } else {
9915 status.errIfFailureAndReset();
9916 return;
9917 }
9918 }
9919 {
9920 // Case 2: compiled formatter object (used at least 3 times)
9921 DecimalFormat inner(u"c0d", {"en", status}, status);
9922 UnicodeString dummy;
9923 inner.format(100, dummy);
9924 inner.format(100, dummy);
9925 inner.format(100, dummy);
9926 if (auto ptr = inner.toNumberFormatter(status)) {
9927 // Copy assignment
9928 outer2 = *ptr;
9929 } else {
9930 status.errIfFailureAndReset();
9931 return;
9932 }
9933 }
9934 {
9935 // Case 3: currency plural info (different code path)
9936 LocalPointer<DecimalFormat> inner(static_cast<DecimalFormat*>(
9937 DecimalFormat::createInstance("en-US", UNUM_CURRENCY_PLURAL, status)));
9938 if (auto ptr = inner->toNumberFormatter(status)) {
9939 // Copy constructor
9940 outer3.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(*ptr), status);
9941 } else {
9942 status.errIfFailureAndReset();
9943 return;
9944 }
9945 }
9946 auto result1 = outer1.formatDouble(99, status);
9947 assertEquals("Using NumberFormatter from DecimalFormat, new version",
9948 u"a99b",
9949 result1.toTempString(status));
9950 auto result2 = outer2.formatDouble(99, status);
9951 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9952 u"c99d",
9953 result2.toTempString(status));
9954 auto result3 = outer3->formatDouble(99, status);
9955 assertEquals("Using NumberFormatter from DecimalFormat, compiled version",
9956 u"99.00 US dollars",
9957 result3.toTempString(status));
9958}
9959
9960void NumberFormatTest::Test13733_StrictAndLenient() {
9961 IcuTestErrorCode status(*this, "Test13733_StrictAndLenient");
9962
9963 static const struct TestCase {
9964 const char16_t* inputString;
9965 const char16_t* patternString;
9966 int64_t expectedStrictParse;
9967 int64_t expectedLenientParse;
9968 } cases[] = { {u"CA$ 12", u"¤ 0", 12, 12},
9969 {u"CA$12", u"¤0", 12, 12},
9970 {u"CAD 12", u"¤¤ 0", 12, 12},
9971 {u"12 CAD", u"0 ¤¤", 12, 12},
9972 {u"12 Canadian dollars", u"0 ¤¤¤", 12, 12},
9973 {u"$12 ", u"¤¤¤¤0", 12, 12},
9974 {u"12$", u"0¤¤¤¤", 12, 12},
9975 {u"CA$ 12", u"¤0", 0, 12},
9976 {u"CA$ 12", u"0 ¤¤", 0, 12},
9977 {u"CA$ 12", u"0 ¤¤¤", 0, 12},
9978 {u"CA$ 12", u"¤¤¤¤0", 0, 12},
9979 {u"CA$ 12", u"0¤¤¤¤", 0, 12},
9980 {u"CA$12", u"¤ 0", 0, 12},
9981 {u"CA$12", u"¤¤ 0", 0, 12},
9982 {u"CA$12", u"0 ¤¤", 0, 12},
9983 {u"CA$12", u"0 ¤¤¤", 0, 12},
9984 {u"CA$12", u"0¤¤¤¤", 0, 12},
9985 {u"CAD 12", u"¤0", 0, 12},
9986 {u"CAD 12", u"0 ¤¤", 0, 12},
9987 {u"CAD 12", u"0 ¤¤¤", 0, 12},
9988 {u"CAD 12", u"¤¤¤¤0", 0, 12},
9989 {u"CAD 12", u"0¤¤¤¤", 0, 12},
9990 {u"12 CAD", u"¤ 0", 0, 12},
9991 {u"12 CAD", u"¤0", 0, 12},
9992 {u"12 CAD", u"¤¤ 0", 0, 12},
9993 {u"12 CAD", u"¤¤¤¤0", 0, 12},
9994 {u"12 CAD", u"0¤¤¤¤", 0, 12},
9995 {u"12 Canadian dollars", u"¤ 0", 0, 12},
9996 {u"12 Canadian dollars", u"¤0", 0, 12},
9997 {u"12 Canadian dollars", u"¤¤ 0", 0, 12},
9998 {u"12 Canadian dollars", u"¤¤¤¤0", 0, 12},
9999 {u"12 Canadian dollars", u"0¤¤¤¤", 0, 12},
10000 {u"$12 ", u"¤ 0", 0, 12},
10001 {u"$12 ", u"¤¤ 0", 0, 12},
10002 {u"$12 ", u"0 ¤¤", 0, 12},
10003 {u"$12 ", u"0 ¤¤¤", 0, 12},
10004 {u"$12 ", u"0¤¤¤¤", 0, 12},
10005 {u"12$", u"¤ 0", 0, 12},
10006 {u"12$", u"¤0", 0, 12},
10007 {u"12$", u"¤¤ 0", 0, 12},
10008 {u"12$", u"0 ¤¤", 0, 12},
10009 {u"12$", u"0 ¤¤¤", 0, 12},
10010 {u"12$", u"¤¤¤¤0", 0, 12} };
10011 for (auto& cas : cases) {
10012 UnicodeString inputString(cas.inputString);
10013 UnicodeString patternString(cas.patternString);
10014 int64_t parsedStrictValue = 0;
10015 int64_t parsedLenientValue = 0;
10016 ParsePosition ppos;
10017
10018 DecimalFormatSymbols dfs(Locale::getEnglish(), status);
10019 if (status.errDataIfFailureAndReset()) {
10020 return;
10021 }
10022 DecimalFormat df(patternString, dfs, status);
10023 if (status.errDataIfFailureAndReset()) {
10024 return;
10025 }
10026 df.setLenient(FALSE);
10027 LocalPointer<CurrencyAmount> ca_strict(df.parseCurrency(inputString, ppos));
10028 if (ca_strict != nullptr) {
10029 parsedStrictValue = ca_strict->getNumber().getInt64();
10030 }
10031 assertEquals("Strict parse of " + inputString + " using " + patternString,
10032 parsedStrictValue, cas.expectedStrictParse);
10033
10034 ppos.setIndex(0);
10035 df.setLenient(TRUE);
10036 LocalPointer<CurrencyAmount> ca_lenient(df.parseCurrency(inputString, ppos));
10037 Formattable parsedNumber_lenient = ca_lenient->getNumber();
10038 if (ca_lenient != nullptr) {
10039 parsedLenientValue = ca_lenient->getNumber().getInt64();
10040 }
10041 assertEquals("Lenient parse of " + inputString + " using " + patternString,
10042 parsedLenientValue, cas.expectedLenientParse);
10043 }
10044}
10045
10046void NumberFormatTest::Test20425_IntegerIncrement() {
10047 IcuTestErrorCode status(*this, "Test20425_IntegerIncrement");
10048
10049 DecimalFormat df("##00", status);
10050 df.setRoundingIncrement(1);
10051 UnicodeString actual;
10052 df.format(1235.5, actual, status);
10053 assertEquals("Should round to integer", u"1236", actual);
10054}
10055
10056void NumberFormatTest::Test20425_FractionWithIntegerIncrement() {
10057 IcuTestErrorCode status(*this, "Test20425_FractionWithIntegerIncrement");
10058
10059 DecimalFormat df("0.0", status);
10060 df.setRoundingIncrement(1);
10061 UnicodeString actual;
10062 df.format(8.6, actual, status);
10063 assertEquals("Should have a fraction digit", u"9.0", actual);
10064}
10065
10066void NumberFormatTest::Test21232_ParseTimeout() {
10067 IcuTestErrorCode status(*this, "Test21232_ParseTimeout");
10068
10069 DecimalFormat df(status);
10070 if (status.errDataIfFailureAndReset()) {
10071 return;
10072 }
10073
10074 UnicodeString input = u"4444444444444444444444444444444444444444";
10075 if (quick) {
10076 for (int32_t i = 0; i < 5; i++) {
10077 input.append(input);
10078 }
10079 assertEquals("Somewhat long input of digits", 1280, input.length());
10080 } else {
10081 for (int32_t i = 0; i < 12; i++) {
10082 input.append(input);
10083 }
10084 assertEquals("Very long input of digits", 163840, input.length());
10085 }
10086 Formattable result;
10087 df.parse(input, result, status);
10088 // Should not hang
10089}
10090
10091void NumberFormatTest::Test10997_FormatCurrency() {
10092 IcuTestErrorCode status(*this, "Test10997_FormatCurrency");
10093
10094 LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance(Locale::getUS(), status));
10095 if (status.errDataIfFailureAndReset()) {
10096 return;
10097 }
10098 fmt->setMinimumFractionDigits(4);
10099 fmt->setMaximumFractionDigits(4);
10100
10101 FieldPosition fp;
10102
10103 UnicodeString str;
10104 Formattable usdAmnt(new CurrencyAmount(123.45, u"USD", status));
10105 fmt->format(usdAmnt, str, fp, status);
10106 assertEquals("minFrac 4 should be respected in default currency", u"$123.4500", str);
10107
10108 UnicodeString str2;
10109 Formattable eurAmnt(new CurrencyAmount(123.45, u"EUR", status));
10110 fmt->format(eurAmnt, str2, fp, status);
10111 assertEquals("minFrac 4 should be respected in different currency", u"€123.4500", str2);
10112}
10113
10114void NumberFormatTest::Test21556_CurrencyAsDecimal() {
10115 IcuTestErrorCode status(*this, "Test21556_CurrencyAsDecimal");
10116
10117 {
10118 DecimalFormat df(u"a0¤00b", status);
10119 if (status.errDataIfFailureAndReset()) {
10120 return;
10121 }
10122 df.setCurrency(u"EUR", status);
10123 UnicodeString result;
10124 FieldPosition fp(UNUM_CURRENCY_FIELD);
10125 df.format(3.141, result, fp);
10126 assertEquals("Basic test: format", u"a3€14b", result);
10127 UnicodeString pattern;
10128 assertEquals("Basic test: toPattern", u"a0¤00b", df.toPattern(pattern));
10129 assertEquals("Basic test: field position begin", 2, fp.getBeginIndex());
10130 assertEquals("Basic test: field position end", 3, fp.getEndIndex());
10131 }
10132
10133 {
10134 LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-GB", status));
10135 DecimalFormat* df = static_cast<DecimalFormat*>(nf.getAlias());
10136 df->applyPattern(u"a0¤00b", status);
10137 UnicodeString result;
10138 FieldPosition fp(UNUM_CURRENCY_FIELD);
10139 df->format(3.141, result, fp);
10140 assertEquals("Via applyPattern: format", u"a3£14b", result);
10141 UnicodeString pattern;
10142 assertEquals("Via applyPattern: toPattern", u"a0¤00b", df->toPattern(pattern));
10143 assertEquals("Via applyPattern: field position begin", 2, fp.getBeginIndex());
10144 assertEquals("Via applyPattern: field position end", 3, fp.getEndIndex());
10145 }
10146}
10147
10148#endif /* #if !UCONFIG_NO_FORMATTING */