#include "lldb/Utility/UUID.h"
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include <cctype>
#include <cstdio>
#include <cstring>
using namespace lldb_private;
static inline bool separate(size_t count) {
if (count >= 10)
return (count - 10) % 6 == 0;
switch (count) {
case 4:
case 6:
case 8:
return true;
default:
return false;
}
}
UUID::UUID(UUID::CvRecordPdb70 debug_info) {
llvm::sys::swapByteOrder(debug_info.Uuid.Data1);
llvm::sys::swapByteOrder(debug_info.Uuid.Data2);
llvm::sys::swapByteOrder(debug_info.Uuid.Data3);
llvm::sys::swapByteOrder(debug_info.Age);
if (debug_info.Age)
*this = UUID(&debug_info, sizeof(debug_info));
else
*this = UUID(&debug_info.Uuid, sizeof(debug_info.Uuid));
}
std::string UUID::GetAsString(llvm::StringRef separator) const {
std::string result;
llvm::raw_string_ostream os(result);
for (auto B : llvm::enumerate(GetBytes())) {
if (separate(B.index()))
os << separator;
os << llvm::format_hex_no_prefix(B.value(), 2, true);
}
os.flush();
return result;
}
void UUID::Dump(Stream &s) const { s.PutCString(GetAsString()); }
static inline int xdigit_to_int(char ch) {
ch = tolower(ch);
if (ch >= 'a' && ch <= 'f')
return 10 + ch - 'a';
return ch - '0';
}
llvm::StringRef
UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
llvm::SmallVectorImpl<uint8_t> &uuid_bytes) {
uuid_bytes.clear();
while (p.size() >= 2) {
if (isxdigit(p[0]) && isxdigit(p[1])) {
int hi_nibble = xdigit_to_int(p[0]);
int lo_nibble = xdigit_to_int(p[1]);
uuid_bytes.push_back((hi_nibble << 4) + lo_nibble);
p = p.drop_front(2);
} else if (p.front() == '-') {
p = p.drop_front();
} else {
break;
}
}
return p;
}
bool UUID::SetFromStringRef(llvm::StringRef str) {
llvm::StringRef p = str;
p = p.ltrim();
llvm::SmallVector<uint8_t, 20> bytes;
llvm::StringRef rest = UUID::DecodeUUIDBytesFromString(p, bytes);
if (!rest.empty() || bytes.empty())
return false;
*this = UUID(bytes);
return true;
}