From cc042b99d1c966a8b3e92ca9b7ffb3b497d0af98 Mon Sep 17 00:00:00 2001 From: Max Prokhorov Date: Sun, 27 Sep 2020 18:11:52 +0300 Subject: [PATCH] WString: c_str() returns null pointer after move (#7611) * (test) WString: c_str() returns null pointer target = std::move(source) does not reset buffer pointer back to the sso * wstring: correctly do move invalidation & copy based on the #7553 without isSSO -> isHeap rename and inline optimizations additionally, remove useless pre-c++11 preprocessor checks Co-authored-by: Takayuki 'January June' Suwa --- cores/esp8266/WString.cpp | 35 +++------------------------------ cores/esp8266/WString.h | 11 ++++------- tests/host/core/test_string.cpp | 13 ++++++++++++ 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 46aad5d5a0..056bbeb988 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -45,7 +45,6 @@ String::String(const __FlashStringHelper *pstr) { *this = pstr; // see operator = } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ String::String(String &&rval) noexcept { init(); move(rval); @@ -55,7 +54,6 @@ String::String(StringSumHelper &&rval) noexcept { init(); move(rval); } -#endif String::String(char c) { init(); @@ -223,36 +221,11 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) { return *this; } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ void String::move(String &rhs) noexcept { - if (buffer()) { - if (capacity() >= rhs.len()) { - memmove_P(wbuffer(), rhs.buffer(), rhs.length() + 1); - setLen(rhs.len()); - rhs.invalidate(); - return; - } else { - if (!isSSO()) { - free(wbuffer()); - setBuffer(nullptr); - } - } - } - if (rhs.isSSO()) { - setSSO(true); - memmove_P(sso.buff, rhs.sso.buff, sizeof(sso.buff)); - } else { - setSSO(false); - setBuffer(rhs.wbuffer()); - } - setCapacity(rhs.capacity()); - setLen(rhs.len()); - rhs.setSSO(false); - rhs.setCapacity(0); - rhs.setLen(0); - rhs.setBuffer(nullptr); + invalidate(); + sso = rhs.sso; + rhs.init(); } -#endif String & String::operator =(const String &rhs) { if (this == &rhs) @@ -266,7 +239,6 @@ String & String::operator =(const String &rhs) { return *this; } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ String & String::operator =(String &&rval) noexcept { if (this != &rval) move(rval); @@ -278,7 +250,6 @@ String & String::operator =(StringSumHelper &&rval) noexcept { move(rval); return *this; } -#endif String & String::operator =(const char *cstr) { if (cstr) diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index 8e2db3f9b9..c9b79f21c4 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -53,13 +53,14 @@ class String { // if the initial value is null or invalid, or if memory allocation // fails, the string will be marked as invalid (i.e. "if (s)" will // be false). - String(const char *cstr = nullptr); + String() { + init(); + } + String(const char *cstr); String(const String &str); String(const __FlashStringHelper *str); -#ifdef __GXX_EXPERIMENTAL_CXX0X__ String(String &&rval) noexcept; String(StringSumHelper &&rval) noexcept; -#endif explicit String(char c); explicit String(unsigned char, unsigned char base = 10); explicit String(int, unsigned char base = 10); @@ -95,10 +96,8 @@ class String { String & operator =(const String &rhs); String & operator =(const char *cstr); String & operator = (const __FlashStringHelper *str); -#ifdef __GXX_EXPERIMENTAL_CXX0X__ String & operator =(String &&rval) noexcept; String & operator =(StringSumHelper &&rval) noexcept; -#endif // concatenate (works w/ built-in types) @@ -316,9 +315,7 @@ class String { // copy and move String & copy(const char *cstr, unsigned int length); String & copy(const __FlashStringHelper *pstr, unsigned int length); -#ifdef __GXX_EXPERIMENTAL_CXX0X__ void move(String &rhs) noexcept; -#endif }; class StringSumHelper: public String { diff --git a/tests/host/core/test_string.cpp b/tests/host/core/test_string.cpp index 2d8ced73fc..f9fb30a6d5 100644 --- a/tests/host/core/test_string.cpp +++ b/tests/host/core/test_string.cpp @@ -19,6 +19,19 @@ #include #include +TEST_CASE("String::move", "[core][String]") +{ + const char buffer[] = "this string goes over the sso limit"; + + String target; + String source(buffer); + + target = std::move(source); + REQUIRE(source.c_str() != nullptr); + REQUIRE(!source.length()); + REQUIRE(target == buffer); +} + TEST_CASE("String::trim", "[core][String]") { String str;