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 { s->PutCString(GetAsString()); } 55 56 static inline int xdigit_to_int(char ch) { 57 ch = tolower(ch); 58 if (ch >= 'a' && ch <= 'f') 59 return 10 + ch - 'a'; 60 return ch - '0'; 61 } 62 63 llvm::StringRef 64 UUID::DecodeUUIDBytesFromString(llvm::StringRef p, 65 llvm::SmallVectorImpl<uint8_t> &uuid_bytes, 66 uint32_t num_uuid_bytes) { 67 uuid_bytes.clear(); 68 while (!p.empty()) { 69 if (isxdigit(p[0]) && isxdigit(p[1])) { 70 int hi_nibble = xdigit_to_int(p[0]); 71 int lo_nibble = xdigit_to_int(p[1]); 72 // Translate the two hex nibble characters into a byte 73 uuid_bytes.push_back((hi_nibble << 4) + lo_nibble); 74 75 // Skip both hex digits 76 p = p.drop_front(2); 77 78 // Increment the byte that we are decoding within the UUID value and 79 // break out if we are done 80 if (uuid_bytes.size() == num_uuid_bytes) 81 break; 82 } else if (p.front() == '-') { 83 // Skip dashes 84 p = p.drop_front(); 85 } else { 86 // UUID values can only consist of hex characters and '-' chars 87 break; 88 } 89 } 90 return p; 91 } 92 93 size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) { 94 llvm::StringRef p = str; 95 96 // Skip leading whitespace characters 97 p = p.ltrim(); 98 99 llvm::SmallVector<uint8_t, 20> bytes; 100 llvm::StringRef rest = 101 UUID::DecodeUUIDBytesFromString(p, bytes, num_uuid_bytes); 102 103 // If we successfully decoded a UUID, return the amount of characters that 104 // were consumed 105 if (bytes.size() == num_uuid_bytes) { 106 *this = fromData(bytes); 107 return str.size() - rest.size(); 108 } 109 110 // Else return zero to indicate we were not able to parse a UUID value 111 return 0; 112 } 113