#ifndef KNOTHASH_HPP_ #define KNOTHASH_HPP_ #include #include #include #include namespace knothash { template auto reverser(std::array & 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; auto render(std::array const& hash) -> std::string; template auto hash_ex(std::size_t cycles, It begin, It end) -> std::array { std::size_t cursor = 0; std::size_t skip = 0; std::array 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