summaryrefslogtreecommitdiff
path: root/Source/cmUuid.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmUuid.cxx')
-rw-r--r--Source/cmUuid.cxx175
1 files changed, 175 insertions, 0 deletions
diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx
new file mode 100644
index 000000000..201e1ccef
--- /dev/null
+++ b/Source/cmUuid.cxx
@@ -0,0 +1,175 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmUuid.h"
+
+#include "cmCryptoHash.h"
+
+#include <string.h>
+
+cmUuid::cmUuid()
+{
+ Groups.push_back(4);
+ Groups.push_back(2);
+ Groups.push_back(2);
+ Groups.push_back(2);
+ Groups.push_back(6);
+}
+
+std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name) const
+{
+ std::vector<unsigned char> hashInput;
+ this->CreateHashInput(uuidNamespace, name, hashInput);
+
+ cmCryptoHash md5(cmCryptoHash::AlgoMD5);
+ md5.Initialize();
+ md5.Append(&hashInput[0], hashInput.size());
+ std::vector<unsigned char> digest = md5.Finalize();
+
+ return this->FromDigest(&digest[0], 3);
+}
+
+std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name) const
+{
+ std::vector<unsigned char> hashInput;
+ this->CreateHashInput(uuidNamespace, name, hashInput);
+
+ cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
+ sha1.Initialize();
+ sha1.Append(&hashInput[0], hashInput.size());
+ std::vector<unsigned char> digest = sha1.Finalize();
+
+ return this->FromDigest(&digest[0], 5);
+}
+
+void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
+ std::string const& name,
+ std::vector<unsigned char>& output) const
+{
+ output = uuidNamespace;
+
+ if (!name.empty()) {
+ output.resize(output.size() + name.size());
+
+ memcpy(&output[0] + uuidNamespace.size(), name.c_str(), name.size());
+ }
+}
+
+std::string cmUuid::FromDigest(const unsigned char* digest,
+ unsigned char version) const
+{
+ typedef unsigned char byte_t;
+
+ byte_t uuid[16] = { 0 };
+ memcpy(uuid, digest, 16);
+
+ uuid[6] &= 0xF;
+ uuid[6] |= byte_t(version << 4);
+
+ uuid[8] &= 0x3F;
+ uuid[8] |= 0x80;
+
+ return this->BinaryToString(uuid);
+}
+
+bool cmUuid::StringToBinary(std::string const& input,
+ std::vector<unsigned char>& output) const
+{
+ output.clear();
+ output.reserve(16);
+
+ if (input.length() != 36) {
+ return false;
+ }
+ size_t index = 0;
+ for (size_t i = 0; i < this->Groups.size(); ++i) {
+ if (i != 0 && input[index++] != '-') {
+ return false;
+ }
+ size_t digits = this->Groups[i] * 2;
+ if (!StringToBinaryImpl(input.substr(index, digits), output)) {
+ return false;
+ }
+
+ index += digits;
+ }
+
+ return true;
+}
+
+std::string cmUuid::BinaryToString(const unsigned char* input) const
+{
+ std::string output;
+
+ size_t inputIndex = 0;
+ for (size_t i = 0; i < this->Groups.size(); ++i) {
+ if (i != 0) {
+ output += '-';
+ }
+
+ size_t bytes = this->Groups[i];
+ for (size_t j = 0; j < bytes; ++j) {
+ unsigned char byte = input[inputIndex++];
+ output += this->ByteToHex(byte);
+ }
+ }
+
+ return output;
+}
+
+std::string cmUuid::ByteToHex(unsigned char byte) const
+{
+ std::string result;
+ for (int i = 0; i < 2; ++i) {
+ unsigned char rest = byte % 16;
+ byte /= 16;
+
+ char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA));
+
+ result = c + result;
+ }
+
+ return result;
+}
+
+bool cmUuid::StringToBinaryImpl(std::string const& input,
+ std::vector<unsigned char>& output) const
+{
+ if (input.size() % 2) {
+ return false;
+ }
+
+ for (size_t i = 0; i < input.size(); i += 2) {
+ char c1 = 0;
+ if (!IntFromHexDigit(input[i], c1)) {
+ return false;
+ }
+
+ char c2 = 0;
+ if (!IntFromHexDigit(input[i + 1], c2)) {
+ return false;
+ }
+
+ output.push_back(char(c1 << 4 | c2));
+ }
+
+ return true;
+}
+
+bool cmUuid::IntFromHexDigit(char input, char& output) const
+{
+ if (input >= '0' && input <= '9') {
+ output = char(input - '0');
+ return true;
+ }
+ if (input >= 'a' && input <= 'f') {
+ output = char(input - 'a' + 0xA);
+ return true;
+ }
+ if (input >= 'A' && input <= 'F') {
+ output = char(input - 'A' + 0xA);
+ return true;
+ }
+ return false;
+}