Home | History | Annotate | Download | only in ObjectYAML
      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:
     66   BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {}
     67   BinaryRef(StringRef Data)
     68       : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()),
     69         DataIsHexString(true) {}
     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.
     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