1259698Sdim//===- YAML.cpp - YAMLIO utilities for object files -----------------------===//
2259698Sdim//
3259698Sdim//                     The LLVM Compiler Infrastructure
4259698Sdim//
5259698Sdim// This file is distributed under the University of Illinois Open Source
6259698Sdim// License. See LICENSE.TXT for details.
7259698Sdim//
8259698Sdim//===----------------------------------------------------------------------===//
9259698Sdim//
10259698Sdim// This file defines utility classes for handling the YAML representation of
11259698Sdim// object files.
12259698Sdim//
13259698Sdim//===----------------------------------------------------------------------===//
14259698Sdim
15259698Sdim#include "llvm/Object/YAML.h"
16259698Sdim#include "llvm/ADT/StringExtras.h"
17259698Sdim#include "llvm/Support/raw_ostream.h"
18259698Sdim#include <cctype>
19259698Sdim
20259698Sdimusing namespace llvm;
21259698Sdimusing namespace object::yaml;
22259698Sdim
23259698Sdimvoid yaml::ScalarTraits<object::yaml::BinaryRef>::output(
24259698Sdim    const object::yaml::BinaryRef &Val, void *, llvm::raw_ostream &Out) {
25259698Sdim  Val.writeAsHex(Out);
26259698Sdim}
27259698Sdim
28259698SdimStringRef yaml::ScalarTraits<object::yaml::BinaryRef>::input(
29259698Sdim    StringRef Scalar, void *, object::yaml::BinaryRef &Val) {
30259698Sdim  if (Scalar.size() % 2 != 0)
31259698Sdim    return "BinaryRef hex string must contain an even number of nybbles.";
32259698Sdim  // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here?
33259698Sdim  // (e.g. a caret pointing to the offending character).
34259698Sdim  for (unsigned I = 0, N = Scalar.size(); I != N; ++I)
35259698Sdim    if (!isxdigit(Scalar[I]))
36259698Sdim      return "BinaryRef hex string must contain only hex digits.";
37259698Sdim  Val = object::yaml::BinaryRef(Scalar);
38259698Sdim  return StringRef();
39259698Sdim}
40259698Sdim
41259698Sdimvoid BinaryRef::writeAsBinary(raw_ostream &OS) const {
42259698Sdim  if (!DataIsHexString) {
43259698Sdim    OS.write((const char *)Data.data(), Data.size());
44259698Sdim    return;
45259698Sdim  }
46259698Sdim  for (unsigned I = 0, N = Data.size(); I != N; I += 2) {
47259698Sdim    uint8_t Byte;
48259698Sdim    StringRef((const char *)&Data[I],  2).getAsInteger(16, Byte);
49259698Sdim    OS.write(Byte);
50259698Sdim  }
51259698Sdim}
52259698Sdim
53259698Sdimvoid BinaryRef::writeAsHex(raw_ostream &OS) const {
54259698Sdim  if (binary_size() == 0) {
55259698Sdim    OS << "\"\"";
56259698Sdim    return;
57259698Sdim  }
58259698Sdim  if (DataIsHexString) {
59259698Sdim    OS.write((const char *)Data.data(), Data.size());
60259698Sdim    return;
61259698Sdim  }
62259698Sdim  for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E;
63259698Sdim       ++I) {
64259698Sdim    uint8_t Byte = *I;
65259698Sdim    OS << hexdigit(Byte >> 4);
66259698Sdim    OS << hexdigit(Byte & 0xf);
67259698Sdim  }
68259698Sdim}
69