Core/Uuid: Add FromString builder method
This commit is contained in:
parent
8dcce73738
commit
d72ac9cc73
|
|
@ -20,7 +20,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Uuid();
|
inline Uuid();
|
||||||
inline Uuid(const std::array<UInt8, 16> guid);
|
inline Uuid(const std::array<UInt8, 16> uuid);
|
||||||
Uuid(const Uuid&) = default;
|
Uuid(const Uuid&) = default;
|
||||||
Uuid(Uuid&& generator) = default;
|
Uuid(Uuid&& generator) = default;
|
||||||
~Uuid() = default;
|
~Uuid() = default;
|
||||||
|
|
@ -34,13 +34,14 @@ namespace Nz
|
||||||
Uuid& operator=(const Uuid&) = default;
|
Uuid& operator=(const Uuid&) = default;
|
||||||
Uuid& operator=(Uuid&&) = default;
|
Uuid& operator=(Uuid&&) = default;
|
||||||
|
|
||||||
|
static Uuid FromString(std::string_view str);
|
||||||
static Uuid Generate();
|
static Uuid Generate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<UInt8, 16> m_guid;
|
std::array<UInt8, 16> m_uuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
NAZARA_CORE_API std::ostream& operator<<(std::ostream& out, const Uuid& guid);
|
NAZARA_CORE_API std::ostream& operator<<(std::ostream& out, const Uuid& uuid);
|
||||||
inline bool operator==(const Uuid& lhs, const Uuid& rhs);
|
inline bool operator==(const Uuid& lhs, const Uuid& rhs);
|
||||||
inline bool operator!=(const Uuid& lhs, const Uuid& rhs);
|
inline bool operator!=(const Uuid& lhs, const Uuid& rhs);
|
||||||
inline bool operator<(const Uuid& lhs, const Uuid& rhs);
|
inline bool operator<(const Uuid& lhs, const Uuid& rhs);
|
||||||
|
|
|
||||||
|
|
@ -9,30 +9,30 @@ namespace Nz
|
||||||
{
|
{
|
||||||
inline Uuid::Uuid()
|
inline Uuid::Uuid()
|
||||||
{
|
{
|
||||||
m_guid.fill(0);
|
m_uuid.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Uuid::Uuid(const std::array<UInt8, 16> guid) :
|
inline Uuid::Uuid(const std::array<UInt8, 16> uuid) :
|
||||||
m_guid(guid)
|
m_uuid(uuid)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Uuid::IsNull() const
|
inline bool Uuid::IsNull() const
|
||||||
{
|
{
|
||||||
Uuid NullGuid;
|
Uuid nullUuid;
|
||||||
return *this == NullGuid;
|
return *this == nullUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::array<UInt8, 16>& Uuid::ToArray() const
|
inline const std::array<UInt8, 16>& Uuid::ToArray() const
|
||||||
{
|
{
|
||||||
return m_guid;
|
return m_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Uuid::ToString() const
|
inline std::string Uuid::ToString() const
|
||||||
{
|
{
|
||||||
std::array<char, 37> guidStr = ToStringArray();
|
std::array<char, 37> uuidStr = ToStringArray();
|
||||||
|
|
||||||
return std::string(guidStr.data(), guidStr.size() - 1);
|
return std::string(uuidStr.data(), uuidStr.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Uuid& lhs, const Uuid& rhs)
|
bool operator==(const Uuid& lhs, const Uuid& rhs)
|
||||||
|
|
@ -93,12 +93,12 @@ namespace std
|
||||||
template <>
|
template <>
|
||||||
struct hash<Nz::Uuid>
|
struct hash<Nz::Uuid>
|
||||||
{
|
{
|
||||||
size_t operator()(const Nz::Uuid& guid) const
|
size_t operator()(const Nz::Uuid& uuid) const
|
||||||
{
|
{
|
||||||
// DJB2 algorithm http://www.cse.yorku.ca/~oz/hash.html
|
// DJB2 algorithm http://www.cse.yorku.ca/~oz/hash.html
|
||||||
size_t h = 5381;
|
size_t h = 5381;
|
||||||
|
|
||||||
const array<Nz::UInt8, 16>& data = guid.ToArray();
|
const array<Nz::UInt8, 16>& data = uuid.ToArray();
|
||||||
for (size_t i = 0; i < data.size(); ++i)
|
for (size_t i = 0; i < data.size(); ++i)
|
||||||
h = ((h << 5) + h) + data[i];
|
h = ((h << 5) + h) + data[i];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,51 +15,101 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool ParseHexadecimalPair(Pointer<const char>& str, UInt8& number)
|
||||||
|
{
|
||||||
|
number = 0;
|
||||||
|
|
||||||
|
for (UInt8 mul : { 0x10, 1 })
|
||||||
|
{
|
||||||
|
if (*str >= '0' && *str <= '9')
|
||||||
|
number += (*str - '0') * mul;
|
||||||
|
else if (((*str & 0x5F) >= 'A' && (*str & 0x5F) <= 'F'))
|
||||||
|
number += ((*str & 0x5F) - 'A' + 10) * mul;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::array<char, 37> Uuid::ToStringArray() const
|
std::array<char, 37> Uuid::ToStringArray() const
|
||||||
{
|
{
|
||||||
std::array<char, 37> guidStr; //< Including \0
|
std::array<char, 37> uuidStr; //< Including \0
|
||||||
std::snprintf(guidStr.data(), guidStr.size(), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
std::snprintf(uuidStr.data(), uuidStr.size(), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||||
m_guid[0], m_guid[1], m_guid[2], m_guid[3], m_guid[4], m_guid[5], m_guid[6], m_guid[7],
|
m_uuid[0], m_uuid[1], m_uuid[2], m_uuid[3], m_uuid[4], m_uuid[5], m_uuid[6], m_uuid[7],
|
||||||
m_guid[8], m_guid[9], m_guid[10], m_guid[11], m_guid[12], m_guid[13], m_guid[14], m_guid[15]);
|
m_uuid[8], m_uuid[9], m_uuid[10], m_uuid[11], m_uuid[12], m_uuid[13], m_uuid[14], m_uuid[15]);
|
||||||
|
|
||||||
return guidStr;
|
return uuidStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uuid Uuid::FromString(std::string_view str)
|
||||||
|
{
|
||||||
|
if (str.size() != 36)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const char* ptr = str.data();
|
||||||
|
|
||||||
|
std::array<UInt8, 16> uuid;
|
||||||
|
UInt8* uuidPart = &uuid[0];
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for (std::size_t groupSize : { 4, 2, 2, 2, 6 })
|
||||||
|
{
|
||||||
|
if (!first && *ptr++ != '-')
|
||||||
|
return {};
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < groupSize; ++i)
|
||||||
|
{
|
||||||
|
if (!ParseHexadecimalPair(ptr, *uuidPart++))
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Uuid{ uuid };
|
||||||
}
|
}
|
||||||
|
|
||||||
Uuid Uuid::Generate()
|
Uuid Uuid::Generate()
|
||||||
{
|
{
|
||||||
std::array<UInt8, 16> guid;
|
std::array<UInt8, 16> uuid;
|
||||||
|
|
||||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||||
GUID id;
|
GUID id;
|
||||||
CoCreateGuid(&id);
|
CoCreateGuid(&id);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 4; ++i)
|
for (unsigned int i = 0; i < 4; ++i)
|
||||||
guid[i] = static_cast<UInt8>(id.Data1 >> ((3 - i) * 8 & 0xFF));
|
uuid[i] = static_cast<UInt8>(id.Data1 >> ((3 - i) * 8 & 0xFF));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 2; ++i)
|
for (unsigned int i = 0; i < 2; ++i)
|
||||||
guid[4 + i] = static_cast<UInt8>(id.Data2 >> ((1 - i) * 8 & 0xFF));
|
uuid[4 + i] = static_cast<UInt8>(id.Data2 >> ((1 - i) * 8 & 0xFF));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 2; ++i)
|
for (unsigned int i = 0; i < 2; ++i)
|
||||||
guid[6 + i] = static_cast<UInt8>(id.Data3 >> ((1 - i) * 8 & 0xFF));
|
uuid[6 + i] = static_cast<UInt8>(id.Data3 >> ((1 - i) * 8 & 0xFF));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 8; ++i)
|
for (unsigned int i = 0; i < 8; ++i)
|
||||||
guid[8 + i] = static_cast<UInt8>(id.Data4[i]);
|
uuid[8 + i] = static_cast<UInt8>(id.Data4[i]);
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX) || defined(NAZARA_PLATFORM_MACOSX)
|
#elif defined(NAZARA_PLATFORM_LINUX) || defined(NAZARA_PLATFORM_MACOSX)
|
||||||
uuid_t id;
|
uuid_t id;
|
||||||
uuid_generate(id);
|
uuid_generate(id);
|
||||||
|
|
||||||
std::copy(std::begin(id), std::end(id), guid.begin());
|
std::copy(std::begin(id), std::end(id), uuid.begin());
|
||||||
#else
|
#else
|
||||||
#error Missing platform support
|
#error Missing platform support
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return guid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const Uuid& guid)
|
std::ostream& operator<<(std::ostream& out, const Uuid& guid)
|
||||||
{
|
{
|
||||||
std::array<char, 37> guidStr = guid.ToStringArray();
|
std::array<char, 37> uuidStr = guid.ToStringArray();
|
||||||
|
|
||||||
return out << guidStr.data();
|
return out << uuidStr.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,25 @@
|
||||||
|
|
||||||
SCENARIO("Uuid", "[CORE][UUID]")
|
SCENARIO("Uuid", "[CORE][UUID]")
|
||||||
{
|
{
|
||||||
|
WHEN("Parsing UUID")
|
||||||
|
{
|
||||||
|
CHECK(Nz::Uuid::FromString("00000000-0000-0000-0000-000000000000") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-43e0-ba4c-e9334183b1f1") == Nz::Uuid({ 0x1B, 0x0E, 0x29, 0xAF, 0xFD, 0x4A, 0x43, 0xE0, 0xBA, 0x4C, 0xE9, 0x33, 0x41, 0x83, 0xB1, 0xF1 }));
|
||||||
|
|
||||||
|
// Testing some invalid cases
|
||||||
|
CHECK(Nz::Uuid::FromString("Nazara Engine") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("Zb0e29af-fd4a-43e0-ba4c-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29a\t-fd4a-43e0-ba4c-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4\v-43e0-ba4c-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-\r3e0-ba4c-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-43e\n-ba4c-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-43e0-\0a4c-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-43e0-ba4\n-e9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-43e0-ba4c-g9334183b1f1") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-fd4a-43e0-ba4c-e9334183b1fG") == Nz::Uuid());
|
||||||
|
CHECK(Nz::Uuid::FromString("1b0e29af-HELL-OWOR-LDDD-e9334183b1f1") == Nz::Uuid());
|
||||||
|
}
|
||||||
|
|
||||||
WHEN("Generating a null UUID")
|
WHEN("Generating a null UUID")
|
||||||
{
|
{
|
||||||
Nz::Uuid nullUuid;
|
Nz::Uuid nullUuid;
|
||||||
|
|
@ -19,6 +38,7 @@ SCENARIO("Uuid", "[CORE][UUID]")
|
||||||
CHECK_FALSE(nullUuid > Nz::Uuid{});
|
CHECK_FALSE(nullUuid > Nz::Uuid{});
|
||||||
CHECK_FALSE(nullUuid < Nz::Uuid{});
|
CHECK_FALSE(nullUuid < Nz::Uuid{});
|
||||||
CHECK(nullUuid != Nz::Uuid::Generate());
|
CHECK(nullUuid != Nz::Uuid::Generate());
|
||||||
|
CHECK(Nz::Uuid::FromString(nullUuid.ToString()) == nullUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN("Generating a UUID")
|
WHEN("Generating a UUID")
|
||||||
|
|
@ -36,6 +56,7 @@ SCENARIO("Uuid", "[CORE][UUID]")
|
||||||
CHECK(uuid <= uuid);
|
CHECK(uuid <= uuid);
|
||||||
CHECK_FALSE(uuid > uuid);
|
CHECK_FALSE(uuid > uuid);
|
||||||
CHECK_FALSE(uuid < uuid);
|
CHECK_FALSE(uuid < uuid);
|
||||||
|
CHECK(Nz::Uuid::FromString(uuid.ToString()) == uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN("Generating multiple UUID, they are unique")
|
WHEN("Generating multiple UUID, they are unique")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue