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.
separate(size_t count)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
GetAsString(llvm::StringRef separator) const39 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
Dump(Stream * s) const54 void UUID::Dump(Stream *s) const { s->PutCString(GetAsString()); }
55
xdigit_to_int(char ch)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
DecodeUUIDBytesFromString(llvm::StringRef p,llvm::SmallVectorImpl<uint8_t> & uuid_bytes,uint32_t num_uuid_bytes)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
SetFromStringRef(llvm::StringRef str,uint32_t num_uuid_bytes)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