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