diff options
author | Brad King <brad.king@kitware.com> | 2018-11-08 13:12:02 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2018-12-12 13:10:16 (GMT) |
commit | 2d68b2c593b0bc19273e95f98ff29b3d3cff90c7 (patch) | |
tree | 6be15c7acfe6fd77f52ddab42519cd52ad3f1a7d /Tests/CMakeLib/testString.cxx | |
parent | a0841b59bdacc1e550e6607d9e44e79ae456cd19 (diff) | |
download | CMake-2d68b2c593b0bc19273e95f98ff29b3d3cff90c7.zip CMake-2d68b2c593b0bc19273e95f98ff29b3d3cff90c7.tar.gz CMake-2d68b2c593b0bc19273e95f98ff29b3d3cff90c7.tar.bz2 |
String: Add str_if_stable() as a const alternative to str()
The `str()` method must be non-const because it may need to internally
mutate the representation of the string in order to have an owned
`std::string` instance holding the exact string (not a superstring).
This is inconvenient in contexts where we can ensure that no mutation
is needed to get a `std::string const&`.
Add a `str_if_stable() const` method that returns `std::string const*`
so we can return `nullptr` if if mutation would be necessary to get a
`std::string const&`. Add supporting `is_stable() const` and
`stabilize()` methods to check and enforce stable availability of
`std::string const&`. These can be used to create `String const`
instances from which we can still get a `std::string const&` via
`*str_if_stable()` by maintaining the stability invariant at runtime.
Diffstat (limited to 'Tests/CMakeLib/testString.cxx')
-rw-r--r-- | Tests/CMakeLib/testString.cxx | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx index 8bdcb15..2aa1459 100644 --- a/Tests/CMakeLib/testString.cxx +++ b/Tests/CMakeLib/testString.cxx @@ -30,8 +30,10 @@ static bool testConstructDefault() ASSERT_TRUE(str_const.data() == nullptr); ASSERT_TRUE(str_const.size() == 0); ASSERT_TRUE(str_const.empty()); + ASSERT_TRUE(str_const.is_stable()); ASSERT_TRUE(str.c_str() == nullptr); ASSERT_TRUE(str.str().empty()); + ASSERT_TRUE(str.is_stable()); return true; } @@ -42,8 +44,10 @@ static bool testFromNullPtr(cm::String str) ASSERT_TRUE(str_const.data() == nullptr); ASSERT_TRUE(str_const.size() == 0); ASSERT_TRUE(str_const.empty()); + ASSERT_TRUE(str_const.is_stable()); ASSERT_TRUE(str.c_str() == nullptr); ASSERT_TRUE(str.str().empty()); + ASSERT_TRUE(str.is_stable()); return true; } @@ -68,8 +72,10 @@ static bool testFromCStrNull(cm::String str) ASSERT_TRUE(str_const.data() == nullptr); ASSERT_TRUE(str_const.size() == 0); ASSERT_TRUE(str_const.empty()); + ASSERT_TRUE(str_const.is_stable()); ASSERT_TRUE(str.c_str() == nullptr); ASSERT_TRUE(str.str().empty()); + ASSERT_TRUE(str.is_stable()); return true; } @@ -96,12 +102,16 @@ static bool testFromCharArray(cm::String str) cm::String const& str_const = str; ASSERT_TRUE(str_const.data() != charArray); ASSERT_TRUE(str_const.size() == sizeof(charArray) - 1); + ASSERT_TRUE(str_const.is_stable()); ASSERT_TRUE(str.c_str() != charArray); + ASSERT_TRUE(str.is_stable()); cm::String substr = str.substr(1); cm::String const& substr_const = substr; ASSERT_TRUE(substr_const.data() != &charArray[1]); ASSERT_TRUE(substr_const.size() == 2); + ASSERT_TRUE(!substr_const.is_stable()); ASSERT_TRUE(substr.c_str() != &charArray[1]); + ASSERT_TRUE(!substr.is_stable()); return true; } @@ -126,6 +136,7 @@ static bool testFromCStr(cm::String const& str) ASSERT_TRUE(str.data() != cstr); ASSERT_TRUE(str.size() == 3); ASSERT_TRUE(std::strncmp(str.data(), cstr, 3) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -156,6 +167,7 @@ static bool testFromStdString(cm::String const& str) #endif ASSERT_TRUE(str.size() == 3); ASSERT_TRUE(std::strncmp(str.data(), stdstr.data(), 3) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -193,6 +205,7 @@ static bool testFromChar(cm::String const& str) { ASSERT_TRUE(str.size() == 1); ASSERT_TRUE(std::strncmp(str.data(), "a", 1) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -216,6 +229,7 @@ static bool testConstructFromInitList() cm::String const str{ 'a', 'b', 'c' }; ASSERT_TRUE(str.size() == 3); ASSERT_TRUE(std::strncmp(str.data(), "abc", 3) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -226,6 +240,7 @@ static bool testAssignFromInitList() str = { 'a', 'b', 'c' }; ASSERT_TRUE(str.size() == 3); ASSERT_TRUE(std::strncmp(str.data(), "abc", 3) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -243,6 +258,7 @@ static bool testConstructFromInputIterator() ASSERT_TRUE(str.data() != cstr); ASSERT_TRUE(str.size() == 3); ASSERT_TRUE(std::strncmp(str.data(), cstr, 3) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -252,6 +268,7 @@ static bool testConstructFromN() cm::String const str(3, 'a'); ASSERT_TRUE(str.size() == 3); ASSERT_TRUE(std::strncmp(str.data(), "aaa", 3) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -262,12 +279,16 @@ static bool testFromStaticStringView(cm::String str) cm::String const& str_const = str; ASSERT_TRUE(str_const.data() == staticStringView.data()); ASSERT_TRUE(str_const.size() == staticStringView.size()); + ASSERT_TRUE(!str_const.is_stable()); ASSERT_TRUE(str.c_str() == staticStringView); + ASSERT_TRUE(!str.is_stable()); cm::String substr = str.substr(1); cm::String const& substr_const = substr; ASSERT_TRUE(substr_const.data() == &staticStringView[1]); ASSERT_TRUE(substr_const.size() == 2); + ASSERT_TRUE(!substr_const.is_stable()); ASSERT_TRUE(substr.c_str() == &staticStringView[1]); + ASSERT_TRUE(!substr.is_stable()); return true; } @@ -294,6 +315,8 @@ static bool testConstructCopy() ASSERT_TRUE(s1.size() == 3); ASSERT_TRUE(s2.size() == 3); ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0); + ASSERT_TRUE(s1.is_stable()); + ASSERT_TRUE(s2.is_stable()); return true; } @@ -306,6 +329,8 @@ static bool testConstructMove() ASSERT_TRUE(s1.size() == 0); ASSERT_TRUE(s2.size() == 3); ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0); + ASSERT_TRUE(s1.is_stable()); + ASSERT_TRUE(s2.is_stable()); return true; } @@ -319,6 +344,8 @@ static bool testAssignCopy() ASSERT_TRUE(s1.size() == 3); ASSERT_TRUE(s2.size() == 3); ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0); + ASSERT_TRUE(s1.is_stable()); + ASSERT_TRUE(s2.is_stable()); return true; } @@ -332,6 +359,8 @@ static bool testAssignMove() ASSERT_TRUE(s1.size() == 0); ASSERT_TRUE(s2.size() == 3); ASSERT_TRUE(std::strncmp(s2.data(), "abc", 3) == 0); + ASSERT_TRUE(s1.is_stable()); + ASSERT_TRUE(s2.is_stable()); return true; } @@ -376,6 +405,7 @@ static bool testOperatorPlusEqual() str += cm::String("g"); ASSERT_TRUE(str.size() == 7); ASSERT_TRUE(std::strncmp(str.data(), "abcdefg", 7) == 0); + ASSERT_TRUE(str.is_stable()); return true; } @@ -742,15 +772,18 @@ static bool testMethod_substr_AtEnd(cm::String str) cm::String substr = str.substr(1); ASSERT_TRUE(substr.data() == str.data() + 1); ASSERT_TRUE(substr.size() == 2); + ASSERT_TRUE(!substr.is_stable()); // c_str() at the end of the buffer does not internally mutate. ASSERT_TRUE(std::strcmp(substr.c_str(), "bc") == 0); ASSERT_TRUE(substr.c_str() == str.data() + 1); ASSERT_TRUE(substr.data() == str.data() + 1); ASSERT_TRUE(substr.size() == 2); + ASSERT_TRUE(!substr.is_stable()); // str() internally mutates. ASSERT_TRUE(substr.str() == "bc"); + ASSERT_TRUE(substr.is_stable()); ASSERT_TRUE(substr.data() != str.data() + 1); ASSERT_TRUE(substr.size() == 2); ASSERT_TRUE(substr.c_str() != str.data() + 1); @@ -783,9 +816,11 @@ static bool testMethod_substr_AtStart(cm::String str) ASSERT_TRUE(substr_c != str.data()); ASSERT_TRUE(substr.data() != str.data()); ASSERT_TRUE(substr.size() == 2); + ASSERT_TRUE(substr.is_stable()); // str() does not need to internally mutate after c_str() did so ASSERT_TRUE(substr.str() == "ab"); + ASSERT_TRUE(substr.is_stable()); ASSERT_TRUE(substr.data() == substr_c); ASSERT_TRUE(substr.size() == 2); ASSERT_TRUE(substr.c_str() == substr_c); @@ -795,9 +830,11 @@ static bool testMethod_substr_AtStart(cm::String str) cm::String substr = str.substr(0, 2); ASSERT_TRUE(substr.data() == str.data()); ASSERT_TRUE(substr.size() == 2); + ASSERT_TRUE(!substr.is_stable()); // str() internally mutates. ASSERT_TRUE(substr.str() == "ab"); + ASSERT_TRUE(substr.is_stable()); ASSERT_TRUE(substr.data() != str.data()); ASSERT_TRUE(substr.size() == 2); ASSERT_TRUE(substr.c_str() != str.data()); @@ -807,6 +844,7 @@ static bool testMethod_substr_AtStart(cm::String str) ASSERT_TRUE(std::strcmp(substr_c, "ab") == 0); ASSERT_TRUE(substr_c == substr.data()); ASSERT_TRUE(substr.size() == 2); + ASSERT_TRUE(substr.is_stable()); } return true; @@ -1088,6 +1126,7 @@ static bool testAddition() cm::String str; str += "a" + cm::String("b") + 'c'; ASSERT_TRUE(str == "abc"); + ASSERT_TRUE(str.is_stable()); } { std::string s; @@ -1102,6 +1141,23 @@ static bool testAddition() return true; } +static bool testStability() +{ + std::cout << "testStability()\n"; + cm::String str = "abc"_s; + ASSERT_TRUE(!str.is_stable()); + ASSERT_TRUE(str.str_if_stable() == nullptr); + str.stabilize(); + ASSERT_TRUE(str.is_stable()); + std::string const* str_if_stable = str.str_if_stable(); + ASSERT_TRUE(str_if_stable != nullptr); + ASSERT_TRUE(*str_if_stable == "abc"); + str.stabilize(); + ASSERT_TRUE(str.is_stable()); + ASSERT_TRUE(str.str_if_stable() == str_if_stable); + return true; +} + int testString(int /*unused*/, char* /*unused*/ []) { if (!testConstructDefault()) { @@ -1284,5 +1340,8 @@ int testString(int /*unused*/, char* /*unused*/ []) if (!testAddition()) { return 1; } + if (!testStability()) { + return 1; + } return 0; } |