diff --git a/include/tins/ipv6_address.h b/include/tins/ipv6_address.h index 32670cf..9689ffd 100644 --- a/include/tins/ipv6_address.h +++ b/include/tins/ipv6_address.h @@ -32,10 +32,10 @@ #include #include +#include #include #include #include -#include namespace Tins { @@ -224,9 +224,14 @@ namespace std { template<> struct hash { - size_t operator()(const Tins::IPv6Address& addr) const - { - return std::hash()(addr.to_string()); + // Implementation taken from boost.functional + size_t operator()(const Tins::IPv6Address& addr) const { + std::size_t output = Tins::IPv6Address::address_size; + Tins::IPv6Address::const_iterator iter = addr.begin(); + for (; iter != addr.end(); ++iter) { + output ^= *iter + 0x9e3779b9 + (output << 6) + (output >> 2); + } + return output; } }; diff --git a/tests/src/ipv6_address_test.cpp b/tests/src/ipv6_address_test.cpp index ff90341..ac001dc 100644 --- a/tests/src/ipv6_address_test.cpp +++ b/tests/src/ipv6_address_test.cpp @@ -5,10 +5,10 @@ #include #include #include +#include using namespace Tins; - const uint8_t empty_addr[IPv6Address::address_size] = { 0 }; void test_to_string(const std::string& str) { @@ -123,3 +123,17 @@ TEST(IPv6AddressTest, MaskAddress) { IPv6Address("deaf:beef:adad:beef::") & IPv6Address("ffff:e000::") ); } + +#if TINS_IS_CXX11 + +TEST(IPv6AddressTest, HashTest) { + using std::hash; + const auto hasher = [](const IPv6Address& address) { + return hash()(address); + }; + EXPECT_NE(hasher("dead:beef::"), hasher("dead:beef::1")); + EXPECT_NE(hasher("dead:beef::"), hasher("feed:dead::1")); + EXPECT_EQ(hasher("dead:beef::"), hasher("dead:beef::")); +} + +#endif