YAML.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- YAML.h ---------------------------------------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_OBJECTYAML_YAML_H
  14. #define LLVM_OBJECTYAML_YAML_H
  15. #include "llvm/ADT/ArrayRef.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/Support/YAMLTraits.h"
  18. #include <cstdint>
  19. namespace llvm {
  20. class raw_ostream;
  21. namespace yaml {
  22. /// Specialized YAMLIO scalar type for representing a binary blob.
  23. ///
  24. /// A typical use case would be to represent the content of a section in a
  25. /// binary file.
  26. /// This class has custom YAMLIO traits for convenient reading and writing.
  27. /// It renders as a string of hex digits in a YAML file.
  28. /// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not
  29. /// require the quotation marks, so for simplicity when outputting they are
  30. /// omitted).
  31. /// When reading, any string whose content is an even number of hex digits
  32. /// will be accepted.
  33. /// For example, all of the following are acceptable:
  34. /// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D')
  35. ///
  36. /// A significant advantage of using this class is that it never allocates
  37. /// temporary strings or buffers for any of its functionality.
  38. ///
  39. /// Example:
  40. ///
  41. /// The YAML mapping:
  42. /// \code
  43. /// Foo: DEADBEEFCAFEBABE
  44. /// \endcode
  45. ///
  46. /// Could be modeled in YAMLIO by the struct:
  47. /// \code
  48. /// struct FooHolder {
  49. /// BinaryRef Foo;
  50. /// };
  51. /// namespace llvm {
  52. /// namespace yaml {
  53. /// template <>
  54. /// struct MappingTraits<FooHolder> {
  55. /// static void mapping(IO &IO, FooHolder &FH) {
  56. /// IO.mapRequired("Foo", FH.Foo);
  57. /// }
  58. /// };
  59. /// } // end namespace yaml
  60. /// } // end namespace llvm
  61. /// \endcode
  62. class BinaryRef {
  63. friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS);
  64. /// Either raw binary data, or a string of hex bytes (must always
  65. /// be an even number of characters).
  66. ArrayRef<uint8_t> Data;
  67. /// Discriminator between the two states of the `Data` member.
  68. bool DataIsHexString = true;
  69. public:
  70. BinaryRef() = default;
  71. BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {}
  72. BinaryRef(StringRef Data) : Data(arrayRefFromStringRef(Data)) {}
  73. /// The number of bytes that are represented by this BinaryRef.
  74. /// This is the number of bytes that writeAsBinary() will write.
  75. ArrayRef<uint8_t>::size_type binary_size() const {
  76. if (DataIsHexString)
  77. return Data.size() / 2;
  78. return Data.size();
  79. }
  80. /// Write the contents (regardless of whether it is binary or a
  81. /// hex string) as binary to the given raw_ostream.
  82. /// N can be used to specify the maximum number of bytes.
  83. void writeAsBinary(raw_ostream &OS, uint64_t N = UINT64_MAX) const;
  84. /// Write the contents (regardless of whether it is binary or a
  85. /// hex string) as hex to the given raw_ostream.
  86. ///
  87. /// For example, a possible output could be `DEADBEEFCAFEBABE`.
  88. void writeAsHex(raw_ostream &OS) const;
  89. };
  90. inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) {
  91. // Special case for default constructed BinaryRef.
  92. if (LHS.Data.empty() && RHS.Data.empty())
  93. return true;
  94. return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data;
  95. }
  96. template <> struct ScalarTraits<BinaryRef> {
  97. static void output(const BinaryRef &, void *, raw_ostream &);
  98. static StringRef input(StringRef, void *, BinaryRef &);
  99. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  100. };
  101. } // end namespace yaml
  102. } // end namespace llvm
  103. #endif // LLVM_OBJECTYAML_YAML_H
  104. #ifdef __GNUC__
  105. #pragma GCC diagnostic pop
  106. #endif