MetaCore/Source/MetaCoreFoundation/Private/MetaCoreAssetGuid.cpp

107 lines
3.2 KiB
C++

#include "MetaCoreFoundation/MetaCoreAssetGuid.h"
#include <iomanip>
#include <optional>
#include <random>
#include <sstream>
namespace MetaCore {
namespace {
[[nodiscard]] std::optional<std::uint8_t> MetaCoreParseHexNibble(char value) {
if (value >= '0' && value <= '9') {
return static_cast<std::uint8_t>(value - '0');
}
if (value >= 'a' && value <= 'f') {
return static_cast<std::uint8_t>(10 + value - 'a');
}
if (value >= 'A' && value <= 'F') {
return static_cast<std::uint8_t>(10 + value - 'A');
}
return std::nullopt;
}
} // namespace
bool MetaCoreAssetGuid::IsValid() const {
for (std::uint8_t byteValue : Bytes) {
if (byteValue != 0) {
return true;
}
}
return false;
}
std::string MetaCoreAssetGuid::ToString() const {
std::ostringstream stream;
stream << std::hex << std::setfill('0');
for (std::size_t index = 0; index < Bytes.size(); ++index) {
if (index == 4 || index == 6 || index == 8 || index == 10) {
stream << '-';
}
stream << std::setw(2) << static_cast<unsigned int>(Bytes[index]);
}
return stream.str();
}
MetaCoreAssetGuid MetaCoreAssetGuid::Generate() {
static thread_local std::mt19937_64 generator(std::random_device{}());
MetaCoreAssetGuid guid;
for (std::size_t index = 0; index < guid.Bytes.size(); index += sizeof(std::uint64_t)) {
const std::uint64_t randomValue = generator();
for (std::size_t byteIndex = 0; byteIndex < sizeof(std::uint64_t) && (index + byteIndex) < guid.Bytes.size(); ++byteIndex) {
guid.Bytes[index + byteIndex] = static_cast<std::uint8_t>((randomValue >> (byteIndex * 8U)) & 0xFFU);
}
}
guid.Bytes[6] = static_cast<std::uint8_t>((guid.Bytes[6] & 0x0FU) | 0x40U);
guid.Bytes[8] = static_cast<std::uint8_t>((guid.Bytes[8] & 0x3FU) | 0x80U);
return guid;
}
std::optional<MetaCoreAssetGuid> MetaCoreAssetGuid::Parse(std::string_view value) {
std::array<char, 32> hexDigits{};
std::size_t digitCount = 0;
for (char character : value) {
if (character == '-') {
continue;
}
if (digitCount >= hexDigits.size()) {
return std::nullopt;
}
hexDigits[digitCount++] = character;
}
if (digitCount != hexDigits.size()) {
return std::nullopt;
}
MetaCoreAssetGuid guid;
for (std::size_t index = 0; index < guid.Bytes.size(); ++index) {
const auto highNibble = MetaCoreParseHexNibble(hexDigits[index * 2]);
const auto lowNibble = MetaCoreParseHexNibble(hexDigits[index * 2 + 1]);
if (!highNibble.has_value() || !lowNibble.has_value()) {
return std::nullopt;
}
guid.Bytes[index] = static_cast<std::uint8_t>((highNibble.value() << 4U) | lowNibble.value());
}
return guid;
}
std::size_t MetaCoreAssetGuidHasher::operator()(const MetaCoreAssetGuid& guid) const noexcept {
std::size_t hashValue = 1469598103934665603ULL;
for (std::uint8_t byteValue : guid.Bytes) {
hashValue ^= static_cast<std::size_t>(byteValue);
hashValue *= 1099511628211ULL;
}
return hashValue;
}
} // namespace MetaCore