12#include <netinet/in.h>
15typedef uint16_t in_port_t;
20typedef uint16_t sa_family_t;
21typedef uint16_t in_port_t;
41OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
53 using T = std::array<uint8_t, N>;
54 typedef typename T::iterator iterator;
55 typedef typename T::const_iterator const_iterator;
57 Hash()
noexcept { data_.fill(0); }
58 Hash(
const uint8_t* h,
size_t data_len)
63 std::copy_n(h, N, data_.begin());
70 explicit Hash(std::string_view hex)
72 if (hex.size() < 2 * N)
75 fromString(hex.data());
78 Hash(
const msgpack::object& o) { msgpack_unpack(o); }
80 static constexpr size_t size() noexcept {
return N; }
81 const uint8_t* data()
const {
return data_.data(); }
82 uint8_t* data() {
return data_.data(); }
83 iterator begin() {
return data_.begin(); }
84 const_iterator cbegin()
const {
return data_.cbegin(); }
85 iterator end() {
return data_.end(); }
86 const_iterator cend()
const {
return data_.cend(); }
88 static constexpr inline Hash zero() noexcept {
return Hash {}; }
90 bool operator==(
const Hash& h)
const {
return data_ == h.data_; }
91 bool operator!=(
const Hash& h)
const {
return !(*
this == h); }
93 bool operator<(
const Hash& o)
const
95 for (
unsigned i = 0; i < N; i++) {
96 if (data_[i] != o.data_[i])
97 return data_[i] < o.data_[i];
102 Hash operator^(
const Hash& o)
const
105 for (
auto i = 0u; i < N; i++) {
106 result[i] = data_[i] ^ o.data_[i];
111 explicit operator bool()
const
113 auto a =
reinterpret_cast<const uint32_t*
>(data_.data());
114 auto b =
reinterpret_cast<const uint32_t*
>(data_.data() + N);
115 for (; a != b; a++) {
122 uint8_t& operator[](
size_t index) {
return data_[index]; }
123 const uint8_t& operator[](
size_t index)
const {
return data_[index]; }
132 for (i = N - 1; i >= 0; i--)
137 for (j = 7; j >= 0; j--)
138 if ((data_[i] & (0x80 >> j)) != 0)
143 static inline int cmp(
const Hash& id1,
const Hash& id2)
145 return std::memcmp(id1.data_.data(), id2.data_.data(), N);
149 static inline unsigned commonBits(
const Hash& id1,
const Hash& id2)
153 for (i = 0; i < N; i++) {
154 if (id1.data_[i] != id2.data_[i])
161 x = id1.data_[i] ^ id2.data_[i];
164 while ((x & 0x80) == 0) {
173 int xorCmp(
const Hash& id1,
const Hash& id2)
const
175 for (
unsigned i = 0; i < N; i++) {
176 if (id1.data_[i] == id2.data_[i])
178 uint8_t xor1 = id1.data_[i] ^ data_[i];
179 uint8_t xor2 = id2.data_[i] ^ data_[i];
180 return (xor1 < xor2) ? -1 : 1;
185 bool getBit(
unsigned nbit)
const
187 auto& num = *(data_.cbegin() + (nbit / 8));
188 unsigned bit = 7 - (nbit % 8);
189 return (num >> bit) & 1;
192 void setBit(
unsigned nbit,
bool b)
194 auto& num = data_[nbit / 8];
195 unsigned bit = 7 - (nbit % 8);
196 num ^= (-b ^ num) & (1 << bit);
199 double toFloat()
const
203 for (
size_t i = 0; i < std::min<size_t>(N,
sizeof(D) - 1); i++)
204 v += *(data_.cbegin() + i) / (double) ((D) 1 << 8 * (i + 1));
208 static inline Hash get(std::string_view data) {
return get((
const uint8_t*) data.data(), data.size()); }
210 static inline Hash get(
const std::vector<uint8_t>& data) {
return get(data.data(), data.size()); }
213 static Hash get(
const Hash<H>& o)
215 return get(o.data(), o.size());
221 static Hash
get(
const uint8_t* data,
size_t data_len)
228 static Hash getRandom();
230 template<
typename Rd>
231 static Hash getRandom(Rd&);
234 friend std::ostream& operator<<(std::ostream& s,
const Hash<M>& h);
237 friend std::istream& operator>>(std::istream& s,
Hash<M>& h);
240 std::string_view
to_view()
const {
return std::string_view(to_c_str(), N * 2); }
241 const char* to_c_str()
const;
243 std::string toString()
const;
245 template<
typename Packer>
246 void msgpack_pack(Packer& pk)
const
249 pk.pack_bin_body((
char*) data_.data(), N);
252 void msgpack_unpack(msgpack::object o)
254 if (o.type != msgpack::type::BIN or o.via.bin.size != N)
255 throw msgpack::type_error();
256 std::copy_n(o.via.bin.ptr, N, data_.data());
261 void fromString(
const char*);
271operator<<(std::ostream& s,
const Hash<N>& h)
273 s.write(h.to_c_str(), N * 2);
279operator>>(std::istream& s,
Hash<N>& h)
281 std::array<char, h.size() * 2> dat;
282 s.exceptions(std::istream::eofbit | std::istream::failbit);
283 s.read(&(*dat.begin()), dat.size());
284 fromString(dat.data());
290Hash<N>::fromString(
const char* in)
292 auto hex2bin = [](
char c) -> uint8_t {
293 if (c >=
'a' and c <=
'f')
295 else if (c >=
'A' and c <=
'F')
297 else if (c >=
'0' and c <=
'9')
300 throw std::domain_error(
"not an hex character");
303 for (
size_t i = 0; i < N; i++)
304 data_[i] = (hex2bin(in[2 * i]) << 4) | hex2bin(in[2 * i + 1]);
305 }
catch (
const std::domain_error&) {
315 std::random_device rdev;
316 std::uniform_int_distribution<uint32_t> rand_int;
317 auto a =
reinterpret_cast<uint32_t*
>(h.data());
318 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
319 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
326Hash<N>::getRandom(Rd& rdev)
329 std::uniform_int_distribution<uint32_t> rand_int;
330 auto a =
reinterpret_cast<uint32_t*
>(h.data());
331 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
332 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
336struct alignas(std::max_align_t) HexMap :
public std::array<std::array<char, 2>, 256>
339 : std::array<std::array<char, 2>, 256>()
341 for (
size_t i = 0; i < size(); i++) {
342 auto& e = (*this)[i];
343 e[0] = hex_digits[(i >> 4) & 0x0F];
344 e[1] = hex_digits[i & 0x0F];
349 static constexpr const char* hex_digits =
"0123456789abcdef";
352inline constexpr HexMap hex_map {};
355toHex(
const uint8_t* data,
size_t size)
357 std::string ret(size * 2,
'\0');
358 for (
size_t i = 0; i < size; i++) {
359 auto b = ret.data() + i * 2;
360 const auto& m = hex_map[data[i]];
361 *((uint16_t*) b) = *((uint16_t*) &m);
367toHex(
const std::vector<uint8_t>& data)
369 return toHex(data.data(), data.size());
374Hash<N>::to_c_str()
const
376 alignas(std::max_align_t)
thread_local std::array<char, N * 2 + 1> buf;
377 for (
size_t i = 0; i < N; i++) {
378 auto b = buf.data() + i * 2;
379 const auto& m = hex_map[data_[i]];
380 *((uint16_t*) b) = *((uint16_t*) &m);
388Hash<N>::toString()
const
390 return std::string(to_c_str(), N * 2);
396struct fmt::formatter<
dht::Hash<N>> : formatter<string_view>
398 constexpr auto format(
const dht::Hash<N>& c, format_context& ctx)
const
400 return formatter<string_view>::format(c.
to_view(), ctx);
static unsigned commonBits(const Hash &id1, const Hash &id2)
Hash(std::string_view hex)
static Hash get(const uint8_t *data, size_t data_len)
std::string_view to_view() const
int xorCmp(const Hash &id1, const Hash &id2) const
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)