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"
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
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()) {
35 this->internally_mutate_to_stable_string();
38 std::string
const* String::str_if_stable() const
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();
56 std::string
const& String::str()
58 if (std::string
const* s
= this->str_if_stable()) {
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();
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') {
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();
87 String
& String::insert(size_type index
, size_type count
, char ch
)
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
;
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
,
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
)
145 return std::string(s
);
148 string_view AsStringView
<String
>::view(String
const& s
)