]> granicus.if.org Git - icu/commitdiff
ICU-7912 add unum_parse and unum_format taking UFormattable (@internal, API proposal...
authorSteven R. Loomis <srl@icu-project.org>
Thu, 27 Jun 2013 19:49:55 +0000 (19:49 +0000)
committerSteven R. Loomis <srl@icu-project.org>
Thu, 27 Jun 2013 19:49:55 +0000 (19:49 +0000)
X-SVN-Rev: 33862

icu4c/source/i18n/unicode/uformattable.h
icu4c/source/i18n/unicode/unum.h
icu4c/source/i18n/unum.cpp
icu4c/source/test/cintltst/cnumtst.c

index 9107ec4465ef2a53f8f0de24853d40e3e6fda957..5027057b4990e6c82b3cf230993c267a598e0d18 100644 (file)
@@ -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.
index a9a32d442e136ba184751cc09f5f3c84a6c0e602..a3e4c578456619bc81f65a64977944c20205fbce 100644 (file)
@@ -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
index 61d8e46ccf239d938a58e07b61e0f2933caaef24..079a6b9b05c878bef1731b84154c7d1c494016f2 100644 (file)
@@ -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 */
index 3bc0005406c8381c04c7069f0c74661f738add53..6c5b368747b4a876aeb87e8f4892af19a13d81e1 100644 (file)
@@ -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 */