Home | History | Annotate | Download | only in MC
      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:
     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 
     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