Coverage Report

Created: 2026-04-29 07:01

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