Coverage Report

Created: 2026-08-25 19:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/util/string.h
Line
Count
Source
1
// Copyright (c) 2019-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#ifndef BITCOIN_UTIL_STRING_H
6
#define BITCOIN_UTIL_STRING_H
7
8
#include <algorithm>
9
#include <array>
10
#include <cstddef>
11
#include <cstdint>
12
#include <initializer_list>
13
#include <locale>
14
#include <optional>
15
#include <span>
16
#include <sstream>
17
#include <string>
18
#include <string_view>
19
#include <vector>
20
21
#include <attributes.h>
22
23
namespace util {
24
namespace detail {
25
template <unsigned num_params>
26
constexpr void CheckNumFormatSpecifiers(const char* str)
27
0
{
28
0
    unsigned count_normal{0}; // Number of "normal" specifiers, like %s
29
0
    unsigned count_pos{0};    // Max number in positional specifier, like %8$s
30
0
    for (auto it{str}; *it != '\0'; ++it) {
31
0
        if (*it != '%' || *++it == '%') continue; // Skip escaped %%
32
0
33
0
        auto add_arg = [&] {
34
0
            unsigned maybe_num{0};
35
0
            while ('0' <= *it && *it <= '9') {
36
0
                maybe_num *= 10;
37
0
                maybe_num += *it - '0';
38
0
                ++it;
39
0
            }
40
0
41
0
            if (*it == '$') {
42
0
                ++it;
43
0
                // Positional specifier, like %8$s
44
0
                if (maybe_num == 0) throw "Positional format specifier must have position of at least 1";
45
0
                count_pos = std::max(count_pos, maybe_num);
46
0
            } else {
47
0
                // Non-positional specifier, like %s
48
0
                ++count_normal;
49
0
            }
50
0
        };
51
0
52
0
        // Increase argument count and consume positional specifier, if present.
53
0
        add_arg();
54
0
55
0
        // Consume flags.
56
0
        while (*it == '#' || *it == '0' || *it == '-' || *it == ' ' || *it == '+') ++it;
57
0
58
0
        auto parse_size = [&] {
59
0
            if (*it == '*') {
60
0
                ++it;
61
0
                add_arg();
62
0
            } else {
63
0
                while ('0' <= *it && *it <= '9') ++it;
64
0
            }
65
0
        };
66
0
67
0
        // Consume dynamic or static width value.
68
0
        parse_size();
69
0
70
0
        // Consume dynamic or static precision value.
71
0
        if (*it == '.') {
72
0
            ++it;
73
0
            parse_size();
74
0
        }
75
0
76
0
        if (*it == '\0') throw "Format specifier incorrectly terminated by end of string";
77
0
78
0
        // Length and type in "[flags][width][.precision][length]type"
79
0
        // is not checked. Parsing continues with the next '%'.
80
0
    }
81
0
    if (count_normal && count_pos) throw "Format specifiers must be all positional or all non-positional!";
82
0
    unsigned count{count_normal | count_pos};
83
0
    if (num_params != count) throw "Format specifier count must match the argument count!";
84
0
}
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj1EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj2EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj3EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj5EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj6EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj0EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj4EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj7EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj18EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj19EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj12EEEvPKc
Unexecuted instantiation: _ZN4util6detail24CheckNumFormatSpecifiersILj8EEEvPKc
85
} // namespace detail
86
87
/**
88
 * @brief A wrapper for a compile-time partially validated format string
89
 *
90
 * This struct can be used to enforce partial compile-time validation of format
91
 * strings, to reduce the likelihood of tinyformat throwing exceptions at
92
 * run-time. Validation is partial to try and prevent the most common errors
93
 * while avoiding re-implementing the entire parsing logic.
94
 */
95
template <unsigned num_params>
96
struct ConstevalFormatString {
97
    const char* const fmt;
98
    consteval ConstevalFormatString(const char* str) : fmt{str} { detail::CheckNumFormatSpecifiers<num_params>(fmt); }
99
};
100
101
void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute);
102
103
/** Split a string on any char found in separators, returning a vector.
104
 *
105
 * If sep does not occur in sp, a singleton with the entirety of sp is returned.
106
 *
107
 * @param[in] include_sep Whether to include the separator at the end of the left side of the splits.
108
 *
109
 * Note that this function does not care about braces, so splitting
110
 * "foo(bar(1),2),3) on ',' will return {"foo(bar(1)", "2)", "3)"}.
111
 *
112
 * If include_sep == true, splitting "foo(bar(1),2),3) on ','
113
 * will return:
114
 *  - foo(bar(1),
115
 *  - 2),
116
 *  - 3)
117
 */
118
template <typename T = std::span<const char>>
119
std::vector<T> Split(const std::span<const char>& sp, std::string_view separators, bool include_sep = false)
120
1.56M
{
121
1.56M
    std::vector<T> ret;
122
1.56M
    auto it = sp.begin();
123
1.56M
    auto start = it;
124
253M
    while (it != sp.end()) {
  Branch (124:12): [True: 18.9M, False: 59.7k]
  Branch (124:12): [True: 232M, False: 1.50M]
  Branch (124:12): [True: 21.8k, False: 479]
125
251M
        if (separators.find(*it) != std::string::npos) {
  Branch (125:13): [True: 1.00M, False: 17.9M]
  Branch (125:13): [True: 972k, False: 231M]
  Branch (125:13): [True: 7.93k, False: 13.8k]
126
1.98M
            if (include_sep) {
  Branch (126:17): [True: 0, False: 1.00M]
  Branch (126:17): [True: 27.3k, False: 945k]
  Branch (126:17): [True: 0, False: 7.93k]
127
27.3k
                ret.emplace_back(start, it + 1);
128
1.96M
            } else {
129
1.96M
                ret.emplace_back(start, it);
130
1.96M
            }
131
1.98M
            start = it + 1;
132
1.98M
        }
133
251M
        ++it;
134
251M
    }
135
1.56M
    ret.emplace_back(start, it);
136
1.56M
    return ret;
137
1.56M
}
_ZN4util5SplitINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEESt6vectorIT_SaIS8_EERKSt4spanIKcLm18446744073709551615EESt17basic_string_viewIcS4_Eb
Line
Count
Source
120
59.7k
{
121
59.7k
    std::vector<T> ret;
122
59.7k
    auto it = sp.begin();
123
59.7k
    auto start = it;
124
19.0M
    while (it != sp.end()) {
  Branch (124:12): [True: 18.9M, False: 59.7k]
125
18.9M
        if (separators.find(*it) != std::string::npos) {
  Branch (125:13): [True: 1.00M, False: 17.9M]
126
1.00M
            if (include_sep) {
  Branch (126:17): [True: 0, False: 1.00M]
127
0
                ret.emplace_back(start, it + 1);
128
1.00M
            } else {
129
1.00M
                ret.emplace_back(start, it);
130
1.00M
            }
131
1.00M
            start = it + 1;
132
1.00M
        }
133
18.9M
        ++it;
134
18.9M
    }
135
59.7k
    ret.emplace_back(start, it);
136
59.7k
    return ret;
137
59.7k
}
_ZN4util5SplitISt4spanIKcLm18446744073709551615EEEESt6vectorIT_SaIS5_EERKS3_St17basic_string_viewIcSt11char_traitsIcEEb
Line
Count
Source
120
1.50M
{
121
1.50M
    std::vector<T> ret;
122
1.50M
    auto it = sp.begin();
123
1.50M
    auto start = it;
124
234M
    while (it != sp.end()) {
  Branch (124:12): [True: 232M, False: 1.50M]
125
232M
        if (separators.find(*it) != std::string::npos) {
  Branch (125:13): [True: 972k, False: 231M]
126
972k
            if (include_sep) {
  Branch (126:17): [True: 27.3k, False: 945k]
127
27.3k
                ret.emplace_back(start, it + 1);
128
945k
            } else {
129
945k
                ret.emplace_back(start, it);
130
945k
            }
131
972k
            start = it + 1;
132
972k
        }
133
232M
        ++it;
134
232M
    }
135
1.50M
    ret.emplace_back(start, it);
136
1.50M
    return ret;
137
1.50M
}
_ZN4util5SplitISt17basic_string_viewIcSt11char_traitsIcEEEESt6vectorIT_SaIS6_EERKSt4spanIKcLm18446744073709551615EES4_b
Line
Count
Source
120
479
{
121
479
    std::vector<T> ret;
122
479
    auto it = sp.begin();
123
479
    auto start = it;
124
22.3k
    while (it != sp.end()) {
  Branch (124:12): [True: 21.8k, False: 479]
125
21.8k
        if (separators.find(*it) != std::string::npos) {
  Branch (125:13): [True: 7.93k, False: 13.8k]
126
7.93k
            if (include_sep) {
  Branch (126:17): [True: 0, False: 7.93k]
127
0
                ret.emplace_back(start, it + 1);
128
7.93k
            } else {
129
7.93k
                ret.emplace_back(start, it);
130
7.93k
            }
131
7.93k
            start = it + 1;
132
7.93k
        }
133
21.8k
        ++it;
134
21.8k
    }
135
479
    ret.emplace_back(start, it);
136
479
    return ret;
137
479
}
138
139
/** Split a string on every instance of sep, returning a vector.
140
 *
141
 * If sep does not occur in sp, a singleton with the entirety of sp is returned.
142
 *
143
 * Note that this function does not care about braces, so splitting
144
 * "foo(bar(1),2),3) on ',' will return {"foo(bar(1)", "2)", "3)"}.
145
 */
146
template <typename T = std::span<const char>>
147
std::vector<T> Split(const std::span<const char>& sp, char sep, bool include_sep = false)
148
1.54M
{
149
1.54M
    return Split<T>(sp, std::string_view{&sep, 1}, include_sep);
150
1.54M
}
_ZN4util5SplitINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEESt6vectorIT_SaIS8_EERKSt4spanIKcLm18446744073709551615EEcb
Line
Count
Source
148
57.7k
{
149
57.7k
    return Split<T>(sp, std::string_view{&sep, 1}, include_sep);
150
57.7k
}
_ZN4util5SplitISt4spanIKcLm18446744073709551615EEEESt6vectorIT_SaIS5_EERKS3_cb
Line
Count
Source
148
1.48M
{
149
1.48M
    return Split<T>(sp, std::string_view{&sep, 1}, include_sep);
150
1.48M
}
Unexecuted instantiation: _ZN4util5SplitISt17basic_string_viewIcSt11char_traitsIcEEEESt6vectorIT_SaIS6_EERKSt4spanIKcLm18446744073709551615EEcb
151
152
[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, char sep)
153
57.7k
{
154
57.7k
    return Split<std::string>(str, sep);
155
57.7k
}
156
157
[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, std::string_view separators)
158
2.04k
{
159
2.04k
    return Split<std::string>(str, separators);
160
2.04k
}
161
162
[[nodiscard]] inline std::string_view TrimStringView(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
163
90.6k
{
164
90.6k
    std::string::size_type front = str.find_first_not_of(pattern);
165
90.6k
    if (front == std::string::npos) {
  Branch (165:9): [True: 3.33k, False: 87.2k]
166
3.33k
        return {};
167
3.33k
    }
168
87.2k
    std::string::size_type end = str.find_last_not_of(pattern);
169
87.2k
    return str.substr(front, end - front + 1);
170
90.6k
}
171
172
[[nodiscard]] inline std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
173
14.9k
{
174
14.9k
    return std::string(TrimStringView(str, pattern));
175
14.9k
}
176
177
[[nodiscard]] inline std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
178
0
{
179
0
    if (str.ends_with(suffix)) {
  Branch (179:9): [True: 0, False: 0]
180
0
        return str.substr(0, str.size() - suffix.size());
181
0
    }
182
0
    return str;
183
0
}
184
185
[[nodiscard]] inline std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
186
6.89M
{
187
6.89M
    if (str.starts_with(prefix)) {
  Branch (187:9): [True: 1.35k, False: 6.89M]
188
1.35k
        return str.substr(prefix.size());
189
1.35k
    }
190
6.89M
    return str;
191
6.89M
}
192
193
[[nodiscard]] inline std::string RemovePrefix(std::string_view str, std::string_view prefix)
194
1.61k
{
195
1.61k
    return std::string(RemovePrefixView(str, prefix));
196
1.61k
}
197
198
/**
199
 * Join all container items. Typically used to concatenate strings but accepts
200
 * containers with elements of any type.
201
 *
202
 * @param container The items to join
203
 * @param separator The separator
204
 * @param unary_op  Apply this operator to each item
205
 */
206
template <typename C, typename S, typename UnaryOp>
207
// NOLINTNEXTLINE(misc-no-recursion)
208
auto Join(const C& container, const S& separator, UnaryOp unary_op)
209
558k
{
210
558k
    decltype(unary_op(*container.begin())) ret;
211
558k
    bool first{true};
212
558k
    for (const auto& item : container) {
  Branch (212:27): [True: 204, False: 34]
  Branch (212:27): [True: 126k, False: 4.36k]
  Branch (212:27): [True: 13.8k, False: 1.61k]
  Branch (212:27): [True: 110k, False: 14.5k]
  Branch (212:27): [True: 153, False: 51]
  Branch (212:27): [True: 16.3k, False: 4.08k]
  Branch (212:27): [True: 2.42k, False: 873]
  Branch (212:27): [True: 6.12k, False: 2.04k]
  Branch (212:27): [True: 0, False: 530k]
  Branch (212:27): [True: 1, False: 1]
  Branch (212:27): [True: 780, False: 260]
  Branch (212:27): [True: 0, False: 0]
213
277k
        if (!first) ret += separator;
  Branch (213:13): [True: 170, False: 34]
  Branch (213:13): [True: 122k, False: 4.36k]
  Branch (213:13): [True: 12.6k, False: 1.23k]
  Branch (213:13): [True: 96.1k, False: 14.5k]
  Branch (213:13): [True: 102, False: 51]
  Branch (213:13): [True: 12.2k, False: 4.08k]
  Branch (213:13): [True: 1.54k, False: 873]
  Branch (213:13): [True: 4.08k, False: 2.04k]
  Branch (213:13): [True: 0, False: 0]
  Branch (213:13): [True: 0, False: 1]
  Branch (213:13): [True: 520, False: 260]
  Branch (213:13): [True: 0, False: 0]
214
277k
        ret += unary_op(item);
215
277k
        first = false;
216
277k
    }
217
558k
    return ret;
218
558k
}
_ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA2_cZNS_17MakeUnorderedListERKS9_EUlRKS7_E_EEDaRKT_RKT0_T1_
Line
Count
Source
209
34
{
210
34
    decltype(unary_op(*container.begin())) ret;
211
34
    bool first{true};
212
204
    for (const auto& item : container) {
  Branch (212:27): [True: 204, False: 34]
213
204
        if (!first) ret += separator;
  Branch (213:13): [True: 170, False: 34]
214
204
        ret += unary_op(item);
215
204
        first = false;
216
204
    }
217
34
    return ret;
218
34
}
_ZN4util4JoinISt6vectorI11LogCategorySaIS2_EEA3_cZNK5BCLog6Logger19LogCategoriesStringB5cxx11EvEUlRKS2_E_EEDaRKT_RKT0_T1_
Line
Count
Source
209
4.36k
{
210
4.36k
    decltype(unary_op(*container.begin())) ret;
211
4.36k
    bool first{true};
212
126k
    for (const auto& item : container) {
  Branch (212:27): [True: 126k, False: 4.36k]
213
126k
        if (!first) ret += separator;
  Branch (213:13): [True: 122k, False: 4.36k]
214
126k
        ret += unary_op(item);
215
126k
        first = false;
216
126k
    }
217
4.36k
    return ret;
218
4.36k
}
_ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EES7_ZNS_4JoinIS9_S7_EEDaRKT_RKT0_EUlSD_E_EEDaSD_SG_T1_
Line
Count
Source
209
1.61k
{
210
1.61k
    decltype(unary_op(*container.begin())) ret;
211
1.61k
    bool first{true};
212
13.8k
    for (const auto& item : container) {
  Branch (212:27): [True: 13.8k, False: 1.61k]
213
13.8k
        if (!first) ret += separator;
  Branch (213:13): [True: 12.6k, False: 1.23k]
214
13.8k
        ret += unary_op(item);
215
13.8k
        first = false;
216
13.8k
    }
217
1.61k
    return ret;
218
1.61k
}
_ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA3_cZNS_4JoinIS9_SA_EEDaRKT_RKT0_EUlSE_E_EEDaSE_SH_T1_
Line
Count
Source
209
14.5k
{
210
14.5k
    decltype(unary_op(*container.begin())) ret;
211
14.5k
    bool first{true};
212
110k
    for (const auto& item : container) {
  Branch (212:27): [True: 110k, False: 14.5k]
213
110k
        if (!first) ret += separator;
  Branch (213:13): [True: 96.1k, False: 14.5k]
214
110k
        ret += unary_op(item);
215
110k
        first = false;
216
110k
    }
217
14.5k
    return ret;
218
14.5k
}
messages.cpp:_ZN4util4JoinISt6vectorISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE15FeeEstimateModeESaISA_EES8_ZN6common8FeeModesERKS8_E3$_0EEDaRKT_RKT0_T1_
Line
Count
Source
209
51
{
210
51
    decltype(unary_op(*container.begin())) ret;
211
51
    bool first{true};
212
153
    for (const auto& item : container) {
  Branch (212:27): [True: 153, False: 51]
213
153
        if (!first) ret += separator;
  Branch (213:13): [True: 102, False: 51]
214
153
        ret += unary_op(item);
215
153
        first = false;
216
153
    }
217
51
    return ret;
218
51
}
outputtype.cpp:_ZN4util4JoinISt5arrayI10OutputTypeLm4EEA3_cZ20FormatAllOutputTypesB5cxx11vE3$_0EEDaRKT_RKT0_T1_
Line
Count
Source
209
4.08k
{
210
4.08k
    decltype(unary_op(*container.begin())) ret;
211
4.08k
    bool first{true};
212
16.3k
    for (const auto& item : container) {
  Branch (212:27): [True: 16.3k, False: 4.08k]
213
16.3k
        if (!first) ret += separator;
  Branch (213:13): [True: 12.2k, False: 4.08k]
214
16.3k
        ret += unary_op(item);
215
16.3k
        first = false;
216
16.3k
    }
217
4.08k
    return ret;
218
4.08k
}
util.cpp:_ZN4util4JoinISt6vectorI6RPCArgSaIS2_EEA2_cZNKS2_8ToStringB5cxx11EbE3$_0EEDaRKT_RKT0_T1_
Line
Count
Source
209
873
{
210
873
    decltype(unary_op(*container.begin())) ret;
211
873
    bool first{true};
212
2.42k
    for (const auto& item : container) {
  Branch (212:27): [True: 2.42k, False: 873]
213
2.42k
        if (!first) ret += separator;
  Branch (213:13): [True: 1.54k, False: 873]
214
2.42k
        ret += unary_op(item);
215
2.42k
        first = false;
216
2.42k
    }
217
873
    return ret;
218
873
}
logging.cpp:_ZN4util4JoinISt6vectorINS_3log5LevelESaIS3_EEA3_cZNK5BCLog6Logger15LogLevelsStringB5cxx11EvE3$_0EEDaRKT_RKT0_T1_
Line
Count
Source
209
2.04k
{
210
2.04k
    decltype(unary_op(*container.begin())) ret;
211
2.04k
    bool first{true};
212
6.12k
    for (const auto& item : container) {
  Branch (212:27): [True: 6.12k, False: 2.04k]
213
6.12k
        if (!first) ret += separator;
  Branch (213:13): [True: 4.08k, False: 2.04k]
214
6.12k
        ret += unary_op(item);
215
6.12k
        first = false;
216
6.12k
    }
217
2.04k
    return ret;
218
2.04k
}
_ZN4util4JoinISt6vectorI13bilingual_strSaIS2_EES2_ZNS_4JoinIS4_S2_EEDaRKT_RKT0_EUlS8_E_EEDaS8_SB_T1_
Line
Count
Source
209
530k
{
210
530k
    decltype(unary_op(*container.begin())) ret;
211
530k
    bool first{true};
212
530k
    for (const auto& item : container) {
  Branch (212:27): [True: 0, False: 530k]
213
0
        if (!first) ret += separator;
  Branch (213:13): [True: 0, False: 0]
214
0
        ret += unary_op(item);
215
0
        first = false;
216
0
    }
217
530k
    return ret;
218
530k
}
blockfilter.cpp:_ZN4util4JoinISt3mapI15BlockFilterTypeNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4lessIS2_ESaISt4pairIKS2_S8_EEEA3_cZ20ListBlockFilterTypesvE3$_0EEDaRKT_RKT0_T1_
Line
Count
Source
209
1
{
210
1
    decltype(unary_op(*container.begin())) ret;
211
1
    bool first{true};
212
1
    for (const auto& item : container) {
  Branch (212:27): [True: 1, False: 1]
213
1
        if (!first) ret += separator;
  Branch (213:13): [True: 0, False: 1]
214
1
        ret += unary_op(item);
215
1
        first = false;
216
1
    }
217
1
    return ret;
218
1
}
validation.cpp:_ZN4util4JoinISt6vectorIiSaIiEEA3_cZN17ChainstateManager16ActivateSnapshotER8AutoFileRKN4node16SnapshotMetadataEbE3$_0EEDaRKT_RKT0_T1_
Line
Count
Source
209
260
{
210
260
    decltype(unary_op(*container.begin())) ret;
211
260
    bool first{true};
212
780
    for (const auto& item : container) {
  Branch (212:27): [True: 780, False: 260]
213
780
        if (!first) ret += separator;
  Branch (213:13): [True: 520, False: 260]
214
780
        ret += unary_op(item);
215
780
        first = false;
216
780
    }
217
260
    return ret;
218
260
}
Unexecuted instantiation: _ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA2_cZNS_4JoinIS9_SA_EEDaRKT_RKT0_EUlSE_E_EEDaSE_SH_T1_
219
220
template <typename C, typename S>
221
auto Join(const C& container, const S& separator)
222
546k
{
223
546k
    return Join(container, separator, [](const auto& i) { return i; });
_ZZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EES7_EEDaRKT_RKT0_ENKUlSC_E_clIS7_EEDaSC_
Line
Count
Source
223
13.8k
    return Join(container, separator, [](const auto& i) { return i; });
_ZZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA3_cEEDaRKT_RKT0_ENKUlSD_E_clIS7_EEDaSD_
Line
Count
Source
223
110k
    return Join(container, separator, [](const auto& i) { return i; });
Unexecuted instantiation: _ZZN4util4JoinISt6vectorI13bilingual_strSaIS2_EES2_EEDaRKT_RKT0_ENKUlS7_E_clIS2_EEDaS7_
Unexecuted instantiation: _ZZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA2_cEEDaRKT_RKT0_ENKUlSD_E_clIS7_EEDaSD_
224
546k
}
_ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EES7_EEDaRKT_RKT0_
Line
Count
Source
222
1.61k
{
223
1.61k
    return Join(container, separator, [](const auto& i) { return i; });
224
1.61k
}
_ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA3_cEEDaRKT_RKT0_
Line
Count
Source
222
14.5k
{
223
14.5k
    return Join(container, separator, [](const auto& i) { return i; });
224
14.5k
}
_ZN4util4JoinISt6vectorI13bilingual_strSaIS2_EES2_EEDaRKT_RKT0_
Line
Count
Source
222
530k
{
223
530k
    return Join(container, separator, [](const auto& i) { return i; });
224
530k
}
Unexecuted instantiation: _ZN4util4JoinISt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS7_EEA2_cEEDaRKT_RKT0_
225
226
/**
227
 * Create an unordered multi-line list of items.
228
 */
229
inline std::string MakeUnorderedList(const std::vector<std::string>& items)
230
34
{
231
204
    return Join(items, "\n", [](const std::string& item) { return "- " + item; });
232
34
}
233
234
/**
235
 * Check if a string does not contain any embedded NUL (\0) characters
236
 */
237
[[nodiscard]] inline bool ContainsNoNUL(std::string_view str) noexcept
238
1.69M
{
239
108M
    for (auto c : str) {
  Branch (239:17): [True: 108M, False: 1.48M]
240
108M
        if (c == 0) return false;
  Branch (240:13): [True: 204k, False: 107M]
241
108M
    }
242
1.48M
    return true;
243
1.69M
}
244
245
/**
246
 * Locale-independent version of std::to_string
247
 */
248
template <typename T>
249
std::string ToString(const T& t)
250
220k
{
251
220k
    std::ostringstream oss;
252
220k
    oss.imbue(std::locale::classic());
253
220k
    oss << t;
254
220k
    return oss.str();
255
220k
}
_ZN4util8ToStringIlEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_
Line
Count
Source
250
2.75k
{
251
2.75k
    std::ostringstream oss;
252
2.75k
    oss.imbue(std::locale::classic());
253
2.75k
    oss << t;
254
2.75k
    return oss.str();
255
2.75k
}
_ZN4util8ToStringIjEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_
Line
Count
Source
250
207k
{
251
207k
    std::ostringstream oss;
252
207k
    oss.imbue(std::locale::classic());
253
207k
    oss << t;
254
207k
    return oss.str();
255
207k
}
_ZN4util8ToStringImEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_
Line
Count
Source
250
7.77k
{
251
7.77k
    std::ostringstream oss;
252
7.77k
    oss.imbue(std::locale::classic());
253
7.77k
    oss << t;
254
7.77k
    return oss.str();
255
7.77k
}
_ZN4util8ToStringIiEENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKT_
Line
Count
Source
250
2.83k
{
251
2.83k
    std::ostringstream oss;
252
2.83k
    oss.imbue(std::locale::classic());
253
2.83k
    oss << t;
254
2.83k
    return oss.str();
255
2.83k
}
256
257
/**
258
 * Check whether a container begins with the given prefix.
259
 */
260
template <typename T1, size_t PREFIX_LEN>
261
[[nodiscard]] inline bool HasPrefix(const T1& obj,
262
                                const std::array<uint8_t, PREFIX_LEN>& prefix)
263
1.53G
{
264
1.53G
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 25.5M, False: 0]
  Branch (264:12): [True: 157M, False: 0]
  Branch (264:12): [True: 1.09M, False: 0]
  Branch (264:12): [True: 2.17M, False: 0]
  Branch (264:12): [True: 186M, False: 0]
  Branch (264:12): [True: 701M, False: 0]
  Branch (264:12): [True: 283M, False: 0]
  Branch (264:12): [True: 181M, False: 0]
265
1.53G
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 37.1k, False: 25.4M]
  Branch (265:12): [True: 148k, False: 157M]
  Branch (265:12): [True: 5.88k, False: 1.09M]
  Branch (265:12): [True: 9.67k, False: 2.16M]
  Branch (265:12): [True: 76.2k, False: 186M]
  Branch (265:12): [True: 2.10M, False: 699M]
  Branch (265:12): [True: 107k, False: 283M]
  Branch (265:12): [True: 27.5k, False: 181M]
266
1.53G
}
_ZN4util9HasPrefixI9prevectorILj16EhjiELm6EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
25.5M
{
264
25.5M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 25.5M, False: 0]
265
25.5M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 37.1k, False: 25.4M]
266
25.5M
}
_ZN4util9HasPrefixI9prevectorILj16EhjiELm12EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
157M
{
264
157M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 157M, False: 0]
265
157M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 148k, False: 157M]
266
157M
}
_ZN4util9HasPrefixISt4spanIKhLm18446744073709551615EELm12EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
1.09M
{
264
1.09M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 1.09M, False: 0]
265
1.09M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 5.88k, False: 1.09M]
266
1.09M
}
_ZN4util9HasPrefixISt4spanIKhLm18446744073709551615EELm6EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
2.17M
{
264
2.17M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 2.17M, False: 0]
265
2.17M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 9.67k, False: 2.16M]
266
2.17M
}
_ZN4util9HasPrefixI9prevectorILj16EhjiELm2EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
186M
{
264
186M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 186M, False: 0]
265
186M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 76.2k, False: 186M]
266
186M
}
_ZN4util9HasPrefixI9prevectorILj16EhjiELm3EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
701M
{
264
701M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 701M, False: 0]
265
701M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 2.10M, False: 699M]
266
701M
}
_ZN4util9HasPrefixI9prevectorILj16EhjiELm4EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
283M
{
264
283M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 283M, False: 0]
265
283M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 107k, False: 283M]
266
283M
}
_ZN4util9HasPrefixI9prevectorILj16EhjiELm8EEEbRKT_RKSt5arrayIhXT0_EE
Line
Count
Source
263
181M
{
264
181M
    return obj.size() >= PREFIX_LEN &&
  Branch (264:12): [True: 181M, False: 0]
265
181M
           std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
  Branch (265:12): [True: 27.5k, False: 181M]
266
181M
}
267
268
class LineReader
269
{
270
    const std::string_view m_str;
271
    const size_t m_max_line_length;
272
    std::string_view::iterator m_it;
273
274
public:
275
    explicit LineReader(std::string_view str, size_t max_line_length);
276
277
    /**
278
     * Returns a string from current iterator position up to (but not including) next \n
279
     * and advances iterator to the character following the \n on success.
280
     * Will not return a line longer than max_line_length.
281
     * @returns the next string from the buffer.
282
     *          std::nullopt if end of buffer is reached without finding a \n.
283
     * @throws a std::runtime_error if max_line_length + 1 bytes are read without finding \n.
284
     */
285
    std::optional<std::string_view> ReadLine() LIFETIMEBOUND;
286
287
    /**
288
     * Returns string from current iterator position of specified length
289
     * if possible and advances iterator on success.
290
     * May exceed max_line_length but will not read past end of buffer.
291
     * @param[in]   len     The number of bytes to read from the buffer
292
     * @returns a string of the expected length.
293
     * @throws a std::runtime_error if there is not enough data in the buffer.
294
     */
295
    std::string_view ReadLength(size_t len) LIFETIMEBOUND;
296
297
    /**
298
     * Returns remaining size of bytes in buffer
299
     */
300
    size_t Remaining() const;
301
302
    /**
303
     * Returns number of bytes already read from buffer
304
     */
305
    size_t Consumed() const;
306
};
307
} // namespace util
308
309
#endif // BITCOIN_UTIL_STRING_H