OLD | NEW |
1 /******************************************************************** | 1 /******************************************************************** |
2 * COPYRIGHT: | 2 * COPYRIGHT: |
3 * Copyright (c) 1997-2013, International Business Machines Corporation and | 3 * Copyright (c) 1997-2014, International Business Machines Corporation and |
4 * others. All Rights Reserved. | 4 * others. All Rights Reserved. |
5 ********************************************************************/ | 5 ********************************************************************/ |
6 | 6 |
7 #include "unicode/utypes.h" | 7 #include "unicode/utypes.h" |
8 | 8 |
9 #if !UCONFIG_NO_FORMATTING | 9 #if !UCONFIG_NO_FORMATTING |
10 | 10 |
11 #include "dcfmapts.h" | 11 #include "dcfmapts.h" |
12 | 12 |
13 #include "unicode/currpinf.h" | 13 #include "unicode/currpinf.h" |
14 #include "unicode/dcfmtsym.h" | 14 #include "unicode/dcfmtsym.h" |
15 #include "unicode/decimfmt.h" | 15 #include "unicode/decimfmt.h" |
16 #include "unicode/fmtable.h" | 16 #include "unicode/fmtable.h" |
17 #include "unicode/localpointer.h" | 17 #include "unicode/localpointer.h" |
18 #include "unicode/parseerr.h" | 18 #include "unicode/parseerr.h" |
19 #include "unicode/stringpiece.h" | 19 #include "unicode/stringpiece.h" |
20 | 20 |
21 #include "putilimp.h" | 21 #include "putilimp.h" |
22 #include "plurrule_impl.h" | 22 #include "plurrule_impl.h" |
23 #include <stdio.h> | 23 #include <stdio.h> |
24 | 24 |
25 #define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0]))) | |
26 | |
27 // This is an API test, not a unit test. It doesn't test very many cases, and d
oesn't | 25 // This is an API test, not a unit test. It doesn't test very many cases, and d
oesn't |
28 // try to test the full functionality. It just calls each function in the class
and | 26 // try to test the full functionality. It just calls each function in the class
and |
29 // verifies that it works on a basic level. | 27 // verifies that it works on a basic level. |
30 | 28 |
31 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const
char* &name, char* /*par*/ ) | 29 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const
char* &name, char* /*par*/ ) |
32 { | 30 { |
33 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI"); | 31 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI"); |
34 switch (index) { | 32 switch (index) { |
35 case 0: name = "DecimalFormat API test"; | 33 case 0: name = "DecimalFormat API test"; |
36 if (exec) { | 34 if (exec) { |
37 logln((UnicodeString)"DecimalFormat API test---"); logln((Un
icodeString)""); | 35 logln((UnicodeString)"DecimalFormat API test---"); logln((Un
icodeString)""); |
38 UErrorCode status = U_ZERO_ERROR; | 36 UErrorCode status = U_ZERO_ERROR; |
39 Locale saveLocale; | 37 Locale saveLocale; |
40 Locale::setDefault(Locale::getEnglish(), status); | 38 Locale::setDefault(Locale::getEnglish(), status); |
41 if(U_FAILURE(status)) { | 39 if(U_FAILURE(status)) { |
42 errln((UnicodeString)"ERROR: Could not set default local
e, test may not give correct results"); | 40 errln((UnicodeString)"ERROR: Could not set default local
e, test may not give correct results"); |
43 } | 41 } |
44 testAPI(/*par*/); | 42 testAPI(/*par*/); |
45 Locale::setDefault(saveLocale, status); | 43 Locale::setDefault(saveLocale, status); |
(...skipping 22 matching lines...) Expand all Loading... |
68 logln((UnicodeString)"Scale test---"); | 66 logln((UnicodeString)"Scale test---"); |
69 TestScale(); | 67 TestScale(); |
70 } | 68 } |
71 break; | 69 break; |
72 case 5: name = "TestFixedDecimal"; | 70 case 5: name = "TestFixedDecimal"; |
73 if(exec) { | 71 if(exec) { |
74 logln((UnicodeString)"TestFixedDecimal ---"); | 72 logln((UnicodeString)"TestFixedDecimal ---"); |
75 TestFixedDecimal(); | 73 TestFixedDecimal(); |
76 } | 74 } |
77 break; | 75 break; |
| 76 case 6: name = "TestBadFastpath"; |
| 77 if(exec) { |
| 78 logln((UnicodeString)"TestBadFastpath ---"); |
| 79 TestBadFastpath(); |
| 80 } |
| 81 break; |
| 82 case 7: name = "TestRequiredDecimalPoint"; |
| 83 if(exec) { |
| 84 logln((UnicodeString)"TestRequiredDecimalPoint ---"); |
| 85 TestRequiredDecimalPoint(); |
| 86 } |
| 87 break; |
78 default: name = ""; break; | 88 default: name = ""; break; |
79 } | 89 } |
80 } | 90 } |
81 | 91 |
82 /** | 92 /** |
83 * This test checks various generic API methods in DecimalFormat to achieve 100% | 93 * This test checks various generic API methods in DecimalFormat to achieve 100% |
84 * API coverage. | 94 * API coverage. |
85 */ | 95 */ |
86 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) | 96 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) |
87 { | 97 { |
88 UErrorCode status = U_ZERO_ERROR; | 98 UErrorCode status = U_ZERO_ERROR; |
89 | 99 |
90 // ======= Test constructors | 100 // ======= Test constructors |
91 | 101 |
92 logln((UnicodeString)"Testing DecimalFormat constructors"); | 102 logln((UnicodeString)"Testing DecimalFormat constructors"); |
93 | 103 |
94 DecimalFormat def(status); | 104 DecimalFormat def(status); |
95 if(U_FAILURE(status)) { | 105 if(U_FAILURE(status)) { |
96 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s
", u_errorName(status)); | 106 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s
", u_errorName(status)); |
97 return; | 107 return; |
98 } | 108 } |
99 | 109 |
| 110 // bug 10864 |
| 111 status = U_ZERO_ERROR; |
| 112 DecimalFormat noGrouping("###0.##", status); |
| 113 if (noGrouping.getGroupingSize() != 0) { |
| 114 errln("Grouping size should be 0 for no grouping."); |
| 115 } |
| 116 // end bug 10864 |
| 117 |
100 status = U_ZERO_ERROR; | 118 status = U_ZERO_ERROR; |
101 const UnicodeString pattern("#,##0.# FF"); | 119 const UnicodeString pattern("#,##0.# FF"); |
102 DecimalFormat pat(pattern, status); | 120 DecimalFormat pat(pattern, status); |
103 if(U_FAILURE(status)) { | 121 if(U_FAILURE(status)) { |
104 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); | 122 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); |
105 return; | 123 return; |
106 } | 124 } |
107 | 125 |
108 status = U_ZERO_ERROR; | 126 status = U_ZERO_ERROR; |
109 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench()
, status); | 127 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench()
, status); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 167 |
150 logln((UnicodeString)"Testing various format() methods"); | 168 logln((UnicodeString)"Testing various format() methods"); |
151 | 169 |
152 double d = -10456.0037; | 170 double d = -10456.0037; |
153 int32_t l = 100000000; | 171 int32_t l = 100000000; |
154 Formattable fD(d); | 172 Formattable fD(d); |
155 Formattable fL(l); | 173 Formattable fL(l); |
156 | 174 |
157 UnicodeString res1, res2, res3, res4; | 175 UnicodeString res1, res2, res3, res4; |
158 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); | 176 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); |
159 | 177 |
160 res1 = def.format(d, res1, pos1); | 178 res1 = def.format(d, res1, pos1); |
161 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); | 179 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); |
162 | 180 |
163 res2 = pat.format(l, res2, pos2); | 181 res2 = pat.format(l, res2, pos2); |
164 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); | 182 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); |
165 | 183 |
166 status = U_ZERO_ERROR; | 184 status = U_ZERO_ERROR; |
167 res3 = cust1.format(fD, res3, pos3, status); | 185 res3 = cust1.format(fD, res3, pos3, status); |
168 if(U_FAILURE(status)) { | 186 if(U_FAILURE(status)) { |
169 errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); | 187 errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); | 298 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); |
281 } | 299 } |
282 | 300 |
283 // Added by Ken Liu testing set/isScientificNotation | 301 // Added by Ken Liu testing set/isScientificNotation |
284 pat.setScientificNotation(TRUE); | 302 pat.setScientificNotation(TRUE); |
285 UBool sn = pat.isScientificNotation(); | 303 UBool sn = pat.isScientificNotation(); |
286 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeS
tring) (sn ? "TRUE" : "FALSE")); | 304 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeS
tring) (sn ? "TRUE" : "FALSE")); |
287 if(sn != TRUE) { | 305 if(sn != TRUE) { |
288 errln((UnicodeString)"ERROR: setScientificNotation() failed"); | 306 errln((UnicodeString)"ERROR: setScientificNotation() failed"); |
289 } | 307 } |
290 | 308 |
291 // Added by Ken Liu testing set/getMinimumExponentDigits | 309 // Added by Ken Liu testing set/getMinimumExponentDigits |
292 int8_t MinimumExponentDigits = 0; | 310 int8_t MinimumExponentDigits = 0; |
293 pat.setMinimumExponentDigits(2); | 311 pat.setMinimumExponentDigits(2); |
294 MinimumExponentDigits = pat.getMinimumExponentDigits(); | 312 MinimumExponentDigits = pat.getMinimumExponentDigits(); |
295 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) Mi
nimumExponentDigits); | 313 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) Mi
nimumExponentDigits); |
296 if(MinimumExponentDigits != 2) { | 314 if(MinimumExponentDigits != 2) { |
297 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); | 315 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); |
298 } | 316 } |
299 | 317 |
300 // Added by Ken Liu testing set/getRoundingIncrement | 318 // Added by Ken Liu testing set/getRoundingIncrement |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 | 427 |
410 cpi->setCurrencyPluralPattern("","",status); | 428 cpi->setCurrencyPluralPattern("","",status); |
411 if(U_FAILURE(status)) { | 429 if(U_FAILURE(status)) { |
412 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPatter
n"); | 430 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPatter
n"); |
413 } | 431 } |
414 | 432 |
415 cpi->setLocale(Locale::getCanada(), status); | 433 cpi->setLocale(Locale::getCanada(), status); |
416 if(U_FAILURE(status)) { | 434 if(U_FAILURE(status)) { |
417 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); | 435 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); |
418 } | 436 } |
419 | 437 |
420 cpi->setPluralRules("",status); | 438 cpi->setPluralRules("",status); |
421 if(U_FAILURE(status)) { | 439 if(U_FAILURE(status)) { |
422 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); | 440 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); |
423 } | 441 } |
424 | 442 |
425 DecimalFormat *df = new DecimalFormat(status); | 443 DecimalFormat *df = new DecimalFormat(status); |
426 if(U_FAILURE(status)) { | 444 if(U_FAILURE(status)) { |
427 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_error
Name(status)); | 445 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_error
Name(status)); |
428 } | 446 } |
429 | 447 |
(...skipping 11 matching lines...) Expand all Loading... |
441 UErrorCode status = U_ZERO_ERROR; | 459 UErrorCode status = U_ZERO_ERROR; |
442 double Roundingnumber = 2.55; | 460 double Roundingnumber = 2.55; |
443 double Roundingnumber1 = -2.55; | 461 double Roundingnumber1 = -2.55; |
444 //+2.55 results -2.55 results | 462 //+2.55 results -2.55 results |
445 double result[]={ 3.0, -2.0, // kRoundCeiling 0, | 463 double result[]={ 3.0, -2.0, // kRoundCeiling 0, |
446 2.0, -3.0, // kRoundFloor 1, | 464 2.0, -3.0, // kRoundFloor 1, |
447 2.0, -2.0, // kRoundDown 2, | 465 2.0, -2.0, // kRoundDown 2, |
448 3.0, -3.0, // kRoundUp 3, | 466 3.0, -3.0, // kRoundUp 3, |
449 3.0, -3.0, // kRoundHalfEven 4, | 467 3.0, -3.0, // kRoundHalfEven 4, |
450 3.0, -3.0, // kRoundHalfDown 5, | 468 3.0, -3.0, // kRoundHalfDown 5, |
451 3.0, -3.0 // kRoundHalfUp 6 | 469 3.0, -3.0 // kRoundHalfUp 6 |
452 }; | 470 }; |
453 DecimalFormat pat(status); | 471 DecimalFormat pat(status); |
454 if(U_FAILURE(status)) { | 472 if(U_FAILURE(status)) { |
455 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s",
u_errorName(status)); | 473 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s",
u_errorName(status)); |
456 return; | 474 return; |
457 } | 475 } |
458 uint16_t mode; | 476 uint16_t mode; |
459 uint16_t i=0; | 477 uint16_t i=0; |
460 UnicodeString message; | 478 UnicodeString message; |
461 UnicodeString resultStr; | 479 UnicodeString resultStr; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 return; | 526 return; |
509 } | 527 } |
510 | 528 |
511 // get default rounding increment | 529 // get default rounding increment |
512 double roundingInc = pat.getRoundingIncrement(); | 530 double roundingInc = pat.getRoundingIncrement(); |
513 if (roundingInc != 0.0) { | 531 if (roundingInc != 0.0) { |
514 errln((UnicodeString)"ERROR: Rounding increment not zero"); | 532 errln((UnicodeString)"ERROR: Rounding increment not zero"); |
515 return; | 533 return; |
516 } | 534 } |
517 | 535 |
518 // With rounding now being handled by decNumber, we no longer | 536 // With rounding now being handled by decNumber, we no longer |
519 // set a rounding increment to enable non-default mode rounding, | 537 // set a rounding increment to enable non-default mode rounding, |
520 // checking of which was the original point of this test. | 538 // checking of which was the original point of this test. |
521 | 539 |
522 // set rounding mode with zero increment. Rounding | 540 // set rounding mode with zero increment. Rounding |
523 // increment should not be set by this operation | 541 // increment should not be set by this operation |
524 pat.setRoundingMode((DecimalFormat::ERoundingMode)0); | 542 pat.setRoundingMode((DecimalFormat::ERoundingMode)0); |
525 roundingInc = pat.getRoundingIncrement(); | 543 roundingInc = pat.getRoundingIncrement(); |
526 if (roundingInc != 0.0) { | 544 if (roundingInc != 0.0) { |
527 errln((UnicodeString)"ERROR: Rounding increment not zero after setRounding
Mode"); | 545 errln((UnicodeString)"ERROR: Rounding increment not zero after setRounding
Mode"); |
528 return; | 546 return; |
529 } | 547 } |
530 } | 548 } |
531 | 549 |
532 void IntlTestDecimalFormatAPI::TestScale() | 550 void IntlTestDecimalFormatAPI::TestScale() |
(...skipping 20 matching lines...) Expand all Loading... |
553 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s",
u_errorName(status)); | 571 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s",
u_errorName(status)); |
554 return; | 572 return; |
555 } | 573 } |
556 | 574 |
557 UnicodeString message; | 575 UnicodeString message; |
558 UnicodeString resultStr; | 576 UnicodeString resultStr; |
559 UnicodeString exp; | 577 UnicodeString exp; |
560 UnicodeString percentPattern("#,##0%"); | 578 UnicodeString percentPattern("#,##0%"); |
561 pat.setMaximumFractionDigits(4); | 579 pat.setMaximumFractionDigits(4); |
562 | 580 |
563 for(int32_t i=0; i < LENGTHOF(testData); i++) { | 581 for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) { |
564 if ( i > 2 ) { | 582 if ( i > 2 ) { |
565 pat.applyPattern(percentPattern,status); | 583 pat.applyPattern(percentPattern,status); |
566 } | 584 } |
567 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status); | 585 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status); |
568 pat.format(testData[i].inputValue, resultStr); | 586 pat.format(testData[i].inputValue, resultStr); |
569 message = UnicodeString("Unexpected output for ") + testData[i].inputVal
ue + UnicodeString(" and scale ") + | 587 message = UnicodeString("Unexpected output for ") + testData[i].inputVal
ue + UnicodeString(" and scale ") + |
570 testData[i].inputScale + UnicodeString(". Got: "); | 588 testData[i].inputScale + UnicodeString(". Got: "); |
571 exp = testData[i].expectedOutput; | 589 exp = testData[i].expectedOutput; |
572 verifyString(message, resultStr, exp); | 590 verifyString(message, resultStr, exp); |
573 message.remove(); | 591 message.remove(); |
574 resultStr.remove(); | 592 resultStr.remove(); |
575 exp.remove(); | 593 exp.remove(); |
576 } | 594 } |
577 } | 595 } |
578 | 596 |
579 | 597 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 // note: going through DigitList path to FixedDecimal, which is trimming | 803 // note: going through DigitList path to FixedDecimal, which is trimming |
786 // int64_t fields to 18 digits. See ticket Ticket #10374 | 804 // int64_t fields to 18 digits. See ticket Ticket #10374 |
787 // ASSERT_EQUAL(223372036854775807LL, fd.intValue); | 805 // ASSERT_EQUAL(223372036854775807LL, fd.intValue); |
788 if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775
807LL)) { | 806 if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775
807LL)) { |
789 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd
.intValue); | 807 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd
.intValue); |
790 } | 808 } |
791 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); | 809 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
792 ASSERT_EQUAL(FALSE, fd.isNegative); | 810 ASSERT_EQUAL(FALSE, fd.isNegative); |
793 | 811 |
794 } | 812 } |
795 | 813 |
| 814 void IntlTestDecimalFormatAPI::TestBadFastpath() { |
| 815 UErrorCode status = U_ZERO_ERROR; |
| 816 |
| 817 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status)); |
| 818 if (U_FAILURE(status)) { |
| 819 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); |
| 820 return; |
| 821 } |
| 822 |
| 823 UnicodeString fmt; |
| 824 fmt.remove(); |
| 825 assertEquals("Format 1234", "1234", df->format(1234, fmt)); |
| 826 df->setGroupingUsed(FALSE); |
| 827 fmt.remove(); |
| 828 assertEquals("Format 1234", "1234", df->format(1234, fmt)); |
| 829 df->setGroupingUsed(TRUE); |
| 830 fmt.remove(); |
| 831 assertEquals("Format 1234 w/ grouping", "1,234", df->format(1234, fmt)); |
| 832 } |
| 833 |
| 834 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() { |
| 835 UErrorCode status = U_ZERO_ERROR; |
| 836 UnicodeString text("99"); |
| 837 Formattable result1; |
| 838 UnicodeString pat1("##.0000"); |
| 839 UnicodeString pat2("00.0"); |
| 840 |
| 841 LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status)); |
| 842 if (U_FAILURE(status)) { |
| 843 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); |
| 844 return; |
| 845 } |
| 846 |
| 847 status = U_ZERO_ERROR; |
| 848 df->applyPattern(pat1, status); |
| 849 if(U_FAILURE(status)) { |
| 850 errln((UnicodeString)"ERROR: applyPattern() failed"); |
| 851 } |
| 852 df->parse(text, result1, status); |
| 853 if(U_FAILURE(status)) { |
| 854 errln((UnicodeString)"ERROR: parse() failed"); |
| 855 } |
| 856 df->setDecimalPatternMatchRequired(TRUE); |
| 857 df->parse(text, result1, status); |
| 858 if(U_SUCCESS(status)) { |
| 859 errln((UnicodeString)"ERROR: unexpected parse()"); |
| 860 } |
| 861 |
| 862 |
| 863 status = U_ZERO_ERROR; |
| 864 df->applyPattern(pat2, status); |
| 865 df->setDecimalPatternMatchRequired(FALSE); |
| 866 if(U_FAILURE(status)) { |
| 867 errln((UnicodeString)"ERROR: applyPattern(2) failed"); |
| 868 } |
| 869 df->parse(text, result1, status); |
| 870 if(U_FAILURE(status)) { |
| 871 errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status)); |
| 872 } |
| 873 df->setDecimalPatternMatchRequired(TRUE); |
| 874 df->parse(text, result1, status); |
| 875 if(U_SUCCESS(status)) { |
| 876 errln((UnicodeString)"ERROR: unexpected parse(2)"); |
| 877 } |
| 878 } |
| 879 |
796 #endif /* #if !UCONFIG_NO_FORMATTING */ | 880 #endif /* #if !UCONFIG_NO_FORMATTING */ |
OLD | NEW |