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