Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2017-2022 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : /**
8 : * Utilities for converting data from/to strings.
9 : */
10 : #ifndef PIVX_UTILSTRENCODINGS_H
11 : #define PIVX_UTILSTRENCODINGS_H
12 :
13 : #include "support/allocators/secure.h"
14 : #include "span.h"
15 :
16 : #include <algorithm>
17 : #include <iterator>
18 : #include <stdint.h>
19 : #include <string>
20 : #include <vector>
21 :
22 : #define BEGIN(a) ((char*)&(a))
23 : #define END(a) ((char*)&((&(a))[1]))
24 : #define UBEGIN(a) ((unsigned char*)&(a))
25 : #define UEND(a) ((unsigned char*)&((&(a))[1]))
26 : #define ARRAYLEN(array) (sizeof(array) / sizeof((array)[0]))
27 :
28 : /** Used by SanitizeString() */
29 : enum SafeChars
30 : {
31 : SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
32 : SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
33 : SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
34 : };
35 :
36 : /**
37 : * Remove unsafe chars. Safe chars chosen to allow simple messages/URLs/email
38 : * addresses, but avoid anything even possibly remotely dangerous like & or >
39 : * @param[in] str The string to sanitize
40 : * @param[in] rule The set of safe chars to choose (default: least restrictive)
41 : * @return A new string without unsafe chars
42 : */
43 : std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT);
44 :
45 : /**
46 : * Check URL format for conformance for validity to a defined pattern
47 : * @param[in] strURL The string to be processed for validity
48 : * @param[in] strErr A string that will be loaded with any validation error message
49 : * @param[in] maxSize An unsigned int, defaulted to 64, to restrict the length
50 : * @return A bool, true if valid, false if not (reason in strErr)
51 : */
52 : bool validateURL(const std::string& strURL, std::string& strErr, unsigned int maxSize = 64);
53 : bool validateURL(const std::string& strURL);
54 :
55 : std::vector<unsigned char> ParseHex(const char* psz);
56 : std::vector<unsigned char> ParseHex(const std::string& str);
57 : signed char HexDigit(char c);
58 : bool IsHex(const std::string& str);
59 : std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = nullptr);
60 : std::string DecodeBase64(const std::string& str);
61 : std::string EncodeBase64(Span<const unsigned char> input);
62 : std::string EncodeBase64(const std::string& str);
63 : std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = nullptr);
64 : std::string DecodeBase32(const std::string& str);
65 :
66 : /**
67 : * Base32 encode.
68 : * If `pad` is true, then the output will be padded with '=' so that its length
69 : * is a multiple of 8.
70 : */
71 : std::string EncodeBase32(Span<const unsigned char> input, bool pad = true);
72 :
73 : /**
74 : * Base32 encode.
75 : * If `pad` is true, then the output will be padded with '=' so that its length
76 : * is a multiple of 8.
77 : */
78 : std::string EncodeBase32(const std::string& str, bool pad = true);
79 :
80 : std::string i64tostr(int64_t n);
81 : std::string itostr(int n);
82 : int64_t atoi64(const char* psz);
83 : int64_t atoi64(const std::string& str);
84 : int atoi(const std::string& str);
85 :
86 : /**
87 : * Tests if the given character is a decimal digit.
88 : * @param[in] c character to test
89 : * @return true if the argument is a decimal digit; otherwise false.
90 : */
91 82603 : constexpr bool IsDigit(char c)
92 : {
93 82603 : return c >= '0' && c <= '9';
94 : }
95 :
96 : /**
97 : * Convert string to signed 32-bit integer with strict parse error feedback.
98 : * @returns true if the entire string could be parsed as valid integer,
99 : * false if not the entire string could be parsed or when overflow or underflow occurred.
100 : */
101 : bool ParseInt32(const std::string& str, int32_t *out);
102 :
103 : /**
104 : * Convert string to signed 64-bit integer with strict parse error feedback.
105 : * @returns true if the entire string could be parsed as valid integer,
106 : * false if not the entire string could be parsed or when overflow or underflow occurred.
107 : */
108 : bool ParseInt64(const std::string& str, int64_t *out);
109 :
110 : /**
111 : * Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
112 : * @returns true if the entire string could be parsed as valid integer,
113 : * false if not the entire string could be parsed or when overflow or underflow occurred.
114 : */
115 : bool ParseUInt8(const std::string& str, uint8_t *out);
116 :
117 : /**
118 : * Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
119 : * @returns true if the entire string could be parsed as valid integer,
120 : * false if not the entire string could be parsed or when overflow or underflow occurred.
121 : */
122 : bool ParseUInt32(const std::string& str, uint32_t *out);
123 :
124 : /**
125 : * Convert string to double with strict parse error feedback.
126 : * @returns true if the entire string could be parsed as valid double,
127 : * false if not the entire string could be parsed or when overflow or underflow occurred.
128 : */
129 : bool ParseDouble(const std::string& str, double *out);
130 :
131 : /* Return iterator to first non zero element, or itend */
132 : template <typename T>
133 382 : T FindFirstNonZero(T itbegin, T itend)
134 : {
135 49123 : return std::find_if(itbegin, itend, [](unsigned char v) { return v != 0; });
136 : }
137 :
138 : /**
139 : * Convert a span of bytes to a lower-case hexadecimal string.
140 : */
141 : std::string HexStr(const Span<const uint8_t> s);
142 126408 : inline std::string HexStr(const Span<const char> s) { return HexStr(MakeUCharSpan(s)); }
143 :
144 : /** Reverse the endianness of a string */
145 9 : inline std::string ReverseEndianString(std::string in)
146 : {
147 9 : std::string out = "";
148 9 : unsigned int s = in.size();
149 67 : for (unsigned int i = 0; i < s; i += 2) {
150 116 : out += in.substr(s - i - 2, 2);
151 : }
152 :
153 9 : return out;
154 : }
155 :
156 : /**
157 : * Format a paragraph of text to a fixed width, adding spaces for
158 : * indentation to any added line.
159 : */
160 : std::string FormatParagraph(const std::string in, size_t width = 79, size_t indent = 0);
161 :
162 : /**
163 : * Timing-attack-resistant comparison.
164 : * Takes time proportional to length
165 : * of first argument.
166 : */
167 : template <typename T>
168 298228 : bool TimingResistantEqual(const T& a, const T& b)
169 : {
170 298228 : if (b.size() == 0) return a.size() == 0;
171 298224 : size_t accumulator = a.size() ^ b.size();
172 22660328 : for (size_t i = 0; i < a.size(); i++)
173 22362118 : accumulator |= a[i] ^ b[i % b.size()];
174 298224 : return accumulator == 0;
175 : }
176 :
177 : /**
178 : * Convert from one power-of-2 number base to another.
179 : *
180 : * Examples using ConvertBits<8, 5, true>():
181 : * 000000 -> 0000000000
182 : * 202020 -> 0400100200
183 : * 757575 -> 0e151a170a
184 : * abcdef -> 150f061e1e
185 : * ffffff -> 1f1f1f1f1e
186 : */
187 : template<int frombits, int tobits, bool pad, typename O, typename I>
188 327388 : bool ConvertBits(const O& outfn, I it, I end) {
189 327388 : size_t acc = 0;
190 327388 : size_t bits = 0;
191 327388 : constexpr size_t maxv = (1 << tobits) - 1;
192 327388 : constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
193 33075869 : while (it != end) {
194 32748465 : acc = ((acc << frombits) | *it) & max_acc;
195 32748465 : bits += frombits;
196 58341710 : while (bits >= tobits) {
197 25593240 : bits -= tobits;
198 25595335 : outfn((acc >> bits) & maxv);
199 : }
200 33074809 : ++it;
201 : }
202 : if (pad) {
203 19139 : if (bits) outfn((acc << (tobits - bits)) & maxv);
204 308249 : } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
205 1 : return false;
206 : }
207 : return true;
208 : }
209 :
210 :
211 : /** Parse number as fixed point according to JSON number syntax.
212 : * See http://json.org/number.gif
213 : * @returns true on success, false on error.
214 : * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
215 : */
216 : bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
217 :
218 : /**
219 : * Converts the given character to its lowercase equivalent.
220 : * This function is locale independent. It only converts uppercase
221 : * characters in the standard 7-bit ASCII range.
222 : * @param[in] c the character to convert to lowercase.
223 : * @return the lowercase equivalent of c; or the argument
224 : * if no conversion is possible.
225 : */
226 70 : constexpr unsigned char ToLower(unsigned char c)
227 : {
228 70 : return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
229 : }
230 :
231 : /**
232 : * Returns the lowercase equivalent of the given string.
233 : * This function is locale independent. It only converts uppercase
234 : * characters in the standard 7-bit ASCII range.
235 : * This is a feature, not a limitation.
236 : *
237 : * @param[in] str the string to convert to lowercase.
238 : * @returns lowercased equivalent of str
239 : */
240 : std::string ToLower(const std::string& str);
241 :
242 : /**
243 : * Converts the given string to its lowercase equivalent.
244 : * This function is locale independent. It only converts uppercase
245 : * characters in the standard 7-bit ASCII range.
246 : * @param[in,out] str the string to convert to lowercase.
247 : */
248 : void Downcase(std::string& str);
249 :
250 : /**
251 : * Converts the given character to its uppercase equivalent.
252 : * This function is locale independent. It only converts lowercase
253 : * characters in the standard 7-bit ASCII range.
254 : * @param[in] c the character to convert to uppercase.
255 : * @return the uppercase equivalent of c; or the argument
256 : * if no conversion is possible.
257 : */
258 20 : constexpr unsigned char ToUpper(unsigned char c)
259 : {
260 20 : return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
261 : }
262 :
263 : /**
264 : * Returns the uppercase equivalent of the given string.
265 : * This function is locale independent. It only converts lowercase
266 : * characters in the standard 7-bit ASCII range.
267 : * This is a feature, not a limitation.
268 : *
269 : * @param[in] str the string to convert to uppercase.
270 : * @returns UPPERCASED EQUIVALENT OF str
271 : */
272 : std::string ToUpper(const std::string& str);
273 :
274 : /**
275 : * Capitalizes the first character of the given string.
276 : * This function is locale independent. It only capitalizes the
277 : * first character of the argument if it has an uppercase equivalent
278 : * in the standard 7-bit ASCII range.
279 : * @param[in] str the string to capitalize.
280 : * @return string with the first letter capitalized.
281 : */
282 : std::string Capitalize(std::string str);
283 :
284 : /**
285 : * Checks for valid 4-byte UTF-8 encoding in a string
286 : * @param[in] str the string to check.
287 : * @return boolean. true for valid UTF-8 encoding.
288 : */
289 : bool IsValidUTF8(const std::string& str);
290 :
291 : #endif // PIVX_UTILSTRENCODINGS_H
|