summaryrefslogtreecommitdiffstats
path: root/Tests/CMakeLib/testString.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2018-11-08 13:12:02 (GMT)
committerBrad King <brad.king@kitware.com>2018-12-12 13:10:16 (GMT)
commit2d68b2c593b0bc19273e95f98ff29b3d3cff90c7 (patch)
tree6be15c7acfe6fd77f52ddab42519cd52ad3f1a7d /Tests/CMakeLib/testString.cxx
parenta0841b59bdacc1e550e6607d9e44e79ae456cd19 (diff)
downloadCMake-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.cxx59
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;
}