1 #ifndef LLVM_MC_YAML_H 2 #define LLVM_MC_YAML_H 3 4 #include "llvm/Support/YAMLTraits.h" 5 6 namespace llvm { 7 namespace 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 48 class 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 56 public: BinaryRef(ArrayRef<uint8_t> Data)57 BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {} BinaryRef(StringRef Data)58 BinaryRef(StringRef Data) 59 : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()), 60 DataIsHexString(true) {} BinaryRef()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. binary_size()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 79 inline 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 87 template <> 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