LLVM  10.0.0svn
MsgPackDocumentYAML.cpp
Go to the documentation of this file.
1 //===-- MsgPackDocumentYAML.cpp - MsgPack Document YAML interface -------*-===//
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 /// This file implements YAMLIO on a msgpack::Document.
11 //
12 //===----------------------------------------------------------------------===//
13 
16 
17 using namespace llvm;
18 using namespace msgpack;
19 
20 namespace {
21 
22 // Struct used to represent scalar node. (MapDocNode and ArrayDocNode already
23 // exist in MsgPackDocument.h.)
24 struct ScalarDocNode : DocNode {
25  ScalarDocNode(DocNode N) : DocNode(N) {}
26 
27  /// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
28  /// returns something else if the result of toString would be ambiguous, e.g.
29  /// a string that parses as a number or boolean.
30  StringRef getYAMLTag() const;
31 };
32 
33 } // namespace
34 
35 /// Convert this DocNode to a string, assuming it is scalar.
36 std::string DocNode::toString() const {
37  std::string S;
38  raw_string_ostream OS(S);
39  switch (getKind()) {
41  OS << Raw;
42  break;
43  case msgpack::Type::Nil:
44  break;
46  OS << (Bool ? "true" : "false");
47  break;
48  case msgpack::Type::Int:
49  OS << Int;
50  break;
52  if (getDocument()->getHexMode())
53  OS << format("%#llx", (unsigned long long)UInt);
54  else
55  OS << UInt;
56  break;
58  OS << Float;
59  break;
60  default:
61  llvm_unreachable("not scalar");
62  break;
63  }
64  return OS.str();
65 }
66 
67 /// Convert the StringRef and use it to set this DocNode (assuming scalar). If
68 /// it is a string, copy the string into the Document's strings list so we do
69 /// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
71  if (Tag == "tag:yaml.org,2002:str")
72  Tag = "";
73  if (Tag == "!int" || Tag == "") {
74  // Try unsigned int then signed int.
75  *this = getDocument()->getNode(uint64_t(0));
76  StringRef Err = yaml::ScalarTraits<uint64_t>::input(S, nullptr, getUInt());
77  if (Err != "") {
78  *this = getDocument()->getNode(int64_t(0));
79  Err = yaml::ScalarTraits<int64_t>::input(S, nullptr, getInt());
80  }
81  if (Err == "" || Tag != "")
82  return Err;
83  }
84  if (Tag == "!nil") {
85  *this = getDocument()->getNode();
86  return "";
87  }
88  if (Tag == "!bool" || Tag == "") {
89  *this = getDocument()->getNode(false);
90  StringRef Err = yaml::ScalarTraits<bool>::input(S, nullptr, getBool());
91  if (Err == "" || Tag != "")
92  return Err;
93  }
94  if (Tag == "!float" || Tag == "") {
95  *this = getDocument()->getNode(0.0);
96  StringRef Err = yaml::ScalarTraits<double>::input(S, nullptr, getFloat());
97  if (Err == "" || Tag != "")
98  return Err;
99  }
100  assert((Tag == "!str" || Tag == "") && "unsupported tag");
101  std::string V;
102  StringRef Err = yaml::ScalarTraits<std::string>::input(S, nullptr, V);
103  if (Err == "")
104  *this = getDocument()->getNode(V, /*Copy=*/true);
105  return Err;
106 }
107 
108 /// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
109 /// returns something else if the result of toString would be ambiguous, e.g.
110 /// a string that parses as a number or boolean.
111 StringRef ScalarDocNode::getYAMLTag() const {
112  if (getKind() == msgpack::Type::Nil)
113  return "!nil";
114  // Try converting both ways and see if we get the same kind. If not, we need
115  // a tag.
116  ScalarDocNode N = getDocument()->getNode();
117  N.fromString(toString(), "");
118  if (N.getKind() == getKind())
119  return "";
120  // Tolerate signedness of int changing, as tags do not differentiate between
121  // them anyway.
122  if (N.getKind() == msgpack::Type::UInt && getKind() == msgpack::Type::Int)
123  return "";
124  if (N.getKind() == msgpack::Type::Int && getKind() == msgpack::Type::UInt)
125  return "";
126  // We do need a tag.
127  switch (getKind()) {
129  return "!str";
130  case msgpack::Type::Int:
131  return "!int";
132  case msgpack::Type::UInt:
133  return "!int";
135  return "!bool";
137  return "!float";
138  default:
139  llvm_unreachable("unrecognized kind");
140  }
141 }
142 
143 namespace llvm {
144 namespace yaml {
145 
146 /// YAMLIO for DocNode
147 template <> struct PolymorphicTraits<DocNode> {
148 
149  static NodeKind getKind(const DocNode &N) {
150  switch (N.getKind()) {
151  case msgpack::Type::Map:
152  return NodeKind::Map;
154  return NodeKind::Sequence;
155  default:
156  return NodeKind::Scalar;
157  }
158  }
159 
160  static MapDocNode &getAsMap(DocNode &N) { return N.getMap(/*Convert=*/true); }
161 
163  N.getArray(/*Convert=*/true);
164  return *static_cast<ArrayDocNode *>(&N);
165  }
166 
167  static ScalarDocNode &getAsScalar(DocNode &N) {
168  return *static_cast<ScalarDocNode *>(&N);
169  }
170 };
171 
172 /// YAMLIO for ScalarDocNode
173 template <> struct TaggedScalarTraits<ScalarDocNode> {
174 
175  static void output(const ScalarDocNode &S, void *Ctxt, raw_ostream &OS,
176  raw_ostream &TagOS) {
177  TagOS << S.getYAMLTag();
178  OS << S.toString();
179  }
180 
181  static StringRef input(StringRef Str, StringRef Tag, void *Ctxt,
182  ScalarDocNode &S) {
183  return S.fromString(Str, Tag);
184  }
185 
186  static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr) {
187  switch (S.getKind()) {
188  case Type::Int:
189  return ScalarTraits<int64_t>::mustQuote(ScalarStr);
190  case Type::UInt:
191  return ScalarTraits<uint64_t>::mustQuote(ScalarStr);
192  case Type::Nil:
193  return ScalarTraits<StringRef>::mustQuote(ScalarStr);
194  case Type::Boolean:
195  return ScalarTraits<bool>::mustQuote(ScalarStr);
196  case Type::Float:
197  return ScalarTraits<double>::mustQuote(ScalarStr);
198  case Type::Binary:
199  case Type::String:
200  return ScalarTraits<std::string>::mustQuote(ScalarStr);
201  default:
202  llvm_unreachable("unrecognized ScalarKind");
203  }
204  }
205 };
206 
207 /// YAMLIO for MapDocNode
208 template <> struct CustomMappingTraits<MapDocNode> {
209 
210  static void inputOne(IO &IO, StringRef Key, MapDocNode &M) {
211  ScalarDocNode KeyObj = M.getDocument()->getNode();
212  KeyObj.fromString(Key, "");
213  IO.mapRequired(Key.str().c_str(), M.getMap()[KeyObj]);
214  }
215 
216  static void output(IO &IO, MapDocNode &M) {
217  for (auto I : M.getMap()) {
218  IO.mapRequired(I.first.toString().c_str(), I.second);
219  }
220  }
221 };
222 
223 /// YAMLIO for ArrayNode
224 template <> struct SequenceTraits<ArrayDocNode> {
225 
226  static size_t size(IO &IO, ArrayDocNode &A) { return A.size(); }
227 
228  static DocNode &element(IO &IO, ArrayDocNode &A, size_t Index) {
229  return A[Index];
230  }
231 };
232 
233 } // namespace yaml
234 } // namespace llvm
235 
236 /// Convert MsgPack Document to YAML text.
238  yaml::Output Yout(OS);
239  Yout << getRoot();
240 }
241 
242 /// Read YAML text into the MsgPack document. Returns false on failure.
244  clear();
245  yaml::Input Yin(S);
246  Yin >> getRoot();
247  return !Yin.error();
248 }
249 
static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr)
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:232
static size_t size(IO &IO, ArrayDocNode &A)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static ArrayDocNode & getAsSequence(DocNode &N)
static MapDocNode & getAsMap(DocNode &N)
static NodeKind getKind(const DocNode &N)
Document * getDocument() const
void toYAML(raw_ostream &OS)
Convert MsgPack Document to YAML text.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
A DocNode that is an array.
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:986
MapDocNode & getMap(bool Convert=false)
Get a MapDocNode for a map node.
static unsigned getInt(StringRef R)
Get an unsigned integer, including error checks.
Definition: DataLayout.cpp:209
bool fromYAML(StringRef S)
Read YAML text into the MsgPack document. Returns false on failure.
Key
PAL metadata keys.
DocNode getNode()
Create a nil node associated with this Document.
std::string toString() const
Convert this node to a string, assuming it is scalar.
static void inputOne(IO &IO, StringRef Key, MapDocNode &M)
static ScalarDocNode & getAsScalar(DocNode &N)
ArrayDocNode & getArray(bool Convert=false)
Get an ArrayDocNode for an array node.
static void output(const ScalarDocNode &S, void *Ctxt, raw_ostream &OS, raw_ostream &TagOS)
std::string & str()
Flushes the stream contents to the target string and returns the string&#39;s reference.
Definition: raw_ostream.h:519
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A DocNode that is a map.
static void clear(coro::Shape &Shape)
Definition: Coroutines.cpp:225
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
Definition: PtrState.h:40
StringRef fromString(StringRef S, StringRef Tag="")
Convert the StringRef and use it to set this DocNode (assuming scalar).
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:503
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
A node in a MsgPack Document.
static DocNode & element(IO &IO, ArrayDocNode &A, size_t Index)
static StringRef input(StringRef Str, StringRef Tag, void *Ctxt, ScalarDocNode &S)