cmake/Source/cmUuid.cxx

168 lines
3.9 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
2015-04-27 22:25:09 +02:00
#include "cmUuid.h"
2019-11-11 23:01:05 +01:00
#include <array>
2020-02-01 23:06:01 +01:00
#include <cstring>
#include "cmCryptoHash.h"
2015-04-27 22:25:09 +02:00
2019-11-11 23:01:05 +01:00
static const std::array<int, 5> kUuidGroups = { { 4, 2, 2, 2, 6 } };
2015-04-27 22:25:09 +02:00
std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,
2016-07-09 11:21:54 +02:00
std::string const& name) const
2015-04-27 22:25:09 +02:00
{
std::vector<unsigned char> hashInput;
this->CreateHashInput(uuidNamespace, name, hashInput);
2017-04-14 19:02:05 +02:00
cmCryptoHash md5(cmCryptoHash::AlgoMD5);
md5.Initialize();
md5.Append(&hashInput[0], hashInput.size());
std::vector<unsigned char> digest = md5.Finalize();
2015-04-27 22:25:09 +02:00
2017-04-14 19:02:05 +02:00
return this->FromDigest(&digest[0], 3);
2015-04-27 22:25:09 +02:00
}
std::string cmUuid::FromSha1(std::vector<unsigned char> const& uuidNamespace,
2016-07-09 11:21:54 +02:00
std::string const& name) const
2015-04-27 22:25:09 +02:00
{
std::vector<unsigned char> hashInput;
this->CreateHashInput(uuidNamespace, name, hashInput);
2017-04-14 19:02:05 +02:00
cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
sha1.Initialize();
sha1.Append(&hashInput[0], hashInput.size());
std::vector<unsigned char> digest = sha1.Finalize();
2015-04-27 22:25:09 +02:00
2017-04-14 19:02:05 +02:00
return this->FromDigest(&digest[0], 5);
2015-04-27 22:25:09 +02:00
}
void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
2016-07-09 11:21:54 +02:00
std::string const& name,
std::vector<unsigned char>& output) const
2015-04-27 22:25:09 +02:00
{
output = uuidNamespace;
2016-07-09 11:21:54 +02:00
if (!name.empty()) {
2015-04-27 22:25:09 +02:00
output.resize(output.size() + name.size());
2016-07-09 11:21:54 +02:00
memcpy(&output[0] + uuidNamespace.size(), name.c_str(), name.size());
}
2015-04-27 22:25:09 +02:00
}
2016-07-09 11:21:54 +02:00
std::string cmUuid::FromDigest(const unsigned char* digest,
unsigned char version) const
2015-04-27 22:25:09 +02:00
{
2020-02-01 23:06:01 +01:00
using byte_t = unsigned char;
2015-04-27 22:25:09 +02:00
2016-07-09 11:21:54 +02:00
byte_t uuid[16] = { 0 };
2015-04-27 22:25:09 +02:00
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,
2016-07-09 11:21:54 +02:00
std::vector<unsigned char>& output) const
2015-04-27 22:25:09 +02:00
{
output.clear();
output.reserve(16);
2016-07-09 11:21:54 +02:00
if (input.length() != 36) {
2015-04-27 22:25:09 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
size_t index = 0;
2019-11-11 23:01:05 +01:00
for (size_t i = 0; i < kUuidGroups.size(); ++i) {
2016-07-09 11:21:54 +02:00
if (i != 0 && input[index++] != '-') {
2015-04-27 22:25:09 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2019-11-11 23:01:05 +01:00
size_t digits = kUuidGroups[i] * 2;
2021-09-14 00:13:48 +02:00
if (!this->StringToBinaryImpl(input.substr(index, digits), output)) {
2015-04-27 22:25:09 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
index += digits;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
return true;
}
std::string cmUuid::BinaryToString(const unsigned char* input) const
{
std::string output;
size_t inputIndex = 0;
2019-11-11 23:01:05 +01:00
for (size_t i = 0; i < kUuidGroups.size(); ++i) {
2016-07-09 11:21:54 +02:00
if (i != 0) {
2015-04-27 22:25:09 +02:00
output += '-';
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
2019-11-11 23:01:05 +01:00
size_t bytes = kUuidGroups[i];
2016-07-09 11:21:54 +02:00
for (size_t j = 0; j < bytes; ++j) {
2015-04-27 22:25:09 +02:00
unsigned char byte = input[inputIndex++];
output += this->ByteToHex(byte);
}
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
return output;
}
std::string cmUuid::ByteToHex(unsigned char byte) const
{
2020-02-01 23:06:01 +01:00
std::string result(" ");
2016-07-09 11:21:54 +02:00
for (int i = 0; i < 2; ++i) {
2015-04-27 22:25:09 +02:00
unsigned char rest = byte % 16;
byte /= 16;
2016-07-09 11:21:54 +02:00
char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA));
2020-02-01 23:06:01 +01:00
result.at(1 - i) = c;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
return result;
}
bool cmUuid::StringToBinaryImpl(std::string const& input,
2016-07-09 11:21:54 +02:00
std::vector<unsigned char>& output) const
2015-04-27 22:25:09 +02:00
{
2016-07-09 11:21:54 +02:00
if (input.size() % 2) {
2015-04-27 22:25:09 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
2016-07-09 11:21:54 +02:00
for (size_t i = 0; i < input.size(); i += 2) {
2015-04-27 22:25:09 +02:00
char c1 = 0;
2021-09-14 00:13:48 +02:00
if (!this->IntFromHexDigit(input[i], c1)) {
2015-04-27 22:25:09 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
char c2 = 0;
2021-09-14 00:13:48 +02:00
if (!this->IntFromHexDigit(input[i + 1], c2)) {
2015-04-27 22:25:09 +02:00
return false;
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
output.push_back(char(c1 << 4 | c2));
2016-07-09 11:21:54 +02:00
}
2015-04-27 22:25:09 +02:00
return true;
}
bool cmUuid::IntFromHexDigit(char input, char& output) const
{
2016-07-09 11:21:54 +02:00
if (input >= '0' && input <= '9') {
2015-04-27 22:25:09 +02:00
output = char(input - '0');
return true;
2016-10-30 18:24:19 +01:00
}
if (input >= 'a' && input <= 'f') {
2015-04-27 22:25:09 +02:00
output = char(input - 'a' + 0xA);
return true;
2016-10-30 18:24:19 +01:00
}
if (input >= 'A' && input <= 'F') {
2015-04-27 22:25:09 +02:00
output = char(input - 'A' + 0xA);
return true;
2016-07-09 11:21:54 +02:00
}
2016-10-30 18:24:19 +01:00
return false;
2015-04-27 22:25:09 +02:00
}