diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index 08b2fca..1d8d90c 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -255,108 +255,72 @@ namespace literals { namespace internal { -template -struct sequence +constexpr size_t length(const char* s) noexcept { -}; - -template -using byte_sequence = sequence; - -template -using char_sequence = sequence; - - -template -struct concatenate; - -template -struct concatenate, byte_sequence> -{ - using type = byte_sequence; -}; - -template -constexpr uint8_t parse_hex_digit() noexcept -{ - static_assert((D >= '0' && D <= '9') || (D >= 'a' && D <= 'f') || (D >= 'A' && D <= 'F'), - "literal must be hexadecimal integer"); - return static_cast( - (D >= '0' && D <= '9') ? D - '0' : (D >= 'a' && D <= 'f') ? D - 'a' + 10 : D - 'A' + 10); + return (*s != '\0') ? length(s + 1) + 1 : 0; } - -template -struct parse_digits; - -template -struct parse_digits> +constexpr int from_hex(char c) noexcept { - using type = byte_sequence(parse_hex_digit() << 4) | - parse_hex_digit()>; -}; + return (c >= 'a' && c <= 'f') ? c - ('a' - 10) : + (c >= 'A' && c <= 'F') ? c - ('A' - 10) : c - '0'; +} -template -struct parse_digits> +constexpr uint8_t byte(const char* s, size_t i) noexcept { - using type = typename concatenate>::type, - typename parse_digits>::type>::type; -}; + return static_cast((from_hex(s[2 * i]) << 4) | from_hex(s[2 * i + 1])); +} +template +T from_hex(const char*) noexcept; -template -struct parse_literal; - -template -struct parse_literal> +template <> +constexpr bytes32 from_hex(const char* s) noexcept { - static_assert(Prefix1 == '0' && Prefix2 == 'x', "literal must be in hexadecimal notation"); - static_assert(sizeof...(Literal) == sizeof(T) * 2, "literal must match the result type size"); + return { + {{byte(s, 0), byte(s, 1), byte(s, 2), byte(s, 3), byte(s, 4), byte(s, 5), byte(s, 6), + byte(s, 7), byte(s, 8), byte(s, 9), byte(s, 10), byte(s, 11), byte(s, 12), byte(s, 13), + byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19), byte(s, 20), + byte(s, 21), byte(s, 22), byte(s, 23), byte(s, 24), byte(s, 25), byte(s, 26), byte(s, 27), + byte(s, 28), byte(s, 29), byte(s, 30), byte(s, 31)}}}; +} - template - static constexpr T create_from(byte_sequence) noexcept - { - return T{{{Bytes...}}}; - } - - static constexpr T get() noexcept - { - return create_from(typename parse_digits>::type{}); - } -}; - -template -struct parse_literal> +template <> +constexpr address from_hex
(const char* s) noexcept { - static_assert(Digit == '0', "only 0 is allowed as a single digit literal"); - static constexpr T get() noexcept { return {}; } -}; + return { + {{byte(s, 0), byte(s, 1), byte(s, 2), byte(s, 3), byte(s, 4), byte(s, 5), byte(s, 6), + byte(s, 7), byte(s, 8), byte(s, 9), byte(s, 10), byte(s, 11), byte(s, 12), byte(s, 13), + byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19)}}}; +} -template -constexpr T parse() noexcept +template +constexpr T from_literal(const char* s) { - return parse_literal>::get(); + return (s[0] == '0' && s[1] == '\0') ? + T{} : + !(s[0] == '0' && s[1] == 'x') ? + throw "literal must be in hexadecimal notation" : + (length(s + 2) != sizeof(T) * 2) ? throw "literal must match the result type size" : + from_hex(s + 2); } } // namespace internal /// Literal for evmc::address. -template -constexpr address operator"" _address() noexcept +constexpr address operator""_address(const char* s) noexcept { - return internal::parse(); + return internal::from_literal
(s); } /// Literal for evmc::bytes32. -template -constexpr bytes32 operator"" _bytes32() noexcept +constexpr bytes32 operator""_bytes32(const char* s) noexcept { - return internal::parse(); + return internal::from_literal(s); } } // namespace literals using namespace literals; - /// Alias for evmc_make_result(). constexpr auto make_result = evmc_make_result;