From d6a436100cd74e7a7b567a242ee84852d0faa552 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 2 Mar 2016 16:53:58 +0100 Subject: [PATCH] Network/IpAddress: Add std::hash specialization Former-commit-id: c8617065e51b307b541e4e58e3fb2494b144e828 --- include/Nazara/Network/IpAddress.inl | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/include/Nazara/Network/IpAddress.inl b/include/Nazara/Network/IpAddress.inl index 425fa6fee..c11c1879a 100644 --- a/include/Nazara/Network/IpAddress.inl +++ b/include/Nazara/Network/IpAddress.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include @@ -211,4 +212,42 @@ namespace Nz } } +namespace std +{ + template<> + struct hash + { + size_t operator()(const Nz::IpAddress& ip) const + { + if (!ip) + return std::numeric_limits::max(); //< Returns a fixed value for invalid addresses + + // This is SDBM adapted for IP addresses, tested to generate the least collisions possible + // (It doesn't mean it cannot be improved though) + std::size_t hash = 0; + switch (ip.GetProtocol()) + { + case Nz::NetProtocol_Any: + case Nz::NetProtocol_Unknown: + return std::numeric_limits::max(); + + case Nz::NetProtocol_IPv4: + { + hash = ip.ToUInt32() + (hash << 6) + (hash << 16) - hash; + break; + } + case Nz::NetProtocol_IPv6: + { + Nz::IpAddress::IPv6 v6 = ip.ToIPv6(); + for (std::size_t i = 0; i < v6.size(); i++) + hash = v6[i] + (hash << 6) + (hash << 16) - hash; + + break; + } + } + + return ip.GetPort() + (hash << 6) + (hash << 16) - hash; + } + }; +} #include