LLVM 19.0.0git
MsgPackDocumentYAML.cpp
Go to the documentation of this file.
1//===-- MsgPackDocumentYAML.cpp - MsgPack Document YAML interface -------*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// This file implements YAMLIO on a msgpack::Document.
10//
11//===----------------------------------------------------------------------===//
12
15
16using namespace llvm;
17using namespace msgpack;
18
19namespace {
20
21// Struct used to represent scalar node. (MapDocNode and ArrayDocNode already
22// exist in MsgPackDocument.h.)
23struct ScalarDocNode : DocNode {
24 ScalarDocNode(DocNode N) : DocNode(N) {}
25
26 /// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
27 /// returns something else if the result of toString would be ambiguous, e.g.
28 /// a string that parses as a number or boolean.
29 StringRef getYAMLTag() const;
30};
31
32} // namespace
33
34/// Convert this DocNode to a string, assuming it is scalar.
35std::string DocNode::toString() const {
36 std::string S;
38 switch (getKind()) {
40 OS << Raw;
41 break;
43 break;
45 OS << (Bool ? "true" : "false");
46 break;
48 OS << Int;
49 break;
51 if (getDocument()->getHexMode())
52 OS << format("%#llx", (unsigned long long)UInt);
53 else
54 OS << UInt;
55 break;
57 OS << Float;
58 break;
59 default:
60 llvm_unreachable("not scalar");
61 break;
62 }
63 return OS.str();
64}
65
66/// Convert the StringRef and use it to set this DocNode (assuming scalar). If
67/// it is a string, copy the string into the Document's strings list so we do
68/// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
70 if (Tag == "tag:yaml.org,2002:str")
71 Tag = "";
72 if (Tag == "!int" || Tag == "") {
73 // Try unsigned int then signed int.
74 *this = getDocument()->getNode(uint64_t(0));
75 StringRef Err = yaml::ScalarTraits<uint64_t>::input(S, nullptr, getUInt());
76 if (Err != "") {
77 *this = getDocument()->getNode(int64_t(0));
78 Err = yaml::ScalarTraits<int64_t>::input(S, nullptr, getInt());
79 }
80 if (Err == "" || Tag != "")
81 return Err;
82 }
83 if (Tag == "!nil") {
84 *this = getDocument()->getNode();
85 return "";
86 }
87 if (Tag == "!bool" || Tag == "") {
88 *this = getDocument()->getNode(false);
89 StringRef Err = yaml::ScalarTraits<bool>::input(S, nullptr, getBool());
90 if (Err == "" || Tag != "")
91 return Err;
92 }
93 if (Tag == "!float" || Tag == "") {
94 *this = getDocument()->getNode(0.0);
95 StringRef Err = yaml::ScalarTraits<double>::input(S, nullptr, getFloat());
96 if (Err == "" || Tag != "")
97 return Err;
98 }
99 assert((Tag == "!str" || Tag == "") && "unsupported tag");
100 std::string V;
101 StringRef Err = yaml::ScalarTraits<std::string>::input(S, nullptr, V);
102 if (Err == "")
103 *this = getDocument()->getNode(V, /*Copy=*/true);
104 return Err;
105}
106
107/// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
108/// returns something else if the result of toString would be ambiguous, e.g.
109/// a string that parses as a number or boolean.
110StringRef ScalarDocNode::getYAMLTag() const {
111 if (getKind() == msgpack::Type::Nil)
112 return "!nil";
113 // Try converting both ways and see if we get the same kind. If not, we need
114 // a tag.
115 ScalarDocNode N = getDocument()->getNode();
116 N.fromString(toString(), "");
117 if (N.getKind() == getKind())
118 return "";
119 // Tolerate signedness of int changing, as tags do not differentiate between
120 // them anyway.
121 if (N.getKind() == msgpack::Type::UInt && getKind() == msgpack::Type::Int)
122 return "";
123 if (N.getKind() == msgpack::Type::Int && getKind() == msgpack::Type::UInt)
124 return "";
125 // We do need a tag.
126 switch (getKind()) {
128 return "!str";
130 return "!int";
132 return "!int";
134 return "!bool";
136 return "!float";
137 default:
138 llvm_unreachable("unrecognized kind");
139 }
140}
141
142namespace llvm {
143namespace yaml {
144
145/// YAMLIO for DocNode
146template <> struct PolymorphicTraits<DocNode> {
147
148 static NodeKind getKind(const DocNode &N) {
149 switch (N.getKind()) {
150 case msgpack::Type::Map:
151 return NodeKind::Map;
152 case msgpack::Type::Array:
153 return NodeKind::Sequence;
154 default:
155 return NodeKind::Scalar;
156 }
157 }
158
159 static MapDocNode &getAsMap(DocNode &N) { return N.getMap(/*Convert=*/true); }
160
162 N.getArray(/*Convert=*/true);
163 return *static_cast<ArrayDocNode *>(&N);
164 }
165
166 static ScalarDocNode &getAsScalar(DocNode &N) {
167 return *static_cast<ScalarDocNode *>(&N);
168 }
169};
170
171/// YAMLIO for ScalarDocNode
172template <> struct TaggedScalarTraits<ScalarDocNode> {
173
174 static void output(const ScalarDocNode &S, void *Ctxt, raw_ostream &OS,
175 raw_ostream &TagOS) {
176 TagOS << S.getYAMLTag();
177 OS << S.toString();
178 }
179
180 static StringRef input(StringRef Str, StringRef Tag, void *Ctxt,
181 ScalarDocNode &S) {
182 return S.fromString(Str, Tag);
183 }
184
185 static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr) {
186 switch (S.getKind()) {
187 case Type::Int:
188 return ScalarTraits<int64_t>::mustQuote(ScalarStr);
189 case Type::UInt:
190 return ScalarTraits<uint64_t>::mustQuote(ScalarStr);
191 case Type::Nil:
192 return ScalarTraits<StringRef>::mustQuote(ScalarStr);
193 case Type::Boolean:
194 return ScalarTraits<bool>::mustQuote(ScalarStr);
195 case Type::Float:
196 return ScalarTraits<double>::mustQuote(ScalarStr);
197 case Type::Binary:
198 case Type::String:
199 return ScalarTraits<std::string>::mustQuote(ScalarStr);
200 default:
201 llvm_unreachable("unrecognized ScalarKind");
202 }
203 }
204};
205
206/// YAMLIO for MapDocNode
207template <> struct CustomMappingTraits<MapDocNode> {
208
209 static void inputOne(IO &IO, StringRef Key, MapDocNode &M) {
210 ScalarDocNode KeyObj = M.getDocument()->getNode();
211 KeyObj.fromString(Key, "");
212 IO.mapRequired(Key.str().c_str(), M.getMap()[KeyObj]);
213 }
214
215 static void output(IO &IO, MapDocNode &M) {
216 for (auto I : M.getMap()) {
217 IO.mapRequired(I.first.toString().c_str(), I.second);
218 }
219 }
220};
221
222/// YAMLIO for ArrayNode
223template <> struct SequenceTraits<ArrayDocNode> {
224
225 static size_t size(IO &IO, ArrayDocNode &A) { return A.size(); }
226
227 static DocNode &element(IO &IO, ArrayDocNode &A, size_t Index) {
228 return A[Index];
229 }
230};
231
232} // namespace yaml
233} // namespace llvm
234
235/// Convert MsgPack Document to YAML text.
237 yaml::Output Yout(OS);
238 Yout << getRoot();
239}
240
241/// Read YAML text into the MsgPack document. Returns false on failure.
243 clear();
244 yaml::Input Yin(S);
245 Yin >> getRoot();
246 return !Yin.error();
247}
248
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static void clear(coro::Shape &Shape)
Definition: Coroutines.cpp:145
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares a class that exposes a simple in-memory representation of a document of MsgPack ob...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A DocNode that is an array.
A node in a MsgPack Document.
StringRef fromString(StringRef S, StringRef Tag="")
Convert the StringRef and use it to set this DocNode (assuming scalar).
std::string toString() const
Convert this node to a string, assuming it is scalar.
Document * getDocument() const
bool getHexMode() const
Get Hexmode flag.
DocNode getNode()
Create a nil node associated with this Document.
void toYAML(raw_ostream &OS)
Convert MsgPack Document to YAML text.
bool fromYAML(StringRef S)
Read YAML text into the MsgPack document. Returns false on failure.
A DocNode that is a map.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:660
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
#define N
static void inputOne(IO &IO, StringRef Key, MapDocNode &M)
static NodeKind getKind(const DocNode &N)
static ArrayDocNode & getAsSequence(DocNode &N)
static MapDocNode & getAsMap(DocNode &N)
static ScalarDocNode & getAsScalar(DocNode &N)
static size_t size(IO &IO, ArrayDocNode &A)
static DocNode & element(IO &IO, ArrayDocNode &A, size_t Index)
static StringRef input(StringRef Str, StringRef Tag, void *Ctxt, ScalarDocNode &S)
static void output(const ScalarDocNode &S, void *Ctxt, raw_ostream &OS, raw_ostream &TagOS)
static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr)