]> granicus.if.org Git - icu/commitdiff
ICU-13800 Adding clone() on [Un]LocalizedNumber[Range]Formatter.
authorShane Carr <shane@unicode.org>
Fri, 11 Jan 2019 21:47:33 +0000 (13:47 -0800)
committerShane F. Carr <shane@unicode.org>
Fri, 25 Jan 2019 23:29:21 +0000 (15:29 -0800)
- Returns a LocalPointer that can be converted to std::unique_ptr.

icu4c/source/i18n/number_fluent.cpp
icu4c/source/i18n/numrange_fluent.cpp
icu4c/source/i18n/unicode/numberformatter.h
icu4c/source/i18n/unicode/numberrangeformatter.h
icu4c/source/test/intltest/numbertest.h
icu4c/source/test/intltest/numbertest_api.cpp
icu4c/source/test/intltest/numbertest_range.cpp

index 37f780c4047115d80463ab9efe02e890f8be171e..5bc1f982fa6877ee5715c225056b905dff1356ad 100644 (file)
@@ -328,6 +328,16 @@ UnicodeString NumberFormatterSettings<Derived>::toSkeleton(UErrorCode& status) c
     return skeleton::generate(fMacros, status);
 }
 
+template<typename Derived>
+LocalPointer<Derived> NumberFormatterSettings<Derived>::clone() const & {
+    return LocalPointer<Derived>(new Derived(*this));
+}
+
+template<typename Derived>
+LocalPointer<Derived> NumberFormatterSettings<Derived>::clone() && {
+    return LocalPointer<Derived>(new Derived(std::move(*this)));
+}
+
 // Declare all classes that implement NumberFormatterSettings
 // See https://stackoverflow.com/a/495056/1407170
 template
index 27ffd0b6bc556fd6612c5c893a157b6ce399c672..10479f9d1060707713168b55a27202a1e44309cd 100644 (file)
@@ -162,6 +162,16 @@ Derived NumberRangeFormatterSettings<Derived>::identityFallback(UNumberRangeIden
     return move;
 }
 
+template<typename Derived>
+LocalPointer<Derived> NumberRangeFormatterSettings<Derived>::clone() const & {
+    return LocalPointer<Derived>(new Derived(*this));
+}
+
+template<typename Derived>
+LocalPointer<Derived> NumberRangeFormatterSettings<Derived>::clone() && {
+    return LocalPointer<Derived>(new Derived(std::move(*this)));
+}
+
 // Declare all classes that implement NumberRangeFormatterSettings
 // See https://stackoverflow.com/a/495056/1407170
 template
index 611fd7e7dc2956acfc1fe62bb7a6c0ef72cd117d..eb3e9f86c335e768bc3bba49ae49ce8269637dc3 100644 (file)
  *     .format(1234)
  *     .toString();  // €1.2K in en-US
  *
- * // Create a formatter in a singleton for use later:
+ * // Create a formatter in a singleton by value for use later:
  * static const LocalizedNumberFormatter formatter = NumberFormatter::withLocale(...)
  *     .unit(NoUnit::percent())
  *     .precision(Precision::fixedFraction(3));
  * formatter.format(5.9831).toString();  // 5.983% in en-US
  *
- * // Create a "template" in a singleton but without setting a locale until the call site:
- * static const UnlocalizedNumberFormatter template = NumberFormatter::with()
+ * // Create a "template" in a singleton unique_ptr but without setting a locale until the call site:
+ * std::unique_ptr<UnlocalizedNumberFormatter> template = NumberFormatter::with()
  *     .sign(UNumberSignDisplay::UNUM_SIGN_ALWAYS)
  *     .adoptUnit(MeasureUnit::createMeter(status))
- *     .unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME);
- * template.locale(...).format(1234).toString();  // +1,234 meters in en-US
+ *     .unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME)
+ *     .clone();
+ * template->locale(...).format(1234).toString();  // +1,234 meters in en-US
  * </pre>
  *
  * <p>
@@ -2078,6 +2079,28 @@ class U_I18N_API NumberFormatterSettings {
      */
     UnicodeString toSkeleton(UErrorCode& status) const;
 
+    /**
+     * Returns the current (Un)LocalizedNumberFormatter as a LocalPointer
+     * wrapping a heap-allocated copy of the current object.
+     *
+     * This is equivalent to new-ing the move constructor with a value object
+     * as the argument.
+     *
+     * @return A wrapped (Un)LocalizedNumberFormatter pointer, or a wrapped
+     *         nullptr on failure.
+     * @draft ICU 64
+     */
+    LocalPointer<Derived> clone() const &;
+
+    /**
+     * Overload of clone for use on an rvalue reference.
+     *
+     * @return A wrapped (Un)LocalizedNumberFormatter pointer, or a wrapped
+     *         nullptr on failure.
+     * @draft ICU 64
+     */
+    LocalPointer<Derived> clone() &&;
+
     /**
      * Sets the UErrorCode if an error occurred in the fluent chain.
      * Preserves older error codes in the outErrorCode.
index dee75c6729ffdf5774ab429a717f3f8d25902575..3cbf290edac01e50e125e0ac88cdb8b8138e4a4c 100644 (file)
@@ -445,6 +445,28 @@ class U_I18N_API NumberRangeFormatterSettings {
      */
     Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&;
 
+    /**
+     * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer
+     * wrapping a heap-allocated copy of the current object.
+     *
+     * This is equivalent to new-ing the move constructor with a value object
+     * as the argument.
+     *
+     * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
+     *         nullptr on failure.
+     * @draft ICU 64
+     */
+    LocalPointer<Derived> clone() const &;
+
+    /**
+     * Overload of clone for use on an rvalue reference.
+     *
+     * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
+     *         nullptr on failure.
+     * @draft ICU 64
+     */
+    LocalPointer<Derived> clone() &&;
+
     /**
      * Sets the UErrorCode if an error occurred in the fluent chain.
      * Preserves older error codes in the outErrorCode.
index 5750cecde69829d71dabf5dd457eb82be37740ae..9efc12da68e6a69e25917b15b1d42c11d45bfa7a 100644 (file)
@@ -78,6 +78,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
     void validRanges();
     void copyMove();
     void localPointerCAPI();
+    void toObject();
 
     void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
 
@@ -270,6 +271,7 @@ class NumberRangeFormatterTest : public IntlTestWithFieldPosition {
     void testPlurals();
     void testFieldPositions();
     void testCopyMove();
+    void toObject();
 
     void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
 
index 26f13ca7e05a5e386d100f9a7db459ac0f1ac26d..bfa0ba23dbc12a025bf5350a9b727b6e2df096b4 100644 (file)
@@ -8,6 +8,7 @@
 #include "charstr.h"
 #include <cstdarg>
 #include <cmath>
+#include <memory>
 #include "unicode/unum.h"
 #include "unicode/numberformatter.h"
 #include "number_asformat.h"
@@ -91,6 +92,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
         TESTCASE_AUTO(validRanges);
         TESTCASE_AUTO(copyMove);
         TESTCASE_AUTO(localPointerCAPI);
+        TESTCASE_AUTO(toObject);
     TESTCASE_AUTO_END;
 }
 
@@ -2783,6 +2785,64 @@ void NumberFormatterApiTest::localPointerCAPI() {
     // No need to do any cleanup since we are using LocalPointer.
 }
 
+void NumberFormatterApiTest::toObject() {
+    IcuTestErrorCode status(*this, "toObject");
+
+    // const lvalue version
+    {
+        LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en")
+                .precision(Precision::fixedFraction(2));
+        LocalPointer<LocalizedNumberFormatter> lnf2(lnf.clone());
+        assertFalse("should create successfully, const lvalue", lnf2.isNull());
+        assertEquals("object API test, const lvalue", u"1,000.00",
+            lnf2->formatDouble(1000, status).toString(status));
+    }
+
+    // rvalue reference version
+    {
+        LocalPointer<LocalizedNumberFormatter> lnf(
+            NumberFormatter::withLocale("en")
+                .precision(Precision::fixedFraction(2))
+                .clone());
+        assertFalse("should create successfully, rvalue reference", lnf.isNull());
+        assertEquals("object API test, rvalue reference", u"1,000.00",
+            lnf->formatDouble(1000, status).toString(status));
+    }
+
+    // to std::unique_ptr via constructor
+    {
+        std::unique_ptr<LocalizedNumberFormatter> lnf(
+            NumberFormatter::withLocale("en")
+                .precision(Precision::fixedFraction(2))
+                .clone());
+        assertTrue("should create successfully, unique_ptr", static_cast<bool>(lnf));
+        assertEquals("object API test, unique_ptr", u"1,000.00",
+            lnf->formatDouble(1000, status).toString(status));
+    }
+
+    // to std::unique_ptr via assignment
+    {
+        std::unique_ptr<LocalizedNumberFormatter> lnf =
+            NumberFormatter::withLocale("en")
+                .precision(Precision::fixedFraction(2))
+                .clone();
+        assertTrue("should create successfully, unique_ptr B", static_cast<bool>(lnf));
+        assertEquals("object API test, unique_ptr B", u"1,000.00",
+            lnf->formatDouble(1000, status).toString(status));
+    }
+
+    // to LocalPointer via assignment
+    {
+        LocalPointer<UnlocalizedNumberFormatter> f =
+            NumberFormatter::with().clone();
+    }
+
+    // make sure no memory leaks
+    {
+        NumberFormatter::with().clone();
+    }
+}
+
 
 void NumberFormatterApiTest::assertFormatDescending(const char16_t* umessage, const char16_t* uskeleton,
                                                     const UnlocalizedNumberFormatter& f, Locale locale,
index a15ef9d9b6f6210e851fd524fbbfb02b8be22c8f..75816ba95731110732e88b9d84e422e1b9a70a7e 100644 (file)
@@ -50,6 +50,7 @@ void NumberRangeFormatterTest::runIndexedTest(int32_t index, UBool exec, const c
         TESTCASE_AUTO(testPlurals);
         TESTCASE_AUTO(testFieldPositions);
         TESTCASE_AUTO(testCopyMove);
+        TESTCASE_AUTO(toObject);
     TESTCASE_AUTO_END;
 }
 
@@ -823,6 +824,42 @@ void NumberRangeFormatterTest::testCopyMove() {
     assertEquals("FormattedNumberRange move assignment", u"3,00–6,00 $US", result.toString(status));
 }
 
+void NumberRangeFormatterTest::toObject() {
+    IcuTestErrorCode status(*this, "toObject");
+
+    // const lvalue version
+    {
+        LocalizedNumberRangeFormatter lnf = NumberRangeFormatter::withLocale("en");
+        LocalPointer<LocalizedNumberRangeFormatter> lnf2(lnf.clone());
+        assertFalse("should create successfully, const lvalue", lnf2.isNull());
+        assertEquals("object API test, const lvalue", u"5–7",
+            lnf2->formatFormattableRange(5, 7, status).toString(status));
+    }
+
+    // rvalue reference version
+    {
+        LocalPointer<LocalizedNumberRangeFormatter> lnf(
+            NumberRangeFormatter::withLocale("en").clone());
+        assertFalse("should create successfully, rvalue reference", lnf.isNull());
+        assertEquals("object API test, rvalue reference", u"5–7",
+            lnf->formatFormattableRange(5, 7, status).toString(status));
+    }
+
+    // to std::unique_ptr via assignment
+    {
+        std::unique_ptr<LocalizedNumberRangeFormatter> lnf =
+            NumberRangeFormatter::withLocale("en").clone();
+        assertTrue("should create successfully, unique_ptr B", static_cast<bool>(lnf));
+        assertEquals("object API test, unique_ptr B", u"5–7",
+            lnf->formatFormattableRange(5, 7, status).toString(status));
+    }
+
+    // make sure no memory leaks
+    {
+        NumberRangeFormatter::with().clone();
+    }
+}
+
 void  NumberRangeFormatterTest::assertFormatRange(
       const char16_t* message,
       const UnlocalizedNumberRangeFormatter& f,