From 2fa49ba63501304babdf477ad5d470c83302cb07 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Thu, 27 Jun 2013 19:49:55 +0000 Subject: [PATCH] ICU-7912 add unum_parse and unum_format taking UFormattable (@internal, API proposal to follow) X-SVN-Rev: 33862 --- icu4c/source/i18n/unicode/uformattable.h | 3 +- icu4c/source/i18n/unicode/unum.h | 31 +++++++++ icu4c/source/i18n/unum.cpp | 52 +++++++++++++- icu4c/source/test/cintltst/cnumtst.c | 88 ++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 2 deletions(-) diff --git a/icu4c/source/i18n/unicode/uformattable.h b/icu4c/source/i18n/unicode/uformattable.h index 9107ec4465e..5027057b499 100644 --- a/icu4c/source/i18n/unicode/uformattable.h +++ b/icu4c/source/i18n/unicode/uformattable.h @@ -101,6 +101,7 @@ U_NAMESPACE_END #endif +#ifndef U_HIDE_INTERNAL_API /** * Return the type of this object * @param fmt the UFormattable object @@ -120,7 +121,7 @@ ufmt_getType(UFormattable* fmt, UErrorCode *status); */ U_INTERNAL UBool U_EXPORT2 ufmt_isNumeric(UFormattable* fmt); - +#endif /** * Get the value as a date, converting if need be. diff --git a/icu4c/source/i18n/unicode/unum.h b/icu4c/source/i18n/unicode/unum.h index a9a32d442e1..a3e4c578456 100644 --- a/icu4c/source/i18n/unicode/unum.h +++ b/icu4c/source/i18n/unicode/unum.h @@ -20,6 +20,8 @@ #include "unicode/uloc.h" #include "unicode/umisc.h" #include "unicode/parseerr.h" +#include "unicode/uformattable.h" + /** * \file * \brief C API: NumberFormat @@ -559,6 +561,20 @@ unum_formatDoubleCurrency(const UNumberFormat* fmt, UFieldPosition* pos, /* ignored if 0 */ UErrorCode* status); +#ifndef U_HIDE_INTERNAL_API +/** + * Format a UFormattable into a string + * @internal + */ +U_INTERNAL int32_t U_EXPORT2 +unum_formatUFormattable(const UNumberFormat* fmt, + UFormattable *number, + UChar *result, + int32_t resultLength, + UFieldPosition *pos, /* ignored if 0 */ + UErrorCode *status); +#endif + /** * Parse a string into an integer using a UNumberFormat. * The string will be parsed according to the UNumberFormat's locale. @@ -693,6 +709,21 @@ unum_parseDoubleCurrency(const UNumberFormat* fmt, UChar* currency, UErrorCode* status); +#ifndef U_HIDE_INTERNAL_API +/** + * Parse into a UFormattable. + * @param result - result formattable. Will be allocated with ufmt_open() first if NULL is passed in. + * @internal + */ +U_INTERNAL UFormattable* U_EXPORT2 +unum_parseToUFormattable(const UNumberFormat* fmt, + UFormattable *result, + const UChar* text, + int32_t textLength, + int32_t* parsePos, /* 0 = start */ + UErrorCode* status); +#endif + /** * Set the pattern used by a UNumberFormat. This can only be used * on a DecimalFormat, other formats return U_UNSUPPORTED_ERROR diff --git a/icu4c/source/i18n/unum.cpp b/icu4c/source/i18n/unum.cpp index 61d8e46ccf2..079a6b9b05c 100644 --- a/icu4c/source/i18n/unum.cpp +++ b/icu4c/source/i18n/unum.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 1996-2012, International Business Machines +* Copyright (C) 1996-2013, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* * Modification History: @@ -783,4 +783,54 @@ unum_getLocaleByType(const UNumberFormat *fmt, return ((const Format*)fmt)->getLocaleID(type, *status); } +U_INTERNAL UFormattable * U_EXPORT2 +unum_parseToUFormattable(const UNumberFormat* fmt, + UFormattable *result, + const UChar* text, + int32_t textLength, + int32_t* parsePos, /* 0 = start */ + UErrorCode* status) { + if(result == NULL) { // allocate if not allocated. + result = ufmt_open(status); // does an error check + } + if(U_FAILURE(*status)) return result; + + parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); + + return result; +} + +U_INTERNAL int32_t U_EXPORT2 +unum_formatUFormattable(const UNumberFormat* fmt, + UFormattable *number, + UChar *result, + int32_t resultLength, + UFieldPosition *pos, /* ignored if 0 */ + UErrorCode *status) { + // cribbed from unum_formatInt64 + if(U_FAILURE(*status)) + return -1; + + UnicodeString res; + if(!(result==NULL && resultLength==0)) { + // NULL destination for pure preflighting: empty dummy string + // otherwise, alias the destination buffer + res.setTo(result, 0, resultLength); + } + + FieldPosition fp; + + if(pos != 0) + fp.setField(pos->field); + + ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); + + if(pos != 0) { + pos->beginIndex = fp.getBeginIndex(); + pos->endIndex = fp.getEndIndex(); + } + + return res.extract(result, resultLength, *status); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/cintltst/cnumtst.c b/icu4c/source/test/cintltst/cnumtst.c index 3bc0005406c..6c5b368747b 100644 --- a/icu4c/source/test/cintltst/cnumtst.c +++ b/icu4c/source/test/cintltst/cnumtst.c @@ -51,6 +51,7 @@ static void TestInt64Parse(void); static void TestParseCurrency(void); static void TestMaxInt(void); static void TestNoExponent(void); +static void TestUFormattable(void); #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x) @@ -73,6 +74,7 @@ void addNumForTest(TestNode** root) TESTCASE(TestCloneWithRBNF); TESTCASE(TestMaxInt); TESTCASE(TestNoExponent); + TESTCASE(TestUFormattable); } /* test Parse int 64 */ @@ -2173,4 +2175,90 @@ static void TestMaxInt(void) { unum_close(fmt); } +static void TestUFormattable(void) { + UChar buf2k[2048]; + UChar out2k[2048]; + // test with explicitly created ufmt_open + { + UErrorCode status = U_ZERO_ERROR; + UFormattable *f; + UNumberFormat *unum; + const char *pattern = ""; + + f = ufmt_open(&status); + unum = unum_open(UNUM_DEFAULT, NULL, -1, "en_US_POSIX", NULL, &status); + if(assertSuccess("calling ufmt_open()", &status)) { + + pattern = "31337"; + log_verbose("-- pattern: %s\n", pattern); + u_uastrcpy(buf2k, pattern); + unum_parseToUFormattable(unum, f, buf2k, -1, NULL, &status); + if(assertSuccess("unum_parseToUFormattable[31337]", &status)) { + assertTrue("ufmt_getLong()=31337", ufmt_getLong(f, &status) == 31337); + assertTrue("ufmt_getType()=UFMT_LONG", ufmt_getType(f, &status) == UFMT_LONG); + log_verbose("long = %d\n", ufmt_getLong(f, &status)); + assertSuccess("ufmt_getLong()", &status); + } + unum_formatUFormattable(unum, f, out2k, 2048, NULL, &status); + if(assertSuccess("unum_formatUFormattable(31337)", &status)) { + assertEquals("unum_formatUFormattable r/t", austrdup(buf2k), austrdup(out2k)); + } + + pattern = "3.14159"; + log_verbose("-- pattern: %s\n", pattern); + u_uastrcpy(buf2k, pattern); + unum_parseToUFormattable(unum, f, buf2k, -1, NULL, &status); + if(assertSuccess("unum_parseToUFormattable[3.14159]", &status)) { + assertTrue("ufmt_getDouble()=3.14159", ufmt_getDouble(f, &status) == 3.14159); + assertTrue("ufmt_getType()=UFMT_DOUBLE", ufmt_getType(f, &status) == UFMT_DOUBLE); + log_verbose("double = %g\n", ufmt_getDouble(f, &status)); + assertSuccess("ufmt_getDouble()", &status); + } + unum_formatUFormattable(unum, f, out2k, 2048, NULL, &status); + if(assertSuccess("unum_formatUFormattable(3.14159)", &status)) { + assertEquals("unum_formatUFormattable r/t", austrdup(buf2k), austrdup(out2k)); + } + } + ufmt_close(f); + unum_close(unum); + } + + // test with auto-generated ufmt + { + UErrorCode status = U_ZERO_ERROR; + UFormattable *f = NULL; + UNumberFormat *unum; + const char *pattern = "73476730924573500000000"; // weight of the moon, kg + + log_verbose("-- pattern: %s (testing auto-opened UFormattable)\n", pattern); + u_uastrcpy(buf2k, pattern); + + unum = unum_open(UNUM_DEFAULT, NULL, -1, "en_US_POSIX", NULL, &status); + if(assertSuccess("calling ufmt_open()", &status)) { + + f = unum_parseToUFormattable(unum, NULL, /* will be unum_open()'ed for us */ + buf2k, -1, NULL, &status); + if(assertSuccess("unum_parseToUFormattable(weight of the moon", &status)) { + log_verbose("new formattable allocated at %p\n", (void*)f); + assertTrue("ufmt_isNumeric() TRUE", ufmt_isNumeric(f)); + unum_formatUFormattable(unum, f, out2k, 2048, NULL, &status); + if(assertSuccess("unum_formatUFormattable(3.14159)", &status)) { + assertEquals("unum_formatUFormattable r/t", austrdup(buf2k), austrdup(out2k)); + } + + log_verbose("double: %g\n", ufmt_getDouble(f, &status)); + assertSuccess("ufmt_getDouble()", &status); + + log_verbose("long: %ld\n", ufmt_getLong(f, &status)); + 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); + ufmt_close(f); // was implicitly opened for us by the first unum_parseToUFormattable() + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ -- 2.40.0