Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / cmString.cxx
blobf7f62932ce34913684ba0832b3beb23009637057
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 // NOLINTNEXTLINE(bugprone-reserved-identifier)
4 #define _SCL_SECURE_NO_WARNINGS
6 #include "cmString.hxx"
8 #include <memory>
9 #include <ostream>
10 #include <stdexcept>
11 #include <string>
13 namespace cm {
15 static std::string const empty_string_;
17 void String::internally_mutate_to_stable_string()
19 // We assume that only one thread mutates this instance at
20 // a time even if we point to a shared string buffer referenced
21 // by other threads.
22 *this = String(this->data(), this->size());
25 bool String::is_stable() const
27 return this->str_if_stable() != nullptr;
30 void String::stabilize()
32 if (this->is_stable()) {
33 return;
35 this->internally_mutate_to_stable_string();
38 std::string const* String::str_if_stable() const
40 if (!this->data()) {
41 // We view no string.
42 // This is stable for the lifetime of our current value.
43 return &empty_string_;
46 if (this->string_ && this->data() == this->string_->data() &&
47 this->size() == this->string_->size()) {
48 // We view an entire string.
49 // This is stable for the lifetime of our current value.
50 return this->string_.get();
53 return nullptr;
56 std::string const& String::str()
58 if (std::string const* s = this->str_if_stable()) {
59 return *s;
61 // Mutate to hold a std::string that is stable for the lifetime
62 // of our current value.
63 this->internally_mutate_to_stable_string();
64 return *this->string_;
67 const char* String::c_str()
69 const char* c = this->data();
70 if (c == nullptr) {
71 return c;
74 // We always point into a null-terminated string so it is safe to
75 // access one past the end. If it is a null byte then we can use
76 // the pointer directly.
77 if (c[this->size()] == '\0') {
78 return c;
81 // Mutate to hold a std::string so we can get a null terminator.
82 this->internally_mutate_to_stable_string();
83 c = this->string_->c_str();
84 return c;
87 String& String::insert(size_type index, size_type count, char ch)
89 std::string s;
90 s.reserve(this->size() + count);
91 s.assign(this->data(), this->size());
92 s.insert(index, count, ch);
93 return *this = std::move(s);
96 String& String::erase(size_type index, size_type count)
98 if (index > this->size()) {
99 throw std::out_of_range("Index out of range in String::erase");
101 size_type const rcount = std::min(count, this->size() - index);
102 size_type const rindex = index + rcount;
103 std::string s;
104 s.reserve(this->size() - rcount);
105 s.assign(this->data(), index);
106 s.append(this->data() + rindex, this->size() - rindex);
107 return *this = std::move(s);
110 String String::substr(size_type pos, size_type count) const
112 if (pos > this->size()) {
113 throw std::out_of_range("Index out of range in String::substr");
115 return String(*this, pos, count);
118 String::String(std::string&& s, Private)
119 : string_(std::make_shared<std::string>(std::move(s)))
120 , view_(this->string_->data(), this->string_->size())
124 String::size_type String::copy(char* dest, size_type count,
125 size_type pos) const
127 return this->view_.copy(dest, count, pos);
130 std::ostream& operator<<(std::ostream& os, String const& s)
132 return os.write(s.data(), s.size());
135 std::string& operator+=(std::string& self, String const& s)
137 return self += s.view();
140 String IntoString<char*>::into_string(const char* s)
142 if (!s) {
143 return String();
145 return std::string(s);
148 string_view AsStringView<String>::view(String const& s)
150 return s.view();
153 } // namespace cm