]> granicus.if.org Git - icu/commitdiff
ICU-13645 Add C++11 move constructor and assign operator to Locale.
authorFredrik Roubert <fredrik@roubert.name>
Sat, 15 Sep 2018 03:07:58 +0000 (20:07 -0700)
committerShane Carr <shane@unicode.org>
Thu, 27 Sep 2018 21:27:39 +0000 (14:27 -0700)
icu4c/source/common/locid.cpp
icu4c/source/common/unicode/locid.h
icu4c/source/test/intltest/loctest.cpp
icu4c/source/test/intltest/loctest.h

index 3d9eacedac7e956e6d1f42b130791906931f5f3f..d83c91582203af8790fa82830de520d49e4972bd 100644 (file)
@@ -31,6 +31,7 @@
 ******************************************************************************
 */
 
+#include <utility>
 
 #include "unicode/bytestream.h"
 #include "unicode/locid.h"
@@ -427,6 +428,11 @@ Locale::Locale(const Locale &other)
     *this = other;
 }
 
+Locale::Locale(Locale&& other) U_NOEXCEPT
+    : UObject(other), fullName(fullNameBuffer), baseName(fullName) {
+  *this = std::move(other);
+}
+
 Locale& Locale::operator=(const Locale& other) {
     if (this == &other) {
         return *this;
@@ -460,6 +466,35 @@ Locale& Locale::operator=(const Locale& other) {
     return *this;
 }
 
+Locale& Locale::operator=(Locale&& other) U_NOEXCEPT {
+    if (baseName != fullName) uprv_free(baseName);
+    if (fullName != fullNameBuffer) uprv_free(fullName);
+
+    if (other.fullName == other.fullNameBuffer) {
+        uprv_strcpy(fullNameBuffer, other.fullNameBuffer);
+        fullName = fullNameBuffer;
+    } else {
+        fullName = other.fullName;
+    }
+
+    if (other.baseName == other.fullName) {
+        baseName = fullName;
+    } else {
+        baseName = other.baseName;
+    }
+
+    uprv_strcpy(language, other.language);
+    uprv_strcpy(script, other.script);
+    uprv_strcpy(country, other.country);
+
+    variantBegin = other.variantBegin;
+    fIsBogus = other.fIsBogus;
+
+    other.baseName = other.fullName = other.fullNameBuffer;
+
+    return *this;
+}
+
 Locale *
 Locale::clone() const {
     return new Locale(*this);
index f1985667b8ac3db363be0d7a0136021b4dce0a1a..e582694326a37e0a24f3d4a4bbd2a41876adb46c 100644 (file)
@@ -284,6 +284,14 @@ public:
      */
     Locale(const    Locale& other);
 
+    /**
+     * Move constructor; might leave source in bogus state.
+     * This locale will have the same contents that the source locale had.
+     *
+     * @param other The Locale object being moved in.
+     * @draft ICU 63
+     */
+    Locale(Locale&& other) U_NOEXCEPT;
 
     /**
      * Destructor
@@ -300,6 +308,17 @@ public:
      */
     Locale& operator=(const Locale& other);
 
+    /**
+     * Move assignment operator; might leave source in bogus state.
+     * This locale will have the same contents that the source locale had.
+     * The behavior is undefined if *this and the source are the same object.
+     *
+     * @param other The Locale object being moved in.
+     * @return      *this
+     * @draft ICU 63
+     */
+    Locale& operator=(Locale&& other) U_NOEXCEPT;
+
     /**
      * Checks if two locale keys are the same.
      *
index 0ca3e40e48c1e8eb56ab0697267ba2e0e08c9370..d3fc4e286c09c19ab075a0d6f79b906be0b8662b 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <iterator>
 #include <set>
+#include <utility>
 
 #include "loctest.h"
 #include "unicode/localpointer.h"
@@ -249,6 +250,8 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c
     TESTCASE_AUTO(TestBug13554);
     TESTCASE_AUTO(TestForLanguageTag);
     TESTCASE_AUTO(TestToLanguageTag);
+    TESTCASE_AUTO(TestMoveAssign);
+    TESTCASE_AUTO(TestMoveCtor);
     TESTCASE_AUTO_END;
 }
 
@@ -3030,3 +3033,95 @@ void LocaleTest::TestToLanguageTag() {
     assertEquals("bogus", U_ILLEGAL_ARGUMENT_ERROR, status.reset());
     assertTrue(result_bogus.c_str(), result_bogus.empty());
 }
+
+void LocaleTest::TestMoveAssign() {
+    // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
+    Locale l1("de@collation=phonebook;x="
+              "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
+              "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
+              "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
+              "aaaaabbbbbzz");
+
+    Locale l2;
+    {
+        Locale l3(l1);
+        assertTrue("l1 == l3", l1 == l3);
+        l2 = std::move(l3);
+        assertTrue("l1 == l2", l1 == l2);
+        assertTrue("l2 != l3", l2.getName() != l3.getName());
+    }
+
+    // This should remain true also after l3 has been destructed.
+    assertTrue("l1 == l2, again", l1 == l2);
+
+    Locale l4("de@collation=phonebook");
+
+    Locale l5;
+    {
+        Locale l6(l4);
+        assertTrue("l4 == l6", l4 == l6);
+        l5 = std::move(l6);
+        assertTrue("l4 == l5", l4 == l5);
+        assertTrue("l5 != l6", l5.getName() != l6.getName());
+    }
+
+    // This should remain true also after l6 has been destructed.
+    assertTrue("l4 == l5, again", l4 == l5);
+
+    Locale l7("vo_Cyrl_AQ_EURO");
+
+    Locale l8;
+    {
+        Locale l9(l7);
+        assertTrue("l7 == l9", l7 == l9);
+        l8 = std::move(l9);
+        assertTrue("l7 == l8", l7 == l8);
+        assertTrue("l8 != l9", l8.getName() != l9.getName());
+    }
+
+    // This should remain true also after l9 has been destructed.
+    assertTrue("l7 == l8, again", l7 == l8);
+
+    assertEquals("language", l7.getLanguage(), l8.getLanguage());
+    assertEquals("script", l7.getScript(), l8.getScript());
+    assertEquals("country", l7.getCountry(), l8.getCountry());
+    assertEquals("variant", l7.getVariant(), l8.getVariant());
+    assertEquals("bogus", l7.isBogus(), l8.isBogus());
+}
+
+void LocaleTest::TestMoveCtor() {
+    // ULOC_FULLNAME_CAPACITY == 157 (uloc.h)
+    Locale l1("de@collation=phonebook;x="
+              "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
+              "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
+              "aaaaabbbbbcccccdddddeeeeefffffggggghhhhh"
+              "aaaaabbbbbzz");
+
+    Locale l3(l1);
+    assertTrue("l1 == l3", l1 == l3);
+    Locale l2(std::move(l3));
+    assertTrue("l1 == l2", l1 == l2);
+    assertTrue("l2 != l3", l2.getName() != l3.getName());
+
+    Locale l4("de@collation=phonebook");
+
+    Locale l6(l4);
+    assertTrue("l4 == l6", l4 == l6);
+    Locale l5(std::move(l6));
+    assertTrue("l4 == l5", l4 == l5);
+    assertTrue("l5 != l6", l5.getName() != l6.getName());
+
+    Locale l7("vo_Cyrl_AQ_EURO");
+
+    Locale l9(l7);
+    assertTrue("l7 == l9", l7 == l9);
+    Locale l8(std::move(l9));
+    assertTrue("l7 == l8", l7 == l8);
+    assertTrue("l8 != l9", l8.getName() != l9.getName());
+
+    assertEquals("language", l7.getLanguage(), l8.getLanguage());
+    assertEquals("script", l7.getScript(), l8.getScript());
+    assertEquals("country", l7.getCountry(), l8.getCountry());
+    assertEquals("variant", l7.getVariant(), l8.getVariant());
+    assertEquals("bogus", l7.isBogus(), l8.isBogus());
+}
index 8c8d7da2eb4ce923f1ca7c57c3e92b617d0b189e..d165cae8932c0b21d8940f5448534d76d1b74c9d 100644 (file)
@@ -121,6 +121,9 @@ public:
     void TestForLanguageTag();
     void TestToLanguageTag();
 
+    void TestMoveAssign();
+    void TestMoveCtor();
+
 private:
     void _checklocs(const char* label,
                     const char* req,