YAML.h revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
1#ifndef LLVM_MC_YAML_H
2#define LLVM_MC_YAML_H
3
4#include "llvm/Support/YAMLTraits.h"
5
6namespace llvm {
7namespace yaml {
8/// \brief Specialized YAMLIO scalar type for representing a binary blob.
9///
10/// A typical use case would be to represent the content of a section in a
11/// binary file.
12/// This class has custom YAMLIO traits for convenient reading and writing.
13/// It renders as a string of hex digits in a YAML file.
14/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not
15/// require the quotation marks, so for simplicity when outputting they are
16/// omitted).
17/// When reading, any string whose content is an even number of hex digits
18/// will be accepted.
19/// For example, all of the following are acceptable:
20/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D')
21///
22/// A significant advantage of using this class is that it never allocates
23/// temporary strings or buffers for any of its functionality.
24///
25/// Example:
26///
27/// The YAML mapping:
28/// \code
29/// Foo: DEADBEEFCAFEBABE
30/// \endcode
31///
32/// Could be modeled in YAMLIO by the struct:
33/// \code
34/// struct FooHolder {
35///   BinaryRef Foo;
36/// };
37/// namespace llvm {
38/// namespace yaml {
39/// template <>
40/// struct MappingTraits<FooHolder> {
41///   static void mapping(IO &IO, FooHolder &FH) {
42///     IO.mapRequired("Foo", FH.Foo);
43///   }
44/// };
45/// } // end namespace yaml
46/// } // end namespace llvm
47/// \endcode
48class BinaryRef {
49  friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS);
50  /// \brief Either raw binary data, or a string of hex bytes (must always
51  /// be an even number of characters).
52  ArrayRef<uint8_t> Data;
53  /// \brief Discriminator between the two states of the `Data` member.
54  bool DataIsHexString;
55
56public:
57  BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {}
58  BinaryRef(StringRef Data)
59      : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()),
60        DataIsHexString(true) {}
61  BinaryRef() : DataIsHexString(true) {}
62  /// \brief The number of bytes that are represented by this BinaryRef.
63  /// This is the number of bytes that writeAsBinary() will write.
64  ArrayRef<uint8_t>::size_type binary_size() const {
65    if (DataIsHexString)
66      return Data.size() / 2;
67    return Data.size();
68  }
69  /// \brief Write the contents (regardless of whether it is binary or a
70  /// hex string) as binary to the given raw_ostream.
71  void writeAsBinary(raw_ostream &OS) const;
72  /// \brief Write the contents (regardless of whether it is binary or a
73  /// hex string) as hex to the given raw_ostream.
74  ///
75  /// For example, a possible output could be `DEADBEEFCAFEBABE`.
76  void writeAsHex(raw_ostream &OS) const;
77};
78
79inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) {
80  // Special case for default constructed BinaryRef.
81  if (LHS.Data.empty() && RHS.Data.empty())
82    return true;
83
84  return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data;
85}
86
87template <> struct ScalarTraits<BinaryRef> {
88  static void output(const BinaryRef &, void *, llvm::raw_ostream &);
89  static StringRef input(StringRef, void *, BinaryRef &);
90  static bool mustQuote(StringRef S) { return needsQuotes(S); }
91};
92}
93}
94#endif
95