Skip to content

Commit 919fbbb

Browse files
committed
[BinaryFormat] Add MsgPackTypes
Add data structure to represent MessagePack "documents" and convert to/from both MessagePack and YAML encodings. Differential Revision: https://reviews.llvm.org/D48175 llvm-svn: 346978
1 parent 6cda874 commit 919fbbb

File tree

5 files changed

+865
-0
lines changed

5 files changed

+865
-0
lines changed
Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
//===- MsgPackTypes.h - MsgPack Types ---------------------------*- C++ -*-===//
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+
/// \file
11+
/// This is a data structure for representing MessagePack "documents", with
12+
/// methods to go to and from MessagePack. The types also specialize YAMLIO
13+
/// traits in order to go to and from YAML.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "llvm/ADT/Optional.h"
18+
#include "llvm/BinaryFormat/MsgPackReader.h"
19+
#include "llvm/BinaryFormat/MsgPackWriter.h"
20+
#include "llvm/Support/Casting.h"
21+
#include "llvm/Support/YAMLTraits.h"
22+
#include <vector>
23+
24+
#ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H
25+
#define LLVM_BINARYFORMAT_MSGPACKTYPES_H
26+
27+
namespace llvm {
28+
namespace msgpack {
29+
30+
class Node;
31+
32+
/// Short-hand for a Node pointer.
33+
using NodePtr = std::shared_ptr<Node>;
34+
35+
/// Short-hand for an Optional Node pointer.
36+
using OptNodePtr = Optional<NodePtr>;
37+
38+
/// Abstract base-class which can be any MessagePack type.
39+
class Node {
40+
public:
41+
enum NodeKind {
42+
NK_Scalar,
43+
NK_Array,
44+
NK_Map,
45+
};
46+
47+
private:
48+
virtual void anchor() = 0;
49+
const NodeKind Kind;
50+
51+
static Expected<OptNodePtr> readArray(Reader &MPReader, size_t Length);
52+
static Expected<OptNodePtr> readMap(Reader &MPReader, size_t Length);
53+
54+
public:
55+
NodeKind getKind() const { return Kind; }
56+
57+
/// Construct a Node. Used by derived classes to track kind information.
58+
Node(NodeKind Kind) : Kind(Kind) {}
59+
60+
virtual ~Node() = default;
61+
62+
/// Read from a MessagePack reader \p MPReader, returning an error if one is
63+
/// encountered, or None if \p MPReader is at the end of stream, or some Node
64+
/// pointer if some type is read.
65+
static Expected<OptNodePtr> read(Reader &MPReader);
66+
67+
/// Write to a MessagePack writer \p MPWriter.
68+
virtual void write(Writer &MPWriter) = 0;
69+
};
70+
71+
/// A MessagePack scalar.
72+
class ScalarNode : public Node {
73+
public:
74+
enum ScalarKind {
75+
SK_Int,
76+
SK_UInt,
77+
SK_Nil,
78+
SK_Boolean,
79+
SK_Float,
80+
SK_String,
81+
SK_Binary,
82+
};
83+
84+
private:
85+
void anchor() override;
86+
87+
void destroy();
88+
89+
ScalarKind SKind;
90+
91+
union {
92+
int64_t IntValue;
93+
uint64_t UIntValue;
94+
bool BoolValue;
95+
double FloatValue;
96+
std::string StringValue;
97+
};
98+
99+
public:
100+
/// Construct an Int ScalarNode.
101+
ScalarNode(int64_t IntValue);
102+
/// Construct an Int ScalarNode.
103+
ScalarNode(int32_t IntValue);
104+
/// Construct an UInt ScalarNode.
105+
ScalarNode(uint64_t UIntValue);
106+
/// Construct an UInt ScalarNode.
107+
ScalarNode(uint32_t UIntValue);
108+
/// Construct a Nil ScalarNode.
109+
ScalarNode();
110+
/// Construct a Boolean ScalarNode.
111+
ScalarNode(bool BoolValue);
112+
/// Construct a Float ScalarNode.
113+
ScalarNode(double FloatValue);
114+
/// Construct a String ScalarNode.
115+
ScalarNode(StringRef StringValue);
116+
/// Construct a String ScalarNode.
117+
ScalarNode(const char *StringValue);
118+
/// Construct a String ScalarNode.
119+
ScalarNode(std::string &&StringValue);
120+
/// Construct a Binary ScalarNode.
121+
ScalarNode(MemoryBufferRef BinaryValue);
122+
123+
~ScalarNode();
124+
125+
ScalarNode &operator=(const ScalarNode &RHS) = delete;
126+
/// A ScalarNode can only be move assigned.
127+
ScalarNode &operator=(ScalarNode &&RHS);
128+
129+
/// Change the kind of this ScalarNode, zero initializing it to the new type.
130+
void setScalarKind(ScalarKind SKind) {
131+
switch (SKind) {
132+
case SK_Int:
133+
*this = int64_t(0);
134+
break;
135+
case SK_UInt:
136+
*this = uint64_t(0);
137+
break;
138+
case SK_Boolean:
139+
*this = false;
140+
break;
141+
case SK_Float:
142+
*this = 0.0;
143+
break;
144+
case SK_String:
145+
*this = StringRef();
146+
break;
147+
case SK_Binary:
148+
*this = MemoryBufferRef("", "");
149+
break;
150+
case SK_Nil:
151+
*this = ScalarNode();
152+
break;
153+
}
154+
}
155+
156+
/// Get the current kind of ScalarNode.
157+
ScalarKind getScalarKind() { return SKind; }
158+
159+
/// Get the value of an Int scalar.
160+
///
161+
/// \warning Assumes getScalarKind() == SK_Int
162+
int64_t getInt() {
163+
assert(SKind == SK_Int);
164+
return IntValue;
165+
}
166+
167+
/// Get the value of a UInt scalar.
168+
///
169+
/// \warning Assumes getScalarKind() == SK_UInt
170+
uint64_t getUInt() {
171+
assert(SKind == SK_UInt);
172+
return UIntValue;
173+
}
174+
175+
/// Get the value of an Boolean scalar.
176+
///
177+
/// \warning Assumes getScalarKind() == SK_Boolean
178+
bool getBool() {
179+
assert(SKind == SK_Boolean);
180+
return BoolValue;
181+
}
182+
183+
/// Get the value of an Float scalar.
184+
///
185+
/// \warning Assumes getScalarKind() == SK_Float
186+
double getFloat() {
187+
assert(SKind == SK_Float);
188+
return FloatValue;
189+
}
190+
191+
/// Get the value of a String scalar.
192+
///
193+
/// \warning Assumes getScalarKind() == SK_String
194+
StringRef getString() {
195+
assert(SKind == SK_String);
196+
return StringValue;
197+
}
198+
199+
/// Get the value of a Binary scalar.
200+
///
201+
/// \warning Assumes getScalarKind() == SK_Binary
202+
StringRef getBinary() {
203+
assert(SKind == SK_Binary);
204+
return StringValue;
205+
}
206+
207+
static bool classof(const Node *N) { return N->getKind() == NK_Scalar; }
208+
209+
void write(Writer &MPWriter) override;
210+
211+
/// Parse a YAML scalar of the current ScalarKind from \p ScalarStr.
212+
///
213+
/// \returns An empty string on success, otherwise an error message.
214+
StringRef inputYAML(StringRef ScalarStr);
215+
216+
/// Output a YAML scalar of the current ScalarKind into \p OS.
217+
void outputYAML(raw_ostream &OS) const;
218+
219+
/// Determine which YAML quoting type the current value would need when
220+
/// output.
221+
yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const;
222+
223+
/// Get the YAML tag for the current ScalarKind.
224+
StringRef getYAMLTag() const;
225+
226+
/// Flag which affects how the type handles YAML tags when reading and
227+
/// writing.
228+
///
229+
/// When false, tags are used when reading and writing. When reading, the tag
230+
/// is used to decide the ScalarKind before parsing. When writing, the tag is
231+
/// output along with the value.
232+
///
233+
/// When true, tags are ignored when reading and writing. When reading, the
234+
/// ScalarKind is always assumed to be String. When writing, the tag is not
235+
/// output.
236+
bool IgnoreTag = false;
237+
238+
static const char *IntTag;
239+
static const char *NilTag;
240+
static const char *BooleanTag;
241+
static const char *FloatTag;
242+
static const char *StringTag;
243+
static const char *BinaryTag;
244+
};
245+
246+
class ArrayNode : public Node, public std::vector<NodePtr> {
247+
void anchor() override;
248+
249+
public:
250+
ArrayNode() : Node(NK_Array) {}
251+
static bool classof(const Node *N) { return N->getKind() == NK_Array; }
252+
253+
void write(Writer &MPWriter) override {
254+
MPWriter.writeArraySize(this->size());
255+
for (auto &N : *this)
256+
N->write(MPWriter);
257+
}
258+
};
259+
260+
class MapNode : public Node, public StringMap<NodePtr> {
261+
void anchor() override;
262+
263+
public:
264+
MapNode() : Node(NK_Map) {}
265+
static bool classof(const Node *N) { return N->getKind() == NK_Map; }
266+
267+
void write(Writer &MPWriter) override {
268+
MPWriter.writeMapSize(this->size());
269+
for (auto &N : *this) {
270+
MPWriter.write(N.first());
271+
N.second->write(MPWriter);
272+
}
273+
}
274+
};
275+
276+
} // end namespace msgpack
277+
278+
namespace yaml {
279+
280+
template <> struct PolymorphicTraits<msgpack::NodePtr> {
281+
static NodeKind getKind(const msgpack::NodePtr &N) {
282+
if (isa<msgpack::ScalarNode>(*N))
283+
return NodeKind::Scalar;
284+
if (isa<msgpack::MapNode>(*N))
285+
return NodeKind::Map;
286+
if (isa<msgpack::ArrayNode>(*N))
287+
return NodeKind::Sequence;
288+
llvm_unreachable("NodeKind not supported");
289+
}
290+
static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) {
291+
if (!N || !isa<msgpack::ScalarNode>(*N))
292+
N.reset(new msgpack::ScalarNode());
293+
return *cast<msgpack::ScalarNode>(N.get());
294+
}
295+
static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) {
296+
if (!N || !isa<msgpack::MapNode>(*N))
297+
N.reset(new msgpack::MapNode());
298+
return *cast<msgpack::MapNode>(N.get());
299+
}
300+
static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) {
301+
if (!N || !isa<msgpack::ArrayNode>(*N))
302+
N.reset(new msgpack::ArrayNode());
303+
return *cast<msgpack::ArrayNode>(N.get());
304+
}
305+
};
306+
307+
template <> struct TaggedScalarTraits<msgpack::ScalarNode> {
308+
static void output(const msgpack::ScalarNode &S, void *Ctxt,
309+
raw_ostream &ScalarOS, raw_ostream &TagOS) {
310+
if (!S.IgnoreTag)
311+
TagOS << S.getYAMLTag();
312+
S.outputYAML(ScalarOS);
313+
}
314+
315+
static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt,
316+
msgpack::ScalarNode &S) {
317+
if (Tag == msgpack::ScalarNode::IntTag) {
318+
S.setScalarKind(msgpack::ScalarNode::SK_UInt);
319+
if (S.inputYAML(ScalarStr) == StringRef())
320+
return StringRef();
321+
S.setScalarKind(msgpack::ScalarNode::SK_Int);
322+
return S.inputYAML(ScalarStr);
323+
}
324+
325+
if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag ||
326+
Tag == "tag:yaml.org,2002:str")
327+
S.setScalarKind(msgpack::ScalarNode::SK_String);
328+
else if (Tag == msgpack::ScalarNode::NilTag)
329+
S.setScalarKind(msgpack::ScalarNode::SK_Nil);
330+
else if (Tag == msgpack::ScalarNode::BooleanTag)
331+
S.setScalarKind(msgpack::ScalarNode::SK_Boolean);
332+
else if (Tag == msgpack::ScalarNode::FloatTag)
333+
S.setScalarKind(msgpack::ScalarNode::SK_Float);
334+
else if (Tag == msgpack::ScalarNode::StringTag)
335+
S.setScalarKind(msgpack::ScalarNode::SK_String);
336+
else if (Tag == msgpack::ScalarNode::BinaryTag)
337+
S.setScalarKind(msgpack::ScalarNode::SK_Binary);
338+
else
339+
return "Unsupported messagepack tag";
340+
341+
return S.inputYAML(ScalarStr);
342+
}
343+
344+
static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) {
345+
return S.mustQuoteYAML(Str);
346+
}
347+
};
348+
349+
template <> struct CustomMappingTraits<msgpack::MapNode> {
350+
static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) {
351+
IO.mapRequired(Key.str().c_str(), M[Key]);
352+
}
353+
static void output(IO &IO, msgpack::MapNode &M) {
354+
for (auto &N : M)
355+
IO.mapRequired(N.getKey().str().c_str(), N.getValue());
356+
}
357+
};
358+
359+
template <> struct SequenceTraits<msgpack::ArrayNode> {
360+
static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); }
361+
static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A,
362+
size_t Index) {
363+
if (Index >= A.size())
364+
A.resize(Index + 1);
365+
return A[Index];
366+
}
367+
};
368+
369+
} // end namespace yaml
370+
} // end namespace llvm
371+
372+
#endif // LLVM_BINARYFORMAT_MSGPACKTYPES_H

llvm/lib/BinaryFormat/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_llvm_library(LLVMBinaryFormat
22
Dwarf.cpp
33
Magic.cpp
44
MsgPackReader.cpp
5+
MsgPackTypes.cpp
56
MsgPackWriter.cpp
67
Wasm.cpp
78

0 commit comments

Comments
 (0)