uuid.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <random>
  5. #include <fmt/format.h>
  6. #include "common/assert.h"
  7. #include "common/uuid.h"
  8. namespace Common {
  9. namespace {
  10. bool IsHexDigit(char c) {
  11. return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
  12. }
  13. u8 HexCharToByte(char c) {
  14. if (c >= '0' && c <= '9') {
  15. return static_cast<u8>(c - '0');
  16. }
  17. if (c >= 'a' && c <= 'f') {
  18. return static_cast<u8>(c - 'a' + 10);
  19. }
  20. if (c >= 'A' && c <= 'F') {
  21. return static_cast<u8>(c - 'A' + 10);
  22. }
  23. ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
  24. return u8{0};
  25. }
  26. } // Anonymous namespace
  27. u128 HexStringToU128(std::string_view hex_string) {
  28. const size_t length = hex_string.length();
  29. // Detect "0x" prefix.
  30. const bool has_0x_prefix = length > 2 && hex_string[0] == '0' && hex_string[1] == 'x';
  31. const size_t offset = has_0x_prefix ? 2 : 0;
  32. // Check length.
  33. if (length > 32 + offset) {
  34. ASSERT_MSG(false, "hex_string has more than 32 hexadecimal characters!");
  35. return INVALID_UUID;
  36. }
  37. u64 lo = 0;
  38. u64 hi = 0;
  39. for (size_t i = 0; i < length - offset; ++i) {
  40. const char c = hex_string[length - 1 - i];
  41. if (!IsHexDigit(c)) {
  42. ASSERT_MSG(false, "{} is not a hexadecimal digit!", c);
  43. return INVALID_UUID;
  44. }
  45. if (i < 16) {
  46. lo |= u64{HexCharToByte(c)} << (i * 4);
  47. }
  48. if (i >= 16) {
  49. hi |= u64{HexCharToByte(c)} << ((i - 16) * 4);
  50. }
  51. }
  52. return u128{lo, hi};
  53. }
  54. UUID UUID::Generate() {
  55. std::random_device device;
  56. std::mt19937 gen(device());
  57. std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
  58. return UUID{distribution(gen), distribution(gen)};
  59. }
  60. std::string UUID::Format() const {
  61. return fmt::format("{:016x}{:016x}", uuid[1], uuid[0]);
  62. }
  63. std::string UUID::FormatSwitch() const {
  64. std::array<u8, 16> s{};
  65. std::memcpy(s.data(), uuid.data(), sizeof(u128));
  66. return fmt::format("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{"
  67. ":02x}{:02x}{:02x}{:02x}{:02x}",
  68. s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11],
  69. s[12], s[13], s[14], s[15]);
  70. }
  71. } // namespace Common