]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/cintltst/cnumtst.c
ICU-491.11.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cnumtst.c
CommitLineData
b75a7d8f
A
1/********************************************************************
2 * COPYRIGHT:
4388f060 3 * Copyright (c) 1997-2012, International Business Machines Corporation and
b75a7d8f
A
4 * others. All Rights Reserved.
5 ********************************************************************/
6/********************************************************************************
7*
8* File CNUMTST.C
9*
10* Madhu Katragadda Creation
11*
12* Modification History:
13*
14* Date Name Description
15* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
16* 07/15/99 helena Ported to HPUX 10/11 CC.
17*********************************************************************************
18*/
19
20/* C API TEST FOR NUMBER FORMAT */
21
22#include "unicode/utypes.h"
23
24#if !UCONFIG_NO_FORMATTING
25
26#include "unicode/uloc.h"
729e4ab9 27#include "unicode/umisc.h"
b75a7d8f
A
28#include "unicode/unum.h"
29#include "unicode/ustring.h"
729e4ab9 30
b75a7d8f
A
31#include "cintltst.h"
32#include "cnumtst.h"
33#include "cmemory.h"
374ca955 34#include "putilimp.h"
b75a7d8f
A
35
36#define LENGTH(arr) (sizeof(arr)/sizeof(arr[0]))
37
38void addNumForTest(TestNode** root);
46f4442e
A
39static void TestTextAttributeCrash(void);
40static void TestNBSPInPattern(void);
729e4ab9 41static void TestInt64Parse(void);
4388f060 42static void TestParseCurrency(void);
729e4ab9 43static void TestParseAltNum(void);
b75a7d8f 44
374ca955
A
45#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
46
b75a7d8f
A
47void addNumForTest(TestNode** root)
48{
374ca955 49 TESTCASE(TestNumberFormat);
46f4442e 50 TESTCASE(TestSpelloutNumberParse);
374ca955 51 TESTCASE(TestSignificantDigits);
729e4ab9 52 TESTCASE(TestSigDigRounding);
374ca955
A
53 TESTCASE(TestNumberFormatPadding);
54 TESTCASE(TestInt64Format);
55 TESTCASE(TestNonExistentCurrency);
73c04bcf 56 TESTCASE(TestCurrencyRegression);
46f4442e 57 TESTCASE(TestTextAttributeCrash);
374ca955 58 TESTCASE(TestRBNFFormat);
46f4442e 59 TESTCASE(TestNBSPInPattern);
729e4ab9
A
60 TESTCASE(TestInt64Parse);
61 TESTCASE(TestParseZero);
4388f060 62 TESTCASE(TestParseCurrency);
729e4ab9 63 TESTCASE(TestParseAltNum);
4388f060 64 TESTCASE(TestCloneWithRBNF);
b75a7d8f
A
65}
66
67/** copy src to dst with unicode-escapes for values < 0x20 and > 0x7e, null terminate if possible */
68static int32_t ustrToAstr(const UChar* src, int32_t srcLength, char* dst, int32_t dstLength) {
69 static const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
70
71 char *p = dst;
72 const char *e = p + dstLength;
73 if (srcLength < 0) {
74 const UChar* s = src;
75 while (*s) {
76 ++s;
77 }
78 srcLength = (int32_t)(s - src);
79 }
80 while (p < e && --srcLength >= 0) {
81 UChar c = *src++;
82 if (c == 0xd || c == 0xa || c == 0x9 || (c>= 0x20 && c <= 0x7e)) {
83 *p++ = (char) c & 0x7f;
84 } else if (e - p >= 6) {
85 *p++ = '\\';
86 *p++ = 'u';
87 *p++ = hex[(c >> 12) & 0xf];
88 *p++ = hex[(c >> 8) & 0xf];
89 *p++ = hex[(c >> 4) & 0xf];
90 *p++ = hex[c & 0xf];
91 } else {
92 break;
93 }
94 }
95 if (p < e) {
96 *p = 0;
97 }
98 return (int32_t)(p - dst);
99}
100
729e4ab9
A
101/* test Parse int 64 */
102
103static void TestInt64Parse()
104{
105
106 UErrorCode st = U_ZERO_ERROR;
107 UErrorCode* status = &st;
108
109 const char* st1 = "009223372036854775808";
110 const int size = 21;
111 UChar text[21];
112
113
114 UNumberFormat* nf;
115
116 int64_t a;
117
118 u_charsToUChars(st1, text, size);
119 nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, status);
120
121 if(U_FAILURE(*status))
122 {
123 log_data_err("Error in unum_open() %s \n", myErrorName(*status));
124 return;
125 }
126
127 log_verbose("About to test unum_parseInt64() with out of range number\n");
128
129 a = unum_parseInt64(nf, text, size, 0, status);
130
131
132 if(!U_FAILURE(*status))
133 {
134 log_err("Error in unum_parseInt64(): %s \n", myErrorName(*status));
135 }
136 else
137 {
138 log_verbose("unum_parseInt64() successful\n");
139 }
140
141 unum_close(nf);
142 return;
143}
144
b75a7d8f
A
145/* test Number Format API */
146static void TestNumberFormat()
147{
148 UChar *result=NULL;
149 UChar temp1[512];
150 UChar temp2[512];
151
152 UChar temp[5];
153
154 UChar prefix[5];
155 UChar suffix[5];
156 UChar symbol[20];
157 int32_t resultlength;
158 int32_t resultlengthneeded;
159 int32_t parsepos;
73c04bcf 160 double d1 = -1.0;
b75a7d8f
A
161 int32_t l1;
162 double d = -10456.37;
374ca955 163 double a = 1234.56, a1 = 1235.0;
b75a7d8f
A
164 int32_t l = 100000000;
165 UFieldPosition pos1;
166 UFieldPosition pos2;
167 int32_t numlocales;
168 int32_t i;
169
170 UNumberFormatAttribute attr;
171 UNumberFormatSymbol symType = UNUM_DECIMAL_SEPARATOR_SYMBOL;
172 int32_t newvalue;
173 UErrorCode status=U_ZERO_ERROR;
174 UNumberFormatStyle style= UNUM_DEFAULT;
175 UNumberFormat *pattern;
176 UNumberFormat *def, *fr, *cur_def, *cur_fr, *per_def, *per_fr,
177 *cur_frpattern, *myclone, *spellout_def;
178
179 /* Testing unum_open() with various Numberformat styles and locales*/
180 status = U_ZERO_ERROR;
181 log_verbose("Testing unum_open() with default style and locale\n");
182 def=unum_open(style, NULL,0,NULL, NULL,&status);
73c04bcf
A
183
184 /* Might as well pack it in now if we can't even get a default NumberFormat... */
b75a7d8f 185 if(U_FAILURE(status))
73c04bcf 186 {
729e4ab9 187 log_data_err("Error in creating default NumberFormat using unum_open(): %s (Are you missing data?)\n", myErrorName(status));
73c04bcf
A
188 return;
189 }
b75a7d8f
A
190
191 log_verbose("\nTesting unum_open() with french locale and default style(decimal)\n");
192 fr=unum_open(style,NULL,0, "fr_FR",NULL, &status);
193 if(U_FAILURE(status))
194 log_err("Error: could not create NumberFormat (french): %s\n", myErrorName(status));
195
196 log_verbose("\nTesting unum_open(currency,NULL,status)\n");
197 style=UNUM_CURRENCY;
198 /* Can't hardcode the result to assume the default locale is "en_US". */
199 cur_def=unum_open(style, NULL,0,"en_US", NULL, &status);
200 if(U_FAILURE(status))
201 log_err("Error: could not create NumberFormat using \n unum_open(currency, NULL, &status) %s\n",
202 myErrorName(status) );
203
204 log_verbose("\nTesting unum_open(currency, frenchlocale, status)\n");
205 cur_fr=unum_open(style,NULL,0, "fr_FR", NULL, &status);
206 if(U_FAILURE(status))
729e4ab9 207 log_err("Error: could not create NumberFormat using unum_open(currency, french, &status): %s\n",
b75a7d8f
A
208 myErrorName(status));
209
210 log_verbose("\nTesting unum_open(percent, NULL, status)\n");
211 style=UNUM_PERCENT;
212 per_def=unum_open(style,NULL,0, NULL,NULL, &status);
213 if(U_FAILURE(status))
214 log_err("Error: could not create NumberFormat using unum_open(percent, NULL, &status): %s\n", myErrorName(status));
215
216 log_verbose("\nTesting unum_open(percent,frenchlocale, status)\n");
217 per_fr=unum_open(style, NULL,0,"fr_FR", NULL,&status);
218 if(U_FAILURE(status))
219 log_err("Error: could not create NumberFormat using unum_open(percent, french, &status): %s\n", myErrorName(status));
220
221 log_verbose("\nTesting unum_open(spellout, NULL, status)");
222 style=UNUM_SPELLOUT;
223 spellout_def=unum_open(style, NULL, 0, "en_US", NULL, &status);
224 if(U_FAILURE(status))
225 log_err("Error: could not create NumberFormat using unum_open(spellout, NULL, &status): %s\n", myErrorName(status));
226
227 /* Testing unum_clone(..) */
228 log_verbose("\nTesting unum_clone(fmt, status)");
229 status = U_ZERO_ERROR;
230 myclone = unum_clone(def,&status);
231 if(U_FAILURE(status))
232 log_err("Error: could not clone unum_clone(def, &status): %s\n", myErrorName(status));
233 else
234 {
235 log_verbose("unum_clone() successful\n");
236 }
237
238 /*Testing unum_getAvailable() and unum_countAvailable()*/
239 log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
240 numlocales=unum_countAvailable();
241 if(numlocales < 0)
242 log_err("error in countAvailable");
243 else{
244 log_verbose("unum_countAvialable() successful\n");
245 log_verbose("The no: of locales where number formattting is applicable is %d\n", numlocales);
246 }
247 for(i=0;i<numlocales;i++)
248 {
249 log_verbose("%s\n", unum_getAvailable(i));
250 if (unum_getAvailable(i) == 0)
251 log_err("No locale for which number formatting patterns are applicable\n");
252 else
253 log_verbose("A locale %s for which number formatting patterns are applicable\n",unum_getAvailable(i));
254 }
255
256
257 /*Testing unum_format() and unum_formatdouble()*/
258 u_uastrcpy(temp1, "$100,000,000.00");
259
260 log_verbose("\nTesting unum_format() \n");
261 resultlength=0;
4388f060 262 pos1.field = UNUM_INTEGER_FIELD;
b75a7d8f
A
263 resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status);
264 if(status==U_BUFFER_OVERFLOW_ERROR)
265 {
266 status=U_ZERO_ERROR;
267 resultlength=resultlengthneeded+1;
268 result=(UChar*)malloc(sizeof(UChar) * resultlength);
269/* for (i = 0; i < 100000; i++) */
270 {
271 unum_format(cur_def, l, result, resultlength, &pos1, &status);
272 }
273 }
274
275 if(U_FAILURE(status))
276 {
277 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
278 }
279 if(u_strcmp(result, temp1)==0)
280 log_verbose("Pass: Number formatting using unum_format() successful\n");
281 else
282 log_err("Fail: Error in number Formatting using unum_format()\n");
283 if(pos1.beginIndex == 1 && pos1.endIndex == 12)
284 log_verbose("Pass: Complete number formatting using unum_format() successful\n");
285 else
286 log_err("Fail: Error in complete number Formatting using unum_format()\nGot: b=%d end=%d\nExpected: b=1 end=12\n",
287 pos1.beginIndex, pos1.endIndex);
288
289free(result);
290 result = 0;
291
292 log_verbose("\nTesting unum_formatDouble()\n");
293 u_uastrcpy(temp1, "($10,456.37)");
294 resultlength=0;
4388f060 295 pos2.field = UNUM_FRACTION_FIELD;
b75a7d8f
A
296 resultlengthneeded=unum_formatDouble(cur_def, d, NULL, resultlength, &pos2, &status);
297 if(status==U_BUFFER_OVERFLOW_ERROR)
298 {
299 status=U_ZERO_ERROR;
300 resultlength=resultlengthneeded+1;
301 result=(UChar*)malloc(sizeof(UChar) * resultlength);
302/* for (i = 0; i < 100000; i++) */
303 {
304 unum_formatDouble(cur_def, d, result, resultlength, &pos2, &status);
305 }
306 }
307 if(U_FAILURE(status))
308 {
309 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
310 }
73c04bcf 311 if(result && u_strcmp(result, temp1)==0)
b75a7d8f
A
312 log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
313 else
314 log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
315 if(pos2.beginIndex == 9 && pos2.endIndex == 11)
316 log_verbose("Pass: Complete number formatting using unum_format() successful\n");
317 else
318 log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=9 end=11",
319 pos1.beginIndex, pos1.endIndex);
320
321
322 /* Testing unum_parse() and unum_parseDouble() */
323 log_verbose("\nTesting unum_parseDouble()\n");
324/* for (i = 0; i < 100000; i++)*/
73c04bcf 325 if (result != NULL)
b75a7d8f
A
326 {
327 parsepos=0;
328 d1=unum_parseDouble(cur_def, result, u_strlen(result), &parsepos, &status);
329 }
73c04bcf
A
330 else {
331 log_err("result is NULL\n");
332 }
b75a7d8f
A
333 if(U_FAILURE(status))
334 {
335 log_err("parse failed. The error is : %s\n", myErrorName(status));
336 }
337
338 if(d1!=d)
339 log_err("Fail: Error in parsing\n");
340 else
341 log_verbose("Pass: parsing successful\n");
374ca955
A
342 if (result)
343 free(result);
344 result = 0;
345
346
347 /* Testing unum_formatDoubleCurrency / unum_parseDoubleCurrency */
348 log_verbose("\nTesting unum_formatDoubleCurrency\n");
349 u_uastrcpy(temp1, "Y1,235");
350 temp1[0] = 0xA5; /* Yen sign */
351 u_uastrcpy(temp, "JPY");
352 resultlength=0;
4388f060 353 pos2.field = UNUM_INTEGER_FIELD;
374ca955
A
354 resultlengthneeded=unum_formatDoubleCurrency(cur_def, a, temp, NULL, resultlength, &pos2, &status);
355 if (status==U_BUFFER_OVERFLOW_ERROR) {
356 status=U_ZERO_ERROR;
357 resultlength=resultlengthneeded+1;
358 result=(UChar*)malloc(sizeof(UChar) * resultlength);
359 unum_formatDoubleCurrency(cur_def, a, temp, result, resultlength, &pos2, &status);
360 }
361 if (U_FAILURE(status)) {
362 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
363 }
364 if (result && u_strcmp(result, temp1)==0) {
365 log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
366 } else {
367 log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
368 }
369 if (pos2.beginIndex == 1 && pos2.endIndex == 6) {
370 log_verbose("Pass: Complete number formatting using unum_format() successful\n");
371 } else {
73c04bcf 372 log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=1 end=6\n",
374ca955
A
373 pos1.beginIndex, pos1.endIndex);
374 }
375
376 log_verbose("\nTesting unum_parseDoubleCurrency\n");
377 parsepos=0;
73c04bcf
A
378 if (result == NULL) {
379 log_err("result is NULL\n");
374ca955 380 }
73c04bcf
A
381 else {
382 d1=unum_parseDoubleCurrency(cur_def, result, u_strlen(result), &parsepos, temp2, &status);
383 if (U_FAILURE(status)) {
384 log_err("parse failed. The error is : %s\n", myErrorName(status));
385 }
386 /* Note: a==1234.56, but on parse expect a1=1235.0 */
387 if (d1!=a1) {
388 log_err("Fail: Error in parsing currency, got %f, expected %f\n", d1, a1);
389 } else {
390 log_verbose("Pass: parsed currency ammount successfully\n");
391 }
392 if (u_strcmp(temp2, temp)==0) {
393 log_verbose("Pass: parsed correct currency\n");
394 } else {
395 log_err("Fail: parsed incorrect currency\n");
396 }
374ca955
A
397 }
398
399free(result);
400 result = 0;
401
b75a7d8f
A
402
403/* performance testing */
404 u_uastrcpy(temp1, "$462.12345");
405 resultlength=u_strlen(temp1);
406/* for (i = 0; i < 100000; i++) */
407 {
408 parsepos=0;
409 d1=unum_parseDouble(cur_def, temp1, resultlength, &parsepos, &status);
410 }
411 if(U_FAILURE(status))
412 {
413 log_err("parse failed. The error is : %s\n", myErrorName(status));
414 }
415
729e4ab9
A
416 /*
417 * Note: "for strict standard conformance all operations and constants are now supposed to be
418 evaluated in precision of long double". So, we assign a1 before comparing to a double. Bug #7932.
419 */
420 a1 = 462.12345;
421
422 if(d1!=a1)
b75a7d8f
A
423 log_err("Fail: Error in parsing\n");
424 else
425 log_verbose("Pass: parsing successful\n");
426
427free(result);
428
429 u_uastrcpy(temp1, "($10,456.3E1])");
430 parsepos=0;
431 d1=unum_parseDouble(cur_def, temp1, u_strlen(temp1), &parsepos, &status);
432 if(U_SUCCESS(status))
433 {
434 log_err("Error in unum_parseDouble(..., %s, ...): %s\n", temp1, myErrorName(status));
435 }
436
437
438 log_verbose("\nTesting unum_format()\n");
439 status=U_ZERO_ERROR;
440 resultlength=0;
441 parsepos=0;
442 resultlengthneeded=unum_format(per_fr, l, NULL, resultlength, &pos1, &status);
443 if(status==U_BUFFER_OVERFLOW_ERROR)
444 {
445 status=U_ZERO_ERROR;
446 resultlength=resultlengthneeded+1;
447 result=(UChar*)malloc(sizeof(UChar) * resultlength);
448/* for (i = 0; i < 100000; i++)*/
449 {
450 unum_format(per_fr, l, result, resultlength, &pos1, &status);
451 }
452 }
453 if(U_FAILURE(status))
454 {
455 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
456 }
457
458
459 log_verbose("\nTesting unum_parse()\n");
460/* for (i = 0; i < 100000; i++) */
461 {
462 parsepos=0;
463 l1=unum_parse(per_fr, result, u_strlen(result), &parsepos, &status);
464 }
465 if(U_FAILURE(status))
466 {
467 log_err("parse failed. The error is : %s\n", myErrorName(status));
468 }
469
470 if(l1!=l)
471 log_err("Fail: Error in parsing\n");
472 else
473 log_verbose("Pass: parsing successful\n");
474
475free(result);
476
477 /* create a number format using unum_openPattern(....)*/
478 log_verbose("\nTesting unum_openPattern()\n");
479 u_uastrcpy(temp1, "#,##0.0#;(#,##0.0#)");
480 pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status);
481 if(U_FAILURE(status))
482 {
483 log_err("error in unum_openPattern(): %s\n", myErrorName(status) );;
484 }
485 else
486 log_verbose("Pass: unum_openPattern() works fine\n");
487
488 /*test for unum_toPattern()*/
489 log_verbose("\nTesting unum_toPattern()\n");
490 resultlength=0;
491 resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status);
492 if(status==U_BUFFER_OVERFLOW_ERROR)
493 {
494 status=U_ZERO_ERROR;
495 resultlength=resultlengthneeded+1;
496 result=(UChar*)malloc(sizeof(UChar) * resultlength);
497 unum_toPattern(pattern, FALSE, result, resultlength, &status);
498 }
499 if(U_FAILURE(status))
500 {
501 log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status));
502 }
503 else
504 {
505 if(u_strcmp(result, temp1)!=0)
506 log_err("FAIL: Error in extracting the pattern using unum_toPattern()\n");
507 else
508 log_verbose("Pass: extracted the pattern correctly using unum_toPattern()\n");
509free(result);
510 }
511
512 /*Testing unum_getSymbols() and unum_setSymbols()*/
513 log_verbose("\nTesting unum_getSymbols and unum_setSymbols()\n");
514 /*when we try to change the symbols of french to default we need to apply the pattern as well to fetch correct results */
515 resultlength=0;
516 resultlengthneeded=unum_toPattern(cur_def, FALSE, NULL, resultlength, &status);
517 if(status==U_BUFFER_OVERFLOW_ERROR)
518 {
519 status=U_ZERO_ERROR;
520 resultlength=resultlengthneeded+1;
521 result=(UChar*)malloc(sizeof(UChar) * resultlength);
522 unum_toPattern(cur_def, FALSE, result, resultlength, &status);
523 }
524 if(U_FAILURE(status))
525 {
526 log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status));
527 }
528
529 status=U_ZERO_ERROR;
530 cur_frpattern=unum_open(UNUM_IGNORE,result, u_strlen(result), "fr_FR",NULL, &status);
531 if(U_FAILURE(status))
532 {
533 log_err("error in unum_openPattern(): %s\n", myErrorName(status));
534 }
535
536free(result);
537
538 /*getting the symbols of cur_def */
539 /*set the symbols of cur_frpattern to cur_def */
540 for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) {
541 status=U_ZERO_ERROR;
542 unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status);
543 unum_setSymbol(cur_frpattern, symType, temp1, -1, &status);
544 if(U_FAILURE(status))
545 {
546 log_err("Error in get/set symbols: %s\n", myErrorName(status));
547 }
548 }
549
550 /*format to check the result */
551 resultlength=0;
552 resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status);
553 if(status==U_BUFFER_OVERFLOW_ERROR)
554 {
555 status=U_ZERO_ERROR;
556 resultlength=resultlengthneeded+1;
557 result=(UChar*)malloc(sizeof(UChar) * resultlength);
558 unum_format(cur_def, l, result, resultlength, &pos1, &status);
559 }
560 if(U_FAILURE(status))
561 {
562 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
563 }
564
565 if(U_FAILURE(status)){
566 log_err("Fail: error in unum_setSymbols: %s\n", myErrorName(status));
567 }
568 unum_applyPattern(cur_frpattern, FALSE, result, u_strlen(result),NULL,NULL);
569
570 for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) {
571 status=U_ZERO_ERROR;
572 unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status);
573 unum_getSymbol(cur_frpattern, symType, temp2, sizeof(temp2), &status);
574 if(U_FAILURE(status) || u_strcmp(temp1, temp2) != 0)
575 {
576 log_err("Fail: error in getting symbols\n");
577 }
578 else
579 log_verbose("Pass: get and set symbols successful\n");
580 }
581
582 /*format and check with the previous result */
583
584 resultlength=0;
585 resultlengthneeded=unum_format(cur_frpattern, l, NULL, resultlength, &pos1, &status);
586 if(status==U_BUFFER_OVERFLOW_ERROR)
587 {
588 status=U_ZERO_ERROR;
589 resultlength=resultlengthneeded+1;
590 unum_format(cur_frpattern, l, temp1, resultlength, &pos1, &status);
591 }
592 if(U_FAILURE(status))
593 {
594 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
595 }
729e4ab9 596 /* TODO:
b75a7d8f
A
597 * This test fails because we have not called unum_applyPattern().
598 * Currently, such an applyPattern() does not exist on the C API, and
599 * we have jitterbug 411 for it.
600 * Since it is close to the 1.5 release, I (markus) am disabling this test just
601 * for this release (I added the test itself only last week).
602 * For the next release, we need to fix this.
603 * Then, remove the uprv_strcmp("1.5", ...) and this comment, and the include "cstring.h" at the beginning of this file.
604 */
605 if(u_strcmp(result, temp1) != 0) {
606 log_err("Formatting failed after setting symbols. result=%s temp1=%s\n", result, temp1);
607 }
608
609
610 /*----------- */
611
612free(result);
613
614 /* Testing unum_get/setSymbol() */
615 for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) {
616 symbol[0] = (UChar)(0x41 + i);
617 symbol[1] = (UChar)(0x61 + i);
618 unum_setSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, 2, &status);
619 if(U_FAILURE(status)) {
620 log_err("Error from unum_setSymbol(%d): %s\n", i, myErrorName(status));
621 return;
622 }
623 }
624 for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) {
625 resultlength = unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status);
626 if(U_FAILURE(status)) {
627 log_err("Error from unum_getSymbol(%d): %s\n", i, myErrorName(status));
628 return;
629 }
630 if(resultlength != 2 || symbol[0] != 0x41 + i || symbol[1] != 0x61 + i) {
631 log_err("Failure in unum_getSymbol(%d): got unexpected symbol\n", i);
632 }
633 }
634 /*try getting from a bogus symbol*/
635 unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status);
636 if(U_SUCCESS(status)){
637 log_err("Error : Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol");
638 }
639 if(U_FAILURE(status)){
640 if(status != U_ILLEGAL_ARGUMENT_ERROR){
641 log_err("Error: Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol, Got %s\n", myErrorName(status));
642 }
643 }
644 status=U_ZERO_ERROR;
645
646 /* Testing unum_getTextAttribute() and unum_setTextAttribute()*/
647 log_verbose("\nTesting getting and setting text attributes\n");
648 resultlength=5;
649 unum_getTextAttribute(cur_fr, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status);
650 if(U_FAILURE(status))
651 {
652 log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
653 }
654 unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status);
655 if(U_FAILURE(status))
656 {
657 log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
658 }
659 unum_getTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, suffix, resultlength, &status);
660 if(U_FAILURE(status))
661 {
662 log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
663 }
664 if(u_strcmp(suffix,temp)!=0)
665 log_err("Fail:Error in setTextAttribute or getTextAttribute in setting and getting suffix\n");
666 else
667 log_verbose("Pass: setting and getting suffix works fine\n");
668 /*set it back to normal */
669 u_uastrcpy(temp,"$");
670 unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status);
671
672 /*checking some more text setter conditions */
673 u_uastrcpy(prefix, "+");
674 unum_setTextAttribute(def, UNUM_POSITIVE_PREFIX, prefix, u_strlen(prefix) , &status);
675 if(U_FAILURE(status))
676 {
677 log_err("error in setting the text attributes : %s\n", myErrorName(status));
678 }
679 unum_getTextAttribute(def, UNUM_POSITIVE_PREFIX, temp, resultlength, &status);
680 if(U_FAILURE(status))
681 {
682 log_err("error in getting the text attributes : %s\n", myErrorName(status));
683 }
684
729e4ab9 685 if(u_strcmp(prefix, temp)!=0)
b75a7d8f
A
686 log_err("ERROR: get and setTextAttributes with positive prefix failed\n");
687 else
688 log_verbose("Pass: get and setTextAttributes with positive prefix works fine\n");
689
690 u_uastrcpy(prefix, "+");
691 unum_setTextAttribute(def, UNUM_NEGATIVE_PREFIX, prefix, u_strlen(prefix), &status);
692 if(U_FAILURE(status))
693 {
694 log_err("error in setting the text attributes : %s\n", myErrorName(status));
695 }
696 unum_getTextAttribute(def, UNUM_NEGATIVE_PREFIX, temp, resultlength, &status);
697 if(U_FAILURE(status))
698 {
699 log_err("error in getting the text attributes : %s\n", myErrorName(status));
700 }
729e4ab9 701 if(u_strcmp(prefix, temp)!=0)
b75a7d8f
A
702 log_err("ERROR: get and setTextAttributes with negative prefix failed\n");
703 else
704 log_verbose("Pass: get and setTextAttributes with negative prefix works fine\n");
705
706 u_uastrcpy(suffix, "+");
707 unum_setTextAttribute(def, UNUM_NEGATIVE_SUFFIX, suffix, u_strlen(suffix) , &status);
708 if(U_FAILURE(status))
709 {
710 log_err("error in setting the text attributes: %s\n", myErrorName(status));
711 }
712
713 unum_getTextAttribute(def, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status);
714 if(U_FAILURE(status))
715 {
716 log_err("error in getting the text attributes : %s\n", myErrorName(status));
717 }
729e4ab9 718 if(u_strcmp(suffix, temp)!=0)
b75a7d8f
A
719 log_err("ERROR: get and setTextAttributes with negative suffix failed\n");
720 else
721 log_verbose("Pass: get and settextAttributes with negative suffix works fine\n");
722
723 u_uastrcpy(suffix, "++");
724 unum_setTextAttribute(def, UNUM_POSITIVE_SUFFIX, suffix, u_strlen(suffix) , &status);
725 if(U_FAILURE(status))
726 {
727 log_err("error in setting the text attributes: %s\n", myErrorName(status));
728 }
729
730 unum_getTextAttribute(def, UNUM_POSITIVE_SUFFIX, temp, resultlength, &status);
731 if(U_FAILURE(status))
732 {
733 log_err("error in getting the text attributes : %s\n", myErrorName(status));
734 }
729e4ab9 735 if(u_strcmp(suffix, temp)!=0)
b75a7d8f
A
736 log_err("ERROR: get and setTextAttributes with negative suffix failed\n");
737 else
738 log_verbose("Pass: get and settextAttributes with negative suffix works fine\n");
739
b75a7d8f
A
740 /*Testing unum_getAttribute and unum_setAttribute() */
741 log_verbose("\nTesting get and set Attributes\n");
742 attr=UNUM_GROUPING_SIZE;
743 newvalue=unum_getAttribute(def, attr);
744 newvalue=2;
745 unum_setAttribute(def, attr, newvalue);
746 if(unum_getAttribute(def,attr)!=2)
747 log_err("Fail: error in setting and getting attributes for UNUM_GROUPING_SIZE\n");
748 else
749 log_verbose("Pass: setting and getting attributes for UNUM_GROUPING_SIZE works fine\n");
750
751 attr=UNUM_MULTIPLIER;
752 newvalue=unum_getAttribute(def, attr);
753 newvalue=8;
754 unum_setAttribute(def, attr, newvalue);
755 if(unum_getAttribute(def,attr) != 8)
756 log_err("error in setting and getting attributes for UNUM_MULTIPLIER\n");
757 else
758 log_verbose("Pass:setting and getting attributes for UNUM_MULTIPLIER works fine\n");
759
374ca955
A
760 attr=UNUM_SECONDARY_GROUPING_SIZE;
761 newvalue=unum_getAttribute(def, attr);
762 newvalue=2;
763 unum_setAttribute(def, attr, newvalue);
764 if(unum_getAttribute(def,attr) != 2)
765 log_err("error in setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE\n");
766 else
767 log_verbose("Pass:setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE works fine\n");
768
b75a7d8f
A
769 /*testing set and get Attributes extensively */
770 log_verbose("\nTesting get and set attributes extensively\n");
771 for(attr=UNUM_PARSE_INT_ONLY; attr<= UNUM_PADDING_POSITION; attr=(UNumberFormatAttribute)((int32_t)attr + 1) )
772 {
773 newvalue=unum_getAttribute(fr, attr);
774 unum_setAttribute(def, attr, newvalue);
775 if(unum_getAttribute(def,attr)!=unum_getAttribute(fr, attr))
776 log_err("error in setting and getting attributes\n");
777 else
778 log_verbose("Pass: attributes set and retrieved successfully\n");
779 }
780
781 /*testing spellout format to make sure we can use it successfully.*/
782 log_verbose("\nTesting spellout format\n");
783 if (spellout_def)
784 {
785 static const int32_t values[] = { 0, -5, 105, 1005, 105050 };
786 for (i = 0; i < LENGTH(values); ++i) {
787 UChar buffer[128];
788 int32_t len;
789 int32_t value = values[i];
790 status = U_ZERO_ERROR;
791 len = unum_format(spellout_def, value, buffer, LENGTH(buffer), NULL, &status);
792 if(U_FAILURE(status)) {
793 log_err("Error in formatting using unum_format(spellout_fmt, ...): %s\n", myErrorName(status));
794 } else {
795 int32_t pp = 0;
796 int32_t parseResult;
797 char logbuf[256];
798 ustrToAstr(buffer, len, logbuf, LENGTH(logbuf));
799 log_verbose("formatted %d as '%s', length: %d\n", value, logbuf, len);
800
801 parseResult = unum_parse(spellout_def, buffer, len, &pp, &status);
802 if (U_FAILURE(status)) {
803 log_err("Error in parsing using unum_format(spellout_fmt, ...): %s\n", myErrorName(status));
804 } else if (parseResult != value) {
805 log_err("unum_format result %d != value %d\n", parseResult, value);
806 }
807 }
808 }
809 }
810 else {
811 log_err("Spellout format is unavailable\n");
812 }
813
729e4ab9
A
814 { /* Test for ticket #7079 */
815 UNumberFormat* dec_en;
816 UChar groupingSep[] = { 0 };
817 UChar numPercent[] = { 0x0031, 0x0032, 0x0025, 0 }; /* "12%" */
818 double parseResult = 0.0;
819
820 status=U_ZERO_ERROR;
821 dec_en = unum_open(UNUM_DECIMAL, NULL, 0, "en_US", NULL, &status);
822 unum_setAttribute(dec_en, UNUM_LENIENT_PARSE, 0);
823 unum_setSymbol(dec_en, UNUM_GROUPING_SEPARATOR_SYMBOL, groupingSep, 0, &status);
824 parseResult = unum_parseDouble(dec_en, numPercent, -1, NULL, &status);
825 /* Without the fix in #7079, the above call will hang */
826 if ( U_FAILURE(status) || parseResult != 12.0 ) {
827 log_err("unum_parseDouble with empty groupingSep: status %s, parseResult %f not 12.0\n",
828 myErrorName(status), parseResult);
829 } else {
830 log_verbose("unum_parseDouble with empty groupingSep: no hang, OK\n");
831 }
832 unum_close(dec_en);
833 }
834
835 { /* Test parse & format of big decimals. Use a number with too many digits to fit in a double,
836 to verify that it is taking the pure decimal path. */
837 UNumberFormat *fmt;
838 const char *bdpattern = "#,##0.#########";
839 const char *numInitial = "12345678900987654321.1234567896";
840 const char *numFormatted = "12,345,678,900,987,654,321.12345679";
841 const char *parseExpected = "12345678900987654321.12345679";
842 int32_t resultSize = 0;
843 int32_t parsePos = 0; /* Output parameter for Parse operations. */
844 #define DESTCAPACITY 100
845 UChar dest[DESTCAPACITY];
846 char desta[DESTCAPACITY];
847 UFieldPosition fieldPos = {0};
848
849 /* Format */
850
851 status = U_ZERO_ERROR;
852 u_uastrcpy(dest, bdpattern);
853 fmt = unum_open(UNUM_PATTERN_DECIMAL, dest, -1, "en", NULL /*parseError*/, &status);
854 if (U_FAILURE(status)) log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
855
856 resultSize = unum_formatDecimal(fmt, numInitial, -1, dest, DESTCAPACITY, NULL, &status);
857 if (U_FAILURE(status)) {
858 log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
859 }
860 u_austrncpy(desta, dest, DESTCAPACITY);
861 if (strcmp(numFormatted, desta) != 0) {
862 log_err("File %s, Line %d, (expected, acutal) = (\"%s\", \"%s\")\n",
863 __FILE__, __LINE__, numFormatted, desta);
864 }
865 if (strlen(numFormatted) != resultSize) {
866 log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n",
867 __FILE__, __LINE__, strlen(numFormatted), resultSize);
868 }
869
870 /* Format with a FieldPosition parameter */
871
4388f060 872 fieldPos.field = UNUM_DECIMAL_SEPARATOR_FIELD;
729e4ab9
A
873 resultSize = unum_formatDecimal(fmt, numInitial, -1, dest, DESTCAPACITY, &fieldPos, &status);
874 if (U_FAILURE(status)) {
875 log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
876 }
877 u_austrncpy(desta, dest, DESTCAPACITY);
878 if (strcmp(numFormatted, desta) != 0) {
879 log_err("File %s, Line %d, (expected, acutal) = (\"%s\", \"%s\")\n",
880 __FILE__, __LINE__, numFormatted, desta);
881 }
882 if (fieldPos.beginIndex != 26) { /* index of "." in formatted number */
883 log_err("File %s, Line %d, (expected, acutal) = (%d, %d)\n",
884 __FILE__, __LINE__, 0, fieldPos.beginIndex);
885 }
886 if (fieldPos.endIndex != 27) {
887 log_err("File %s, Line %d, (expected, acutal) = (%d, %d)\n",
888 __FILE__, __LINE__, 0, fieldPos.endIndex);
889 }
890
891 /* Parse */
892
893 status = U_ZERO_ERROR;
894 u_uastrcpy(dest, numFormatted); /* Parse the expected output of the formatting test */
895 resultSize = unum_parseDecimal(fmt, dest, -1, NULL, desta, DESTCAPACITY, &status);
896 if (U_FAILURE(status)) {
897 log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
898 }
899 if (strcmp(parseExpected, desta) != 0) {
900 log_err("File %s, Line %d, (expected, actual) = (\"%s\", \"%s\")\n",
901 __FILE__, __LINE__, parseExpected, desta);
902 }
903 if (strlen(parseExpected) != resultSize) {
904 log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n",
905 __FILE__, __LINE__, strlen(parseExpected), resultSize);
906 }
907
908 /* Parse with a parsePos parameter */
909
910 status = U_ZERO_ERROR;
911 u_uastrcpy(dest, numFormatted); /* Parse the expected output of the formatting test */
912 parsePos = 3; /* 12,345,678,900,987,654,321.12345679 */
913 /* start parsing at the the third char */
914 resultSize = unum_parseDecimal(fmt, dest, -1, &parsePos, desta, DESTCAPACITY, &status);
915 if (U_FAILURE(status)) {
916 log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
917 }
918 if (strcmp(parseExpected+2, desta) != 0) { /* "345678900987654321.12345679" */
919 log_err("File %s, Line %d, (expected, actual) = (\"%s\", \"%s\")\n",
920 __FILE__, __LINE__, parseExpected+2, desta);
921 }
922 if (strlen(numFormatted) != parsePos) {
923 log_err("File %s, Line %d, parsePos (expected, actual) = (\"%d\", \"%d\")\n",
924 __FILE__, __LINE__, strlen(parseExpected), parsePos);
925 }
926
927 unum_close(fmt);
928 }
929
4388f060
A
930 status = U_ZERO_ERROR;
931 /* Test invalid symbol argument */
932 {
933 int32_t badsymbolLarge = UNUM_FORMAT_SYMBOL_COUNT + 1;
934 int32_t badsymbolSmall = -1;
935 UChar value[10];
936 int32_t valueLength = 10;
937 UNumberFormat *fmt = unum_open(UNUM_DEFAULT, NULL, 0, NULL, NULL, &status);
938 if (U_FAILURE(status)) {
939 log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
940 } else {
941 unum_getSymbol(fmt, (UNumberFormatSymbol)badsymbolLarge, NULL, 0, &status);
942 if (U_SUCCESS(status)) log_err("unum_getSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (> UNUM_FORMAT_SYMBOL_COUNT) argument\n");
943
944 status = U_ZERO_ERROR;
945 unum_getSymbol(fmt, (UNumberFormatSymbol)badsymbolSmall, NULL, 0, &status);
946 if (U_SUCCESS(status)) log_err("unum_getSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (less than 0) argument\n");
947
948 status = U_ZERO_ERROR;
949 unum_setSymbol(fmt, (UNumberFormatSymbol)badsymbolLarge, value, valueLength, &status);
950 if (U_SUCCESS(status)) log_err("unum_setSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (> UNUM_FORMAT_SYMBOL_COUNT) argument\n");
951
952 status = U_ZERO_ERROR;
953 unum_setSymbol(fmt, (UNumberFormatSymbol)badsymbolSmall, value, valueLength, &status);
954 if (U_SUCCESS(status)) log_err("unum_setSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (less than 0) argument\n");
955
956 unum_close(fmt);
957 }
958 }
959
729e4ab9 960
b75a7d8f
A
961 /*closing the NumberFormat() using unum_close(UNumberFormat*)")*/
962 unum_close(def);
963 unum_close(fr);
964 unum_close(cur_def);
965 unum_close(cur_fr);
966 unum_close(per_def);
967 unum_close(per_fr);
968 unum_close(spellout_def);
969 unum_close(pattern);
970 unum_close(cur_frpattern);
971 unum_close(myclone);
972
973}
974
729e4ab9
A
975static void TestParseZero(void)
976{
977 UErrorCode errorCode = U_ZERO_ERROR;
4388f060
A
978 UChar input[] = {0x30, 0}; /* Input text is decimal '0' */
979 UChar pat[] = {0x0023,0x003b,0x0023,0}; /* {'#', ';', '#', 0}; */
729e4ab9
A
980 double dbl;
981
982#if 0
983 UNumberFormat* unum = unum_open( UNUM_DECIMAL /*or UNUM_DEFAULT*/, NULL, -1, NULL, NULL, &errorCode);
984#else
985 UNumberFormat* unum = unum_open( UNUM_PATTERN_DECIMAL /*needs pattern*/, pat, -1, NULL, NULL, &errorCode);
986#endif
987
988 dbl = unum_parseDouble( unum, input, -1 /*u_strlen(input)*/, 0 /* 0 = start */, &errorCode );
989 if (U_FAILURE(errorCode)) {
4388f060 990 log_data_err("Result - %s\n", u_errorName(errorCode));
729e4ab9
A
991 } else {
992 log_verbose("Double: %f\n", dbl);
993 }
4388f060
A
994 unum_close(unum);
995}
996
997static const UChar dollars2Sym[] = { 0x24,0x32,0x2E,0x30,0x30,0 }; /* $2.00 */
998static const UChar dollars4Sym[] = { 0x24,0x34,0 }; /* $4 */
999static const UChar dollars9Sym[] = { 0x39,0xA0,0x24,0 }; /* 9 $ */
1000static const UChar pounds3Sym[] = { 0xA3,0x33,0x2E,0x30,0x30,0 }; /* [POUND]3.00 */
1001static const UChar pounds5Sym[] = { 0xA3,0x35,0 }; /* [POUND]5 */
1002static const UChar pounds7Sym[] = { 0x37,0xA0,0xA3,0 }; /* 7 [POUND] */
1003static const UChar euros4Sym[] = { 0x34,0x2C,0x30,0x30,0xA0,0x20AC,0 }; /* 4,00 [EURO] */
1004static const UChar euros6Sym[] = { 0x36,0xA0,0x20AC,0 }; /* 6 [EURO] */
1005static const UChar euros8Sym[] = { 0x20AC,0x38,0 }; /* [EURO]8 */
1006static const UChar dollars4PluEn[] = { 0x34,0x20,0x55,0x53,0x20,0x64,0x6F,0x6C,0x6C,0x61,0x72,0x73,0 }; /* 4 US dollars*/
1007static const UChar pounds5PluEn[] = { 0x35,0x20,0x42,0x72,0x69,0x74,0x69,0x73,0x68,0x20,0x70,0x6F,0x75,0x6E,0x64,0x73,0x20,0x73,0x74,0x65,0x72,0x6C,0x69,0x6E,0x67,0 }; /* 5 British pounds sterling */
1008static const UChar euros8PluEn[] = { 0x38,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 8 euros*/
1009static const UChar euros6PluFr[] = { 0x36,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 6 euros*/
1010
1011typedef struct {
1012 const char * locale;
1013 const char * descrip;
1014 const UChar * currStr;
1015 const UChar * plurStr;
1016 UErrorCode parsDoubExpectErr;
1017 int32_t parsDoubExpectPos;
1018 double parsDoubExpectVal;
1019 UErrorCode parsCurrExpectErr;
1020 int32_t parsCurrExpectPos;
1021 double parsCurrExpectVal;
1022 const char * parsCurrExpectCurr;
1023} ParseCurrencyItem;
1024
1025static const ParseCurrencyItem parseCurrencyItems[] = {
1026 { "en_US", "dollars2", dollars2Sym, NULL, U_ZERO_ERROR, 5, 2.0, U_ZERO_ERROR, 5, 2.0, "USD" },
1027 { "en_US", "dollars4", dollars4Sym, dollars4PluEn, U_ZERO_ERROR, 2, 4.0, U_ZERO_ERROR, 2, 4.0, "USD" },
1028 { "en_US", "dollars9", dollars9Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
1029 { "en_US", "pounds3", pounds3Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 5, 3.0, "GBP" },
1030 { "en_US", "pounds5", pounds5Sym, pounds5PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 5.0, "GBP" },
1031 { "en_US", "pounds7", pounds7Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
1032 { "en_US", "euros8", euros8Sym, euros8PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 8.0, "EUR" },
1033
1034 { "en_GB", "pounds3", pounds3Sym, NULL, U_ZERO_ERROR, 5, 3.0, U_ZERO_ERROR, 5, 3.0, "GBP" },
1035 { "en_GB", "pounds5", pounds5Sym, pounds5PluEn, U_ZERO_ERROR, 2, 5.0, U_ZERO_ERROR, 2, 5.0, "GBP" },
1036 { "en_GB", "pounds7", pounds7Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
1037 { "en_GB", "euros4", euros4Sym, NULL, U_PARSE_ERROR, 4, 0.0, U_PARSE_ERROR, 4, 0.0, "" },
1038 { "en_GB", "euros6", euros6Sym, NULL, U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, "" },
1039 { "en_GB", "euros8", euros8Sym, euros8PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 8.0, "EUR" },
1040 { "en_GB", "dollars4", dollars4Sym, dollars4PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR, 2, 4.0, "USD" },
1041
1042 { "fr_FR", "euros4", euros4Sym, NULL, U_ZERO_ERROR, 6, 4.0, U_ZERO_ERROR, 6, 4.0, "EUR" },
1043 { "fr_FR", "euros6", euros6Sym, euros6PluFr, U_ZERO_ERROR, 3, 6.0, U_ZERO_ERROR, 3, 6.0, "EUR" },
1044 { "fr_FR", "euros8", euros8Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, "" },
1045 { "fr_FR", "dollars2", dollars2Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, "" },
1046 { "fr_FR", "dollars4", dollars4Sym, NULL, U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, "" },
1047
1048 { NULL, NULL, NULL, NULL, 0, 0, 0.0, 0, 0, 0.0, NULL }
1049};
1050
1051static void TestParseCurrency()
1052{
1053 const ParseCurrencyItem * itemPtr;
1054 for (itemPtr = parseCurrencyItems; itemPtr->locale != NULL; ++itemPtr) {
1055 UNumberFormat* unum;
1056 UErrorCode status;
1057 double parseVal;
1058 int32_t parsePos;
1059 UChar parseCurr[4];
1060 char parseCurrB[4];
1061
1062 status = U_ZERO_ERROR;
1063 unum = unum_open(UNUM_CURRENCY, NULL, 0, itemPtr->locale, NULL, &status);
1064 if (U_SUCCESS(status)) {
1065 status = U_ZERO_ERROR;
1066 parsePos = 0;
1067 parseVal = unum_parseDouble(unum, itemPtr->currStr, -1, &parsePos, &status);
1068 if (status != itemPtr->parsDoubExpectErr || parsePos != itemPtr->parsDoubExpectPos || parseVal != itemPtr->parsDoubExpectVal) {
1069 log_err("UNUM_CURRENCY parseDouble %s/%s, expect %s pos %d val %.1f, get %s pos %d val %.1f\n",
1070 itemPtr->locale, itemPtr->descrip,
1071 u_errorName(itemPtr->parsDoubExpectErr), itemPtr->parsDoubExpectPos, itemPtr->parsDoubExpectVal,
1072 u_errorName(status), parsePos, parseVal );
1073 }
1074 status = U_ZERO_ERROR;
1075 parsePos = 0;
1076 parseCurr[0] = 0;
1077 parseVal = unum_parseDoubleCurrency(unum, itemPtr->currStr, -1, &parsePos, parseCurr, &status);
1078 u_austrncpy(parseCurrB, parseCurr, 4);
1079 if (status != itemPtr->parsCurrExpectErr || parsePos != itemPtr->parsCurrExpectPos || parseVal != itemPtr->parsCurrExpectVal ||
1080 strncmp(parseCurrB, itemPtr->parsCurrExpectCurr, 4) != 0) {
1081 log_err("UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s pos %d val %.1f cur %s, get %s pos %d val %.1f cur %s\n",
1082 itemPtr->locale, itemPtr->descrip,
1083 u_errorName(itemPtr->parsCurrExpectErr), itemPtr->parsCurrExpectPos, itemPtr->parsCurrExpectVal, itemPtr->parsCurrExpectCurr,
1084 u_errorName(status), parsePos, parseVal, parseCurrB );
1085 }
1086 unum_close(unum);
1087 } else {
1088 log_data_err("unexpected error in unum_open UNUM_CURRENCY for locale %s: '%s'\n", itemPtr->locale, u_errorName(status));
1089 }
1090
1091#if 0
1092 /* Hmm, for UNUM_CURRENCY_PLURAL, currently unum_open always sets U_UNSUPPORTED_ERROR, save this test until it is supported */
1093 if (itemPtr->plurStr != NULL) {
1094 status = U_ZERO_ERROR;
1095 unum = unum_open(UNUM_CURRENCY_PLURAL, NULL, 0, itemPtr->locale, NULL, &status);
1096 if (U_SUCCESS(status)) {
1097 status = U_ZERO_ERROR;
1098 parsePos = 0;
1099 parseVal = unum_parseDouble(unum, itemPtr->plurStr, -1, &parsePos, &status);
1100 if (status != itemPtr->parsDoubExpectErr || parseVal != itemPtr->parsDoubExpectVal) {
1101 log_err("UNUM_CURRENCY parseDouble %s/%s, expect %s val %.1f, get %s val %.1f\n",
1102 itemPtr->locale, itemPtr->descrip,
1103 u_errorName(itemPtr->parsDoubExpectErr), itemPtr->parsDoubExpectVal,
1104 u_errorName(status), parseVal );
1105 }
1106 status = U_ZERO_ERROR;
1107 parsePos = 0;
1108 parseCurr[0] = 0;
1109 parseVal = unum_parseDoubleCurrency(unum, itemPtr->plurStr, -1, &parsePos, parseCurr, &status);
1110 u_austrncpy(parseCurrB, parseCurr, 4);
1111 if (status != itemPtr->parsCurrExpectErr || parseVal != itemPtr->parsCurrExpectVal ||
1112 strncmp(parseCurrB, itemPtr->parsCurrExpectCurr, 4) != 0) {
1113 log_err("UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s val %.1f cur %s, get %s val %.1f cur %s\n",
1114 itemPtr->locale, itemPtr->descrip,
1115 u_errorName(itemPtr->parsCurrExpectErr), itemPtr->parsCurrExpectVal, itemPtr->parsCurrExpectCurr,
1116 u_errorName(status), parseVal, parseCurrB );
1117 }
1118 unum_close(unum);
1119 } else {
1120 log_data_err("unexpected error in unum_open UNUM_CURRENCY_PLURAL for locale %s: '%s'\n", itemPtr->locale, u_errorName(status));
1121 }
1122 }
1123#endif
1124 }
729e4ab9
A
1125}
1126
46f4442e
A
1127typedef struct {
1128 const char * testname;
1129 const char * locale;
729e4ab9 1130 UBool lenient;
46f4442e
A
1131 const UChar * source;
1132 int32_t startPos;
1133 int32_t value;
1134 int32_t endPos;
1135 UErrorCode status;
729e4ab9
A
1136} NumParseTestItem;
1137
1138static const UChar ustr_zh50d[] = {0x4E94, 0x3007, 0}; /* decimal 50 */
1139static const UChar ustr_zh05a[] = {0x96F6, 0x4E94, 0}; /* decimal-alt 05 */
1140static const UChar ustr_zh05d[] = {0x3007, 0x4E94, 0}; /* decimal 05 */
1141
1142static const NumParseTestItem altnumParseTests[] = {
1143 /* name loc lenent src start val end status */
1144 { "zh@hd,50dL","zh@numbers=hanidec", TRUE, ustr_zh50d, 0, 50, 2, U_ZERO_ERROR },
1145 { "zh@hd,05aL","zh@numbers=hanidec", TRUE, ustr_zh05a, 0, 5, 2, U_ZERO_ERROR },
1146 { "zh@hd,05dL","zh@numbers=hanidec", TRUE, ustr_zh05d, 0, 5, 2, U_ZERO_ERROR },
1147 { NULL, NULL, FALSE, NULL, 0, 0, 0, 0 } /* terminator */
1148};
1149
1150static void TestParseAltNum(void)
1151{
1152 const NumParseTestItem * testPtr;
1153 for (testPtr = altnumParseTests; testPtr->testname != NULL; ++testPtr) {
1154 UErrorCode status = U_ZERO_ERROR;
1155 int32_t value, position = testPtr->startPos;
1156 UNumberFormat *nf = unum_open(UNUM_DECIMAL, NULL, 0, testPtr->locale, NULL, &status);
1157 if (U_FAILURE(status)) {
1158 log_err_status(status, "unum_open fails for UNUM_DECIMAL with locale %s, status %s\n", testPtr->locale, myErrorName(status));
1159 continue;
1160 }
1161 unum_setAttribute(nf, UNUM_LENIENT_PARSE, testPtr->lenient);
1162 value = unum_parse(nf, testPtr->source, -1, &position, &status);
1163 if ( value != testPtr->value || position != testPtr->endPos || status != testPtr->status ) {
1164 log_err("unum_parse DECIMAL, locale %s, testname %s, startPos %d: for value / endPos / status, expected %d / %d / %s, got %d / %d / %s\n",
1165 testPtr->locale, testPtr->testname, testPtr->startPos,
1166 testPtr->value, testPtr->endPos, myErrorName(testPtr->status),
1167 value, position, myErrorName(status) );
1168 }
1169 unum_close(nf);
1170 }
1171}
46f4442e
A
1172
1173static const UChar ustr_en0[] = {0x7A, 0x65, 0x72, 0x6F, 0}; /* zero */
1174static const UChar ustr_123[] = {0x31, 0x32, 0x33, 0}; /* 123 */
1175static const UChar ustr_en123[] = {0x6f, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
729e4ab9
A
1176 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79,
1177 0x2d, 0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* one hundred twenty-three */
1178static const UChar ustr_fr123[] = {0x63, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x69, 0x6e, 0x67, 0x74, 0x2d,
1179 0x74, 0x72, 0x6f, 0x69, 0x73, 0}; /* cent-vingt-trois */
46f4442e 1180static const UChar ustr_ja123[] = {0x767e, 0x4e8c, 0x5341, 0x4e09, 0}; /* kanji 100(+)2(*)10(+)3 */
729e4ab9
A
1181static const UChar ustr_zh50s[] = {0x4E94, 0x5341, 0}; /* spellout 50 */
1182//static const UChar ustr_zh50d[] = [reuse from above] /* decimal 50 */
1183//static const UChar ustr_zh05a[] = [reuse from above] /* decimal-alt 05 */
1184//static const UChar ustr_zh05d[] = [reuse from above] /* decimal 05 */
1185
1186#define NUMERIC_STRINGS_NOT_PARSEABLE 1 // ticket/8224
1187
1188static const NumParseTestItem spelloutParseTests[] = {
1189 /* name loc lenent src start val end status */
1190 { "en0", "en", FALSE, ustr_en0, 0, 0, 4, U_ZERO_ERROR },
1191 { "en0", "en", FALSE, ustr_en0, 2, 0, 2, U_PARSE_ERROR },
1192 { "en0", "ja", FALSE, ustr_en0, 0, 0, 0, U_PARSE_ERROR },
1193#if NUMERIC_STRINGS_NOT_PARSEABLE
1194 { "123", "en", FALSE, ustr_123, 0, 0, 0, U_PARSE_ERROR },
1195#else
1196 { "123", "en", FALSE, ustr_123, 0, 123, 3, U_ZERO_ERROR },
1197#endif
1198 { "123L", "en", TRUE, ustr_123, 0, 123, 3, U_ZERO_ERROR },
1199 { "en123", "en", FALSE, ustr_en123, 0, 123, 24, U_ZERO_ERROR },
1200 { "en123", "en", FALSE, ustr_en123, 12, 23, 24, U_ZERO_ERROR },
1201 { "en123", "fr", FALSE, ustr_en123, 16, 0, 16, U_PARSE_ERROR },
1202 { "fr123", "fr", FALSE, ustr_fr123, 0, 123, 16, U_ZERO_ERROR },
1203 { "fr123", "fr", FALSE, ustr_fr123, 5, 23, 16, U_ZERO_ERROR },
1204 { "fr123", "en", FALSE, ustr_fr123, 0, 0, 0, U_PARSE_ERROR },
1205 { "ja123", "ja", FALSE, ustr_ja123, 0, 123, 4, U_ZERO_ERROR },
1206 { "ja123", "ja", FALSE, ustr_ja123, 1, 23, 4, U_ZERO_ERROR },
1207 { "ja123", "fr", FALSE, ustr_ja123, 0, 0, 0, U_PARSE_ERROR },
1208 { "zh,50s", "zh", FALSE, ustr_zh50s, 0, 50, 2, U_ZERO_ERROR },
1209#if NUMERIC_STRINGS_NOT_PARSEABLE
1210 { "zh@hd,50d", "zh@numbers=hanidec", FALSE, ustr_zh50d, 0, 5, 1, U_ZERO_ERROR },
1211 { "zh@hd,05a", "zh@numbers=hanidec", FALSE, ustr_zh05a, 0, 0, 1, U_ZERO_ERROR },
1212 { "zh@hd,05d", "zh@numbers=hanidec", FALSE, ustr_zh05d, 0, 0, 1, U_ZERO_ERROR },
1213#else
1214 { "zh@hd,50d", "zh@numbers=hanidec", FALSE, ustr_zh50d, 0, 50, 2, U_ZERO_ERROR },
1215 { "zh@hd,05a", "zh@numbers=hanidec", FALSE, ustr_zh05a, 0, 5, 2, U_ZERO_ERROR },
1216 { "zh@hd,05d", "zh@numbers=hanidec", FALSE, ustr_zh05d, 0, 5, 2, U_ZERO_ERROR },
1217#endif
1218 { "zh@hd,50dL","zh@numbers=hanidec", TRUE, ustr_zh50d, 0, 50, 2, U_ZERO_ERROR },
1219 { "zh@hd,05aL","zh@numbers=hanidec", TRUE, ustr_zh05a, 0, 5, 2, U_ZERO_ERROR },
1220 { "zh@hd,05dL","zh@numbers=hanidec", TRUE, ustr_zh05d, 0, 5, 2, U_ZERO_ERROR },
1221 { "zh,50dL","zh", TRUE, ustr_zh50d, 0, 5, 1, U_ZERO_ERROR },
1222 { "zh,05aL","zh", TRUE, ustr_zh05a, 0, 0, 1, U_ZERO_ERROR },
1223 { "zh,05dL","zh", TRUE, ustr_zh05d, 0, 0, 1, U_ZERO_ERROR },
1224 { NULL, NULL, FALSE, NULL, 0, 0, 0, 0 } /* terminator */
46f4442e
A
1225};
1226
1227static void TestSpelloutNumberParse()
1228{
729e4ab9 1229 const NumParseTestItem * testPtr;
46f4442e
A
1230 for (testPtr = spelloutParseTests; testPtr->testname != NULL; ++testPtr) {
1231 UErrorCode status = U_ZERO_ERROR;
1232 int32_t value, position = testPtr->startPos;
1233 UNumberFormat *nf = unum_open(UNUM_SPELLOUT, NULL, 0, testPtr->locale, NULL, &status);
1234 if (U_FAILURE(status)) {
729e4ab9 1235 log_err_status(status, "unum_open fails for UNUM_SPELLOUT with locale %s, status %s\n", testPtr->locale, myErrorName(status));
46f4442e
A
1236 continue;
1237 }
729e4ab9 1238 unum_setAttribute(nf, UNUM_LENIENT_PARSE, testPtr->lenient);
46f4442e
A
1239 value = unum_parse(nf, testPtr->source, -1, &position, &status);
1240 if ( value != testPtr->value || position != testPtr->endPos || status != testPtr->status ) {
1241 log_err("unum_parse SPELLOUT, locale %s, testname %s, startPos %d: for value / endPos / status, expected %d / %d / %s, got %d / %d / %s\n",
1242 testPtr->locale, testPtr->testname, testPtr->startPos,
1243 testPtr->value, testPtr->endPos, myErrorName(testPtr->status),
1244 value, position, myErrorName(status) );
1245 }
1246 unum_close(nf);
1247 }
1248}
1249
374ca955
A
1250static void TestSignificantDigits()
1251{
1252 UChar temp[128];
1253 int32_t resultlengthneeded;
1254 int32_t resultlength;
1255 UErrorCode status = U_ZERO_ERROR;
1256 UChar *result = NULL;
1257 UNumberFormat* fmt;
1258 double d = 123456.789;
1259
1260 u_uastrcpy(temp, "###0.0#");
1261 fmt=unum_open(UNUM_IGNORE, temp, -1, NULL, NULL,&status);
1262 if (U_FAILURE(status)) {
4388f060 1263 log_data_err("got unexpected error for unum_open: '%s'\n", u_errorName(status));
46f4442e 1264 return;
374ca955
A
1265 }
1266 unum_setAttribute(fmt, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
1267 unum_setAttribute(fmt, UNUM_MAX_SIGNIFICANT_DIGITS, 6);
1268
1269 u_uastrcpy(temp, "123457");
1270 resultlength=0;
1271 resultlengthneeded=unum_formatDouble(fmt, d, NULL, resultlength, NULL, &status);
1272 if(status==U_BUFFER_OVERFLOW_ERROR)
1273 {
1274 status=U_ZERO_ERROR;
1275 resultlength=resultlengthneeded+1;
1276 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1277 unum_formatDouble(fmt, d, result, resultlength, NULL, &status);
1278 }
1279 if(U_FAILURE(status))
1280 {
1281 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
1282 return;
1283 }
1284 if(u_strcmp(result, temp)==0)
1285 log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
1286 else
1287 log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
1288 free(result);
1289 unum_close(fmt);
1290}
1291
729e4ab9
A
1292static void TestSigDigRounding()
1293{
1294 UErrorCode status = U_ZERO_ERROR;
1295 UChar expected[128];
1296 UChar result[128];
1297 char temp1[128];
1298 char temp2[128];
1299 UNumberFormat* fmt;
1300 double d = 123.4;
1301
1302 fmt=unum_open(UNUM_DECIMAL, NULL, 0, NULL /* "en_US"*/, NULL, &status);
1303 if (U_FAILURE(status)) {
1304 log_data_err("got unexpected error for unum_open: '%s'\n", u_errorName(status));
1305 return;
1306 }
1307 unum_setAttribute(fmt, UNUM_LENIENT_PARSE, FALSE);
1308 unum_setAttribute(fmt, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
1309 unum_setAttribute(fmt, UNUM_MAX_SIGNIFICANT_DIGITS, 2);
1310 /* unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 0); */
1311
1312 unum_setAttribute(fmt, UNUM_ROUNDING_MODE, UNUM_ROUND_UP);
1313 unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, 20.0);
1314
1315 (void)unum_formatDouble(fmt, d, result, sizeof(result) / sizeof(result[0]), NULL, &status);
1316 if(U_FAILURE(status))
1317 {
1318 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
1319 return;
1320 }
1321
1322 u_uastrcpy(expected, "140");
1323 if(u_strcmp(result, expected)!=0)
1324 log_err("FAIL: Error in unum_formatDouble result %s instead of %s\n", u_austrcpy(temp1, result), u_austrcpy(temp2, expected) );
1325
1326 unum_close(fmt);
1327}
1328
b75a7d8f
A
1329static void TestNumberFormatPadding()
1330{
1331 UChar *result=NULL;
1332 UChar temp1[512];
1333
1334 UErrorCode status=U_ZERO_ERROR;
1335 int32_t resultlength;
1336 int32_t resultlengthneeded;
1337 UNumberFormat *pattern;
1338 double d1;
1339 double d = -10456.37;
1340 UFieldPosition pos1;
1341 int32_t parsepos;
1342
1343 /* create a number format using unum_openPattern(....)*/
1344 log_verbose("\nTesting unum_openPattern() with padding\n");
1345 u_uastrcpy(temp1, "*#,##0.0#*;(#,##0.0#)");
1346 status=U_ZERO_ERROR;
1347 pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status);
1348 if(U_SUCCESS(status))
1349 {
729e4ab9 1350 log_err("error in unum_openPattern(%s): %s\n", temp1, myErrorName(status) );
b75a7d8f
A
1351 }
1352 else
1353 {
1354 unum_close(pattern);
1355 }
1356
1357/* u_uastrcpy(temp1, "*x#,###,###,##0.0#;(*x#,###,###,##0.0#)"); */
1358 u_uastrcpy(temp1, "*x#,###,###,##0.0#;*x(###,###,##0.0#)");
1359 status=U_ZERO_ERROR;
1360 pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), "en_US",NULL, &status);
1361 if(U_FAILURE(status))
1362 {
729e4ab9 1363 log_err_status(status, "error in padding unum_openPattern(%s): %s\n", temp1, myErrorName(status) );;
b75a7d8f
A
1364 }
1365 else {
1366 log_verbose("Pass: padding unum_openPattern() works fine\n");
1367
1368 /*test for unum_toPattern()*/
1369 log_verbose("\nTesting padding unum_toPattern()\n");
1370 resultlength=0;
1371 resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status);
1372 if(status==U_BUFFER_OVERFLOW_ERROR)
1373 {
1374 status=U_ZERO_ERROR;
1375 resultlength=resultlengthneeded+1;
1376 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1377 unum_toPattern(pattern, FALSE, result, resultlength, &status);
1378 }
1379 if(U_FAILURE(status))
1380 {
1381 log_err("error in extracting the padding pattern from UNumberFormat: %s\n", myErrorName(status));
1382 }
1383 else
1384 {
1385 if(u_strcmp(result, temp1)!=0)
1386 log_err("FAIL: Error in extracting the padding pattern using unum_toPattern()\n");
1387 else
1388 log_verbose("Pass: extracted the padding pattern correctly using unum_toPattern()\n");
1389free(result);
1390 }
1391/* u_uastrcpy(temp1, "(xxxxxxx10,456.37)"); */
1392 u_uastrcpy(temp1, "xxxxx(10,456.37)");
1393 resultlength=0;
4388f060 1394 pos1.field = UNUM_FRACTION_FIELD;
b75a7d8f
A
1395 resultlengthneeded=unum_formatDouble(pattern, d, NULL, resultlength, &pos1, &status);
1396 if(status==U_BUFFER_OVERFLOW_ERROR)
1397 {
1398 status=U_ZERO_ERROR;
1399 resultlength=resultlengthneeded+1;
1400 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1401 unum_formatDouble(pattern, d, result, resultlength, NULL, &status);
1402 }
1403 if(U_FAILURE(status))
1404 {
1405 log_err("Error in formatting using unum_formatDouble(.....) with padding : %s\n", myErrorName(status));
1406 }
1407 else
1408 {
1409 if(u_strcmp(result, temp1)==0)
1410 log_verbose("Pass: Number Formatting using unum_formatDouble() padding Successful\n");
1411 else
729e4ab9 1412 log_data_err("FAIL: Error in number formatting using unum_formatDouble() with padding\n");
b75a7d8f
A
1413 if(pos1.beginIndex == 13 && pos1.endIndex == 15)
1414 log_verbose("Pass: Complete number formatting using unum_formatDouble() successful\n");
1415 else
1416 log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=13 end=15\n",
1417 pos1.beginIndex, pos1.endIndex);
1418
1419
1420 /* Testing unum_parse() and unum_parseDouble() */
1421 log_verbose("\nTesting padding unum_parseDouble()\n");
1422 parsepos=0;
1423 d1=unum_parseDouble(pattern, result, u_strlen(result), &parsepos, &status);
1424 if(U_FAILURE(status))
1425 {
1426 log_err("padding parse failed. The error is : %s\n", myErrorName(status));
1427 }
1428
1429 if(d1!=d)
1430 log_err("Fail: Error in padding parsing\n");
1431 else
1432 log_verbose("Pass: padding parsing successful\n");
1433free(result);
1434 }
1435 }
1436
1437 unum_close(pattern);
1438}
1439
374ca955
A
1440static UBool
1441withinErr(double a, double b, double err) {
729e4ab9 1442 return uprv_fabs(a - b) < uprv_fabs(a * err);
374ca955
A
1443}
1444
1445static void TestInt64Format() {
1446 UChar temp1[512];
1447 UChar result[512];
1448 UNumberFormat *fmt;
1449 UErrorCode status = U_ZERO_ERROR;
1450 const double doubleInt64Max = (double)U_INT64_MAX;
1451 const double doubleInt64Min = (double)U_INT64_MIN;
729e4ab9 1452 const double doubleBig = 10.0 * (double)U_INT64_MAX;
374ca955
A
1453 int32_t val32;
1454 int64_t val64;
1455 double valDouble;
1456 int32_t parsepos;
1457
1458 /* create a number format using unum_openPattern(....) */
1459 log_verbose("\nTesting Int64Format\n");
1460 u_uastrcpy(temp1, "#.#E0");
1461 fmt = unum_open(UNUM_IGNORE, temp1, u_strlen(temp1), NULL, NULL, &status);
1462 if(U_FAILURE(status)) {
4388f060 1463 log_data_err("error in unum_openPattern() - %s\n", myErrorName(status));
374ca955
A
1464 } else {
1465 unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 20);
1466 unum_formatInt64(fmt, U_INT64_MAX, result, 512, NULL, &status);
1467 if (U_FAILURE(status)) {
1468 log_err("error in unum_format(): %s\n", myErrorName(status));
1469 } else {
1470 log_verbose("format int64max: '%s'\n", result);
1471 parsepos = 0;
1472 val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
1473 if (status != U_INVALID_FORMAT_ERROR) {
1474 log_err("parse didn't report error: %s\n", myErrorName(status));
1475 } else if (val32 != INT32_MAX) {
1476 log_err("parse didn't pin return value, got: %d\n", val32);
1477 }
1478
1479 status = U_ZERO_ERROR;
1480 parsepos = 0;
1481 val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
1482 if (U_FAILURE(status)) {
1483 log_err("parseInt64 returned error: %s\n", myErrorName(status));
1484 } else if (val64 != U_INT64_MAX) {
1485 log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
1486 }
1487
1488 status = U_ZERO_ERROR;
1489 parsepos = 0;
1490 valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1491 if (U_FAILURE(status)) {
1492 log_err("parseDouble returned error: %s\n", myErrorName(status));
1493 } else if (valDouble != doubleInt64Max) {
1494 log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
1495 }
1496 }
1497
1498 unum_formatInt64(fmt, U_INT64_MIN, result, 512, NULL, &status);
1499 if (U_FAILURE(status)) {
1500 log_err("error in unum_format(): %s\n", myErrorName(status));
1501 } else {
1502 log_verbose("format int64min: '%s'\n", result);
1503 parsepos = 0;
1504 val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
1505 if (status != U_INVALID_FORMAT_ERROR) {
1506 log_err("parse didn't report error: %s\n", myErrorName(status));
1507 } else if (val32 != INT32_MIN) {
1508 log_err("parse didn't pin return value, got: %d\n", val32);
1509 }
1510
1511 status = U_ZERO_ERROR;
1512 parsepos = 0;
1513 val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
1514 if (U_FAILURE(status)) {
1515 log_err("parseInt64 returned error: %s\n", myErrorName(status));
1516 } else if (val64 != U_INT64_MIN) {
1517 log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
1518 }
1519
1520 status = U_ZERO_ERROR;
1521 parsepos = 0;
1522 valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1523 if (U_FAILURE(status)) {
1524 log_err("parseDouble returned error: %s\n", myErrorName(status));
1525 } else if (valDouble != doubleInt64Min) {
1526 log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
1527 }
1528 }
1529
1530 unum_formatDouble(fmt, doubleBig, result, 512, NULL, &status);
1531 if (U_FAILURE(status)) {
1532 log_err("error in unum_format(): %s\n", myErrorName(status));
1533 } else {
1534 log_verbose("format doubleBig: '%s'\n", result);
1535 parsepos = 0;
1536 val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
1537 if (status != U_INVALID_FORMAT_ERROR) {
1538 log_err("parse didn't report error: %s\n", myErrorName(status));
1539 } else if (val32 != INT32_MAX) {
1540 log_err("parse didn't pin return value, got: %d\n", val32);
1541 }
1542
1543 status = U_ZERO_ERROR;
1544 parsepos = 0;
1545 val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
1546 if (status != U_INVALID_FORMAT_ERROR) {
1547 log_err("parseInt64 didn't report error error: %s\n", myErrorName(status));
1548 } else if (val64 != U_INT64_MAX) {
1549 log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
1550 }
1551
1552 status = U_ZERO_ERROR;
1553 parsepos = 0;
1554 valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1555 if (U_FAILURE(status)) {
1556 log_err("parseDouble returned error: %s\n", myErrorName(status));
1557 } else if (!withinErr(valDouble, doubleBig, 1e-15)) {
1558 log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
1559 }
1560 }
729e4ab9 1561
4388f060
A
1562 u_uastrcpy(result, "5.06e-27");
1563 parsepos = 0;
1564 valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1565 if (U_FAILURE(status)) {
1566 log_err("parseDouble() returned error: %s\n", myErrorName(status));
1567 } else if (!withinErr(valDouble, 5.06e-27, 1e-15)) {
1568 log_err("parseDouble() returned incorrect value, got: %g\n", valDouble);
1569 }
374ca955
A
1570 }
1571 unum_close(fmt);
1572}
1573
1574
1575static void test_fmt(UNumberFormat* fmt, UBool isDecimal) {
1576 char temp[512];
1577 UChar buffer[512];
1578 int32_t BUFSIZE = sizeof(buffer)/sizeof(buffer[0]);
1579 double vals[] = {
1580 -.2, 0, .2, 5.5, 15.2, 250, 123456789
1581 };
1582 int i;
1583
1584 for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
1585 UErrorCode status = U_ZERO_ERROR;
1586 unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
1587 if (U_FAILURE(status)) {
1588 log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
1589 } else {
1590 u_austrcpy(temp, buffer);
1591 log_verbose("formatting %g returned '%s'\n", vals[i], temp);
1592 }
1593 }
1594
1595 /* check APIs now */
1596 {
1597 UErrorCode status = U_ZERO_ERROR;
1598 UParseError perr;
1599 u_uastrcpy(buffer, "#,##0.0#");
1600 unum_applyPattern(fmt, FALSE, buffer, -1, &perr, &status);
1601 if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
1602 log_err("got unexpected error for applyPattern: '%s'\n", u_errorName(status));
1603 }
1604 }
1605
1606 {
1607 int isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
1608 log_verbose("lenient: 0x%x\n", isLenient);
4388f060 1609 if (isLenient != FALSE) {
374ca955
A
1610 log_err("didn't expect lenient value: %d\n", isLenient);
1611 }
1612
1613 unum_setAttribute(fmt, UNUM_LENIENT_PARSE, TRUE);
1614 isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
4388f060 1615 if (isLenient != TRUE) {
374ca955
A
1616 log_err("didn't expect lenient value after set: %d\n", isLenient);
1617 }
1618 }
1619
1620 {
1621 double val2;
1622 double val = unum_getDoubleAttribute(fmt, UNUM_LENIENT_PARSE);
1623 if (val != -1) {
1624 log_err("didn't expect double attribute\n");
1625 }
1626 val = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
1627 if ((val == -1) == isDecimal) {
1628 log_err("didn't expect -1 rounding increment\n");
1629 }
1630 unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, val+.5);
1631 val2 = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
1632 if (isDecimal && (val2 - val != .5)) {
1633 log_err("set rounding increment had no effect on decimal format");
1634 }
1635 }
1636
1637 {
1638 UErrorCode status = U_ZERO_ERROR;
1639 int len = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
1640 if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
1641 log_err("got unexpected error for get default ruleset: '%s'\n", u_errorName(status));
1642 }
1643 if (U_SUCCESS(status)) {
1644 u_austrcpy(temp, buffer);
1645 log_verbose("default ruleset: '%s'\n", temp);
1646 }
1647
1648 status = U_ZERO_ERROR;
1649 len = unum_getTextAttribute(fmt, UNUM_PUBLIC_RULESETS, buffer, BUFSIZE, &status);
1650 if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
1651 log_err("got unexpected error for get public rulesets: '%s'\n", u_errorName(status));
1652 }
1653 if (U_SUCCESS(status)) {
1654 u_austrcpy(temp, buffer);
1655 log_verbose("public rulesets: '%s'\n", temp);
1656
1657 /* set the default ruleset to the first one found, and retry */
1658
1659 if (len > 0) {
1660 for (i = 0; i < len && temp[i] != ';'; ++i){};
1661 if (i < len) {
1662 buffer[i] = 0;
1663 unum_setTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, -1, &status);
1664 if (U_FAILURE(status)) {
1665 log_err("unexpected error setting default ruleset: '%s'\n", u_errorName(status));
1666 } else {
1667 int len2 = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
1668 if (U_FAILURE(status)) {
1669 log_err("could not fetch default ruleset: '%s'\n", u_errorName(status));
1670 } else if (len2 != i) {
1671 u_austrcpy(temp, buffer);
1672 log_err("unexpected ruleset len: %d ex: %d val: %s\n", len2, i, temp);
1673 } else {
1674 for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
1675 status = U_ZERO_ERROR;
1676 unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
1677 if (U_FAILURE(status)) {
1678 log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
1679 } else {
1680 u_austrcpy(temp, buffer);
1681 log_verbose("formatting %g returned '%s'\n", vals[i], temp);
1682 }
1683 }
1684 }
1685 }
1686 }
1687 }
1688 }
1689 }
1690
1691 {
1692 UErrorCode status = U_ZERO_ERROR;
1693 unum_toPattern(fmt, FALSE, buffer, BUFSIZE, &status);
1694 if (U_SUCCESS(status)) {
1695 u_austrcpy(temp, buffer);
1696 log_verbose("pattern: '%s'\n", temp);
1697 } else if (status != U_BUFFER_OVERFLOW_ERROR) {
1698 log_err("toPattern failed unexpectedly: %s\n", u_errorName(status));
1699 } else {
1700 log_verbose("pattern too long to display\n");
1701 }
1702 }
1703
1704 {
1705 UErrorCode status = U_ZERO_ERROR;
1706 int len = unum_getSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, BUFSIZE, &status);
1707 if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
1708 log_err("unexpected error getting symbol: '%s'\n", u_errorName(status));
1709 }
1710
1711 unum_setSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, len, &status);
1712 if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
1713 log_err("unexpected error setting symbol: '%s'\n", u_errorName(status));
1714 }
1715 }
1716}
1717
1718static void TestNonExistentCurrency() {
1719 UNumberFormat *format;
1720 UErrorCode status = U_ZERO_ERROR;
1721 UChar currencySymbol[8];
1722 static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
1723
1724 /* Get a non-existent currency and make sure it returns the correct currency code. */
1725 format = unum_open(UNUM_CURRENCY, NULL, 0, "th_TH@currency=QQQ", NULL, &status);
1726 if (format == NULL || U_FAILURE(status)) {
729e4ab9 1727 log_data_err("unum_open did not return expected result for non-existent requested currency: '%s' (Are you missing data?)\n", u_errorName(status));
374ca955
A
1728 }
1729 else {
1730 unum_getSymbol(format,
1731 UNUM_CURRENCY_SYMBOL,
1732 currencySymbol,
1733 sizeof(currencySymbol)/sizeof(currencySymbol[0]),
1734 &status);
1735 if (u_strcmp(currencySymbol, QQQ) != 0) {
1736 log_err("unum_open set the currency to QQQ\n");
1737 }
1738 }
1739 unum_close(format);
1740}
1741
1742static void TestRBNFFormat() {
1743 UErrorCode status;
1744 UParseError perr;
1745 UChar pat[1024];
1746 UChar tempUChars[512];
1747 UNumberFormat *formats[5];
1748 int COUNT = sizeof(formats)/sizeof(formats[0]);
1749 int i;
1750
1751 for (i = 0; i < COUNT; ++i) {
1752 formats[i] = 0;
1753 }
1754
1755 /* instantiation */
1756 status = U_ZERO_ERROR;
1757 u_uastrcpy(pat, "#,##0.0#;(#,##0.0#)");
1758 formats[0] = unum_open(UNUM_PATTERN_DECIMAL, pat, -1, "en_US", &perr, &status);
1759 if (U_FAILURE(status)) {
729e4ab9
A
1760 log_err_status(status, "unable to open decimal pattern -> %s\n", u_errorName(status));
1761 return;
374ca955
A
1762 }
1763
1764 status = U_ZERO_ERROR;
1765 formats[1] = unum_open(UNUM_SPELLOUT, NULL, 0, "en_US", &perr, &status);
1766 if (U_FAILURE(status)) {
729e4ab9
A
1767 log_err_status(status, "unable to open spellout -> %s\n", u_errorName(status));
1768 return;
374ca955
A
1769 }
1770
1771 status = U_ZERO_ERROR;
1772 formats[2] = unum_open(UNUM_ORDINAL, NULL, 0, "en_US", &perr, &status);
1773 if (U_FAILURE(status)) {
729e4ab9
A
1774 log_err_status(status, "unable to open ordinal -> %s\n", u_errorName(status));
1775 return;
374ca955
A
1776 }
1777
1778 status = U_ZERO_ERROR;
1779 formats[3] = unum_open(UNUM_DURATION, NULL, 0, "en_US", &perr, &status);
1780 if (U_FAILURE(status)) {
729e4ab9
A
1781 log_err_status(status, "unable to open duration %s\n", u_errorName(status));
1782 return;
374ca955
A
1783 }
1784
1785 status = U_ZERO_ERROR;
1786 u_uastrcpy(pat,
1787 "%standard:\n"
1788 "-x: minus >>;\n"
1789 "x.x: << point >>;\n"
1790 "zero; one; two; three; four; five; six; seven; eight; nine;\n"
1791 "ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
1792 "seventeen; eighteen; nineteen;\n"
1793 "20: twenty[->>];\n"
1794 "30: thirty[->>];\n"
1795 "40: forty[->>];\n"
1796 "50: fifty[->>];\n"
1797 "60: sixty[->>];\n"
1798 "70: seventy[->>];\n"
1799 "80: eighty[->>];\n"
1800 "90: ninety[->>];\n"
1801 "100: =#,##0=;\n");
1802 u_uastrcpy(tempUChars,
1803 "%simple:\n"
1804 "=%standard=;\n"
1805 "20: twenty[ and change];\n"
1806 "30: thirty[ and change];\n"
1807 "40: forty[ and change];\n"
1808 "50: fifty[ and change];\n"
1809 "60: sixty[ and change];\n"
1810 "70: seventy[ and change];\n"
1811 "80: eighty[ and change];\n"
1812 "90: ninety[ and change];\n"
1813 "100: =#,##0=;\n"
1814 "%bogus:\n"
1815 "0.x: tiny;\n"
1816 "x.x: << point something;\n"
1817 "=%standard=;\n"
1818 "20: some reasonable number;\n"
1819 "100: some substantial number;\n"
1820 "100,000,000: some huge number;\n");
1821 /* This is to get around some compiler warnings about char * string length. */
1822 u_strcat(pat, tempUChars);
1823 formats[4] = unum_open(UNUM_PATTERN_RULEBASED, pat, -1, "en_US", &perr, &status);
1824 if (U_FAILURE(status)) {
729e4ab9 1825 log_err_status(status, "unable to open rulebased pattern -> %s\n", u_errorName(status));
46f4442e
A
1826 }
1827 if (U_FAILURE(status)) {
729e4ab9 1828 log_err_status(status, "Something failed with %s\n", u_errorName(status));
46f4442e 1829 return;
374ca955
A
1830 }
1831
1832 for (i = 0; i < COUNT; ++i) {
1833 log_verbose("\n\ntesting format %d\n", i);
1834 test_fmt(formats[i], (UBool)(i == 0));
1835 }
1836
4388f060
A
1837 #define FORMAT_BUF_CAPACITY 64
1838 {
1839 UChar fmtbuf[FORMAT_BUF_CAPACITY];
1840 int32_t len;
1841 double nanvalue = uprv_getNaN();
1842 status = U_ZERO_ERROR;
1843 len = unum_formatDouble(formats[1], nanvalue, fmtbuf, FORMAT_BUF_CAPACITY, NULL, &status);
1844 if (U_FAILURE(status)) {
1845 log_err_status(status, "unum_formatDouble NAN failed with %s\n", u_errorName(status));
1846 } else {
1847 UChar nansym[] = { 0x4E, 0x61, 0x4E, 0 }; /* NaN */
1848 if ( len != 3 || u_strcmp(fmtbuf, nansym) != 0 ) {
1849 log_err("unum_formatDouble NAN produced wrong answer for en_US\n");
1850 }
1851 }
1852 }
1853
374ca955
A
1854 for (i = 0; i < COUNT; ++i) {
1855 unum_close(formats[i]);
1856 }
1857}
1858
73c04bcf 1859static void TestCurrencyRegression(void) {
729e4ab9 1860/*
73c04bcf
A
1861 I've found a case where unum_parseDoubleCurrency is not doing what I
1862expect. The value I pass in is $1234567890q123460000.00 and this
1863returns with a status of zero error & a parse pos of 22 (I would
1864expect a parse error at position 11).
1865
1866I stepped into DecimalFormat::subparse() and it looks like it parses
1867the first 10 digits and then stops parsing at the q but doesn't set an
1868error. Then later in DecimalFormat::parse() the value gets crammed
1869into a long (which greatly truncates the value).
1870
1871This is very problematic for me 'cause I try to remove chars that are
1872invalid but this allows my users to enter bad chars and truncates
1873their data!
1874*/
1875
1876 UChar buf[1024];
1877 UChar currency[8];
1878 char acurrency[16];
1879 double d;
1880 UNumberFormat *cur;
1881 int32_t pos;
1882 UErrorCode status = U_ZERO_ERROR;
1883 const int32_t expected = 11;
1884
1885 currency[0]=0;
1886 u_uastrcpy(buf, "$1234567890q643210000.00");
1887 cur = unum_open(UNUM_CURRENCY, NULL,0,"en_US", NULL, &status);
729e4ab9 1888
73c04bcf 1889 if(U_FAILURE(status)) {
729e4ab9 1890 log_data_err("unum_open failed: %s (Are you missing data?)\n", u_errorName(status));
73c04bcf
A
1891 return;
1892 }
729e4ab9 1893
73c04bcf
A
1894 status = U_ZERO_ERROR; /* so we can test it later. */
1895 pos = 0;
729e4ab9 1896
73c04bcf
A
1897 d = unum_parseDoubleCurrency(cur,
1898 buf,
1899 -1,
1900 &pos, /* 0 = start */
1901 currency,
1902 &status);
1903
1904 u_austrcpy(acurrency, currency);
1905
1906 if(U_FAILURE(status) || (pos != expected)) {
1907 log_err("unum_parseDoubleCurrency should have failed with pos %d, but gave: value %.9f, err %s, pos=%d, currency [%s]\n",
1908 expected, d, u_errorName(status), pos, acurrency);
1909 } else {
1910 log_verbose("unum_parseDoubleCurrency failed, value %.9f err %s, pos %d, currency [%s]\n", d, u_errorName(status), pos, acurrency);
1911 }
729e4ab9 1912
73c04bcf
A
1913 unum_close(cur);
1914}
1915
46f4442e
A
1916static void TestTextAttributeCrash(void) {
1917 UChar ubuffer[64] = {0x0049,0x004E,0x0052,0};
1918 static const UChar expectedNeg[] = {0x0049,0x004E,0x0052,0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0};
1919 static const UChar expectedPos[] = {0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0};
729e4ab9 1920 int32_t used;
46f4442e 1921 UErrorCode status = U_ZERO_ERROR;
729e4ab9 1922 UNumberFormat *nf = unum_open(UNUM_CURRENCY, NULL, 0, "en_US", NULL, &status);
46f4442e 1923 if (U_FAILURE(status)) {
729e4ab9 1924 log_data_err("FAILED 1 -> %s (Are you missing data?)\n", u_errorName(status));
46f4442e
A
1925 return;
1926 }
1927 unum_setTextAttribute(nf, UNUM_CURRENCY_CODE, ubuffer, 3, &status);
1928 /*
1929 * the usual negative prefix and suffix seem to be '($' and ')' at this point
1930 * also crashes if UNUM_NEGATIVE_SUFFIX is substituted for UNUM_NEGATIVE_PREFIX here
1931 */
1932 used = unum_getTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, 64, &status);
1933 unum_setTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, used, &status);
1934 if (U_FAILURE(status)) {
1935 log_err("FAILED 2\n"); exit(1);
1936 }
1937 log_verbose("attempting to format...\n");
729e4ab9 1938 used = unum_formatDouble(nf, -1234.5, ubuffer, 64, NULL, &status);
46f4442e
A
1939 if (U_FAILURE(status) || 64 < used) {
1940 log_err("Failed formatting %s\n", u_errorName(status));
1941 return;
1942 }
1943 if (u_strcmp(expectedNeg, ubuffer) == 0) {
1944 log_err("Didn't get expected negative result\n");
1945 }
729e4ab9 1946 used = unum_formatDouble(nf, 1234.5, ubuffer, 64, NULL, &status);
46f4442e
A
1947 if (U_FAILURE(status) || 64 < used) {
1948 log_err("Failed formatting %s\n", u_errorName(status));
1949 return;
1950 }
1951 if (u_strcmp(expectedPos, ubuffer) == 0) {
1952 log_err("Didn't get expected positive result\n");
1953 }
1954 unum_close(nf);
1955}
1956
1957static void TestNBSPPatternRtNum(const char *testcase, UNumberFormat *nf, double myNumber) {
1958 UErrorCode status = U_ZERO_ERROR;
1959 UChar myString[20];
1960 char tmpbuf[200];
1961 double aNumber = -1.0;
1962 unum_formatDouble(nf, myNumber, myString, 20, NULL, &status);
729e4ab9 1963 log_verbose("%s: formatted %.2f into %s\n", testcase, myNumber, u_austrcpy(tmpbuf, myString));
46f4442e
A
1964 if(U_FAILURE(status)) {
1965 log_err("%s: failed format of %.2g with %s\n", testcase, myNumber, u_errorName(status));
1966 return;
1967 }
1968 aNumber = unum_parse(nf, myString, -1, NULL, &status);
1969 if(U_FAILURE(status)) {
1970 log_err("%s: failed parse with %s\n", testcase, u_errorName(status));
1971 return;
1972 }
1973 if(uprv_fabs(aNumber-myNumber)>.001) {
1974 log_err("FAIL: %s: formatted %.2f, parsed into %.2f\n", testcase, myNumber, aNumber);
1975 } else {
1976 log_verbose("PASS: %s: formatted %.2f, parsed into %.2f\n", testcase, myNumber, aNumber);
1977 }
1978}
1979
1980static void TestNBSPPatternRT(const char *testcase, UNumberFormat *nf) {
1981 TestNBSPPatternRtNum(testcase, nf, 12345.);
1982 TestNBSPPatternRtNum(testcase, nf, -12345.);
1983}
1984
1985static void TestNBSPInPattern(void) {
1986 UErrorCode status = U_ZERO_ERROR;
1987 UNumberFormat* nf = NULL;
1988 const char *testcase;
729e4ab9
A
1989
1990
46f4442e
A
1991 testcase="ar_AE UNUM_CURRENCY";
1992 nf = unum_open(UNUM_CURRENCY, NULL, -1, "ar_AE", NULL, &status);
729e4ab9
A
1993 if(U_FAILURE(status) || nf == NULL) {
1994 log_data_err("%s: unum_open failed with %s (Are you missing data?)\n", testcase, u_errorName(status));
1995 return;
46f4442e
A
1996 }
1997 TestNBSPPatternRT(testcase, nf);
729e4ab9 1998
46f4442e
A
1999 /* if we don't have CLDR 1.6 data, bring out the problem anyways */
2000 {
2001#define SPECIAL_PATTERN "\\u00A4\\u00A4'\\u062f.\\u0625.\\u200f\\u00a0'###0.00"
2002 UChar pat[200];
2003 testcase = "ar_AE special pattern: " SPECIAL_PATTERN;
2004 u_unescape(SPECIAL_PATTERN, pat, sizeof(pat)/sizeof(pat[0]));
2005 unum_applyPattern(nf, FALSE, pat, -1, NULL, &status);
729e4ab9 2006 if(U_FAILURE(status)) {
46f4442e
A
2007 log_err("%s: unum_applyPattern failed with %s\n", testcase, u_errorName(status));
2008 } else {
2009 TestNBSPPatternRT(testcase, nf);
2010 }
2011#undef SPECIAL_PATTERN
2012 }
2013 unum_close(nf); status = U_ZERO_ERROR;
729e4ab9 2014
46f4442e
A
2015 testcase="ar_AE UNUM_DECIMAL";
2016 nf = unum_open(UNUM_DECIMAL, NULL, -1, "ar_AE", NULL, &status);
2017 if(U_FAILURE(status)) {
2018 log_err("%s: unum_open failed with %s\n", testcase, u_errorName(status));
2019 }
2020 TestNBSPPatternRT(testcase, nf);
2021 unum_close(nf); status = U_ZERO_ERROR;
729e4ab9 2022
46f4442e
A
2023 testcase="ar_AE UNUM_PERCENT";
2024 nf = unum_open(UNUM_PERCENT, NULL, -1, "ar_AE", NULL, &status);
2025 if(U_FAILURE(status)) {
2026 log_err("%s: unum_open failed with %s\n", testcase, u_errorName(status));
729e4ab9
A
2027 }
2028 TestNBSPPatternRT(testcase, nf);
46f4442e 2029 unum_close(nf); status = U_ZERO_ERROR;
729e4ab9
A
2030
2031
2032
46f4442e 2033}
4388f060
A
2034static void TestCloneWithRBNF(void) {
2035 UChar pattern[1024];
2036 UChar pat2[512];
2037 UErrorCode status = U_ZERO_ERROR;
2038 UChar buffer[256];
2039 UChar buffer_cloned[256];
2040 char temp1[256];
2041 char temp2[256];
2042 UNumberFormat *pform_cloned;
2043 UNumberFormat *pform;
2044
2045 u_uastrcpy(pattern,
2046 "%main:\n"
2047 "0.x: >%%millis-only>;\n"
2048 "x.0: <%%duration<;\n"
2049 "x.x: <%%durationwithmillis<>%%millis-added>;\n"
2050 "-x: ->>;%%millis-only:\n"
2051 "1000: 00:00.<%%millis<;\n"
2052 "%%millis-added:\n"
2053 "1000: .<%%millis<;\n"
2054 "%%millis:\n"
2055 "0: =000=;\n"
2056 "%%duration:\n"
2057 "0: =%%seconds-only=;\n"
2058 "60: =%%min-sec=;\n"
2059 "3600: =%%hr-min-sec=;\n"
2060 "86400/86400: <%%ddaayyss<[, >>];\n"
2061 "%%durationwithmillis:\n"
2062 "0: =%%seconds-only=;\n"
2063 "60: =%%min-sec=;\n"
2064 "3600: =%%hr-min-sec=;\n"
2065 "86400/86400: <%%ddaayyss<, >>;\n");
2066 u_uastrcpy(pat2,
2067 "%%seconds-only:\n"
2068 "0: 0:00:=00=;\n"
2069 "%%min-sec:\n"
2070 "0: :=00=;\n"
2071 "0/60: 0:<00<>>;\n"
2072 "%%hr-min-sec:\n"
2073 "0: :=00=;\n"
2074 "60/60: <00<>>;\n"
2075 "3600/60: <0<:>>>;\n"
2076 "%%ddaayyss:\n"
2077 "0 days;\n"
2078 "1 day;\n"
2079 "=0= days;");
46f4442e 2080
4388f060
A
2081 /* This is to get around some compiler warnings about char * string length. */
2082 u_strcat(pattern, pat2);
2083
2084 pform = unum_open(UNUM_PATTERN_RULEBASED, pattern, -1, "en_US", NULL, &status);
2085 unum_formatDouble(pform, 3600, buffer, 256, NULL, &status);
2086
2087 pform_cloned = unum_clone(pform,&status);
2088 unum_formatDouble(pform_cloned, 3600, buffer_cloned, 256, NULL, &status);
2089
2090 unum_close(pform);
2091 unum_close(pform_cloned);
2092
2093 if (u_strcmp(buffer,buffer_cloned)) {
2094 log_data_err("Result from cloned formatter not identical to the original. Original: %s Cloned: %s - (Are you missing data?)",u_austrcpy(temp1, buffer),u_austrcpy(temp2,buffer_cloned));
2095 }
2096}
b75a7d8f 2097#endif /* #if !UCONFIG_NO_FORMATTING */