2017-01-20 00:20:31 +00:00
// © 2016 and later: Unicode, Inc. and others.
2016-06-15 18:58:17 +00:00
// License & terms of use: http://www.unicode.org/copyright.html
2000-01-15 02:00:06 +00:00
/********************************************************************
2001-02-28 22:26:09 +00:00
* COPYRIGHT :
2016-05-31 21:45:07 +00:00
* Copyright ( c ) 1997 - 2016 , International Business Machines Corporation and
* others . All Rights Reserved .
2000-01-15 02:00:06 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/********************************************************************************
1999-08-16 21:50:52 +00:00
*
* File CNUMTST . C
*
* Madhu Katragadda Creation
*
* Modification History :
*
* Date Name Description
* 06 / 24 / 99 helena Integrated Alan ' s NF enhancements and Java2 bug fixes
* 07 / 15 / 99 helena Ported to HPUX 10 / 11 CC .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/* C API TEST FOR NUMBER FORMAT */
1999-12-28 23:57:50 +00:00
# include "unicode/utypes.h"
2002-09-20 17:54:45 +00:00
# if !UCONFIG_NO_FORMATTING
# include "unicode/uloc.h"
2010-10-12 05:11:41 +00:00
# include "unicode/umisc.h"
1999-12-28 23:57:50 +00:00
# include "unicode/unum.h"
2013-09-11 05:07:00 +00:00
# include "unicode/unumsys.h"
1999-12-28 23:57:50 +00:00
# include "unicode/ustring.h"
2014-02-06 09:41:17 +00:00
# include "unicode/udisplaycontext.h"
2010-10-12 05:11:41 +00:00
1999-08-16 21:50:52 +00:00
# include "cintltst.h"
# include "cnumtst.h"
2001-06-01 17:17:21 +00:00
# include "cmemory.h"
2013-09-11 05:07:00 +00:00
# include "cstring.h"
2004-10-18 02:43:33 +00:00
# include "putilimp.h"
2018-10-25 01:48:55 +00:00
# include "uassert.h"
2012-10-12 19:52:43 +00:00
# include <stdio.h>
2014-02-06 06:31:50 +00:00
# include <stdlib.h>
2001-06-01 17:17:21 +00:00
2012-10-12 19:52:43 +00:00
static const char * tagAssert ( const char * f , int32_t l , const char * msg ) {
static char _fileline [ 1000 ] ;
sprintf ( _fileline , " %s:%d: ASSERT_TRUE(%s) " , f , l , msg ) ;
return _fileline ;
}
# define ASSERT_TRUE(x) assertTrue(tagAssert(__FILE__, __LINE__, #x), (x))
2001-06-01 17:17:21 +00:00
void addNumForTest ( TestNode * * root ) ;
2007-07-17 21:46:59 +00:00
static void TestTextAttributeCrash ( void ) ;
2008-06-20 00:43:45 +00:00
static void TestNBSPInPattern ( void ) ;
2010-09-22 20:00:38 +00:00
static void TestInt64Parse ( void ) ;
2011-07-12 03:22:59 +00:00
static void TestParseCurrency ( void ) ;
2012-07-06 22:47:27 +00:00
static void TestMaxInt ( void ) ;
2012-10-12 19:52:43 +00:00
static void TestNoExponent ( void ) ;
2019-01-25 03:44:17 +00:00
static void TestSignAlwaysShown ( void ) ;
static void TestMinimumGroupingDigits ( void ) ;
static void TestParseCaseSensitive ( void ) ;
2013-06-27 19:49:55 +00:00
static void TestUFormattable ( void ) ;
2013-09-11 05:07:00 +00:00
static void TestUNumberingSystem ( void ) ;
2014-02-06 06:31:50 +00:00
static void TestCurrencyIsoPluralFormat ( void ) ;
2014-01-15 09:31:11 +00:00
static void TestContext ( void ) ;
2014-06-12 21:40:34 +00:00
static void TestCurrencyUsage ( void ) ;
2014-09-07 20:01:55 +00:00
static void TestCurrFmtNegSameAsPositive ( void ) ;
2015-06-23 18:09:52 +00:00
static void TestVariousStylesAndAttributes ( void ) ;
2016-09-15 03:55:22 +00:00
static void TestParseCurrPatternWithDecStyle ( void ) ;
2017-01-16 19:48:33 +00:00
static void TestFormatForFields ( void ) ;
2017-08-17 23:21:03 +00:00
static void TestRBNFRounding ( void ) ;
2018-04-28 05:50:52 +00:00
static void Test12052_NullPointer ( void ) ;
2019-02-05 19:34:29 +00:00
static void TestParseCases ( void ) ;
2019-02-14 08:59:47 +00:00
static void TestSetMaxFracAndRoundIncr ( void ) ;
2019-03-12 19:08:26 +00:00
static void TestIgnorePadding ( void ) ;
2019-08-28 06:19:19 +00:00
static void TestSciNotationMaxFracCap ( void ) ;
2012-07-06 22:47:27 +00:00
2004-05-20 22:02:34 +00:00
# define TESTCASE(x) addTest(root, &x, "tsformat / cnumtst / " #x)
1999-08-16 21:50:52 +00:00
void addNumForTest ( TestNode * * root )
{
2004-05-20 22:02:34 +00:00
TESTCASE ( TestNumberFormat ) ;
2009-02-19 08:41:08 +00:00
TESTCASE ( TestSpelloutNumberParse ) ;
2004-05-20 22:02:34 +00:00
TESTCASE ( TestSignificantDigits ) ;
2010-06-04 05:42:19 +00:00
TESTCASE ( TestSigDigRounding ) ;
2004-05-20 22:02:34 +00:00
TESTCASE ( TestNumberFormatPadding ) ;
TESTCASE ( TestInt64Format ) ;
2004-08-09 07:07:33 +00:00
TESTCASE ( TestNonExistentCurrency ) ;
2006-03-23 05:53:36 +00:00
TESTCASE ( TestCurrencyRegression ) ;
2007-07-17 21:46:59 +00:00
TESTCASE ( TestTextAttributeCrash ) ;
2004-05-20 22:02:34 +00:00
TESTCASE ( TestRBNFFormat ) ;
2017-08-17 23:21:03 +00:00
TESTCASE ( TestRBNFRounding ) ;
2008-06-20 00:43:45 +00:00
TESTCASE ( TestNBSPInPattern ) ;
2010-09-22 21:06:39 +00:00
TESTCASE ( TestInt64Parse ) ;
2011-05-04 12:23:42 +00:00
TESTCASE ( TestParseZero ) ;
2011-07-12 03:22:59 +00:00
TESTCASE ( TestParseCurrency ) ;
2011-12-12 23:28:25 +00:00
TESTCASE ( TestCloneWithRBNF ) ;
2012-07-06 22:47:27 +00:00
TESTCASE ( TestMaxInt ) ;
2012-10-12 19:52:43 +00:00
TESTCASE ( TestNoExponent ) ;
2019-01-25 03:44:17 +00:00
TESTCASE ( TestSignAlwaysShown ) ;
TESTCASE ( TestMinimumGroupingDigits ) ;
TESTCASE ( TestParseCaseSensitive ) ;
2013-06-27 19:49:55 +00:00
TESTCASE ( TestUFormattable ) ;
2013-09-11 05:07:00 +00:00
TESTCASE ( TestUNumberingSystem ) ;
2014-02-06 06:31:50 +00:00
TESTCASE ( TestCurrencyIsoPluralFormat ) ;
2014-01-15 09:31:11 +00:00
TESTCASE ( TestContext ) ;
2014-06-12 21:40:34 +00:00
TESTCASE ( TestCurrencyUsage ) ;
2014-09-07 20:01:55 +00:00
TESTCASE ( TestCurrFmtNegSameAsPositive ) ;
2015-06-23 18:09:52 +00:00
TESTCASE ( TestVariousStylesAndAttributes ) ;
2016-09-15 03:55:22 +00:00
TESTCASE ( TestParseCurrPatternWithDecStyle ) ;
2017-01-16 19:48:33 +00:00
TESTCASE ( TestFormatForFields ) ;
2018-04-28 05:50:52 +00:00
TESTCASE ( Test12052_NullPointer ) ;
2019-02-05 19:34:29 +00:00
TESTCASE ( TestParseCases ) ;
2019-02-14 08:59:47 +00:00
TESTCASE ( TestSetMaxFracAndRoundIncr ) ;
2019-03-12 19:08:26 +00:00
TESTCASE ( TestIgnorePadding ) ;
2019-08-28 06:19:19 +00:00
TESTCASE ( TestSciNotationMaxFracCap ) ;
1999-08-16 21:50:52 +00:00
}
2001-02-28 22:26:09 +00:00
2010-09-22 20:00:38 +00:00
/* test Parse int 64 */
static void TestInt64Parse ( )
{
2010-09-22 21:06:39 +00:00
UErrorCode st = U_ZERO_ERROR ;
UErrorCode * status = & st ;
2011-05-04 12:23:42 +00:00
2010-10-12 05:11:41 +00:00
const char * st1 = " 009223372036854775808 " ;
2010-09-22 21:06:39 +00:00
const int size = 21 ;
UChar text [ 21 ] ;
2011-05-04 12:23:42 +00:00
2010-09-22 20:00:38 +00:00
UNumberFormat * nf ;
2010-09-22 21:06:39 +00:00
int64_t a ;
2010-09-22 20:00:38 +00:00
2010-09-22 21:06:39 +00:00
u_charsToUChars ( st1 , text , size ) ;
nf = unum_open ( UNUM_DEFAULT , NULL , - 1 , NULL , NULL , status ) ;
2010-09-22 20:00:38 +00:00
2010-09-22 21:06:39 +00:00
if ( U_FAILURE ( * status ) )
{
2010-09-25 04:42:19 +00:00
log_data_err ( " Error in unum_open() %s \n " , myErrorName ( * status ) ) ;
2010-09-22 21:06:39 +00:00
return ;
}
2010-09-22 20:00:38 +00:00
2010-09-22 21:06:39 +00:00
log_verbose ( " About to test unum_parseInt64() with out of range number \n " ) ;
2010-09-22 20:00:38 +00:00
2010-09-22 21:06:39 +00:00
a = unum_parseInt64 ( nf , text , size , 0 , status ) ;
2013-03-21 05:48:52 +00:00
( void ) a ; /* Suppress set but not used warning. */
2011-05-04 12:23:42 +00:00
2010-09-22 20:00:38 +00:00
if ( ! U_FAILURE ( * status ) )
{
log_err ( " Error in unum_parseInt64(): %s \n " , myErrorName ( * status ) ) ;
}
2010-09-22 21:06:39 +00:00
else
{
log_verbose ( " unum_parseInt64() successful \n " ) ;
}
2010-09-22 20:00:38 +00:00
2010-09-22 21:06:39 +00:00
unum_close ( nf ) ;
return ;
2010-09-22 20:00:38 +00:00
}
1999-08-16 21:50:52 +00:00
/* test Number Format API */
2000-11-07 18:56:35 +00:00
static void TestNumberFormat ( )
1999-08-16 21:50:52 +00:00
{
2000-08-14 17:13:09 +00:00
UChar * result = NULL ;
2000-11-02 02:44:22 +00:00
UChar temp1 [ 512 ] ;
2001-09-17 21:50:19 +00:00
UChar temp2 [ 512 ] ;
1999-08-16 21:50:52 +00:00
UChar temp [ 5 ] ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
UChar prefix [ 5 ] ;
UChar suffix [ 5 ] ;
2000-05-25 01:10:55 +00:00
UChar symbol [ 20 ] ;
1999-08-16 21:50:52 +00:00
int32_t resultlength ;
int32_t resultlengthneeded ;
int32_t parsepos ;
2006-07-25 02:52:22 +00:00
double d1 = - 1.0 ;
1999-08-16 21:50:52 +00:00
int32_t l1 ;
double d = - 10456.37 ;
2004-04-15 18:15:17 +00:00
double a = 1234.56 , a1 = 1235.0 ;
1999-08-16 21:50:52 +00:00
int32_t l = 100000000 ;
UFieldPosition pos1 ;
UFieldPosition pos2 ;
int32_t numlocales ;
2000-05-25 01:10:55 +00:00
int32_t i ;
1999-08-16 21:50:52 +00:00
UNumberFormatAttribute attr ;
2001-09-17 21:50:19 +00:00
UNumberFormatSymbol symType = UNUM_DECIMAL_SEPARATOR_SYMBOL ;
2001-02-28 22:26:09 +00:00
int32_t newvalue ;
1999-10-07 00:07:53 +00:00
UErrorCode status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
UNumberFormatStyle style = UNUM_DEFAULT ;
UNumberFormat * pattern ;
2000-11-07 18:56:35 +00:00
UNumberFormat * def , * fr , * cur_def , * cur_fr , * per_def , * per_fr ,
2001-11-07 00:02:41 +00:00
* cur_frpattern , * myclone , * spellout_def ;
1999-08-16 21:50:52 +00:00
/* Testing unum_open() with various Numberformat styles and locales*/
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
log_verbose ( " Testing unum_open() with default style and locale \n " ) ;
2001-08-16 00:58:53 +00:00
def = unum_open ( style , NULL , 0 , NULL , NULL , & status ) ;
2004-12-16 02:54:23 +00:00
/* Might as well pack it in now if we can't even get a default NumberFormat... */
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
2004-12-16 02:54:23 +00:00
{
2009-06-09 21:28:13 +00:00
log_data_err ( " Error in creating default NumberFormat using unum_open(): %s (Are you missing data?) \n " , myErrorName ( status ) ) ;
2004-12-16 02:54:23 +00:00
return ;
}
1999-08-16 21:50:52 +00:00
log_verbose ( " \n Testing unum_open() with french locale and default style(decimal) \n " ) ;
2001-08-16 00:58:53 +00:00
fr = unum_open ( style , NULL , 0 , " fr_FR " , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
log_err ( " Error: could not create NumberFormat (french): %s \n " , myErrorName ( status ) ) ;
log_verbose ( " \n Testing unum_open(currency,NULL,status) \n " ) ;
style = UNUM_CURRENCY ;
/* Can't hardcode the result to assume the default locale is "en_US". */
2001-08-16 00:58:53 +00:00
cur_def = unum_open ( style , NULL , 0 , " en_US " , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
log_err ( " Error: could not create NumberFormat using \n unum_open(currency, NULL, &status) %s \n " ,
myErrorName ( status ) ) ;
log_verbose ( " \n Testing unum_open(currency, frenchlocale, status) \n " ) ;
2001-08-16 00:58:53 +00:00
cur_fr = unum_open ( style , NULL , 0 , " fr_FR " , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
2011-05-04 12:23:42 +00:00
log_err ( " Error: could not create NumberFormat using unum_open(currency, french, &status): %s \n " ,
1999-08-16 21:50:52 +00:00
myErrorName ( status ) ) ;
log_verbose ( " \n Testing unum_open(percent, NULL, status) \n " ) ;
style = UNUM_PERCENT ;
2001-08-16 00:58:53 +00:00
per_def = unum_open ( style , NULL , 0 , NULL , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
log_err ( " Error: could not create NumberFormat using unum_open(percent, NULL, &status): %s \n " , myErrorName ( status ) ) ;
log_verbose ( " \n Testing unum_open(percent,frenchlocale, status) \n " ) ;
2001-08-16 00:58:53 +00:00
per_fr = unum_open ( style , NULL , 0 , " fr_FR " , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
log_err ( " Error: could not create NumberFormat using unum_open(percent, french, &status): %s \n " , myErrorName ( status ) ) ;
log_verbose ( " \n Testing unum_open(spellout, NULL, status) " ) ;
style = UNUM_SPELLOUT ;
2002-04-12 16:53:04 +00:00
spellout_def = unum_open ( style , NULL , 0 , " en_US " , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
log_err ( " Error: could not create NumberFormat using unum_open(spellout, NULL, &status): %s \n " , myErrorName ( status ) ) ;
2001-11-07 00:02:41 +00:00
2000-06-22 01:09:15 +00:00
/* Testing unum_clone(..) */
log_verbose ( " \n Testing unum_clone(fmt, status) " ) ;
status = U_ZERO_ERROR ;
myclone = unum_clone ( def , & status ) ;
if ( U_FAILURE ( status ) )
log_err ( " Error: could not clone unum_clone(def, &status): %s \n " , myErrorName ( status ) ) ;
else
2000-08-11 01:27:17 +00:00
{
2000-06-22 01:09:15 +00:00
log_verbose ( " unum_clone() successful \n " ) ;
2000-08-11 01:27:17 +00:00
}
2001-02-28 22:26:09 +00:00
/*Testing unum_getAvailable() and unum_countAvailable()*/
1999-08-16 21:50:52 +00:00
log_verbose ( " \n Testing getAvailableLocales and countAvailable() \n " ) ;
numlocales = unum_countAvailable ( ) ;
if ( numlocales < 0 )
log_err ( " error in countAvailable " ) ;
else {
log_verbose ( " unum_countAvialable() successful \n " ) ;
log_verbose ( " The no: of locales where number formattting is applicable is %d \n " , numlocales ) ;
}
2000-06-22 01:09:15 +00:00
for ( i = 0 ; i < numlocales ; i + + )
2000-08-11 01:27:17 +00:00
{
2001-02-28 22:26:09 +00:00
log_verbose ( " %s \n " , unum_getAvailable ( i ) ) ;
2000-08-11 01:27:17 +00:00
if ( unum_getAvailable ( i ) = = 0 )
log_err ( " No locale for which number formatting patterns are applicable \n " ) ;
2001-02-28 22:26:09 +00:00
else
2000-08-11 01:27:17 +00:00
log_verbose ( " A locale %s for which number formatting patterns are applicable \n " , unum_getAvailable ( i ) ) ;
}
1999-08-16 21:50:52 +00:00
/*Testing unum_format() and unum_formatdouble()*/
u_uastrcpy ( temp1 , " $100,000,000.00 " ) ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
log_verbose ( " \n Testing unum_format() \n " ) ;
resultlength = 0 ;
2012-02-10 00:38:34 +00:00
pos1 . field = UNUM_INTEGER_FIELD ;
1999-08-16 21:50:52 +00:00
resultlengthneeded = unum_format ( cur_def , l , NULL , resultlength , & pos1 , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
2000-11-07 18:56:35 +00:00
/* for (i = 0; i < 100000; i++) */
2000-11-02 02:44:22 +00:00
{
unum_format ( cur_def , l , result , resultlength , & pos1 , & status ) ;
}
1999-08-16 21:50:52 +00:00
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Error in formatting using unum_format(.....): %s \n " , myErrorName ( status ) ) ;
}
if ( u_strcmp ( result , temp1 ) = = 0 )
2000-11-02 02:44:22 +00:00
log_verbose ( " Pass: Number formatting using unum_format() successful \n " ) ;
1999-08-16 21:50:52 +00:00
else
2000-11-02 02:44:22 +00:00
log_err ( " Fail: Error in number Formatting using unum_format() \n " ) ;
2001-03-08 23:41:16 +00:00
if ( pos1 . beginIndex = = 1 & & pos1 . endIndex = = 12 )
log_verbose ( " Pass: Complete number formatting using unum_format() successful \n " ) ;
else
log_err ( " Fail: Error in complete number Formatting using unum_format() \n Got: b=%d end=%d \n Expected: b=1 end=12 \n " ,
pos1 . beginIndex , pos1 . endIndex ) ;
2001-02-28 22:26:09 +00:00
2012-11-29 01:09:50 +00:00
free ( result ) ;
1999-08-16 21:50:52 +00:00
result = 0 ;
log_verbose ( " \n Testing unum_formatDouble() \n " ) ;
2013-07-08 06:51:38 +00:00
u_uastrcpy ( temp1 , " -$10,456.37 " ) ;
1999-08-16 21:50:52 +00:00
resultlength = 0 ;
2012-02-10 00:38:34 +00:00
pos2 . field = UNUM_FRACTION_FIELD ;
1999-08-16 21:50:52 +00:00
resultlengthneeded = unum_formatDouble ( cur_def , d , NULL , resultlength , & pos2 , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
2000-11-07 18:56:35 +00:00
/* for (i = 0; i < 100000; i++) */
2000-11-02 02:44:22 +00:00
{
unum_formatDouble ( cur_def , d , result , resultlength , & pos2 , & status ) ;
}
1999-08-16 21:50:52 +00:00
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
2000-11-02 02:44:22 +00:00
log_err ( " Error in formatting using unum_formatDouble(.....): %s \n " , myErrorName ( status ) ) ;
1999-08-16 21:50:52 +00:00
}
2006-07-13 18:53:36 +00:00
if ( result & & u_strcmp ( result , temp1 ) = = 0 )
1999-08-16 21:50:52 +00:00
log_verbose ( " Pass: Number Formatting using unum_formatDouble() Successful \n " ) ;
2013-09-05 05:32:56 +00:00
else {
log_err ( " FAIL: Error in number formatting using unum_formatDouble() - got '%s' expected '%s' \n " ,
aescstrdup ( result , - 1 ) , aescstrdup ( temp1 , - 1 ) ) ;
}
2001-03-08 23:41:16 +00:00
if ( pos2 . beginIndex = = 9 & & pos2 . endIndex = = 11 )
log_verbose ( " Pass: Complete number formatting using unum_format() successful \n " ) ;
else
log_err ( " Fail: Error in complete number Formatting using unum_formatDouble() \n Got: b=%d end=%d \n Expected: b=9 end=11 " ,
pos1 . beginIndex , pos1 . endIndex ) ;
1999-08-16 21:50:52 +00:00
/* Testing unum_parse() and unum_parseDouble() */
log_verbose ( " \n Testing unum_parseDouble() \n " ) ;
2000-10-25 16:57:32 +00:00
/* for (i = 0; i < 100000; i++)*/
2012-11-29 01:09:50 +00:00
parsepos = 0 ;
if ( result ! = NULL ) {
d1 = unum_parseDouble ( cur_def , result , u_strlen ( result ) , & parsepos , & status ) ;
} else {
log_err ( " result is NULL \n " ) ;
2006-07-13 18:53:36 +00:00
}
2012-11-29 01:09:50 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " parse of '%s' failed. Parsepos=%d. The error is : %s \n " , aescstrdup ( result , u_strlen ( result ) ) , parsepos , myErrorName ( status ) ) ;
1999-08-16 21:50:52 +00:00
}
if ( d1 ! = d )
log_err ( " Fail: Error in parsing \n " ) ;
else
log_verbose ( " Pass: parsing successful \n " ) ;
2004-04-23 18:02:55 +00:00
if ( result )
free ( result ) ;
result = 0 ;
1999-08-16 21:50:52 +00:00
2012-11-29 01:09:50 +00:00
status = U_ZERO_ERROR ;
2004-04-15 18:15:17 +00:00
/* Testing unum_formatDoubleCurrency / unum_parseDoubleCurrency */
log_verbose ( " \n Testing unum_formatDoubleCurrency \n " ) ;
u_uastrcpy ( temp1 , " Y1,235 " ) ;
temp1 [ 0 ] = 0xA5 ; /* Yen sign */
u_uastrcpy ( temp , " JPY " ) ;
resultlength = 0 ;
2012-02-10 00:38:34 +00:00
pos2 . field = UNUM_INTEGER_FIELD ;
2004-04-15 18:15:17 +00:00
resultlengthneeded = unum_formatDoubleCurrency ( cur_def , a , temp , NULL , resultlength , & pos2 , & status ) ;
if ( status = = U_BUFFER_OVERFLOW_ERROR ) {
status = U_ZERO_ERROR ;
resultlength = resultlengthneeded + 1 ;
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
unum_formatDoubleCurrency ( cur_def , a , temp , result , resultlength , & pos2 , & status ) ;
}
if ( U_FAILURE ( status ) ) {
2013-09-05 05:32:56 +00:00
log_err ( " Error in formatting using unum_formatDoubleCurrency(.....): %s \n " , myErrorName ( status ) ) ;
2004-04-15 18:15:17 +00:00
}
2004-08-13 20:34:31 +00:00
if ( result & & u_strcmp ( result , temp1 ) = = 0 ) {
2013-09-05 05:32:56 +00:00
log_verbose ( " Pass: Number Formatting using unum_formatDoubleCurrency() Successful \n " ) ;
2004-04-15 18:15:17 +00:00
} else {
2013-09-05 05:32:56 +00:00
log_err ( " FAIL: Error in number formatting using unum_formatDoubleCurrency() - got '%s' expected '%s' \n " ,
aescstrdup ( result , - 1 ) , aescstrdup ( temp1 , - 1 ) ) ;
2004-04-15 18:15:17 +00:00
}
if ( pos2 . beginIndex = = 1 & & pos2 . endIndex = = 6 ) {
log_verbose ( " Pass: Complete number formatting using unum_format() successful \n " ) ;
} else {
2006-07-13 18:53:36 +00:00
log_err ( " Fail: Error in complete number Formatting using unum_formatDouble() \n Got: b=%d end=%d \n Expected: b=1 end=6 \n " ,
2004-04-15 18:15:17 +00:00
pos1 . beginIndex , pos1 . endIndex ) ;
}
log_verbose ( " \n Testing unum_parseDoubleCurrency \n " ) ;
parsepos = 0 ;
2006-07-13 18:53:36 +00:00
if ( result = = NULL ) {
log_err ( " result is NULL \n " ) ;
2004-04-15 18:15:17 +00:00
}
2006-07-13 18:53:36 +00:00
else {
d1 = unum_parseDoubleCurrency ( cur_def , result , u_strlen ( result ) , & parsepos , temp2 , & status ) ;
if ( U_FAILURE ( status ) ) {
2012-11-29 01:09:50 +00:00
log_err ( " parseDoubleCurrency '%s' failed. The error is : %s \n " , aescstrdup ( result , u_strlen ( result ) ) , myErrorName ( status ) ) ;
2006-07-13 18:53:36 +00:00
}
/* Note: a==1234.56, but on parse expect a1=1235.0 */
if ( d1 ! = a1 ) {
log_err ( " Fail: Error in parsing currency, got %f, expected %f \n " , d1 , a1 ) ;
} else {
2013-09-05 05:32:56 +00:00
log_verbose ( " Pass: parsed currency amount successfully \n " ) ;
2006-07-13 18:53:36 +00:00
}
if ( u_strcmp ( temp2 , temp ) = = 0 ) {
log_verbose ( " Pass: parsed correct currency \n " ) ;
} else {
log_err ( " Fail: parsed incorrect currency \n " ) ;
}
2004-04-15 18:15:17 +00:00
}
2012-11-29 01:09:50 +00:00
status = U_ZERO_ERROR ; /* reset */
2004-04-15 18:15:17 +00:00
2012-11-29 01:09:50 +00:00
free ( result ) ;
2004-04-15 18:15:17 +00:00
result = 0 ;
2000-10-24 16:18:36 +00:00
/* performance testing */
u_uastrcpy ( temp1 , " $462.12345 " ) ;
resultlength = u_strlen ( temp1 ) ;
2000-10-25 16:57:32 +00:00
/* for (i = 0; i < 100000; i++) */
2000-10-24 16:18:36 +00:00
{
parsepos = 0 ;
d1 = unum_parseDouble ( cur_def , temp1 , resultlength , & parsepos , & status ) ;
}
if ( U_FAILURE ( status ) )
{
2012-11-29 01:09:50 +00:00
log_err ( " parseDouble('%s') failed. The error is : %s \n " , aescstrdup ( temp1 , resultlength ) , myErrorName ( status ) ) ;
2000-10-24 16:18:36 +00:00
}
2010-09-21 19:10:03 +00:00
/*
2011-05-04 12:23:42 +00:00
* Note : " for strict standard conformance all operations and constants are now supposed to be
2010-10-12 05:11:41 +00:00
evaluated in precision of long double " . So, we assign a1 before comparing to a double. Bug #7932.
2010-09-21 19:10:03 +00:00
*/
a1 = 462.12345 ;
if ( d1 ! = a1 )
2000-10-24 16:18:36 +00:00
log_err ( " Fail: Error in parsing \n " ) ;
else
log_verbose ( " Pass: parsing successful \n " ) ;
2002-07-29 21:04:18 +00:00
free ( result ) ;
1999-08-16 21:50:52 +00:00
2000-08-07 23:09:41 +00:00
u_uastrcpy ( temp1 , " ($10,456.3E1]) " ) ;
parsepos = 0 ;
d1 = unum_parseDouble ( cur_def , temp1 , u_strlen ( temp1 ) , & parsepos , & status ) ;
if ( U_SUCCESS ( status ) )
{
log_err ( " Error in unum_parseDouble(..., %s, ...): %s \n " , temp1 , myErrorName ( status ) ) ;
}
log_verbose ( " \n Testing unum_format() \n " ) ;
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = 0 ;
parsepos = 0 ;
resultlengthneeded = unum_format ( per_fr , l , NULL , resultlength , & pos1 , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
2000-11-02 02:44:22 +00:00
/* for (i = 0; i < 100000; i++)*/
{
unum_format ( per_fr , l , result , resultlength , & pos1 , & status ) ;
}
1999-08-16 21:50:52 +00:00
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Error in formatting using unum_format(.....): %s \n " , myErrorName ( status ) ) ;
}
2000-11-02 02:44:22 +00:00
2000-08-07 23:09:41 +00:00
log_verbose ( " \n Testing unum_parse() \n " ) ;
2000-10-25 16:57:32 +00:00
/* for (i = 0; i < 100000; i++) */
2000-10-24 16:18:36 +00:00
{
2000-08-07 23:09:41 +00:00
parsepos = 0 ;
l1 = unum_parse ( per_fr , result , u_strlen ( result ) , & parsepos , & status ) ;
2000-10-24 16:18:36 +00:00
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " parse failed. The error is : %s \n " , myErrorName ( status ) ) ;
}
2000-11-02 02:44:22 +00:00
1999-08-16 21:50:52 +00:00
if ( l1 ! = l )
log_err ( " Fail: Error in parsing \n " ) ;
else
log_verbose ( " Pass: parsing successful \n " ) ;
2000-11-02 02:44:22 +00:00
2002-07-29 21:04:18 +00:00
free ( result ) ;
1999-08-16 21:50:52 +00:00
/* create a number format using unum_openPattern(....)*/
log_verbose ( " \n Testing unum_openPattern() \n " ) ;
u_uastrcpy ( temp1 , " #,##0.0#;(#,##0.0#) " ) ;
2001-08-16 00:58:53 +00:00
pattern = unum_open ( UNUM_IGNORE , temp1 , u_strlen ( temp1 ) , NULL , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
2019-08-07 18:56:02 +00:00
log_err ( " error in unum_openPattern(): %s \n " , myErrorName ( status ) ) ;
1999-08-16 21:50:52 +00:00
}
else
log_verbose ( " Pass: unum_openPattern() works fine \n " ) ;
2000-11-02 02:44:22 +00:00
1999-08-16 21:50:52 +00:00
/*test for unum_toPattern()*/
log_verbose ( " \n Testing unum_toPattern() \n " ) ;
resultlength = 0 ;
resultlengthneeded = unum_toPattern ( pattern , FALSE , NULL , resultlength , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
1999-08-16 21:50:52 +00:00
unum_toPattern ( pattern , FALSE , result , resultlength , & status ) ;
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in extracting the pattern from UNumberFormat: %s \n " , myErrorName ( status ) ) ;
}
else
2000-11-02 02:44:22 +00:00
{
if ( u_strcmp ( result , temp1 ) ! = 0 )
log_err ( " FAIL: Error in extracting the pattern using unum_toPattern() \n " ) ;
else
log_verbose ( " Pass: extracted the pattern correctly using unum_toPattern() \n " ) ;
2002-07-29 21:04:18 +00:00
free ( result ) ;
2000-11-02 02:44:22 +00:00
}
1999-08-16 21:50:52 +00:00
/*Testing unum_getSymbols() and unum_setSymbols()*/
log_verbose ( " \n Testing unum_getSymbols and unum_setSymbols() \n " ) ;
/*when we try to change the symbols of french to default we need to apply the pattern as well to fetch correct results */
resultlength = 0 ;
resultlengthneeded = unum_toPattern ( cur_def , FALSE , NULL , resultlength , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
1999-08-16 21:50:52 +00:00
unum_toPattern ( cur_def , FALSE , result , resultlength , & status ) ;
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in extracting the pattern from UNumberFormat: %s \n " , myErrorName ( status ) ) ;
}
2000-11-02 02:44:22 +00:00
status = U_ZERO_ERROR ;
2001-08-16 00:58:53 +00:00
cur_frpattern = unum_open ( UNUM_IGNORE , result , u_strlen ( result ) , " fr_FR " , NULL , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in unum_openPattern(): %s \n " , myErrorName ( status ) ) ;
}
2001-02-28 22:26:09 +00:00
2002-07-29 21:04:18 +00:00
free ( result ) ;
1999-08-16 21:50:52 +00:00
/*getting the symbols of cur_def */
2001-09-17 21:50:19 +00:00
/*set the symbols of cur_frpattern to cur_def */
for ( symType = UNUM_DECIMAL_SEPARATOR_SYMBOL ; symType < UNUM_FORMAT_SYMBOL_COUNT ; symType + + ) {
status = U_ZERO_ERROR ;
unum_getSymbol ( cur_def , symType , temp1 , sizeof ( temp1 ) , & status ) ;
unum_setSymbol ( cur_frpattern , symType , temp1 , - 1 , & status ) ;
if ( U_FAILURE ( status ) )
{
log_err ( " Error in get/set symbols: %s \n " , myErrorName ( status ) ) ;
}
}
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
/*format to check the result */
resultlength = 0 ;
resultlengthneeded = unum_format ( cur_def , l , NULL , resultlength , & pos1 , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
1999-08-16 21:50:52 +00:00
unum_format ( cur_def , l , result , resultlength , & pos1 , & status ) ;
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Error in formatting using unum_format(.....): %s \n " , myErrorName ( status ) ) ;
}
2001-02-28 22:26:09 +00:00
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) ) {
1999-08-16 21:50:52 +00:00
log_err ( " Fail: error in unum_setSymbols: %s \n " , myErrorName ( status ) ) ;
}
2001-08-16 00:58:53 +00:00
unum_applyPattern ( cur_frpattern , FALSE , result , u_strlen ( result ) , NULL , NULL ) ;
2001-09-17 21:50:19 +00:00
for ( symType = UNUM_DECIMAL_SEPARATOR_SYMBOL ; symType < UNUM_FORMAT_SYMBOL_COUNT ; symType + + ) {
status = U_ZERO_ERROR ;
unum_getSymbol ( cur_def , symType , temp1 , sizeof ( temp1 ) , & status ) ;
unum_getSymbol ( cur_frpattern , symType , temp2 , sizeof ( temp2 ) , & status ) ;
if ( U_FAILURE ( status ) | | u_strcmp ( temp1 , temp2 ) ! = 0 )
{
log_err ( " Fail: error in getting symbols \n " ) ;
}
else
log_verbose ( " Pass: get and set symbols successful \n " ) ;
}
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
/*format and check with the previous result */
resultlength = 0 ;
resultlengthneeded = unum_format ( cur_frpattern , l , NULL , resultlength , & pos1 , & status ) ;
1999-10-07 00:07:53 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
1999-08-16 21:50:52 +00:00
{
1999-10-07 00:07:53 +00:00
status = U_ZERO_ERROR ;
1999-08-16 21:50:52 +00:00
resultlength = resultlengthneeded + 1 ;
unum_format ( cur_frpattern , l , temp1 , resultlength , & pos1 , & status ) ;
}
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Error in formatting using unum_format(.....): %s \n " , myErrorName ( status ) ) ;
}
2011-05-04 12:23:42 +00:00
/* TODO:
2000-05-30 17:21:22 +00:00
* This test fails because we have not called unum_applyPattern ( ) .
* Currently , such an applyPattern ( ) does not exist on the C API , and
* we have jitterbug 411 for it .
* Since it is close to the 1.5 release , I ( markus ) am disabling this test just
* for this release ( I added the test itself only last week ) .
* For the next release , we need to fix this .
* Then , remove the uprv_strcmp ( " 1.5 " , . . . ) and this comment , and the include " cstring.h " at the beginning of this file .
*/
2000-07-21 23:27:47 +00:00
if ( u_strcmp ( result , temp1 ) ! = 0 ) {
2000-08-07 23:09:41 +00:00
log_err ( " Formatting failed after setting symbols. result=%s temp1=%s \n " , result , temp1 ) ;
2000-05-25 01:10:55 +00:00
}
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
/*----------- */
2001-02-28 22:26:09 +00:00
2002-07-29 21:04:18 +00:00
free ( result ) ;
2000-05-25 01:10:55 +00:00
/* Testing unum_get/setSymbol() */
for ( i = 0 ; i < UNUM_FORMAT_SYMBOL_COUNT ; + + i ) {
symbol [ 0 ] = ( UChar ) ( 0x41 + i ) ;
symbol [ 1 ] = ( UChar ) ( 0x61 + i ) ;
2000-08-14 23:35:57 +00:00
unum_setSymbol ( cur_frpattern , ( UNumberFormatSymbol ) i , symbol , 2 , & status ) ;
2000-05-25 01:10:55 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " Error from unum_setSymbol(%d): %s \n " , i , myErrorName ( status ) ) ;
return ;
}
}
for ( i = 0 ; i < UNUM_FORMAT_SYMBOL_COUNT ; + + i ) {
2016-02-24 22:52:29 +00:00
resultlength = unum_getSymbol ( cur_frpattern , ( UNumberFormatSymbol ) i , symbol , UPRV_LENGTHOF ( symbol ) , & status ) ;
2000-05-25 01:10:55 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " Error from unum_getSymbol(%d): %s \n " , i , myErrorName ( status ) ) ;
return ;
}
if ( resultlength ! = 2 | | symbol [ 0 ] ! = 0x41 + i | | symbol [ 1 ] ! = 0x61 + i ) {
log_err ( " Failure in unum_getSymbol(%d): got unexpected symbol \n " , i ) ;
}
}
2000-06-22 01:09:15 +00:00
/*try getting from a bogus symbol*/
2016-02-24 22:52:29 +00:00
unum_getSymbol ( cur_frpattern , ( UNumberFormatSymbol ) i , symbol , UPRV_LENGTHOF ( symbol ) , & status ) ;
2000-06-22 01:09:15 +00:00
if ( U_SUCCESS ( status ) ) {
log_err ( " Error : Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol " ) ;
}
if ( U_FAILURE ( status ) ) {
if ( status ! = U_ILLEGAL_ARGUMENT_ERROR ) {
2001-02-28 22:26:09 +00:00
log_err ( " Error: Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol, Got %s \n " , myErrorName ( status ) ) ;
2000-06-22 01:09:15 +00:00
}
}
status = U_ZERO_ERROR ;
2000-05-25 01:10:55 +00:00
1999-08-16 21:50:52 +00:00
/* Testing unum_getTextAttribute() and unum_setTextAttribute()*/
log_verbose ( " \n Testing getting and setting text attributes \n " ) ;
resultlength = 5 ;
unum_getTextAttribute ( cur_fr , UNUM_NEGATIVE_SUFFIX , temp , resultlength , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Failure in gettting the Text attributes of number format: %s \n " , myErrorName ( status ) ) ;
}
unum_setTextAttribute ( cur_def , UNUM_NEGATIVE_SUFFIX , temp , u_strlen ( temp ) , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Failure in gettting the Text attributes of number format: %s \n " , myErrorName ( status ) ) ;
}
unum_getTextAttribute ( cur_def , UNUM_NEGATIVE_SUFFIX , suffix , resultlength , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " Failure in gettting the Text attributes of number format: %s \n " , myErrorName ( status ) ) ;
}
if ( u_strcmp ( suffix , temp ) ! = 0 )
log_err ( " Fail:Error in setTextAttribute or getTextAttribute in setting and getting suffix \n " ) ;
else
log_verbose ( " Pass: setting and getting suffix works fine \n " ) ;
/*set it back to normal */
u_uastrcpy ( temp , " $ " ) ;
unum_setTextAttribute ( cur_def , UNUM_NEGATIVE_SUFFIX , temp , u_strlen ( temp ) , & status ) ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
/*checking some more text setter conditions */
u_uastrcpy ( prefix , " + " ) ;
unum_setTextAttribute ( def , UNUM_POSITIVE_PREFIX , prefix , u_strlen ( prefix ) , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in setting the text attributes : %s \n " , myErrorName ( status ) ) ;
}
unum_getTextAttribute ( def , UNUM_POSITIVE_PREFIX , temp , resultlength , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in getting the text attributes : %s \n " , myErrorName ( status ) ) ;
}
2001-02-28 22:26:09 +00:00
2011-05-04 12:23:42 +00:00
if ( u_strcmp ( prefix , temp ) ! = 0 )
1999-08-16 21:50:52 +00:00
log_err ( " ERROR: get and setTextAttributes with positive prefix failed \n " ) ;
else
log_verbose ( " Pass: get and setTextAttributes with positive prefix works fine \n " ) ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
u_uastrcpy ( prefix , " + " ) ;
unum_setTextAttribute ( def , UNUM_NEGATIVE_PREFIX , prefix , u_strlen ( prefix ) , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in setting the text attributes : %s \n " , myErrorName ( status ) ) ;
}
unum_getTextAttribute ( def , UNUM_NEGATIVE_PREFIX , temp , resultlength , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in getting the text attributes : %s \n " , myErrorName ( status ) ) ;
}
2011-05-04 12:23:42 +00:00
if ( u_strcmp ( prefix , temp ) ! = 0 )
1999-08-16 21:50:52 +00:00
log_err ( " ERROR: get and setTextAttributes with negative prefix failed \n " ) ;
else
log_verbose ( " Pass: get and setTextAttributes with negative prefix works fine \n " ) ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
u_uastrcpy ( suffix , " + " ) ;
unum_setTextAttribute ( def , UNUM_NEGATIVE_SUFFIX , suffix , u_strlen ( suffix ) , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in setting the text attributes: %s \n " , myErrorName ( status ) ) ;
}
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
unum_getTextAttribute ( def , UNUM_NEGATIVE_SUFFIX , temp , resultlength , & status ) ;
1999-10-18 22:48:32 +00:00
if ( U_FAILURE ( status ) )
1999-08-16 21:50:52 +00:00
{
log_err ( " error in getting the text attributes : %s \n " , myErrorName ( status ) ) ;
}
2011-05-04 12:23:42 +00:00
if ( u_strcmp ( suffix , temp ) ! = 0 )
1999-08-16 21:50:52 +00:00
log_err ( " ERROR: get and setTextAttributes with negative suffix failed \n " ) ;
else
log_verbose ( " Pass: get and settextAttributes with negative suffix works fine \n " ) ;
2000-06-22 01:09:15 +00:00
u_uastrcpy ( suffix , " ++ " ) ;
unum_setTextAttribute ( def , UNUM_POSITIVE_SUFFIX , suffix , u_strlen ( suffix ) , & status ) ;
if ( U_FAILURE ( status ) )
{
log_err ( " error in setting the text attributes: %s \n " , myErrorName ( status ) ) ;
}
2001-02-28 22:26:09 +00:00
2000-06-22 01:09:15 +00:00
unum_getTextAttribute ( def , UNUM_POSITIVE_SUFFIX , temp , resultlength , & status ) ;
if ( U_FAILURE ( status ) )
{
log_err ( " error in getting the text attributes : %s \n " , myErrorName ( status ) ) ;
}
2011-05-04 12:23:42 +00:00
if ( u_strcmp ( suffix , temp ) ! = 0 )
2000-06-22 01:09:15 +00:00
log_err ( " ERROR: get and setTextAttributes with negative suffix failed \n " ) ;
else
log_verbose ( " Pass: get and settextAttributes with negative suffix works fine \n " ) ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
/*Testing unum_getAttribute and unum_setAttribute() */
log_verbose ( " \n Testing get and set Attributes \n " ) ;
attr = UNUM_GROUPING_SIZE ;
newvalue = unum_getAttribute ( def , attr ) ;
newvalue = 2 ;
unum_setAttribute ( def , attr , newvalue ) ;
if ( unum_getAttribute ( def , attr ) ! = 2 )
log_err ( " Fail: error in setting and getting attributes for UNUM_GROUPING_SIZE \n " ) ;
else
log_verbose ( " Pass: setting and getting attributes for UNUM_GROUPING_SIZE works fine \n " ) ;
attr = UNUM_MULTIPLIER ;
newvalue = unum_getAttribute ( def , attr ) ;
newvalue = 8 ;
unum_setAttribute ( def , attr , newvalue ) ;
if ( unum_getAttribute ( def , attr ) ! = 8 )
log_err ( " error in setting and getting attributes for UNUM_MULTIPLIER \n " ) ;
else
log_verbose ( " Pass:setting and getting attributes for UNUM_MULTIPLIER works fine \n " ) ;
2001-02-28 22:26:09 +00:00
2004-07-18 10:22:23 +00:00
attr = UNUM_SECONDARY_GROUPING_SIZE ;
newvalue = unum_getAttribute ( def , attr ) ;
newvalue = 2 ;
unum_setAttribute ( def , attr , newvalue ) ;
if ( unum_getAttribute ( def , attr ) ! = 2 )
2018-04-18 03:59:39 +00:00
log_err ( " error in setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE: got %d \n " ,
unum_getAttribute ( def , attr ) ) ;
2004-07-18 10:22:23 +00:00
else
log_verbose ( " Pass:setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE works fine \n " ) ;
1999-08-16 21:50:52 +00:00
/*testing set and get Attributes extensively */
log_verbose ( " \n Testing get and set attributes extensively \n " ) ;
2000-11-07 18:56:35 +00:00
for ( attr = UNUM_PARSE_INT_ONLY ; attr < = UNUM_PADDING_POSITION ; attr = ( UNumberFormatAttribute ) ( ( int32_t ) attr + 1 ) )
{
newvalue = unum_getAttribute ( fr , attr ) ;
unum_setAttribute ( def , attr , newvalue ) ;
if ( unum_getAttribute ( def , attr ) ! = unum_getAttribute ( fr , attr ) )
log_err ( " error in setting and getting attributes \n " ) ;
else
log_verbose ( " Pass: attributes set and retrieved successfully \n " ) ;
1999-08-16 21:50:52 +00:00
}
2002-04-02 02:55:31 +00:00
/*testing spellout format to make sure we can use it successfully.*/
log_verbose ( " \n Testing spellout format \n " ) ;
2002-07-15 19:01:17 +00:00
if ( spellout_def )
{
static const int32_t values [ ] = { 0 , - 5 , 105 , 1005 , 105050 } ;
2016-02-23 10:40:09 +00:00
for ( i = 0 ; i < UPRV_LENGTHOF ( values ) ; + + i ) {
2002-07-15 19:01:17 +00:00
UChar buffer [ 128 ] ;
int32_t len ;
int32_t value = values [ i ] ;
status = U_ZERO_ERROR ;
2016-02-23 10:40:09 +00:00
len = unum_format ( spellout_def , value , buffer , UPRV_LENGTHOF ( buffer ) , NULL , & status ) ;
2002-07-15 19:01:17 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " Error in formatting using unum_format(spellout_fmt, ...): %s \n " , myErrorName ( status ) ) ;
} else {
int32_t pp = 0 ;
int32_t parseResult ;
2016-02-23 10:40:09 +00:00
/*ustrToAstr(buffer, len, logbuf, UPRV_LENGTHOF(logbuf));*/
2012-11-29 01:09:50 +00:00
log_verbose ( " formatted %d as '%s', length: %d \n " , value , aescstrdup ( buffer , len ) , len ) ;
2002-07-15 19:01:17 +00:00
parseResult = unum_parse ( spellout_def , buffer , len , & pp , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " Error in parsing using unum_format(spellout_fmt, ...): %s \n " , myErrorName ( status ) ) ;
} else if ( parseResult ! = value ) {
log_err ( " unum_format result %d != value %d \n " , parseResult , value ) ;
}
2002-04-02 02:55:31 +00:00
}
}
}
2002-07-15 19:01:17 +00:00
else {
log_err ( " Spellout format is unavailable \n " ) ;
2002-04-02 02:55:31 +00:00
}
2001-02-28 22:26:09 +00:00
2010-01-26 08:51:23 +00:00
{ /* Test for ticket #7079 */
UNumberFormat * dec_en ;
UChar groupingSep [ ] = { 0 } ;
UChar numPercent [ ] = { 0x0031 , 0x0032 , 0x0025 , 0 } ; /* "12%" */
double parseResult = 0.0 ;
2011-05-04 12:23:42 +00:00
2010-01-26 08:51:23 +00:00
status = U_ZERO_ERROR ;
dec_en = unum_open ( UNUM_DECIMAL , NULL , 0 , " en_US " , NULL , & status ) ;
unum_setAttribute ( dec_en , UNUM_LENIENT_PARSE , 0 ) ;
unum_setSymbol ( dec_en , UNUM_GROUPING_SEPARATOR_SYMBOL , groupingSep , 0 , & status ) ;
parseResult = unum_parseDouble ( dec_en , numPercent , - 1 , NULL , & status ) ;
/* Without the fix in #7079, the above call will hang */
if ( U_FAILURE ( status ) | | parseResult ! = 12.0 ) {
log_err ( " unum_parseDouble with empty groupingSep: status %s, parseResult %f not 12.0 \n " ,
myErrorName ( status ) , parseResult ) ;
} else {
log_verbose ( " unum_parseDouble with empty groupingSep: no hang, OK \n " ) ;
}
2010-02-25 19:19:53 +00:00
unum_close ( dec_en ) ;
2010-01-26 08:51:23 +00:00
}
2011-05-04 12:23:42 +00:00
2010-10-12 05:11:41 +00:00
{ /* Test parse & format of big decimals. Use a number with too many digits to fit in a double,
to verify that it is taking the pure decimal path . */
UNumberFormat * fmt ;
2011-05-04 12:23:42 +00:00
const char * bdpattern = " #,##0.######### " ;
const char * numInitial = " 12345678900987654321.1234567896 " ;
2010-10-12 05:11:41 +00:00
const char * numFormatted = " 12,345,678,900,987,654,321.12345679 " ;
2018-04-18 03:59:39 +00:00
const char * parseExpected = " 1.234567890098765432112345679E+19 " ;
const char * parseExpected2 = " 3.4567890098765432112345679E+17 " ;
2010-10-12 05:11:41 +00:00
int32_t resultSize = 0 ;
int32_t parsePos = 0 ; /* Output parameter for Parse operations. */
# define DESTCAPACITY 100
UChar dest [ DESTCAPACITY ] ;
char desta [ DESTCAPACITY ] ;
UFieldPosition fieldPos = { 0 } ;
/* Format */
status = U_ZERO_ERROR ;
u_uastrcpy ( dest , bdpattern ) ;
fmt = unum_open ( UNUM_PATTERN_DECIMAL , dest , - 1 , " en " , NULL /*parseError*/ , & status ) ;
if ( U_FAILURE ( status ) ) log_err ( " File %s, Line %d, status = %s \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
2011-05-04 12:23:42 +00:00
resultSize = unum_formatDecimal ( fmt , numInitial , - 1 , dest , DESTCAPACITY , NULL , & status ) ;
2010-10-12 05:11:41 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " File %s, Line %d, status = %s \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
}
u_austrncpy ( desta , dest , DESTCAPACITY ) ;
if ( strcmp ( numFormatted , desta ) ! = 0 ) {
log_err ( " File %s, Line %d, (expected, acutal) = ( \" %s \" , \" %s \" ) \n " ,
__FILE__ , __LINE__ , numFormatted , desta ) ;
}
2019-07-27 01:09:39 +00:00
if ( ( int32_t ) strlen ( numFormatted ) ! = resultSize ) {
2011-05-04 12:23:42 +00:00
log_err ( " File %s, Line %d, (expected, actual) = (%d, %d) \n " ,
2019-07-27 01:09:39 +00:00
__FILE__ , __LINE__ , ( int32_t ) strlen ( numFormatted ) , resultSize ) ;
2010-10-12 05:11:41 +00:00
}
/* Format with a FieldPosition parameter */
2012-02-10 00:38:34 +00:00
fieldPos . field = UNUM_DECIMAL_SEPARATOR_FIELD ;
2011-05-04 12:23:42 +00:00
resultSize = unum_formatDecimal ( fmt , numInitial , - 1 , dest , DESTCAPACITY , & fieldPos , & status ) ;
2010-10-12 05:11:41 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " File %s, Line %d, status = %s \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
}
u_austrncpy ( desta , dest , DESTCAPACITY ) ;
if ( strcmp ( numFormatted , desta ) ! = 0 ) {
log_err ( " File %s, Line %d, (expected, acutal) = ( \" %s \" , \" %s \" ) \n " ,
__FILE__ , __LINE__ , numFormatted , desta ) ;
}
if ( fieldPos . beginIndex ! = 26 ) { /* index of "." in formatted number */
log_err ( " File %s, Line %d, (expected, acutal) = (%d, %d) \n " ,
__FILE__ , __LINE__ , 0 , fieldPos . beginIndex ) ;
}
if ( fieldPos . endIndex ! = 27 ) {
log_err ( " File %s, Line %d, (expected, acutal) = (%d, %d) \n " ,
__FILE__ , __LINE__ , 0 , fieldPos . endIndex ) ;
}
2011-05-04 12:23:42 +00:00
2010-10-12 05:11:41 +00:00
/* Parse */
status = U_ZERO_ERROR ;
u_uastrcpy ( dest , numFormatted ) ; /* Parse the expected output of the formatting test */
resultSize = unum_parseDecimal ( fmt , dest , - 1 , NULL , desta , DESTCAPACITY , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " File %s, Line %d, status = %s \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
}
2018-04-18 03:59:39 +00:00
if ( uprv_strcmp ( parseExpected , desta ) ! = 0 ) {
2010-10-12 05:11:41 +00:00
log_err ( " File %s, Line %d, (expected, actual) = ( \" %s \" , \" %s \" ) \n " ,
__FILE__ , __LINE__ , parseExpected , desta ) ;
2018-04-18 03:59:39 +00:00
} else {
log_verbose ( " File %s, Line %d, got expected = \" %s \" \n " ,
__FILE__ , __LINE__ , desta ) ;
2010-10-12 05:11:41 +00:00
}
2019-07-27 01:09:39 +00:00
if ( ( int32_t ) strlen ( parseExpected ) ! = resultSize ) {
2010-10-12 05:11:41 +00:00
log_err ( " File %s, Line %d, (expected, actual) = (%d, %d) \n " ,
2019-07-27 01:09:39 +00:00
__FILE__ , __LINE__ , ( int32_t ) strlen ( parseExpected ) , resultSize ) ;
2010-10-12 05:11:41 +00:00
}
/* Parse with a parsePos parameter */
2011-05-04 12:23:42 +00:00
2010-10-12 05:11:41 +00:00
status = U_ZERO_ERROR ;
u_uastrcpy ( dest , numFormatted ) ; /* Parse the expected output of the formatting test */
parsePos = 3 ; /* 12,345,678,900,987,654,321.12345679 */
/* start parsing at the the third char */
resultSize = unum_parseDecimal ( fmt , dest , - 1 , & parsePos , desta , DESTCAPACITY , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " File %s, Line %d, status = %s \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
}
2018-04-18 03:59:39 +00:00
if ( strcmp ( parseExpected2 , desta ) ! = 0 ) { /* "3.4567890098765432112345679E+17" */
2010-10-12 05:11:41 +00:00
log_err ( " File %s, Line %d, (expected, actual) = ( \" %s \" , \" %s \" ) \n " ,
2018-04-18 03:59:39 +00:00
__FILE__ , __LINE__ , parseExpected2 , desta ) ;
} else {
log_verbose ( " File %s, Line %d, got expected = \" %s \" \n " ,
__FILE__ , __LINE__ , desta ) ;
2010-10-12 05:11:41 +00:00
}
2019-07-27 01:09:39 +00:00
if ( ( int32_t ) strlen ( numFormatted ) ! = parsePos ) {
2010-10-12 05:11:41 +00:00
log_err ( " File %s, Line %d, parsePos (expected, actual) = ( \" %d \" , \" %d \" ) \n " ,
2019-07-27 01:09:39 +00:00
__FILE__ , __LINE__ , ( int32_t ) strlen ( parseExpected ) , parsePos ) ;
2010-10-12 05:11:41 +00:00
}
unum_close ( fmt ) ;
}
2011-03-22 16:58:58 +00:00
status = U_ZERO_ERROR ;
/* Test invalid symbol argument */
{
int32_t badsymbolLarge = UNUM_FORMAT_SYMBOL_COUNT + 1 ;
int32_t badsymbolSmall = - 1 ;
UChar value [ 10 ] ;
int32_t valueLength = 10 ;
UNumberFormat * fmt = unum_open ( UNUM_DEFAULT , NULL , 0 , NULL , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " File %s, Line %d, status = %s \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
} else {
unum_getSymbol ( fmt , ( UNumberFormatSymbol ) badsymbolLarge , NULL , 0 , & status ) ;
if ( U_SUCCESS ( status ) ) log_err ( " unum_getSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (> UNUM_FORMAT_SYMBOL_COUNT) argument \n " ) ;
status = U_ZERO_ERROR ;
unum_getSymbol ( fmt , ( UNumberFormatSymbol ) badsymbolSmall , NULL , 0 , & status ) ;
if ( U_SUCCESS ( status ) ) log_err ( " unum_getSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (less than 0) argument \n " ) ;
status = U_ZERO_ERROR ;
unum_setSymbol ( fmt , ( UNumberFormatSymbol ) badsymbolLarge , value , valueLength , & status ) ;
if ( U_SUCCESS ( status ) ) log_err ( " unum_setSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (> UNUM_FORMAT_SYMBOL_COUNT) argument \n " ) ;
status = U_ZERO_ERROR ;
unum_setSymbol ( fmt , ( UNumberFormatSymbol ) badsymbolSmall , value , valueLength , & status ) ;
if ( U_SUCCESS ( status ) ) log_err ( " unum_setSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (less than 0) argument \n " ) ;
unum_close ( fmt ) ;
}
}
2010-01-26 08:51:23 +00:00
1999-08-16 21:50:52 +00:00
/*closing the NumberFormat() using unum_close(UNumberFormat*)")*/
unum_close ( def ) ;
unum_close ( fr ) ;
unum_close ( cur_def ) ;
unum_close ( cur_fr ) ;
unum_close ( per_def ) ;
unum_close ( per_fr ) ;
2001-11-07 00:02:41 +00:00
unum_close ( spellout_def ) ;
1999-08-16 21:50:52 +00:00
unum_close ( pattern ) ;
unum_close ( cur_frpattern ) ;
2000-07-06 23:01:50 +00:00
unum_close ( myclone ) ;
2001-02-28 22:26:09 +00:00
1999-08-16 21:50:52 +00:00
}
2000-11-07 18:56:35 +00:00
2011-05-04 12:23:42 +00:00
static void TestParseZero ( void )
{
UErrorCode errorCode = U_ZERO_ERROR ;
2011-05-11 04:42:01 +00:00
UChar input [ ] = { 0x30 , 0 } ; /* Input text is decimal '0' */
UChar pat [ ] = { 0x0023 , 0x003b , 0x0023 , 0 } ; /* {'#', ';', '#', 0}; */
2011-05-04 12:23:42 +00:00
double dbl ;
#if 0
UNumberFormat * unum = unum_open ( UNUM_DECIMAL /*or UNUM_DEFAULT*/ , NULL , - 1 , NULL , NULL , & errorCode ) ;
# else
UNumberFormat * unum = unum_open ( UNUM_PATTERN_DECIMAL /*needs pattern*/ , pat , - 1 , NULL , NULL , & errorCode ) ;
# endif
dbl = unum_parseDouble ( unum , input , - 1 /*u_strlen(input)*/ , 0 /* 0 = start */ , & errorCode ) ;
if ( U_FAILURE ( errorCode ) ) {
2011-05-10 22:01:46 +00:00
log_data_err ( " Result - %s \n " , u_errorName ( errorCode ) ) ;
2011-05-04 12:23:42 +00:00
} else {
log_verbose ( " Double: %f \n " , dbl ) ;
}
2011-05-09 02:35:48 +00:00
unum_close ( unum ) ;
2011-05-04 12:23:42 +00:00
}
2011-07-12 03:22:59 +00:00
static const UChar dollars2Sym [ ] = { 0x24 , 0x32 , 0x2E , 0x30 , 0x30 , 0 } ; /* $2.00 */
static const UChar dollars4Sym [ ] = { 0x24 , 0x34 , 0 } ; /* $4 */
2016-06-30 23:41:56 +00:00
static const UChar dollarsUS4Sym [ ] = { 0x55 , 0x53 , 0x24 , 0x34 , 0 } ; /* US$4 */
2011-07-12 03:22:59 +00:00
static const UChar dollars9Sym [ ] = { 0x39 , 0xA0 , 0x24 , 0 } ; /* 9 $ */
static const UChar pounds3Sym [ ] = { 0xA3 , 0x33 , 0x2E , 0x30 , 0x30 , 0 } ; /* [POUND]3.00 */
static const UChar pounds5Sym [ ] = { 0xA3 , 0x35 , 0 } ; /* [POUND]5 */
static const UChar pounds7Sym [ ] = { 0x37 , 0xA0 , 0xA3 , 0 } ; /* 7 [POUND] */
static const UChar euros4Sym [ ] = { 0x34 , 0x2C , 0x30 , 0x30 , 0xA0 , 0x20AC , 0 } ; /* 4,00 [EURO] */
static const UChar euros6Sym [ ] = { 0x36 , 0xA0 , 0x20AC , 0 } ; /* 6 [EURO] */
static const UChar euros8Sym [ ] = { 0x20AC , 0x38 , 0 } ; /* [EURO]8 */
static const UChar dollars4PluEn [ ] = { 0x34 , 0x20 , 0x55 , 0x53 , 0x20 , 0x64 , 0x6F , 0x6C , 0x6C , 0x61 , 0x72 , 0x73 , 0 } ; /* 4 US dollars*/
static 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 */
static const UChar euros8PluEn [ ] = { 0x38 , 0x20 , 0x65 , 0x75 , 0x72 , 0x6F , 0x73 , 0 } ; /* 8 euros*/
static const UChar euros6PluFr [ ] = { 0x36 , 0x20 , 0x65 , 0x75 , 0x72 , 0x6F , 0x73 , 0 } ; /* 6 euros*/
typedef struct {
const char * locale ;
const char * descrip ;
const UChar * currStr ;
const UChar * plurStr ;
UErrorCode parsDoubExpectErr ;
int32_t parsDoubExpectPos ;
double parsDoubExpectVal ;
UErrorCode parsCurrExpectErr ;
int32_t parsCurrExpectPos ;
double parsCurrExpectVal ;
const char * parsCurrExpectCurr ;
} ParseCurrencyItem ;
static const ParseCurrencyItem parseCurrencyItems [ ] = {
2018-05-24 04:35:16 +00:00
{ " en_US " , " dollars2 " , dollars2Sym , NULL , U_ZERO_ERROR , 5 , 2.0 , U_ZERO_ERROR , 5 , 2.0 , " USD " } ,
{ " en_US " , " dollars4 " , dollars4Sym , dollars4PluEn , U_ZERO_ERROR , 2 , 4.0 , U_ZERO_ERROR , 2 , 4.0 , " USD " } ,
{ " en_US " , " dollars9 " , dollars9Sym , NULL , U_PARSE_ERROR , 1 , 0.0 , U_PARSE_ERROR , 1 , 0.0 , " " } ,
{ " en_US " , " pounds3 " , pounds3Sym , NULL , U_PARSE_ERROR , 0 , 0.0 , U_ZERO_ERROR , 5 , 3.0 , " GBP " } ,
{ " en_US " , " pounds5 " , pounds5Sym , pounds5PluEn , U_PARSE_ERROR , 0 , 0.0 , U_ZERO_ERROR , 2 , 5.0 , " GBP " } ,
{ " en_US " , " pounds7 " , pounds7Sym , NULL , U_PARSE_ERROR , 1 , 0.0 , U_PARSE_ERROR , 1 , 0.0 , " " } ,
{ " en_US " , " euros8 " , euros8Sym , euros8PluEn , U_PARSE_ERROR , 0 , 0.0 , U_ZERO_ERROR , 2 , 8.0 , " EUR " } ,
{ " en_GB " , " pounds3 " , pounds3Sym , NULL , U_ZERO_ERROR , 5 , 3.0 , U_ZERO_ERROR , 5 , 3.0 , " GBP " } ,
{ " en_GB " , " pounds5 " , pounds5Sym , pounds5PluEn , U_ZERO_ERROR , 2 , 5.0 , U_ZERO_ERROR , 2 , 5.0 , " GBP " } ,
{ " en_GB " , " pounds7 " , pounds7Sym , NULL , U_PARSE_ERROR , 1 , 0.0 , U_PARSE_ERROR , 1 , 0.0 , " " } ,
{ " en_GB " , " euros4 " , euros4Sym , NULL , U_PARSE_ERROR , 0 , 0.0 , U_PARSE_ERROR , 0 , 0.0 , " " } ,
{ " en_GB " , " euros6 " , euros6Sym , NULL , U_PARSE_ERROR , 1 , 0.0 , U_PARSE_ERROR , 1 , 0.0 , " " } ,
{ " en_GB " , " euros8 " , euros8Sym , euros8PluEn , U_PARSE_ERROR , 0 , 0.0 , U_ZERO_ERROR , 2 , 8.0 , " EUR " } ,
{ " en_GB " , " dollars4 " , dollarsUS4Sym , dollars4PluEn , U_PARSE_ERROR , 0 , 0.0 , U_ZERO_ERROR , 4 , 4.0 , " USD " } ,
{ " fr_FR " , " euros4 " , euros4Sym , NULL , U_ZERO_ERROR , 6 , 4.0 , U_ZERO_ERROR , 6 , 4.0 , " EUR " } ,
{ " fr_FR " , " euros6 " , euros6Sym , euros6PluFr , U_ZERO_ERROR , 3 , 6.0 , U_ZERO_ERROR , 3 , 6.0 , " EUR " } ,
{ " fr_FR " , " euros8 " , euros8Sym , NULL , U_PARSE_ERROR , 2 , 0.0 , U_PARSE_ERROR , 2 , 0.0 , " " } ,
{ " fr_FR " , " dollars2 " , dollars2Sym , NULL , U_PARSE_ERROR , 0 , 0.0 , U_PARSE_ERROR , 0 , 0.0 , " " } ,
{ " fr_FR " , " dollars4 " , dollars4Sym , NULL , U_PARSE_ERROR , 0 , 0.0 , U_PARSE_ERROR , 0 , 0.0 , " " } ,
2019-02-14 08:59:47 +00:00
2018-05-24 04:35:16 +00:00
{ NULL , NULL , NULL , NULL , 0 , 0 , 0.0 , 0 , 0 , 0.0 , NULL }
2011-07-12 03:22:59 +00:00
} ;
static void TestParseCurrency ( )
{
const ParseCurrencyItem * itemPtr ;
for ( itemPtr = parseCurrencyItems ; itemPtr - > locale ! = NULL ; + + itemPtr ) {
UNumberFormat * unum ;
UErrorCode status ;
double parseVal ;
int32_t parsePos ;
UChar parseCurr [ 4 ] ;
char parseCurrB [ 4 ] ;
status = U_ZERO_ERROR ;
unum = unum_open ( UNUM_CURRENCY , NULL , 0 , itemPtr - > locale , NULL , & status ) ;
if ( U_SUCCESS ( status ) ) {
2017-09-26 21:20:01 +00:00
const UChar * currStr = itemPtr - > currStr ;
2011-07-12 03:22:59 +00:00
status = U_ZERO_ERROR ;
parsePos = 0 ;
2017-09-26 21:20:01 +00:00
parseVal = unum_parseDouble ( unum , currStr , - 1 , & parsePos , & status ) ;
2018-05-24 04:35:16 +00:00
if ( status ! = itemPtr - > parsDoubExpectErr | | parsePos ! = itemPtr - > parsDoubExpectPos | | parseVal ! = itemPtr - > parsDoubExpectVal ) {
2011-07-12 03:22:59 +00:00
log_err ( " UNUM_CURRENCY parseDouble %s/%s, expect %s pos %d val %.1f, get %s pos %d val %.1f \n " ,
itemPtr - > locale , itemPtr - > descrip ,
2018-05-24 04:35:16 +00:00
u_errorName ( itemPtr - > parsDoubExpectErr ) , itemPtr - > parsDoubExpectPos , itemPtr - > parsDoubExpectVal ,
2011-07-12 03:22:59 +00:00
u_errorName ( status ) , parsePos , parseVal ) ;
}
status = U_ZERO_ERROR ;
parsePos = 0 ;
parseCurr [ 0 ] = 0 ;
2017-09-26 21:20:01 +00:00
parseVal = unum_parseDoubleCurrency ( unum , currStr , - 1 , & parsePos , parseCurr , & status ) ;
2011-07-12 03:22:59 +00:00
u_austrncpy ( parseCurrB , parseCurr , 4 ) ;
2018-05-24 04:35:16 +00:00
if ( status ! = itemPtr - > parsCurrExpectErr | | parsePos ! = itemPtr - > parsCurrExpectPos | | parseVal ! = itemPtr - > parsCurrExpectVal | |
2011-07-12 03:22:59 +00:00
strncmp ( parseCurrB , itemPtr - > parsCurrExpectCurr , 4 ) ! = 0 ) {
log_err ( " UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s pos %d val %.1f cur %s, get %s pos %d val %.1f cur %s \n " ,
itemPtr - > locale , itemPtr - > descrip ,
2018-05-24 04:35:16 +00:00
u_errorName ( itemPtr - > parsCurrExpectErr ) , itemPtr - > parsCurrExpectPos , itemPtr - > parsCurrExpectVal , itemPtr - > parsCurrExpectCurr ,
2011-07-12 03:22:59 +00:00
u_errorName ( status ) , parsePos , parseVal , parseCurrB ) ;
}
unum_close ( unum ) ;
} else {
log_data_err ( " unexpected error in unum_open UNUM_CURRENCY for locale %s: '%s' \n " , itemPtr - > locale , u_errorName ( status ) ) ;
}
if ( itemPtr - > plurStr ! = NULL ) {
status = U_ZERO_ERROR ;
unum = unum_open ( UNUM_CURRENCY_PLURAL , NULL , 0 , itemPtr - > locale , NULL , & status ) ;
if ( U_SUCCESS ( status ) ) {
status = U_ZERO_ERROR ;
parsePos = 0 ;
parseVal = unum_parseDouble ( unum , itemPtr - > plurStr , - 1 , & parsePos , & status ) ;
2018-05-24 04:35:16 +00:00
if ( status ! = itemPtr - > parsDoubExpectErr | | parseVal ! = itemPtr - > parsDoubExpectVal ) {
log_err ( " UNUM_CURRENCY parseDouble Plural %s/%s, expect %s val %.1f, get %s val %.1f \n " ,
2011-07-12 03:22:59 +00:00
itemPtr - > locale , itemPtr - > descrip ,
2018-05-24 04:35:16 +00:00
u_errorName ( itemPtr - > parsDoubExpectErr ) , itemPtr - > parsDoubExpectVal ,
2011-07-12 03:22:59 +00:00
u_errorName ( status ) , parseVal ) ;
}
status = U_ZERO_ERROR ;
parsePos = 0 ;
parseCurr [ 0 ] = 0 ;
parseVal = unum_parseDoubleCurrency ( unum , itemPtr - > plurStr , - 1 , & parsePos , parseCurr , & status ) ;
u_austrncpy ( parseCurrB , parseCurr , 4 ) ;
if ( status ! = itemPtr - > parsCurrExpectErr | | parseVal ! = itemPtr - > parsCurrExpectVal | |
strncmp ( parseCurrB , itemPtr - > parsCurrExpectCurr , 4 ) ! = 0 ) {
2018-05-24 04:35:16 +00:00
log_err ( " UNUM_CURRENCY parseDoubleCurrency Plural %s/%s, expect %s val %.1f cur %s, get %s val %.1f cur %s \n " ,
2011-07-12 03:22:59 +00:00
itemPtr - > locale , itemPtr - > descrip ,
u_errorName ( itemPtr - > parsCurrExpectErr ) , itemPtr - > parsCurrExpectVal , itemPtr - > parsCurrExpectCurr ,
u_errorName ( status ) , parseVal , parseCurrB ) ;
}
unum_close ( unum ) ;
} else {
log_data_err ( " unexpected error in unum_open UNUM_CURRENCY_PLURAL for locale %s: '%s' \n " , itemPtr - > locale , u_errorName ( status ) ) ;
}
}
}
}
2009-02-19 08:41:08 +00:00
typedef struct {
const char * testname ;
const char * locale ;
const UChar * source ;
int32_t startPos ;
int32_t value ;
int32_t endPos ;
UErrorCode status ;
} SpelloutParseTest ;
static const UChar ustr_en0 [ ] = { 0x7A , 0x65 , 0x72 , 0x6F , 0 } ; /* zero */
static const UChar ustr_123 [ ] = { 0x31 , 0x32 , 0x33 , 0 } ; /* 123 */
static const UChar ustr_en123 [ ] = { 0x6f , 0x6e , 0x65 , 0x20 , 0x68 , 0x75 , 0x6e , 0x64 , 0x72 , 0x65 , 0x64 ,
2009-03-30 15:00:49 +00:00
0x20 , 0x74 , 0x77 , 0x65 , 0x6e , 0x74 , 0x79 ,
0x2d , 0x74 , 0x68 , 0x72 , 0x65 , 0x65 , 0 } ; /* one hundred twenty-three */
2013-09-07 20:46:42 +00:00
static const UChar ustr_fr123 [ ] = { 0x63 , 0x65 , 0x6e , 0x74 , 0x20 , 0x76 , 0x69 , 0x6e , 0x67 , 0x74 , 0x2d ,
0x74 , 0x72 , 0x6f , 0x69 , 0x73 , 0 } ; /* cent vingt-trois */
2009-02-19 08:41:08 +00:00
static const UChar ustr_ja123 [ ] = { 0x767e , 0x4e8c , 0x5341 , 0x4e09 , 0 } ; /* kanji 100(+)2(*)10(+)3 */
static const SpelloutParseTest spelloutParseTests [ ] = {
/* name loc src start val end status */
{ " en0 " , " en " , ustr_en0 , 0 , 0 , 4 , U_ZERO_ERROR } ,
{ " en0 " , " en " , ustr_en0 , 2 , 0 , 2 , U_PARSE_ERROR } ,
{ " en0 " , " ja " , ustr_en0 , 0 , 0 , 0 , U_PARSE_ERROR } ,
2009-03-30 15:00:49 +00:00
{ " 123 " , " en " , ustr_123 , 0 , 123 , 3 , U_ZERO_ERROR } ,
{ " en123 " , " en " , ustr_en123 , 0 , 123 , 24 , U_ZERO_ERROR } ,
{ " en123 " , " en " , ustr_en123 , 12 , 23 , 24 , U_ZERO_ERROR } ,
2009-02-19 08:41:08 +00:00
{ " en123 " , " fr " , ustr_en123 , 16 , 0 , 16 , U_PARSE_ERROR } ,
{ " fr123 " , " fr " , ustr_fr123 , 0 , 123 , 16 , U_ZERO_ERROR } ,
{ " fr123 " , " fr " , ustr_fr123 , 5 , 23 , 16 , U_ZERO_ERROR } ,
{ " fr123 " , " en " , ustr_fr123 , 0 , 0 , 0 , U_PARSE_ERROR } ,
{ " ja123 " , " ja " , ustr_ja123 , 0 , 123 , 4 , U_ZERO_ERROR } ,
{ " ja123 " , " ja " , ustr_ja123 , 1 , 23 , 4 , U_ZERO_ERROR } ,
{ " ja123 " , " fr " , ustr_ja123 , 0 , 0 , 0 , U_PARSE_ERROR } ,
{ NULL , NULL , NULL , 0 , 0 , 0 , 0 } /* terminator */
} ;
static void TestSpelloutNumberParse ( )
{
const SpelloutParseTest * testPtr ;
for ( testPtr = spelloutParseTests ; testPtr - > testname ! = NULL ; + + testPtr ) {
UErrorCode status = U_ZERO_ERROR ;
2014-09-07 20:01:55 +00:00
int32_t value , position = testPtr - > startPos ;
2009-02-19 08:41:08 +00:00
UNumberFormat * nf = unum_open ( UNUM_SPELLOUT , NULL , 0 , testPtr - > locale , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " unum_open fails for UNUM_SPELLOUT with locale %s, status %s \n " , testPtr - > locale , myErrorName ( status ) ) ;
2009-02-19 08:41:08 +00:00
continue ;
}
2016-06-10 21:49:00 +00:00
status = U_ZERO_ERROR ;
2009-02-19 08:41:08 +00:00
value = unum_parse ( nf , testPtr - > source , - 1 , & position , & status ) ;
if ( value ! = testPtr - > value | | position ! = testPtr - > endPos | | status ! = testPtr - > status ) {
log_err ( " unum_parse SPELLOUT, locale %s, testname %s, startPos %d: for value / endPos / status, expected %d / %d / %s, got %d / %d / %s \n " ,
testPtr - > locale , testPtr - > testname , testPtr - > startPos ,
testPtr - > value , testPtr - > endPos , myErrorName ( testPtr - > status ) ,
value , position , myErrorName ( status ) ) ;
}
unum_close ( nf ) ;
}
}
2004-04-29 17:50:01 +00:00
static void TestSignificantDigits ( )
{
UChar temp [ 128 ] ;
int32_t resultlengthneeded ;
int32_t resultlength ;
UErrorCode status = U_ZERO_ERROR ;
2004-05-19 06:13:31 +00:00
UChar * result = NULL ;
2004-04-29 17:50:01 +00:00
UNumberFormat * fmt ;
double d = 123456.789 ;
u_uastrcpy ( temp , " ###0.0# " ) ;
2018-04-28 03:53:57 +00:00
fmt = unum_open ( UNUM_IGNORE , temp , - 1 , " en " , NULL , & status ) ;
2004-04-29 17:50:01 +00:00
if ( U_FAILURE ( status ) ) {
2011-05-10 22:01:46 +00:00
log_data_err ( " got unexpected error for unum_open: '%s' \n " , u_errorName ( status ) ) ;
2008-02-19 05:05:51 +00:00
return ;
2004-04-29 17:50:01 +00:00
}
unum_setAttribute ( fmt , UNUM_SIGNIFICANT_DIGITS_USED , TRUE ) ;
unum_setAttribute ( fmt , UNUM_MAX_SIGNIFICANT_DIGITS , 6 ) ;
u_uastrcpy ( temp , " 123457 " ) ;
resultlength = 0 ;
resultlengthneeded = unum_formatDouble ( fmt , d , NULL , resultlength , NULL , & status ) ;
if ( status = = U_BUFFER_OVERFLOW_ERROR )
{
status = U_ZERO_ERROR ;
resultlength = resultlengthneeded + 1 ;
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
unum_formatDouble ( fmt , d , result , resultlength , NULL , & status ) ;
}
if ( U_FAILURE ( status ) )
{
log_err ( " Error in formatting using unum_formatDouble(.....): %s \n " , myErrorName ( status ) ) ;
2004-05-19 06:13:31 +00:00
return ;
2004-04-29 17:50:01 +00:00
}
if ( u_strcmp ( result , temp ) = = 0 )
log_verbose ( " Pass: Number Formatting using unum_formatDouble() Successful \n " ) ;
else
log_err ( " FAIL: Error in number formatting using unum_formatDouble() \n " ) ;
free ( result ) ;
2004-05-14 05:39:37 +00:00
unum_close ( fmt ) ;
2004-04-29 17:50:01 +00:00
}
2010-06-04 05:42:19 +00:00
static void TestSigDigRounding ( )
{
UErrorCode status = U_ZERO_ERROR ;
UChar expected [ 128 ] ;
UChar result [ 128 ] ;
2014-09-07 20:01:55 +00:00
char temp1 [ 128 ] ;
char temp2 [ 128 ] ;
2010-06-04 05:42:19 +00:00
UNumberFormat * fmt ;
double d = 123.4 ;
2018-04-28 03:53:57 +00:00
fmt = unum_open ( UNUM_DECIMAL , NULL , 0 , " en " , NULL , & status ) ;
2010-06-04 05:42:19 +00:00
if ( U_FAILURE ( status ) ) {
2010-07-14 16:09:03 +00:00
log_data_err ( " got unexpected error for unum_open: '%s' \n " , u_errorName ( status ) ) ;
2010-06-04 05:42:19 +00:00
return ;
}
unum_setAttribute ( fmt , UNUM_LENIENT_PARSE , FALSE ) ;
unum_setAttribute ( fmt , UNUM_SIGNIFICANT_DIGITS_USED , TRUE ) ;
unum_setAttribute ( fmt , UNUM_MAX_SIGNIFICANT_DIGITS , 2 ) ;
2010-06-07 18:46:34 +00:00
/* unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 0); */
2010-06-04 05:42:19 +00:00
unum_setAttribute ( fmt , UNUM_ROUNDING_MODE , UNUM_ROUND_UP ) ;
unum_setDoubleAttribute ( fmt , UNUM_ROUNDING_INCREMENT , 20.0 ) ;
2016-02-23 10:40:09 +00:00
( void ) unum_formatDouble ( fmt , d , result , UPRV_LENGTHOF ( result ) , NULL , & status ) ;
2010-06-04 05:42:19 +00:00
if ( U_FAILURE ( status ) )
{
log_err ( " Error in formatting using unum_formatDouble(.....): %s \n " , myErrorName ( status ) ) ;
return ;
}
u_uastrcpy ( expected , " 140 " ) ;
if ( u_strcmp ( result , expected ) ! = 0 )
log_err ( " FAIL: Error in unum_formatDouble result %s instead of %s \n " , u_austrcpy ( temp1 , result ) , u_austrcpy ( temp2 , expected ) ) ;
2011-05-04 12:23:42 +00:00
2010-06-04 05:42:19 +00:00
unum_close ( fmt ) ;
}
2000-11-07 18:56:35 +00:00
static void TestNumberFormatPadding ( )
{
UChar * result = NULL ;
UChar temp1 [ 512 ] ;
2018-04-18 03:59:39 +00:00
UChar temp2 [ 512 ] ;
2000-11-07 18:56:35 +00:00
UErrorCode status = U_ZERO_ERROR ;
int32_t resultlength ;
int32_t resultlengthneeded ;
UNumberFormat * pattern ;
double d1 ;
double d = - 10456.37 ;
2001-03-08 23:41:16 +00:00
UFieldPosition pos1 ;
2000-11-07 18:56:35 +00:00
int32_t parsepos ;
/* create a number format using unum_openPattern(....)*/
log_verbose ( " \n Testing unum_openPattern() with padding \n " ) ;
u_uastrcpy ( temp1 , " *#,##0.0#*;(#,##0.0#) " ) ;
status = U_ZERO_ERROR ;
2001-08-16 00:58:53 +00:00
pattern = unum_open ( UNUM_IGNORE , temp1 , u_strlen ( temp1 ) , NULL , NULL , & status ) ;
2000-11-07 18:56:35 +00:00
if ( U_SUCCESS ( status ) )
{
2009-06-09 21:28:13 +00:00
log_err ( " error in unum_openPattern(%s): %s \n " , temp1 , myErrorName ( status ) ) ;
2000-11-07 18:56:35 +00:00
}
2000-12-14 01:19:54 +00:00
else
{
unum_close ( pattern ) ;
}
2000-11-07 18:56:35 +00:00
/* u_uastrcpy(temp1, "*x#,###,###,##0.0#;(*x#,###,###,##0.0#)"); */
2018-04-18 03:59:39 +00:00
u_uastrcpy ( temp1 , " *x#,###,###,##0.0#;*x(###,###,##0.0#) " ) ; // input pattern
u_uastrcpy ( temp2 , " *x#########,##0.0#;(#########,##0.0#) " ) ; // equivalent (?) output pattern
2000-11-07 18:56:35 +00:00
status = U_ZERO_ERROR ;
2001-08-16 00:58:53 +00:00
pattern = unum_open ( UNUM_IGNORE , temp1 , u_strlen ( temp1 ) , " en_US " , NULL , & status ) ;
2000-11-07 18:56:35 +00:00
if ( U_FAILURE ( status ) )
{
2019-08-07 18:56:02 +00:00
log_err_status ( status , " error in padding unum_openPattern(%s): %s \n " , temp1 , myErrorName ( status ) ) ;
2000-11-07 18:56:35 +00:00
}
else {
log_verbose ( " Pass: padding unum_openPattern() works fine \n " ) ;
/*test for unum_toPattern()*/
log_verbose ( " \n Testing padding unum_toPattern() \n " ) ;
resultlength = 0 ;
resultlengthneeded = unum_toPattern ( pattern , FALSE , NULL , resultlength , & status ) ;
if ( status = = U_BUFFER_OVERFLOW_ERROR )
{
status = U_ZERO_ERROR ;
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
2000-11-07 18:56:35 +00:00
unum_toPattern ( pattern , FALSE , result , resultlength , & status ) ;
}
if ( U_FAILURE ( status ) )
{
log_err ( " error in extracting the padding pattern from UNumberFormat: %s \n " , myErrorName ( status ) ) ;
}
else
{
2018-04-18 03:59:39 +00:00
if ( u_strncmp ( result , temp2 , resultlengthneeded ) ! = 0 ) {
log_err (
" FAIL: Error in extracting the padding pattern using unum_toPattern(): %d: %s != %s \n " ,
resultlengthneeded ,
austrdup ( temp2 ) ,
austrdup ( result ) ) ;
} else {
2000-11-07 18:56:35 +00:00
log_verbose ( " Pass: extracted the padding pattern correctly using unum_toPattern() \n " ) ;
2018-04-18 03:59:39 +00:00
}
2000-11-07 18:56:35 +00:00
}
2018-04-18 03:59:39 +00:00
free ( result ) ;
2000-11-07 18:56:35 +00:00
/* u_uastrcpy(temp1, "(xxxxxxx10,456.37)"); */
2000-12-06 18:42:36 +00:00
u_uastrcpy ( temp1 , " xxxxx(10,456.37) " ) ;
2000-11-07 18:56:35 +00:00
resultlength = 0 ;
2012-02-10 00:38:34 +00:00
pos1 . field = UNUM_FRACTION_FIELD ;
2001-03-08 23:41:16 +00:00
resultlengthneeded = unum_formatDouble ( pattern , d , NULL , resultlength , & pos1 , & status ) ;
2000-11-07 18:56:35 +00:00
if ( status = = U_BUFFER_OVERFLOW_ERROR )
{
status = U_ZERO_ERROR ;
resultlength = resultlengthneeded + 1 ;
2002-07-29 21:04:18 +00:00
result = ( UChar * ) malloc ( sizeof ( UChar ) * resultlength ) ;
2001-03-08 23:41:16 +00:00
unum_formatDouble ( pattern , d , result , resultlength , NULL , & status ) ;
2000-11-07 18:56:35 +00:00
}
if ( U_FAILURE ( status ) )
{
log_err ( " Error in formatting using unum_formatDouble(.....) with padding : %s \n " , myErrorName ( status ) ) ;
}
else
2000-12-14 01:19:54 +00:00
{
if ( u_strcmp ( result , temp1 ) = = 0 )
log_verbose ( " Pass: Number Formatting using unum_formatDouble() padding Successful \n " ) ;
else
2010-07-14 16:09:03 +00:00
log_data_err ( " FAIL: Error in number formatting using unum_formatDouble() with padding \n " ) ;
2001-03-08 23:41:16 +00:00
if ( pos1 . beginIndex = = 13 & & pos1 . endIndex = = 15 )
log_verbose ( " Pass: Complete number formatting using unum_formatDouble() successful \n " ) ;
else
log_err ( " Fail: Error in complete number Formatting using unum_formatDouble() \n Got: b=%d end=%d \n Expected: b=13 end=15 \n " ,
pos1 . beginIndex , pos1 . endIndex ) ;
2000-11-07 18:56:35 +00:00
2000-12-14 01:19:54 +00:00
/* Testing unum_parse() and unum_parseDouble() */
log_verbose ( " \n Testing padding unum_parseDouble() \n " ) ;
parsepos = 0 ;
d1 = unum_parseDouble ( pattern , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) )
{
log_err ( " padding parse failed. The error is : %s \n " , myErrorName ( status ) ) ;
}
2000-11-07 18:56:35 +00:00
2000-12-14 01:19:54 +00:00
if ( d1 ! = d )
log_err ( " Fail: Error in padding parsing \n " ) ;
else
log_verbose ( " Pass: padding parsing successful \n " ) ;
2002-07-29 21:04:18 +00:00
free ( result ) ;
2000-12-14 01:19:54 +00:00
}
2000-11-07 18:56:35 +00:00
}
unum_close ( pattern ) ;
2000-11-30 20:55:12 +00:00
}
2003-11-04 23:10:46 +00:00
static UBool
withinErr ( double a , double b , double err ) {
2011-05-04 12:23:42 +00:00
return uprv_fabs ( a - b ) < uprv_fabs ( a * err ) ;
2003-11-04 23:10:46 +00:00
}
static void TestInt64Format ( ) {
2004-03-16 17:09:44 +00:00
UChar temp1 [ 512 ] ;
UChar result [ 512 ] ;
UNumberFormat * fmt ;
UErrorCode status = U_ZERO_ERROR ;
const double doubleInt64Max = ( double ) U_INT64_MAX ;
const double doubleInt64Min = ( double ) U_INT64_MIN ;
2011-05-04 12:23:42 +00:00
const double doubleBig = 10.0 * ( double ) U_INT64_MAX ;
2004-03-16 17:09:44 +00:00
int32_t val32 ;
int64_t val64 ;
double valDouble ;
int32_t parsepos ;
/* create a number format using unum_openPattern(....) */
log_verbose ( " \n Testing Int64Format \n " ) ;
u_uastrcpy ( temp1 , " #.#E0 " ) ;
2016-09-03 01:30:52 +00:00
fmt = unum_open ( UNUM_IGNORE , temp1 , u_strlen ( temp1 ) , " en_US " , NULL , & status ) ;
2004-03-16 17:09:44 +00:00
if ( U_FAILURE ( status ) ) {
2011-05-10 22:01:46 +00:00
log_data_err ( " error in unum_openPattern() - %s \n " , myErrorName ( status ) ) ;
2003-11-04 23:10:46 +00:00
} else {
2004-03-16 17:09:44 +00:00
unum_setAttribute ( fmt , UNUM_MAX_FRACTION_DIGITS , 20 ) ;
unum_formatInt64 ( fmt , U_INT64_MAX , result , 512 , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " error in unum_format(): %s \n " , myErrorName ( status ) ) ;
} else {
log_verbose ( " format int64max: '%s' \n " , result ) ;
parsepos = 0 ;
val32 = unum_parse ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( status ! = U_INVALID_FORMAT_ERROR ) {
log_err ( " parse didn't report error: %s \n " , myErrorName ( status ) ) ;
} else if ( val32 ! = INT32_MAX ) {
log_err ( " parse didn't pin return value, got: %d \n " , val32 ) ;
}
status = U_ZERO_ERROR ;
parsepos = 0 ;
val64 = unum_parseInt64 ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " parseInt64 returned error: %s \n " , myErrorName ( status ) ) ;
} else if ( val64 ! = U_INT64_MAX ) {
log_err ( " parseInt64 returned incorrect value, got: %ld \n " , val64 ) ;
}
status = U_ZERO_ERROR ;
parsepos = 0 ;
valDouble = unum_parseDouble ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " parseDouble returned error: %s \n " , myErrorName ( status ) ) ;
} else if ( valDouble ! = doubleInt64Max ) {
log_err ( " parseDouble returned incorrect value, got: %g \n " , valDouble ) ;
}
}
unum_formatInt64 ( fmt , U_INT64_MIN , result , 512 , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " error in unum_format(): %s \n " , myErrorName ( status ) ) ;
} else {
log_verbose ( " format int64min: '%s' \n " , result ) ;
parsepos = 0 ;
val32 = unum_parse ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( status ! = U_INVALID_FORMAT_ERROR ) {
log_err ( " parse didn't report error: %s \n " , myErrorName ( status ) ) ;
} else if ( val32 ! = INT32_MIN ) {
log_err ( " parse didn't pin return value, got: %d \n " , val32 ) ;
}
status = U_ZERO_ERROR ;
parsepos = 0 ;
val64 = unum_parseInt64 ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " parseInt64 returned error: %s \n " , myErrorName ( status ) ) ;
} else if ( val64 ! = U_INT64_MIN ) {
log_err ( " parseInt64 returned incorrect value, got: %ld \n " , val64 ) ;
}
status = U_ZERO_ERROR ;
parsepos = 0 ;
valDouble = unum_parseDouble ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " parseDouble returned error: %s \n " , myErrorName ( status ) ) ;
} else if ( valDouble ! = doubleInt64Min ) {
log_err ( " parseDouble returned incorrect value, got: %g \n " , valDouble ) ;
}
}
unum_formatDouble ( fmt , doubleBig , result , 512 , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " error in unum_format(): %s \n " , myErrorName ( status ) ) ;
} else {
log_verbose ( " format doubleBig: '%s' \n " , result ) ;
parsepos = 0 ;
val32 = unum_parse ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( status ! = U_INVALID_FORMAT_ERROR ) {
log_err ( " parse didn't report error: %s \n " , myErrorName ( status ) ) ;
} else if ( val32 ! = INT32_MAX ) {
log_err ( " parse didn't pin return value, got: %d \n " , val32 ) ;
}
status = U_ZERO_ERROR ;
parsepos = 0 ;
val64 = unum_parseInt64 ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( status ! = U_INVALID_FORMAT_ERROR ) {
log_err ( " parseInt64 didn't report error error: %s \n " , myErrorName ( status ) ) ;
} else if ( val64 ! = U_INT64_MAX ) {
log_err ( " parseInt64 returned incorrect value, got: %ld \n " , val64 ) ;
}
status = U_ZERO_ERROR ;
parsepos = 0 ;
valDouble = unum_parseDouble ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " parseDouble returned error: %s \n " , myErrorName ( status ) ) ;
} else if ( ! withinErr ( valDouble , doubleBig , 1e-15 ) ) {
log_err ( " parseDouble returned incorrect value, got: %g \n " , valDouble ) ;
}
2011-03-07 20:02:28 +00:00
}
2014-09-07 20:01:55 +00:00
u_uastrcpy ( result , " 5.06e-27 " ) ;
2011-03-07 20:02:28 +00:00
parsepos = 0 ;
valDouble = unum_parseDouble ( fmt , result , u_strlen ( result ) , & parsepos , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " parseDouble() returned error: %s \n " , myErrorName ( status ) ) ;
} else if ( ! withinErr ( valDouble , 5.06e-27 , 1e-15 ) ) {
log_err ( " parseDouble() returned incorrect value, got: %g \n " , valDouble ) ;
2004-03-16 17:09:44 +00:00
}
}
unum_close ( fmt ) ;
2003-11-04 23:10:46 +00:00
}
2004-03-12 20:15:13 +00:00
2004-05-19 06:13:31 +00:00
static void test_fmt ( UNumberFormat * fmt , UBool isDecimal ) {
char temp [ 512 ] ;
2004-03-16 17:09:44 +00:00
UChar buffer [ 512 ] ;
2016-02-23 10:40:09 +00:00
int32_t BUFSIZE = UPRV_LENGTHOF ( buffer ) ;
2004-03-16 17:09:44 +00:00
double vals [ ] = {
- .2 , 0 , .2 , 5.5 , 15.2 , 250 , 123456789
} ;
int i ;
2016-02-23 10:40:09 +00:00
for ( i = 0 ; i < UPRV_LENGTHOF ( vals ) ; + + i ) {
2004-03-16 17:09:44 +00:00
UErrorCode status = U_ZERO_ERROR ;
unum_formatDouble ( fmt , vals [ i ] , buffer , BUFSIZE , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " failed to format: %g, returned %s \n " , vals [ i ] , u_errorName ( status ) ) ;
} else {
u_austrcpy ( temp , buffer ) ;
log_verbose ( " formatting %g returned '%s' \n " , vals [ i ] , temp ) ;
}
}
/* check APIs now */
{
UErrorCode status = U_ZERO_ERROR ;
UParseError perr ;
2004-05-19 06:13:31 +00:00
u_uastrcpy ( buffer , " #,##0.0# " ) ;
unum_applyPattern ( fmt , FALSE , buffer , - 1 , & perr , & status ) ;
2004-03-16 17:09:44 +00:00
if ( isDecimal ? U_FAILURE ( status ) : ( status ! = U_UNSUPPORTED_ERROR ) ) {
log_err ( " got unexpected error for applyPattern: '%s' \n " , u_errorName ( status ) ) ;
}
}
{
int isLenient = unum_getAttribute ( fmt , UNUM_LENIENT_PARSE ) ;
log_verbose ( " lenient: 0x%x \n " , isLenient ) ;
2011-05-04 12:23:42 +00:00
if ( isLenient ! = FALSE ) {
2004-03-16 17:09:44 +00:00
log_err ( " didn't expect lenient value: %d \n " , isLenient ) ;
}
unum_setAttribute ( fmt , UNUM_LENIENT_PARSE , TRUE ) ;
isLenient = unum_getAttribute ( fmt , UNUM_LENIENT_PARSE ) ;
2011-05-04 12:23:42 +00:00
if ( isLenient ! = TRUE ) {
2004-03-16 17:09:44 +00:00
log_err ( " didn't expect lenient value after set: %d \n " , isLenient ) ;
}
}
{
double val2 ;
double val = unum_getDoubleAttribute ( fmt , UNUM_LENIENT_PARSE ) ;
if ( val ! = - 1 ) {
log_err ( " didn't expect double attribute \n " ) ;
}
val = unum_getDoubleAttribute ( fmt , UNUM_ROUNDING_INCREMENT ) ;
if ( ( val = = - 1 ) = = isDecimal ) {
log_err ( " didn't expect -1 rounding increment \n " ) ;
}
unum_setDoubleAttribute ( fmt , UNUM_ROUNDING_INCREMENT , val + .5 ) ;
val2 = unum_getDoubleAttribute ( fmt , UNUM_ROUNDING_INCREMENT ) ;
if ( isDecimal & & ( val2 - val ! = .5 ) ) {
log_err ( " set rounding increment had no effect on decimal format " ) ;
}
}
{
UErrorCode status = U_ZERO_ERROR ;
int len = unum_getTextAttribute ( fmt , UNUM_DEFAULT_RULESET , buffer , BUFSIZE , & status ) ;
if ( isDecimal ? ( status ! = U_UNSUPPORTED_ERROR ) : U_FAILURE ( status ) ) {
log_err ( " got unexpected error for get default ruleset: '%s' \n " , u_errorName ( status ) ) ;
}
if ( U_SUCCESS ( status ) ) {
u_austrcpy ( temp , buffer ) ;
log_verbose ( " default ruleset: '%s' \n " , temp ) ;
}
status = U_ZERO_ERROR ;
len = unum_getTextAttribute ( fmt , UNUM_PUBLIC_RULESETS , buffer , BUFSIZE , & status ) ;
if ( isDecimal ? ( status ! = U_UNSUPPORTED_ERROR ) : U_FAILURE ( status ) ) {
log_err ( " got unexpected error for get public rulesets: '%s' \n " , u_errorName ( status ) ) ;
}
if ( U_SUCCESS ( status ) ) {
u_austrcpy ( temp , buffer ) ;
log_verbose ( " public rulesets: '%s' \n " , temp ) ;
/* set the default ruleset to the first one found, and retry */
if ( len > 0 ) {
2019-08-07 18:56:02 +00:00
for ( i = 0 ; i < len & & temp [ i ] ! = ' ; ' ; + + i ) { }
2004-03-16 17:09:44 +00:00
if ( i < len ) {
buffer [ i ] = 0 ;
unum_setTextAttribute ( fmt , UNUM_DEFAULT_RULESET , buffer , - 1 , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unexpected error setting default ruleset: '%s' \n " , u_errorName ( status ) ) ;
} else {
int len2 = unum_getTextAttribute ( fmt , UNUM_DEFAULT_RULESET , buffer , BUFSIZE , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " could not fetch default ruleset: '%s' \n " , u_errorName ( status ) ) ;
} else if ( len2 ! = i ) {
u_austrcpy ( temp , buffer ) ;
log_err ( " unexpected ruleset len: %d ex: %d val: %s \n " , len2 , i , temp ) ;
} else {
2016-02-23 10:40:09 +00:00
for ( i = 0 ; i < UPRV_LENGTHOF ( vals ) ; + + i ) {
2004-05-19 06:13:31 +00:00
status = U_ZERO_ERROR ;
2004-03-16 17:09:44 +00:00
unum_formatDouble ( fmt , vals [ i ] , buffer , BUFSIZE , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " failed to format: %g, returned %s \n " , vals [ i ] , u_errorName ( status ) ) ;
} else {
u_austrcpy ( temp , buffer ) ;
log_verbose ( " formatting %g returned '%s' \n " , vals [ i ] , temp ) ;
}
}
}
}
}
}
}
}
{
UErrorCode status = U_ZERO_ERROR ;
2004-05-30 21:25:27 +00:00
unum_toPattern ( fmt , FALSE , buffer , BUFSIZE , & status ) ;
2004-03-16 17:09:44 +00:00
if ( U_SUCCESS ( status ) ) {
u_austrcpy ( temp , buffer ) ;
log_verbose ( " pattern: '%s' \n " , temp ) ;
} else if ( status ! = U_BUFFER_OVERFLOW_ERROR ) {
log_err ( " toPattern failed unexpectedly: %s \n " , u_errorName ( status ) ) ;
} else {
log_verbose ( " pattern too long to display \n " ) ;
}
}
{
UErrorCode status = U_ZERO_ERROR ;
int len = unum_getSymbol ( fmt , UNUM_CURRENCY_SYMBOL , buffer , BUFSIZE , & status ) ;
if ( isDecimal ? U_FAILURE ( status ) : ( status ! = U_UNSUPPORTED_ERROR ) ) {
log_err ( " unexpected error getting symbol: '%s' \n " , u_errorName ( status ) ) ;
}
unum_setSymbol ( fmt , UNUM_CURRENCY_SYMBOL , buffer , len , & status ) ;
if ( isDecimal ? U_FAILURE ( status ) : ( status ! = U_UNSUPPORTED_ERROR ) ) {
log_err ( " unexpected error setting symbol: '%s' \n " , u_errorName ( status ) ) ;
}
}
2004-03-12 20:15:13 +00:00
}
2004-08-09 07:07:33 +00:00
static void TestNonExistentCurrency ( ) {
UNumberFormat * format ;
UErrorCode status = U_ZERO_ERROR ;
2004-08-10 05:37:11 +00:00
UChar currencySymbol [ 8 ] ;
static const UChar QQQ [ ] = { 0x51 , 0x51 , 0x51 , 0 } ;
2004-08-09 07:07:33 +00:00
2004-08-10 05:37:11 +00:00
/* Get a non-existent currency and make sure it returns the correct currency code. */
2004-08-09 07:07:33 +00:00
format = unum_open ( UNUM_CURRENCY , NULL , 0 , " th_TH@currency=QQQ " , NULL , & status ) ;
2004-08-10 05:37:11 +00:00
if ( format = = NULL | | U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_data_err ( " unum_open did not return expected result for non-existent requested currency: '%s' (Are you missing data?) \n " , u_errorName ( status ) ) ;
2004-08-09 07:07:33 +00:00
}
2004-08-10 05:37:11 +00:00
else {
unum_getSymbol ( format ,
UNUM_CURRENCY_SYMBOL ,
currencySymbol ,
2016-02-23 10:40:09 +00:00
UPRV_LENGTHOF ( currencySymbol ) ,
2004-08-10 05:37:11 +00:00
& status ) ;
if ( u_strcmp ( currencySymbol , QQQ ) ! = 0 ) {
log_err ( " unum_open set the currency to QQQ \n " ) ;
}
}
unum_close ( format ) ;
2004-08-09 07:07:33 +00:00
}
2004-03-12 20:15:13 +00:00
static void TestRBNFFormat ( ) {
2004-03-16 21:20:52 +00:00
UErrorCode status ;
2004-03-16 17:09:44 +00:00
UParseError perr ;
2004-05-30 21:25:27 +00:00
UChar pat [ 1024 ] ;
UChar tempUChars [ 512 ] ;
2004-03-16 17:09:44 +00:00
UNumberFormat * formats [ 5 ] ;
2016-02-23 10:40:09 +00:00
int COUNT = UPRV_LENGTHOF ( formats ) ;
2004-03-16 17:09:44 +00:00
int i ;
for ( i = 0 ; i < COUNT ; + + i ) {
formats [ i ] = 0 ;
}
/* instantiation */
2004-03-12 20:15:13 +00:00
status = U_ZERO_ERROR ;
2004-05-30 21:25:27 +00:00
u_uastrcpy ( pat , " #,##0.0#;(#,##0.0#) " ) ;
formats [ 0 ] = unum_open ( UNUM_PATTERN_DECIMAL , pat , - 1 , " en_US " , & perr , & status ) ;
2004-03-12 20:15:13 +00:00
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " unable to open decimal pattern -> %s \n " , u_errorName ( status ) ) ;
2010-07-14 16:09:03 +00:00
return ;
2004-03-12 20:15:13 +00:00
}
status = U_ZERO_ERROR ;
formats [ 1 ] = unum_open ( UNUM_SPELLOUT , NULL , 0 , " en_US " , & perr , & status ) ;
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " unable to open spellout -> %s \n " , u_errorName ( status ) ) ;
2010-07-14 16:09:03 +00:00
return ;
2004-03-12 20:15:13 +00:00
}
status = U_ZERO_ERROR ;
formats [ 2 ] = unum_open ( UNUM_ORDINAL , NULL , 0 , " en_US " , & perr , & status ) ;
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " unable to open ordinal -> %s \n " , u_errorName ( status ) ) ;
2010-07-14 16:09:03 +00:00
return ;
2004-03-12 20:15:13 +00:00
}
status = U_ZERO_ERROR ;
formats [ 3 ] = unum_open ( UNUM_DURATION , NULL , 0 , " en_US " , & perr , & status ) ;
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " unable to open duration %s \n " , u_errorName ( status ) ) ;
2010-07-14 16:09:03 +00:00
return ;
2004-03-12 20:15:13 +00:00
}
status = U_ZERO_ERROR ;
2004-05-30 21:25:27 +00:00
u_uastrcpy ( pat ,
2004-03-16 17:09:44 +00:00
" %standard: \n "
" -x: minus >>; \n "
" x.x: << point >>; \n "
" zero; one; two; three; four; five; six; seven; eight; nine; \n "
" ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen; \n "
" seventeen; eighteen; nineteen; \n "
" 20: twenty[->>]; \n "
" 30: thirty[->>]; \n "
" 40: forty[->>]; \n "
" 50: fifty[->>]; \n "
" 60: sixty[->>]; \n "
" 70: seventy[->>]; \n "
" 80: eighty[->>]; \n "
" 90: ninety[->>]; \n "
2004-05-30 21:25:27 +00:00
" 100: =#,##0=; \n " ) ;
u_uastrcpy ( tempUChars ,
2004-03-16 17:09:44 +00:00
" %simple: \n "
" =%standard=; \n "
" 20: twenty[ and change]; \n "
" 30: thirty[ and change]; \n "
" 40: forty[ and change]; \n "
" 50: fifty[ and change]; \n "
" 60: sixty[ and change]; \n "
" 70: seventy[ and change]; \n "
" 80: eighty[ and change]; \n "
" 90: ninety[ and change]; \n "
" 100: =#,##0=; \n "
" %bogus: \n "
" 0.x: tiny; \n "
" x.x: << point something; \n "
" =%standard=; \n "
" 20: some reasonable number; \n "
" 100: some substantial number; \n "
2004-05-30 21:25:27 +00:00
" 100,000,000: some huge number; \n " ) ;
/* This is to get around some compiler warnings about char * string length. */
u_strcat ( pat , tempUChars ) ;
formats [ 4 ] = unum_open ( UNUM_PATTERN_RULEBASED , pat , - 1 , " en_US " , & perr , & status ) ;
2004-03-12 20:15:13 +00:00
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " unable to open rulebased pattern -> %s \n " , u_errorName ( status ) ) ;
2008-02-19 05:05:51 +00:00
}
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_err_status ( status , " Something failed with %s \n " , u_errorName ( status ) ) ;
2008-02-19 05:05:51 +00:00
return ;
2004-03-12 20:15:13 +00:00
}
for ( i = 0 ; i < COUNT ; + + i ) {
2004-03-16 17:09:44 +00:00
log_verbose ( " \n \n testing format %d \n " , i ) ;
test_fmt ( formats [ i ] , ( UBool ) ( i = = 0 ) ) ;
2004-03-12 20:15:13 +00:00
}
2011-06-30 05:43:56 +00:00
# define FORMAT_BUF_CAPACITY 64
{
UChar fmtbuf [ FORMAT_BUF_CAPACITY ] ;
int32_t len ;
double nanvalue = uprv_getNaN ( ) ;
status = U_ZERO_ERROR ;
len = unum_formatDouble ( formats [ 1 ] , nanvalue , fmtbuf , FORMAT_BUF_CAPACITY , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err_status ( status , " unum_formatDouble NAN failed with %s \n " , u_errorName ( status ) ) ;
} else {
UChar nansym [ ] = { 0x4E , 0x61 , 0x4E , 0 } ; /* NaN */
if ( len ! = 3 | | u_strcmp ( fmtbuf , nansym ) ! = 0 ) {
log_err ( " unum_formatDouble NAN produced wrong answer for en_US \n " ) ;
}
}
}
2004-03-12 20:15:13 +00:00
for ( i = 0 ; i < COUNT ; + + i ) {
2004-03-16 17:09:44 +00:00
unum_close ( formats [ i ] ) ;
2004-03-12 20:15:13 +00:00
}
}
2017-08-17 23:21:03 +00:00
static void TestRBNFRounding ( ) {
UChar fmtbuf [ FORMAT_BUF_CAPACITY ] ;
UChar expectedBuf [ FORMAT_BUF_CAPACITY ] ;
int32_t len ;
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * fmt = unum_open ( UNUM_SPELLOUT , NULL , 0 , " en_US " , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err_status ( status , " unable to open spellout -> %s \n " , u_errorName ( status ) ) ;
return ;
}
len = unum_formatDouble ( fmt , 10.123456789 , fmtbuf , FORMAT_BUF_CAPACITY , NULL , & status ) ;
2018-10-25 01:48:55 +00:00
U_ASSERT ( len < FORMAT_BUF_CAPACITY ) ;
2019-06-20 18:51:27 +00:00
( void ) len ;
2017-08-17 23:21:03 +00:00
if ( U_FAILURE ( status ) ) {
log_err_status ( status , " unum_formatDouble 10.123456789 failed with %s \n " , u_errorName ( status ) ) ;
}
u_uastrcpy ( expectedBuf , " ten point one two three four five six seven eight nine " ) ;
if ( u_strcmp ( expectedBuf , fmtbuf ) ! = 0 ) {
log_err ( " Wrong result for unrounded value \n " ) ;
}
unum_setAttribute ( fmt , UNUM_MAX_FRACTION_DIGITS , 3 ) ;
if ( unum_getAttribute ( fmt , UNUM_MAX_FRACTION_DIGITS ) ! = 3 ) {
log_err ( " UNUM_MAX_FRACTION_DIGITS was incorrectly ignored -> %d \n " , unum_getAttribute ( fmt , UNUM_MAX_FRACTION_DIGITS ) ) ;
}
if ( unum_getAttribute ( fmt , UNUM_ROUNDING_MODE ) ! = UNUM_ROUND_UNNECESSARY ) {
log_err ( " UNUM_ROUNDING_MODE was set -> %d \n " , unum_getAttribute ( fmt , UNUM_ROUNDING_MODE ) ) ;
}
unum_setAttribute ( fmt , UNUM_ROUNDING_MODE , UNUM_ROUND_HALFUP ) ;
if ( unum_getAttribute ( fmt , UNUM_ROUNDING_MODE ) ! = UNUM_ROUND_HALFUP ) {
log_err ( " UNUM_ROUNDING_MODE was not set -> %d \n " , unum_getAttribute ( fmt , UNUM_ROUNDING_MODE ) ) ;
}
len = unum_formatDouble ( fmt , 10.123456789 , fmtbuf , FORMAT_BUF_CAPACITY , NULL , & status ) ;
2018-10-25 01:48:55 +00:00
U_ASSERT ( len < FORMAT_BUF_CAPACITY ) ;
2017-08-17 23:21:03 +00:00
if ( U_FAILURE ( status ) ) {
log_err_status ( status , " unum_formatDouble 10.123456789 failed with %s \n " , u_errorName ( status ) ) ;
}
u_uastrcpy ( expectedBuf , " ten point one two three " ) ;
if ( u_strcmp ( expectedBuf , fmtbuf ) ! = 0 ) {
char temp [ 512 ] ;
u_austrcpy ( temp , fmtbuf ) ;
log_err ( " Wrong result for rounded value. Got: %s \n " , temp ) ;
}
unum_close ( fmt ) ;
}
2006-03-23 05:53:36 +00:00
static void TestCurrencyRegression ( void ) {
2011-05-04 12:23:42 +00:00
/*
2005-06-02 21:56:14 +00:00
I ' ve found a case where unum_parseDoubleCurrency is not doing what I
expect . The value I pass in is $ 1234567890 q123460000 .00 and this
returns with a status of zero error & a parse pos of 22 ( I would
expect a parse error at position 11 ) .
I stepped into DecimalFormat : : subparse ( ) and it looks like it parses
the first 10 digits and then stops parsing at the q but doesn ' t set an
error . Then later in DecimalFormat : : parse ( ) the value gets crammed
into a long ( which greatly truncates the value ) .
This is very problematic for me ' cause I try to remove chars that are
invalid but this allows my users to enter bad chars and truncates
their data !
*/
UChar buf [ 1024 ] ;
UChar currency [ 8 ] ;
char acurrency [ 16 ] ;
double d ;
UNumberFormat * cur ;
int32_t pos ;
UErrorCode status = U_ZERO_ERROR ;
const int32_t expected = 11 ;
currency [ 0 ] = 0 ;
u_uastrcpy ( buf , " $1234567890q643210000.00 " ) ;
cur = unum_open ( UNUM_CURRENCY , NULL , 0 , " en_US " , NULL , & status ) ;
2011-05-04 12:23:42 +00:00
2005-06-02 21:56:14 +00:00
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_data_err ( " unum_open failed: %s (Are you missing data?) \n " , u_errorName ( status ) ) ;
2005-06-02 21:56:14 +00:00
return ;
}
2011-05-04 12:23:42 +00:00
2005-06-02 21:56:14 +00:00
status = U_ZERO_ERROR ; /* so we can test it later. */
pos = 0 ;
2011-05-04 12:23:42 +00:00
2005-06-02 21:56:14 +00:00
d = unum_parseDoubleCurrency ( cur ,
buf ,
- 1 ,
& pos , /* 0 = start */
currency ,
& status ) ;
u_austrcpy ( acurrency , currency ) ;
2006-07-10 23:40:17 +00:00
if ( U_FAILURE ( status ) | | ( pos ! = expected ) ) {
2005-06-02 21:56:14 +00:00
log_err ( " unum_parseDoubleCurrency should have failed with pos %d, but gave: value %.9f, err %s, pos=%d, currency [%s] \n " ,
expected , d , u_errorName ( status ) , pos , acurrency ) ;
} else {
log_verbose ( " unum_parseDoubleCurrency failed, value %.9f err %s, pos %d, currency [%s] \n " , d , u_errorName ( status ) , pos , acurrency ) ;
}
2011-05-04 12:23:42 +00:00
2005-06-02 21:56:14 +00:00
unum_close ( cur ) ;
}
2007-07-17 21:46:59 +00:00
static void TestTextAttributeCrash ( void ) {
UChar ubuffer [ 64 ] = { 0x0049 , 0x004E , 0x0052 , 0 } ;
static const UChar expectedNeg [ ] = { 0x0049 , 0x004E , 0x0052 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x002E , 0x0035 , 0 } ;
static const UChar expectedPos [ ] = { 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x002E , 0x0035 , 0 } ;
2011-05-04 12:23:42 +00:00
int32_t used ;
2007-07-17 21:46:59 +00:00
UErrorCode status = U_ZERO_ERROR ;
2011-05-04 12:23:42 +00:00
UNumberFormat * nf = unum_open ( UNUM_CURRENCY , NULL , 0 , " en_US " , NULL , & status ) ;
2007-07-17 21:46:59 +00:00
if ( U_FAILURE ( status ) ) {
2009-06-09 21:28:13 +00:00
log_data_err ( " FAILED 1 -> %s (Are you missing data?) \n " , u_errorName ( status ) ) ;
2007-07-17 21:46:59 +00:00
return ;
}
unum_setTextAttribute ( nf , UNUM_CURRENCY_CODE , ubuffer , 3 , & status ) ;
2007-07-18 02:44:16 +00:00
/*
* the usual negative prefix and suffix seem to be ' ( $ ' and ' ) ' at this point
* also crashes if UNUM_NEGATIVE_SUFFIX is substituted for UNUM_NEGATIVE_PREFIX here
*/
2007-07-17 21:46:59 +00:00
used = unum_getTextAttribute ( nf , UNUM_NEGATIVE_PREFIX , ubuffer , 64 , & status ) ;
unum_setTextAttribute ( nf , UNUM_NEGATIVE_PREFIX , ubuffer , used , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " FAILED 2 \n " ) ; exit ( 1 ) ;
}
log_verbose ( " attempting to format... \n " ) ;
2011-05-04 12:23:42 +00:00
used = unum_formatDouble ( nf , - 1234.5 , ubuffer , 64 , NULL , & status ) ;
2007-07-17 21:46:59 +00:00
if ( U_FAILURE ( status ) | | 64 < used ) {
log_err ( " Failed formatting %s \n " , u_errorName ( status ) ) ;
return ;
}
if ( u_strcmp ( expectedNeg , ubuffer ) = = 0 ) {
log_err ( " Didn't get expected negative result \n " ) ;
}
2011-05-04 12:23:42 +00:00
used = unum_formatDouble ( nf , 1234.5 , ubuffer , 64 , NULL , & status ) ;
2007-07-17 21:46:59 +00:00
if ( U_FAILURE ( status ) | | 64 < used ) {
log_err ( " Failed formatting %s \n " , u_errorName ( status ) ) ;
return ;
}
if ( u_strcmp ( expectedPos , ubuffer ) = = 0 ) {
log_err ( " Didn't get expected positive result \n " ) ;
}
2007-07-26 21:05:44 +00:00
unum_close ( nf ) ;
2007-07-17 21:46:59 +00:00
}
2012-05-30 00:41:57 +00:00
static void TestNBSPPatternRtNum ( const char * testcase , int line , UNumberFormat * nf , double myNumber ) {
2008-06-20 00:43:45 +00:00
UErrorCode status = U_ZERO_ERROR ;
UChar myString [ 20 ] ;
char tmpbuf [ 200 ] ;
double aNumber = - 1.0 ;
unum_formatDouble ( nf , myNumber , myString , 20 , NULL , & status ) ;
2012-05-30 00:41:57 +00:00
log_verbose ( " %s:%d: formatted %.2f into %s \n " , testcase , line , myNumber , u_austrcpy ( tmpbuf , myString ) ) ;
2008-06-20 00:43:45 +00:00
if ( U_FAILURE ( status ) ) {
2012-05-30 00:41:57 +00:00
log_err ( " %s:%d: failed format of %.2g with %s \n " , testcase , line , myNumber , u_errorName ( status ) ) ;
2008-06-20 00:43:45 +00:00
return ;
}
aNumber = unum_parse ( nf , myString , - 1 , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
2012-05-30 00:41:57 +00:00
log_err ( " %s:%d: failed parse with %s \n " , testcase , line , u_errorName ( status ) ) ;
2008-06-20 00:43:45 +00:00
return ;
}
if ( uprv_fabs ( aNumber - myNumber ) > .001 ) {
2012-05-30 00:41:57 +00:00
log_err ( " FAIL: %s:%d formatted %.2f, parsed into %.2f \n " , testcase , line , myNumber , aNumber ) ;
2008-06-20 00:43:45 +00:00
} else {
2012-05-30 00:41:57 +00:00
log_verbose ( " PASS: %s:%d formatted %.2f, parsed into %.2f \n " , testcase , line , myNumber , aNumber ) ;
2008-06-20 00:43:45 +00:00
}
}
static void TestNBSPPatternRT ( const char * testcase , UNumberFormat * nf ) {
2012-05-30 00:41:57 +00:00
TestNBSPPatternRtNum ( testcase , __LINE__ , nf , 12345. ) ;
TestNBSPPatternRtNum ( testcase , __LINE__ , nf , - 12345. ) ;
2008-06-20 00:43:45 +00:00
}
static void TestNBSPInPattern ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * nf = NULL ;
const char * testcase ;
2011-05-04 12:23:42 +00:00
2008-06-20 00:43:45 +00:00
testcase = " ar_AE UNUM_CURRENCY " ;
nf = unum_open ( UNUM_CURRENCY , NULL , - 1 , " ar_AE " , NULL , & status ) ;
2009-06-09 21:28:13 +00:00
if ( U_FAILURE ( status ) | | nf = = NULL ) {
2012-05-30 00:41:57 +00:00
log_data_err ( " %s:%d: %s: unum_open failed with %s (Are you missing data?) \n " , __FILE__ , __LINE__ , testcase , u_errorName ( status ) ) ;
2009-06-09 21:28:13 +00:00
return ;
2008-06-20 00:43:45 +00:00
}
TestNBSPPatternRT ( testcase , nf ) ;
2011-05-04 12:23:42 +00:00
2008-06-20 00:43:45 +00:00
/* if we don't have CLDR 1.6 data, bring out the problem anyways */
{
# define SPECIAL_PATTERN "\\u00A4\\u00A4'\\u062f.\\u0625.\\u200f\\u00a0'###0.00"
UChar pat [ 200 ] ;
testcase = " ar_AE special pattern: " SPECIAL_PATTERN ;
2016-02-23 10:40:09 +00:00
u_unescape ( SPECIAL_PATTERN , pat , UPRV_LENGTHOF ( pat ) ) ;
2008-06-20 00:43:45 +00:00
unum_applyPattern ( nf , FALSE , pat , - 1 , NULL , & status ) ;
2011-05-04 12:23:42 +00:00
if ( U_FAILURE ( status ) ) {
2008-06-20 00:43:45 +00:00
log_err ( " %s: unum_applyPattern failed with %s \n " , testcase , u_errorName ( status ) ) ;
} else {
TestNBSPPatternRT ( testcase , nf ) ;
}
# undef SPECIAL_PATTERN
}
unum_close ( nf ) ; status = U_ZERO_ERROR ;
2011-05-04 12:23:42 +00:00
2008-06-20 00:43:45 +00:00
testcase = " ar_AE UNUM_DECIMAL " ;
nf = unum_open ( UNUM_DECIMAL , NULL , - 1 , " ar_AE " , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " %s: unum_open failed with %s \n " , testcase , u_errorName ( status ) ) ;
}
TestNBSPPatternRT ( testcase , nf ) ;
unum_close ( nf ) ; status = U_ZERO_ERROR ;
2011-05-04 12:23:42 +00:00
2008-06-20 00:43:45 +00:00
testcase = " ar_AE UNUM_PERCENT " ;
nf = unum_open ( UNUM_PERCENT , NULL , - 1 , " ar_AE " , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " %s: unum_open failed with %s \n " , testcase , u_errorName ( status ) ) ;
2011-05-04 12:23:42 +00:00
}
TestNBSPPatternRT ( testcase , nf ) ;
2008-06-20 00:43:45 +00:00
unum_close ( nf ) ; status = U_ZERO_ERROR ;
2011-05-04 12:23:42 +00:00
2008-06-20 00:43:45 +00:00
}
2019-02-14 08:59:47 +00:00
static void TestCloneWithRBNF ( void ) {
2011-10-26 14:39:51 +00:00
UChar pattern [ 1024 ] ;
UChar pat2 [ 512 ] ;
UErrorCode status = U_ZERO_ERROR ;
UChar buffer [ 256 ] ;
UChar buffer_cloned [ 256 ] ;
char temp1 [ 256 ] ;
char temp2 [ 256 ] ;
UNumberFormat * pform_cloned ;
UNumberFormat * pform ;
u_uastrcpy ( pattern ,
" %main: \n "
" 0.x: >%%millis-only>; \n "
" x.0: <%%duration<; \n "
" x.x: <%%durationwithmillis<>%%millis-added>; \n "
" -x: ->>;%%millis-only: \n "
" 1000: 00:00.<%%millis<; \n "
" %%millis-added: \n "
" 1000: .<%%millis<; \n "
" %%millis: \n "
" 0: =000=; \n "
" %%duration: \n "
" 0: =%%seconds-only=; \n "
" 60: =%%min-sec=; \n "
" 3600: =%%hr-min-sec=; \n "
" 86400/86400: <%%ddaayyss<[, >>]; \n "
" %%durationwithmillis: \n "
" 0: =%%seconds-only=; \n "
" 60: =%%min-sec=; \n "
" 3600: =%%hr-min-sec=; \n "
" 86400/86400: <%%ddaayyss<, >>; \n " ) ;
u_uastrcpy ( pat2 ,
" %%seconds-only: \n "
" 0: 0:00:=00=; \n "
" %%min-sec: \n "
" 0: :=00=; \n "
" 0/60: 0:<00<>>; \n "
" %%hr-min-sec: \n "
" 0: :=00=; \n "
" 60/60: <00<>>; \n "
" 3600/60: <0<:>>>; \n "
" %%ddaayyss: \n "
" 0 days; \n "
" 1 day; \n "
" =0= days; " ) ;
/* This is to get around some compiler warnings about char * string length. */
u_strcat ( pattern , pat2 ) ;
pform = unum_open ( UNUM_PATTERN_RULEBASED , pattern , - 1 , " en_US " , NULL , & status ) ;
unum_formatDouble ( pform , 3600 , buffer , 256 , NULL , & status ) ;
pform_cloned = unum_clone ( pform , & status ) ;
unum_formatDouble ( pform_cloned , 3600 , buffer_cloned , 256 , NULL , & status ) ;
2011-11-09 21:12:06 +00:00
unum_close ( pform ) ;
unum_close ( pform_cloned ) ;
2011-10-26 14:39:51 +00:00
if ( u_strcmp ( buffer , buffer_cloned ) ) {
2011-12-12 23:28:25 +00:00
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 ) ) ;
2011-10-26 14:39:51 +00:00
}
2011-10-26 02:16:23 +00:00
}
2012-07-06 22:47:27 +00:00
2012-10-12 19:52:43 +00:00
static void TestNoExponent ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UChar str [ 100 ] ;
const char * cstr ;
UNumberFormat * fmt ;
int32_t pos ;
int32_t expect = 0 ;
int32_t num ;
fmt = unum_open ( UNUM_DECIMAL , NULL , - 1 , " en_US " , NULL , & status ) ;
if ( U_FAILURE ( status ) | | fmt = = NULL ) {
log_data_err ( " %s:%d: unum_open failed with %s (Are you missing data?) \n " , __FILE__ , __LINE__ , u_errorName ( status ) ) ;
return ;
}
cstr = " 10E6 " ;
u_uastrcpy ( str , cstr ) ;
expect = 10000000 ;
pos = 0 ;
num = unum_parse ( fmt , str , - 1 , & pos , & status ) ;
ASSERT_TRUE ( pos = = 4 ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " %s:%d: unum_parse failed with %s for %s (Are you missing data?) \n " , __FILE__ , __LINE__ , u_errorName ( status ) , cstr ) ;
} else if ( expect ! = num ) {
log_data_err ( " %s:%d: unum_parse failed, got %d expected %d for '%s'(Are you missing data?) \n " , __FILE__ , __LINE__ , num , expect , cstr ) ;
} else {
log_verbose ( " %s:%d: unum_parse returned %d for '%s' \n " , __FILE__ , __LINE__ , num , cstr ) ;
}
ASSERT_TRUE ( unum_getAttribute ( fmt , UNUM_PARSE_NO_EXPONENT ) = = 0 ) ;
unum_setAttribute ( fmt , UNUM_PARSE_NO_EXPONENT , 1 ) ; /* no error code */
log_verbose ( " set UNUM_PARSE_NO_EXPONENT \n " ) ;
ASSERT_TRUE ( unum_getAttribute ( fmt , UNUM_PARSE_NO_EXPONENT ) = = 1 ) ;
pos = 0 ;
expect = 10 ;
num = unum_parse ( fmt , str , - 1 , & pos , & status ) ;
if ( num = = 10000000 ) {
log_err ( " %s:%d: FAIL: unum_parse should have returned 10, not 10000000 on %s after UNUM_PARSE_NO_EXPONENT \n " , __FILE__ , __LINE__ , cstr ) ;
} else if ( num = = expect ) {
log_verbose ( " %s:%d: unum_parse gave %d for %s - good. \n " , __FILE__ , __LINE__ , num , cstr ) ;
}
ASSERT_TRUE ( pos = = 2 ) ;
status = U_ZERO_ERROR ;
unum_close ( fmt ) ;
/* ok, now try scientific */
fmt = unum_open ( UNUM_SCIENTIFIC , NULL , - 1 , " en_US " , NULL , & status ) ;
assertSuccess ( " unum_open(UNUM_SCIENTIFIC, ...) " , & status ) ;
ASSERT_TRUE ( unum_getAttribute ( fmt , UNUM_PARSE_NO_EXPONENT ) = = 0 ) ;
cstr = " 10E6 " ;
u_uastrcpy ( str , cstr ) ;
expect = 10000000 ;
pos = 0 ;
num = unum_parse ( fmt , str , - 1 , & pos , & status ) ;
ASSERT_TRUE ( pos = = 4 ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " %s:%d: unum_parse failed with %s for %s (Are you missing data?) \n " , __FILE__ , __LINE__ , u_errorName ( status ) , cstr ) ;
} else if ( expect ! = num ) {
log_data_err ( " %s:%d: unum_parse failed, got %d expected %d for '%s'(Are you missing data?) \n " , __FILE__ , __LINE__ , num , expect , cstr ) ;
} else {
log_verbose ( " %s:%d: unum_parse returned %d for '%s' \n " , __FILE__ , __LINE__ , num , cstr ) ;
}
unum_setAttribute ( fmt , UNUM_PARSE_NO_EXPONENT , 1 ) ; /* no error code */
log_verbose ( " set UNUM_PARSE_NO_EXPONENT \n " ) ;
ASSERT_TRUE ( unum_getAttribute ( fmt , UNUM_PARSE_NO_EXPONENT ) = = 1 ) ;
2018-04-18 06:03:29 +00:00
// A scientific formatter should parse the exponent even if UNUM_PARSE_NO_EXPONENT is set
2012-10-12 19:52:43 +00:00
cstr = " 10E6 " ;
u_uastrcpy ( str , cstr ) ;
expect = 10000000 ;
pos = 0 ;
num = unum_parse ( fmt , str , - 1 , & pos , & status ) ;
ASSERT_TRUE ( pos = = 4 ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " %s:%d: unum_parse failed with %s for %s (Are you missing data?) \n " , __FILE__ , __LINE__ , u_errorName ( status ) , cstr ) ;
} else if ( expect ! = num ) {
log_data_err ( " %s:%d: unum_parse failed, got %d expected %d for '%s'(Are you missing data?) \n " , __FILE__ , __LINE__ , num , expect , cstr ) ;
} else {
log_verbose ( " %s:%d: unum_parse returned %d for '%s' \n " , __FILE__ , __LINE__ , num , cstr ) ;
}
unum_close ( fmt ) ;
}
2012-07-06 22:47:27 +00:00
static void TestMaxInt ( void ) {
2012-10-12 19:52:43 +00:00
UErrorCode status = U_ZERO_ERROR ;
UChar pattern_hash [ ] = { 0x23 , 0x00 } ; /* "#" */
UChar result1 [ 1024 ] = { 0 } , result2 [ 1024 ] = { 0 } ;
int32_t len1 , len2 ;
UChar expect [ ] = { 0x0039 , 0x0037 , 0 } ;
UNumberFormat * fmt = unum_open (
2012-07-06 22:47:27 +00:00
UNUM_PATTERN_DECIMAL , /* style */
& pattern_hash [ 0 ] , /* pattern */
u_strlen ( pattern_hash ) , /* patternLength */
2018-04-28 03:53:57 +00:00
" en " ,
2012-07-06 22:47:27 +00:00
0 , /* parseErr */
& status ) ;
if ( U_FAILURE ( status ) | | fmt = = NULL ) {
2012-10-12 19:52:43 +00:00
log_data_err ( " %s:%d: %s: unum_open failed with %s (Are you missing data?) \n " , __FILE__ , __LINE__ , " TestMaxInt " , u_errorName ( status ) ) ;
2012-07-06 22:47:27 +00:00
return ;
}
2012-10-12 19:52:43 +00:00
unum_setAttribute ( fmt , UNUM_MAX_INTEGER_DIGITS , 2 ) ;
2012-07-06 22:47:27 +00:00
2012-10-12 19:52:43 +00:00
status = U_ZERO_ERROR ;
/* #1 */
len1 = unum_formatInt64 ( fmt , 1997 , result1 , 1024 , NULL , & status ) ;
result1 [ len1 ] = 0 ;
if ( U_FAILURE ( status ) | | u_strcmp ( expect , result1 ) ) {
log_err ( " unum_formatInt64 Expected %s but got %s status %s \n " , austrdup ( expect ) , austrdup ( result1 ) , u_errorName ( status ) ) ;
}
2012-07-06 22:47:27 +00:00
2012-10-12 19:52:43 +00:00
status = U_ZERO_ERROR ;
/* #2 */
len2 = unum_formatDouble ( fmt , 1997.0 , result2 , 1024 , NULL , & status ) ;
result2 [ len2 ] = 0 ;
if ( U_FAILURE ( status ) | | u_strcmp ( expect , result2 ) ) {
log_err ( " unum_formatDouble Expected %s but got %s status %s \n " , austrdup ( expect ) , austrdup ( result2 ) , u_errorName ( status ) ) ;
}
2012-10-12 21:53:41 +00:00
/* test UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS */
ASSERT_TRUE ( unum_getAttribute ( fmt , UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS ) = = 0 ) ;
2012-10-12 19:52:43 +00:00
2012-10-12 21:53:41 +00:00
unum_setAttribute ( fmt , UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS , 1 ) ;
/* test UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS */
ASSERT_TRUE ( unum_getAttribute ( fmt , UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS ) = = 1 ) ;
2012-10-12 19:52:43 +00:00
status = U_ZERO_ERROR ;
/* max int digits still '2' */
len1 = unum_formatInt64 ( fmt , 1997 , result1 , 1024 , NULL , & status ) ;
ASSERT_TRUE ( status = = U_ILLEGAL_ARGUMENT_ERROR ) ;
status = U_ZERO_ERROR ;
/* But, formatting 97->'97' works fine. */
/* #1 */
len1 = unum_formatInt64 ( fmt , 97 , result1 , 1024 , NULL , & status ) ;
result1 [ len1 ] = 0 ;
if ( U_FAILURE ( status ) | | u_strcmp ( expect , result1 ) ) {
log_err ( " unum_formatInt64 Expected %s but got %s status %s \n " , austrdup ( expect ) , austrdup ( result1 ) , u_errorName ( status ) ) ;
}
2012-07-06 22:47:27 +00:00
2012-10-12 19:52:43 +00:00
status = U_ZERO_ERROR ;
/* #2 */
len2 = unum_formatDouble ( fmt , 97.0 , result2 , 1024 , NULL , & status ) ;
result2 [ len2 ] = 0 ;
if ( U_FAILURE ( status ) | | u_strcmp ( expect , result2 ) ) {
log_err ( " unum_formatDouble Expected %s but got %s status %s \n " , austrdup ( expect ) , austrdup ( result2 ) , u_errorName ( status ) ) ;
}
2012-07-06 22:47:27 +00:00
2012-10-12 19:52:43 +00:00
unum_close ( fmt ) ;
2012-07-06 22:47:27 +00:00
}
2019-01-25 03:44:17 +00:00
static void TestSignAlwaysShown ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * fmt = unum_open (
UNUM_DECIMAL , /* style */
NULL , /* pattern */
0 , /* patternLength */
" en-US " ,
NULL , /* parseErr */
& status ) ;
assertSuccess ( " Creating UNumberFormat " , & status ) ;
unum_setAttribute ( fmt , UNUM_SIGN_ALWAYS_SHOWN , 1 ) ;
UChar result [ 100 ] ;
unum_formatDouble ( fmt , 42 , result , 100 , NULL , & status ) ;
assertSuccess ( " Formatting with UNumberFormat " , & status ) ;
assertUEquals ( " Result with sign always shown " , u " +42 " , result ) ;
unum_close ( fmt ) ;
}
static void TestMinimumGroupingDigits ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * fmt = unum_open (
UNUM_DECIMAL , /* style */
NULL , /* pattern */
0 , /* patternLength */
" en-US " ,
NULL , /* parseErr */
& status ) ;
assertSuccess ( " Creating UNumberFormat " , & status ) ;
unum_setAttribute ( fmt , UNUM_MINIMUM_GROUPING_DIGITS , 2 ) ;
UChar result [ 100 ] ;
unum_formatDouble ( fmt , 1234 , result , 100 , NULL , & status ) ;
assertSuccess ( " Formatting with UNumberFormat A " , & status ) ;
assertUEquals ( " Result with minimum grouping digits A " , u " 1234 " , result ) ;
unum_formatDouble ( fmt , 12345 , result , 100 , NULL , & status ) ;
assertSuccess ( " Formatting with UNumberFormat B " , & status ) ;
assertUEquals ( " Result with minimum grouping digits B " , u " 12,345 " , result ) ;
unum_close ( fmt ) ;
}
static void TestParseCaseSensitive ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * fmt = unum_open (
UNUM_DECIMAL , /* style */
NULL , /* pattern */
0 , /* patternLength */
" en-US " ,
NULL , /* parseErr */
& status ) ;
assertSuccess ( " Creating UNumberFormat " , & status ) ;
double result = unum_parseDouble ( fmt , u " 1e2 " , - 1 , NULL , & status ) ;
assertSuccess ( " Parsing with UNumberFormat, case insensitive " , & status ) ;
2019-02-21 03:38:58 +00:00
assertIntEquals ( " Result with case sensitive " , 100 , ( int64_t ) result ) ;
2019-01-25 03:44:17 +00:00
unum_setAttribute ( fmt , UNUM_PARSE_CASE_SENSITIVE , 1 ) ;
int32_t ppos = 0 ;
result = unum_parseDouble ( fmt , u " 1e2 " , - 1 , & ppos , & status ) ;
assertSuccess ( " Parsing with UNumberFormat, case sensitive " , & status ) ;
assertIntEquals ( " Position with case sensitive " , 1 , ppos ) ;
2019-02-21 03:38:58 +00:00
assertIntEquals ( " Result with case sensitive " , 1 , ( int64_t ) result ) ;
2019-01-25 03:44:17 +00:00
unum_close ( fmt ) ;
}
2013-06-27 19:49:55 +00:00
static void TestUFormattable ( void ) {
UChar out2k [ 2048 ] ;
2013-07-11 00:31:41 +00:00
// simple test for API docs
{
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unum = unum_open ( UNUM_DEFAULT , NULL , - 1 , " en_US_POSIX " , NULL , & status ) ;
2013-09-20 05:00:30 +00:00
if ( assertSuccessCheck ( " calling unum_open() " , & status , TRUE ) ) {
2013-07-11 00:31:41 +00:00
//! [unum_parseToUFormattable]
const UChar str [ ] = { 0x0031 , 0x0032 , 0x0033 , 0x0000 } ; /* 123 */
int32_t result = 0 ;
UFormattable * ufmt = ufmt_open ( & status ) ;
unum_parseToUFormattable ( unum , ufmt , str , - 1 , NULL , & status ) ;
if ( ufmt_isNumeric ( ufmt ) ) {
2013-08-13 23:32:48 +00:00
result = ufmt_getLong ( ufmt , & status ) ; /* == 123 */
2013-07-11 00:31:41 +00:00
} /* else { ... } */
ufmt_close ( ufmt ) ;
//! [unum_parseToUFormattable]
assertTrue ( " result == 123 " , ( result = = 123 ) ) ;
}
2013-08-13 23:32:48 +00:00
unum_close ( unum ) ;
2013-07-11 00:31:41 +00:00
}
2013-06-27 19:49:55 +00:00
// test with explicitly created ufmt_open
{
2013-07-11 00:31:41 +00:00
UChar buffer [ 2048 ] ;
2013-06-27 19:49:55 +00:00
UErrorCode status = U_ZERO_ERROR ;
2013-07-11 00:31:41 +00:00
UFormattable * ufmt ;
2013-06-27 19:49:55 +00:00
UNumberFormat * unum ;
const char * pattern = " " ;
2013-07-11 00:31:41 +00:00
ufmt = ufmt_open ( & status ) ;
2013-06-27 19:49:55 +00:00
unum = unum_open ( UNUM_DEFAULT , NULL , - 1 , " en_US_POSIX " , NULL , & status ) ;
2013-09-20 05:00:30 +00:00
if ( assertSuccessCheck ( " calling ufmt_open() || unum_open() " , & status , TRUE ) ) {
2013-06-27 19:49:55 +00:00
pattern = " 31337 " ;
log_verbose ( " -- pattern: %s \n " , pattern ) ;
2013-07-11 00:31:41 +00:00
u_uastrcpy ( buffer , pattern ) ;
unum_parseToUFormattable ( unum , ufmt , buffer , - 1 , NULL , & status ) ;
2013-09-20 21:17:16 +00:00
if ( assertSuccess ( " unum_parseToUFormattable(31337) " , & status ) ) {
2013-07-11 00:31:41 +00:00
assertTrue ( " ufmt_getLong()=31337 " , ufmt_getLong ( ufmt , & status ) = = 31337 ) ;
assertTrue ( " ufmt_getType()=UFMT_LONG " , ufmt_getType ( ufmt , & status ) = = UFMT_LONG ) ;
log_verbose ( " long = %d \n " , ufmt_getLong ( ufmt , & status ) ) ;
2013-06-27 19:49:55 +00:00
assertSuccess ( " ufmt_getLong() " , & status ) ;
}
2013-07-11 00:31:41 +00:00
unum_formatUFormattable ( unum , ufmt , out2k , 2048 , NULL , & status ) ;
2013-06-27 19:49:55 +00:00
if ( assertSuccess ( " unum_formatUFormattable(31337) " , & status ) ) {
2013-07-11 00:31:41 +00:00
assertEquals ( " unum_formatUFormattable r/t " , austrdup ( buffer ) , austrdup ( out2k ) ) ;
2013-06-27 19:49:55 +00:00
}
pattern = " 3.14159 " ;
log_verbose ( " -- pattern: %s \n " , pattern ) ;
2013-07-11 00:31:41 +00:00
u_uastrcpy ( buffer , pattern ) ;
unum_parseToUFormattable ( unum , ufmt , buffer , - 1 , NULL , & status ) ;
2013-09-20 21:17:16 +00:00
if ( assertSuccess ( " unum_parseToUFormattable(3.14159) " , & status ) ) {
2013-09-04 22:36:52 +00:00
assertTrue ( " ufmt_getDouble()==3.14159 " , withinErr ( ufmt_getDouble ( ufmt , & status ) , 3.14159 , 1e-15 ) ) ;
assertSuccess ( " ufmt_getDouble() " , & status ) ;
2013-07-11 00:31:41 +00:00
assertTrue ( " ufmt_getType()=UFMT_DOUBLE " , ufmt_getType ( ufmt , & status ) = = UFMT_DOUBLE ) ;
log_verbose ( " double = %g \n " , ufmt_getDouble ( ufmt , & status ) ) ;
2013-06-27 19:49:55 +00:00
}
2013-07-11 00:31:41 +00:00
unum_formatUFormattable ( unum , ufmt , out2k , 2048 , NULL , & status ) ;
2013-06-27 19:49:55 +00:00
if ( assertSuccess ( " unum_formatUFormattable(3.14159) " , & status ) ) {
2013-07-11 00:31:41 +00:00
assertEquals ( " unum_formatUFormattable r/t " , austrdup ( buffer ) , austrdup ( out2k ) ) ;
2013-06-27 19:49:55 +00:00
}
}
2013-07-11 00:31:41 +00:00
ufmt_close ( ufmt ) ;
2013-06-27 19:49:55 +00:00
unum_close ( unum ) ;
}
// test with auto-generated ufmt
{
2013-07-11 00:31:41 +00:00
UChar buffer [ 2048 ] ;
2013-06-27 19:49:55 +00:00
UErrorCode status = U_ZERO_ERROR ;
2013-07-11 00:31:41 +00:00
UFormattable * ufmt = NULL ;
2013-06-27 19:49:55 +00:00
UNumberFormat * unum ;
const char * pattern = " 73476730924573500000000 " ; // weight of the moon, kg
log_verbose ( " -- pattern: %s (testing auto-opened UFormattable) \n " , pattern ) ;
2013-07-11 00:31:41 +00:00
u_uastrcpy ( buffer , pattern ) ;
2013-06-27 19:49:55 +00:00
unum = unum_open ( UNUM_DEFAULT , NULL , - 1 , " en_US_POSIX " , NULL , & status ) ;
2013-09-20 05:00:30 +00:00
if ( assertSuccessCheck ( " calling unum_open() " , & status , TRUE ) ) {
2013-06-27 19:49:55 +00:00
2013-09-20 05:00:30 +00:00
ufmt = unum_parseToUFormattable ( unum , NULL , /* will be ufmt_open()'ed for us */
2013-07-11 00:31:41 +00:00
buffer , - 1 , NULL , & status ) ;
2013-09-20 05:00:30 +00:00
if ( assertSuccess ( " unum_parseToUFormattable(weight of the moon) " , & status ) ) {
2013-07-11 00:31:41 +00:00
log_verbose ( " new formattable allocated at %p \n " , ( void * ) ufmt ) ;
assertTrue ( " ufmt_isNumeric() TRUE " , ufmt_isNumeric ( ufmt ) ) ;
unum_formatUFormattable ( unum , ufmt , out2k , 2048 , NULL , & status ) ;
2013-06-27 19:49:55 +00:00
if ( assertSuccess ( " unum_formatUFormattable(3.14159) " , & status ) ) {
2013-07-11 00:31:41 +00:00
assertEquals ( " unum_formatUFormattable r/t " , austrdup ( buffer ) , austrdup ( out2k ) ) ;
2013-06-27 19:49:55 +00:00
}
2013-07-11 00:31:41 +00:00
log_verbose ( " double: %g \n " , ufmt_getDouble ( ufmt , & status ) ) ;
2013-06-27 19:49:55 +00:00
assertSuccess ( " ufmt_getDouble() " , & status ) ;
2013-07-11 00:31:41 +00:00
log_verbose ( " long: %ld \n " , ufmt_getLong ( ufmt , & status ) ) ;
2013-06-27 19:49:55 +00:00
assertTrue ( " failure on ufmt_getLong() for huge number: " , U_FAILURE ( status ) ) ;
// status is now a failure due to ufmt_getLong() above.
// the intltest does extensive r/t testing of Formattable vs. UFormattable.
}
}
unum_close ( unum ) ;
2013-07-11 00:31:41 +00:00
ufmt_close ( ufmt ) ; // was implicitly opened for us by the first unum_parseToUFormattable()
2013-06-27 19:49:55 +00:00
}
}
2013-09-11 05:07:00 +00:00
typedef struct {
2013-09-12 04:33:03 +00:00
const char * locale ;
const char * numsys ;
2013-09-11 05:07:00 +00:00
int32_t radix ;
UBool isAlgorithmic ;
2013-09-12 04:33:03 +00:00
const UChar * description ;
2013-09-11 05:07:00 +00:00
} NumSysTestItem ;
2013-09-12 04:33:03 +00:00
static const UChar latnDesc [ ] = { 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 , 0 } ; // 0123456789
static const UChar romanDesc [ ] = { 0x25 , 0x72 , 0x6F , 0x6D , 0x61 , 0x6E , 0x2D , 0x75 , 0x70 , 0x70 , 0x65 , 0x72 , 0 } ; // %roman-upper
static const UChar arabDesc [ ] = { 0x0660 , 0x0661 , 0x0662 , 0x0663 , 0x0664 , 0x0665 , 0x0666 , 0x0667 , 0x0668 , 0x0669 , 0 } ; //
static const UChar arabextDesc [ ] = { 0x06F0 , 0x06F1 , 0x06F2 , 0x06F3 , 0x06F4 , 0x06F5 , 0x06F6 , 0x06F7 , 0x06F8 , 0x06F9 , 0 } ; //
static const UChar hanidecDesc [ ] = { 0x3007 , 0x4E00 , 0x4E8C , 0x4E09 , 0x56DB , 0x4E94 , 0x516D , 0x4E03 , 0x516B , 0x4E5D , 0 } ; //
static const UChar hantDesc [ ] = { 0x7A , 0x68 , 0x5F , 0x48 , 0x61 , 0x6E , 0x74 , 0x2F , 0x53 , 0x70 , 0x65 , 0x6C , 0x6C , 0x6F , 0x75 , 0x74 ,
0x52 , 0x75 , 0x6C , 0x65 , 0x73 , 0x2F , 0x25 , 0x73 , 0x70 , 0x65 , 0x6C , 0x6C , 0x6F , 0x75 , 0x74 , 0x2D ,
0x63 , 0x61 , 0x72 , 0x64 , 0x69 , 0x6E , 0x61 , 0x6C , 0 } ; // zh_Hant/SpelloutRules/%spellout-cardinal
2013-09-11 05:07:00 +00:00
static const NumSysTestItem numSysTestItems [ ] = {
2013-09-12 04:33:03 +00:00
//locale numsys radix isAlgo description
{ " en " , " latn " , 10 , FALSE , latnDesc } ,
{ " en@numbers=roman " , " roman " , 10 , TRUE , romanDesc } ,
{ " en@numbers=finance " , " latn " , 10 , FALSE , latnDesc } ,
2018-02-26 23:32:05 +00:00
{ " ar-EG " , " arab " , 10 , FALSE , arabDesc } ,
2013-09-12 04:33:03 +00:00
{ " fa " , " arabext " , 10 , FALSE , arabextDesc } ,
{ " zh_Hans@numbers=hanidec " , " hanidec " , 10 , FALSE , hanidecDesc } ,
{ " zh_Hant@numbers=traditional " , " hant " , 10 , TRUE , hantDesc } ,
{ NULL , NULL , 0 , FALSE , NULL } ,
2013-09-11 05:07:00 +00:00
} ;
2013-09-12 04:33:03 +00:00
enum { kNumSysDescripBufMax = 64 } ;
2013-09-11 05:07:00 +00:00
static void TestUNumberingSystem ( void ) {
const NumSysTestItem * itemPtr ;
UNumberingSystem * unumsys ;
UEnumeration * uenum ;
const char * numsys ;
UErrorCode status ;
2019-02-14 08:59:47 +00:00
2013-09-11 05:07:00 +00:00
for ( itemPtr = numSysTestItems ; itemPtr - > locale ! = NULL ; itemPtr + + ) {
status = U_ZERO_ERROR ;
unumsys = unumsys_open ( itemPtr - > locale , & status ) ;
if ( U_SUCCESS ( status ) ) {
2013-09-12 04:33:03 +00:00
UChar ubuf [ kNumSysDescripBufMax ] ;
int32_t ulen , radix = unumsys_getRadix ( unumsys ) ;
2013-09-11 05:07:00 +00:00
UBool isAlgorithmic = unumsys_isAlgorithmic ( unumsys ) ;
numsys = unumsys_getName ( unumsys ) ;
if ( uprv_strcmp ( numsys , itemPtr - > numsys ) ! = 0 | | radix ! = itemPtr - > radix | | ! isAlgorithmic ! = ! itemPtr - > isAlgorithmic ) {
2013-09-19 02:32:57 +00:00
log_data_err ( " unumsys name/radix/isAlgorithmic for locale %s, expected %s/%d/%d, got %s/%d/%d \n " ,
2013-09-11 05:07:00 +00:00
itemPtr - > locale , itemPtr - > numsys , itemPtr - > radix , itemPtr - > isAlgorithmic , numsys , radix , isAlgorithmic ) ;
}
2013-09-12 04:33:03 +00:00
ulen = unumsys_getDescription ( unumsys , ubuf , kNumSysDescripBufMax , & status ) ;
2014-01-10 08:35:00 +00:00
( void ) ulen ; // Suppress variable not used warning.
2013-09-12 04:33:03 +00:00
if ( U_FAILURE ( status ) | | u_strcmp ( ubuf , itemPtr - > description ) ! = 0 ) {
2013-09-19 02:32:57 +00:00
log_data_err ( " unumsys description for locale %s, description unexpected and/or status % \n " , myErrorName ( status ) ) ;
2013-09-12 04:33:03 +00:00
}
2013-09-11 05:07:00 +00:00
unumsys_close ( unumsys ) ;
} else {
log_data_err ( " unumsys_open for locale %s fails with status %s \n " , itemPtr - > locale , myErrorName ( status ) ) ;
}
}
2019-02-14 08:59:47 +00:00
2019-03-07 02:43:59 +00:00
for ( int i = 0 ; i < 3 ; + + i ) {
// Run the test of unumsys_openAvailableNames() multiple times.
// Helps verify the management of the internal cache of the names.
status = U_ZERO_ERROR ;
uenum = unumsys_openAvailableNames ( & status ) ;
if ( U_SUCCESS ( status ) ) {
int32_t numsysCount = 0 ;
// sanity check for a couple of number systems that must be in the enumeration
UBool foundLatn = FALSE ;
UBool foundArab = FALSE ;
while ( ( numsys = uenum_next ( uenum , NULL , & status ) ) ! = NULL & & U_SUCCESS ( status ) ) {
status = U_ZERO_ERROR ;
unumsys = unumsys_openByName ( numsys , & status ) ;
if ( U_SUCCESS ( status ) ) {
numsysCount + + ;
if ( uprv_strcmp ( numsys , " latn " ) ) foundLatn = TRUE ;
if ( uprv_strcmp ( numsys , " arab " ) ) foundArab = TRUE ;
unumsys_close ( unumsys ) ;
} else {
log_err ( " unumsys_openAvailableNames includes %s but unumsys_openByName on it fails with status %s \n " ,
numsys , myErrorName ( status ) ) ;
}
2013-09-11 05:07:00 +00:00
}
2019-03-07 02:43:59 +00:00
uenum_close ( uenum ) ;
if ( numsysCount < 40 | | ! foundLatn | | ! foundArab ) {
log_err ( " unumsys_openAvailableNames results incomplete: numsysCount %d, foundLatn %d, foundArab %d \n " ,
numsysCount , foundLatn , foundArab ) ;
}
} else {
log_data_err ( " unumsys_openAvailableNames fails with status %s \n " , myErrorName ( status ) ) ;
2013-09-11 05:07:00 +00:00
}
}
}
2014-02-06 06:31:50 +00:00
/* plain-C version of test in numfmtst.cpp */
enum { kUBufMax = 64 } ;
static void TestCurrencyIsoPluralFormat ( void ) {
2015-09-10 05:40:20 +00:00
static const char * DATA [ ] [ 8 ] = {
2014-02-06 06:31:50 +00:00
// the data are:
// locale,
// currency amount to be formatted,
// currency ISO code to be formatted,
// format result using CURRENCYSTYLE,
2015-09-10 05:40:20 +00:00
// format result using CURRENCY_STANDARD,
// format result using CURRENCY_ACCOUNTING,
2014-02-06 06:31:50 +00:00
// format result using ISOCURRENCYSTYLE,
// format result using PLURALCURRENCYSTYLE,
2018-04-18 06:03:29 +00:00
// locale amount ISOcode CURRENCYSTYLE CURRENCY_STANDARD CURRENCY_ACCOUNTING ISOCURRENCYSTYLE PLURALCURRENCYSTYLE
{ " en_US " , " 1 " , " USD " , " $1.00 " , " $1.00 " , " $1.00 " , " USD \\ u00A01.00 " , " 1.00 US dollars " } ,
{ " en_US " , " 1234.56 " , " USD " , " $1,234.56 " , " $1,234.56 " , " $1,234.56 " , " USD \\ u00A01,234.56 " , " 1,234.56 US dollars " } ,
{ " en_US@cf=account " , " 1234.56 " , " USD " , " $1,234.56 " , " $1,234.56 " , " $1,234.56 " , " USD \\ u00A01,234.56 " , " 1,234.56 US dollars " } ,
{ " en_US " , " -1234.56 " , " USD " , " -$1,234.56 " , " -$1,234.56 " , " ($1,234.56) " , " -USD \\ u00A01,234.56 " , " -1,234.56 US dollars " } ,
{ " en_US@cf=account " , " -1234.56 " , " USD " , " ($1,234.56) " , " -$1,234.56 " , " ($1,234.56) " , " -USD \\ u00A01,234.56 " , " -1,234.56 US dollars " } ,
{ " en_US@cf=standard " , " -1234.56 " , " USD " , " -$1,234.56 " , " -$1,234.56 " , " ($1,234.56) " , " -USD \\ u00A01,234.56 " , " -1,234.56 US dollars " } ,
{ " zh_CN " , " 1 " , " USD " , " US$1.00 " , " US$1.00 " , " US$1.00 " , " USD \\ u00A01.00 " , " 1.00 \\ u00A0 \\ u7F8E \\ u5143 " } ,
{ " zh_CN " , " -1 " , " USD " , " -US$1.00 " , " -US$1.00 " , " (US$1.00) " , " -USD \\ u00A01.00 " , " -1.00 \\ u00A0 \\ u7F8E \\ u5143 " } ,
{ " zh_CN@cf=account " , " -1 " , " USD " , " (US$1.00) " , " -US$1.00 " , " (US$1.00) " , " -USD \\ u00A01.00 " , " -1.00 \\ u00A0 \\ u7F8E \\ u5143 " } ,
{ " zh_CN@cf=standard " , " -1 " , " USD " , " -US$1.00 " , " -US$1.00 " , " (US$1.00) " , " -USD \\ u00A01.00 " , " -1.00 \\ u00A0 \\ u7F8E \\ u5143 " } ,
{ " zh_CN " , " 1234.56 " , " USD " , " US$1,234.56 " , " US$1,234.56 " , " US$1,234.56 " , " USD \\ u00A01,234.56 " , " 1,234.56 \\ u00A0 \\ u7F8E \\ u5143 " } ,
2015-09-10 05:40:20 +00:00
// {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "CHY1.00", "CHY1.00", "1.00 CHY"}, // wrong ISO code
// {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"}, // wrong ISO code
2019-09-04 05:33:27 +00:00
{ " zh_CN " , " 1 " , " CNY " , " \\ u00A51.00 " , " \\ u00A51.00 " , " \\ u00A51.00 " , " CNY \\ u00A01.00 " , " 1.00 \\ u00A0 \\ u4EBA \\ u6C11 \\ u5E01 " } ,
{ " zh_CN " , " 1234.56 " , " CNY " , " \\ u00A51,234.56 " , " \\ u00A51,234.56 " , " \\ u00A51,234.56 " , " CNY \\ u00A01,234.56 " , " 1,234.56 \\ u00A0 \\ u4EBA \\ u6C11 \\ u5E01 " } ,
2018-04-18 06:03:29 +00:00
{ " ru_RU " , " 1 " , " RUB " , " 1,00 \\ u00A0 \\ u20BD " , " 1,00 \\ u00A0 \\ u20BD " , " 1,00 \\ u00A0 \\ u20BD " , " 1,00 \\ u00A0RUB " , " 1,00 \\ u0440 \\ u043E \\ u0441 \\ u0441 \\ u0438 \\ u0439 \\ u0441 \\ u043A \\ u043E \\ u0433 \\ u043E "
" \\ u0440 \\ u0443 \\ u0431 \\ u043B \\ u044F " } ,
{ " ru_RU " , " 2 " , " RUB " , " 2,00 \\ u00A0 \\ u20BD " , " 2,00 \\ u00A0 \\ u20BD " , " 2,00 \\ u00A0 \\ u20BD " , " 2,00 \\ u00A0RUB " , " 2,00 \\ u0440 \\ u043E \\ u0441 \\ u0441 \\ u0438 \\ u0439 \\ u0441 \\ u043A \\ u043E \\ u0433 \\ u043E "
" \\ u0440 \\ u0443 \\ u0431 \\ u043B \\ u044F " } ,
{ " ru_RU " , " 5 " , " RUB " , " 5,00 \\ u00A0 \\ u20BD " , " 5,00 \\ u00A0 \\ u20BD " , " 5,00 \\ u00A0 \\ u20BD " , " 5,00 \\ u00A0RUB " , " 5,00 \\ u0440 \\ u043E \\ u0441 \\ u0441 \\ u0438 \\ u0439 \\ u0441 \\ u043A \\ u043E \\ u0433 \\ u043E "
" \\ u0440 \\ u0443 \\ u0431 \\ u043B \\ u044F " } ,
2014-02-06 06:31:50 +00:00
// test locale without currency information
2015-09-10 05:40:20 +00:00
{ " root " , " -1.23 " , " USD " , " -US$ \\ u00A01.23 " , " -US$ \\ u00A01.23 " , " -US$ \\ u00A01.23 " , " -USD \\ u00A01.23 " , " -1.23 USD " } ,
{ " root@cf=account " , " -1.23 " , " USD " , " -US$ \\ u00A01.23 " , " -US$ \\ u00A01.23 " , " -US$ \\ u00A01.23 " , " -USD \\ u00A01.23 " , " -1.23 USD " } ,
2014-02-06 06:31:50 +00:00
// test choice format
2015-09-10 05:40:20 +00:00
{ " es_AR " , " 1 " , " INR " , " INR \\ u00A01,00 " , " INR \\ u00A01,00 " , " INR \\ u00A01,00 " , " INR \\ u00A01,00 " , " 1,00 rupia india " } ,
2014-02-06 06:31:50 +00:00
} ;
static const UNumberFormatStyle currencyStyles [ ] = {
UNUM_CURRENCY ,
2015-09-10 05:40:20 +00:00
UNUM_CURRENCY_STANDARD ,
UNUM_CURRENCY_ACCOUNTING ,
2014-02-06 06:31:50 +00:00
UNUM_CURRENCY_ISO ,
UNUM_CURRENCY_PLURAL
} ;
int32_t i , sIndex ;
2019-02-14 08:59:47 +00:00
for ( i = 0 ; i < UPRV_LENGTHOF ( DATA ) ; + + i ) {
2014-02-06 06:31:50 +00:00
const char * localeString = DATA [ i ] [ 0 ] ;
double numberToBeFormat = atof ( DATA [ i ] [ 1 ] ) ;
const char * currencyISOCode = DATA [ i ] [ 2 ] ;
2016-02-23 10:40:09 +00:00
for ( sIndex = 0 ; sIndex < UPRV_LENGTHOF ( currencyStyles ) ; + + sIndex ) {
2014-02-06 06:31:50 +00:00
UNumberFormatStyle style = currencyStyles [ sIndex ] ;
UErrorCode status = U_ZERO_ERROR ;
UChar currencyCode [ 4 ] ;
UChar ubufResult [ kUBufMax ] ;
UChar ubufExpected [ kUBufMax ] ;
int32_t ulenRes ;
2019-02-14 08:59:47 +00:00
2014-02-06 06:31:50 +00:00
UNumberFormat * unumFmt = unum_open ( style , NULL , 0 , localeString , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " FAIL: unum_open, locale %s, style %d - %s \n " , localeString , ( int ) style , myErrorName ( status ) ) ;
continue ;
}
u_charsToUChars ( currencyISOCode , currencyCode , 4 ) ;
unum_setTextAttribute ( unumFmt , UNUM_CURRENCY_CODE , currencyCode , 3 , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " FAIL: unum_setTextAttribute, locale %s, UNUM_CURRENCY_CODE %s \n " , localeString , currencyISOCode ) ;
}
ulenRes = unum_formatDouble ( unumFmt , numberToBeFormat , ubufResult , kUBufMax , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " FAIL: unum_formatDouble, locale %s, UNUM_CURRENCY_CODE %s - %s \n " , localeString , currencyISOCode , myErrorName ( status ) ) ;
} else {
int32_t ulenExp = u_unescape ( DATA [ i ] [ 3 + sIndex ] , ubufExpected , kUBufMax ) ;
if ( ulenRes ! = ulenExp | | u_strncmp ( ubufResult , ubufExpected , ulenExp ) ! = 0 ) {
log_err ( " FAIL: unum_formatDouble, locale %s, UNUM_CURRENCY_CODE %s, expected %s, got something else \n " ,
localeString , currencyISOCode , DATA [ i ] [ 3 + sIndex ] ) ;
}
}
2014-02-06 09:41:17 +00:00
unum_close ( unumFmt ) ;
2014-02-06 06:31:50 +00:00
}
2019-02-14 08:59:47 +00:00
}
2014-02-06 06:31:50 +00:00
}
2014-02-06 09:41:17 +00:00
typedef struct {
const char * locale ;
UNumberFormatStyle style ;
UDisplayContext context ;
const char * expectedResult ;
} TestContextItem ;
/* currently no locales have contextTransforms data for "symbol" type */
static const TestContextItem tcItems [ ] = { /* results for 123.45 */
{ " sv " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE , " ett \\ u00ADhundra \\ u00ADtjugo \\ u00ADtre komma fyra fem " } ,
{ " sv " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE , " Ett \\ u00ADhundra \\ u00ADtjugo \\ u00ADtre komma fyra fem " } ,
{ " sv " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU , " ett \\ u00ADhundra \\ u00ADtjugo \\ u00ADtre komma fyra fem " } ,
{ " sv " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_STANDALONE , " ett \\ u00ADhundra \\ u00ADtjugo \\ u00ADtre komma fyra fem " } ,
2014-02-24 07:17:41 +00:00
{ " en " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE , " one hundred twenty-three point four five " } ,
{ " en " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE , " One hundred twenty-three point four five " } ,
{ " en " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU , " One hundred twenty-three point four five " } ,
{ " en " , UNUM_SPELLOUT , UDISPCTX_CAPITALIZATION_FOR_STANDALONE , " One hundred twenty-three point four five " } ,
2014-02-06 09:41:17 +00:00
{ NULL , ( UNumberFormatStyle ) 0 , ( UDisplayContext ) 0 , NULL }
} ;
2014-01-15 09:31:11 +00:00
static void TestContext ( void ) {
UErrorCode status = U_ZERO_ERROR ;
2014-02-06 09:41:17 +00:00
const TestContextItem * itemPtr ;
2019-02-14 08:59:47 +00:00
2014-01-15 09:31:11 +00:00
UNumberFormat * unum = unum_open ( UNUM_SPELLOUT , NULL , 0 , " en " , NULL , & status ) ;
if ( U_SUCCESS ( status ) ) {
UDisplayContext context = unum_getContext ( unum , UDISPCTX_TYPE_CAPITALIZATION , & status ) ;
if ( U_FAILURE ( status ) | | context ! = UDISPCTX_CAPITALIZATION_NONE ) {
log_err ( " FAIL: Initial unum_getContext is not UDISPCTX_CAPITALIZATION_NONE \n " ) ;
status = U_ZERO_ERROR ;
}
unum_setContext ( unum , UDISPCTX_CAPITALIZATION_FOR_STANDALONE , & status ) ;
context = unum_getContext ( unum , UDISPCTX_TYPE_CAPITALIZATION , & status ) ;
if ( U_FAILURE ( status ) | | context ! = UDISPCTX_CAPITALIZATION_FOR_STANDALONE ) {
log_err ( " FAIL: unum_getContext does not return the value set, UDISPCTX_CAPITALIZATION_FOR_STANDALONE \n " ) ;
}
unum_close ( unum ) ;
} else {
log_data_err ( " unum_open UNUM_SPELLOUT for en fails with status %s \n " , myErrorName ( status ) ) ;
}
2014-03-15 06:08:42 +00:00
# if !UCONFIG_NO_NORMALIZATION && !UCONFIG_NO_BREAK_ITERATION
2014-02-06 09:41:17 +00:00
for ( itemPtr = tcItems ; itemPtr - > locale ! = NULL ; itemPtr + + ) {
UChar ubufResult [ kUBufMax ] ;
int32_t ulenRes ;
2019-02-14 08:59:47 +00:00
2014-02-06 09:41:17 +00:00
status = U_ZERO_ERROR ;
unum = unum_open ( itemPtr - > style , NULL , 0 , itemPtr - > locale , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " FAIL: unum_open, locale %s, style %d - %s \n " ,
itemPtr - > locale , ( int ) itemPtr - > style , myErrorName ( status ) ) ;
continue ;
}
unum_setContext ( unum , itemPtr - > context , & status ) ;
ulenRes = unum_formatDouble ( unum , 123.45 , ubufResult , kUBufMax , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " FAIL: unum_formatDouble, locale %s, style %d, context %d - %s \n " ,
itemPtr - > locale , ( int ) itemPtr - > style , ( int ) itemPtr - > context , myErrorName ( status ) ) ;
} else {
UChar ubufExpected [ kUBufMax ] ;
int32_t ulenExp = u_unescape ( itemPtr - > expectedResult , ubufExpected , kUBufMax ) ;
if ( ulenRes ! = ulenExp | | u_strncmp ( ubufResult , ubufExpected , ulenExp ) ! = 0 ) {
char bbuf [ kUBufMax * 2 ] ;
2019-02-14 08:59:47 +00:00
u_austrncpy ( bbuf , ubufResult , sizeof ( bbuf ) ) ;
2014-02-06 09:41:17 +00:00
log_err ( " FAIL: unum_formatDouble, locale %s, style %d, context %d, expected %d: \" %s \" , got %d: \" %s \" \n " ,
itemPtr - > locale , ( int ) itemPtr - > style , ( int ) itemPtr - > context , ulenExp ,
itemPtr - > expectedResult , ulenRes , bbuf ) ;
}
}
unum_close ( unum ) ;
}
2014-03-15 06:08:42 +00:00
# endif /* #if !UCONFIG_NO_NORMALIZATION && !UCONFIG_NO_BREAK_ITERATION */
2014-01-15 09:31:11 +00:00
}
2014-06-12 21:40:34 +00:00
static void TestCurrencyUsage ( void ) {
static const char * DATA [ ] [ 2 ] = {
2014-09-02 23:18:20 +00:00
/* the data are:
* currency ISO code to be formatted ,
* format result using CURRENCYSTYLE with CASH purpose , -
* Note that as of CLDR 26 : -
* - TWD switches from 0 decimals to 2 ; PKR still has 0 , so change test to that
2016-02-26 22:51:31 +00:00
* - CAD rounds to .05
2014-09-02 23:18:20 +00:00
*/
2018-04-18 06:03:29 +00:00
{ " PKR " , " PKR \\ u00A0124 " } ,
2016-02-26 22:51:31 +00:00
{ " CAD " , " CA$123.55 " } ,
2014-06-12 21:40:34 +00:00
{ " USD " , " $123.57 " }
} ;
// 1st time for getter/setter, 2nd for factory method
int32_t i ;
for ( i = 0 ; i < 2 ; i + + ) {
const char * localeString = " en_US " ;
double numberToBeFormat = 123.567 ;
UNumberFormat * unumFmt ;
UNumberFormatStyle style = UNUM_CURRENCY ;
UErrorCode status = U_ZERO_ERROR ;
int32_t j ;
if ( i = = 1 ) { // change for factory method
style = UNUM_CASH_CURRENCY ;
}
unumFmt = unum_open ( style , NULL , 0 , localeString , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " FAIL: unum_open, locale %s, style %d - %s \n " ,
localeString , ( int ) style , myErrorName ( status ) ) ;
2014-07-02 05:09:05 +00:00
continue ;
2014-06-12 21:40:34 +00:00
}
if ( i = = 0 ) { // this is for the getter/setter
if ( unum_getAttribute ( unumFmt , UNUM_CURRENCY_USAGE ) ! = UCURR_USAGE_STANDARD ) {
log_err ( " FAIL: currency usage attribute is not UNUM_CURRENCY_STANDARD \n " ) ;
}
unum_setAttribute ( unumFmt , UNUM_CURRENCY_USAGE , UCURR_USAGE_CASH ) ;
}
if ( unum_getAttribute ( unumFmt , UNUM_CURRENCY_USAGE ) ! = UCURR_USAGE_CASH ) {
log_err ( " FAIL: currency usage attribute is not UNUM_CURRENCY_CASH \n " ) ;
}
2019-02-14 08:59:47 +00:00
for ( j = 0 ; j < UPRV_LENGTHOF ( DATA ) ; + + j ) {
2014-06-12 21:40:34 +00:00
UChar expect [ 64 ] ;
int32_t expectLen ;
UChar currencyCode [ 4 ] ;
UChar result [ 64 ] ;
int32_t resultLen ;
UFieldPosition pos = { 0 } ;
u_charsToUChars ( DATA [ j ] [ 0 ] , currencyCode , 3 ) ;
2016-02-23 10:40:09 +00:00
expectLen = u_unescape ( DATA [ j ] [ 1 ] , expect , UPRV_LENGTHOF ( expect ) ) ;
2014-06-12 21:40:34 +00:00
unum_setTextAttribute ( unumFmt , UNUM_CURRENCY_CODE , currencyCode , 3 , & status ) ;
assertSuccess ( " num_setTextAttribute() " , & status ) ;
2016-02-23 10:40:09 +00:00
resultLen = unum_formatDouble ( unumFmt , numberToBeFormat , result , UPRV_LENGTHOF ( result ) ,
2014-06-12 21:40:34 +00:00
& pos , & status ) ;
assertSuccess ( " num_formatDouble() " , & status ) ;
if ( resultLen ! = expectLen | | u_strcmp ( result , expect ) ! = 0 ) {
log_err ( " Fail: Error in Number Format Currency Purpose using unum_setAttribute() expected: %s, got %s \n " ,
aescstrdup ( expect , expectLen ) , aescstrdup ( result , resultLen ) ) ;
}
}
2019-02-14 08:59:47 +00:00
2014-06-12 21:40:34 +00:00
unum_close ( unumFmt ) ;
}
}
2014-09-07 20:01:55 +00:00
static UChar currFmtNegSameAsPos [ ] = /* "\u00A4#,##0.00;\u00A4#,##0.00" */
{ 0xA4 , 0x23 , 0x2C , 0x23 , 0x23 , 0x30 , 0x2E , 0x30 , 0x30 , 0x3B , 0xA4 , 0x23 , 0x2C , 0x23 , 0x23 , 0x30 , 0x2E , 0x30 , 0x30 , 0 } ;
2018-04-18 06:03:29 +00:00
// NOTE: As of ICU 62, identical positive and negative subpatterns means no minus sign!
// See CLDR ticket https://unicode.org/cldr/trac/ticket/10703
//static UChar currFmtToPatExpected[] = /* "\u00A4#,##0.00" */
// {0xA4,0x23,0x2C,0x23,0x23,0x30,0x2E,0x30,0x30,0};
static const UChar * currFmtToPatExpected = currFmtNegSameAsPos ;
2014-09-07 20:01:55 +00:00
static UChar currFmtResultExpected [ ] = /* "$100.00" */
{ 0x24 , 0x31 , 0x30 , 0x30 , 0x2E , 0x30 , 0x30 , 0 } ;
static UChar emptyString [ ] = { 0 } ;
2015-06-23 18:09:52 +00:00
enum { kUBufSize = 64 , kBBufSize = 128 } ;
2014-09-07 20:01:55 +00:00
static void TestCurrFmtNegSameAsPositive ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unumfmt = unum_open ( UNUM_CURRENCY , NULL , 0 , " en_US " , NULL , & status ) ;
if ( U_SUCCESS ( status ) ) {
unum_applyPattern ( unumfmt , FALSE , currFmtNegSameAsPos , - 1 , NULL , & status ) ;
if ( U_SUCCESS ( status ) ) {
UChar ubuf [ kUBufSize ] ;
int32_t ulen = unum_toPattern ( unumfmt , FALSE , ubuf , kUBufSize , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_toPattern fails with status %s \n " , myErrorName ( status ) ) ;
} else if ( u_strcmp ( ubuf , currFmtToPatExpected ) ! = 0 ) {
log_err ( " unum_toPattern result wrong, expected %s, got %s \n " , aescstrdup ( currFmtToPatExpected , - 1 ) , aescstrdup ( ubuf , ulen ) ) ;
}
unum_setSymbol ( unumfmt , UNUM_MINUS_SIGN_SYMBOL , emptyString , 0 , & status ) ;
if ( U_SUCCESS ( status ) ) {
ulen = unum_formatDouble ( unumfmt , - 100.0 , ubuf , kUBufSize , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_formatDouble fails with status %s \n " , myErrorName ( status ) ) ;
} else if ( u_strcmp ( ubuf , currFmtResultExpected ) ! = 0 ) {
log_err ( " unum_formatDouble result wrong, expected %s, got %s \n " , aescstrdup ( currFmtResultExpected , - 1 ) , aescstrdup ( ubuf , ulen ) ) ;
}
} else {
log_err ( " unum_setSymbol fails with status %s \n " , myErrorName ( status ) ) ;
}
} else {
log_err ( " unum_applyPattern fails with status %s \n " , myErrorName ( status ) ) ;
}
unum_close ( unumfmt ) ;
} else {
log_data_err ( " unum_open UNUM_CURRENCY for en_US fails with status %s \n " , myErrorName ( status ) ) ;
}
}
2015-06-23 18:09:52 +00:00
typedef struct {
double value ;
const char * expected ;
} ValueAndExpectedString ;
static const ValueAndExpectedString enShort [ ] = {
{ 0.0 , " 0 " } ,
{ 0.17 , " 0.17 " } ,
{ 1.0 , " 1 " } ,
2018-04-18 06:03:29 +00:00
{ 1234.0 , " 1.2K " } ,
{ 12345.0 , " 12K " } ,
2015-06-23 18:09:52 +00:00
{ 123456.0 , " 123K " } ,
2018-04-18 06:03:29 +00:00
{ 1234567.0 , " 1.2M " } ,
{ 12345678.0 , " 12M " } ,
2015-06-23 18:09:52 +00:00
{ 123456789.0 , " 123M " } ,
2018-04-18 06:03:29 +00:00
{ 1.23456789E9 , " 1.2B " } ,
{ 1.23456789E10 , " 12B " } ,
2015-06-23 18:09:52 +00:00
{ 1.23456789E11 , " 123B " } ,
2018-04-18 06:03:29 +00:00
{ 1.23456789E12 , " 1.2T " } ,
{ 1.23456789E13 , " 12T " } ,
2015-06-23 18:09:52 +00:00
{ 1.23456789E14 , " 123T " } ,
2018-04-18 06:03:29 +00:00
{ 1.23456789E15 , " 1235T " } ,
2015-06-23 18:09:52 +00:00
{ 0.0 , NULL }
} ;
static const ValueAndExpectedString enShortMax2 [ ] = {
{ 0.0 , " 0 " } ,
{ 0.17 , " 0.17 " } ,
{ 1.0 , " 1 " } ,
{ 1234.0 , " 1.2K " } ,
{ 12345.0 , " 12K " } ,
{ 123456.0 , " 120K " } ,
{ 1234567.0 , " 1.2M " } ,
{ 12345678.0 , " 12M " } ,
{ 123456789.0 , " 120M " } ,
{ 1.23456789E9 , " 1.2B " } ,
{ 1.23456789E10 , " 12B " } ,
{ 1.23456789E11 , " 120B " } ,
{ 1.23456789E12 , " 1.2T " } ,
{ 1.23456789E13 , " 12T " } ,
{ 1.23456789E14 , " 120T " } ,
{ 1.23456789E15 , " 1200T " } ,
{ 0.0 , NULL }
} ;
static const ValueAndExpectedString enShortMax5 [ ] = {
{ 0.0 , " 0 " } ,
{ 0.17 , " 0.17 " } ,
{ 1.0 , " 1 " } ,
{ 1234.0 , " 1.234K " } ,
{ 12345.0 , " 12.345K " } ,
{ 123456.0 , " 123.46K " } ,
{ 1234567.0 , " 1.2346M " } ,
{ 12345678.0 , " 12.346M " } ,
{ 123456789.0 , " 123.46M " } ,
{ 1.23456789E9 , " 1.2346B " } ,
{ 1.23456789E10 , " 12.346B " } ,
{ 1.23456789E11 , " 123.46B " } ,
{ 1.23456789E12 , " 1.2346T " } ,
{ 1.23456789E13 , " 12.346T " } ,
{ 1.23456789E14 , " 123.46T " } ,
{ 1.23456789E15 , " 1234.6T " } ,
{ 0.0 , NULL }
} ;
static const ValueAndExpectedString enShortMin3 [ ] = {
{ 0.0 , " 0.00 " } ,
{ 0.17 , " 0.170 " } ,
{ 1.0 , " 1.00 " } ,
{ 1234.0 , " 1.23K " } ,
{ 12345.0 , " 12.3K " } ,
{ 123456.0 , " 123K " } ,
{ 1234567.0 , " 1.23M " } ,
{ 12345678.0 , " 12.3M " } ,
{ 123456789.0 , " 123M " } ,
{ 1.23456789E9 , " 1.23B " } ,
{ 1.23456789E10 , " 12.3B " } ,
{ 1.23456789E11 , " 123B " } ,
{ 1.23456789E12 , " 1.23T " } ,
{ 1.23456789E13 , " 12.3T " } ,
{ 1.23456789E14 , " 123T " } ,
{ 1.23456789E15 , " 1230T " } ,
{ 0.0 , NULL }
} ;
static const ValueAndExpectedString jaShortMax2 [ ] = {
2015-08-27 20:23:27 +00:00
{ 1234.0 , " 1200 " } ,
2015-06-23 18:09:52 +00:00
{ 12345.0 , " 1.2 \\ u4E07 " } ,
{ 123456.0 , " 12 \\ u4E07 " } ,
{ 1234567.0 , " 120 \\ u4E07 " } ,
{ 12345678.0 , " 1200 \\ u4E07 " } ,
{ 123456789.0 , " 1.2 \\ u5104 " } ,
{ 1.23456789E9 , " 12 \\ u5104 " } ,
{ 1.23456789E10 , " 120 \\ u5104 " } ,
{ 1.23456789E11 , " 1200 \\ u5104 " } ,
{ 1.23456789E12 , " 1.2 \\ u5146 " } ,
{ 1.23456789E13 , " 12 \\ u5146 " } ,
{ 1.23456789E14 , " 120 \\ u5146 " } ,
{ 0.0 , NULL }
} ;
static const ValueAndExpectedString srLongMax2 [ ] = {
{ 1234.0 , " 1,2 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0435 " } , // 10^3 few
{ 12345.0 , " 12 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0430 " } , // 10^3 other
{ 21789.0 , " 22 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0435 " } , // 10^3 few
{ 123456.0 , " 120 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0430 " } , // 10^3 other
{ 999999.0 , " 1 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D " } , // 10^6 one
{ 1234567.0 , " 1,2 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D \\ u0430 " } , // 10^6 few
{ 12345678.0 , " 12 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D \\ u0430 " } , // 10^6 other
{ 123456789.0 , " 120 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D \\ u0430 " } , // 10^6 other
{ 1.23456789E9 , " 1,2 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0435 " } , // 10^9 few
{ 1.23456789E10 , " 12 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0438 " } , // 10^9 other
{ 2.08901234E10 , " 21 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0430 " } , // 10^9 one
{ 2.18901234E10 , " 22 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0435 " } , // 10^9 few
{ 1.23456789E11 , " 120 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0438 " } , // 10^9 other
{ - 1234.0 , " -1,2 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0435 " } ,
{ - 12345.0 , " -12 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0430 " } ,
{ - 21789.0 , " -22 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0435 " } ,
{ - 123456.0 , " -120 \\ u0445 \\ u0438 \\ u0459 \\ u0430 \\ u0434 \\ u0430 " } ,
{ - 999999.0 , " -1 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D " } ,
{ - 1234567.0 , " -1,2 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D \\ u0430 " } ,
{ - 12345678.0 , " -12 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D \\ u0430 " } ,
{ - 123456789.0 , " -120 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u043E \\ u043D \\ u0430 " } ,
{ - 1.23456789E9 , " -1,2 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0435 " } ,
{ - 1.23456789E10 , " -12 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0438 " } ,
{ - 2.08901234E10 , " -21 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0430 " } ,
{ - 2.18901234E10 , " -22 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0435 " } ,
{ - 1.23456789E11 , " -120 \\ u043C \\ u0438 \\ u043B \\ u0438 \\ u0458 \\ u0430 \\ u0440 \\ u0434 \\ u0438 " } ,
{ 0.0 , NULL }
} ;
typedef struct {
const char * locale ;
UNumberFormatStyle style ;
int32_t attribute ; // UNumberFormatAttribute, or -1 for none
int32_t attrValue ; //
const ValueAndExpectedString * veItems ;
} LocStyleAttributeTest ;
static const LocStyleAttributeTest lsaTests [ ] = {
{ " en " , UNUM_DECIMAL_COMPACT_SHORT , - 1 , 0 , enShort } ,
{ " en " , UNUM_DECIMAL_COMPACT_SHORT , UNUM_MAX_SIGNIFICANT_DIGITS , 2 , enShortMax2 } ,
{ " en " , UNUM_DECIMAL_COMPACT_SHORT , UNUM_MAX_SIGNIFICANT_DIGITS , 5 , enShortMax5 } ,
{ " en " , UNUM_DECIMAL_COMPACT_SHORT , UNUM_MIN_SIGNIFICANT_DIGITS , 3 , enShortMin3 } ,
{ " ja " , UNUM_DECIMAL_COMPACT_SHORT , UNUM_MAX_SIGNIFICANT_DIGITS , 2 , jaShortMax2 } ,
{ " sr " , UNUM_DECIMAL_COMPACT_LONG , UNUM_MAX_SIGNIFICANT_DIGITS , 2 , srLongMax2 } ,
2019-02-14 08:59:47 +00:00
{ NULL , ( UNumberFormatStyle ) 0 , - 1 , 0 , NULL }
2015-06-23 18:09:52 +00:00
} ;
static void TestVariousStylesAndAttributes ( void ) {
const LocStyleAttributeTest * lsaTestPtr ;
for ( lsaTestPtr = lsaTests ; lsaTestPtr - > locale ! = NULL ; lsaTestPtr + + ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unum = unum_open ( lsaTestPtr - > style , NULL , 0 , lsaTestPtr - > locale , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
2015-06-30 23:45:58 +00:00
log_data_err ( " FAIL: unum_open style %d, locale %s: error %s \n " , ( int ) lsaTestPtr - > style , lsaTestPtr - > locale , u_errorName ( status ) ) ;
2015-06-23 18:09:52 +00:00
} else {
const ValueAndExpectedString * veItemPtr ;
if ( lsaTestPtr - > attribute > = 0 ) {
unum_setAttribute ( unum , ( UNumberFormatAttribute ) lsaTestPtr - > attribute , lsaTestPtr - > attrValue ) ;
}
2018-04-18 06:03:29 +00:00
// ICU 62: should call minSignificantDigits in tandem with maxSignificantDigits.
if ( lsaTestPtr - > attribute = = UNUM_MIN_SIGNIFICANT_DIGITS ) {
unum_setAttribute ( unum , UNUM_MAX_SIGNIFICANT_DIGITS , lsaTestPtr - > attrValue ) ;
}
2015-06-23 18:09:52 +00:00
for ( veItemPtr = lsaTestPtr - > veItems ; veItemPtr - > expected ! = NULL ; veItemPtr + + ) {
UChar uexp [ kUBufSize ] ;
UChar uget [ kUBufSize ] ;
int32_t uexplen , ugetlen ;
2019-02-14 08:59:47 +00:00
2015-06-23 18:09:52 +00:00
status = U_ZERO_ERROR ;
uexplen = u_unescape ( veItemPtr - > expected , uexp , kUBufSize ) ;
ugetlen = unum_formatDouble ( unum , veItemPtr - > value , uget , kUBufSize , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " FAIL: unum_formatDouble style %d, locale %s, attr %d, value %.2f: error %s \n " ,
( int ) lsaTestPtr - > style , lsaTestPtr - > locale , lsaTestPtr - > attribute , veItemPtr - > value , u_errorName ( status ) ) ;
} else if ( ugetlen ! = uexplen | | u_strncmp ( uget , uexp , uexplen ) ! = 0 ) {
char bexp [ kBBufSize ] ;
char bget [ kBBufSize ] ;
u_strToUTF8 ( bexp , kBBufSize , NULL , uexp , uexplen , & status ) ;
u_strToUTF8 ( bget , kBBufSize , NULL , uget , ugetlen , & status ) ;
log_err ( " FAIL: unum_formatDouble style %d, locale %s, attr %d, value %.2f: expect \" %s \" , get \" %s \" \n " ,
( int ) lsaTestPtr - > style , lsaTestPtr - > locale , lsaTestPtr - > attribute , veItemPtr - > value , bexp , bget ) ;
}
}
unum_close ( unum ) ;
}
}
}
2016-09-27 00:23:19 +00:00
static const UChar currpat [ ] = { 0xA4 , 0x23 , 0x2C , 0x23 , 0x23 , 0x30 , 0x2E , 0x30 , 0x30 , 0 } ;
2016-09-15 03:55:22 +00:00
static const UChar parsetxt [ ] = { 0x78 , 0x30 , 0x79 , 0x24 , 0 } ; /* x0y$ */
static void TestParseCurrPatternWithDecStyle ( ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unumfmt = unum_open ( UNUM_DECIMAL , NULL , 0 , " en_US " , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " unum_open DECIMAL failed for en_US: %s (Are you missing data?) \n " , u_errorName ( status ) ) ;
} else {
unum_applyPattern ( unumfmt , FALSE , currpat , - 1 , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err_status ( status , " unum_applyPattern failed: %s \n " , u_errorName ( status ) ) ;
} else {
int32_t pos = 0 ;
double value = unum_parseDouble ( unumfmt , parsetxt , - 1 , & pos , & status ) ;
if ( U_SUCCESS ( status ) ) {
log_err_status ( status , " unum_parseDouble expected to fail but got status %s, value %f \n " , u_errorName ( status ) , value ) ;
}
}
unum_close ( unumfmt ) ;
}
}
2017-01-16 19:48:33 +00:00
/*
* Ticket # 12684
* Test unum_formatDoubleForFields ( and UFieldPositionIterator )
*/
typedef struct {
int32_t field ;
int32_t beginPos ;
int32_t endPos ;
} FieldsData ;
typedef struct {
const char * locale ;
UNumberFormatStyle style ;
double value ;
const FieldsData * expectedFields ;
} FormatForFieldsItem ;
static const UChar patNoFields [ ] = { 0x0027 , 0x0078 , 0x0027 , 0 } ; /* "'x'", for UNUM_PATTERN_DECIMAL */
/* "en_US", UNUM_CURRENCY, 123456.0 : "¤#,##0.00" => "$123,456.00" */
static const FieldsData fields_en_CURR [ ] = {
{ UNUM_CURRENCY_FIELD /*7*/ , 0 , 1 } ,
{ UNUM_GROUPING_SEPARATOR_FIELD /*6*/ , 4 , 5 } ,
{ UNUM_INTEGER_FIELD /*0*/ , 1 , 8 } ,
{ UNUM_DECIMAL_SEPARATOR_FIELD /*2*/ , 8 , 9 } ,
{ UNUM_FRACTION_FIELD /*1*/ , 9 , 11 } ,
{ - 1 , - 1 , - 1 } ,
} ;
/* "en_US", UNUM_PERCENT, -34 : "#,##0%" => "-34%" */
static const FieldsData fields_en_PRCT [ ] = {
{ UNUM_SIGN_FIELD /*10*/ , 0 , 1 } ,
{ UNUM_INTEGER_FIELD /*0*/ , 1 , 3 } ,
{ UNUM_PERCENT_FIELD /*8*/ , 3 , 4 } ,
{ - 1 , - 1 , - 1 } ,
} ;
/* "fr_FR", UNUM_CURRENCY, 123456.0 : "#,##0.00 ¤" => "123,456.00 €" */
static const FieldsData fields_fr_CURR [ ] = {
{ UNUM_GROUPING_SEPARATOR_FIELD /*6*/ , 3 , 4 } ,
{ UNUM_INTEGER_FIELD /*0*/ , 0 , 7 } ,
{ UNUM_DECIMAL_SEPARATOR_FIELD /*2*/ , 7 , 8 } ,
{ UNUM_FRACTION_FIELD /*1*/ , 8 , 10 } ,
{ UNUM_CURRENCY_FIELD /*7*/ , 11 , 12 } ,
{ - 1 , - 1 , - 1 } ,
} ;
/* "en_US", UNUM_PATTERN_DECIMAL, 12.0 : "'x'" => "x12" */
static const FieldsData fields_en_PATN [ ] = {
{ UNUM_INTEGER_FIELD /*0*/ , 1 , 3 } ,
{ - 1 , - 1 , - 1 } ,
} ;
static const FormatForFieldsItem fffItems [ ] = {
{ " en_US " , UNUM_CURRENCY_STANDARD , 123456.0 , fields_en_CURR } ,
{ " en_US " , UNUM_PERCENT , - 0.34 , fields_en_PRCT } ,
{ " fr_FR " , UNUM_CURRENCY_STANDARD , 123456.0 , fields_fr_CURR } ,
{ " en_US " , UNUM_PATTERN_DECIMAL , 12.0 , fields_en_PATN } ,
{ NULL , ( UNumberFormatStyle ) 0 , 0 , NULL } ,
} ;
static void TestFormatForFields ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UFieldPositionIterator * fpositer = ufieldpositer_open ( & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " ufieldpositer_open fails, status %s \n " , u_errorName ( status ) ) ;
} else {
const FormatForFieldsItem * itemPtr ;
for ( itemPtr = fffItems ; itemPtr - > locale ! = NULL ; itemPtr + + ) {
UNumberFormat * unum ;
status = U_ZERO_ERROR ;
unum = ( itemPtr - > style = = UNUM_PATTERN_DECIMAL ) ?
unum_open ( itemPtr - > style , patNoFields , - 1 , itemPtr - > locale , NULL , & status ) :
unum_open ( itemPtr - > style , NULL , 0 , itemPtr - > locale , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " unum_open fails for locale %s, style %d: status %s (Are you missing data?) \n " , itemPtr - > locale , itemPtr - > style , u_errorName ( status ) ) ;
} else {
UChar ubuf [ kUBufSize ] ;
int32_t ulen = unum_formatDoubleForFields ( unum , itemPtr - > value , ubuf , kUBufSize , fpositer , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_formatDoubleForFields fails for locale %s, style %d: status %s \n " , itemPtr - > locale , itemPtr - > style , u_errorName ( status ) ) ;
} else {
const FieldsData * fptr ;
int32_t field , beginPos , endPos ;
for ( fptr = itemPtr - > expectedFields ; TRUE ; fptr + + ) {
field = ufieldpositer_next ( fpositer , & beginPos , & endPos ) ;
if ( field ! = fptr - > field | | ( field > = 0 & & ( beginPos ! = fptr - > beginPos | | endPos ! = fptr - > endPos ) ) ) {
if ( fptr - > field > = 0 ) {
log_err ( " unum_formatDoubleForFields for locale %s as \" %s \" ; expect field %d range %d-%d, get field %d range %d-%d \n " ,
itemPtr - > locale , aescstrdup ( ubuf , ulen ) , fptr - > field , fptr - > beginPos , fptr - > endPos , field , beginPos , endPos ) ;
} else {
log_err ( " unum_formatDoubleForFields for locale %s as \" %s \" ; expect field < 0, get field %d range %d-%d \n " ,
itemPtr - > locale , aescstrdup ( ubuf , ulen ) , field , beginPos , endPos ) ;
}
break ;
}
if ( field < 0 ) {
break ;
}
}
}
unum_close ( unum ) ;
}
}
ufieldpositer_close ( fpositer ) ;
}
}
2018-04-28 05:50:52 +00:00
static void Test12052_NullPointer ( ) {
UErrorCode status = U_ZERO_ERROR ;
static const UChar input [ ] = u " 199a " ;
UChar currency [ 200 ] = { 0 } ;
UNumberFormat * theFormatter = unum_open ( UNUM_CURRENCY , NULL , 0 , " en_US " , NULL , & status ) ;
2018-06-01 01:19:38 +00:00
if ( ! assertSuccessCheck ( " unum_open() failed " , & status , TRUE ) ) { return ; }
2018-04-28 05:50:52 +00:00
status = U_ZERO_ERROR ;
unum_setAttribute ( theFormatter , UNUM_LENIENT_PARSE , 1 ) ;
int32_t pos = 1 ;
unum_parseDoubleCurrency ( theFormatter , input , - 1 , & pos , currency , & status ) ;
assertEquals ( " should fail gracefully " , " U_PARSE_ERROR " , u_errorName ( status ) ) ;
unum_close ( theFormatter ) ;
}
2019-02-05 19:34:29 +00:00
typedef struct {
const char * locale ;
const UChar * text ; // text to parse
UBool lenient ; // leniency to use
UBool intOnly ; // whether to set PARSE_INT_ONLY
UErrorCode intStatus ; // expected status from parse
int32_t intPos ; // expected final pos from parse
int32_t intValue ; // expected value from parse
UErrorCode doubStatus ; // expected status from parseDouble
int32_t doubPos ; // expected final pos from parseDouble
double doubValue ; // expected value from parseDouble
UErrorCode decStatus ; // expected status from parseDecimal
int32_t decPos ; // expected final pos from parseDecimal
const char * decString ; // expected output string from parseDecimal
} ParseCaseItem ;
static const ParseCaseItem parseCaseItems [ ] = {
{ " en " , u " 0,000 " , FALSE , FALSE , U_ZERO_ERROR , 5 , 0 , U_ZERO_ERROR , 5 , 0.0 , U_ZERO_ERROR , 5 , " 0 " } ,
{ " en " , u " 0,000 " , TRUE , FALSE , U_ZERO_ERROR , 5 , 0 , U_ZERO_ERROR , 5 , 0.0 , U_ZERO_ERROR , 5 , " 0 " } ,
{ " en " , u " 1000,000 " , FALSE , FALSE , U_PARSE_ERROR , 0 , 0 , U_PARSE_ERROR , 0 , 0.0 , U_PARSE_ERROR , 0 , " " } ,
{ " en " , u " 1000,000 " , TRUE , FALSE , U_ZERO_ERROR , 8 , 1000000 , U_ZERO_ERROR , 8 , 1000000.0 , U_ZERO_ERROR , 8 , " 1000000 " } ,
2019-02-06 05:45:03 +00:00
{ " en " , u " " , FALSE , FALSE , U_PARSE_ERROR , 0 , 0 , U_PARSE_ERROR , 0 , 0.0 , U_PARSE_ERROR , 0 , " " } ,
{ " en " , u " " , TRUE , FALSE , U_PARSE_ERROR , 0 , 0 , U_PARSE_ERROR , 0 , 0.0 , U_PARSE_ERROR , 0 , " " } ,
2019-02-05 19:34:29 +00:00
{ " en " , u " 9999990000503021 " , FALSE , FALSE , U_INVALID_FORMAT_ERROR , 16 , 2147483647 , U_ZERO_ERROR , 16 , 9999990000503020.0 , U_ZERO_ERROR , 16 , " 9999990000503021 " } ,
{ " en " , u " 9999990000503021 " , FALSE , TRUE , U_INVALID_FORMAT_ERROR , 16 , 2147483647 , U_ZERO_ERROR , 16 , 9999990000503020.0 , U_ZERO_ERROR , 16 , " 9999990000503021 " } ,
{ " en " , u " 1000000.5 " , FALSE , FALSE , U_ZERO_ERROR , 9 , 1000000 , U_ZERO_ERROR , 9 , 1000000.5 , U_ZERO_ERROR , 9 , " 1.0000005E+6 " } ,
{ " en " , u " 1000000.5 " , FALSE , TRUE , U_ZERO_ERROR , 7 , 1000000 , U_ZERO_ERROR , 7 , 1000000.0 , U_ZERO_ERROR , 7 , " 1000000 " } ,
{ " en " , u " 123.5 " , FALSE , FALSE , U_ZERO_ERROR , 5 , 123 , U_ZERO_ERROR , 5 , 123.5 , U_ZERO_ERROR , 5 , " 123.5 " } ,
{ " en " , u " 123.5 " , FALSE , TRUE , U_ZERO_ERROR , 3 , 123 , U_ZERO_ERROR , 3 , 123.0 , U_ZERO_ERROR , 3 , " 123 " } ,
{ NULL , NULL , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0.0 , 0 , 0 , NULL }
} ;
static void TestParseCases ( void ) {
const ParseCaseItem * itemPtr ;
for ( itemPtr = parseCaseItems ; itemPtr - > locale ! = NULL ; itemPtr + + ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unumDec = unum_open ( UNUM_DECIMAL , NULL , 0 , itemPtr - > locale , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " unum_open UNUM_DECIMAL fails for locale %s: %s \n " , itemPtr - > locale , u_errorName ( status ) ) ;
continue ;
}
int32_t intValue , parsePos , dclen ;
double doubValue ;
char decstr [ 32 ] ;
unum_setAttribute ( unumDec , UNUM_LENIENT_PARSE , itemPtr - > lenient ) ;
unum_setAttribute ( unumDec , UNUM_PARSE_INT_ONLY , itemPtr - > intOnly ) ;
parsePos = 0 ;
status = U_ZERO_ERROR ;
intValue = unum_parse ( unumDec , itemPtr - > text , - 1 , & parsePos , & status ) ;
if ( status ! = itemPtr - > intStatus | | parsePos ! = itemPtr - > intPos | | intValue ! = itemPtr - > intValue ) {
char btext [ 32 ] ;
u_austrcpy ( btext , itemPtr - > text ) ;
log_err ( " locale %s, text \" %s \" , lenient %d, intOnly %d; \n parse expected status %s, pos %d, value %d; \n got %s, %d, %d \n " ,
itemPtr - > locale , btext , itemPtr - > lenient , itemPtr - > intOnly ,
u_errorName ( itemPtr - > intStatus ) , itemPtr - > intPos , itemPtr - > intValue ,
u_errorName ( status ) , parsePos , intValue ) ;
}
parsePos = 0 ;
status = U_ZERO_ERROR ;
doubValue = unum_parseDouble ( unumDec , itemPtr - > text , - 1 , & parsePos , & status ) ;
if ( status ! = itemPtr - > doubStatus | | parsePos ! = itemPtr - > doubPos | | doubValue ! = itemPtr - > doubValue ) {
char btext [ 32 ] ;
u_austrcpy ( btext , itemPtr - > text ) ;
log_err ( " locale %s, text \" %s \" , lenient %d, intOnly %d; \n parseDouble expected status %s, pos %d, value %.1f; \n got %s, %d, %.1f \n " ,
itemPtr - > locale , btext , itemPtr - > lenient , itemPtr - > intOnly ,
u_errorName ( itemPtr - > doubStatus ) , itemPtr - > doubPos , itemPtr - > doubValue ,
u_errorName ( status ) , parsePos , doubValue ) ;
}
parsePos = 0 ;
status = U_ZERO_ERROR ;
decstr [ 0 ] = 0 ;
dclen = unum_parseDecimal ( unumDec , itemPtr - > text , - 1 , & parsePos , decstr , 32 , & status ) ;
2019-06-20 18:51:27 +00:00
( void ) dclen ;
2019-02-05 19:34:29 +00:00
if ( status ! = itemPtr - > decStatus | | parsePos ! = itemPtr - > decPos | | uprv_strcmp ( decstr , itemPtr - > decString ) ! = 0 ) {
char btext [ 32 ] ;
u_austrcpy ( btext , itemPtr - > text ) ;
log_err ( " locale %s, text \" %s \" , lenient %d, intOnly %d; \n parseDecimal expected status %s, pos %d, str \" %s \" ; \n got %s, %d, \" %s \" \n " ,
itemPtr - > locale , btext , itemPtr - > lenient , itemPtr - > intOnly ,
u_errorName ( itemPtr - > decStatus ) , itemPtr - > decPos , itemPtr - > decString ,
u_errorName ( status ) , parsePos , decstr ) ;
}
2019-02-05 21:32:52 +00:00
unum_close ( unumDec ) ;
2019-02-05 19:34:29 +00:00
}
}
2019-02-14 08:59:47 +00:00
typedef struct {
const char * descrip ;
const char * locale ;
UNumberFormatStyle style ;
int32_t minInt ;
int32_t minFrac ;
int32_t maxFrac ;
double roundIncr ;
const UChar * expPattern ;
double valueToFmt ;
const UChar * expFormat ;
} SetMaxFracAndRoundIncrItem ;
static const SetMaxFracAndRoundIncrItem maxFracAndRoundIncrItems [ ] = {
// descrip locale style mnI mnF mxF rdInc expPat value expFmt
{ " 01 en_US DEC 1/0/3/0.0 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 3 , 0.0 , u " #,##0.### " , 0.128 , u " 0.128 " } ,
{ " 02 en_US DEC 1/0/1/0.0 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 1 , 0.0 , u " #,##0.# " , 0.128 , u " 0.1 " } ,
{ " 03 en_US DEC 1/0/1/0.01 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 1 , 0.01 , u " #,##0.# " , 0.128 , u " 0.1 " } ,
{ " 04 en_US DEC 1/1/1/0.01 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 1 , 0.01 , u " #,##0.0 " , 0.128 , u " 0.1 " } ,
{ " 05 en_US DEC 1/0/1/0.1 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 1 , 0.1 , u " #,##0.1 " , 0.128 , u " 0.1 " } , // use incr
{ " 06 en_US DEC 1/1/1/0.1 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 1 , 0.1 , u " #,##0.1 " , 0.128 , u " 0.1 " } , // use incr
{ " 10 en_US DEC 1/0/1/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 1 , 0.02 , u " #,##0.# " , 0.128 , u " 0.1 " } ,
{ " 11 en_US DEC 1/0/2/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 2 , 0.02 , u " #,##0.02 " , 0.128 , u " 0.12 " } , // use incr
{ " 12 en_US DEC 1/0/3/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 0 , 3 , 0.02 , u " #,##0.02# " , 0.128 , u " 0.12 " } , // use incr
{ " 13 en_US DEC 1/1/1/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 1 , 0.02 , u " #,##0.0 " , 0.128 , u " 0.1 " } ,
{ " 14 en_US DEC 1/1/2/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 2 , 0.02 , u " #,##0.02 " , 0.128 , u " 0.12 " } , // use incr
{ " 15 en_US DEC 1/1/3/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 3 , 0.02 , u " #,##0.02# " , 0.128 , u " 0.12 " } , // use incr
{ " 16 en_US DEC 1/2/2/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 2 , 2 , 0.02 , u " #,##0.02 " , 0.128 , u " 0.12 " } , // use incr
{ " 17 en_US DEC 1/2/3/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 2 , 3 , 0.02 , u " #,##0.02# " , 0.128 , u " 0.12 " } , // use incr
{ " 18 en_US DEC 1/3/3/0.02 " , " en_US " , UNUM_DECIMAL , 1 , 3 , 3 , 0.02 , u " #,##0.020 " , 0.128 , u " 0.120 " } , // use incr
{ " 20 en_US DEC 1/1/1/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 1 , 0.0075 , u " #,##0.0 " , 0.019 , u " 0.0 " } ,
{ " 21 en_US DEC 1/1/2/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 2 , 0.0075 , u " #,##0.0075 " , 0.004 , u " 0.0075 " } , // use incr
{ " 22 en_US DEC 1/1/2/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 2 , 0.0075 , u " #,##0.0075 " , 0.019 , u " 0.0225 " } , // use incr
{ " 23 en_US DEC 1/1/3/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 3 , 0.0075 , u " #,##0.0075 " , 0.004 , u " 0.0075 " } , // use incr
{ " 24 en_US DEC 1/1/3/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 1 , 3 , 0.0075 , u " #,##0.0075 " , 0.019 , u " 0.0225 " } , // use incr
{ " 25 en_US DEC 1/2/2/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 2 , 2 , 0.0075 , u " #,##0.0075 " , 0.004 , u " 0.0075 " } , // use incr
{ " 26 en_US DEC 1/2/2/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 2 , 2 , 0.0075 , u " #,##0.0075 " , 0.019 , u " 0.0225 " } , // use incr
{ " 27 en_US DEC 1/2/3/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 2 , 3 , 0.0075 , u " #,##0.0075 " , 0.004 , u " 0.0075 " } , // use incr
{ " 28 en_US DEC 1/2/3/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 2 , 3 , 0.0075 , u " #,##0.0075 " , 0.019 , u " 0.0225 " } , // use incr
{ " 29 en_US DEC 1/3/3/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 3 , 3 , 0.0075 , u " #,##0.0075 " , 0.004 , u " 0.0075 " } , // use incr
{ " 2A en_US DEC 1/3/3/0.0075 " , " en_US " , UNUM_DECIMAL , 1 , 3 , 3 , 0.0075 , u " #,##0.0075 " , 0.019 , u " 0.0225 " } , // use incr
{ NULL , NULL , UNUM_IGNORE , 0 , 0 , 0 , 0.0 , NULL , 0.0 , NULL }
} ;
// The following is copied from C++ number_patternstring.cpp for this C test.
//
// Determine whether a given roundingIncrement should be ignored for formatting
// based on the current maxFrac value (maximum fraction digits). For example a
// roundingIncrement of 0.01 should be ignored if maxFrac is 1, but not if maxFrac
// is 2 or more. Note that roundingIncrements are rounded in significance, so
// a roundingIncrement of 0.006 is treated like 0.01 for this determination, i.e.
// it should not be ignored if maxFrac is 2 or more (but a roundingIncrement of
// 0.005 is treated like 0.001 for significance). This is the reason for the
// initial doubling below.
// roundIncr must be non-zero
static UBool ignoreRoundingIncrement ( double roundIncr , int32_t maxFrac ) {
if ( maxFrac < 0 ) {
return FALSE ;
}
int32_t frac = 0 ;
roundIncr * = 2.0 ;
for ( frac = 0 ; frac < = maxFrac & & roundIncr < = 1.0 ; frac + + , roundIncr * = 10.0 ) ;
return ( frac > maxFrac ) ;
}
enum { kBBufMax = 128 } ;
static void TestSetMaxFracAndRoundIncr ( void ) {
const SetMaxFracAndRoundIncrItem * itemPtr ;
for ( itemPtr = maxFracAndRoundIncrItems ; itemPtr - > descrip ! = NULL ; itemPtr + + ) {
UChar ubuf [ kUBufMax ] ;
char bbufe [ kBBufMax ] ;
char bbufg [ kBBufMax ] ;
int32_t ulen ;
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unf = unum_open ( itemPtr - > style , NULL , 0 , itemPtr - > locale , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " locale %s: unum_open style %d fails with %s \n " , itemPtr - > locale , itemPtr - > style , u_errorName ( status ) ) ;
continue ;
}
unum_setAttribute ( unf , UNUM_MIN_INTEGER_DIGITS , itemPtr - > minInt ) ;
unum_setAttribute ( unf , UNUM_MIN_FRACTION_DIGITS , itemPtr - > minFrac ) ;
unum_setAttribute ( unf , UNUM_MAX_FRACTION_DIGITS , itemPtr - > maxFrac ) ;
unum_setDoubleAttribute ( unf , UNUM_ROUNDING_INCREMENT , itemPtr - > roundIncr ) ;
UBool roundIncrUsed = ( itemPtr - > roundIncr ! = 0.0 & & ! ignoreRoundingIncrement ( itemPtr - > roundIncr , itemPtr - > maxFrac ) ) ;
int32_t minInt = unum_getAttribute ( unf , UNUM_MIN_INTEGER_DIGITS ) ;
if ( minInt ! = itemPtr - > minInt ) {
log_err ( " test %s: unum_getAttribute UNUM_MIN_INTEGER_DIGITS, expected %d, got %d \n " ,
itemPtr - > descrip , itemPtr - > minInt , minInt ) ;
}
int32_t minFrac = unum_getAttribute ( unf , UNUM_MIN_FRACTION_DIGITS ) ;
if ( minFrac ! = itemPtr - > minFrac ) {
log_err ( " test %s: unum_getAttribute UNUM_MIN_FRACTION_DIGITS, expected %d, got %d \n " ,
itemPtr - > descrip , itemPtr - > minFrac , minFrac ) ;
}
// If incrementRounding is used, maxFrac is set equal to minFrac
int32_t maxFrac = unum_getAttribute ( unf , UNUM_MAX_FRACTION_DIGITS ) ;
// If incrementRounding is used, maxFrac is set equal to minFrac
int32_t expMaxFrac = ( roundIncrUsed ) ? itemPtr - > minFrac : itemPtr - > maxFrac ;
if ( maxFrac ! = expMaxFrac ) {
log_err ( " test %s: unum_getAttribute UNUM_MAX_FRACTION_DIGITS, expected %d, got %d \n " ,
itemPtr - > descrip , expMaxFrac , maxFrac ) ;
}
double roundIncr = unum_getDoubleAttribute ( unf , UNUM_ROUNDING_INCREMENT ) ;
// If incrementRounding is not used, roundIncr is set to 0.0
double expRoundIncr = ( roundIncrUsed ) ? itemPtr - > roundIncr : 0.0 ;
if ( roundIncr ! = expRoundIncr ) {
log_err ( " test %s: unum_getDoubleAttribute UNUM_ROUNDING_INCREMENT, expected %f, got %f \n " ,
itemPtr - > descrip , expRoundIncr , roundIncr ) ;
}
status = U_ZERO_ERROR ;
ulen = unum_toPattern ( unf , FALSE , ubuf , kUBufMax , & status ) ;
2019-06-20 18:51:27 +00:00
( void ) ulen ;
2019-02-14 08:59:47 +00:00
if ( U_FAILURE ( status ) ) {
log_err ( " test %s: unum_toPattern fails with %s \n " , itemPtr - > descrip , u_errorName ( status ) ) ;
} else if ( u_strcmp ( ubuf , itemPtr - > expPattern ) ! = 0 ) {
u_austrcpy ( bbufe , itemPtr - > expPattern ) ;
u_austrcpy ( bbufg , ubuf ) ;
log_err ( " test %s: unum_toPattern expect \" %s \" , get \" %s \" \n " , itemPtr - > descrip , bbufe , bbufg ) ;
}
status = U_ZERO_ERROR ;
ulen = unum_formatDouble ( unf , itemPtr - > valueToFmt , ubuf , kUBufMax , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " test %s: unum_formatDouble fails with %s \n " , itemPtr - > descrip , u_errorName ( status ) ) ;
} else if ( u_strcmp ( ubuf , itemPtr - > expFormat ) ! = 0 ) {
u_austrcpy ( bbufe , itemPtr - > expFormat ) ;
u_austrcpy ( bbufg , ubuf ) ;
log_err ( " test %s: unum_formatDouble expect \" %s \" , get \" %s \" \n " , itemPtr - > descrip , bbufe , bbufg ) ;
}
unum_close ( unf ) ;
}
}
2019-03-12 19:08:26 +00:00
static void TestIgnorePadding ( void ) {
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unum = unum_open ( UNUM_PATTERN_DECIMAL , NULL , 0 , " en_US " , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " unum_open UNUM_PATTERN_DECIMAL for en_US and NULL pattern fails:%s \n " , u_errorName ( status ) ) ;
} else {
unum_setAttribute ( unum , UNUM_GROUPING_USED , 0 ) ;
unum_setAttribute ( unum , UNUM_FORMAT_WIDTH , 0 ) ;
unum_setTextAttribute ( unum , UNUM_PADDING_CHARACTER , u " * " , 1 , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_setTextAttribute UNUM_PADDING_CHARACTER to '*' fails: %s \n " , u_errorName ( status ) ) ;
} else {
unum_setAttribute ( unum , UNUM_PADDING_POSITION , 0 ) ;
unum_setAttribute ( unum , UNUM_MIN_INTEGER_DIGITS , 0 ) ;
unum_setAttribute ( unum , UNUM_MAX_INTEGER_DIGITS , 8 ) ;
unum_setAttribute ( unum , UNUM_MIN_FRACTION_DIGITS , 0 ) ;
unum_setAttribute ( unum , UNUM_MAX_FRACTION_DIGITS , 0 ) ;
UChar ubuf [ kUBufMax ] ;
int32_t ulen = unum_toPattern ( unum , FALSE , ubuf , kUBufMax , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_toPattern fails: %s \n " , u_errorName ( status ) ) ;
} else {
char bbuf [ kBBufMax ] ;
if ( ulen > 0 & & ubuf [ 0 ] = = u ' * ' ) {
ubuf [ kUBufMax - 1 ] = 0 ; // ensure zero termination
u_austrncpy ( bbuf , ubuf , kBBufMax ) ;
log_err ( " unum_toPattern result should ignore padding but get %s \n " , bbuf ) ;
}
unum_applyPattern ( unum , FALSE , ubuf , ulen , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_applyPattern fails: %s \n " , u_errorName ( status ) ) ;
} else {
ulen = unum_formatDecimal ( unum , " 24 " , - 1 , ubuf , kUBufMax , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_formatDecimal fails: %s \n " , u_errorName ( status ) ) ;
} else if ( u_strcmp ( ubuf , u " 24 " ) ! = 0 ) {
ubuf [ kUBufMax - 1 ] = 0 ; // ensure zero termination
u_austrncpy ( bbuf , ubuf , kBBufMax ) ;
log_err ( " unum_formatDecimal result expect 24 but get %s \n " , bbuf ) ;
}
}
}
}
unum_close ( unum ) ;
}
}
2019-08-28 06:19:19 +00:00
static void TestSciNotationMaxFracCap ( void ) {
static const UChar * pat1 = u " #.##E+00;-#.##E+00 " ;
UErrorCode status = U_ZERO_ERROR ;
UNumberFormat * unum = unum_open ( UNUM_PATTERN_DECIMAL , pat1 , - 1 , " en_US " , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_data_err ( " unum_open UNUM_PATTERN_DECIMAL with scientific pattern for \" en_US \" fails with %s \n " , u_errorName ( status ) ) ;
} else {
double value ;
UChar ubuf [ kUBufMax ] ;
char bbuf [ kBBufMax ] ;
int32_t ulen ;
unum_setAttribute ( unum , UNUM_MIN_FRACTION_DIGITS , 0 ) ;
unum_setAttribute ( unum , UNUM_MAX_FRACTION_DIGITS , 2147483647 ) ;
ulen = unum_toPattern ( unum , FALSE , ubuf , kUBufMax , & status ) ;
if ( U_SUCCESS ( status ) ) {
u_austrncpy ( bbuf , ubuf , kUBufMax ) ;
log_info ( " unum_toPattern (%d): %s \n " , ulen , bbuf ) ;
}
for ( value = 10.0 ; value < 1000000000.0 ; value * = 10.0 ) {
status = U_ZERO_ERROR ;
ulen = unum_formatDouble ( unum , value , ubuf , kUBufMax , NULL , & status ) ;
if ( U_FAILURE ( status ) ) {
log_err ( " unum_formatDouble value %.1f status %s \n " , value , u_errorName ( status ) ) ;
} else if ( u_strncmp ( ubuf , u " 1E+0 " , 4 ) ! = 0 ) {
u_austrncpy ( bbuf , ubuf , kUBufMax ) ;
log_err ( " unum_formatDouble value %.1f expected result to begin with 1E+0, got %s \n " , value , bbuf ) ;
}
}
unum_close ( unum ) ;
}
}
2002-09-20 17:54:45 +00:00
# endif /* #if !UCONFIG_NO_FORMATTING */