YAML.h 3.1 KB

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