diff options
Diffstat (limited to 'Source/cmUuid.cxx')
-rw-r--r-- | Source/cmUuid.cxx | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx new file mode 100644 index 0000000..201e1cc --- /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; +} |