summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/fs/fs_util.cpp8
-rw-r--r--src/common/fs/fs_util.h18
-rw-r--r--src/common/logging/filter.cpp1
-rw-r--r--src/common/logging/types.h1
-rw-r--r--src/common/page_table.cpp58
-rw-r--r--src/common/page_table.h24
-rw-r--r--src/common/telemetry.h3
-rw-r--r--src/common/uuid.cpp208
-rw-r--r--src/common/uuid.h166
9 files changed, 383 insertions, 104 deletions
diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp
index 9f8671982..0068112e6 100644
--- a/src/common/fs/fs_util.cpp
+++ b/src/common/fs/fs_util.cpp
@@ -16,6 +16,10 @@ std::u8string BufferToU8String(std::span<const u8> buffer) {
16 return std::u8string{buffer.begin(), std::ranges::find(buffer, u8{0})}; 16 return std::u8string{buffer.begin(), std::ranges::find(buffer, u8{0})};
17} 17}
18 18
19std::u8string_view BufferToU8StringView(std::span<const u8> buffer) {
20 return std::u8string_view{reinterpret_cast<const char8_t*>(buffer.data())};
21}
22
19std::string ToUTF8String(std::u8string_view u8_string) { 23std::string ToUTF8String(std::u8string_view u8_string) {
20 return std::string{u8_string.begin(), u8_string.end()}; 24 return std::string{u8_string.begin(), u8_string.end()};
21} 25}
@@ -24,6 +28,10 @@ std::string BufferToUTF8String(std::span<const u8> buffer) {
24 return std::string{buffer.begin(), std::ranges::find(buffer, u8{0})}; 28 return std::string{buffer.begin(), std::ranges::find(buffer, u8{0})};
25} 29}
26 30
31std::string_view BufferToUTF8StringView(std::span<const u8> buffer) {
32 return std::string_view{reinterpret_cast<const char*>(buffer.data())};
33}
34
27std::string PathToUTF8String(const std::filesystem::path& path) { 35std::string PathToUTF8String(const std::filesystem::path& path) {
28 return ToUTF8String(path.u8string()); 36 return ToUTF8String(path.u8string());
29} 37}
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index 1ec82eb35..1620d38c9 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -38,6 +38,15 @@ concept IsChar = std::same_as<T, char>;
38[[nodiscard]] std::u8string BufferToU8String(std::span<const u8> buffer); 38[[nodiscard]] std::u8string BufferToU8String(std::span<const u8> buffer);
39 39
40/** 40/**
41 * Same as BufferToU8String, but returns a string view of the buffer.
42 *
43 * @param buffer Buffer of bytes
44 *
45 * @returns UTF-8 encoded std::u8string_view.
46 */
47[[nodiscard]] std::u8string_view BufferToU8StringView(std::span<const u8> buffer);
48
49/**
41 * Converts a std::u8string or std::u8string_view to a UTF-8 encoded std::string. 50 * Converts a std::u8string or std::u8string_view to a UTF-8 encoded std::string.
42 * 51 *
43 * @param u8_string UTF-8 encoded u8string 52 * @param u8_string UTF-8 encoded u8string
@@ -58,6 +67,15 @@ concept IsChar = std::same_as<T, char>;
58[[nodiscard]] std::string BufferToUTF8String(std::span<const u8> buffer); 67[[nodiscard]] std::string BufferToUTF8String(std::span<const u8> buffer);
59 68
60/** 69/**
70 * Same as BufferToUTF8String, but returns a string view of the buffer.
71 *
72 * @param buffer Buffer of bytes
73 *
74 * @returns UTF-8 encoded std::string_view.
75 */
76[[nodiscard]] std::string_view BufferToUTF8StringView(std::span<const u8> buffer);
77
78/**
61 * Converts a filesystem path to a UTF-8 encoded std::string. 79 * Converts a filesystem path to a UTF-8 encoded std::string.
62 * 80 *
63 * @param path Filesystem path 81 * @param path Filesystem path
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index b898a652c..4afc1369a 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -108,6 +108,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
108 SUB(Service, Migration) \ 108 SUB(Service, Migration) \
109 SUB(Service, Mii) \ 109 SUB(Service, Mii) \
110 SUB(Service, MM) \ 110 SUB(Service, MM) \
111 SUB(Service, MNPP) \
111 SUB(Service, NCM) \ 112 SUB(Service, NCM) \
112 SUB(Service, NFC) \ 113 SUB(Service, NFC) \
113 SUB(Service, NFP) \ 114 SUB(Service, NFP) \
diff --git a/src/common/logging/types.h b/src/common/logging/types.h
index 9ed0c7ad6..2b6e4daa7 100644
--- a/src/common/logging/types.h
+++ b/src/common/logging/types.h
@@ -76,6 +76,7 @@ enum class Class : u8 {
76 Service_Migration, ///< The migration service 76 Service_Migration, ///< The migration service
77 Service_Mii, ///< The Mii service 77 Service_Mii, ///< The Mii service
78 Service_MM, ///< The MM (Multimedia) service 78 Service_MM, ///< The MM (Multimedia) service
79 Service_MNPP, ///< The MNPP service
79 Service_NCM, ///< The NCM service 80 Service_NCM, ///< The NCM service
80 Service_NFC, ///< The NFC (Near-field communication) service 81 Service_NFC, ///< The NFC (Near-field communication) service
81 Service_NFP, ///< The NFP service 82 Service_NFP, ///< The NFP service
diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp
index 9fffd816f..4817b09f9 100644
--- a/src/common/page_table.cpp
+++ b/src/common/page_table.cpp
@@ -10,11 +10,65 @@ PageTable::PageTable() = default;
10 10
11PageTable::~PageTable() noexcept = default; 11PageTable::~PageTable() noexcept = default;
12 12
13void PageTable::Resize(size_t address_space_width_in_bits, size_t page_size_in_bits) { 13bool PageTable::BeginTraversal(TraversalEntry& out_entry, TraversalContext& out_context,
14 const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)}; 14 u64 address) const {
15 // Setup invalid defaults.
16 out_entry.phys_addr = 0;
17 out_entry.block_size = page_size;
18 out_context.next_page = 0;
19
20 // Validate that we can read the actual entry.
21 const auto page = address / page_size;
22 if (page >= backing_addr.size()) {
23 return false;
24 }
25
26 // Validate that the entry is mapped.
27 const auto phys_addr = backing_addr[page];
28 if (phys_addr == 0) {
29 return false;
30 }
31
32 // Populate the results.
33 out_entry.phys_addr = phys_addr + address;
34 out_context.next_page = page + 1;
35 out_context.next_offset = address + page_size;
36
37 return true;
38}
39
40bool PageTable::ContinueTraversal(TraversalEntry& out_entry, TraversalContext& context) const {
41 // Setup invalid defaults.
42 out_entry.phys_addr = 0;
43 out_entry.block_size = page_size;
44
45 // Validate that we can read the actual entry.
46 const auto page = context.next_page;
47 if (page >= backing_addr.size()) {
48 return false;
49 }
50
51 // Validate that the entry is mapped.
52 const auto phys_addr = backing_addr[page];
53 if (phys_addr == 0) {
54 return false;
55 }
56
57 // Populate the results.
58 out_entry.phys_addr = phys_addr + context.next_offset;
59 context.next_page = page + 1;
60 context.next_offset += page_size;
61
62 return true;
63}
64
65void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits) {
66 const std::size_t num_page_table_entries{1ULL
67 << (address_space_width_in_bits - page_size_in_bits)};
15 pointers.resize(num_page_table_entries); 68 pointers.resize(num_page_table_entries);
16 backing_addr.resize(num_page_table_entries); 69 backing_addr.resize(num_page_table_entries);
17 current_address_space_width_in_bits = address_space_width_in_bits; 70 current_address_space_width_in_bits = address_space_width_in_bits;
71 page_size = 1ULL << page_size_in_bits;
18} 72}
19 73
20} // namespace Common 74} // namespace Common
diff --git a/src/common/page_table.h b/src/common/page_table.h
index 8267e8b4d..82d91e9f3 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -27,6 +27,16 @@ enum class PageType : u8 {
27 * mimics the way a real CPU page table works. 27 * mimics the way a real CPU page table works.
28 */ 28 */
29struct PageTable { 29struct PageTable {
30 struct TraversalEntry {
31 u64 phys_addr{};
32 std::size_t block_size{};
33 };
34
35 struct TraversalContext {
36 u64 next_page{};
37 u64 next_offset{};
38 };
39
30 /// Number of bits reserved for attribute tagging. 40 /// Number of bits reserved for attribute tagging.
31 /// This can be at most the guaranteed alignment of the pointers in the page table. 41 /// This can be at most the guaranteed alignment of the pointers in the page table.
32 static constexpr int ATTRIBUTE_BITS = 2; 42 static constexpr int ATTRIBUTE_BITS = 2;
@@ -89,6 +99,10 @@ struct PageTable {
89 PageTable(PageTable&&) noexcept = default; 99 PageTable(PageTable&&) noexcept = default;
90 PageTable& operator=(PageTable&&) noexcept = default; 100 PageTable& operator=(PageTable&&) noexcept = default;
91 101
102 bool BeginTraversal(TraversalEntry& out_entry, TraversalContext& out_context,
103 u64 address) const;
104 bool ContinueTraversal(TraversalEntry& out_entry, TraversalContext& context) const;
105
92 /** 106 /**
93 * Resizes the page table to be able to accommodate enough pages within 107 * Resizes the page table to be able to accommodate enough pages within
94 * a given address space. 108 * a given address space.
@@ -96,9 +110,9 @@ struct PageTable {
96 * @param address_space_width_in_bits The address size width in bits. 110 * @param address_space_width_in_bits The address size width in bits.
97 * @param page_size_in_bits The page size in bits. 111 * @param page_size_in_bits The page size in bits.
98 */ 112 */
99 void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits); 113 void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits);
100 114
101 size_t GetAddressSpaceBits() const { 115 std::size_t GetAddressSpaceBits() const {
102 return current_address_space_width_in_bits; 116 return current_address_space_width_in_bits;
103 } 117 }
104 118
@@ -110,9 +124,11 @@ struct PageTable {
110 124
111 VirtualBuffer<u64> backing_addr; 125 VirtualBuffer<u64> backing_addr;
112 126
113 size_t current_address_space_width_in_bits; 127 std::size_t current_address_space_width_in_bits{};
128
129 u8* fastmem_arena{};
114 130
115 u8* fastmem_arena; 131 std::size_t page_size{};
116}; 132};
117 133
118} // namespace Common 134} // namespace Common
diff --git a/src/common/telemetry.h b/src/common/telemetry.h
index d38aeac99..4d632f7eb 100644
--- a/src/common/telemetry.h
+++ b/src/common/telemetry.h
@@ -171,6 +171,9 @@ struct VisitorInterface {
171struct NullVisitor final : public VisitorInterface { 171struct NullVisitor final : public VisitorInterface {
172 YUZU_NON_COPYABLE(NullVisitor); 172 YUZU_NON_COPYABLE(NullVisitor);
173 173
174 NullVisitor() = default;
175 ~NullVisitor() override = default;
176
174 void Visit(const Field<bool>& /*field*/) override {} 177 void Visit(const Field<bool>& /*field*/) override {}
175 void Visit(const Field<double>& /*field*/) override {} 178 void Visit(const Field<double>& /*field*/) override {}
176 void Visit(const Field<float>& /*field*/) override {} 179 void Visit(const Field<float>& /*field*/) override {}
diff --git a/src/common/uuid.cpp b/src/common/uuid.cpp
index d7435a6e9..2b6a530e3 100644
--- a/src/common/uuid.cpp
+++ b/src/common/uuid.cpp
@@ -1,23 +1,25 @@
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>
6#include <optional>
5#include <random> 7#include <random>
6 8
7#include <fmt/format.h> 9#include <fmt/format.h>
8 10
9#include "common/assert.h" 11#include "common/assert.h"
12#include "common/tiny_mt.h"
10#include "common/uuid.h" 13#include "common/uuid.h"
11 14
12namespace Common { 15namespace Common {
13 16
14namespace { 17namespace {
15 18
16bool IsHexDigit(char c) { 19constexpr size_t RawStringSize = sizeof(UUID) * 2;
17 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 20constexpr size_t FormattedStringSize = RawStringSize + 4;
18}
19 21
20u8 HexCharToByte(char c) { 22std::optional<u8> HexCharToByte(char c) {
21 if (c >= '0' && c <= '9') { 23 if (c >= '0' && c <= '9') {
22 return static_cast<u8>(c - '0'); 24 return static_cast<u8>(c - '0');
23 } 25 }
@@ -28,60 +30,184 @@ u8 HexCharToByte(char c) {
28 return static_cast<u8>(c - 'A' + 10); 30 return static_cast<u8>(c - 'A' + 10);
29 } 31 }
30 ASSERT_MSG(false, "{} is not a hexadecimal digit!", c); 32 ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
31 return u8{0}; 33 return std::nullopt;
32} 34}
33 35
34} // Anonymous namespace 36std::array<u8, 0x10> ConstructFromRawString(std::string_view raw_string) {
37 std::array<u8, 0x10> uuid;
38
39 for (size_t i = 0; i < RawStringSize; i += 2) {
40 const auto upper = HexCharToByte(raw_string[i]);
41 const auto lower = HexCharToByte(raw_string[i + 1]);
42 if (!upper || !lower) {
43 return {};
44 }
45 uuid[i / 2] = static_cast<u8>((*upper << 4) | *lower);
46 }
47
48 return uuid;
49}
35 50
36u128 HexStringToU128(std::string_view hex_string) { 51std::array<u8, 0x10> ConstructFromFormattedString(std::string_view formatted_string) {
37 const size_t length = hex_string.length(); 52 std::array<u8, 0x10> uuid;
38 53
39 // Detect "0x" prefix. 54 size_t i = 0;
40 const bool has_0x_prefix = length > 2 && hex_string[0] == '0' && hex_string[1] == 'x';
41 const size_t offset = has_0x_prefix ? 2 : 0;
42 55
43 // Check length. 56 // Process the first 8 characters.
44 if (length > 32 + offset) { 57 const auto* str = formatted_string.data();
45 ASSERT_MSG(false, "hex_string has more than 32 hexadecimal characters!"); 58
46 return INVALID_UUID; 59 for (; i < 4; ++i) {
60 const auto upper = HexCharToByte(*(str++));
61 const auto lower = HexCharToByte(*(str++));
62 if (!upper || !lower) {
63 return {};
64 }
65 uuid[i] = static_cast<u8>((*upper << 4) | *lower);
66 }
67
68 // Process the next 4 characters.
69 ++str;
70
71 for (; i < 6; ++i) {
72 const auto upper = HexCharToByte(*(str++));
73 const auto lower = HexCharToByte(*(str++));
74 if (!upper || !lower) {
75 return {};
76 }
77 uuid[i] = static_cast<u8>((*upper << 4) | *lower);
47 } 78 }
48 79
49 u64 lo = 0; 80 // Process the next 4 characters.
50 u64 hi = 0; 81 ++str;
51 for (size_t i = 0; i < length - offset; ++i) { 82
52 const char c = hex_string[length - 1 - i]; 83 for (; i < 8; ++i) {
53 if (!IsHexDigit(c)) { 84 const auto upper = HexCharToByte(*(str++));
54 ASSERT_MSG(false, "{} is not a hexadecimal digit!", c); 85 const auto lower = HexCharToByte(*(str++));
55 return INVALID_UUID; 86 if (!upper || !lower) {
87 return {};
56 } 88 }
57 if (i < 16) { 89 uuid[i] = static_cast<u8>((*upper << 4) | *lower);
58 lo |= u64{HexCharToByte(c)} << (i * 4); 90 }
91
92 // Process the next 4 characters.
93 ++str;
94
95 for (; i < 10; ++i) {
96 const auto upper = HexCharToByte(*(str++));
97 const auto lower = HexCharToByte(*(str++));
98 if (!upper || !lower) {
99 return {};
59 } 100 }
60 if (i >= 16) { 101 uuid[i] = static_cast<u8>((*upper << 4) | *lower);
61 hi |= u64{HexCharToByte(c)} << ((i - 16) * 4); 102 }
103
104 // Process the last 12 characters.
105 ++str;
106
107 for (; i < 16; ++i) {
108 const auto upper = HexCharToByte(*(str++));
109 const auto lower = HexCharToByte(*(str++));
110 if (!upper || !lower) {
111 return {};
62 } 112 }
113 uuid[i] = static_cast<u8>((*upper << 4) | *lower);
114 }
115
116 return uuid;
117}
118
119std::array<u8, 0x10> ConstructUUID(std::string_view uuid_string) {
120 const auto length = uuid_string.length();
121
122 if (length == 0) {
123 return {};
124 }
125
126 // Check if the input string contains 32 hexadecimal characters.
127 if (length == RawStringSize) {
128 return ConstructFromRawString(uuid_string);
129 }
130
131 // Check if the input string has the length of a RFC 4122 formatted UUID string.
132 if (length == FormattedStringSize) {
133 return ConstructFromFormattedString(uuid_string);
63 } 134 }
64 return u128{lo, hi}; 135
136 ASSERT_MSG(false, "UUID string has an invalid length of {} characters!", length);
137
138 return {};
139}
140
141} // Anonymous namespace
142
143UUID::UUID(std::string_view uuid_string) : uuid{ConstructUUID(uuid_string)} {}
144
145std::string UUID::RawString() const {
146 return fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}"
147 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
148 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
149 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],
150 uuid[15]);
151}
152
153std::string UUID::FormattedString() const {
154 return fmt::format("{:02x}{:02x}{:02x}{:02x}"
155 "-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-"
156 "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
157 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
158 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],
159 uuid[15]);
160}
161
162size_t UUID::Hash() const noexcept {
163 u64 upper_hash;
164 u64 lower_hash;
165
166 std::memcpy(&upper_hash, uuid.data(), sizeof(u64));
167 std::memcpy(&lower_hash, uuid.data() + sizeof(u64), sizeof(u64));
168
169 return upper_hash ^ std::rotl(lower_hash, 1);
65} 170}
66 171
67UUID UUID::Generate() { 172u128 UUID::AsU128() const {
173 u128 uuid_old;
174 std::memcpy(&uuid_old, uuid.data(), sizeof(UUID));
175 return uuid_old;
176}
177
178UUID UUID::MakeRandom() {
68 std::random_device device; 179 std::random_device device;
69 std::mt19937 gen(device()); 180
70 std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); 181 return MakeRandomWithSeed(device());
71 return UUID{distribution(gen), distribution(gen)};
72} 182}
73 183
74std::string UUID::Format() const { 184UUID UUID::MakeRandomWithSeed(u32 seed) {
75 return fmt::format("{:016x}{:016x}", uuid[1], uuid[0]); 185 // Create and initialize our RNG.
186 TinyMT rng;
187 rng.Initialize(seed);
188
189 UUID uuid;
190
191 // Populate the UUID with random bytes.
192 rng.GenerateRandomBytes(uuid.uuid.data(), sizeof(UUID));
193
194 return uuid;
76} 195}
77 196
78std::string UUID::FormatSwitch() const { 197UUID UUID::MakeRandomRFC4122V4() {
79 std::array<u8, 16> s{}; 198 auto uuid = MakeRandom();
80 std::memcpy(s.data(), uuid.data(), sizeof(u128)); 199
81 return fmt::format("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{" 200 // According to Proposed Standard RFC 4122 Section 4.4, we must:
82 ":02x}{:02x}{:02x}{:02x}{:02x}", 201
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], 202 // 1. Set the two most significant bits (bits 6 and 7) of the
84 s[12], s[13], s[14], s[15]); 203 // clock_seq_hi_and_reserved to zero and one, respectively.
204 uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F);
205
206 // 2. Set the four most significant bits (bits 12 through 15) of the
207 // time_hi_and_version field to the 4-bit version number from Section 4.1.3.
208 uuid.uuid[6] = 0x40 | (uuid.uuid[6] & 0xF);
209
210 return uuid;
85} 211}
86 212
87} // namespace Common 213} // 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