MetaCore/Source/MetaCoreFoundation/Private/MetaCoreHash.cpp

60 lines
1.8 KiB
C++

#include "MetaCoreFoundation/MetaCoreHash.h"
#include <array>
#include <fstream>
namespace MetaCore {
namespace {
constexpr std::uint64_t GMetaCoreFnvOffsetBasis = 1469598103934665603ULL;
constexpr std::uint64_t GMetaCoreFnvPrime = 1099511628211ULL;
} // namespace
std::uint64_t MetaCoreHashBytes(std::span<const std::byte> data) {
std::uint64_t hashValue = GMetaCoreFnvOffsetBasis;
for (std::byte byteValue : data) {
hashValue ^= static_cast<std::uint64_t>(std::to_integer<unsigned char>(byteValue));
hashValue *= GMetaCoreFnvPrime;
}
return hashValue;
}
std::uint64_t MetaCoreHashString(std::string_view value) {
const auto* bytes = reinterpret_cast<const std::byte*>(value.data());
return MetaCoreHashBytes(std::span(bytes, value.size()));
}
std::optional<std::uint64_t> MetaCoreHashFile(const std::filesystem::path& path) {
std::ifstream input(path, std::ios::binary);
if (!input.is_open()) {
return std::nullopt;
}
std::array<char, 4096> buffer{};
std::uint64_t hashValue = GMetaCoreFnvOffsetBasis;
while (input.good()) {
input.read(buffer.data(), static_cast<std::streamsize>(buffer.size()));
const std::streamsize readCount = input.gcount();
if (readCount <= 0) {
break;
}
const auto* bytes = reinterpret_cast<const std::byte*>(buffer.data());
for (std::streamsize index = 0; index < readCount; ++index) {
hashValue ^= static_cast<std::uint64_t>(std::to_integer<unsigned char>(bytes[index]));
hashValue *= GMetaCoreFnvPrime;
}
}
return hashValue;
}
std::uint64_t MetaCoreHashCombine(std::uint64_t seed, std::uint64_t value) {
seed ^= value + 0x9E3779B97F4A7C15ULL + (seed << 6U) + (seed >> 2U);
return seed;
}
} // namespace MetaCore