Branch data Line data Source code
1 : : // Copyright (c) 2019-2022 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 <util/spanparsing.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 : :
19 : : void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute);
20 : :
21 : 368 : [[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, char sep)
22 : : {
23 : 368 : return spanparsing::Split<std::string>(str, sep);
24 : : }
25 : :
26 : 0 : [[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, std::string_view separators)
27 : : {
28 : 0 : return spanparsing::Split<std::string>(str, separators);
29 : : }
30 : :
31 : 4 : [[nodiscard]] inline std::string_view TrimStringView(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
32 : : {
33 : 4 : std::string::size_type front = str.find_first_not_of(pattern);
34 [ - + ]: 4 : if (front == std::string::npos) {
35 : 0 : return {};
36 : : }
37 : 4 : std::string::size_type end = str.find_last_not_of(pattern);
38 : 4 : return str.substr(front, end - front + 1);
39 : 4 : }
40 : :
41 : 0 : [[nodiscard]] inline std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v")
42 : : {
43 [ # # ]: 0 : return std::string(TrimStringView(str, pattern));
44 : 0 : }
45 : :
46 : 1 : [[nodiscard]] inline std::string_view RemovePrefixView(std::string_view str, std::string_view prefix)
47 : : {
48 [ - + ]: 1 : if (str.substr(0, prefix.size()) == prefix) {
49 : 0 : return str.substr(prefix.size());
50 : : }
51 : 1 : return str;
52 : 1 : }
53 : :
54 : 1 : [[nodiscard]] inline std::string RemovePrefix(std::string_view str, std::string_view prefix)
55 : : {
56 [ + - ]: 1 : return std::string(RemovePrefixView(str, prefix));
57 : 0 : }
58 : :
59 : : /**
60 : : * Join all container items. Typically used to concatenate strings but accepts
61 : : * containers with elements of any type.
62 : : *
63 : : * @param container The items to join
64 : : * @param separator The separator
65 : : * @param unary_op Apply this operator to each item
66 : : */
67 : : template <typename C, typename S, typename UnaryOp>
68 : 43 : auto Join(const C& container, const S& separator, UnaryOp unary_op)
69 : : {
70 : 43 : decltype(unary_op(*container.begin())) ret;
71 : 43 : bool first{true};
72 [ + + ][ # # ]: 403 : for (const auto& item : container) {
73 [ + + ][ + - ]: 360 : if (!first) ret += separator;
[ # # ][ # # ]
74 [ + - ][ + - ]: 360 : ret += unary_op(item);
[ # # ][ # # ]
75 : 360 : first = false;
76 : : }
77 : 43 : return ret;
78 : 43 : }
79 : :
80 : : template <typename C, typename S>
81 : 33 : auto Join(const C& container, const S& separator)
82 : : {
83 : 255 : return Join(container, separator, [](const auto& i) { return i; });
84 : : }
85 : :
86 : : /**
87 : : * Create an unordered multi-line list of items.
88 : : */
89 : 2 : inline std::string MakeUnorderedList(const std::vector<std::string>& items)
90 : : {
91 : 14 : return Join(items, "\n", [](const std::string& item) { return "- " + item; });
92 : : }
93 : :
94 : : /**
95 : : * Check if a string does not contain any embedded NUL (\0) characters
96 : : */
97 : 576 : [[nodiscard]] inline bool ContainsNoNUL(std::string_view str) noexcept
98 : : {
99 [ + + ]: 6048 : for (auto c : str) {
100 [ - + ]: 5472 : if (c == 0) return false;
101 : : }
102 : 576 : return true;
103 : 576 : }
104 : :
105 : : /**
106 : : * Locale-independent version of std::to_string
107 : : */
108 : : template <typename T>
109 : 5 : std::string ToString(const T& t)
110 : : {
111 : 5 : std::ostringstream oss;
112 [ + - ][ + - ]: 5 : oss.imbue(std::locale::classic());
[ # # ][ # # ]
113 [ + - ][ # # ]: 5 : oss << t;
114 [ + - ][ # # ]: 5 : return oss.str();
115 : 5 : }
116 : :
117 : : /**
118 : : * Check whether a container begins with the given prefix.
119 : : */
120 : : template <typename T1, size_t PREFIX_LEN>
121 : 6433 : [[nodiscard]] inline bool HasPrefix(const T1& obj,
122 : : const std::array<uint8_t, PREFIX_LEN>& prefix)
123 : : {
124 [ - + ][ - + ]: 12866 : return obj.size() >= PREFIX_LEN &&
[ - + ][ - + ]
[ # # ][ # # ]
[ # # ]
125 : 6433 : std::equal(std::begin(prefix), std::end(prefix), std::begin(obj));
126 : : }
127 : :
128 : : #endif // BITCOIN_UTIL_STRING_H
|