Skip to content

Commit

Permalink
Allow shorter literals
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed May 20, 2022
1 parent 4f0f615 commit 20ba8bf
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
27 changes: 18 additions & 9 deletions include/evmc/evmc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,37 +281,46 @@ inline constexpr bytes32::operator bool() const noexcept

namespace literals
{
/// Breaks compilation and reports error string in constexpr context.
inline void error([[maybe_unused]] const char* message) noexcept {}
/// In constexpr context, this raises compile time error (because this function is non-constexpr).
[[noreturn]] inline void error([[maybe_unused]] const char* message) noexcept
{
std::terminate();
}

/// Converts a raw literal into value of type T.
///
/// This function is expected to be used on literals in constexpr context only.
template <typename T>
constexpr T to(std::string_view s) noexcept
constexpr T from_hex(std::string_view s) noexcept
{
if (s == "0")
return T{};

if (s[0] != '0' || s[1] != 'x')
error("literal must be in hexadecimal notation");
s.remove_prefix(2);
if (s.length() > 2 * sizeof(T))
error("literal must not exceed the result type size");
if (s.length() % 2 != 0)
error("hexadecimal literal must have even number of digits");

if (s.length() != 2 * sizeof(T) + 2)
error("literal must match the result type size");

const auto num_bytes = s.length() / 2;
T r{};
internal::from_hex(s, r.bytes);
if (!internal::from_hex(s, &r.bytes[sizeof(T) - num_bytes]))
error("literal contains non-hex digit");
return r;
}

/// Literal for evmc::address.
constexpr address operator""_address(const char* s) noexcept
{
return to<address>(s);
return from_hex<address>(s);
}

/// Literal for evmc::bytes32.
constexpr bytes32 operator""_bytes32(const char* s) noexcept
{
return to<bytes32>(s);
return from_hex<bytes32>(s);
}
} // namespace literals

Expand Down
26 changes: 24 additions & 2 deletions test/unittests/cpp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,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(0_address, evmc::address{});
EXPECT_EQ(0_bytes32, evmc::bytes32{});

Expand All @@ -375,6 +379,18 @@ TEST(cpp, literals)
0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd0, 0xd1, 0xd2}}};
EXPECT_EQ(h1, f1);
}
//
// TEST(cpp, literals_errors)
// {
// static int error_count = 0;
// const auto orig_handler = std::set_terminate([]{++error_count;});
//
// const auto l = "1";
// evmc::literals::operator""_address(l);
// EXPECT_EQ(error_count, 1);
//
// std::set_terminate(orig_handler);
// }

TEST(cpp, bytes32_from_uint)
{
Expand Down Expand Up @@ -820,7 +836,10 @@ TEST(cpp, status_code_to_string)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define TEST_CASE(NAME) \
TestCase { NAME, #NAME }
TestCase \
{ \
NAME, #NAME \
}
constexpr TestCase test_cases[]{
TEST_CASE(EVMC_SUCCESS),
TEST_CASE(EVMC_FAILURE),
Expand Down Expand Up @@ -871,7 +890,10 @@ TEST(cpp, revision_to_string)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define TEST_CASE(NAME) \
TestCase { NAME, #NAME }
TestCase \
{ \
NAME, #NAME \
}
constexpr TestCase test_cases[]{
TEST_CASE(EVMC_FRONTIER),
TEST_CASE(EVMC_HOMESTEAD),
Expand Down

0 comments on commit 20ba8bf

Please sign in to comment.