OpenClonk
C4PuncherHash.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #ifndef C4PuncherHash_H
17 #define C4PuncherHash_H
18 
19 #include <functional>
20 #include "network/C4NetIO.h"
21 
22 namespace {
23 
24  size_t hash_combiner(size_t left, size_t right) //replacable
25  { return left*2793419347^right; }
26 
27  template<int index, class...types>
28  struct hash_impl {
29  size_t operator()(size_t a, const std::tuple<types...>& t) const {
30  typedef typename std::tuple_element<index-1, std::tuple<types...>>::type nexttype;
31  hash_impl<index-1, types...> next;
32  size_t b = std::hash<nexttype>()(std::get<index-1>(t));
33  return next(hash_combiner(a, b), t);
34  }
35  };
36  template<class...types>
37  struct hash_impl<1, types...> {
38  size_t operator()(size_t a, const std::tuple<types...>& t) const {
39  typedef typename std::tuple_element<0, std::tuple<types...>>::type nexttype;
40  size_t b = std::hash<nexttype>()(std::get<0>(t));
41  return hash_combiner(a, b);
42  }
43  };
44  template<class...types>
45  struct hash_impl<0, types...> {
46  size_t operator()(size_t a, const std::tuple<types...>& t) const {
47  return 0;
48  }
49  };
50 }
51 
52 namespace std {
53  // Remove this when C++ gets proper tuple hashes. For now, http://stackoverflow.com/questions/7110301/generic-hash-for-tuples-in-unordered-map-unordered-set will do
54  template<class...types>
55  struct hash<std::tuple<types...>> {
56  size_t operator()(const std::tuple<types...>& t) const {
57  const size_t begin = std::tuple_size<std::tuple<types...>>::value;
58  return hash_impl<begin, types...>()(19739, t);
59  }
60  };
61 
62  template<>
63  struct hash<C4NetIO::addr_t> {
64  size_t operator()(const C4NetIO::addr_t& addr) const {
65  switch (addr.GetFamily())
66  {
68  {
69  sockaddr_in v4 = addr;
70  auto unpack = make_tuple(v4.sin_family, v4.sin_addr.s_addr, v4.sin_port);
71  return hash<decltype(unpack)>()(unpack);
72  }
74  {
75  sockaddr_in6 v6 = addr;
76  auto unpack = make_tuple(v6.sin6_family, v6.sin6_port, v6.sin6_flowinfo, std::string((char*) v6.sin6_addr.s6_addr, 16), v6.sin6_scope_id);
77  return hash<decltype(unpack)>()(unpack);
78  }
80  assert(!"Unexpected address family");
81  return 0;
82  }
83  }
84  };
85 }
86 
87 #endif
#define a
#define b
AddressFamily GetFamily() const
Definition: C4NetIO.cpp:520
size_t operator()(const C4NetIO::addr_t &addr) const
Definition: C4PuncherHash.h:64
size_t operator()(const std::tuple< types... > &t) const
Definition: C4PuncherHash.h:56