56 lines
1.4 KiB
C++
56 lines
1.4 KiB
C++
#ifndef KNOTHASH_HPP_
|
|
#define KNOTHASH_HPP_
|
|
|
|
#include <cstddef>
|
|
#include <array>
|
|
#include <algorithm>
|
|
#include <string>
|
|
|
|
namespace knothash {
|
|
|
|
template <std::size_t N>
|
|
auto reverser(std::array<std::uint8_t, N> & result, std::size_t cursor, std::size_t len) -> void {
|
|
auto leftside = N - cursor;
|
|
auto start = result.begin() + cursor;
|
|
if (len <= leftside) {
|
|
std::reverse(start, start + len);
|
|
} else {
|
|
auto rightside = len - leftside;
|
|
if (leftside < rightside) {
|
|
std::swap_ranges(start, result.end(), result.rend() - rightside);
|
|
std::reverse(result.begin(), result.begin() + (rightside-leftside));
|
|
} else {
|
|
std::swap_ranges(result.rend() - rightside, result.rend(), start);
|
|
std::reverse(result.end() - (leftside-rightside), result.end());
|
|
}
|
|
}
|
|
}
|
|
|
|
auto hash(std::string key) -> std::array<std::uint8_t, 16>;
|
|
auto render(std::array<std::uint8_t, 16> const& hash) -> std::string;
|
|
|
|
template <std::size_t N, typename It>
|
|
auto hash_ex(std::size_t cycles, It begin, It end)
|
|
-> std::array<std::uint8_t, N>
|
|
{
|
|
std::size_t cursor = 0;
|
|
std::size_t skip = 0;
|
|
|
|
std::array<std::uint8_t, N> result;
|
|
for (std::size_t i = 0; i < N; i++) { result[i] = i; }
|
|
|
|
for (std::size_t i = 0; i < cycles; i++) {
|
|
std::for_each(begin, end, [&](std::size_t len) {
|
|
reverser(result, cursor, len);
|
|
cursor += skip + len;
|
|
cursor %= N;
|
|
skip++;
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
#endif
|