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);
52 using T = std::array<uint8_t, N>;
53 typedef typename T::iterator iterator;
54 typedef typename T::const_iterator const_iterator;
56 constexpr Hash() noexcept
59 constexpr Hash(
const uint8_t* h,
size_t data_len)
60 : data_(fromBytes(h, data_len))
67 explicit constexpr Hash(std::string_view hex)
68 : data_(fromString(hex))
71 Hash(
const msgpack::object& o) { msgpack_unpack(o); }
73 static constexpr size_t size() noexcept {
return N; }
74 constexpr const uint8_t* data()
const {
return data_.data(); }
75 uint8_t* data() {
return data_.data(); }
76 iterator begin() {
return data_.begin(); }
77 const_iterator cbegin()
const {
return data_.cbegin(); }
78 iterator end() {
return data_.end(); }
79 const_iterator cend()
const {
return data_.cend(); }
81 static constexpr inline Hash zero() noexcept {
return Hash {}; }
83 constexpr bool operator==(
const Hash& h)
const
85#if __cplusplus >= 202002L
86 return data_ == h.data_;
88 for (
size_t i = 0; i < N; ++i) {
89 if (data_[i] != h.data_[i])
95 constexpr bool operator!=(
const Hash& h)
const {
return !(*
this == h); }
97 constexpr bool operator<(
const Hash& o)
const
99 for (
unsigned i = 0; i < N; i++) {
100 if (data_[i] != o.data_[i])
101 return data_[i] < o.data_[i];
106 constexpr Hash operator^(
const Hash& o)
const
109 for (
auto i = 0u; i < N; i++) {
110 result[i] = data_[i] ^ o.data_[i];
115 explicit constexpr operator bool()
const
117#if __cplusplus >= 202002L
118 auto a =
reinterpret_cast<const uint32_t*
>(data_.data());
119 auto b =
reinterpret_cast<const uint32_t*
>(data_.data() + N);
120 for (; a != b; a++) {
126 for (
size_t i = 0; i < N; ++i) {
134 uint8_t& operator[](
size_t index) {
return data_[index]; }
135 constexpr const uint8_t& operator[](
size_t index)
const {
return data_[index]; }
151 if ((data_[i] & (0x80 >> j)) != 0)
156 static inline int cmp(
const Hash& id1,
const Hash& id2)
158 return std::memcmp(id1.data_.data(), id2.data_.data(), N);
162 static constexpr inline unsigned commonBits(
const Hash& id1,
const Hash& id2)
166 if (id1.data_[i] != id2.data_[i])
173 uint8_t x = id1.data_[i] ^ id2.data_[i];
176 while ((x & 0x80) == 0) {
185 constexpr int xorCmp(
const Hash& id1,
const Hash& id2)
const
187 for (
unsigned i = 0; i < N; i++) {
188 if (id1.data_[i] == id2.data_[i])
190 uint8_t xor1 = id1.data_[i] ^ data_[i];
191 uint8_t xor2 = id2.data_[i] ^ data_[i];
192 return (xor1 < xor2) ? -1 : 1;
197 constexpr bool getBit(
unsigned nbit)
const
199 auto& num = *(data_.cbegin() + (nbit / 8));
200 unsigned bit = 7 - (nbit % 8);
201 return (num >> bit) & 1;
204 void setBit(
unsigned nbit,
bool b)
206 auto& num = data_[nbit / 8];
207 unsigned bit = 7 - (nbit % 8);
208 num ^= (-b ^ num) & (1 << bit);
211 double toFloat()
const
215 for (
size_t i = 0; i < std::min<size_t>(N,
sizeof(D) - 1); i++)
216 v += *(data_.cbegin() + i) / (double) ((D) 1 << 8 * (i + 1));
220 static inline Hash get(std::string_view data) {
return get((
const uint8_t*) data.data(), data.size()); }
222 static inline Hash get(
const std::vector<uint8_t>& data) {
return get(data.data(), data.size()); }
225 static Hash get(
const Hash<H>& o)
227 return get(o.data(), o.size());
233 static Hash
get(
const uint8_t* data,
size_t data_len)
240 static Hash getRandom();
242 template<
typename Rd>
243 static Hash getRandom(Rd&);
246 friend std::ostream& operator<<(std::ostream& s,
const Hash<M>& h);
249 friend std::istream& operator>>(std::istream& s,
Hash<M>& h);
252 std::string_view
to_view()
const {
return std::string_view(to_c_str(), N * 2); }
253 const char* to_c_str()
const;
255 std::string toString()
const;
257 template<
typename Packer>
258 void msgpack_pack(Packer& pk)
const
261 pk.pack_bin_body((
char*) data_.data(), N);
264 void msgpack_unpack(msgpack::object o)
266 if (o.type != msgpack::type::BIN or o.via.bin.size != N)
267 throw msgpack::type_error();
268 std::copy_n(o.via.bin.ptr, N, data_.data());
273 static constexpr T fromBytes(
const uint8_t*,
size_t);
274 static constexpr T fromString(std::string_view);
284operator<<(std::ostream& s,
const Hash<N>& h)
286 s.write(h.to_c_str(), N * 2);
292operator>>(std::istream& s,
Hash<N>& h)
294 std::array<char, h.size() * 2> dat;
295 s.exceptions(std::istream::eofbit | std::istream::failbit);
296 s.read(&(*dat.begin()), dat.size());
297 h =
Hash<N>(std::string_view(dat.data(), dat.size()));
302constexpr typename Hash<N>::T
303Hash<N>::fromBytes(
const uint8_t* in,
size_t size)
308 for (
size_t i = 0; i < N; ++i)
314constexpr typename Hash<N>::T
315Hash<N>::fromString(std::string_view in)
318 if (in.size() < 2 * N)
321 constexpr auto hex2bin = [](
char c,
bool& valid) -> uint8_t {
322 if (c >=
'a' and c <=
'f')
324 else if (c >=
'A' and c <=
'F')
326 else if (c >=
'0' and c <=
'9')
334 for (
size_t i = 0; i < N && valid; i++) {
335 uint8_t high = hex2bin(in[2 * i], valid);
336 uint8_t low = hex2bin(in[2 * i + 1], valid);
337 data[i] = (high << 4) | low;
349 std::random_device rdev;
350 std::uniform_int_distribution<uint32_t> rand_int;
351 auto a =
reinterpret_cast<uint32_t*
>(h.data());
352 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
353 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
360Hash<N>::getRandom(Rd& rdev)
363 std::uniform_int_distribution<uint32_t> rand_int;
364 auto a =
reinterpret_cast<uint32_t*
>(h.data());
365 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
366 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
370struct alignas(std::max_align_t) HexMap :
public std::array<std::array<char, 2>, 256>
373 : std::array<std::array<char, 2>, 256>()
375 for (
size_t i = 0; i < size(); i++) {
376 auto& e = (*this)[i];
377 e[0] = hex_digits[(i >> 4) & 0x0F];
378 e[1] = hex_digits[i & 0x0F];
383 static constexpr const char* hex_digits =
"0123456789abcdef";
386inline constexpr HexMap hex_map {};
389toHex(
const uint8_t* data,
size_t size)
391 std::string ret(size * 2,
'\0');
392 for (
size_t i = 0; i < size; i++) {
393 auto b = ret.data() + i * 2;
394 const auto& m = hex_map[data[i]];
395 *((uint16_t*) b) = *((uint16_t*) &m);
401toHex(
const std::vector<uint8_t>& data)
403 return toHex(data.data(), data.size());
407constexpr std::array<char, N * 2>
410 std::array<char, N * 2> ret {};
411 for (
size_t i = 0; i < N; i++) {
412 const auto& m = hex_map[h[i]];
414 ret[i * 2 + 1] = m[1];
421Hash<N>::to_c_str()
const
423 alignas(std::max_align_t)
thread_local std::array<char, N * 2 + 1> buf;
424 for (
size_t i = 0; i < N; i++) {
425 auto b = buf.data() + i * 2;
426 const auto& m = hex_map[data_[i]];
427 *((uint16_t*) b) = *((uint16_t*) &m);
435Hash<N>::toString()
const
437 return std::string(to_c_str(), N * 2);
443struct fmt::formatter<
dht::Hash<N>> : formatter<string_view>
445 constexpr auto format(
const dht::Hash<N>& c, format_context& ctx)
const
447 return formatter<string_view>::format(c.
to_view(), ctx);
constexpr int lowbit() const
static Hash get(const uint8_t *data, size_t data_len)
static constexpr unsigned commonBits(const Hash &id1, const Hash &id2)
constexpr Hash(std::string_view hex)
constexpr int xorCmp(const Hash &id1, const Hash &id2) const
std::string_view to_view() const
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)