180814287SRaphael Isemann //===-- UUID.cpp ----------------------------------------------------------===//
20e1d52aeSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60e1d52aeSZachary Turner //
70e1d52aeSZachary Turner //===----------------------------------------------------------------------===//
80e1d52aeSZachary Turner
90e1d52aeSZachary Turner #include "lldb/Utility/UUID.h"
100e1d52aeSZachary Turner
11666cc0b2SZachary Turner #include "lldb/Utility/Stream.h"
12666cc0b2SZachary Turner #include "llvm/ADT/StringRef.h"
1377c397f4SPavel Labath #include "llvm/Support/Format.h"
14666cc0b2SZachary Turner
15*76e47d48SRaphael Isemann #include <cctype>
16*76e47d48SRaphael Isemann #include <cstdio>
17*76e47d48SRaphael Isemann #include <cstring>
180e1d52aeSZachary Turner
19a174bcbfSPavel Labath using namespace lldb_private;
200e1d52aeSZachary Turner
2177c397f4SPavel Labath // Whether to put a separator after count uuid bytes.
2277c397f4SPavel Labath // For the first 16 bytes we follow the traditional UUID format. After that, we
2377c397f4SPavel Labath // simply put a dash after every 6 bytes.
separate(size_t count)2477c397f4SPavel Labath static inline bool separate(size_t count) {
2577c397f4SPavel Labath if (count >= 10)
2677c397f4SPavel Labath return (count - 10) % 6 == 0;
270e1d52aeSZachary Turner
2877c397f4SPavel Labath switch (count) {
2977c397f4SPavel Labath case 4:
3077c397f4SPavel Labath case 6:
3177c397f4SPavel Labath case 8:
3277c397f4SPavel Labath return true;
3377c397f4SPavel Labath default:
3477c397f4SPavel Labath return false;
3577c397f4SPavel Labath }
360e1d52aeSZachary Turner }
370e1d52aeSZachary Turner
fromCvRecord(UUID::CvRecordPdb70 debug_info)384348e0eeSZequan Wu UUID UUID::fromCvRecord(UUID::CvRecordPdb70 debug_info) {
394348e0eeSZequan Wu llvm::sys::swapByteOrder(debug_info.Uuid.Data1);
404348e0eeSZequan Wu llvm::sys::swapByteOrder(debug_info.Uuid.Data2);
414348e0eeSZequan Wu llvm::sys::swapByteOrder(debug_info.Uuid.Data3);
424348e0eeSZequan Wu llvm::sys::swapByteOrder(debug_info.Age);
434348e0eeSZequan Wu if (debug_info.Age)
444348e0eeSZequan Wu return UUID::fromOptionalData(&debug_info, sizeof(debug_info));
454348e0eeSZequan Wu return UUID::fromOptionalData(&debug_info.Uuid, sizeof(debug_info.Uuid));
464348e0eeSZequan Wu }
474348e0eeSZequan Wu
GetAsString(llvm::StringRef separator) const4877c397f4SPavel Labath std::string UUID::GetAsString(llvm::StringRef separator) const {
490e1d52aeSZachary Turner std::string result;
5077c397f4SPavel Labath llvm::raw_string_ostream os(result);
5177c397f4SPavel Labath
5277c397f4SPavel Labath for (auto B : llvm::enumerate(GetBytes())) {
5377c397f4SPavel Labath if (separate(B.index()))
5477c397f4SPavel Labath os << separator;
5577c397f4SPavel Labath
5677c397f4SPavel Labath os << llvm::format_hex_no_prefix(B.value(), 2, true);
570e1d52aeSZachary Turner }
5877c397f4SPavel Labath os.flush();
5977c397f4SPavel Labath
600e1d52aeSZachary Turner return result;
610e1d52aeSZachary Turner }
620e1d52aeSZachary Turner
Dump(Stream * s) const6365e5e278SJonas Devlieghere void UUID::Dump(Stream *s) const { s->PutCString(GetAsString()); }
640e1d52aeSZachary Turner
xdigit_to_int(char ch)650e1d52aeSZachary Turner static inline int xdigit_to_int(char ch) {
660e1d52aeSZachary Turner ch = tolower(ch);
670e1d52aeSZachary Turner if (ch >= 'a' && ch <= 'f')
680e1d52aeSZachary Turner return 10 + ch - 'a';
690e1d52aeSZachary Turner return ch - '0';
700e1d52aeSZachary Turner }
710e1d52aeSZachary Turner
7277c397f4SPavel Labath llvm::StringRef
DecodeUUIDBytesFromString(llvm::StringRef p,llvm::SmallVectorImpl<uint8_t> & uuid_bytes)7377c397f4SPavel Labath UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
741beffc18SJaroslav Sevcik llvm::SmallVectorImpl<uint8_t> &uuid_bytes) {
7577c397f4SPavel Labath uuid_bytes.clear();
761beffc18SJaroslav Sevcik while (p.size() >= 2) {
770e1d52aeSZachary Turner if (isxdigit(p[0]) && isxdigit(p[1])) {
780e1d52aeSZachary Turner int hi_nibble = xdigit_to_int(p[0]);
790e1d52aeSZachary Turner int lo_nibble = xdigit_to_int(p[1]);
800e1d52aeSZachary Turner // Translate the two hex nibble characters into a byte
8177c397f4SPavel Labath uuid_bytes.push_back((hi_nibble << 4) + lo_nibble);
820e1d52aeSZachary Turner
830e1d52aeSZachary Turner // Skip both hex digits
840e1d52aeSZachary Turner p = p.drop_front(2);
850e1d52aeSZachary Turner } else if (p.front() == '-') {
860e1d52aeSZachary Turner // Skip dashes
870e1d52aeSZachary Turner p = p.drop_front();
880e1d52aeSZachary Turner } else {
890e1d52aeSZachary Turner // UUID values can only consist of hex characters and '-' chars
900e1d52aeSZachary Turner break;
910e1d52aeSZachary Turner }
920e1d52aeSZachary Turner }
930e1d52aeSZachary Turner return p;
940e1d52aeSZachary Turner }
950e1d52aeSZachary Turner
SetFromStringRef(llvm::StringRef str)961beffc18SJaroslav Sevcik bool UUID::SetFromStringRef(llvm::StringRef str) {
972833321fSZachary Turner llvm::StringRef p = str;
980e1d52aeSZachary Turner
990e1d52aeSZachary Turner // Skip leading whitespace characters
1000e1d52aeSZachary Turner p = p.ltrim();
1010e1d52aeSZachary Turner
10277c397f4SPavel Labath llvm::SmallVector<uint8_t, 20> bytes;
1031beffc18SJaroslav Sevcik llvm::StringRef rest = UUID::DecodeUUIDBytesFromString(p, bytes);
1040e1d52aeSZachary Turner
1051beffc18SJaroslav Sevcik // Return false if we could not consume the entire string or if the parsed
1061beffc18SJaroslav Sevcik // UUID is empty.
1071beffc18SJaroslav Sevcik if (!rest.empty() || bytes.empty())
1081beffc18SJaroslav Sevcik return false;
1091beffc18SJaroslav Sevcik
11077c397f4SPavel Labath *this = fromData(bytes);
1111beffc18SJaroslav Sevcik return true;
1120e1d52aeSZachary Turner }
1130e1d52aeSZachary Turner
SetFromOptionalStringRef(llvm::StringRef str)1141beffc18SJaroslav Sevcik bool UUID::SetFromOptionalStringRef(llvm::StringRef str) {
1151beffc18SJaroslav Sevcik bool result = SetFromStringRef(str);
1161beffc18SJaroslav Sevcik if (result) {
117f3ecbfc1SJim Ingham if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; }))
118f3ecbfc1SJim Ingham Clear();
119f3ecbfc1SJim Ingham }
120f3ecbfc1SJim Ingham
1211beffc18SJaroslav Sevcik return result;
122f3ecbfc1SJim Ingham }
123