1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
/* 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 <array>
#include <cstring>
#include "cmCryptoHash.h"
static const std::array<int, 5> kUuidGroups = { { 4, 2, 2, 2, 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.data(), hashInput.size());
std::vector<unsigned char> digest = md5.Finalize();
return this->FromDigest(digest.data(), 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.data(), hashInput.size());
std::vector<unsigned char> digest = sha1.Finalize();
return this->FromDigest(digest.data(), 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.data() + uuidNamespace.size(), name.c_str(), name.size());
}
}
std::string cmUuid::FromDigest(const unsigned char* digest,
unsigned char version) const
{
using byte_t = unsigned char;
byte_t uuid[16] = { 0 };
memcpy(uuid, digest, 16);
uuid[6] &= 0xF;
uuid[6] |= static_cast<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 < kUuidGroups.size(); ++i) {
if (i != 0 && input[index++] != '-') {
return false;
}
size_t digits = kUuidGroups[i] * 2;
if (!this->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 < kUuidGroups.size(); ++i) {
if (i != 0) {
output += '-';
}
size_t bytes = kUuidGroups[i];
for (size_t j = 0; j < bytes; ++j) {
unsigned char inputByte = input[inputIndex++];
output += this->ByteToHex(inputByte);
}
}
return output;
}
std::string cmUuid::ByteToHex(unsigned char inputByte) const
{
std::string result(" ");
for (int i = 0; i < 2; ++i) {
unsigned char rest = inputByte % 16;
inputByte /= 16;
char c = (rest < 0xA) ? static_cast<char>('0' + rest)
: static_cast<char>('a' + (rest - 0xA));
result.at(1 - i) = c;
}
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 (!this->IntFromHexDigit(input[i], c1)) {
return false;
}
char c2 = 0;
if (!this->IntFromHexDigit(input[i + 1], c2)) {
return false;
}
output.push_back(static_cast<char>(c1 << 4 | c2));
}
return true;
}
bool cmUuid::IntFromHexDigit(char input, char& output) const
{
if (input >= '0' && input <= '9') {
output = static_cast<char>(input - '0');
return true;
}
if (input >= 'a' && input <= 'f') {
output = static_cast<char>(input - 'a' + 0xA);
return true;
}
if (input >= 'A' && input <= 'F') {
output = static_cast<char>(input - 'A' + 0xA);
return true;
}
return false;
}
|