1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

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 <jjsuwa@sys3175.com>
This commit is contained in:
Max Prokhorov 2020-09-27 18:11:52 +03:00 committed by GitHub
parent a3281fe2f3
commit cc042b99d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 39 deletions

View File

@ -45,7 +45,6 @@ String::String(const __FlashStringHelper *pstr) {
*this = pstr; // see operator = *this = pstr; // see operator =
} }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String::String(String &&rval) noexcept { String::String(String &&rval) noexcept {
init(); init();
move(rval); move(rval);
@ -55,7 +54,6 @@ String::String(StringSumHelper &&rval) noexcept {
init(); init();
move(rval); move(rval);
} }
#endif
String::String(char c) { String::String(char c) {
init(); init();
@ -223,36 +221,11 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
return *this; return *this;
} }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void String::move(String &rhs) noexcept { void String::move(String &rhs) noexcept {
if (buffer()) { invalidate();
if (capacity() >= rhs.len()) { sso = rhs.sso;
memmove_P(wbuffer(), rhs.buffer(), rhs.length() + 1); rhs.init();
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);
} }
#endif
String & String::operator =(const String &rhs) { String & String::operator =(const String &rhs) {
if (this == &rhs) if (this == &rhs)
@ -266,7 +239,6 @@ String & String::operator =(const String &rhs) {
return *this; return *this;
} }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & String::operator =(String &&rval) noexcept { String & String::operator =(String &&rval) noexcept {
if (this != &rval) if (this != &rval)
move(rval); move(rval);
@ -278,7 +250,6 @@ String & String::operator =(StringSumHelper &&rval) noexcept {
move(rval); move(rval);
return *this; return *this;
} }
#endif
String & String::operator =(const char *cstr) { String & String::operator =(const char *cstr) {
if (cstr) if (cstr)

View File

@ -53,13 +53,14 @@ class String {
// if the initial value is null or invalid, or if memory allocation // 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 // fails, the string will be marked as invalid (i.e. "if (s)" will
// be false). // be false).
String(const char *cstr = nullptr); String() {
init();
}
String(const char *cstr);
String(const String &str); String(const String &str);
String(const __FlashStringHelper *str); String(const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String(String &&rval) noexcept; String(String &&rval) noexcept;
String(StringSumHelper &&rval) noexcept; String(StringSumHelper &&rval) noexcept;
#endif
explicit String(char c); explicit String(char c);
explicit String(unsigned char, unsigned char base = 10); explicit String(unsigned char, unsigned char base = 10);
explicit String(int, 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 String &rhs);
String & operator =(const char *cstr); String & operator =(const char *cstr);
String & operator = (const __FlashStringHelper *str); String & operator = (const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & operator =(String &&rval) noexcept; String & operator =(String &&rval) noexcept;
String & operator =(StringSumHelper &&rval) noexcept; String & operator =(StringSumHelper &&rval) noexcept;
#endif
// concatenate (works w/ built-in types) // concatenate (works w/ built-in types)
@ -316,9 +315,7 @@ class String {
// copy and move // copy and move
String & copy(const char *cstr, unsigned int length); String & copy(const char *cstr, unsigned int length);
String & copy(const __FlashStringHelper *pstr, unsigned int length); String & copy(const __FlashStringHelper *pstr, unsigned int length);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void move(String &rhs) noexcept; void move(String &rhs) noexcept;
#endif
}; };
class StringSumHelper: public String { class StringSumHelper: public String {

View File

@ -19,6 +19,19 @@
#include <limits.h> #include <limits.h>
#include <StreamString.h> #include <StreamString.h>
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]") TEST_CASE("String::trim", "[core][String]")
{ {
String str; String str;