Bitcoin Core 29.99.0
P2P Digital Currency
string.h
Go to the documentation of this file.
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 <span.h>
9
10#include <array>
11#include <cstdint>
12#include <cstring>
13#include <locale>
14#include <sstream>
15#include <string> // IWYU pragma: export
16#include <string_view> // IWYU pragma: export
17#include <vector>
18
19namespace util {
20namespace detail {
21template <unsigned num_params>
22constexpr static void CheckNumFormatSpecifiers(const char* str)
23{
24 unsigned count_normal{0}; // Number of "normal" specifiers, like %s
25 unsigned count_pos{0}; // Max number in positional specifier, like %8$s
26 for (auto it{str}; *it != '\0'; ++it) {
27 if (*it != '%' || *++it == '%') continue; // Skip escaped %%
28
29 auto add_arg = [&] {
30 unsigned maybe_num{0};
31 while ('0' <= *it && *it <= '9') {
32 maybe_num *= 10;
33 maybe_num += *it - '0';
34 ++it;
35 }
36
37 if (*it == '$') {
38 ++it;
39 // Positional specifier, like %8$s
40 if (maybe_num == 0) throw "Positional format specifier must have position of at least 1";
41 count_pos = std::max(count_pos, maybe_num);
42 } else {
43 // Non-positional specifier, like %s
44 ++count_normal;
45 }
46 };
47
48 // Increase argument count and consume positional specifier, if present.
49 add_arg();
50
51 // Consume flags.
52 while (*it == '#' || *it == '0' || *it == '-' || *it == ' ' || *it == '+') ++it;
53
54 auto parse_size = [&] {
55 if (*it == '*') {
56 ++it;
57 add_arg();
58 } else {
59 while ('0' <= *it && *it <= '9') ++it;
60 }
61 };
62
63 // Consume dynamic or static width value.
64 parse_size();
65
66 // Consume dynamic or static precision value.
67 if (*it == '.') {
68 ++it;
69 parse_size();
70 }
71
72 if (*it == '\0') throw "Format specifier incorrectly terminated by end of string";
73
74 // Length and type in "[flags][width][.precision][length]type"
75 // is not checked. Parsing continues with the next '%'.
76 }
77 if (count_normal && count_pos) throw "Format specifiers must be all positional or all non-positional!";
78 unsigned count{count_normal | count_pos};
79 if (num_params != count) throw "Format specifier count must match the argument count!";
80}
81} // namespace detail
82
91template <unsigned num_params>
93 const char* const fmt;
94 consteval ConstevalFormatString(const char* str) : fmt{str} { detail::CheckNumFormatSpecifiers<num_params>(fmt); }
95};
96
97void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute);
98
114template <typename T = std::span<const char>>
115std::vector<T> Split(const std::span<const char>& sp, std::string_view separators, bool include_sep = false)
116{
117 std::vector<T> ret;
118 auto it = sp.begin();
119 auto start = it;
120 while (it != sp.end()) {
121 if (separators.find(*it) != std::string::npos) {
122 if (include_sep) {
123 ret.emplace_back(start, it + 1);
124 } else {
125 ret.emplace_back(start, it);
126 }
127 start = it + 1;
128 }
129 ++it;
130 }
131 ret.emplace_back(start, it);
132 return ret;
133}
134
142template <typename T = std::span<const char>>
143std::vector<T> Split(const std::span<const char>& sp, char sep, bool include_sep = false)
144{
145 return Split<T>(sp, std::string_view{&sep, 1}, include_sep);
146}
147
148[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, char sep)
149{
150 return Split<std::string>(str, sep);
151}
152
153[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, std::string_view separators)
154{
155 return Split<std::string>(str, separators);
156}
157
158[[nodiscard]] inline std::string_view TrimStringView(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
159{
160 std::string::size_type front = str.find_first_not_of(pattern);
161 if (front == std::string::npos) {
162 return {};
163 }
164 std::string::size_type end = str.find_last_not_of(pattern);
165 return str.substr(front, end - front + 1);
166}
167
168[[nodiscard]] inline std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
169{
170 return std::string(TrimStringView(str, pattern));
171}
172
173[[nodiscard]] inline std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
174{
175 if (str.ends_with(suffix)) {
176 return str.substr(0, str.size() - suffix.size());
177 }
178 return str;
179}
180
181[[nodiscard]] inline std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
182{
183 if (str.starts_with(prefix)) {
184 return str.substr(prefix.size());
185 }
186 return str;
187}
188
189[[nodiscard]] inline std::string RemovePrefix(std::string_view str, std::string_view prefix)
190{
191 return std::string(RemovePrefixView(str, prefix));
192}
193
202template <typename C, typename S, typename UnaryOp>
203// NOLINTNEXTLINE(misc-no-recursion)
204auto Join(const C& container, const S& separator, UnaryOp unary_op)
205{
206 decltype(unary_op(*container.begin())) ret;
207 bool first{true};
208 for (const auto& item : container) {
209 if (!first) ret += separator;
210 ret += unary_op(item);
211 first = false;
212 }
213 return ret;
214}
215
216template <typename C, typename S>
217auto Join(const C& container, const S& separator)
218{
219 return Join(container, separator, [](const auto& i) { return i; });
220}
221
225inline std::string MakeUnorderedList(const std::vector<std::string>& items)
226{
227 return Join(items, "\n", [](const std::string& item) { return "- " + item; });
228}
229
233[[nodiscard]] inline bool ContainsNoNUL(std::string_view str) noexcept
234{
235 for (auto c : str) {
236 if (c == 0) return false;
237 }
238 return true;
239}
240
244template <typename T>
245std::string ToString(const T& t)
246{
247 std::ostringstream oss;
248 oss.imbue(std::locale::classic());
249 oss << t;
250 return oss.str();
251}
252
256template <typename T1, size_t PREFIX_LEN>
257[[nodiscard]] inline bool HasPrefix(const T1& obj,
258 const std::array<uint8_t, PREFIX_LEN>& prefix)
259{
260 return obj.size() >= PREFIX_LEN &&
261 std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
262}
263} // namespace util
264
265#endif // BITCOIN_UTIL_STRING_H
int ret
static constexpr void CheckNumFormatSpecifiers(const char *str)
Definition: string.h:22
std::vector< std::string > SplitString(std::string_view str, char sep)
Definition: string.h:148
bool HasPrefix(const T1 &obj, const std::array< uint8_t, PREFIX_LEN > &prefix)
Check whether a container begins with the given prefix.
Definition: string.h:257
std::string_view TrimStringView(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:158
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
Definition: string.h:225
std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
Definition: string.h:173
std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
Definition: string.h:181
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:245
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:168
std::string RemovePrefix(std::string_view str, std::string_view prefix)
Definition: string.h:189
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
Definition: string.h:204
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:233
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition: string.cpp:11
std::vector< T > Split(const std::span< const char > &sp, std::string_view separators, bool include_sep=false)
Split a string on any char found in separators, returning a vector.
Definition: string.h:115
#define S(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
const char * prefix
Definition: rest.cpp:1117
A wrapper for a compile-time partially validated format string.
Definition: string.h:92
consteval ConstevalFormatString(const char *str)
Definition: string.h:94
const char *const fmt
Definition: string.h:93
static int count