cmUuid.cxx 4.0 KB

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