Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackDocumentYAML.cpp
35234 views
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
13
#include "llvm/BinaryFormat/MsgPackDocument.h"
14
#include "llvm/Support/YAMLTraits.h"
15
16
using namespace llvm;
17
using namespace msgpack;
18
19
namespace {
20
21
// Struct used to represent scalar node. (MapDocNode and ArrayDocNode already
22
// exist in MsgPackDocument.h.)
23
struct 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.
35
std::string DocNode::toString() const {
36
std::string S;
37
raw_string_ostream OS(S);
38
switch (getKind()) {
39
case msgpack::Type::String:
40
OS << Raw;
41
break;
42
case msgpack::Type::Nil:
43
break;
44
case msgpack::Type::Boolean:
45
OS << (Bool ? "true" : "false");
46
break;
47
case msgpack::Type::Int:
48
OS << Int;
49
break;
50
case msgpack::Type::UInt:
51
if (getDocument()->getHexMode())
52
OS << format("%#llx", (unsigned long long)UInt);
53
else
54
OS << UInt;
55
break;
56
case msgpack::Type::Float:
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.
69
StringRef DocNode::fromString(StringRef S, StringRef 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.
110
StringRef 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()) {
127
case msgpack::Type::String:
128
return "!str";
129
case msgpack::Type::Int:
130
return "!int";
131
case msgpack::Type::UInt:
132
return "!int";
133
case msgpack::Type::Boolean:
134
return "!bool";
135
case msgpack::Type::Float:
136
return "!float";
137
default:
138
llvm_unreachable("unrecognized kind");
139
}
140
}
141
142
namespace llvm {
143
namespace yaml {
144
145
/// YAMLIO for DocNode
146
template <> 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
161
static ArrayDocNode &getAsSequence(DocNode &N) {
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
172
template <> 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
207
template <> 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
223
template <> 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.
236
void msgpack::Document::toYAML(raw_ostream &OS) {
237
yaml::Output Yout(OS);
238
Yout << getRoot();
239
}
240
241
/// Read YAML text into the MsgPack document. Returns false on failure.
242
bool msgpack::Document::fromYAML(StringRef S) {
243
clear();
244
yaml::Input Yin(S);
245
Yin >> getRoot();
246
return !Yin.error();
247
}
248
249
250