summaryrefslogtreecommitdiffstats
path: root/Source
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 /Source
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 'Source')
-rw-r--r--Source/cmString.cxx27
-rw-r--r--Source/cmString.hxx14
2 files changed, 38 insertions, 3 deletions
diff --git a/Source/cmString.cxx b/Source/cmString.cxx
index e965bfb..2a0c125 100644
--- a/Source/cmString.cxx
+++ b/Source/cmString.cxx
@@ -22,20 +22,41 @@ void String::internally_mutate_to_stable_string()
*this = String(data(), size());
}
-std::string const& String::str()
+bool String::is_stable() const
+{
+ return str_if_stable() != nullptr;
+}
+
+void String::stabilize()
+{
+ if (is_stable()) {
+ return;
+ }
+ this->internally_mutate_to_stable_string();
+}
+
+std::string const* String::str_if_stable() const
{
if (!data()) {
// We view no string.
// This is stable for the lifetime of our current value.
- return empty_string_;
+ return &empty_string_;
}
if (string_ && data() == string_->data() && size() == string_->size()) {
// We view an entire string.
// This is stable for the lifetime of our current value.
- return *string_;
+ return string_.get();
}
+ return nullptr;
+}
+
+std::string const& String::str()
+{
+ if (std::string const* s = str_if_stable()) {
+ return *s;
+ }
// Mutate to hold a std::string that is stable for the lifetime
// of our current value.
this->internally_mutate_to_stable_string();
diff --git a/Source/cmString.hxx b/Source/cmString.hxx
index 52e891c..1623a43 100644
--- a/Source/cmString.hxx
+++ b/Source/cmString.hxx
@@ -348,6 +348,20 @@ public:
char back() const noexcept { return view_.back(); }
+ /** Return true if this instance is stable and otherwise false.
+ An instance is stable if it is in the 'null' state or if it is
+ an 'owned' state not produced by substring operations, or
+ after a call to 'stabilize()' or 'str()'. */
+ bool is_stable() const;
+
+ /** If 'is_stable()' does not return true, mutate so it does. */
+ void stabilize();
+
+ /** Get a pointer to a normal std::string if 'is_stable()' returns
+ true and otherwise nullptr. The pointer is valid until this
+ instance is mutated or destroyed. */
+ std::string const* str_if_stable() const;
+
/** Get a refernce to a normal std::string. The reference
is valid until this instance is mutated or destroyed. */
std::string const& str();