Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/BinaryFormat/MsgPackDocumentYAML.cpp
Line
Count
Source (jump to first uncovered line)
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
14
#include "llvm/BinaryFormat/MsgPackDocument.h"
15
#include "llvm/Support/YAMLTraits.h"
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
176k
  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
515k
std::string DocNode::toString() const {
37
515k
  std::string S;
38
515k
  raw_string_ostream OS(S);
39
515k
  switch (getKind()) {
40
515k
  case msgpack::Type::String:
41
314k
    OS << Raw;
42
314k
    break;
43
515k
  case msgpack::Type::Nil:
44
0
    break;
45
515k
  case msgpack::Type::Boolean:
46
108
    OS << (Bool ? "true" : 
"false"0
);
47
108
    break;
48
515k
  case msgpack::Type::Int:
49
8
    OS << Int;
50
8
    break;
51
515k
  case msgpack::Type::UInt:
52
200k
    if (getDocument()->getHexMode())
53
297
      OS << format("%#llx", (unsigned long long)UInt);
54
200k
    else
55
200k
      OS << UInt;
56
200k
    break;
57
515k
  case msgpack::Type::Float:
58
0
    OS << Float;
59
0
    break;
60
515k
  default:
61
0
    llvm_unreachable("not scalar");
62
515k
    
break0
;
63
515k
  }
64
515k
  return OS.str();
65
515k
}
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.
70
182k
StringRef DocNode::fromString(StringRef S, StringRef Tag) {
71
182k
  if (Tag == "tag:yaml.org,2002:str")
72
6.62k
    Tag = "";
73
182k
  if (Tag == "!int" || 
Tag == ""182k
) {
74
182k
    // Try unsigned int then signed int.
75
182k
    *this = getDocument()->getNode(uint64_t(0));
76
182k
    StringRef Err = yaml::ScalarTraits<uint64_t>::input(S, nullptr, getUInt());
77
182k
    if (Err != "") {
78
79.0k
      *this = getDocument()->getNode(int64_t(0));
79
79.0k
      Err = yaml::ScalarTraits<int64_t>::input(S, nullptr, getInt());
80
79.0k
    }
81
182k
    if (Err == "" || 
Tag != ""79.0k
)
82
103k
      return Err;
83
79.0k
  }
84
79.0k
  if (Tag == "!nil") {
85
0
    *this = getDocument()->getNode();
86
0
    return "";
87
0
  }
88
79.0k
  if (Tag == "!bool" || Tag == "") {
89
79.0k
    *this = getDocument()->getNode(false);
90
79.0k
    StringRef Err = yaml::ScalarTraits<bool>::input(S, nullptr, getBool());
91
79.0k
    if (Err == "" || 
Tag != ""78.9k
)
92
66
      return Err;
93
78.9k
  }
94
78.9k
  if (Tag == "!float" || Tag == "") {
95
78.9k
    *this = getDocument()->getNode(0.0);
96
78.9k
    StringRef Err = yaml::ScalarTraits<double>::input(S, nullptr, getFloat());
97
78.9k
    if (Err == "" || 
Tag != ""78.9k
)
98
10
      return Err;
99
78.9k
  }
100
78.9k
  assert((Tag == "!str" || Tag == "") && "unsupported tag");
101
78.9k
  std::string V;
102
78.9k
  StringRef Err = yaml::ScalarTraits<std::string>::input(S, nullptr, V);
103
78.9k
  if (Err == "")
104
78.9k
    *this = getDocument()->getNode(V, /*Copy=*/true);
105
78.9k
  return Err;
106
78.9k
}
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
169k
StringRef ScalarDocNode::getYAMLTag() const {
112
169k
  if (getKind() == msgpack::Type::Nil)
113
0
    return "!nil";
114
169k
  // Try converting both ways and see if we get the same kind. If not, we need
115
169k
  // a tag.
116
169k
  ScalarDocNode N = getDocument()->getNode();
117
169k
  N.fromString(toString(), "");
118
169k
  if (N.getKind() == getKind())
119
169k
    return "";
120
14
  // Tolerate signedness of int changing, as tags do not differentiate between
121
14
  // them anyway.
122
14
  if (N.getKind() == msgpack::Type::UInt && 
getKind() == msgpack::Type::Int4
)
123
4
    return "";
124
10
  if (N.getKind() == msgpack::Type::Int && 
getKind() == msgpack::Type::UInt0
)
125
0
    return "";
126
10
  // We do need a tag.
127
10
  switch (getKind()) {
128
10
  case msgpack::Type::String:
129
10
    return "!str";
130
10
  case msgpack::Type::Int:
131
0
    return "!int";
132
10
  case msgpack::Type::UInt:
133
0
    return "!int";
134
10
  case msgpack::Type::Boolean:
135
0
    return "!bool";
136
10
  case msgpack::Type::Float:
137
0
    return "!float";
138
10
  default:
139
0
    llvm_unreachable("unrecognized kind");
140
10
  }
141
10
}
142
143
namespace llvm {
144
namespace yaml {
145
146
/// YAMLIO for DocNode
147
template <> struct PolymorphicTraits<DocNode> {
148
149
201k
  static NodeKind getKind(const DocNode &N) {
150
201k
    switch (N.getKind()) {
151
201k
    case msgpack::Type::Map:
152
23.4k
      return NodeKind::Map;
153
201k
    case msgpack::Type::Array:
154
8.19k
      return NodeKind::Sequence;
155
201k
    default:
156
169k
      return NodeKind::Scalar;
157
201k
    }
158
201k
  }
159
160
24.5k
  static MapDocNode &getAsMap(DocNode &N) { return N.getMap(/*Convert=*/true); }
161
162
8.48k
  static ArrayDocNode &getAsSequence(DocNode &N) {
163
8.48k
    N.getArray(/*Convert=*/true);
164
8.48k
    return *static_cast<ArrayDocNode *>(&N);
165
8.48k
  }
166
167
176k
  static ScalarDocNode &getAsScalar(DocNode &N) {
168
176k
    return *static_cast<ScalarDocNode *>(&N);
169
176k
  }
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
169k
                     raw_ostream &TagOS) {
177
169k
    TagOS << S.getYAMLTag();
178
169k
    OS << S.toString();
179
169k
  }
180
181
  static StringRef input(StringRef Str, StringRef Tag, void *Ctxt,
182
6.62k
                         ScalarDocNode &S) {
183
6.62k
    return S.fromString(Str, Tag);
184
6.62k
  }
185
186
169k
  static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr) {
187
169k
    switch (S.getKind()) {
188
169k
    case Type::Int:
189
4
      return ScalarTraits<int64_t>::mustQuote(ScalarStr);
190
169k
    case Type::UInt:
191
100k
      return ScalarTraits<uint64_t>::mustQuote(ScalarStr);
192
169k
    case Type::Nil:
193
0
      return ScalarTraits<StringRef>::mustQuote(ScalarStr);
194
169k
    case Type::Boolean:
195
54
      return ScalarTraits<bool>::mustQuote(ScalarStr);
196
169k
    case Type::Float:
197
0
      return ScalarTraits<double>::mustQuote(ScalarStr);
198
169k
    case Type::Binary:
199
69.1k
    case Type::String:
200
69.1k
      return ScalarTraits<std::string>::mustQuote(ScalarStr);
201
69.1k
    default:
202
0
      llvm_unreachable("unrecognized ScalarKind");
203
169k
    }
204
169k
  }
205
};
206
207
/// YAMLIO for MapDocNode
208
template <> struct CustomMappingTraits<MapDocNode> {
209
210
6.59k
  static void inputOne(IO &IO, StringRef Key, MapDocNode &M) {
211
6.59k
    ScalarDocNode KeyObj = M.getDocument()->getNode();
212
6.59k
    KeyObj.fromString(Key, "");
213
6.59k
    IO.mapRequired(Key.str().c_str(), M.getMap()[KeyObj]);
214
6.59k
  }
215
216
23.4k
  static void output(IO &IO, MapDocNode &M) {
217
175k
    for (auto I : M.getMap()) {
218
175k
      IO.mapRequired(I.first.toString().c_str(), I.second);
219
175k
    }
220
23.4k
  }
221
};
222
223
/// YAMLIO for ArrayNode
224
template <> struct SequenceTraits<ArrayDocNode> {
225
226
8.19k
  static size_t size(IO &IO, ArrayDocNode &A) { return A.size(); }
227
228
26.3k
  static DocNode &element(IO &IO, ArrayDocNode &A, size_t Index) {
229
26.3k
    return A[Index];
230
26.3k
  }
231
};
232
233
} // namespace yaml
234
} // namespace llvm
235
236
/// Convert MsgPack Document to YAML text.
237
602
void msgpack::Document::toYAML(raw_ostream &OS) {
238
602
  yaml::Output Yout(OS);
239
602
  Yout << getRoot();
240
602
}
241
242
/// Read YAML text into the MsgPack document. Returns false on failure.
243
20
bool msgpack::Document::fromYAML(StringRef S) {
244
20
  clear();
245
20
  yaml::Input Yin(S);
246
20
  Yin >> getRoot();
247
20
  return !Yin.error();
248
20
}
249