• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tstack / lnav / 11872214087-1756

16 Nov 2024 06:12PM UTC coverage: 70.243% (+0.5%) from 69.712%
11872214087-1756

push

github

tstack
[build] disable regex101

46266 of 65866 relevant lines covered (70.24%)

467515.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.33
/src/base/string_util.hh
1
/**
2
 * Copyright (c) 2019, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29

30
#ifndef lnav_string_util_hh
31
#define lnav_string_util_hh
32

33
#include <string>
34
#include <vector>
35

36
#include <string.h>
37

38
#include "auto_mem.hh"
39
#include "intern_string.hh"
40
#include "ww898/cp_utf8.hpp"
41

42
void scrub_to_utf8(char* buffer, size_t length);
43

44
inline bool
45
is_line_ending(char ch)
40,876✔
46
{
47
    return ch == '\r' || ch == '\n';
40,876✔
48
}
49

50
void quote_content(auto_buffer& buf,
51
                   const string_fragment& sf,
52
                   char quote_char);
53

54
size_t unquote_content(char* dst, const char* str, size_t len, char quote_char);
55

56
size_t unquote(char* dst, const char* str, size_t len);
57

58
size_t unquote_w3c(char* dst, const char* str, size_t len);
59

60
inline bool
61
startswith(const char* str, const char* prefix)
115,529✔
62
{
63
    return strncmp(str, prefix, strlen(prefix)) == 0;
115,529✔
64
}
65

66
inline bool
67
startswith(const std::string& str, const char* prefix)
17,448✔
68
{
69
    return startswith(str.c_str(), prefix);
17,448✔
70
}
71

72
inline bool
73
startswith(const std::string& str, const std::string& prefix)
107✔
74
{
75
    return startswith(str.c_str(), prefix.c_str());
107✔
76
}
77

78
inline bool
79
endswith(const char* str, const char* suffix)
25✔
80
{
81
    size_t len = strlen(str), suffix_len = strlen(suffix);
25✔
82

83
    if (suffix_len > len) {
25✔
84
        return false;
1✔
85
    }
86

87
    return strcmp(&str[len - suffix_len], suffix) == 0;
24✔
88
}
89

90
template<int N>
91
inline bool
92
endswith(const std::string& str, const char (&suffix)[N])
9,654✔
93
{
94
    if (N - 1 > str.length()) {
9,654✔
95
        return false;
608✔
96
    }
97

98
    return strcmp(&str[str.size() - (N - 1)], suffix) == 0;
9,046✔
99
}
100

131✔
101
void truncate_to(std::string& str, size_t max_char_len);
102

131✔
103
std::string scrub_ws(const char* in, ssize_t len = -1);
×
104
inline std::string
105
scrub_ws(const string_fragment& sf)
12✔
106
{
131✔
107
    return scrub_ws(sf.data(), sf.length());
12✔
108
}
×
109

110
inline std::string
×
111
trim(const std::string& str)
10,228✔
112
{
113
    std::string::size_type start, end;
114

×
115
    for (start = 0; start < str.size() && isspace(str[start]); start++)
17,835✔
116
        ;
117
    for (end = str.size(); end > 0 && isspace(str[end - 1]); end--)
17,950✔
118
        ;
119

120
    return str.substr(start, end - start);
10,228✔
121
}
122

123
inline const char*
124
ltrim(const char* str)
125
{
126
    while (isspace(*str)) {
127
        str += 1;
128
    }
129

130
    return str;
131
}
132

133
inline std::string
134
rtrim(const std::string& str)
×
135
{
136
    std::string::size_type end;
137

138
    for (end = str.size(); end > 0 && isspace(str[end - 1]); end--)
×
139
        ;
140

141
    return str.substr(0, end);
×
142
}
143

144
inline std::string
145
tolower(const char* str)
22,365✔
146
{
147
    std::string retval;
22,365✔
148

149
    for (int lpc = 0; str[lpc]; lpc++) {
715,653✔
150
        retval.push_back(::tolower(str[lpc]));
693,288✔
151
    }
152

153
    return retval;
22,365✔
154
}
×
155

156
inline std::string
157
tolower(const std::string& str)
22,365✔
158
{
159
    return tolower(str.c_str());
22,365✔
160
}
161

162
inline std::string
163
toupper(const char* str)
90,871✔
164
{
165
    std::string retval;
90,871✔
166

167
    for (int lpc = 0; str[lpc]; lpc++) {
636,551✔
168
        retval.push_back(::toupper(str[lpc]));
545,680✔
169
    }
170

171
    return retval;
90,871✔
172
}
×
173

174
inline std::string
175
toupper(const std::string& str)
36,003✔
176
{
177
    return toupper(str.c_str());
36,003✔
178
}
179

180
inline ssize_t
181
utf8_char_to_byte_index(const std::string& str, ssize_t ch_index)
283✔
182
{
183
    ssize_t retval = 0;
283✔
184

185
    while (ch_index > 0) {
9,746✔
186
        auto ch_len
187
            = ww898::utf::utf8::char_size([&str, retval]() {
9,463✔
188
                  return std::make_pair(str[retval], str.length() - retval - 1);
9,463✔
189
              }).unwrapOr(1);
9,463✔
190

191
        retval += ch_len;
9,463✔
192
        ch_index -= 1;
9,463✔
193
    }
194

195
    return retval;
283✔
196
}
197

198
inline Result<size_t, const char*>
199
utf8_string_length(const char* str, ssize_t len = -1)
17,246✔
200
{
201
    size_t retval = 0;
17,246✔
202

203
    if (len == -1) {
17,246✔
204
        len = strlen(str);
×
205
    }
206

207
    for (ssize_t byte_index = 0; byte_index < len;) {
8,600,959✔
208
        auto ch_size
209
            = TRY(ww898::utf::utf8::char_size([str, len, byte_index]() {
17,167,426✔
210
                  return std::make_pair(str[byte_index], len - byte_index);
211
              }));
212
        byte_index += ch_size;
8,583,713✔
213
        retval += 1;
8,583,713✔
214
    }
215

216
    return Ok(retval);
17,246✔
217
}
218

219
inline Result<size_t, const char*>
220
utf8_string_length(const std::string& str)
9,002✔
221
{
222
    return utf8_string_length(str.c_str(), str.length());
9,002✔
223
}
224

225
bool is_url(const std::string& fn);
226

227
bool is_blank(const std::string& str);
228

229
size_t abbreviate_str(char* str, size_t len, size_t max_len);
230

231
size_t last_word_str(char* str, size_t len, size_t max_len);
232

233
void split_ws(const std::string& str, std::vector<std::string>& toks_out);
234

235
std::string repeat(const std::string& input, size_t num);
236

237
std::string center_str(const std::string& subject, size_t width);
238

239
inline std::string
240
on_blank(const std::string& str, const std::string& def)
×
241
{
242
    if (is_blank(str)) {
×
243
        return def;
×
244
    }
245

246
    return str;
×
247
}
248

249
std::string to_superscript(const std::string& in);
250

251
template<typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
252
inline std::string
253
to_superscript(T in)
254
{
255
    return to_superscript(fmt::to_string(in));
256
}
257

258
namespace lnav {
259
class tainted_string {
260
public:
261
    explicit tainted_string(std::string s) : ts_str(std::move(s)) {}
262

263
    bool operator==(const tainted_string& other) const
264
    {
265
        return this->ts_str == other.ts_str;
266
    }
267

268
    bool operator!=(const tainted_string& other) const
269
    {
257✔
270
        return this->ts_str != other.ts_str;
271
    }
257✔
272

273
    bool operator<(const tainted_string& other) const
274
    {
275
        return this->ts_str < other.ts_str;
276
    }
277

278
    bool empty() const { return this->ts_str.empty(); }
279

280
    size_t length() const { return this->ts_str.length(); }
281

282
    size_t size() const { return this->ts_str.size(); }
283

284
    friend fmt::formatter<lnav::tainted_string>;
285

286
private:
287
    const std::string ts_str;
288
};
289
}  // namespace lnav
290

291
namespace fmt {
292
template<>
293
struct formatter<lnav::tainted_string> : formatter<string_view> {
294
    auto format(const lnav::tainted_string& ts, format_context& ctx)
295
        -> decltype(ctx.out()) const;
296
};
297
}  // namespace fmt
298

299
namespace lnav {
300
namespace pcre2pp {
301

302
std::string quote(string_fragment sf);
303

304
}
305
}  // namespace lnav
306

307
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc