resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmString.cxx
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
5
6 #include "cmString.hxx"
7
8 #include <memory>
9 #include <ostream>
10 #include <stdexcept>
11 #include <string>
12 #include <type_traits>
13
14 namespace cm {
15
16 static std::string const empty_string_;
17
18 void String::internally_mutate_to_stable_string()
19 {
20   // We assume that only one thread mutates this instance at
21   // a time even if we point to a shared string buffer referenced
22   // by other threads.
23   *this = String(this->data(), this->size());
24 }
25
26 bool String::is_stable() const
27 {
28   return this->str_if_stable() != nullptr;
29 }
30
31 void String::stabilize()
32 {
33   if (this->is_stable()) {
34     return;
35   }
36   this->internally_mutate_to_stable_string();
37 }
38
39 std::string const* String::str_if_stable() const
40 {
41   if (!this->data()) {
42     // We view no string.
43     // This is stable for the lifetime of our current value.
44     return &empty_string_;
45   }
46
47   if (this->string_ && this->data() == this->string_->data() &&
48       this->size() == this->string_->size()) {
49     // We view an entire string.
50     // This is stable for the lifetime of our current value.
51     return this->string_.get();
52   }
53
54   return nullptr;
55 }
56
57 std::string const& String::str()
58 {
59   if (std::string const* s = this->str_if_stable()) {
60     return *s;
61   }
62   // Mutate to hold a std::string that is stable for the lifetime
63   // of our current value.
64   this->internally_mutate_to_stable_string();
65   return *this->string_;
66 }
67
68 const char* String::c_str()
69 {
70   const char* c = this->data();
71   if (c == nullptr) {
72     return c;
73   }
74
75   // We always point into a null-terminated string so it is safe to
76   // access one past the end.  If it is a null byte then we can use
77   // the pointer directly.
78   if (c[this->size()] == '\0') {
79     return c;
80   }
81
82   // Mutate to hold a std::string so we can get a null terminator.
83   this->internally_mutate_to_stable_string();
84   c = this->string_->c_str();
85   return c;
86 }
87
88 String& String::insert(size_type index, size_type count, char ch)
89 {
90   std::string s;
91   s.reserve(this->size() + count);
92   s.assign(this->data(), this->size());
93   s.insert(index, count, ch);
94   return *this = std::move(s);
95 }
96
97 String& String::erase(size_type index, size_type count)
98 {
99   if (index > this->size()) {
100     throw std::out_of_range("Index out of range in String::erase");
101   }
102   size_type const rcount = std::min(count, this->size() - index);
103   size_type const rindex = index + rcount;
104   std::string s;
105   s.reserve(this->size() - rcount);
106   s.assign(this->data(), index);
107   s.append(this->data() + rindex, this->size() - rindex);
108   return *this = std::move(s);
109 }
110
111 String String::substr(size_type pos, size_type count) const
112 {
113   if (pos > this->size()) {
114     throw std::out_of_range("Index out of range in String::substr");
115   }
116   return String(*this, pos, count);
117 }
118
119 String::String(std::string&& s, Private)
120   : string_(std::make_shared<std::string>(std::move(s)))
121   , view_(this->string_->data(), this->string_->size())
122 {
123 }
124
125 String::size_type String::copy(char* dest, size_type count,
126                                size_type pos) const
127 {
128   return this->view_.copy(dest, count, pos);
129 }
130
131 std::ostream& operator<<(std::ostream& os, String const& s)
132 {
133   return os.write(s.data(), s.size());
134 }
135
136 std::string& operator+=(std::string& self, String const& s)
137 {
138   return self += s.view();
139 }
140
141 String IntoString<char*>::into_string(const char* s)
142 {
143   if (!s) {
144     return String();
145   }
146   return std::string(s);
147 }
148
149 string_view AsStringView<String>::view(String const& s)
150 {
151   return s.view();
152 }
153
154 } // namespace cm