15fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//===- YAML.h - YAMLIO utilities for object files ---------------*- C++ -*-===//
25fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//
35fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//                     The LLVM Compiler Infrastructure
45fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//
55fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola// This file is distributed under the University of Illinois Open Source
65fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola// License. See LICENSE.TXT for details.
75fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//
85fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//===----------------------------------------------------------------------===//
95fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//
105fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola// This file declares utility classes for handling the YAML representation of
115fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola// object files.
125fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//
135fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola//===----------------------------------------------------------------------===//
145fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
155fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola#ifndef LLVM_OBJECT_YAML_H
165fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola#define LLVM_OBJECT_YAML_H
175fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
185fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola#include "llvm/Support/YAMLTraits.h"
195fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
205fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolanamespace llvm {
215fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolanamespace object {
225fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolanamespace yaml {
235fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
24272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// \brief Specialized YAMLIO scalar type for representing a binary blob.
25272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///
26272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// A typical use case would be to represent the content of a section in a
27272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// binary file.
28272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// This class has custom YAMLIO traits for convenient reading and writing.
29272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// It renders as a string of hex digits in a YAML file.
30272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not
31272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// require the quotation marks, so for simplicity when outputting they are
32272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// omitted).
33272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// When reading, any string whose content is an even number of hex digits
34272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// will be accepted.
35272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// For example, all of the following are acceptable:
36272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D')
37272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///
38272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// A significant advantage of using this class is that it never allocates
39272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// temporary strings or buffers for any of its functionality.
40272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///
41272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// Example:
42272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///
43272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// The YAML mapping:
44272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// \code
45272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// Foo: DEADBEEFCAFEBABE
46272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// \endcode
47272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///
48272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// Could be modeled in YAMLIO by the struct:
49272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// \code
50272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// struct FooHolder {
51272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///   BinaryRef Foo;
52272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// };
53272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// namespace llvm {
54272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// namespace yaml {
55272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// template <>
56272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// struct MappingTraits<FooHolder> {
57272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///   static void mapping(IO &IO, FooHolder &FH) {
58272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///     IO.mapRequired("Foo", FH.Foo);
59272d881234dac8d51bccf90d52550ee4da888c94Sean Silva///   }
60272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// };
61272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// } // end namespace yaml
62272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// } // end namespace llvm
63272d881234dac8d51bccf90d52550ee4da888c94Sean Silva/// \endcode
645fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolaclass BinaryRef {
65814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola  friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS);
662b1068952ade3a1d2c704e7589c54e3d32dc0eb8Sean Silva  /// \brief Either raw binary data, or a string of hex bytes (must always
672b1068952ade3a1d2c704e7589c54e3d32dc0eb8Sean Silva  /// be an even number of characters).
685fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola  ArrayRef<uint8_t> Data;
696acc982e74cd8a10d097c10254d7215028e7f036Sean Silva  /// \brief Discriminator between the two states of the `Data` member.
706acc982e74cd8a10d097c10254d7215028e7f036Sean Silva  bool DataIsHexString;
715fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
725fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolapublic:
736acc982e74cd8a10d097c10254d7215028e7f036Sean Silva  BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {}
745fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola  BinaryRef(StringRef Data)
755fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola      : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()),
766acc982e74cd8a10d097c10254d7215028e7f036Sean Silva        DataIsHexString(true) {}
776acc982e74cd8a10d097c10254d7215028e7f036Sean Silva  BinaryRef() : DataIsHexString(true) {}
7863958fba58716ed435563321944f7d4663d2ee2dSean Silva  /// \brief The number of bytes that are represented by this BinaryRef.
7963958fba58716ed435563321944f7d4663d2ee2dSean Silva  /// This is the number of bytes that writeAsBinary() will write.
8063958fba58716ed435563321944f7d4663d2ee2dSean Silva  ArrayRef<uint8_t>::size_type binary_size() const {
816acc982e74cd8a10d097c10254d7215028e7f036Sean Silva    if (DataIsHexString)
8263958fba58716ed435563321944f7d4663d2ee2dSean Silva      return Data.size() / 2;
8363958fba58716ed435563321944f7d4663d2ee2dSean Silva    return Data.size();
8463958fba58716ed435563321944f7d4663d2ee2dSean Silva  }
85639adc59f86d0526dbace4a1ecc4924c6c52e1cdSean Silva  /// \brief Write the contents (regardless of whether it is binary or a
86639adc59f86d0526dbace4a1ecc4924c6c52e1cdSean Silva  /// hex string) as binary to the given raw_ostream.
87639adc59f86d0526dbace4a1ecc4924c6c52e1cdSean Silva  void writeAsBinary(raw_ostream &OS) const;
884370ddb8b821bda66478160c1a1c5714a1877d85Sean Silva  /// \brief Write the contents (regardless of whether it is binary or a
894370ddb8b821bda66478160c1a1c5714a1877d85Sean Silva  /// hex string) as hex to the given raw_ostream.
904370ddb8b821bda66478160c1a1c5714a1877d85Sean Silva  ///
914370ddb8b821bda66478160c1a1c5714a1877d85Sean Silva  /// For example, a possible output could be `DEADBEEFCAFEBABE`.
924370ddb8b821bda66478160c1a1c5714a1877d85Sean Silva  void writeAsHex(raw_ostream &OS) const;
935fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola};
945fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
95814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindolainline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) {
96814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola  // Special case for default constructed BinaryRef.
97814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola  if (LHS.Data.empty() && RHS.Data.empty())
98814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola    return true;
99814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola
100814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola  return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data;
101814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola}
102814b52710ad53e6d613aebaca8df8e962a432f50Rafael Espindola
1035fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola}
1045fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola}
1055fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
1065fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolanamespace yaml {
1075fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindolatemplate <> struct ScalarTraits<object::yaml::BinaryRef> {
1085fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola  static void output(const object::yaml::BinaryRef &, void *,
1095fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola                     llvm::raw_ostream &);
1105fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola  static StringRef input(StringRef, void *, object::yaml::BinaryRef &);
1115fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola};
1125fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola}
1135fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
1145fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola}
1155fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola
1165fd5fe0f7bfac0f7973475fcf7a5f8061d983538Rafael Espindola#endif
117