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