Bitcoin Core 28.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
106template <typename T = Span<const char>>
107std::vector<T> Split(const Span<const char>& sp, std::string_view separators)
108{
109 std::vector<T> ret;
110 auto it = sp.begin();
111 auto start = it;
112 while (it != sp.end()) {
113 if (separators.find(*it) != std::string::npos) {
114 ret.emplace_back(start, it);
115 start = it + 1;
116 }
117 ++it;
118 }
119 ret.emplace_back(start, it);
120 return ret;
121}
122
130template <typename T = Span<const char>>
131std::vector<T> Split(const Span<const char>& sp, char sep)
132{
133 return Split<T>(sp, std::string_view{&sep, 1});
134}
135
136[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, char sep)
137{
138 return Split<std::string>(str, sep);
139}
140
141[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, std::string_view separators)
142{
143 return Split<std::string>(str, separators);
144}
145
146[[nodiscard]] inline std::string_view TrimStringView(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
147{
148 std::string::size_type front = str.find_first_not_of(pattern);
149 if (front == std::string::npos) {
150 return {};
151 }
152 std::string::size_type end = str.find_last_not_of(pattern);
153 return str.substr(front, end - front + 1);
154}
155
156[[nodiscard]] inline std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
157{
158 return std::string(TrimStringView(str, pattern));
159}
160
161[[nodiscard]] inline std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
162{
163 if (str.ends_with(suffix)) {
164 return str.substr(0, str.size() - suffix.size());
165 }
166 return str;
167}
168
169[[nodiscard]] inline std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
170{
171 if (str.substr(0, prefix.size()) == prefix) {
172 return str.substr(prefix.size());
173 }
174 return str;
175}
176
177[[nodiscard]] inline std::string RemovePrefix(std::string_view str, std::string_view prefix)
178{
179 return std::string(RemovePrefixView(str, prefix));
180}
181
190template <typename C, typename S, typename UnaryOp>
191// NOLINTNEXTLINE(misc-no-recursion)
192auto Join(const C& container, const S& separator, UnaryOp unary_op)
193{
194 decltype(unary_op(*container.begin())) ret;
195 bool first{true};
196 for (const auto& item : container) {
197 if (!first) ret += separator;
198 ret += unary_op(item);
199 first = false;
200 }
201 return ret;
202}
203
204template <typename C, typename S>
205auto Join(const C& container, const S& separator)
206{
207 return Join(container, separator, [](const auto& i) { return i; });
208}
209
213inline std::string MakeUnorderedList(const std::vector<std::string>& items)
214{
215 return Join(items, "\n", [](const std::string& item) { return "- " + item; });
216}
217
221[[nodiscard]] inline bool ContainsNoNUL(std::string_view str) noexcept
222{
223 for (auto c : str) {
224 if (c == 0) return false;
225 }
226 return true;
227}
228
232template <typename T>
233std::string ToString(const T& t)
234{
235 std::ostringstream oss;
236 oss.imbue(std::locale::classic());
237 oss << t;
238 return oss.str();
239}
240
244template <typename T1, size_t PREFIX_LEN>
245[[nodiscard]] inline bool HasPrefix(const T1& obj,
246 const std::array<uint8_t, PREFIX_LEN>& prefix)
247{
248 return obj.size() >= PREFIX_LEN &&
249 std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
250}
251} // namespace util
252
253#endif // BITCOIN_UTIL_STRING_H
int ret
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
constexpr C * begin() const noexcept
Definition: span.h:175
constexpr C * end() const noexcept
Definition: span.h:176
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:136
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:245
std::string_view TrimStringView(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:146
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
Definition: string.h:213
std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
Definition: string.h:161
std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
Definition: string.h:169
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:233
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:156
std::string RemovePrefix(std::string_view str, std::string_view prefix)
Definition: string.h:177
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
Definition: string.h:192
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:221
std::vector< T > Split(const Span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
Definition: string.h:107
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition: string.cpp:11
#define S(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
const char * prefix
Definition: rest.cpp:1009
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