diff --git a/examples/example_host.cpp b/examples/example_host.cpp index c13d87640..f2316c3ae 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -138,6 +138,7 @@ class ExampleHost : public evmc::Host evmc_tx_context get_tx_context() const noexcept final { return tx_context; } + // NOLINTNEXTLINE(bugprone-exception-escape) evmc::bytes32 get_block_hash(int64_t number) const noexcept final { const int64_t current_block_number = get_tx_context().block_number; diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index b2f925bdf..d24a28b4a 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -280,69 +281,27 @@ inline constexpr bytes32::operator bool() const noexcept namespace literals { -namespace internal -{ -constexpr int from_hex(char c) noexcept -{ - return (c >= 'a' && c <= 'f') ? c - ('a' - 10) : - (c >= 'A' && c <= 'F') ? c - ('A' - 10) : - c - '0'; -} - -constexpr uint8_t byte(const char* s, size_t i) noexcept -{ - return static_cast((from_hex(s[2 * i]) << 4) | from_hex(s[2 * i + 1])); -} - +/// Converts a raw literal into value of type T. +/// +/// This function is expected to be used on literals in constexpr context only. +/// In case the input is invalid the std::terminate() is called. +/// TODO(c++20): Use consteval. template -T from_hex(const char*) noexcept; - -template <> -constexpr bytes32 from_hex(const char* s) noexcept +constexpr T parse(std::string_view s) noexcept { - 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)}}}; + return from_hex(s).value(); } -template <> -constexpr address from_hex
(const char* s) noexcept -{ - 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 from_literal() noexcept -{ - constexpr auto size = sizeof...(c); - constexpr char literal[] = {c...}; - - static_assert(size > 2 && literal[0] == '0' && literal[1] == 'x', - "literal must be in hexadecimal notation"); - static_assert(size == 2 * sizeof(T) + 2, "literal must match the result type size"); - - return from_hex(&literal[2]); -} -} // namespace internal - /// Literal for evmc::address. -template -constexpr address operator""_address() noexcept +constexpr address operator""_address(const char* s) noexcept { - return internal::from_literal(); + return parse
(s); } /// Literal for evmc::bytes32. -template -constexpr bytes32 operator""_bytes32() noexcept +constexpr bytes32 operator""_bytes32(const char* s) noexcept { - return internal::from_literal(); + return parse(s); } } // namespace literals diff --git a/test/unittests/cpp_test.cpp b/test/unittests/cpp_test.cpp index af3213d45..baea93241 100644 --- a/test/unittests/cpp_test.cpp +++ b/test/unittests/cpp_test.cpp @@ -362,6 +362,10 @@ TEST(cpp, literals) static_assert(zero_address == evmc::address{}); static_assert(zero_hash == evmc::bytes32{}); + static_assert(0x00_address == 0x0000000000000000000000000000000000000000_address); + static_assert(0x01_address == 0x0000000000000000000000000000000000000001_address); + static_assert(0xf101_address == 0x000000000000000000000000000000000000f101_address); + EXPECT_EQ(0x0000000000000000000000000000000000000000_address, evmc::address{}); EXPECT_EQ(0x0000000000000000000000000000000000000000000000000000000000000000_bytes32, evmc::bytes32{});