From 7d4b54dfc359a834ae3ca06880d134e454c17b6d Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Tue, 27 Mar 2018 06:07:17 +0000 Subject: [PATCH] ICU-13597 Small API tweaks. X-SVN-Rev: 41160 --- icu4c/source/i18n/number_capi.cpp | 5 ++ icu4c/source/i18n/unicode/unumberformatter.h | 52 +++++++++++++++---- .../test/cintltst/unumberformattertst.c | 31 +++++++++++ 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/icu4c/source/i18n/number_capi.cpp b/icu4c/source/i18n/number_capi.cpp index 1dc2955faa9..7095fe0fd6f 100644 --- a/icu4c/source/i18n/number_capi.cpp +++ b/icu4c/source/i18n/number_capi.cpp @@ -150,6 +150,11 @@ unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t buf const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); if (U_FAILURE(*ec)) { return 0; } + if (buffer == nullptr) { + // Return the length without setting an error. + return result->string.length(); + } + return result->string.toUnicodeString().extract(buffer, bufferCapacity, *ec); } diff --git a/icu4c/source/i18n/unicode/unumberformatter.h b/icu4c/source/i18n/unicode/unumberformatter.h index 059cbb64916..d0bb64c05f7 100644 --- a/icu4c/source/i18n/unicode/unumberformatter.h +++ b/icu4c/source/i18n/unicode/unumberformatter.h @@ -17,6 +17,38 @@ * * This is the C-compatible version of the NumberFormatter API introduced in ICU 60. C++ users should * include unicode/numberformatter.h and use the proper C++ APIs. + * + * The C API accepts a number skeleton string for specifying the settings for formatting, which covers a + * very large subset of all possible number formatting features. For more information on number skeleton + * strings, see unicode/numberformatter.h. + * + * When using UNumberFormatter, which is treated as immutable, the results are exported to a mutable + * UFormattedNumber object, which you subsequently use for populating your string buffer or iterating over + * the fields. + * + * Example code: + *
+ * // Setup:
+ * UErrorCode ec = U_ZERO_ERROR;
+ * UNumberFormatter* uformatter = unumf_openFromSkeletonAndLocale(u"round-integer", -1, "en", &ec);
+ * UFormattedNumber* uresult = unumf_openResult(&ec);
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Format a double:
+ * unumf_formatDouble(uformatter, 5142.3, uresult, &ec);
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Export the string:
+ * int32_t len = unumf_resultToString(uresult, NULL, 0, &ec);
+ * UChar* buffer = (UChar*) malloc((len+1)*sizeof(UChar));
+ * unumf_resultToString(uresult, buffer, len+1, &ec);
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Cleanup:
+ * unumf_close(uformatter);
+ * unumf_closeResult(uresult);
+ * free(buffer);
+ * 
*/ @@ -355,7 +387,8 @@ typedef struct UFormattedNumber UFormattedNumber; /** - * Creates a new UNumberFormatter from the given skeleton string and locale. + * Creates a new UNumberFormatter from the given skeleton string and locale. This is currently the only + * method for creating a new UNumberFormatter. * * For more details on skeleton strings, see the documentation in numberformatter.h. For more details on * the usage of this API, see the documentation at the top of unumberformatter.h. @@ -381,7 +414,7 @@ unumf_openResult(UErrorCode* ec); /** - * Uses a UNumberFormatter to format a double to a UFormattedNumber. A string, field position, and other + * Uses a UNumberFormatter to format an integer to a UFormattedNumber. A string, field position, and other * information can be retrieved from the UFormattedNumber. * * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. @@ -423,19 +456,16 @@ unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32 /** - * Extracts the result number string out of a UFormattedNumber to a UChar buffer. The usual ICU pattern - * is used for writing to the buffer: + * Extracts the result number string out of a UFormattedNumber to a UChar buffer if possible. + * If bufferCapacity is greater than the required length, a terminating NUL is written. + * If bufferCapacity is less than the required length, an error code is set. * - * - If the string is shorter than the buffer, it will be written to the buffer and will be NUL-terminated. - * - If the string is exactly the length of the buffer, it will be written to the buffer, but it will not - * be NUL-terminated, and a warning will be set. - * - If the string is longer than the buffer, nothing will be written to the buffer, and an error will be - * set. - * - * In all cases, the actual length of the string is returned, whether or not it was written to the buffer. + * If NULL is passed as the buffer argument, the required length is returned without setting an error. * * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. * + * @return The required length. + * * @draft ICU 62 */ U_DRAFT int32_t U_EXPORT2 diff --git a/icu4c/source/test/cintltst/unumberformattertst.c b/icu4c/source/test/cintltst/unumberformattertst.c index e8ae8b50138..0e6aa54e19b 100644 --- a/icu4c/source/test/cintltst/unumberformattertst.c +++ b/icu4c/source/test/cintltst/unumberformattertst.c @@ -13,16 +13,20 @@ #include "unicode/umisc.h" #include "unicode/unum.h" #include "cintltst.h" +#include "cmemory.h" static void TestSkeletonFormatToString(); static void TestSkeletonFormatToFields(); +static void TestExampleCode(); + void addUNumberFormatterTest(TestNode** root); void addUNumberFormatterTest(TestNode** root) { addTest(root, &TestSkeletonFormatToString, "unumberformatter/TestSkeletonFormatToString"); addTest(root, &TestSkeletonFormatToFields, "unumberformatter/TestSkeletonFormatToFields"); + addTest(root, &TestExampleCode, "unumberformatter/TestExampleCode"); } @@ -130,4 +134,31 @@ static void TestSkeletonFormatToFields() { } +static void TestExampleCode() { + // This is the example code given in unumberformatter.h. + + // Setup: + UErrorCode ec = U_ZERO_ERROR; + UNumberFormatter* uformatter = unumf_openFromSkeletonAndLocale(u"round-integer", -1, "en", &ec); + UFormattedNumber* uresult = unumf_openResult(&ec); + assertSuccess("There should not be a failure in the example code", &ec); + + // Format a double: + unumf_formatDouble(uformatter, 5142.3, uresult, &ec); + assertSuccess("There should not be a failure in the example code", &ec); + + // Export the string: + int32_t len = unumf_resultToString(uresult, NULL, 0, &ec); + UChar* buffer = (UChar*) uprv_malloc((len+1)*sizeof(UChar)); + unumf_resultToString(uresult, buffer, len+1, &ec); + assertSuccess("There should not be a failure in the example code", &ec); + assertUEquals("Should produce expected string result", u"5,142", buffer); + + // Cleanup: + unumf_close(uformatter); + unumf_closeResult(uresult); + uprv_free(buffer); +} + + #endif /* #if !UCONFIG_NO_FORMATTING */ -- 2.40.0