const& _h)
{
return (*this |= _h.template bloomPart());
}
template inline bool containsBloom(FixedHash const& _h)
{
return contains(_h.template bloomPart());
}
template inline FixedHash bloomPart() const
{
unsigned const c_bloomBits = M * 8;
unsigned const c_mask = c_bloomBits - 1;
unsigned const c_bloomBytes = (StaticLog2::result + 7) / 8;
static_assert((M & (M - 1)) == 0, "M must be power-of-two");
static_assert(P * c_bloomBytes <= N, "out of range");
FixedHash ret;
byte const* p = data();
for (unsigned i = 0; i < P; ++i)
{
unsigned index = 0;
for (unsigned j = 0; j < c_bloomBytes; ++j, ++p)
index = (index << 8) | *p;
index &= c_mask;
ret[M - 1 - index / 8] |= (1 << (index % 8));
}
return ret;
}
/// Returns the index of the first bit set to one, or size() * 8 if no bits are set.
inline unsigned firstBitSet() const
{
unsigned ret = 0;
for (auto d: m_data)
if (d)
for (;; ++ret, d <<= 1)
if (d & 0x80)
return ret;
else {}
else
ret += 8;
return ret;
}
void clear() { m_data.fill(0); }
private:
std::array m_data; ///< The binary data.
};
/// Fast equality operator for h256.
template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
{
const uint64_t* hash1 = (const uint64_t*)data();
const uint64_t* hash2 = (const uint64_t*)_other.data();
return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]);
}
/// Fast std::hash compatible hash function object for h256.
template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const
{
uint64_t const* data = reinterpret_cast(value.data());
return boost::hash_range(data, data + 4);
}
/// Stream I/O for the FixedHash class.
template
inline std::ostream& operator<<(std::ostream& _out, FixedHash const& _h)
{
boost::io::ios_all_saver guard(_out);
_out << std::noshowbase << std::hex << std::setfill('0');
for (unsigned i = 0; i < N; ++i)
_out << std::setw(2) << (int)_h[i];
_out << std::dec;
return _out;
}
// Common types of FixedHash.
using h2048 = FixedHash<256>;
using h1024 = FixedHash<128>;
using h520 = FixedHash<65>;
using h512 = FixedHash<64>;
using h256 = FixedHash<32>;
using h160 = FixedHash<20>;
using h128 = FixedHash<16>;
using h64 = FixedHash<8>;
using h512s = std::vector;
using h256s = std::vector;
using h160s = std::vector;
using h256Set = std::set;
using h160Set = std::set;
using h256Hash = std::unordered_set;
using h160Hash = std::unordered_set;
/// Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes.
inline h160 right160(h256 const& _t)
{
h160 ret;
memcpy(ret.data(), _t.data() + 12, 20);
return ret;
}
/// Convert the given value into h160 (160-bit unsigned integer) using the left 20 bytes.
inline h160 left160(h256 const& _t)
{
h160 ret;
memcpy(&ret[0], _t.data(), 20);
return ret;
}
inline std::string toString(h256s const& _bs)
{
std::ostringstream out;
out << "[ ";
for (auto i: _bs)
out << i.abridged() << ", ";
out << "]";
return out.str();
}
}
namespace std
{
/// Forward std::hash to dev::FixedHash::hash.
template<> struct hash: dev::h64::hash {};
template<> struct hash: dev::h128::hash {};
template<> struct hash: dev::h160::hash {};
template<> struct hash: dev::h256::hash {};
template<> struct hash: dev::h512::hash {};
}