Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmStringAlgorithms.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
#include "cmStringAlgorithms.h"
4
5
#include <algorithm>
6
#include <cerrno>
7
#include <cstddef> // IWYU pragma: keep
8
#include <cstdio>
9
#include <cstdlib>
10
11
bool cmStrCaseEq(cm::string_view s1, cm::string_view s2)
12
0
{
13
0
  if (s1.size() != s2.size()) {
14
0
    return false;
15
0
  }
16
17
0
  return std::equal(
18
0
    s1.begin(), s1.end(), s2.begin(),
19
0
    [](unsigned char a, unsigned char b) { return tolower(a) == tolower(b); });
20
0
}
21
22
std::string cmTrimWhitespace(cm::string_view str)
23
1.50k
{
24
  // XXX(clang-tidy): This declaration and the next cannot be `const auto*`
25
  // because the qualification of `auto` is platform-dependent.
26
  // NOLINTNEXTLINE(readability-qualified-auto)
27
1.50k
  auto start = str.begin();
28
126k
  while (start != str.end() && cmIsSpace(*start)) {
29
125k
    ++start;
30
125k
  }
31
1.50k
  if (start == str.end()) {
32
29
    return std::string();
33
29
  }
34
  // NOLINTNEXTLINE(readability-qualified-auto)
35
1.47k
  auto stop = str.end() - 1;
36
16.1k
  while (cmIsSpace(*stop)) {
37
14.6k
    --stop;
38
14.6k
  }
39
1.47k
  return std::string(start, stop + 1);
40
1.50k
}
41
42
cm::string_view cmStripWhitespace(cm::string_view str)
43
0
{
44
0
  std::string::size_type const l = str.size();
45
46
0
  std::string::size_type s = 0;
47
0
  while (s < l && cmIsSpace(str[s])) {
48
0
    ++s;
49
0
  }
50
0
  if (s == l) {
51
0
    return cm::string_view{};
52
0
  }
53
0
  std::string::size_type e = l - 1;
54
0
  while (cmIsSpace(str[e])) {
55
0
    --e;
56
0
  }
57
0
  return str.substr(s, e + 1 - s);
58
0
}
59
60
std::string cmRemoveQuotes(cm::string_view str)
61
1.50k
{
62
  // We process only strings that have two quotes at least.
63
  // Also front() and back() are only defined behavior on non empty strings.
64
1.50k
  if (str.size() >= 2 &&    //
65
1.46k
      str.front() == '"' && //
66
45
      str.back() == '"') {
67
    // Remove a quote from the front and back
68
9
    str.remove_prefix(1);
69
9
    str.remove_suffix(1);
70
9
  }
71
1.50k
  return std::string(str);
72
1.50k
}
73
74
std::string cmEscapeQuotes(cm::string_view str)
75
1.50k
{
76
1.50k
  std::string result;
77
1.50k
  result.reserve(str.size());
78
1.81M
  for (char const ch : str) {
79
1.81M
    if (ch == '"') {
80
2.99k
      result += '\\';
81
2.99k
    }
82
1.81M
    result += ch;
83
1.81M
  }
84
1.50k
  return result;
85
1.50k
}
86
87
namespace {
88
template <std::size_t N, typename T>
89
inline void MakeDigits(cm::string_view& view, char (&digits)[N],
90
                       char const* pattern, T value)
91
3
{
92
3
  int res = std::snprintf(digits, N, pattern, value);
93
3
  if (res > 0 && res < static_cast<int>(N)) {
94
3
    view = cm::string_view(digits, static_cast<std::size_t>(res));
95
3
  }
96
3
}
Unexecuted instantiation: cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, int>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, int)
cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, unsigned int>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, unsigned int)
Line
Count
Source
91
3
{
92
3
  int res = std::snprintf(digits, N, pattern, value);
93
3
  if (res > 0 && res < static_cast<int>(N)) {
94
3
    view = cm::string_view(digits, static_cast<std::size_t>(res));
95
3
  }
96
3
}
Unexecuted instantiation: cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, long)
Unexecuted instantiation: cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, unsigned long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, unsigned long)
Unexecuted instantiation: cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, long long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, long long)
Unexecuted instantiation: cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, unsigned long long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, unsigned long long)
Unexecuted instantiation: cmStringAlgorithms.cxx:void (anonymous namespace)::MakeDigits<32ul, double>(std::__1::basic_string_view<char, std::__1::char_traits<char> >&, char (&) [32ul], char const*, double)
97
} // unnamed namespace
98
99
cmAlphaNum::cmAlphaNum(int val)
100
0
{
101
0
  MakeDigits(this->View_, this->Digits_, "%i", val);
102
0
}
103
104
cmAlphaNum::cmAlphaNum(unsigned int val)
105
3
{
106
3
  MakeDigits(this->View_, this->Digits_, "%u", val);
107
3
}
108
109
cmAlphaNum::cmAlphaNum(long int val)
110
0
{
111
0
  MakeDigits(this->View_, this->Digits_, "%li", val);
112
0
}
113
114
cmAlphaNum::cmAlphaNum(unsigned long int val)
115
0
{
116
0
  MakeDigits(this->View_, this->Digits_, "%lu", val);
117
0
}
118
119
cmAlphaNum::cmAlphaNum(long long int val)
120
0
{
121
0
  MakeDigits(this->View_, this->Digits_, "%lli", val);
122
0
}
123
124
cmAlphaNum::cmAlphaNum(unsigned long long int val)
125
0
{
126
0
  MakeDigits(this->View_, this->Digits_, "%llu", val);
127
0
}
128
129
cmAlphaNum::cmAlphaNum(float val)
130
0
{
131
0
  MakeDigits(this->View_, this->Digits_, "%g", static_cast<double>(val));
132
0
}
133
134
cmAlphaNum::cmAlphaNum(double val)
135
0
{
136
0
  MakeDigits(this->View_, this->Digits_, "%g", val);
137
0
}
138
139
std::string cmCatViews(
140
  std::initializer_list<std::pair<cm::string_view, std::string*>> views)
141
86.1k
{
142
86.1k
  std::size_t totalSize = 0;
143
86.1k
  std::string* rvalueString = nullptr;
144
86.1k
  std::size_t rvalueStringLength = 0;
145
86.1k
  std::size_t rvalueStringOffset = 0;
146
205k
  for (auto const& view : views) {
147
    // Find the rvalue string with the largest capacity.
148
205k
    if (view.second &&
149
27.3k
        (!rvalueString ||
150
27.3k
         view.second->capacity() > rvalueString->capacity())) {
151
27.3k
      rvalueString = view.second;
152
27.3k
      rvalueStringLength = rvalueString->length();
153
27.3k
      rvalueStringOffset = totalSize;
154
27.3k
    }
155
205k
    totalSize += view.first.size();
156
205k
  }
157
158
86.1k
  std::string result;
159
86.1k
  std::string::size_type initialLen = 0;
160
86.1k
  if (rvalueString && rvalueString->capacity() >= totalSize) {
161
23.6k
    result = std::move(*rvalueString);
162
62.4k
  } else {
163
62.4k
    rvalueString = nullptr;
164
62.4k
  }
165
86.1k
  result.resize(totalSize);
166
86.1k
  if (rvalueString && rvalueStringOffset > 0) {
167
23.6k
    std::copy_backward(result.begin(), result.begin() + rvalueStringLength,
168
23.6k
                       result.begin() + rvalueStringOffset +
169
23.6k
                         rvalueStringLength);
170
23.6k
  }
171
86.1k
  std::string::iterator sit = result.begin() + initialLen;
172
205k
  for (auto const& view : views) {
173
205k
    if (rvalueString && view.second == rvalueString) {
174
23.6k
      sit += rvalueStringLength;
175
181k
    } else {
176
181k
      sit = std::copy_n(view.first.data(), view.first.size(), sit);
177
181k
    }
178
205k
  }
179
86.1k
  return result;
180
86.1k
}
181
182
bool cmStrToLong(char const* str, long* value)
183
0
{
184
0
  errno = 0;
185
0
  char* endp;
186
0
  *value = strtol(str, &endp, 10);
187
0
  return (*endp == '\0') && (endp != str) && (errno == 0);
188
0
}
189
190
bool cmStrToLong(std::string const& str, long* value)
191
0
{
192
0
  return cmStrToLong(str.c_str(), value);
193
0
}
194
195
bool cmStrToULong(char const* str, unsigned long* value)
196
0
{
197
0
  errno = 0;
198
0
  char* endp;
199
0
  while (cmIsSpace(*str)) {
200
0
    ++str;
201
0
  }
202
0
  if (*str == '-') {
203
0
    return false;
204
0
  }
205
0
  *value = strtoul(str, &endp, 10);
206
0
  return (*endp == '\0') && (endp != str) && (errno == 0);
207
0
}
208
209
bool cmStrToULong(std::string const& str, unsigned long* value)
210
0
{
211
0
  return cmStrToULong(str.c_str(), value);
212
0
}
213
214
bool cmStrToLongLong(char const* str, long long* value)
215
0
{
216
0
  errno = 0;
217
0
  char* endp;
218
0
  *value = strtoll(str, &endp, 10);
219
0
  return (*endp == '\0') && (endp != str) && (errno == 0);
220
0
}
221
222
bool cmStrToLongLong(std::string const& str, long long* value)
223
0
{
224
0
  return cmStrToLongLong(str.c_str(), value);
225
0
}
226
227
bool cmStrToULongLong(char const* str, unsigned long long* value)
228
0
{
229
0
  errno = 0;
230
0
  char* endp;
231
0
  while (cmIsSpace(*str)) {
232
0
    ++str;
233
0
  }
234
0
  if (*str == '-') {
235
0
    return false;
236
0
  }
237
0
  *value = strtoull(str, &endp, 10);
238
0
  return (*endp == '\0') && (endp != str) && (errno == 0);
239
0
}
240
241
bool cmStrToULongLong(std::string const& str, unsigned long long* value)
242
0
{
243
0
  return cmStrToULongLong(str.c_str(), value);
244
0
}
245
246
std::string cmJoin(std::vector<std::string> const& rng,
247
                   cm::string_view separator, cm::string_view initial)
248
3.00k
{
249
3.00k
  return cmJoinStrings(rng, separator, initial);
250
3.00k
}
251
252
std::string cmJoin(cmStringRange rng, cm::string_view separator,
253
                   cm::string_view initial)
254
0
{
255
0
  return cmJoinStrings(rng, separator, initial);
256
0
}