107 lines
3.2 KiB
C++
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
|
|
|