LLVM  8.0.1
MsgPackTypes.h
Go to the documentation of this file.
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"
20 #include "llvm/Support/Casting.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.
37 
38 /// Abstract base-class which can be any MessagePack type.
39 class Node {
40 public:
41  enum NodeKind {
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 {
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
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
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:
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:
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> {
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  }
291  if (!N || !isa<msgpack::ScalarNode>(*N))
292  N.reset(new msgpack::ScalarNode());
293  return *cast<msgpack::ScalarNode>(N.get());
294  }
296  if (!N || !isa<msgpack::MapNode>(*N))
297  N.reset(new msgpack::MapNode());
298  return *cast<msgpack::MapNode>(N.get());
299  }
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) {
319  if (S.inputYAML(ScalarStr) == StringRef())
320  return StringRef();
322  return S.inputYAML(ScalarStr);
323  }
324 
325  if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag ||
326  Tag == "tag:yaml.org,2002:str")
328  else if (Tag == msgpack::ScalarNode::NilTag)
330  else if (Tag == msgpack::ScalarNode::BooleanTag)
332  else if (Tag == msgpack::ScalarNode::FloatTag)
334  else if (Tag == msgpack::ScalarNode::StringTag)
336  else if (Tag == msgpack::ScalarNode::BinaryTag)
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(); }
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
static const char * FloatTag
Definition: MsgPackTypes.h:241
static size_t size(IO &IO, msgpack::ArrayNode &A)
Definition: MsgPackTypes.h:360
static bool classof(const Node *N)
Definition: MsgPackTypes.h:265
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:228
static NodeKind getKind(const msgpack::NodePtr &N)
Definition: MsgPackTypes.h:281
This class represents lattice values for constants.
Definition: AllocatorList.h:24
NodeKind getKind() const
Definition: MsgPackTypes.h:55
StringRef getYAMLTag() const
Get the YAML tag for the current ScalarKind.
ScalarKind getScalarKind()
Get the current kind of ScalarNode.
Definition: MsgPackTypes.h:157
yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const
Determine which YAML quoting type the current value would need when output.
StringRef getString()
Get the value of a String scalar.
Definition: MsgPackTypes.h:194
double getFloat()
Get the value of an Float scalar.
Definition: MsgPackTypes.h:186
static bool classof(const Node *N)
Definition: MsgPackTypes.h:251
void writeMapSize(uint32_t Size)
Write the header for a Map of the given size.
Writes MessagePack objects to an output stream, one at a time.
Definition: MsgPackWriter.h:41
uint64_t getUInt()
Get the value of a UInt scalar.
Definition: MsgPackTypes.h:170
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
static const char * BinaryTag
Definition: MsgPackTypes.h:243
void outputYAML(raw_ostream &OS) const
Output a YAML scalar of the current ScalarKind into OS.
Key
PAL metadata keys.
static msgpack::ArrayNode & getAsSequence(msgpack::NodePtr &N)
Definition: MsgPackTypes.h:300
static const char * IntTag
Definition: MsgPackTypes.h:238
static Expected< OptNodePtr > read(Reader &MPReader)
Read from a MessagePack reader MPReader, returning an error if one is encountered, or None if MPReader is at the end of stream, or some Node pointer if some type is read.
static bool classof(const Node *N)
Definition: MsgPackTypes.h:207
static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M)
Definition: MsgPackTypes.h:350
int64_t getInt()
Get the value of an Int scalar.
Definition: MsgPackTypes.h:162
static const char * BooleanTag
Definition: MsgPackTypes.h:240
Reads MessagePack objects from memory, one at a time.
Definition: MsgPackReader.h:99
virtual void write(Writer &MPWriter)=0
Write to a MessagePack writer MPWriter.
std::shared_ptr< Node > NodePtr
Short-hand for a Node pointer.
Definition: MsgPackTypes.h:33
bool IgnoreTag
Flag which affects how the type handles YAML tags when reading and writing.
Definition: MsgPackTypes.h:236
void writeArraySize(uint32_t Size)
Write the header for an Array of the given size.
Node(NodeKind Kind)
Construct a Node. Used by derived classes to track kind information.
Definition: MsgPackTypes.h:58
void write(Writer &MPWriter) override
Write to a MessagePack writer MPWriter.
Definition: MsgPackTypes.h:267
Abstract base-class which can be any MessagePack type.
Definition: MsgPackTypes.h:39
static void output(const msgpack::ScalarNode &S, void *Ctxt, raw_ostream &ScalarOS, raw_ostream &TagOS)
Definition: MsgPackTypes.h:308
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A scalar node is an opaque datum that can be presented as a series of zero or more Unicode scalar val...
Definition: YAMLParser.h:207
static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str)
Definition: MsgPackTypes.h:344
static const char * NilTag
Definition: MsgPackTypes.h:239
static msgpack::MapNode & getAsMap(msgpack::NodePtr &N)
Definition: MsgPackTypes.h:295
This is a MessagePack reader.
void write(bool b)
Write a Boolean to the output stream.
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:1167
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:220
static msgpack::ScalarNode & getAsScalar(msgpack::NodePtr &N)
Definition: MsgPackTypes.h:290
static void output(IO &IO, msgpack::MapNode &M)
Definition: MsgPackTypes.h:353
#define N
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
Definition: PtrState.h:41
void setScalarKind(ScalarKind SKind)
Change the kind of this ScalarNode, zero initializing it to the new type.
Definition: MsgPackTypes.h:130
static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt, msgpack::ScalarNode &S)
Definition: MsgPackTypes.h:315
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef getBinary()
Get the value of a Binary scalar.
Definition: MsgPackTypes.h:202
virtual ~Node()=default
static msgpack::NodePtr & element(IO &IO, msgpack::ArrayNode &A, size_t Index)
Definition: MsgPackTypes.h:361
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
A MessagePack scalar.
Definition: MsgPackTypes.h:72
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
bool getBool()
Get the value of an Boolean scalar.
Definition: MsgPackTypes.h:178
This file contains a MessagePack writer.
static const char * StringTag
Definition: MsgPackTypes.h:242
void write(Writer &MPWriter) override
Write to a MessagePack writer MPWriter.
Definition: MsgPackTypes.h:253
StringRef inputYAML(StringRef ScalarStr)
Parse a YAML scalar of the current ScalarKind from ScalarStr.