Improve C++ helpers

This commit is contained in:
Paweł Bylica 2018-09-08 16:08:37 +02:00
parent da9c03ffb5
commit 5c8e64915a
No known key found for this signature in database
GPG Key ID: 7A0C037434FE77EF
5 changed files with 60 additions and 22 deletions

View File

@ -7,8 +7,8 @@
#include "example_host.h"
#include <evmc/helpers.hpp>
#include <evmc/helpers.h>
#include <evmc/helpers.hpp>
#include <map>

View File

@ -10,6 +10,8 @@
* These are convenient for languages where invoking function pointers
* is "ugly" or impossible (such as Go).
*
* It also contains helpers (overloaded operators) for using EVMC types effectively in C++.
*
* @defgroup helpers EVMC Helpers
* @{
*/

View File

@ -4,11 +4,10 @@
*/
/**
* EVMC C++ helpers
* @file
* A collection of helpers (overloaded operators) for using EVMC types effectively in C++.
*
* A collection of helpers (overloaded operators) for using EVMC effectively in C++.
*
* @defgroup cpphelpers EVMC C++ helpers
* @addtogroup helpers
* @{
*/
#pragma once
@ -19,31 +18,31 @@
#include <functional>
/// The comparator for std::map<evmc_address, ...>.
bool operator<(const evmc_address& a, const evmc_address& b)
inline bool operator<(const evmc_address& a, const evmc_address& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a)) < 0;
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) < 0;
}
/// The comparator for std::map<evmc_bytes32, ...>.
bool operator<(const evmc_bytes32& a, const evmc_bytes32& b)
inline bool operator<(const evmc_bytes32& a, const evmc_bytes32& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a)) < 0;
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) < 0;
}
/// The comparator for equality.
bool operator==(const evmc_address& a, const evmc_address& b)
inline bool operator==(const evmc_address& a, const evmc_address& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0;
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) == 0;
}
/// The comparator for equality.
bool operator==(const evmc_bytes32& a, const evmc_bytes32& b)
inline bool operator==(const evmc_bytes32& a, const evmc_bytes32& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0;
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) == 0;
}
/// FNV1a hash function with 64-bit result.
static inline uint64_t fnv1a_64(const uint8_t* ptr, size_t len)
inline uint64_t fnv1a_64(const uint8_t* ptr, size_t len)
{
constexpr uint64_t prime = 1099511628211ULL;
constexpr uint64_t offset_basis = 14695981039346656037ULL;
@ -57,20 +56,27 @@ static inline uint64_t fnv1a_64(const uint8_t* ptr, size_t len)
return ret;
}
static_assert(sizeof(size_t) == sizeof(uint64_t), "size_t is not 64-bit wide");
namespace std
{
/// Hash operator template needed for std::ordered_set and others using hashes.
/// Hash operator template specialization for evmc_address needed for unordered containers.
template <>
struct hash<evmc_address>
{
/// Hash operator using FNV1a.
std::enable_if<sizeof(size_t) == 8, std::size_t>::type operator()(const evmc_address& s) const
noexcept
{
return fnv1a_64(s.bytes, sizeof(s.bytes));
}
};
/// Hash operator template needed for std::unordered_set and others using hashes.
template <>
struct hash<evmc_bytes32>
{
/// The argument type.
typedef evmc_bytes32 argument_type;
/// The result type.
typedef std::size_t result_type;
/// Hash operator using FNV1a.
result_type operator()(argument_type const& s) const noexcept
std::enable_if<sizeof(size_t) == 8, std::size_t>::type operator()(const evmc_bytes32& s) const
noexcept
{
return fnv1a_64(s.bytes, sizeof(s.bytes));
}

View File

@ -39,6 +39,7 @@ add_custom_command(
add_executable(
evmc-test
test_helpers.cpp
test_instructions.cpp
test_loader.cpp
)

View File

@ -0,0 +1,29 @@
// EVMC: Ethereum Client-VM Connector API.
// Copyright 2018 The EVMC Authors.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
#include <evmc/helpers.hpp>
#include <gtest/gtest.h>
#include <map>
#include <unordered_map>
TEST(helpers, maps)
{
std::map<evmc_address, bool> addresses;
addresses[{}] = true;
ASSERT_EQ(addresses.size(), 1);
std::unordered_map<evmc_address, bool> unordered_addresses;
unordered_addresses.emplace(*addresses.begin());
EXPECT_EQ(unordered_addresses.size(), 1);
std::map<evmc_bytes32, bool> storage;
storage[{}] = true;
ASSERT_EQ(storage.size(), 1);
std::unordered_map<evmc_bytes32, bool> unordered_storage;
unordered_storage.emplace(*storage.begin());
EXPECT_EQ(unordered_storage.size(), 1);
}