//===-- UUID.cpp ----------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "lldb/Utility/UUID.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Format.h" #include #include #include using namespace lldb_private; // Whether to put a separator after count uuid bytes. // For the first 16 bytes we follow the traditional UUID format. After that, we // simply put a dash after every 6 bytes. static inline bool separate(size_t count) { if (count >= 10) return (count - 10) % 6 == 0; switch (count) { case 4: case 6: case 8: return true; default: return false; } } UUID UUID::fromCvRecord(UUID::CvRecordPdb70 debug_info) { llvm::sys::swapByteOrder(debug_info.Uuid.Data1); llvm::sys::swapByteOrder(debug_info.Uuid.Data2); llvm::sys::swapByteOrder(debug_info.Uuid.Data3); llvm::sys::swapByteOrder(debug_info.Age); if (debug_info.Age) return UUID::fromOptionalData(&debug_info, sizeof(debug_info)); return UUID::fromOptionalData(&debug_info.Uuid, sizeof(debug_info.Uuid)); } std::string UUID::GetAsString(llvm::StringRef separator) const { std::string result; llvm::raw_string_ostream os(result); for (auto B : llvm::enumerate(GetBytes())) { if (separate(B.index())) os << separator; os << llvm::format_hex_no_prefix(B.value(), 2, true); } os.flush(); return result; } void UUID::Dump(Stream *s) const { s->PutCString(GetAsString()); } static inline int xdigit_to_int(char ch) { ch = tolower(ch); if (ch >= 'a' && ch <= 'f') return 10 + ch - 'a'; return ch - '0'; } llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p, llvm::SmallVectorImpl &uuid_bytes) { uuid_bytes.clear(); while (p.size() >= 2) { if (isxdigit(p[0]) && isxdigit(p[1])) { int hi_nibble = xdigit_to_int(p[0]); int lo_nibble = xdigit_to_int(p[1]); // Translate the two hex nibble characters into a byte uuid_bytes.push_back((hi_nibble << 4) + lo_nibble); // Skip both hex digits p = p.drop_front(2); } else if (p.front() == '-') { // Skip dashes p = p.drop_front(); } else { // UUID values can only consist of hex characters and '-' chars break; } } return p; } bool UUID::SetFromStringRef(llvm::StringRef str) { llvm::StringRef p = str; // Skip leading whitespace characters p = p.ltrim(); llvm::SmallVector bytes; llvm::StringRef rest = UUID::DecodeUUIDBytesFromString(p, bytes); // Return false if we could not consume the entire string or if the parsed // UUID is empty. if (!rest.empty() || bytes.empty()) return false; *this = fromData(bytes); return true; } bool UUID::SetFromOptionalStringRef(llvm::StringRef str) { bool result = SetFromStringRef(str); if (result) { if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; })) Clear(); } return result; }