Line data Source code
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 : /// 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 : /// 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 : /// Discriminator between the two states of the `Data` member.
72 : bool DataIsHexString = true;
73 :
74 : public:
75 1611 : BinaryRef() = default;
76 83 : 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 : /// 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 3573 : if (DataIsHexString)
84 2409 : return Data.size() / 2;
85 1164 : return Data.size();
86 : }
87 :
88 : /// 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 : /// 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 1432 : static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
111 : };
112 :
113 : } // end namespace yaml
114 :
115 : } // end namespace llvm
116 :
117 : #endif // LLVM_OBJECTYAML_YAML_H
|