1 //===-- UUID.cpp ------------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Utility/UUID.h" 11 12 #include "lldb/Utility/Stream.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/Support/Format.h" 15 16 #include <ctype.h> 17 #include <stdio.h> 18 #include <string.h> 19 20 using namespace lldb_private; 21 22 // Whether to put a separator after count uuid bytes. 23 // For the first 16 bytes we follow the traditional UUID format. After that, we 24 // simply put a dash after every 6 bytes. 25 static inline bool separate(size_t count) { 26 if (count >= 10) 27 return (count - 10) % 6 == 0; 28 29 switch (count) { 30 case 4: 31 case 6: 32 case 8: 33 return true; 34 default: 35 return false; 36 } 37 } 38 39 std::string UUID::GetAsString(llvm::StringRef separator) const { 40 std::string result; 41 llvm::raw_string_ostream os(result); 42 43 for (auto B : llvm::enumerate(GetBytes())) { 44 if (separate(B.index())) 45 os << separator; 46 47 os << llvm::format_hex_no_prefix(B.value(), 2, true); 48 } 49 os.flush(); 50 51 return result; 52 } 53 54 void UUID::Dump(Stream *s) const { 55 s->PutCString(GetAsString().c_str()); 56 } 57 58 static inline int xdigit_to_int(char ch) { 59 ch = tolower(ch); 60 if (ch >= 'a' && ch <= 'f') 61 return 10 + ch - 'a'; 62 return ch - '0'; 63 } 64 65 llvm::StringRef 66 UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 67 llvm::SmallVectorImpl<uint8_t> &uuid_bytes, 68 uint32_t num_uuid_bytes) { 69 uuid_bytes.clear(); 70 while (!p.empty()) { 71 if (isxdigit(p[0]) && isxdigit(p[1])) { 72 int hi_nibble = xdigit_to_int(p[0]); 73 int lo_nibble = xdigit_to_int(p[1]); 74 // Translate the two hex nibble characters into a byte 75 uuid_bytes.push_back((hi_nibble << 4) + lo_nibble); 76 77 // Skip both hex digits 78 p = p.drop_front(2); 79 80 // Increment the byte that we are decoding within the UUID value and 81 // break out if we are done 82 if (uuid_bytes.size() == num_uuid_bytes) 83 break; 84 } else if (p.front() == '-') { 85 // Skip dashes 86 p = p.drop_front(); 87 } else { 88 // UUID values can only consist of hex characters and '-' chars 89 break; 90 } 91 } 92 return p; 93 } 94 95 size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) { 96 llvm::StringRef p = str; 97 98 // Skip leading whitespace characters 99 p = p.ltrim(); 100 101 llvm::SmallVector<uint8_t, 20> bytes; 102 llvm::StringRef rest = 103 UUID::DecodeUUIDBytesFromString(p, bytes, num_uuid_bytes); 104 105 // If we successfully decoded a UUID, return the amount of characters that 106 // were consumed 107 if (bytes.size() == num_uuid_bytes) { 108 *this = fromData(bytes); 109 return str.size() - rest.size(); 110 } 111 112 // Else return zero to indicate we were not able to parse a UUID value 113 return 0; 114 } 115