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 <ctype.h> 16 #include <stdio.h> 17 #include <string.h> 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 std::string UUID::GetAsString(llvm::StringRef separator) const { 39 std::string result; 40 llvm::raw_string_ostream os(result); 41 42 for (auto B : llvm::enumerate(GetBytes())) { 43 if (separate(B.index())) 44 os << separator; 45 46 os << llvm::format_hex_no_prefix(B.value(), 2, true); 47 } 48 os.flush(); 49 50 return result; 51 } 52 53 void UUID::Dump(Stream *s) const { s->PutCString(GetAsString()); } 54 55 static inline int xdigit_to_int(char ch) { 56 ch = tolower(ch); 57 if (ch >= 'a' && ch <= 'f') 58 return 10 + ch - 'a'; 59 return ch - '0'; 60 } 61 62 llvm::StringRef 63 UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 64 llvm::SmallVectorImpl<uint8_t> &uuid_bytes) { 65 uuid_bytes.clear(); 66 while (p.size() >= 2) { 67 if (isxdigit(p[0]) && isxdigit(p[1])) { 68 int hi_nibble = xdigit_to_int(p[0]); 69 int lo_nibble = xdigit_to_int(p[1]); 70 // Translate the two hex nibble characters into a byte 71 uuid_bytes.push_back((hi_nibble << 4) + lo_nibble); 72 73 // Skip both hex digits 74 p = p.drop_front(2); 75 } else if (p.front() == '-') { 76 // Skip dashes 77 p = p.drop_front(); 78 } else { 79 // UUID values can only consist of hex characters and '-' chars 80 break; 81 } 82 } 83 return p; 84 } 85 86 bool UUID::SetFromStringRef(llvm::StringRef str) { 87 llvm::StringRef p = str; 88 89 // Skip leading whitespace characters 90 p = p.ltrim(); 91 92 llvm::SmallVector<uint8_t, 20> bytes; 93 llvm::StringRef rest = UUID::DecodeUUIDBytesFromString(p, bytes); 94 95 // Return false if we could not consume the entire string or if the parsed 96 // UUID is empty. 97 if (!rest.empty() || bytes.empty()) 98 return false; 99 100 *this = fromData(bytes); 101 return true; 102 } 103 104 bool UUID::SetFromOptionalStringRef(llvm::StringRef str) { 105 bool result = SetFromStringRef(str); 106 if (result) { 107 if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; })) 108 Clear(); 109 } 110 111 return result; 112 } 113