| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| // NOLINTNEXTLINE(bugprone-reserved-identifier) | |
| #define _SCL_SECURE_NO_WARNINGS | |
| #include "cmString.hxx" | |
| #include <memory> | |
| #include <ostream> | |
| #include <stdexcept> | |
| #include <string> | |
| namespace cm { | |
| static std::string const empty_string_; | |
| void String::internally_mutate_to_stable_string() | |
| { | |
| // We assume that only one thread mutates this instance at | |
| // a time even if we point to a shared string buffer referenced | |
| // by other threads. | |
| *this = String(this->data(), this->size()); | |
| } | |
| bool String::is_stable() const | |
| { | |
| return this->str_if_stable() != nullptr; | |
| } | |
| void String::stabilize() | |
| { | |
| if (this->is_stable()) { | |
| return; | |
| } | |
| this->internally_mutate_to_stable_string(); | |
| } | |
| std::string const* String::str_if_stable() const | |
| { | |
| if (!this->data()) { | |
| // We view no string. | |
| // This is stable for the lifetime of our current value. | |
| return &empty_string_; | |
| } | |
| if (this->string_ && this->data() == this->string_->data() && | |
| this->size() == this->string_->size()) { | |
| // We view an entire string. | |
| // This is stable for the lifetime of our current value. | |
| return this->string_.get(); | |
| } | |
| return nullptr; | |
| } | |
| std::string const& String::str() | |
| { | |
| if (std::string const* s = this->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(); | |
| return *this->string_; | |
| } | |
| char const* String::c_str() | |
| { | |
| char const* c = this->data(); | |
| if (!c) { | |
| return c; | |
| } | |
| // We always point into a null-terminated string so it is safe to | |
| // access one past the end. If it is a null byte then we can use | |
| // the pointer directly. | |
| if (c[this->size()] == '\0') { | |
| return c; | |
| } | |
| // Mutate to hold a std::string so we can get a null terminator. | |
| this->internally_mutate_to_stable_string(); | |
| c = this->string_->c_str(); | |
| return c; | |
| } | |
| String& String::insert(size_type index, size_type count, char ch) | |
| { | |
| std::string s; | |
| s.reserve(this->size() + count); | |
| s.assign(this->data(), this->size()); | |
| s.insert(index, count, ch); | |
| return *this = std::move(s); | |
| } | |
| String& String::erase(size_type index, size_type count) | |
| { | |
| if (index > this->size()) { | |
| throw std::out_of_range("Index out of range in String::erase"); | |
| } | |
| size_type const rcount = std::min(count, this->size() - index); | |
| size_type const rindex = index + rcount; | |
| std::string s; | |
| s.reserve(this->size() - rcount); | |
| s.assign(this->data(), index); | |
| s.append(this->data() + rindex, this->size() - rindex); | |
| return *this = std::move(s); | |
| } | |
| String String::substr(size_type pos, size_type count) const | |
| { | |
| if (pos > this->size()) { | |
| throw std::out_of_range("Index out of range in String::substr"); | |
| } | |
| return String(*this, pos, count); | |
| } | |
| String::String(std::string&& s, Private) | |
| : string_(std::make_shared<std::string>(std::move(s))) | |
| , view_(this->string_->data(), this->string_->size()) | |
| { | |
| } | |
| String::size_type String::copy(char* dest, size_type count, | |
| size_type pos) const | |
| { | |
| return this->view_.copy(dest, count, pos); | |
| } | |
| std::ostream& operator<<(std::ostream& os, String const& s) | |
| { | |
| return os.write(s.data(), s.size()); | |
| } | |
| std::string& operator+=(std::string& self, String const& s) | |
| { | |
| return self += s.view(); | |
| } | |
| String IntoString<char*>::into_string(char const* s) | |
| { | |
| if (!s) { | |
| return String(); | |
| } | |
| return std::string(s); | |
| } | |
| string_view AsStringView<String>::view(String const& s) | |
| { | |
| return s.view(); | |
| } | |
| } // namespace cm |