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 /Source | |
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 'Source')
-rw-r--r-- | Source/cmString.cxx | 27 | ||||
-rw-r--r-- | Source/cmString.hxx | 14 |
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(); |