strencodings.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-2022 The Limenka 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 LIMENKA_UTIL_STRENCODINGS_H
  10  #define LIMENKA_UTIL_STRENCODINGS_H
  11  
  12  #include <crypto/hex_base.h> // IWYU pragma: export
  13  #include <span.h>
  14  #include <util/string.h>
  15  
  16  #include <array>
  17  #include <bit>
  18  #include <charconv>
  19  #include <cstddef>
  20  #include <cstdint>
  21  #include <limits>
  22  #include <optional>
  23  #include <string>      // IWYU pragma: export
  24  #include <string_view> // IWYU pragma: export
  25  #include <system_error>
  26  #include <type_traits>
  27  #include <vector>
  28  
  29  /** Used by SanitizeString() */
  30  enum SafeChars
  31  {
  32      SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
  33      SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
  34      SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
  35      SAFE_CHARS_URI, //!< Chars allowed in URIs (RFC 3986)
  36      SAFE_CHARS_PRINTABLE, //!< The full set of printable chars
  37  };
  38  
  39  /**
  40   * Used by ParseByteUnits()
  41   * Lowercase base 1000
  42   * Uppercase base 1024
  43  */
  44  enum class ByteUnit : uint64_t {
  45      NOOP = 1ULL,
  46      k = 1000ULL,
  47      K = 1024ULL,
  48      m = 1'000'000ULL,
  49      M = 1ULL << 20,
  50      g = 1'000'000'000ULL,
  51      G = 1ULL << 30,
  52      t = 1'000'000'000'000ULL,
  53      T = 1ULL << 40,
  54  };
  55  
  56  /**
  57  * Remove unsafe chars. Safe chars chosen to allow simple messages/URLs/email
  58  * addresses, but avoid anything even possibly remotely dangerous like & or >
  59  * @param[in] str    The string to sanitize
  60  * @param[in] rule   The set of safe chars to choose (default: least restrictive)
  61  * @return           A new string without unsafe chars
  62  */
  63  std::string SanitizeString(std::string_view str, int rule = SAFE_CHARS_DEFAULT, bool escape = false);
  64  /** Parse the hex string into bytes (uint8_t or std::byte). Ignores whitespace. Returns nullopt on invalid input. */
  65  template <typename Byte = std::byte>
  66  std::optional<std::vector<Byte>> TryParseHex(std::string_view str);
  67  /** Like TryParseHex, but returns an empty vector on invalid input. */
  68  template <typename Byte = uint8_t>
  69  std::vector<Byte> ParseHex(std::string_view hex_str)
  70  {
  71      return TryParseHex<Byte>(hex_str).value_or(std::vector<Byte>{});
  72  }
  73  /* Returns true if each character in str is a hex character, and has an even
  74   * number of hex digits.*/
  75  bool IsHex(std::string_view str);
  76  std::optional<std::vector<unsigned char>> DecodeBase64(std::string_view str);
  77  std::string EncodeBase64(Span<const unsigned char> input);
  78  inline std::string EncodeBase64(Span<const std::byte> input) { return EncodeBase64(MakeUCharSpan(input)); }
  79  inline std::string EncodeBase64(std::string_view str) { return EncodeBase64(MakeUCharSpan(str)); }
  80  std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str);
  81  
  82  /**
  83   * Base32 encode.
  84   * If `pad` is true, then the output will be padded with '=' so that its length
  85   * is a multiple of 8.
  86   */
  87  std::string EncodeBase32(Span<const unsigned char> input, bool pad = true);
  88  
  89  /**
  90   * Base32 encode.
  91   * If `pad` is true, then the output will be padded with '=' so that its length
  92   * is a multiple of 8.
  93   */
  94  std::string EncodeBase32(std::string_view str, bool pad = true);
  95  
  96  /**
  97   * Splits socket address string into host string and port value.
  98   * Validates port value.
  99   *
 100   * @param[in] in        The socket address string to split.
 101   * @param[out] portOut  Port-portion of the input, if found and parsable.
 102   * @param[out] hostOut  Host-portion of the input, if found.
 103   * @return              true if port-portion is absent or within its allowed range, otherwise false
 104   */
 105  bool SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut);
 106  
 107  // LocaleIndependentAtoi is provided for backwards compatibility reasons.
 108  //
 109  // New code should use ToIntegral or the ParseInt* functions
 110  // which provide parse error feedback.
 111  //
 112  // The goal of LocaleIndependentAtoi is to replicate the defined behaviour of
 113  // std::atoi as it behaves under the "C" locale, and remove some undefined
 114  // behavior. If the parsed value is bigger than the integer type's maximum
 115  // value, or smaller than the integer type's minimum value, std::atoi has
 116  // undefined behavior, while this function returns the maximum or minimum
 117  // values, respectively.
 118  template <typename T>
 119  T LocaleIndependentAtoi(std::string_view str)
 120  {
 121      static_assert(std::is_integral<T>::value);
 122      T result;
 123      // Emulate atoi(...) handling of white space and leading +/-.
 124      std::string_view s = util::TrimStringView(str);
 125      if (!s.empty() && s[0] == '+') {
 126          if (s.length() >= 2 && s[1] == '-') {
 127              return 0;
 128          }
 129          s = s.substr(1);
 130      }
 131      auto [_, error_condition] = std::from_chars(s.data(), s.data() + s.size(), result);
 132      if (error_condition == std::errc::result_out_of_range) {
 133          if (s.length() >= 1 && s[0] == '-') {
 134              // Saturate underflow, per strtoll's behavior.
 135              return std::numeric_limits<T>::min();
 136          } else {
 137              // Saturate overflow, per strtoll's behavior.
 138              return std::numeric_limits<T>::max();
 139          }
 140      } else if (error_condition != std::errc{}) {
 141          return 0;
 142      }
 143      return result;
 144  }
 145  
 146  /**
 147   * Tests if the given character is a decimal digit.
 148   * @param[in] c     character to test
 149   * @return          true if the argument is a decimal digit; otherwise false.
 150   */
 151  constexpr bool IsDigit(char c)
 152  {
 153      return c >= '0' && c <= '9';
 154  }
 155  
 156  /**
 157   * Tests if the given character is a whitespace character. The whitespace characters
 158   * are: space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
 159   * tab ('\t'), and vertical tab ('\v').
 160   *
 161   * This function is locale independent. Under the C locale this function gives the
 162   * same result as std::isspace.
 163   *
 164   * @param[in] c     character to test
 165   * @return          true if the argument is a whitespace character; otherwise false
 166   */
 167  constexpr inline bool IsSpace(const char c) noexcept {
 168      return c <= ' ' && (c == ' ' || (c >= '\t' && c <= '\r'));
 169  }
 170  
 171  /**
 172   * Convert string to integral type T. Leading whitespace, a leading +, or any
 173   * trailing character fail the parsing. The required format expressed as regex
 174   * is `-?[0-9]+`. The minus sign is only permitted for signed integer types.
 175   *
 176   * @returns std::nullopt if the entire string could not be parsed, or if the
 177   *   parsed value is not in the range representable by the type T.
 178   */
 179  template <typename T>
 180  std::optional<T> ToIntegral(std::string_view str)
 181  {
 182      static_assert(std::is_integral<T>::value);
 183      T result;
 184      const auto [first_nonmatching, error_condition] = std::from_chars(str.data(), str.data() + str.size(), result);
 185      if (first_nonmatching != str.data() + str.size() || error_condition != std::errc{}) {
 186          return std::nullopt;
 187      }
 188      return result;
 189  }
 190  
 191  /**
 192   * Convert string to signed 32-bit integer with strict parse error feedback.
 193   * @returns true if the entire string could be parsed as valid integer,
 194   *   false if not the entire string could be parsed or when overflow or underflow occurred.
 195   */
 196  [[nodiscard]] bool ParseInt32(std::string_view str, int32_t *out);
 197  
 198  /**
 199   * Convert string to signed 64-bit integer with strict parse error feedback.
 200   * @returns true if the entire string could be parsed as valid integer,
 201   *   false if not the entire string could be parsed or when overflow or underflow occurred.
 202   */
 203  [[nodiscard]] bool ParseInt64(std::string_view str, int64_t *out);
 204  
 205  /**
 206   * Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
 207   * @returns true if the entire string could be parsed as valid integer,
 208   *   false if not the entire string could be parsed or when overflow or underflow occurred.
 209   */
 210  [[nodiscard]] bool ParseUInt8(std::string_view str, uint8_t *out);
 211  
 212  /**
 213   * Convert decimal string to unsigned 16-bit integer with strict parse error feedback.
 214   * @returns true if the entire string could be parsed as valid integer,
 215   *   false if the entire string could not be parsed or if overflow or underflow occurred.
 216   */
 217  [[nodiscard]] bool ParseUInt16(std::string_view str, uint16_t* out);
 218  
 219  /**
 220   * Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
 221   * @returns true if the entire string could be parsed as valid integer,
 222   *   false if not the entire string could be parsed or when overflow or underflow occurred.
 223   */
 224  [[nodiscard]] bool ParseUInt32(std::string_view str, uint32_t *out);
 225  
 226  /**
 227   * Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
 228   * @returns true if the entire string could be parsed as valid integer,
 229   *   false if not the entire string could be parsed or when overflow or underflow occurred.
 230   */
 231  [[nodiscard]] bool ParseUInt64(std::string_view str, uint64_t *out);
 232  
 233  /**
 234   * Format a paragraph of text to a fixed width, adding spaces for
 235   * indentation to any added line.
 236   */
 237  std::string FormatParagraph(std::string_view in, size_t width = 79, size_t indent = 0);
 238  
 239  /**
 240   * Timing-attack-resistant comparison.
 241   * Takes time proportional to length
 242   * of first argument.
 243   */
 244  template <typename T>
 245  bool TimingResistantEqual(const T& a, const T& b)
 246  {
 247      if (b.size() == 0) return a.size() == 0;
 248      size_t accumulator = a.size() ^ b.size();
 249      for (size_t i = 0; i < a.size(); i++)
 250          accumulator |= size_t(a[i] ^ b[i%b.size()]);
 251      return accumulator == 0;
 252  }
 253  
 254  /** Parse number as fixed point according to JSON number syntax.
 255   * @returns true on success, false on error.
 256   * @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
 257   */
 258  [[nodiscard]] bool ParseFixedPoint(std::string_view, int decimals, int64_t *amount_out);
 259  
 260  namespace {
 261  /** Helper class for the default infn argument to ConvertBits (just returns the input). */
 262  struct IntIdentity
 263  {
 264      [[maybe_unused]] int operator()(int x) const { return x; }
 265  };
 266  
 267  } // namespace
 268  
 269  /** Convert from one power-of-2 number base to another. */
 270  template<int frombits, int tobits, bool pad, typename O, typename It, typename I = IntIdentity>
 271  bool ConvertBits(O outfn, It it, It end, I infn = {}) {
 272      size_t acc = 0;
 273      size_t bits = 0;
 274      constexpr size_t maxv = (1 << tobits) - 1;
 275      constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
 276      while (it != end) {
 277          int v = infn(*it);
 278          if (v < 0) return false;
 279          acc = ((acc << frombits) | v) & max_acc;
 280          bits += frombits;
 281          while (bits >= tobits) {
 282              bits -= tobits;
 283              outfn((acc >> bits) & maxv);
 284          }
 285          ++it;
 286      }
 287      if (pad) {
 288          if (bits) outfn((acc << (tobits - bits)) & maxv);
 289      } else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
 290          return false;
 291      }
 292      return true;
 293  }
 294  
 295  /**
 296   * Converts the given character to its lowercase equivalent.
 297   * This function is locale independent. It only converts uppercase
 298   * characters in the standard 7-bit ASCII range.
 299   * This is a feature, not a limitation.
 300   *
 301   * @param[in] c     the character to convert to lowercase.
 302   * @return          the lowercase equivalent of c; or the argument
 303   *                  if no conversion is possible.
 304   */
 305  constexpr char ToLower(char c)
 306  {
 307      return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
 308  }
 309  
 310  /**
 311   * Returns the lowercase equivalent of the given string.
 312   * This function is locale independent. It only converts uppercase
 313   * characters in the standard 7-bit ASCII range.
 314   * This is a feature, not a limitation.
 315   *
 316   * @param[in] str   the string to convert to lowercase.
 317   * @returns         lowercased equivalent of str
 318   */
 319  std::string ToLower(std::string_view str);
 320  
 321  /**
 322   * Converts the given character to its uppercase equivalent.
 323   * This function is locale independent. It only converts lowercase
 324   * characters in the standard 7-bit ASCII range.
 325   * This is a feature, not a limitation.
 326   *
 327   * @param[in] c     the character to convert to uppercase.
 328   * @return          the uppercase equivalent of c; or the argument
 329   *                  if no conversion is possible.
 330   */
 331  constexpr char ToUpper(char c)
 332  {
 333      return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
 334  }
 335  
 336  /**
 337   * Returns the uppercase equivalent of the given string.
 338   * This function is locale independent. It only converts lowercase
 339   * characters in the standard 7-bit ASCII range.
 340   * This is a feature, not a limitation.
 341   *
 342   * @param[in] str   the string to convert to uppercase.
 343   * @returns         UPPERCASED EQUIVALENT OF str
 344   */
 345  std::string ToUpper(std::string_view str);
 346  
 347  /**
 348   * Capitalizes the first character of the given string.
 349   * This function is locale independent. It only converts lowercase
 350   * characters in the standard 7-bit ASCII range.
 351   * This is a feature, not a limitation.
 352   *
 353   * @param[in] str   the string to capitalize.
 354   * @returns         string with the first letter capitalized.
 355   */
 356  std::string Capitalize(std::string str);
 357  
 358  /**
 359   * Parse a string with suffix unit [k|K|m|M|g|G|t|T].
 360   * Must be a whole integer, fractions not allowed (0.5t), no whitespace or +-
 361   * Lowercase units are 1000 base. Uppercase units are 1024 base.
 362   * Examples: 2m,27M,19g,41T
 363   *
 364   * @param[in] str                  the string to convert into bytes
 365   * @param[in] default_multiplier   if no unit is found in str use this unit
 366   * @returns                        optional uint64_t bytes from str or nullopt
 367   *                                 if ToIntegral is false, str is empty, trailing whitespace or overflow
 368   */
 369  std::optional<uint64_t> ParseByteUnits(std::string_view str, ByteUnit default_multiplier);
 370  
 371  namespace util {
 372  /** consteval version of HexDigit() without the lookup table. */
 373  consteval uint8_t ConstevalHexDigit(const char c)
 374  {
 375      if (c >= '0' && c <= '9') return c - '0';
 376      if (c >= 'a' && c <= 'f') return c - 'a' + 0xa;
 377  
 378      throw "Only lowercase hex digits are allowed, for consistency";
 379  }
 380  
 381  namespace detail {
 382  template <size_t N>
 383  struct Hex {
 384      std::array<std::byte, N / 2> bytes{};
 385      consteval Hex(const char (&hex_str)[N])
 386          // 2 hex digits required per byte + implicit null terminator
 387          requires(N % 2 == 1)
 388      {
 389          if (hex_str[N - 1]) throw "null terminator required";
 390          for (std::size_t i = 0; i < bytes.size(); ++i) {
 391              bytes[i] = static_cast<std::byte>(
 392                  (ConstevalHexDigit(hex_str[2 * i]) << 4) |
 393                   ConstevalHexDigit(hex_str[2 * i + 1]));
 394          }
 395      }
 396  };
 397  } // namespace detail
 398  
 399  /**
 400   * ""_hex is a compile-time user-defined literal returning a
 401   * `std::array<std::byte>`, equivalent to ParseHex(). Variants provided:
 402   *
 403   * - ""_hex_v: Returns `std::vector<std::byte>`, useful for heap allocation or
 404   *   variable-length serialization.
 405   *
 406   * - ""_hex_u8: Returns `std::array<uint8_t>`, for cases where `std::byte` is
 407   *   incompatible.
 408   *
 409   * - ""_hex_v_u8: Returns `std::vector<uint8_t>`, combining heap allocation with
 410   *   `uint8_t`.
 411   *
 412   * @warning It could be necessary to use vector instead of array variants when
 413   *   serializing, or vice versa, because vectors are assumed to be variable-
 414   *   length and serialized with a size prefix, while arrays are considered fixed
 415   *   length and serialized with no prefix.
 416   *
 417   * @warning It may be preferable to use vector variants to save stack space when
 418   *   declaring local variables if hex strings are large. Alternatively variables
 419   *   could be declared constexpr to avoid using stack space.
 420   *
 421   * @warning Avoid `uint8_t` variants when not necessary, as the codebase
 422   *   migrates to use `std::byte` instead of `unsigned char` and `uint8_t`.
 423   *
 424   * @note One reason ""_hex uses `std::array` instead of `std::vector` like
 425   *   ParseHex() does is because heap-based containers cannot cross the compile-
 426   *   time/runtime barrier.
 427   */
 428  inline namespace hex_literals {
 429  
 430  template <util::detail::Hex str>
 431  constexpr auto operator""_hex() { return str.bytes; }
 432  
 433  template <util::detail::Hex str>
 434  constexpr auto operator""_hex_u8() { return std::bit_cast<std::array<uint8_t, str.bytes.size()>>(str.bytes); }
 435  
 436  template <util::detail::Hex str>
 437  constexpr auto operator""_hex_v() { return std::vector<std::byte>{str.bytes.begin(), str.bytes.end()}; }
 438  
 439  template <util::detail::Hex str>
 440  inline auto operator""_hex_v_u8() { return std::vector<uint8_t>{UCharCast(str.bytes.data()), UCharCast(str.bytes.data() + str.bytes.size())}; }
 441  
 442  } // inline namespace hex_literals
 443  } // namespace util
 444  
 445  #endif // LIMENKA_UTIL_STRENCODINGS_H
 446