reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
//===-- UUID.cpp ------------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Utility/UUID.h"

#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"

#include <ctype.h>
#include <stdio.h>
#include <string.h>

using namespace lldb_private;

// Whether to put a separator after count uuid bytes.
// For the first 16 bytes we follow the traditional UUID format. After that, we
// simply put a dash after every 6 bytes.
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;
  }
}

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,
                                uint32_t num_uuid_bytes) {
  uuid_bytes.clear();
  while (!p.empty()) {
    if (isxdigit(p[0]) && isxdigit(p[1])) {
      int hi_nibble = xdigit_to_int(p[0]);
      int lo_nibble = xdigit_to_int(p[1]);
      // Translate the two hex nibble characters into a byte
      uuid_bytes.push_back((hi_nibble << 4) + lo_nibble);

      // Skip both hex digits
      p = p.drop_front(2);

      // Increment the byte that we are decoding within the UUID value and
      // break out if we are done
      if (uuid_bytes.size() == num_uuid_bytes)
        break;
    } else if (p.front() == '-') {
      // Skip dashes
      p = p.drop_front();
    } else {
      // UUID values can only consist of hex characters and '-' chars
      break;
    }
  }
  return p;
}

size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) {
  llvm::StringRef p = str;

  // Skip leading whitespace characters
  p = p.ltrim();

  llvm::SmallVector<uint8_t, 20> bytes;
  llvm::StringRef rest =
      UUID::DecodeUUIDBytesFromString(p, bytes, num_uuid_bytes);

  // If we successfully decoded a UUID, return the amount of characters that
  // were consumed
  if (bytes.size() == num_uuid_bytes) {
    *this = fromData(bytes);
    return str.size() - rest.size();
  }

  // Else return zero to indicate we were not able to parse a UUID value
  return 0;
}

size_t UUID::SetFromOptionalStringRef(llvm::StringRef str, 
                                      uint32_t num_uuid_bytes) {
  size_t num_chars_consumed = SetFromStringRef(str, num_uuid_bytes);
  if (num_chars_consumed) {
    if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; }))
        Clear();
  }
  
  return num_chars_consumed;
}