LLVM  10.0.0svn
MsgPackDocument.h
Go to the documentation of this file.
1 //===-- MsgPackDocument.h - MsgPack Document --------------------*- 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 /// This file declares a class that exposes a simple in-memory representation
10 /// of a document of MsgPack objects, that can be read from MsgPack, written to
11 /// MsgPack, and inspected and modified in memory. This is intended to be a
12 /// lighter-weight (in terms of memory allocations) replacement for
13 /// MsgPackTypes.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
18 #define LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
19 
21 #include <map>
22 
23 namespace llvm {
24 namespace msgpack {
25 
26 class ArrayDocNode;
27 class Document;
28 class MapDocNode;
29 
30 /// The kind of a DocNode and its owning Document.
34 };
35 
36 /// A node in a MsgPack Document. This is a simple copyable and
37 /// passable-by-value type that does not own any memory.
38 class DocNode {
39  friend Document;
40 
41 public:
42  typedef std::map<DocNode, DocNode> MapTy;
43  typedef std::vector<DocNode> ArrayTy;
44 
45 private:
46  // Using KindAndDocument allows us to squeeze Kind and a pointer to the
47  // owning Document into the same word. Having a pointer to the owning
48  // Document makes the API of DocNode more convenient, and allows its use in
49  // YAMLIO.
50  const KindAndDocument *KindAndDoc;
51 
52 protected:
53  // The union of different values.
54  union {
55  int64_t Int;
56  uint64_t UInt;
57  bool Bool;
58  double Float;
60  ArrayTy *Array;
61  MapTy *Map;
62  };
63 
64 public:
65  DocNode() : KindAndDoc(nullptr) {}
66 
67  // Type methods
68  bool isMap() const { return getKind() == Type::Map; }
69  bool isArray() const { return getKind() == Type::Array; }
70  bool isScalar() const { return !isMap() && !isArray(); }
71  bool isString() const { return getKind() == Type::String; }
72 
73  // Accessors
74  bool isEmpty() const { return !KindAndDoc; }
75  Type getKind() const { return KindAndDoc->Kind; }
76  Document *getDocument() const { return KindAndDoc->Doc; }
77 
78  int64_t &getInt() {
79  assert(getKind() == Type::Int);
80  return Int;
81  }
82 
83  uint64_t &getUInt() {
84  assert(getKind() == Type::UInt);
85  return UInt;
86  }
87 
88  bool &getBool() {
89  assert(getKind() == Type::Boolean);
90  return Bool;
91  }
92 
93  double &getFloat() {
94  assert(getKind() == Type::Float);
95  return Float;
96  }
97 
98  int64_t getInt() const {
99  assert(getKind() == Type::Int);
100  return Int;
101  }
102 
103  uint64_t getUInt() const {
104  assert(getKind() == Type::UInt);
105  return UInt;
106  }
107 
108  bool getBool() const {
109  assert(getKind() == Type::Boolean);
110  return Bool;
111  }
112 
113  double getFloat() const {
114  assert(getKind() == Type::Float);
115  return Float;
116  }
117 
119  assert(getKind() == Type::String);
120  return Raw;
121  }
122 
123  /// Get an ArrayDocNode for an array node. If Convert, convert the node to an
124  /// array node if necessary.
125  ArrayDocNode &getArray(bool Convert = false) {
126  if (getKind() != Type::Array) {
127  assert(Convert);
128  convertToArray();
129  }
130  // This could be a static_cast, except ArrayDocNode is a forward reference.
131  return *reinterpret_cast<ArrayDocNode *>(this);
132  }
133 
134  /// Get a MapDocNode for a map node. If Convert, convert the node to a map
135  /// node if necessary.
136  MapDocNode &getMap(bool Convert = false) {
137  if (getKind() != Type::Map) {
138  assert(Convert);
139  convertToMap();
140  }
141  // This could be a static_cast, except MapDocNode is a forward reference.
142  return *reinterpret_cast<MapDocNode *>(this);
143  }
144 
145  /// Comparison operator, used for map keys.
146  friend bool operator<(const DocNode &Lhs, const DocNode &Rhs) {
147  // This has to cope with one or both of the nodes being default-constructed,
148  // such that KindAndDoc is not set.
149  if (Lhs.KindAndDoc != Rhs.KindAndDoc) {
150  if (!Rhs.KindAndDoc)
151  return false;
152  if (!Lhs.KindAndDoc)
153  return true;
154  return (unsigned)Lhs.getKind() < (unsigned)Rhs.getKind();
155  }
156  switch (Lhs.getKind()) {
157  case Type::Int:
158  return Lhs.Int < Rhs.Int;
159  case Type::UInt:
160  return Lhs.UInt < Rhs.UInt;
161  case Type::Nil:
162  return false;
163  case Type::Boolean:
164  return Lhs.Bool < Rhs.Bool;
165  case Type::Float:
166  return Lhs.Float < Rhs.Float;
167  case Type::String:
168  case Type::Binary:
169  return Lhs.Raw < Rhs.Raw;
170  default:
171  llvm_unreachable("bad map key type");
172  }
173  }
174 
175  /// Equality operator
176  friend bool operator==(const DocNode &Lhs, const DocNode &Rhs) {
177  return !(Lhs < Rhs) && !(Rhs < Lhs);
178  }
179 
180  /// Convert this node to a string, assuming it is scalar.
181  std::string toString() const;
182 
183  /// Convert the StringRef and use it to set this DocNode (assuming scalar). If
184  /// it is a string, copy the string into the Document's strings list so we do
185  /// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
187 
188 private:
189  // Private constructor setting KindAndDoc, used by methods in Document.
190  DocNode(const KindAndDocument *KindAndDoc) : KindAndDoc(KindAndDoc) {}
191 
192  void convertToArray();
193  void convertToMap();
194 };
195 
196 /// A DocNode that is a map.
197 class MapDocNode : public DocNode {
198 public:
200  MapDocNode(DocNode &N) : DocNode(N) { assert(getKind() == Type::Map); }
201 
202  // Map access methods.
203  size_t size() const { return Map->size(); }
204  bool empty() const { return !size(); }
205  MapTy::iterator begin() { return Map->begin(); }
206  MapTy::iterator end() { return Map->end(); }
207  MapTy::iterator find(DocNode Key) { return Map->find(Key); }
208  MapTy::iterator find(StringRef Key);
209  /// Member access. The string data must remain valid for the lifetime of the
210  /// Document.
211  DocNode &operator[](StringRef S);
212  /// Member access.
213  DocNode &operator[](DocNode Key);
214 };
215 
216 /// A DocNode that is an array.
217 class ArrayDocNode : public DocNode {
218 public:
220  ArrayDocNode(DocNode &N) : DocNode(N) { assert(getKind() == Type::Array); }
221 
222  // Array access methods.
223  size_t size() const { return Array->size(); }
224  bool empty() const { return !size(); }
225  ArrayTy::iterator begin() { return Array->begin(); }
226  ArrayTy::iterator end() { return Array->end(); }
228  assert(N.getDocument() == getDocument());
229  Array->push_back(N);
230  }
231 
232  /// Element access. This extends the array if necessary.
233  DocNode &operator[](size_t Index);
234 };
235 
236 /// Simple in-memory representation of a document of msgpack objects with
237 /// ability to find and create array and map elements. Does not currently cope
238 /// with any extension types.
239 class Document {
240  // Maps, arrays and strings used by nodes in the document. No attempt is made
241  // to free unused ones.
242  std::vector<std::unique_ptr<DocNode::MapTy>> Maps;
243  std::vector<std::unique_ptr<DocNode::ArrayTy>> Arrays;
244  std::vector<std::unique_ptr<char[]>> Strings;
245 
246  // The root node of the document.
247  DocNode Root;
248 
249  // The KindAndDocument structs pointed to by nodes in the document.
250  KindAndDocument KindAndDocs[size_t(Type::Extension) + 1];
251 
252  // Whether YAML output uses hex for UInt.
253  bool HexMode = false;
254 
255 public:
257  clear();
258  for (unsigned T = 0; T != size_t(Type::Extension) + 1; ++T)
259  KindAndDocs[T] = {this, Type(T)};
260  }
261 
262  /// Get ref to the document's root element.
263  DocNode &getRoot() { return Root; }
264 
265  /// Restore the Document to an empty state.
266  void clear() { getRoot() = getNode(); }
267 
268  /// Create a nil node associated with this Document.
270  auto N = DocNode(&KindAndDocs[size_t(Type::Nil)]);
271  return N;
272  }
273 
274  /// Create an Int node associated with this Document.
275  DocNode getNode(int64_t V) {
276  auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
277  N.Int = V;
278  return N;
279  }
280 
281  /// Create an Int node associated with this Document.
282  DocNode getNode(int V) {
283  auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
284  N.Int = V;
285  return N;
286  }
287 
288  /// Create a UInt node associated with this Document.
289  DocNode getNode(uint64_t V) {
290  auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
291  N.UInt = V;
292  return N;
293  }
294 
295  /// Create a UInt node associated with this Document.
296  DocNode getNode(unsigned V) {
297  auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
298  N.UInt = V;
299  return N;
300  }
301 
302  /// Create a Boolean node associated with this Document.
303  DocNode getNode(bool V) {
304  auto N = DocNode(&KindAndDocs[size_t(Type::Boolean)]);
305  N.Bool = V;
306  return N;
307  }
308 
309  /// Create a Float node associated with this Document.
310  DocNode getNode(double V) {
311  auto N = DocNode(&KindAndDocs[size_t(Type::Float)]);
312  N.Float = V;
313  return N;
314  }
315 
316  /// Create a String node associated with this Document. If !Copy, the passed
317  /// string must remain valid for the lifetime of the Document.
318  DocNode getNode(StringRef V, bool Copy = false) {
319  if (Copy)
320  V = addString(V);
321  auto N = DocNode(&KindAndDocs[size_t(Type::String)]);
322  N.Raw = V;
323  return N;
324  }
325 
326  /// Create a String node associated with this Document. If !Copy, the passed
327  /// string must remain valid for the lifetime of the Document.
328  DocNode getNode(const char *V, bool Copy = false) {
329  return getNode(StringRef(V), Copy);
330  }
331 
332  /// Create an empty Map node associated with this Document.
334  auto N = DocNode(&KindAndDocs[size_t(Type::Map)]);
335  Maps.push_back(std::unique_ptr<DocNode::MapTy>(new DocNode::MapTy));
336  N.Map = Maps.back().get();
337  return N.getMap();
338  }
339 
340  /// Create an empty Array node associated with this Document.
342  auto N = DocNode(&KindAndDocs[size_t(Type::Array)]);
343  Arrays.push_back(std::unique_ptr<DocNode::ArrayTy>(new DocNode::ArrayTy));
344  N.Array = Arrays.back().get();
345  return N.getArray();
346  }
347 
348  /// Read a MsgPack document from a binary MsgPack blob.
349  /// The blob data must remain valid for the lifetime of this Document (because
350  /// a string object in the document contains a StringRef into the original
351  /// blob).
352  /// If Multi, then this sets root to an array and adds top-level objects to
353  /// it. If !Multi, then it only reads a single top-level object, even if there
354  /// are more, and sets root to that.
355  /// Returns false if failed due to illegal format.
356  bool readFromBlob(StringRef Blob, bool Multi);
357 
358  /// Write a MsgPack document to a binary MsgPack blob.
359  void writeToBlob(std::string &Blob);
360 
361  /// Copy a string into the Document's strings list, and return the copy that
362  /// is owned by the Document.
364  Strings.push_back(std::unique_ptr<char[]>(new char[S.size()]));
365  memcpy(&Strings.back()[0], S.data(), S.size());
366  return StringRef(&Strings.back()[0], S.size());
367  }
368 
369  /// Set whether YAML output uses hex for UInt. Default off.
370  void setHexMode(bool Val = true) { HexMode = Val; }
371 
372  /// Get Hexmode flag.
373  bool getHexMode() const { return HexMode; }
374 
375  /// Convert MsgPack Document to YAML text.
376  void toYAML(raw_ostream &OS);
377 
378  /// Read YAML text into the MsgPack document. Returns false on failure.
379  bool fromYAML(StringRef S);
380 };
381 
382 } // namespace msgpack
383 } // namespace llvm
384 
385 #endif // LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
Definition: MsgPackReader.h:48
DocNode & getRoot()
Get ref to the document&#39;s root element.
void setHexMode(bool Val=true)
Set whether YAML output uses hex for UInt. Default off.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
The kind of a DocNode and its owning Document.
Document * getDocument() const
DocNode getNode(unsigned V)
Create a UInt node associated with this Document.
DocNode getNode(bool V)
Create a Boolean node associated with this Document.
A DocNode that is an array.
DocNode getNode(StringRef V, bool Copy=false)
Create a String node associated with this Document.
DocNode getNode(int64_t V)
Create an Int node associated with this Document.
StringRef addString(StringRef S)
Copy a string into the Document&#39;s strings list, and return the copy that is owned by the Document...
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:986
MapDocNode & getMap(bool Convert=false)
Get a MapDocNode for a map node.
uint64_t getUInt() const
DocNode getNode(const char *V, bool Copy=false)
Create a String node associated with this Document.
std::error_code fromString(std::string String, Metadata &HSAMetadata)
Converts String to HSAMetadata.
Key
PAL metadata keys.
ArrayTy::iterator begin()
DocNode getNode()
Create a nil node associated with this Document.
friend bool operator==(const DocNode &Lhs, const DocNode &Rhs)
Equality operator.
StringRef getString() const
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:144
ArrayDocNode getArrayNode()
Create an empty Array node associated with this Document.
MapTy::iterator find(DocNode Key)
std::vector< DocNode > ArrayTy
DocNode getNode(int V)
Create an Int node associated with this Document.
std::map< DocNode, DocNode > MapTy
ArrayDocNode & getArray(bool Convert=false)
Get an ArrayDocNode for an array node.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1186
MapDocNode getMapNode()
Create an empty Map node associated with this Document.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is a MessagePack reader.
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:1146
friend bool operator<(const DocNode &Lhs, const DocNode &Rhs)
Comparison operator, used for map keys.
Simple in-memory representation of a document of msgpack objects with ability to find and create arra...
A DocNode that is a map.
static void clear(coro::Shape &Shape)
Definition: Coroutines.cpp:225
DocNode getNode(uint64_t V)
Create a UInt node associated with this Document.
void clear()
Restore the Document to an empty state.
#define N
int64_t getInt() const
DocNode getNode(double V)
Create a Float node associated with this Document.
static bool isArray(AllocaInst *AI)
Determine whether this alloca is either a VLA or an array.
Definition: Local.cpp:1379
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:136
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
A node in a MsgPack Document.
bool getHexMode() const
Get Hexmode flag.