cmUuid.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmUuid.h"
  4. #include <array>
  5. #include <cstring>
  6. #include "cmCryptoHash.h"
  7. static const std::array<int, 5> kUuidGroups = { { 4, 2, 2, 2, 6 } };
  8. std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,
  9. std::string const& name) const
  10. {
  11. std::vector<unsigned char> hashInput;
  12. this->CreateHashInput(uuidNamespace, name, hashInput);
  13. cmCryptoHash md5(cmCryptoHash::AlgoMD5);
  14. md5.Initialize();
  15. md5.Append(hashInput.data(), hashInput.size());
  16. std::vector<unsigned char> digest = md5.Finalize();
  17. return this->FromDigest(digest.data(), 3);
  18. }
  19. std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace,
  20. std::string const& name) const
  21. {
  22. std::vector<unsigned char> hashInput;
  23. this->CreateHashInput(uuidNamespace, name, hashInput);
  24. cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
  25. sha1.Initialize();
  26. sha1.Append(hashInput.data(), hashInput.size());
  27. std::vector<unsigned char> digest = sha1.Finalize();
  28. return this->FromDigest(digest.data(), 5);
  29. }
  30. void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
  31. std::string const& name,
  32. std::vector<unsigned char>& output) const
  33. {
  34. output = uuidNamespace;
  35. if (!name.empty()) {
  36. output.resize(output.size() + name.size());
  37. memcpy(output.data() + uuidNamespace.size(), name.c_str(), name.size());
  38. }
  39. }
  40. std::string cmUuid::FromDigest(const unsigned char* digest,
  41. unsigned char version) const
  42. {
  43. using byte_t = unsigned char;
  44. byte_t uuid[16] = { 0 };
  45. memcpy(uuid, digest, 16);
  46. uuid[6] &= 0xF;
  47. uuid[6] |= byte_t(version << 4);
  48. uuid[8] &= 0x3F;
  49. uuid[8] |= 0x80;
  50. return this->BinaryToString(uuid);
  51. }
  52. bool cmUuid::StringToBinary(std::string const& input,
  53. std::vector<unsigned char>& output) const
  54. {
  55. output.clear();
  56. output.reserve(16);
  57. if (input.length() != 36) {
  58. return false;
  59. }
  60. size_t index = 0;
  61. for (size_t i = 0; i < kUuidGroups.size(); ++i) {
  62. if (i != 0 && input[index++] != '-') {
  63. return false;
  64. }
  65. size_t digits = kUuidGroups[i] * 2;
  66. if (!this->StringToBinaryImpl(input.substr(index, digits), output)) {
  67. return false;
  68. }
  69. index += digits;
  70. }
  71. return true;
  72. }
  73. std::string cmUuid::BinaryToString(const unsigned char* input) const
  74. {
  75. std::string output;
  76. size_t inputIndex = 0;
  77. for (size_t i = 0; i < kUuidGroups.size(); ++i) {
  78. if (i != 0) {
  79. output += '-';
  80. }
  81. size_t bytes = kUuidGroups[i];
  82. for (size_t j = 0; j < bytes; ++j) {
  83. unsigned char byte = input[inputIndex++];
  84. output += this->ByteToHex(byte);
  85. }
  86. }
  87. return output;
  88. }
  89. std::string cmUuid::ByteToHex(unsigned char byte) const
  90. {
  91. std::string result(" ");
  92. for (int i = 0; i < 2; ++i) {
  93. unsigned char rest = byte % 16;
  94. byte /= 16;
  95. char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA));
  96. result.at(1 - i) = c;
  97. }
  98. return result;
  99. }
  100. bool cmUuid::StringToBinaryImpl(std::string const& input,
  101. std::vector<unsigned char>& output) const
  102. {
  103. if (input.size() % 2) {
  104. return false;
  105. }
  106. for (size_t i = 0; i < input.size(); i += 2) {
  107. char c1 = 0;
  108. if (!this->IntFromHexDigit(input[i], c1)) {
  109. return false;
  110. }
  111. char c2 = 0;
  112. if (!this->IntFromHexDigit(input[i + 1], c2)) {
  113. return false;
  114. }
  115. output.push_back(char(c1 << 4 | c2));
  116. }
  117. return true;
  118. }
  119. bool cmUuid::IntFromHexDigit(char input, char& output) const
  120. {
  121. if (input >= '0' && input <= '9') {
  122. output = char(input - '0');
  123. return true;
  124. }
  125. if (input >= 'a' && input <= 'f') {
  126. output = char(input - 'a' + 0xA);
  127. return true;
  128. }
  129. if (input >= 'A' && input <= 'F') {
  130. output = char(input - 'A' + 0xA);
  131. return true;
  132. }
  133. return false;
  134. }