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