Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2020 The Bitcoin Core developers 3 : // Distributed under the MIT software license, see the accompanying 4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : 6 : /** 7 : * Utilities for converting data from/to strings. 8 : */ 9 : #ifndef BITCOIN_UTIL_STRENCODINGS_H 10 : #define BITCOIN_UTIL_STRENCODINGS_H 11 : 12 : #include <attributes.h> 13 : #include <span.h> 14 : 15 : #include <cstdint> 16 : #include <iterator> 17 : #include <string> 18 : #include <vector> 19 : 20 : #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) 21 : 22 : /** Used by SanitizeString() */ 23 : enum SafeChars 24 : { 25 : SAFE_CHARS_DEFAULT, //!< The full set of allowed chars 26 : SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset 27 : SAFE_CHARS_FILENAME, //!< Chars allowed in filenames 28 : SAFE_CHARS_URI, //!< Chars allowed in URIs (RFC 3986) 29 : }; 30 : 31 : /** 32 : * Remove unsafe chars. Safe chars chosen to allow simple messages/URLs/email 33 : * addresses, but avoid anything even possibly remotely dangerous like & or > 34 : * @param[in] str The string to sanitize 35 : * @param[in] rule The set of safe chars to choose (default: least restrictive) 36 : * @return A new string without unsafe chars 37 : */ 38 : std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT); 39 : std::vector<unsigned char> ParseHex(const char* psz); 40 : std::vector<unsigned char> ParseHex(const std::string& str); 41 : signed char HexDigit(char c); 42 : /* Returns true if each character in str is a hex character, and has an even 43 : * number of hex digits.*/ 44 : bool IsHex(const std::string& str); 45 : /** 46 : * Return true if the string is a hex number, optionally prefixed with "0x" 47 : */ 48 : bool IsHexNumber(const std::string& str); 49 : std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid = nullptr); 50 : std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr); 51 : std::string EncodeBase64(Span<const unsigned char> input); 52 : std::string EncodeBase64(const std::string& str); 53 : std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid = nullptr); 54 : std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr); 55 : std::string EncodeBase32(Span<const unsigned char> input); 56 : std::string EncodeBase32(const std::string& str); 57 : 58 : void SplitHostPort(std::string in, int& portOut, std::string& hostOut); 59 : int64_t atoi64(const std::string& str); 60 : int atoi(const std::string& str); 61 : 62 : /** 63 : * Tests if the given character is a decimal digit. 64 : * @param[in] c character to test 65 : * @return true if the argument is a decimal digit; otherwise false. 66 : */ 67 509493 : constexpr bool IsDigit(char c) 68 : { 69 509493 : return c >= '0' && c <= '9'; 70 : } 71 : 72 : /** 73 : * Tests if the given character is a whitespace character. The whitespace characters 74 : * are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal 75 : * tab ('\t'), and vertical tab ('\v'). 76 : * 77 : * This function is locale independent. Under the C locale this function gives the 78 : * same result as std::isspace. 79 : * 80 : * @param[in] c character to test 81 : * @return true if the argument is a whitespace character; otherwise false 82 : */ 83 42531723 : constexpr inline bool IsSpace(char c) noexcept { 84 42531723 : return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; 85 : } 86 : 87 : /** 88 : * Convert string to signed 32-bit integer with strict parse error feedback. 89 : * @returns true if the entire string could be parsed as valid integer, 90 : * false if not the entire string could be parsed or when overflow or underflow occurred. 91 : */ 92 : NODISCARD bool ParseInt32(const std::string& str, int32_t *out); 93 : 94 : /** 95 : * Convert string to signed 64-bit integer with strict parse error feedback. 96 : * @returns true if the entire string could be parsed as valid integer, 97 : * false if not the entire string could be parsed or when overflow or underflow occurred. 98 : */ 99 : NODISCARD bool ParseInt64(const std::string& str, int64_t *out); 100 : 101 : /** 102 : * Convert decimal string to unsigned 8-bit integer with strict parse error feedback. 103 : * @returns true if the entire string could be parsed as valid integer, 104 : * false if not the entire string could be parsed or when overflow or underflow occurred. 105 : */ 106 : NODISCARD bool ParseUInt8(const std::string& str, uint8_t *out); 107 : 108 : /** 109 : * Convert decimal string to unsigned 32-bit integer with strict parse error feedback. 110 : * @returns true if the entire string could be parsed as valid integer, 111 : * false if not the entire string could be parsed or when overflow or underflow occurred. 112 : */ 113 : NODISCARD bool ParseUInt32(const std::string& str, uint32_t *out); 114 : 115 : /** 116 : * Convert decimal string to unsigned 64-bit integer with strict parse error feedback. 117 : * @returns true if the entire string could be parsed as valid integer, 118 : * false if not the entire string could be parsed or when overflow or underflow occurred. 119 : */ 120 : NODISCARD bool ParseUInt64(const std::string& str, uint64_t *out); 121 : 122 : /** 123 : * Convert string to double with strict parse error feedback. 124 : * @returns true if the entire string could be parsed as valid double, 125 : * false if not the entire string could be parsed or when overflow or underflow occurred. 126 : */ 127 : NODISCARD bool ParseDouble(const std::string& str, double *out); 128 : 129 : /** 130 : * Convert a span of bytes to a lower-case hexadecimal string. 131 : */ 132 : std::string HexStr(const Span<const uint8_t> s); 133 21387 : inline std::string HexStr(const Span<const char> s) { return HexStr(MakeUCharSpan(s)); } 134 : 135 : /** 136 : * Format a paragraph of text to a fixed width, adding spaces for 137 : * indentation to any added line. 138 : */ 139 : std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0); 140 : 141 : /** 142 : * Timing-attack-resistant comparison. 143 : * Takes time proportional to length 144 : * of first argument. 145 : */ 146 : template <typename T> 147 79126 : bool TimingResistantEqual(const T& a, const T& b) 148 : { 149 79126 : if (b.size() == 0) return a.size() == 0; 150 79122 : size_t accumulator = a.size() ^ b.size(); 151 6005448 : for (size_t i = 0; i < a.size(); i++) 152 5926326 : accumulator |= a[i] ^ b[i%b.size()]; 153 79122 : return accumulator == 0; 154 79126 : } 155 : 156 : /** Parse number as fixed point according to JSON number syntax. 157 : * See http://json.org/number.gif 158 : * @returns true on success, false on error. 159 : * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger. 160 : */ 161 : NODISCARD bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out); 162 : 163 : /** Convert from one power-of-2 number base to another. */ 164 : template<int frombits, int tobits, bool pad, typename O, typename I> 165 139381 : bool ConvertBits(const O& outfn, I it, I end) { 166 : size_t acc = 0; 167 : size_t bits = 0; 168 : constexpr size_t maxv = (1 << tobits) - 1; 169 : constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1; 170 10170937 : while (it != end) { 171 10031556 : acc = ((acc << frombits) | *it) & max_acc; 172 10031556 : bits += frombits; 173 18393667 : while (bits >= tobits) { 174 8362111 : bits -= tobits; 175 8362111 : outfn((acc >> bits) & maxv); 176 : } 177 10031556 : ++it; 178 : } 179 : if (pad) { 180 42940 : if (bits) outfn((acc << (tobits - bits)) & maxv); 181 96441 : } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) { 182 6 : return false; 183 : } 184 139375 : return true; 185 96441 : } 186 : 187 : /** 188 : * Converts the given character to its lowercase equivalent. 189 : * This function is locale independent. It only converts uppercase 190 : * characters in the standard 7-bit ASCII range. 191 : * This is a feature, not a limitation. 192 : * 193 : * @param[in] c the character to convert to lowercase. 194 : * @return the lowercase equivalent of c; or the argument 195 : * if no conversion is possible. 196 : */ 197 58324 : constexpr char ToLower(char c) 198 : { 199 58324 : return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c); 200 : } 201 : 202 : /** 203 : * Returns the lowercase equivalent of the given string. 204 : * This function is locale independent. It only converts uppercase 205 : * characters in the standard 7-bit ASCII range. 206 : * This is a feature, not a limitation. 207 : * 208 : * @param[in] str the string to convert to lowercase. 209 : * @returns lowercased equivalent of str 210 : */ 211 : std::string ToLower(const std::string& str); 212 : 213 : /** 214 : * Converts the given character to its uppercase equivalent. 215 : * This function is locale independent. It only converts lowercase 216 : * characters in the standard 7-bit ASCII range. 217 : * This is a feature, not a limitation. 218 : * 219 : * @param[in] c the character to convert to uppercase. 220 : * @return the uppercase equivalent of c; or the argument 221 : * if no conversion is possible. 222 : */ 223 1166 : constexpr char ToUpper(char c) 224 : { 225 1166 : return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c); 226 : } 227 : 228 : /** 229 : * Returns the uppercase equivalent of the given string. 230 : * This function is locale independent. It only converts lowercase 231 : * characters in the standard 7-bit ASCII range. 232 : * This is a feature, not a limitation. 233 : * 234 : * @param[in] str the string to convert to uppercase. 235 : * @returns UPPERCASED EQUIVALENT OF str 236 : */ 237 : std::string ToUpper(const std::string& str); 238 : 239 : /** 240 : * Capitalizes the first character of the given string. 241 : * This function is locale independent. It only converts lowercase 242 : * characters in the standard 7-bit ASCII range. 243 : * This is a feature, not a limitation. 244 : * 245 : * @param[in] str the string to capitalize. 246 : * @returns string with the first letter capitalized. 247 : */ 248 : std::string Capitalize(std::string str); 249 : 250 : #endif // BITCOIN_UTIL_STRENCODINGS_H