brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 4e06f91 Raw
134 lines · cpp
1//===-- UUID.cpp ----------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Utility/UUID.h"10 11#include "lldb/Utility/Stream.h"12#include "llvm/ADT/StringRef.h"13#include "llvm/Support/Format.h"14#include "llvm/Support/RandomNumberGenerator.h"15 16#include <cctype>17#include <chrono>18#include <climits>19#include <cstdint>20#include <cstdio>21#include <cstring>22#include <random>23 24using namespace lldb_private;25 26// Whether to put a separator after count uuid bytes.27// For the first 16 bytes we follow the traditional UUID format. After that, we28// simply put a dash after every 6 bytes.29static inline bool separate(size_t count) {30  if (count >= 10)31    return (count - 10) % 6 == 0;32 33  switch (count) {34  case 4:35  case 6:36  case 8:37    return true;38  default:39    return false;40  }41}42 43UUID::UUID(UUID::CvRecordPdb70 debug_info) {44  llvm::sys::swapByteOrder(debug_info.Uuid.Data1);45  llvm::sys::swapByteOrder(debug_info.Uuid.Data2);46  llvm::sys::swapByteOrder(debug_info.Uuid.Data3);47  llvm::sys::swapByteOrder(debug_info.Age);48  if (debug_info.Age)49    *this = UUID(&debug_info, sizeof(debug_info));50  else51    *this = UUID(&debug_info.Uuid, sizeof(debug_info.Uuid));52}53 54std::string UUID::GetAsString(llvm::StringRef separator) const {55  std::string result;56  llvm::raw_string_ostream os(result);57 58  for (auto B : llvm::enumerate(GetBytes())) {59    if (separate(B.index()))60      os << separator;61 62    os << llvm::format_hex_no_prefix(B.value(), 2, true);63  }64 65  return result;66}67 68void UUID::Dump(Stream &s) const { s.PutCString(GetAsString()); }69 70static inline int xdigit_to_int(char ch) {71  ch = tolower(ch);72  if (ch >= 'a' && ch <= 'f')73    return 10 + ch - 'a';74  return ch - '0';75}76 77llvm::StringRef78UUID::DecodeUUIDBytesFromString(llvm::StringRef p,79                                llvm::SmallVectorImpl<uint8_t> &uuid_bytes) {80  uuid_bytes.clear();81  while (p.size() >= 2) {82    if (isxdigit(p[0]) && isxdigit(p[1])) {83      int hi_nibble = xdigit_to_int(p[0]);84      int lo_nibble = xdigit_to_int(p[1]);85      // Translate the two hex nibble characters into a byte86      uuid_bytes.push_back((hi_nibble << 4) + lo_nibble);87 88      // Skip both hex digits89      p = p.drop_front(2);90    } else if (p.front() == '-') {91      // Skip dashes92      p = p.drop_front();93    } else {94      // UUID values can only consist of hex characters and '-' chars95      break;96    }97  }98  return p;99}100 101bool UUID::SetFromStringRef(llvm::StringRef str) {102  llvm::StringRef p = str;103 104  // Skip leading whitespace characters105  p = p.ltrim();106 107  llvm::SmallVector<uint8_t, 20> bytes;108  llvm::StringRef rest = UUID::DecodeUUIDBytesFromString(p, bytes);109 110  // Return false if we could not consume the entire string or if the parsed111  // UUID is empty.112  if (!rest.empty() || bytes.empty())113    return false;114 115  *this = UUID(bytes);116  return true;117}118 119UUID UUID::Generate(uint32_t num_bytes) {120  llvm::SmallVector<uint8_t, 20> bytes(num_bytes);121  auto ec = llvm::getRandomBytes(bytes.data(), bytes.size());122 123  // If getRandomBytes failed, fall back to a lower entropy source.124  if (ec) {125    auto seed = std::chrono::steady_clock::now().time_since_epoch().count();126    std::independent_bits_engine<std::default_random_engine, CHAR_BIT,127                                 unsigned short>128        engine(seed);129    std::generate(bytes.begin(), bytes.end(), std::ref(engine));130  }131 132  return UUID(bytes);133}134