Coverage Report

Created: 2026-03-12 06:35

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.61k
{
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.61k
  auto start = str.begin();
30
119k
  while (start != str.end() && cmsysString_isspace(*start)) {
31
118k
    ++start;
32
118k
  }
33
1.61k
  if (start == str.end()) {
34
26
    return std::string();
35
26
  }
36
  // NOLINTNEXTLINE(readability-qualified-auto)
37
1.58k
  auto stop = str.end() - 1;
38
13.5k
  while (cmsysString_isspace(*stop)) {
39
11.9k
    --stop;
40
11.9k
  }
41
1.58k
  return std::string(start, stop + 1);
42
1.61k
}
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.61k
{
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.61k
  if (str.size() >= 2 &&    //
67
1.55k
      str.front() == '"' && //
68
55
      str.back() == '"') {
69
    // Remove a quote from the front and back
70
12
    str.remove_prefix(1);
71
12
    str.remove_suffix(1);
72
12
  }
73
1.61k
  return std::string(str);
74
1.61k
}
75
76
std::string cmEscapeQuotes(cm::string_view str)
77
1.61k
{
78
1.61k
  std::string result;
79
1.61k
  result.reserve(str.size());
80
1.94M
  for (char const ch : str) {
81
1.94M
    if (ch == '"') {
82
2.90k
      result += '\\';
83
2.90k
    }
84
1.94M
    result += ch;
85
1.94M
  }
86
1.61k
  return result;
87
1.61k
}
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
6.86k
{
94
6.86k
  int res = std::snprintf(digits, N, pattern, value);
95
6.86k
  if (res > 0 && res < static_cast<int>(N)) {
96
6.86k
    view = cm::string_view(digits, static_cast<std::size_t>(res));
97
6.86k
  }
98
6.86k
}
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
6.86k
{
94
6.86k
  int res = std::snprintf(digits, N, pattern, value);
95
6.86k
  if (res > 0 && res < static_cast<int>(N)) {
96
6.86k
    view = cm::string_view(digits, static_cast<std::size_t>(res));
97
6.86k
  }
98
6.86k
}
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
6.86k
{
113
6.86k
  MakeDigits(this->View_, this->Digits_, "%li", val);
114
6.86k
}
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
102k
{
144
102k
  std::size_t totalSize = 0;
145
102k
  std::string* rvalueString = nullptr;
146
102k
  std::size_t rvalueStringLength = 0;
147
102k
  std::size_t rvalueStringOffset = 0;
148
250k
  for (auto const& view : views) {
149
    // Find the rvalue string with the largest capacity.
150
250k
    if (view.second &&
151
33.6k
        (!rvalueString ||
152
33.6k
         view.second->capacity() > rvalueString->capacity())) {
153
33.6k
      rvalueString = view.second;
154
33.6k
      rvalueStringLength = rvalueString->length();
155
33.6k
      rvalueStringOffset = totalSize;
156
33.6k
    }
157
250k
    totalSize += view.first.size();
158
250k
  }
159
160
102k
  std::string result;
161
102k
  std::string::size_type initialLen = 0;
162
102k
  if (rvalueString && rvalueString->capacity() >= totalSize) {
163
26.8k
    result = std::move(*rvalueString);
164
75.6k
  } else {
165
75.6k
    rvalueString = nullptr;
166
75.6k
  }
167
102k
  result.resize(totalSize);
168
102k
  if (rvalueString && rvalueStringOffset > 0) {
169
26.5k
    std::copy_backward(result.begin(), result.begin() + rvalueStringLength,
170
26.5k
                       result.begin() + rvalueStringOffset +
171
26.5k
                         rvalueStringLength);
172
26.5k
  }
173
102k
  std::string::iterator sit = result.begin() + initialLen;
174
250k
  for (auto const& view : views) {
175
250k
    if (rvalueString && view.second == rvalueString) {
176
26.8k
      sit += rvalueStringLength;
177
223k
    } else {
178
223k
      sit = std::copy_n(view.first.data(), view.first.size(), sit);
179
223k
    }
180
250k
  }
181
102k
  return result;
182
102k
}
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.22k
{
251
3.22k
  return cmJoinStrings(rng, separator, initial);
252
3.22k
}
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
}