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

libbitcoin / libbitcoin-system / 13069453084

31 Jan 2025 08:55AM UTC coverage: 82.728% (-0.007%) from 82.735%
13069453084

push

github

web-flow
Merge pull request #1604 from evoskuil/master

Set _CRTDBG_MAP_ALLOC for vc++ debug mode leak tracking.

2 of 2 new or added lines in 1 file covered. (100.0%)

15 existing lines in 11 files now uncovered.

10039 of 12135 relevant lines covered (82.73%)

3871639.49 hits per line

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

91.13
/src/data/string.cpp
1
/**
2
 * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/system/data/string.hpp>
20

21
#include <algorithm>
22
#include <iterator>
23
#include <sstream>
24
#include <utility>
25
#include <bitcoin/system/data/data_slice.hpp>
26
#include <bitcoin/system/define.hpp>
27
#include <bitcoin/system/unicode/unicode.hpp>
28

29
namespace libbitcoin {
30
namespace system {
31

32
std::string join(const string_list& tokens,
44,213✔
33
    const std::string& delimiter) NOEXCEPT
34
{
35
    if (tokens.empty())
44,213✔
36
        return {};
8✔
37

38
    // Start with the first token.
39
    std::ostringstream sentence;
44,205✔
40

41
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
42
    sentence << tokens.front();
44,205✔
43

44
    // Add remaining tokens preceded by delimiters.
45
    for (auto token = std::next(tokens.begin()); token != tokens.end(); ++token)
422,817✔
46
        sentence << delimiter << *token;
378,612✔
47

48
    return sentence.str();
44,205✔
49
    BC_POP_WARNING()
50
}
44,205✔
51

52
void reduce(string_list& tokens, const string_list& trim_tokens,
34,597✔
53
    bool compress) NOEXCEPT
54
{
55
    static const std::string empty{};
34,597✔
56

57
    if (tokens.empty())
34,597✔
58
        return;
59

60
    for (auto& token: tokens)
263,254✔
61
        trim(token, trim_tokens);
228,658✔
62

63
    if (compress)
34,596✔
64
        std::erase(tokens, empty);
34,429✔
65

66
    if (tokens.empty())
34,596✔
67
        tokens.push_back({});
164✔
68
}
69

70
string_list reduce_copy(const string_list& tokens,
×
71
    const string_list& trim_tokens, bool compress) NOEXCEPT
72
{
73
    string_list copy{ tokens };
×
74
    reduce(copy, trim_tokens, compress);
×
75
    return copy;
×
UNCOV
76
}
×
77

78
size_t replace(std::string& text, const std::string& from,
175,030✔
79
    const std::string& to) NOEXCEPT
80
{
81
    auto count = zero;
175,030✔
82

83
    for (auto position = text.find(from);
363,968✔
84
        position != std::string::npos;
363,968✔
85
        position = text.find(from, position + to.length()))
188,938✔
86
    {
87
        ++count;
188,938✔
88
        text.replace(position, from.length(), to);
188,938✔
89
    }
90

91
    return count;
175,030✔
92
}
93

94
std::string replace_copy(const std::string& text, const std::string& from,
2✔
95
    const std::string& to) NOEXCEPT
96
{
97
    std::string copy{ text };
2✔
98
    replace(copy, from, to);
2✔
99
    return copy;
2✔
100
}
101

102
static string_list splitter(const std::string& text, const std::string& delimiter,
34,589✔
103
    const string_list& trim_tokens, bool compress) NOEXCEPT
104
{
105
    auto start = zero;
34,589✔
106
    string_list tokens;
34,589✔
107

108
    // Push all but the last token.
109
    for (auto position = text.find(delimiter);
34,589✔
110
        position != std::string::npos;
228,637✔
111
        position = text.find(delimiter, start))
194,048✔
112
    {
113
        tokens.push_back(text.substr(start, position - start));
194,048✔
114
        start = position + delimiter.length();
194,048✔
115
    }
116

117
    // Push last token (delimiter not found).
118
    tokens.push_back(text.substr(start, text.length() - start));
34,589✔
119
    reduce(tokens, trim_tokens, compress);
34,589✔
120
    return tokens;
34,589✔
UNCOV
121
}
×
122

123
string_list split(const std::string& text, const string_list& delimiters,
34,589✔
124
    const string_list& trim_tokens, bool compress) NOEXCEPT
125
{
126
    // Nothing to do.
127
    if (delimiters.empty() && trim_tokens.empty())
34,589✔
128
        return { text };
×
129

130
    // Trim first to preclude outer empty otherwise trimmable outer tokens.
131
    auto trimmed = trim_copy(text, trim_tokens);
34,589✔
132

133
    // Nothing more to do.
134
    if (delimiters.empty())
34,589✔
135
        return { trimmed };
×
136

137
    // Replace all other delimiters with the first delimiter.
138
    for (auto it = std::next(delimiters.begin()); it != delimiters.end(); ++it)
209,607✔
139
        replace(trimmed, *it, delimiters.front());
175,018✔
140

141
    // Split on the first delimiter and conditionally compress empty tokens.
142
    return splitter(trimmed, delimiters.front(), trim_tokens, compress);
34,589✔
143
}
144

145
string_list split(const std::string& text, const std::string& delimiter,
251✔
146
    bool trim, bool compress) NOEXCEPT
147
{
148
    const auto trim_tokens = trim ? ascii_whitespace : string_list{};
251✔
149
    return split(text, string_list{ delimiter }, trim_tokens, compress);
753✔
150
}
251✔
151

152
string_list split(const std::string& text, bool compress) NOEXCEPT
33,946✔
153
{
154
    // Splitting is prioritized over trimming, because each token is trimmed.
155
    // So trimming is not an option when splitting on the trim characters.
156
    return split(text, ascii_whitespace, ascii_whitespace, compress);
33,946✔
157
}
158

159
bool trim_left(std::string& text, const std::string& token) NOEXCEPT
1,760,959✔
160
{
161
    auto found = false;
1,760,959✔
162
    const auto length = token.length();
1,760,959✔
163
    while (starts_with(text, token))
1,761,102✔
164
    {
165
        found = true;
143✔
166
        text.erase(zero, length);
143✔
167
    }
168
    text.shrink_to_fit();
1,760,959✔
169
    return found;
1,760,959✔
170
}
171

172
bool trim_right(std::string& text, const std::string& token) NOEXCEPT
1,761,001✔
173
{
174
    auto found = false;
1,761,001✔
175
    const auto length = token.length();
1,761,001✔
176
    while (ends_with(text, token))
1,761,433✔
177
    {
178
        found = true;
432✔
179
        text.erase(text.length() - length);
432✔
180
    }
181
    text.shrink_to_fit();
1,761,001✔
182
    return found;
1,761,001✔
183
}
184

185
bool trim_left(std::string& text, const string_list& trim_tokens) NOEXCEPT
269,432✔
186
{
187
    bool found{};
269,432✔
188
    do
269,499✔
189
    {
190
        found = false;
269,499✔
191
        for (const auto& token: trim_tokens)
2,030,458✔
192
            if (trim_left(text, token))
1,760,959✔
193
                found = true;
119✔
194
    }
195
    while (found);
196
    return found;
269,432✔
197
}
198

199
bool trim_right(std::string& text, const string_list& trim_tokens) NOEXCEPT
269,488✔
200
{
201
    bool found{};
269,488✔
202
    do
269,565✔
203
    {
204
        found = false;
269,565✔
205
        for (const auto& token: trim_tokens)
2,030,566✔
206
            if (trim_right(text, token))
1,761,001✔
207
                found = true;
114✔
208
    }
209
    while (found);
210
    return found;
269,488✔
211
}
212

213
void trim(std::string& text, const string_list& trim_tokens) NOEXCEPT
269,430✔
214
{
215
    trim_left(text, trim_tokens);
269,430✔
216
    trim_right(text, trim_tokens);
269,430✔
217
}
269,430✔
218

219
std::string trim_left_copy(const std::string& text,
1✔
220
    const string_list& trim_tokens) NOEXCEPT
221
{
222
    std::string copy{ text };
1✔
223
    trim_left(copy, trim_tokens);
1✔
224
    return copy;
1✔
225
}
226

227
std::string trim_left_copy(std::string&& text,
1✔
228
    const string_list& trim_tokens) NOEXCEPT
229
{
230
    trim_left(text, trim_tokens);
1✔
231
    return std::move(text);
1✔
232
}
233

234
std::string trim_right_copy(const std::string& text,
2✔
235
    const string_list& trim_tokens) NOEXCEPT
236
{
237
    std::string copy{ text };
2✔
238
    trim_right(copy, trim_tokens);
2✔
239
    return copy;
2✔
240
}
241

242
std::string trim_right_copy(std::string&& text,
×
243
    const string_list& trim_tokens) NOEXCEPT
244
{
245
    trim_right(text, trim_tokens);
×
246
    return std::move(text);
×
247
}
248

249
std::string trim_copy(const std::string& text,
40,760✔
250
    const string_list& trim_tokens) NOEXCEPT
251
{
252
    std::string copy{ text };
40,760✔
253
    trim(copy, trim_tokens);
40,760✔
254
    return copy;
40,760✔
255
}
256

257
std::string trim_copy(std::string&& text,
7✔
258
    const string_list& trim_tokens) NOEXCEPT
259
{
260
    trim(text, trim_tokens);
7✔
261
    return std::move(text);
7✔
262
}
263

264
bool ends_with(const std::string& text, const std::string& suffix) NOEXCEPT
1,761,437✔
265
{
266
    const auto at = text.rfind(suffix);
1,761,437✔
267
    return at != std::string::npos && (at + suffix.length()) == text.length();
1,761,437✔
268
}
269

270
bool starts_with(const std::string& text, const std::string& prefix) NOEXCEPT
1,775,373✔
271
{
272
    return is_zero(text.find(prefix));
1,775,373✔
273
}
274

275
} // namespace system
276
} // namespace libbitcoin
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

© 2025 Coveralls, Inc