1 //===-- UUID.cpp ----------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Utility/UUID.h" 10 11 #include "lldb/Utility/Stream.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/Support/Format.h" 14 15 #include <cctype> 16 #include <cstdio> 17 #include <cstring> 18 19 using namespace lldb_private; 20 21 // Whether to put a separator after count uuid bytes. 22 // For the first 16 bytes we follow the traditional UUID format. After that, we 23 // simply put a dash after every 6 bytes. 24 static inline bool separate(size_t count) { 25 if (count >= 10) 26 return (count - 10) % 6 == 0; 27 28 switch (count) { 29 case 4: 30 case 6: 31 case 8: 32 return true; 33 default: 34 return false; 35 } 36 } 37 38 UUID UUID::fromCvRecord(UUID::CvRecordPdb70 debug_info) { 39 llvm::sys::swapByteOrder(debug_info.Uuid.Data1); 40 llvm::sys::swapByteOrder(debug_info.Uuid.Data2); 41 llvm::sys::swapByteOrder(debug_info.Uuid.Data3); 42 llvm::sys::swapByteOrder(debug_info.Age); 43 if (debug_info.Age) 44 return UUID::fromOptionalData(&debug_info, sizeof(debug_info)); 45 return UUID::fromOptionalData(&debug_info.Uuid, sizeof(debug_info.Uuid)); 46 } 47 48 std::string UUID::GetAsString(llvm::StringRef separator) const { 49 std::string result; 50 llvm::raw_string_ostream os(result); 51 52 for (auto B : llvm::enumerate(GetBytes())) { 53 if (separate(B.index())) 54 os << separator; 55 56 os << llvm::format_hex_no_prefix(B.value(), 2, true); 57 } 58 os.flush(); 59 60 return result; 61 } 62 63 void UUID::Dump(Stream *s) const { s->PutCString(GetAsString()); } 64 65 static inline int xdigit_to_int(char ch) { 66 ch = tolower(ch); 67 if (ch >= 'a' && ch <= 'f') 68 return 10 + ch - 'a'; 69 return ch - '0'; 70 } 71 72 llvm::StringRef 73 UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 74 llvm::SmallVectorImpl<uint8_t> &uuid_bytes) { 75 uuid_bytes.clear(); 76 while (p.size() >= 2) { 77 if (isxdigit(p[0]) && isxdigit(p[1])) { 78 int hi_nibble = xdigit_to_int(p[0]); 79 int lo_nibble = xdigit_to_int(p[1]); 80 // Translate the two hex nibble characters into a byte 81 uuid_bytes.push_back((hi_nibble << 4) + lo_nibble); 82 83 // Skip both hex digits 84 p = p.drop_front(2); 85 } else if (p.front() == '-') { 86 // Skip dashes 87 p = p.drop_front(); 88 } else { 89 // UUID values can only consist of hex characters and '-' chars 90 break; 91 } 92 } 93 return p; 94 } 95 96 bool UUID::SetFromStringRef(llvm::StringRef str) { 97 llvm::StringRef p = str; 98 99 // Skip leading whitespace characters 100 p = p.ltrim(); 101 102 llvm::SmallVector<uint8_t, 20> bytes; 103 llvm::StringRef rest = UUID::DecodeUUIDBytesFromString(p, bytes); 104 105 // Return false if we could not consume the entire string or if the parsed 106 // UUID is empty. 107 if (!rest.empty() || bytes.empty()) 108 return false; 109 110 *this = fromData(bytes); 111 return true; 112 } 113 114 bool UUID::SetFromOptionalStringRef(llvm::StringRef str) { 115 bool result = SetFromStringRef(str); 116 if (result) { 117 if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; })) 118 Clear(); 119 } 120 121 return result; 122 } 123