summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/input.h8
-rw-r--r--src/common/new_uuid.cpp188
-rw-r--r--src/common/new_uuid.h141
-rw-r--r--src/common/uuid.cpp185
-rw-r--r--src/common/uuid.h166
6 files changed, 256 insertions, 434 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 3dd460191..adf70eb8b 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -99,8 +99,6 @@ add_library(common STATIC
99 microprofile.cpp 99 microprofile.cpp
100 microprofile.h 100 microprofile.h
101 microprofileui.h 101 microprofileui.h
102 new_uuid.cpp
103 new_uuid.h
104 nvidia_flags.cpp 102 nvidia_flags.cpp
105 nvidia_flags.h 103 nvidia_flags.h
106 page_table.cpp 104 page_table.cpp
diff --git a/src/common/input.h b/src/common/input.h
index 95d30497d..54fcb24b0 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -10,8 +10,8 @@
10#include <unordered_map> 10#include <unordered_map>
11#include <utility> 11#include <utility>
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/new_uuid.h"
14#include "common/param_package.h" 13#include "common/param_package.h"
14#include "common/uuid.h"
15 15
16namespace Common::Input { 16namespace Common::Input {
17 17
@@ -97,7 +97,7 @@ struct AnalogStatus {
97 97
98// Button data 98// Button data
99struct ButtonStatus { 99struct ButtonStatus {
100 Common::NewUUID uuid{}; 100 Common::UUID uuid{};
101 bool value{}; 101 bool value{};
102 bool inverted{}; 102 bool inverted{};
103 bool toggle{}; 103 bool toggle{};
@@ -109,7 +109,7 @@ using BatteryStatus = BatteryLevel;
109 109
110// Analog and digital joystick data 110// Analog and digital joystick data
111struct StickStatus { 111struct StickStatus {
112 Common::NewUUID uuid{}; 112 Common::UUID uuid{};
113 AnalogStatus x{}; 113 AnalogStatus x{};
114 AnalogStatus y{}; 114 AnalogStatus y{};
115 bool left{}; 115 bool left{};
@@ -120,7 +120,7 @@ struct StickStatus {
120 120
121// Analog and digital trigger data 121// Analog and digital trigger data
122struct TriggerStatus { 122struct TriggerStatus {
123 Common::NewUUID uuid{}; 123 Common::UUID uuid{};
124 AnalogStatus analog{}; 124 AnalogStatus analog{};
125 ButtonStatus pressed{}; 125 ButtonStatus pressed{};
126}; 126};
diff --git a/src/common/new_uuid.cpp b/src/common/new_uuid.cpp
deleted file mode 100644
index f2f0077ae..000000000
--- a/src/common/new_uuid.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <bit>
6#include <random>
7
8#include <fmt/format.h>
9
10#include "common/assert.h"
11#include "common/new_uuid.h"
12#include "common/tiny_mt.h"
13
14namespace Common {
15
16namespace {
17
18constexpr size_t RawStringSize = sizeof(NewUUID) * 2;
19constexpr size_t FormattedStringSize = RawStringSize + 4;
20
21u8 HexCharToByte(char c) {
22 if (c >= '0' && c <= '9') {
23 return static_cast<u8>(c - '0');
24 }
25 if (c >= 'a' && c <= 'f') {
26 return static_cast<u8>(c - 'a' + 10);
27 }
28 if (c >= 'A' && c <= 'F') {
29 return static_cast<u8>(c - 'A' + 10);
30 }
31 ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
32 return u8{0};
33}
34
35std::array<u8, 0x10> ConstructFromRawString(std::string_view raw_string) {
36 std::array<u8, 0x10> uuid;
37
38 for (size_t i = 0; i < RawStringSize; i += 2) {
39 uuid[i / 2] =
40 static_cast<u8>((HexCharToByte(raw_string[i]) << 4) | HexCharToByte(raw_string[i + 1]));
41 }
42
43 return uuid;
44}
45
46std::array<u8, 0x10> ConstructFromFormattedString(std::string_view formatted_string) {
47 std::array<u8, 0x10> uuid;
48
49 size_t i = 0;
50
51 // Process the first 8 characters.
52 const auto* str = formatted_string.data();
53
54 for (; i < 4; ++i) {
55 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
56 uuid[i] |= HexCharToByte(*(str++));
57 }
58
59 // Process the next 4 characters.
60 ++str;
61
62 for (; i < 6; ++i) {
63 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
64 uuid[i] |= HexCharToByte(*(str++));
65 }
66
67 // Process the next 4 characters.
68 ++str;
69
70 for (; i < 8; ++i) {
71 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
72 uuid[i] |= HexCharToByte(*(str++));
73 }
74
75 // Process the next 4 characters.
76 ++str;
77
78 for (; i < 10; ++i) {
79 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
80 uuid[i] |= HexCharToByte(*(str++));
81 }
82
83 // Process the last 12 characters.
84 ++str;
85
86 for (; i < 16; ++i) {
87 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
88 uuid[i] |= HexCharToByte(*(str++));
89 }
90
91 return uuid;
92}
93
94std::array<u8, 0x10> ConstructUUID(std::string_view uuid_string) {
95 const auto length = uuid_string.length();
96
97 if (length == 0) {
98 return {};
99 }
100
101 // Check if the input string contains 32 hexadecimal characters.
102 if (length == RawStringSize) {
103 return ConstructFromRawString(uuid_string);
104 }
105
106 // Check if the input string has the length of a RFC 4122 formatted UUID string.
107 if (length == FormattedStringSize) {
108 return ConstructFromFormattedString(uuid_string);
109 }
110
111 ASSERT_MSG(false, "UUID string has an invalid length of {} characters!", length);
112
113 return {};
114}
115
116} // Anonymous namespace
117
118NewUUID::NewUUID(std::string_view uuid_string) : uuid{ConstructUUID(uuid_string)} {}
119
120std::string NewUUID::RawString() const {
121 return fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}"
122 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
123 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
124 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],
125 uuid[15]);
126}
127
128std::string NewUUID::FormattedString() const {
129 return fmt::format("{:02x}{:02x}{:02x}{:02x}"
130 "-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-"
131 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
132 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
133 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],
134 uuid[15]);
135}
136
137size_t NewUUID::Hash() const noexcept {
138 u64 hash;
139 u64 temp;
140
141 std::memcpy(&hash, uuid.data(), sizeof(u64));
142 std::memcpy(&temp, uuid.data() + 8, sizeof(u64));
143
144 return hash ^ std::rotl(temp, 1);
145}
146
147u128 NewUUID::AsU128() const {
148 u128 uuid_old;
149 std::memcpy(&uuid_old, uuid.data(), sizeof(NewUUID));
150 return uuid_old;
151}
152
153NewUUID NewUUID::MakeRandom() {
154 std::random_device device;
155
156 return MakeRandomWithSeed(device());
157}
158
159NewUUID NewUUID::MakeRandomWithSeed(u32 seed) {
160 // Create and initialize our RNG.
161 TinyMT rng;
162 rng.Initialize(seed);
163
164 NewUUID uuid;
165
166 // Populate the UUID with random bytes.
167 rng.GenerateRandomBytes(uuid.uuid.data(), sizeof(NewUUID));
168
169 return uuid;
170}
171
172NewUUID NewUUID::MakeRandomRFC4122V4() {
173 auto uuid = MakeRandom();
174
175 // According to Proposed Standard RFC 4122 Section 4.4, we must:
176
177 // 1. Set the two most significant bits (bits 6 and 7) of the
178 // clock_seq_hi_and_reserved to zero and one, respectively.
179 uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F);
180
181 // 2. Set the four most significant bits (bits 12 through 15) of the
182 // time_hi_and_version field to the 4-bit version number from Section 4.1.3.
183 uuid.uuid[6] = 0x40 | (uuid.uuid[6] & 0xF);
184
185 return uuid;
186}
187
188} // namespace Common
diff --git a/src/common/new_uuid.h b/src/common/new_uuid.h
deleted file mode 100644
index 44665ad5a..000000000
--- a/src/common/new_uuid.h
+++ /dev/null
@@ -1,141 +0,0 @@
1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <functional>
9#include <string>
10#include <string_view>
11
12#include "common/common_types.h"
13
14namespace Common {
15
16struct NewUUID {
17 std::array<u8, 0x10> uuid{};
18
19 /// Constructs an invalid UUID.
20 constexpr NewUUID() = default;
21
22 /// Constructs a UUID from a reference to a 128 bit array.
23 constexpr explicit NewUUID(const std::array<u8, 16>& uuid_) : uuid{uuid_} {}
24
25 /**
26 * Constructs a UUID from either:
27 * 1. A 32 hexadecimal character string representing the bytes of the UUID
28 * 2. A RFC 4122 formatted UUID string, in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
29 *
30 * The input string may contain uppercase or lowercase characters, but they must:
31 * 1. Contain valid hexadecimal characters (0-9, a-f, A-F)
32 * 2. Not contain the "0x" hexadecimal prefix
33 *
34 * Should the input string not meet the above requirements,
35 * an assert will be triggered and an invalid UUID is set instead.
36 */
37 explicit NewUUID(std::string_view uuid_string);
38
39 ~NewUUID() = default;
40
41 constexpr NewUUID(const NewUUID&) noexcept = default;
42 constexpr NewUUID(NewUUID&&) noexcept = default;
43
44 constexpr NewUUID& operator=(const NewUUID&) noexcept = default;
45 constexpr NewUUID& operator=(NewUUID&&) noexcept = default;
46
47 /**
48 * Returns whether the stored UUID is valid or not.
49 *
50 * @returns True if the stored UUID is valid, false otherwise.
51 */
52 constexpr bool IsValid() const {
53 return uuid != std::array<u8, 0x10>{};
54 }
55
56 /**
57 * Returns whether the stored UUID is invalid or not.
58 *
59 * @returns True if the stored UUID is invalid, false otherwise.
60 */
61 constexpr bool IsInvalid() const {
62 return !IsValid();
63 }
64
65 /**
66 * Returns a 32 hexadecimal character string representing the bytes of the UUID.
67 *
68 * @returns A 32 hexadecimal character string of the UUID.
69 */
70 std::string RawString() const;
71
72 /**
73 * Returns a RFC 4122 formatted UUID string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
74 *
75 * @returns A RFC 4122 formatted UUID string.
76 */
77 std::string FormattedString() const;
78
79 /**
80 * Returns a 64-bit hash of the UUID for use in hash table data structures.
81 *
82 * @returns A 64-bit hash of the UUID.
83 */
84 size_t Hash() const noexcept;
85
86 /// DO NOT USE. Copies the contents of the UUID into a u128.
87 u128 AsU128() const;
88
89 /**
90 * Creates a default UUID "yuzu Default UID".
91 *
92 * @returns A UUID with its bytes set to the ASCII values of "yuzu Default UID".
93 */
94 static constexpr NewUUID MakeDefault() {
95 return NewUUID{
96 {'y', 'u', 'z', 'u', ' ', 'D', 'e', 'f', 'a', 'u', 'l', 't', ' ', 'U', 'I', 'D'},
97 };
98 }
99
100 /**
101 * Creates a random UUID.
102 *
103 * @returns A random UUID.
104 */
105 static NewUUID MakeRandom();
106
107 /**
108 * Creates a random UUID with a seed.
109 *
110 * @param seed A seed to initialize the Mersenne-Twister RNG
111 *
112 * @returns A random UUID.
113 */
114 static NewUUID MakeRandomWithSeed(u32 seed);
115
116 /**
117 * Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
118 *
119 * @returns A random UUID that is RFC 4122 Version 4 compliant.
120 */
121 static NewUUID MakeRandomRFC4122V4();
122
123 friend constexpr bool operator==(const NewUUID& lhs, const NewUUID& rhs) = default;
124};
125static_assert(sizeof(NewUUID) == 0x10, "UUID has incorrect size.");
126
127/// An invalid UUID. This UUID has all its bytes set to 0.
128constexpr NewUUID InvalidUUID = {};
129
130} // namespace Common
131
132namespace std {
133
134template <>
135struct hash<Common::NewUUID> {
136 size_t operator()(const Common::NewUUID& uuid) const noexcept {
137 return uuid.Hash();
138 }
139};
140
141} // namespace std
diff --git a/src/common/uuid.cpp b/src/common/uuid.cpp
index d7435a6e9..10a1b86e0 100644
--- a/src/common/uuid.cpp
+++ b/src/common/uuid.cpp
@@ -1,21 +1,22 @@
1// Copyright 2018 yuzu Emulator Project 1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <bit>
5#include <random> 6#include <random>
6 7
7#include <fmt/format.h> 8#include <fmt/format.h>
8 9
9#include "common/assert.h" 10#include "common/assert.h"
11#include "common/tiny_mt.h"
10#include "common/uuid.h" 12#include "common/uuid.h"
11 13
12namespace Common { 14namespace Common {
13 15
14namespace { 16namespace {
15 17
16bool IsHexDigit(char c) { 18constexpr size_t RawStringSize = sizeof(UUID) * 2;
17 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 19constexpr size_t FormattedStringSize = RawStringSize + 4;
18}
19 20
20u8 HexCharToByte(char c) { 21u8 HexCharToByte(char c) {
21 if (c >= '0' && c <= '9') { 22 if (c >= '0' && c <= '9') {
@@ -31,57 +32,157 @@ u8 HexCharToByte(char c) {
31 return u8{0}; 32 return u8{0};
32} 33}
33 34
34} // Anonymous namespace 35std::array<u8, 0x10> ConstructFromRawString(std::string_view raw_string) {
36 std::array<u8, 0x10> uuid;
37
38 for (size_t i = 0; i < RawStringSize; i += 2) {
39 uuid[i / 2] =
40 static_cast<u8>((HexCharToByte(raw_string[i]) << 4) | HexCharToByte(raw_string[i + 1]));
41 }
42
43 return uuid;
44}
45
46std::array<u8, 0x10> ConstructFromFormattedString(std::string_view formatted_string) {
47 std::array<u8, 0x10> uuid;
35 48
36u128 HexStringToU128(std::string_view hex_string) { 49 size_t i = 0;
37 const size_t length = hex_string.length();
38 50
39 // Detect "0x" prefix. 51 // Process the first 8 characters.
40 const bool has_0x_prefix = length > 2 && hex_string[0] == '0' && hex_string[1] == 'x'; 52 const auto* str = formatted_string.data();
41 const size_t offset = has_0x_prefix ? 2 : 0;
42 53
43 // Check length. 54 for (; i < 4; ++i) {
44 if (length > 32 + offset) { 55 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
45 ASSERT_MSG(false, "hex_string has more than 32 hexadecimal characters!"); 56 uuid[i] |= HexCharToByte(*(str++));
46 return INVALID_UUID;
47 } 57 }
48 58
49 u64 lo = 0; 59 // Process the next 4 characters.
50 u64 hi = 0; 60 ++str;
51 for (size_t i = 0; i < length - offset; ++i) { 61
52 const char c = hex_string[length - 1 - i]; 62 for (; i < 6; ++i) {
53 if (!IsHexDigit(c)) { 63 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
54 ASSERT_MSG(false, "{} is not a hexadecimal digit!", c); 64 uuid[i] |= HexCharToByte(*(str++));
55 return INVALID_UUID; 65 }
56 } 66
57 if (i < 16) { 67 // Process the next 4 characters.
58 lo |= u64{HexCharToByte(c)} << (i * 4); 68 ++str;
59 } 69
60 if (i >= 16) { 70 for (; i < 8; ++i) {
61 hi |= u64{HexCharToByte(c)} << ((i - 16) * 4); 71 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
62 } 72 uuid[i] |= HexCharToByte(*(str++));
63 } 73 }
64 return u128{lo, hi}; 74
75 // Process the next 4 characters.
76 ++str;
77
78 for (; i < 10; ++i) {
79 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
80 uuid[i] |= HexCharToByte(*(str++));
81 }
82
83 // Process the last 12 characters.
84 ++str;
85
86 for (; i < 16; ++i) {
87 uuid[i] = static_cast<u8>((HexCharToByte(*(str++)) << 4));
88 uuid[i] |= HexCharToByte(*(str++));
89 }
90
91 return uuid;
65} 92}
66 93
67UUID UUID::Generate() { 94std::array<u8, 0x10> ConstructUUID(std::string_view uuid_string) {
95 const auto length = uuid_string.length();
96
97 if (length == 0) {
98 return {};
99 }
100
101 // Check if the input string contains 32 hexadecimal characters.
102 if (length == RawStringSize) {
103 return ConstructFromRawString(uuid_string);
104 }
105
106 // Check if the input string has the length of a RFC 4122 formatted UUID string.
107 if (length == FormattedStringSize) {
108 return ConstructFromFormattedString(uuid_string);
109 }
110
111 ASSERT_MSG(false, "UUID string has an invalid length of {} characters!", length);
112
113 return {};
114}
115
116} // Anonymous namespace
117
118UUID::UUID(std::string_view uuid_string) : uuid{ConstructUUID(uuid_string)} {}
119
120std::string UUID::RawString() const {
121 return fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}"
122 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
123 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
124 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],
125 uuid[15]);
126}
127
128std::string UUID::FormattedString() const {
129 return fmt::format("{:02x}{:02x}{:02x}{:02x}"
130 "-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-"
131 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
132 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
133 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],
134 uuid[15]);
135}
136
137size_t UUID::Hash() const noexcept {
138 u64 hash;
139 u64 temp;
140
141 std::memcpy(&hash, uuid.data(), sizeof(u64));
142 std::memcpy(&temp, uuid.data() + 8, sizeof(u64));
143
144 return hash ^ std::rotl(temp, 1);
145}
146
147u128 UUID::AsU128() const {
148 u128 uuid_old;
149 std::memcpy(&uuid_old, uuid.data(), sizeof(UUID));
150 return uuid_old;
151}
152
153UUID UUID::MakeRandom() {
68 std::random_device device; 154 std::random_device device;
69 std::mt19937 gen(device()); 155
70 std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); 156 return MakeRandomWithSeed(device());
71 return UUID{distribution(gen), distribution(gen)};
72} 157}
73 158
74std::string UUID::Format() const { 159UUID UUID::MakeRandomWithSeed(u32 seed) {
75 return fmt::format("{:016x}{:016x}", uuid[1], uuid[0]); 160 // Create and initialize our RNG.
161 TinyMT rng;
162 rng.Initialize(seed);
163
164 UUID uuid;
165
166 // Populate the UUID with random bytes.
167 rng.GenerateRandomBytes(uuid.uuid.data(), sizeof(UUID));
168
169 return uuid;
76} 170}
77 171
78std::string UUID::FormatSwitch() const { 172UUID UUID::MakeRandomRFC4122V4() {
79 std::array<u8, 16> s{}; 173 auto uuid = MakeRandom();
80 std::memcpy(s.data(), uuid.data(), sizeof(u128)); 174
81 return fmt::format("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{" 175 // According to Proposed Standard RFC 4122 Section 4.4, we must:
82 ":02x}{:02x}{:02x}{:02x}{:02x}", 176
83 s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11], 177 // 1. Set the two most significant bits (bits 6 and 7) of the
84 s[12], s[13], s[14], s[15]); 178 // clock_seq_hi_and_reserved to zero and one, respectively.
179 uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F);
180
181 // 2. Set the four most significant bits (bits 12 through 15) of the
182 // time_hi_and_version field to the 4-bit version number from Section 4.1.3.
183 uuid.uuid[6] = 0x40 | (uuid.uuid[6] & 0xF);
184
185 return uuid;
85} 186}
86 187
87} // namespace Common 188} // namespace Common
diff --git a/src/common/uuid.h b/src/common/uuid.h
index 8ea01f8da..fe31e64e6 100644
--- a/src/common/uuid.h
+++ b/src/common/uuid.h
@@ -1,9 +1,11 @@
1// Copyright 2018 yuzu Emulator Project 1// Copyright 2022 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <functional>
7#include <string> 9#include <string>
8#include <string_view> 10#include <string_view>
9 11
@@ -11,69 +13,119 @@
11 13
12namespace Common { 14namespace Common {
13 15
14constexpr u128 INVALID_UUID{{0, 0}};
15
16/**
17 * Converts a hex string to a 128-bit unsigned integer.
18 *
19 * The hex string can be formatted in lowercase or uppercase, with or without the "0x" prefix.
20 *
21 * This function will assert and return INVALID_UUID under the following conditions:
22 * - If the hex string is more than 32 characters long
23 * - If the hex string contains non-hexadecimal characters
24 *
25 * @param hex_string Hexadecimal string
26 *
27 * @returns A 128-bit unsigned integer if successfully converted, INVALID_UUID otherwise.
28 */
29[[nodiscard]] u128 HexStringToU128(std::string_view hex_string);
30
31struct UUID { 16struct UUID {
32 // UUIDs which are 0 are considered invalid! 17 std::array<u8, 0x10> uuid{};
33 u128 uuid; 18
34 UUID() = default; 19 /// Constructs an invalid UUID.
35 constexpr explicit UUID(const u128& id) : uuid{id} {} 20 constexpr UUID() = default;
36 constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} 21
37 explicit UUID(std::string_view hex_string) { 22 /// Constructs a UUID from a reference to a 128 bit array.
38 uuid = HexStringToU128(hex_string); 23 constexpr explicit UUID(const std::array<u8, 16>& uuid_) : uuid{uuid_} {}
39 } 24
40 25 /**
41 [[nodiscard]] constexpr explicit operator bool() const { 26 * Constructs a UUID from either:
42 return uuid != INVALID_UUID; 27 * 1. A 32 hexadecimal character string representing the bytes of the UUID
43 } 28 * 2. A RFC 4122 formatted UUID string, in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
44 29 *
45 [[nodiscard]] constexpr bool operator==(const UUID& rhs) const { 30 * The input string may contain uppercase or lowercase characters, but they must:
46 return uuid == rhs.uuid; 31 * 1. Contain valid hexadecimal characters (0-9, a-f, A-F)
47 } 32 * 2. Not contain the "0x" hexadecimal prefix
48 33 *
49 [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const { 34 * Should the input string not meet the above requirements,
50 return !operator==(rhs); 35 * an assert will be triggered and an invalid UUID is set instead.
51 } 36 */
52 37 explicit UUID(std::string_view uuid_string);
53 // TODO(ogniK): Properly generate uuids based on RFC-4122 38
54 [[nodiscard]] static UUID Generate(); 39 ~UUID() = default;
55 40
56 // Set the UUID to {0,0} to be considered an invalid user 41 constexpr UUID(const UUID&) noexcept = default;
57 constexpr void Invalidate() { 42 constexpr UUID(UUID&&) noexcept = default;
58 uuid = INVALID_UUID; 43
44 constexpr UUID& operator=(const UUID&) noexcept = default;
45 constexpr UUID& operator=(UUID&&) noexcept = default;
46
47 /**
48 * Returns whether the stored UUID is valid or not.
49 *
50 * @returns True if the stored UUID is valid, false otherwise.
51 */
52 constexpr bool IsValid() const {
53 return uuid != std::array<u8, 0x10>{};
59 } 54 }
60 55
61 [[nodiscard]] constexpr bool IsInvalid() const { 56 /**
62 return uuid == INVALID_UUID; 57 * Returns whether the stored UUID is invalid or not.
63 } 58 *
64 [[nodiscard]] constexpr bool IsValid() const { 59 * @returns True if the stored UUID is invalid, false otherwise.
65 return !IsInvalid(); 60 */
61 constexpr bool IsInvalid() const {
62 return !IsValid();
66 } 63 }
67 64
68 // TODO(ogniK): Properly generate a Nintendo ID 65 /**
69 [[nodiscard]] constexpr u64 GetNintendoID() const { 66 * Returns a 32 hexadecimal character string representing the bytes of the UUID.
70 return uuid[0]; 67 *
68 * @returns A 32 hexadecimal character string of the UUID.
69 */
70 std::string RawString() const;
71
72 /**
73 * Returns a RFC 4122 formatted UUID string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
74 *
75 * @returns A RFC 4122 formatted UUID string.
76 */
77 std::string FormattedString() const;
78
79 /**
80 * Returns a 64-bit hash of the UUID for use in hash table data structures.
81 *
82 * @returns A 64-bit hash of the UUID.
83 */
84 size_t Hash() const noexcept;
85
86 /// DO NOT USE. Copies the contents of the UUID into a u128.
87 u128 AsU128() const;
88
89 /**
90 * Creates a default UUID "yuzu Default UID".
91 *
92 * @returns A UUID with its bytes set to the ASCII values of "yuzu Default UID".
93 */
94 static constexpr UUID MakeDefault() {
95 return UUID{
96 {'y', 'u', 'z', 'u', ' ', 'D', 'e', 'f', 'a', 'u', 'l', 't', ' ', 'U', 'I', 'D'},
97 };
71 } 98 }
72 99
73 [[nodiscard]] std::string Format() const; 100 /**
74 [[nodiscard]] std::string FormatSwitch() const; 101 * Creates a random UUID.
102 *
103 * @returns A random UUID.
104 */
105 static UUID MakeRandom();
106
107 /**
108 * Creates a random UUID with a seed.
109 *
110 * @param seed A seed to initialize the Mersenne-Twister RNG
111 *
112 * @returns A random UUID.
113 */
114 static UUID MakeRandomWithSeed(u32 seed);
115
116 /**
117 * Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
118 *
119 * @returns A random UUID that is RFC 4122 Version 4 compliant.
120 */
121 static UUID MakeRandomRFC4122V4();
122
123 friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
75}; 124};
76static_assert(sizeof(UUID) == 16, "UUID is an invalid size!"); 125static_assert(sizeof(UUID) == 0x10, "UUID has incorrect size.");
126
127/// An invalid UUID. This UUID has all its bytes set to 0.
128constexpr UUID InvalidUUID = {};
77 129
78} // namespace Common 130} // namespace Common
79 131
@@ -82,7 +134,7 @@ namespace std {
82template <> 134template <>
83struct hash<Common::UUID> { 135struct hash<Common::UUID> {
84 size_t operator()(const Common::UUID& uuid) const noexcept { 136 size_t operator()(const Common::UUID& uuid) const noexcept {
85 return uuid.uuid[1] ^ uuid.uuid[0]; 137 return uuid.Hash();
86 } 138 }
87}; 139};
88 140