Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmString.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst 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
13
namespace cm {
14
15
static std::string const empty_string_;
16
17
void String::internally_mutate_to_stable_string()
18
0
{
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
0
  *this = String(this->data(), this->size());
23
0
}
24
25
bool String::is_stable() const
26
0
{
27
0
  return this->str_if_stable() != nullptr;
28
0
}
29
30
void String::stabilize()
31
0
{
32
0
  if (this->is_stable()) {
33
0
    return;
34
0
  }
35
0
  this->internally_mutate_to_stable_string();
36
0
}
37
38
std::string const* String::str_if_stable() const
39
6
{
40
6
  if (!this->data()) {
41
    // We view no string.
42
    // This is stable for the lifetime of our current value.
43
0
    return &empty_string_;
44
0
  }
45
46
6
  if (this->string_ && this->data() == this->string_->data() &&
47
6
      this->size() == this->string_->size()) {
48
    // We view an entire string.
49
    // This is stable for the lifetime of our current value.
50
6
    return this->string_.get();
51
6
  }
52
53
0
  return nullptr;
54
6
}
55
56
std::string const& String::str()
57
0
{
58
0
  if (std::string const* s = this->str_if_stable()) {
59
0
    return *s;
60
0
  }
61
  // Mutate to hold a std::string that is stable for the lifetime
62
  // of our current value.
63
0
  this->internally_mutate_to_stable_string();
64
0
  return *this->string_;
65
0
}
66
67
char const* String::c_str()
68
0
{
69
0
  char const* c = this->data();
70
0
  if (!c) {
71
0
    return c;
72
0
  }
73
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
0
  if (c[this->size()] == '\0') {
78
0
    return c;
79
0
  }
80
81
  // Mutate to hold a std::string so we can get a null terminator.
82
0
  this->internally_mutate_to_stable_string();
83
0
  c = this->string_->c_str();
84
0
  return c;
85
0
}
86
87
String& String::insert(size_type index, size_type count, char ch)
88
0
{
89
0
  std::string s;
90
0
  s.reserve(this->size() + count);
91
0
  s.assign(this->data(), this->size());
92
0
  s.insert(index, count, ch);
93
0
  return *this = std::move(s);
94
0
}
95
96
String& String::erase(size_type index, size_type count)
97
0
{
98
0
  if (index > this->size()) {
99
0
    throw std::out_of_range("Index out of range in String::erase");
100
0
  }
101
0
  size_type const rcount = std::min(count, this->size() - index);
102
0
  size_type const rindex = index + rcount;
103
0
  std::string s;
104
0
  s.reserve(this->size() - rcount);
105
0
  s.assign(this->data(), index);
106
0
  s.append(this->data() + rindex, this->size() - rindex);
107
0
  return *this = std::move(s);
108
0
}
109
110
String String::substr(size_type pos, size_type count) const
111
0
{
112
0
  if (pos > this->size()) {
113
0
    throw std::out_of_range("Index out of range in String::substr");
114
0
  }
115
0
  return String(*this, pos, count);
116
0
}
117
118
String::String(std::string&& s, Private)
119
195
  : string_(std::make_shared<std::string>(std::move(s)))
120
195
  , view_(this->string_->data(), this->string_->size())
121
195
{
122
195
}
123
124
String::size_type String::copy(char* dest, size_type count,
125
                               size_type pos) const
126
0
{
127
0
  return this->view_.copy(dest, count, pos);
128
0
}
129
130
std::ostream& operator<<(std::ostream& os, String const& s)
131
0
{
132
0
  return os.write(s.data(), s.size());
133
0
}
134
135
std::string& operator+=(std::string& self, String const& s)
136
0
{
137
0
  return self += s.view();
138
0
}
139
140
String IntoString<char*>::into_string(char const* s)
141
0
{
142
0
  if (!s) {
143
0
    return String();
144
0
  }
145
0
  return std::string(s);
146
0
}
147
148
string_view AsStringView<String>::view(String const& s)
149
0
{
150
0
  return s.view();
151
0
}
152
153
} // namespace cm