LLVM 22.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
32bool isJSONSchemaBoolLiteral(StringRef S) {
33 return S == "true" || S == "false";
34}
35
36} // namespace
37
38/// Convert this DocNode to a string, assuming it is scalar.
39std::string DocNode::toString() const {
40 std::string S;
42 switch (getKind()) {
44 OS << Raw;
45 break;
47 break;
49 OS << (Bool ? "true" : "false");
50 break;
52 OS << Int;
53 break;
55 if (getDocument()->getHexMode())
56 OS << format("%#llx", (unsigned long long)UInt);
57 else
58 OS << UInt;
59 break;
61 OS << Float;
62 break;
63 default:
64 llvm_unreachable("not scalar");
65 break;
66 }
67 return OS.str();
68}
69
70/// Convert the StringRef and use it to set this DocNode (assuming scalar). If
71/// it is a string, copy the string into the Document's strings list so we do
72/// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
74 if (Tag == "tag:yaml.org,2002:str")
75 Tag = "";
76 if (Tag == "!int" || Tag == "") {
77 // Try unsigned int then signed int.
78 *this = getDocument()->getNode(uint64_t(0));
80 if (Err != "") {
81 *this = getDocument()->getNode(int64_t(0));
82 Err = yaml::ScalarTraits<int64_t>::input(S, nullptr, getInt());
83 }
84 if (Err == "" || Tag != "")
85 return Err;
86 }
87 if (Tag == "!nil") {
88 *this = getDocument()->getNode();
89 return "";
90 }
91 if (Tag == "!bool") {
92 *this = getDocument()->getNode(false);
93 return yaml::ScalarTraits<bool>::input(S, nullptr, getBool());
94 }
95 // FIXME: This enforces the "JSON Schema" tag resolution for boolean literals,
96 // defined at https://yaml.org/spec/1.2.2/#json-schema which we adopt because
97 // the more general pre-1.2 resolution includes many common strings (e.g. "n",
98 // "no", "y", "yes", ...). This should be handled at the YAMLTraits level, but
99 // that change would have a much broader impact.
100 if (Tag == "" && isJSONSchemaBoolLiteral(S)) {
101 *this = getDocument()->getNode(S == "true");
102 return "";
103 }
104 if (Tag == "!float" || Tag == "") {
105 *this = getDocument()->getNode(0.0);
107 if (Err == "" || Tag != "")
108 return Err;
109 }
110 assert((Tag == "!str" || Tag == "") && "unsupported tag");
111 std::string V;
113 if (Err == "")
114 *this = getDocument()->getNode(V, /*Copy=*/true);
115 return Err;
116}
117
118/// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
119/// returns something else if the result of toString would be ambiguous, e.g.
120/// a string that parses as a number or boolean.
121StringRef ScalarDocNode::getYAMLTag() const {
122 if (getKind() == msgpack::Type::Nil)
123 return "!nil";
124 // Try converting both ways and see if we get the same kind. If not, we need
125 // a tag.
126 ScalarDocNode N = getDocument()->getNode();
127 N.fromString(toString(), "");
128 if (N.getKind() == getKind())
129 return "";
130 // Tolerate signedness of int changing, as tags do not differentiate between
131 // them anyway.
132 if (N.getKind() == msgpack::Type::UInt && getKind() == msgpack::Type::Int)
133 return "";
134 if (N.getKind() == msgpack::Type::Int && getKind() == msgpack::Type::UInt)
135 return "";
136 // We do need a tag.
137 switch (getKind()) {
139 return "!str";
141 return "!int";
143 return "!int";
145 return "!bool";
147 return "!float";
148 default:
149 llvm_unreachable("unrecognized kind");
150 }
151}
152
153namespace llvm {
154namespace yaml {
155
156/// YAMLIO for DocNode
157template <> struct PolymorphicTraits<DocNode> {
158
159 static NodeKind getKind(const DocNode &N) {
160 switch (N.getKind()) {
162 return NodeKind::Map;
164 return NodeKind::Sequence;
165 default:
166 return NodeKind::Scalar;
167 }
168 }
169
170 static MapDocNode &getAsMap(DocNode &N) { return N.getMap(/*Convert=*/true); }
171
173 N.getArray(/*Convert=*/true);
174 return *static_cast<ArrayDocNode *>(&N);
175 }
176
177 static ScalarDocNode &getAsScalar(DocNode &N) {
178 return *static_cast<ScalarDocNode *>(&N);
179 }
180};
181
182/// YAMLIO for ScalarDocNode
183template <> struct TaggedScalarTraits<ScalarDocNode> {
184
185 static void output(const ScalarDocNode &S, void *Ctxt, raw_ostream &OS,
186 raw_ostream &TagOS) {
187 TagOS << S.getYAMLTag();
188 OS << S.toString();
189 }
190
191 static StringRef input(StringRef Str, StringRef Tag, void *Ctxt,
192 ScalarDocNode &S) {
193 return S.fromString(Str, Tag);
194 }
195
196 static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr) {
197 switch (S.getKind()) {
198 case Type::Int:
199 return ScalarTraits<int64_t>::mustQuote(ScalarStr);
200 case Type::UInt:
201 return ScalarTraits<uint64_t>::mustQuote(ScalarStr);
202 case Type::Nil:
203 return ScalarTraits<StringRef>::mustQuote(ScalarStr);
204 case Type::Boolean:
205 return ScalarTraits<bool>::mustQuote(ScalarStr);
206 case Type::Float:
207 return ScalarTraits<double>::mustQuote(ScalarStr);
208 case Type::Binary:
209 case Type::String:
210 return ScalarTraits<std::string>::mustQuote(ScalarStr);
211 default:
212 llvm_unreachable("unrecognized ScalarKind");
213 }
214 }
215};
216
217/// YAMLIO for MapDocNode
218template <> struct CustomMappingTraits<MapDocNode> {
219
220 static void inputOne(IO &IO, StringRef Key, MapDocNode &M) {
221 ScalarDocNode KeyObj = M.getDocument()->getNode();
222 KeyObj.fromString(Key, "");
223 IO.mapRequired(Key, M.getMap()[KeyObj]);
224 }
225
226 static void output(IO &IO, MapDocNode &M) {
227 for (auto I : M.getMap()) {
228 IO.mapRequired(I.first.toString(), I.second);
229 }
230 }
231};
232
233/// YAMLIO for ArrayNode
234template <> struct SequenceTraits<ArrayDocNode> {
235
236 static size_t size(IO &IO, ArrayDocNode &A) { return A.size(); }
237
238 static DocNode &element(IO &IO, ArrayDocNode &A, size_t Index) {
239 return A[Index];
240 }
241};
242
243} // namespace yaml
244} // namespace llvm
245
246/// Convert MsgPack Document to YAML text.
248 yaml::Output Yout(OS);
249 Yout << getRoot();
250}
251
252/// Read YAML text into the MsgPack document. Returns false on failure.
254 clear();
255 yaml::Input Yin(S);
256 Yin >> getRoot();
257 return !Yin.error();
258}
259
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static DeltaTreeNode * getRoot(void *Root)
#define I(x, y, z)
Definition MD5.cpp:57
This file declares a class that exposes a simple in-memory representation of a document of MsgPack ob...
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
A DocNode that is an array.
A node in a MsgPack Document.
LLVM_ABI StringRef fromString(StringRef S, StringRef Tag="")
Convert the StringRef and use it to set this DocNode (assuming scalar).
LLVM_ABI std::string toString() const
Convert this node to a string, assuming it is scalar.
Document * getDocument() const
void clear()
Restore the Document to an empty state.
DocNode getNode()
Create a nil node associated with this Document.
LLVM_ABI void toYAML(raw_ostream &OS)
Convert MsgPack Document to YAML text.
LLVM_ABI 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:53
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
void mapRequired(StringRef Key, T &Val)
Definition YAMLTraits.h:789
The Input class is used to parse a yaml document into in-memory structs and vectors.
std::error_code error() override
The Output class is used to generate a yaml document from in-memory structs and vectors.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
QuotingType
Describe which type of quotes should be used when quoting is necessary.
Definition YAMLTraits.h:131
This is an optimization pass for GlobalISel generic memory operations.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:129
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
#define N
static void inputOne(IO &IO, StringRef Key, MapDocNode &M)
This class should be specialized by any type that needs to be converted to/from a YAML mapping in the...
Definition YAMLTraits.h:273
static NodeKind getKind(const DocNode &N)
static ArrayDocNode & getAsSequence(DocNode &N)
static ScalarDocNode & getAsScalar(DocNode &N)
This class should be specialized by any type that can be represented as a scalar, map,...
Definition YAMLTraits.h:295
This class should be specialized by type that requires custom conversion to/from a yaml scalar.
Definition YAMLTraits.h:149
static size_t size(IO &IO, ArrayDocNode &A)
static DocNode & element(IO &IO, ArrayDocNode &A, size_t Index)
This class should be specialized by any type that needs to be converted to/from a YAML sequence.
Definition YAMLTraits.h:245
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)
This class should be specialized by type that requires custom conversion to/from a YAML scalar with o...
Definition YAMLTraits.h:215