diff --git a/include/xrpl/basics/StringUtilities.h b/include/xrpl/basics/StringUtilities.h index 5f905638cb..12bf7b2f5f 100644 --- a/include/xrpl/basics/StringUtilities.h +++ b/include/xrpl/basics/StringUtilities.h @@ -27,9 +27,11 @@ #include #include +#include #include #include #include +#include namespace ripple { @@ -46,28 +48,40 @@ namespace ripple { std::string sqlBlobLiteral(Blob const& blob); +namespace impl { + +template +concept SomeChar = std::same_as, int8_t> || + std::same_as, char> || + std::same_as, uint8_t>; + +inline constexpr std::array, 256> DIGIT_LOOKUP_TABLE = []() { + std::array, 256> t{}; + + for (int i = 0; i < 10; ++i) + t['0' + i] = i; + + for (int i = 0; i < 6; ++i) + { + t['A' + i] = 10 + i; + t['a' + i] = 10 + i; + } + + return t; +}(); + +inline std::optional +hexCharToInt(SomeChar auto hexChar) +{ + return DIGIT_LOOKUP_TABLE[static_cast(hexChar)]; +} + +} // namespace impl + template std::optional strUnHex(std::size_t strSize, Iterator begin, Iterator end) { - static constexpr std::array const unxtab = []() { - std::array t{}; - - for (auto& x : t) - x = -1; - - for (int i = 0; i < 10; ++i) - t['0' + i] = i; - - for (int i = 0; i < 6; ++i) - { - t['A' + i] = 10 + i; - t['a' + i] = 10 + i; - } - - return t; - }(); - Blob out; out.reserve((strSize + 1) / 2); @@ -76,27 +90,27 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end) if (strSize & 1) { - int c = unxtab[*iter++]; + auto const c = impl::hexCharToInt(*iter++); - if (c < 0) + if (!c.has_value()) return {}; - out.push_back(c); + out.push_back(static_cast(*c)); } while (iter != end) { - int cHigh = unxtab[*iter++]; + auto const cHigh = impl::hexCharToInt(*iter++); - if (cHigh < 0) + if (!cHigh.has_value()) return {}; - int cLow = unxtab[*iter++]; + auto const cLow = impl::hexCharToInt(*iter++); - if (cLow < 0) + if (!cLow.has_value()) return {}; - out.push_back(static_cast((cHigh << 4) | cLow)); + out.push_back(static_cast((*cHigh << 4) | *cLow)); } return {std::move(out)};