LLVM 23.0.0git
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/// \file
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
22#include <map>
23
24namespace llvm {
25namespace msgpack {
26
27class ArrayDocNode;
28class Document;
29class MapDocNode;
30
31/// The kind of a DocNode and its owning Document.
36
37/// A node in a MsgPack Document. This is a simple copyable and
38/// passable-by-value type that does not own any memory.
39class DocNode {
40 friend Document;
41
42public:
43 typedef std::map<DocNode, DocNode> MapTy;
44 typedef std::vector<DocNode> ArrayTy;
45
46private:
47 // Using KindAndDocument allows us to squeeze Kind and a pointer to the
48 // owning Document into the same word. Having a pointer to the owning
49 // Document makes the API of DocNode more convenient, and allows its use in
50 // YAMLIO.
51 const KindAndDocument *KindAndDoc;
52
53protected:
54 // The union of different values.
55 union {
56 int64_t Int;
58 bool Bool;
59 double Float;
63 };
64
65public:
66 // Default constructor gives an empty node with no associated Document. All
67 // you can do with it is "isEmpty()".
68 DocNode() : KindAndDoc(nullptr) {}
69
70 // Type methods
71 bool isMap() const { return getKind() == Type::Map; }
72 bool isArray() const { return getKind() == Type::Array; }
73 bool isScalar() const { return !isMap() && !isArray(); }
74 bool isString() const { return getKind() == Type::String; }
75
76 // Accessors. isEmpty() returns true for both a default-constructed DocNode
77 // that has no associated Document, and the result of getEmptyNode(), which
78 // does have an associated document.
79 bool isEmpty() const { return !KindAndDoc || getKind() == Type::Empty; }
80 Type getKind() const {
81 assert(KindAndDoc);
82 return KindAndDoc->Kind;
83 }
84 Document *getDocument() const {
85 assert(KindAndDoc);
86 return KindAndDoc->Doc;
87 }
88
89 int64_t &getInt() {
91 return Int;
92 }
93
96 return UInt;
97 }
98
99 bool &getBool() {
101 return Bool;
102 }
103
104 double &getFloat() {
106 return Float;
107 }
108
109 int64_t getInt() const {
111 return Int;
112 }
113
116 return UInt;
117 }
118
119 bool getBool() const {
121 return Bool;
122 }
123
124 double getFloat() const {
126 return Float;
127 }
128
131 return Raw;
132 }
133
136 return MemoryBufferRef(Raw, "");
137 }
138
139 /// Get an ArrayDocNode for an array node. If Convert, convert the node to an
140 /// array node if necessary.
141 ArrayDocNode &getArray(bool Convert = false) {
142 if (getKind() != Type::Array) {
143 assert(Convert);
144 convertToArray();
145 }
146 // This could be a static_cast, except ArrayDocNode is a forward reference.
147 return *reinterpret_cast<ArrayDocNode *>(this);
148 }
149
150 /// Get a MapDocNode for a map node. If Convert, convert the node to a map
151 /// node if necessary.
152 MapDocNode &getMap(bool Convert = false) {
153 if (getKind() != Type::Map) {
154 assert(Convert);
155 convertToMap();
156 }
157 // This could be a static_cast, except MapDocNode is a forward reference.
158 return *reinterpret_cast<MapDocNode *>(this);
159 }
160
161 /// Comparison operator, used for map keys. Compares by value, so nodes
162 /// from different Documents with the same kind and value are ordered
163 /// consistently. Only supports scalar types; Array and Map nodes should
164 /// not be used as map keys.
165 friend bool operator<(const DocNode &Lhs, const DocNode &Rhs) {
166 // Cope with default-constructed nodes where KindAndDoc is not set:
167 // isEmpty() returns true both for default-constructed nodes and for
168 // nodes returned by getEmptyNode().
169 if (Rhs.isEmpty())
170 return false;
171 if (Lhs.isEmpty())
172 return true;
173 if (Lhs.getKind() != Rhs.getKind())
174 return (unsigned)Lhs.getKind() < (unsigned)Rhs.getKind();
175 switch (Lhs.getKind()) {
176 case Type::Int:
177 return Lhs.Int < Rhs.Int;
178 case Type::UInt:
179 return Lhs.UInt < Rhs.UInt;
180 case Type::Nil:
181 return false;
182 case Type::Boolean:
183 return Lhs.Bool < Rhs.Bool;
184 case Type::Float:
185 return Lhs.Float < Rhs.Float;
186 case Type::String:
187 case Type::Binary:
188 return Lhs.Raw < Rhs.Raw;
189 default:
190 assert(false && "bad map key type");
191 return false;
192 }
193 }
194
195 /// Equality operator. Supports all node types including Array and Map,
196 /// comparing recursively by value. Works correctly for nodes from
197 /// different Documents.
198 LLVM_ABI friend bool operator==(const DocNode &Lhs, const DocNode &Rhs);
199
200 /// Inequality operator
201 friend bool operator!=(const DocNode &Lhs, const DocNode &Rhs) {
202 return !(Lhs == Rhs);
203 }
204
205 /// Convert this node to a string, assuming it is scalar.
206 LLVM_ABI std::string toString() const;
207
208 /// Convert the StringRef and use it to set this DocNode (assuming scalar). If
209 /// it is a string, copy the string into the Document's strings list so we do
210 /// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
212
213 /// Convenience assignment operators. This only works if the destination
214 /// DocNode has an associated Document, i.e. it was not constructed using the
215 /// default constructor. The string one does not copy, so the string must
216 /// remain valid for the lifetime of the Document. Use fromString to avoid
217 /// that restriction.
218 DocNode &operator=(const char *Val) { return *this = StringRef(Val); }
221 LLVM_ABI DocNode &operator=(bool Val);
222 LLVM_ABI DocNode &operator=(int Val);
223 LLVM_ABI DocNode &operator=(unsigned Val);
224 LLVM_ABI DocNode &operator=(int64_t Val);
226 LLVM_ABI DocNode &operator=(double Val);
227
228private:
229 // Private constructor setting KindAndDoc, used by methods in Document.
230 DocNode(const KindAndDocument *KindAndDoc) : KindAndDoc(KindAndDoc) {}
231
232 LLVM_ABI void convertToArray();
233 LLVM_ABI void convertToMap();
234};
235
236/// Namespace-scope declaration for the out-of-line friend operator==.
237LLVM_ABI bool operator==(const DocNode &Lhs, const DocNode &Rhs);
238
239/// A DocNode that is a map.
240class MapDocNode : public DocNode {
241public:
242 MapDocNode() = default;
244
245 // Map access methods.
246 size_t size() const { return Map->size(); }
247 bool empty() const { return !size(); }
248 MapTy::iterator begin() { return Map->begin(); }
249 MapTy::iterator end() { return Map->end(); }
250 MapTy::iterator find(DocNode Key) { return Map->find(Key); }
251 LLVM_ABI MapTy::iterator find(StringRef Key);
252 MapTy::iterator erase(MapTy::const_iterator I) { return Map->erase(I); }
253 size_t erase(DocNode Key) { return Map->erase(Key); }
254 MapTy::iterator erase(MapTy::const_iterator First,
255 MapTy::const_iterator Second) {
256 return Map->erase(First, Second);
257 }
258 /// Member access. The string data must remain valid for the lifetime of the
259 /// Document.
261 /// Member access, with convenience versions for an integer key.
264 LLVM_ABI DocNode &operator[](unsigned Key);
265 LLVM_ABI DocNode &operator[](int64_t Key);
267};
268
269/// A DocNode that is an array.
270class ArrayDocNode : public DocNode {
271public:
272 ArrayDocNode() = default;
274
275 // Array access methods.
276 size_t size() const { return Array->size(); }
277 bool empty() const { return !size(); }
278 DocNode &back() const { return Array->back(); }
279 ArrayTy::iterator begin() { return Array->begin(); }
280 ArrayTy::iterator end() { return Array->end(); }
282 assert(N.isEmpty() || N.getDocument() == getDocument());
283 Array->push_back(N);
284 }
285
286 /// Element access. This extends the array if necessary, with empty nodes.
287 LLVM_ABI DocNode &operator[](size_t Index);
288};
289
290/// Simple in-memory representation of a document of msgpack objects with
291/// ability to find and create array and map elements. Does not currently cope
292/// with any extension types.
293class Document {
294 // Maps, arrays and strings used by nodes in the document. No attempt is made
295 // to free unused ones.
296 std::vector<std::unique_ptr<DocNode::MapTy>> Maps;
297 std::vector<std::unique_ptr<DocNode::ArrayTy>> Arrays;
298 std::vector<std::unique_ptr<char[]>> Strings;
299
300 // The root node of the document.
301 DocNode Root;
302
303 // The KindAndDocument structs pointed to by nodes in the document.
304 KindAndDocument KindAndDocs[size_t(Type::Empty) + 1];
305
306 // Whether YAML output uses hex for UInt.
307 bool HexMode = false;
308
309public:
311 clear();
312 for (unsigned T = 0; T != unsigned(Type::Empty) + 1; ++T)
313 KindAndDocs[T] = {this, Type(T)};
314 }
315
316 /// Get ref to the document's root element.
317 DocNode &getRoot() { return Root; }
318
319 /// Restore the Document to an empty state.
320 void clear() { getRoot() = getEmptyNode(); }
321
322 /// Create an empty node associated with this Document.
324 auto N = DocNode(&KindAndDocs[size_t(Type::Empty)]);
325 return N;
326 }
327
328 /// Create a nil node associated with this Document.
330 auto N = DocNode(&KindAndDocs[size_t(Type::Nil)]);
331 return N;
332 }
333
334 /// Create an Int node associated with this Document.
335 DocNode getNode(int64_t V) {
336 auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
337 N.Int = V;
338 return N;
339 }
340
341 /// Create an Int node associated with this Document.
343 auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
344 N.Int = V;
345 return N;
346 }
347
348 /// Create a UInt node associated with this Document.
350 auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
351 N.UInt = V;
352 return N;
353 }
354
355 /// Create a UInt node associated with this Document.
356 DocNode getNode(unsigned V) {
357 auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
358 N.UInt = V;
359 return N;
360 }
361
362 /// Create a Boolean node associated with this Document.
363 DocNode getNode(bool V) {
364 auto N = DocNode(&KindAndDocs[size_t(Type::Boolean)]);
365 N.Bool = V;
366 return N;
367 }
368
369 /// Create a Float node associated with this Document.
370 DocNode getNode(double V) {
371 auto N = DocNode(&KindAndDocs[size_t(Type::Float)]);
372 N.Float = V;
373 return N;
374 }
375
376 /// Create a String node associated with this Document. If !Copy, the passed
377 /// string must remain valid for the lifetime of the Document.
378 DocNode getNode(StringRef V, bool Copy = false) {
379 if (Copy)
380 V = addString(V);
381 auto N = DocNode(&KindAndDocs[size_t(Type::String)]);
382 N.Raw = V;
383 return N;
384 }
385
386 /// Create a String node associated with this Document. If !Copy, the passed
387 /// string must remain valid for the lifetime of the Document.
388 DocNode getNode(const char *V, bool Copy = false) {
389 return getNode(StringRef(V), Copy);
390 }
391
392 /// Create a Binary node associated with this Document. If !Copy, the passed
393 /// buffer must remain valid for the lifetime of the Document.
394 DocNode getNode(MemoryBufferRef V, bool Copy = false) {
395 auto Raw = V.getBuffer();
396 if (Copy)
397 Raw = addString(Raw);
398 auto N = DocNode(&KindAndDocs[size_t(Type::Binary)]);
399 N.Raw = Raw;
400 return N;
401 }
402
403 /// Create an empty Map node associated with this Document.
405 auto N = DocNode(&KindAndDocs[size_t(Type::Map)]);
406 Maps.push_back(std::make_unique<DocNode::MapTy>());
407 N.Map = Maps.back().get();
408 return N.getMap();
409 }
410
411 /// Create an empty Array node associated with this Document.
413 auto N = DocNode(&KindAndDocs[size_t(Type::Array)]);
414 Arrays.push_back(std::make_unique<DocNode::ArrayTy>());
415 N.Array = Arrays.back().get();
416 return N.getArray();
417 }
418
419 /// Deep copy a DocNode from any Document into this Document. The returned
420 /// node is owned by this Document and is independent of the source node's
421 /// Document. Strings are copied so the source Document's lifetime does not
422 /// need to extend beyond this call.
424
425 /// Read a document from a binary msgpack blob, merging into anything already
426 /// in the Document. The blob data must remain valid for the lifetime of this
427 /// Document (because a string object in the document contains a StringRef
428 /// into the original blob). If Multi, then this sets root to an array and
429 /// adds top-level objects to it. If !Multi, then it only reads a single
430 /// top-level object, even if there are more, and sets root to that. Returns
431 /// false if failed due to illegal format or merge error.
432 ///
433 /// The Merger arg is a callback function that is called when the merge has a
434 /// conflict, that is, it is trying to set an item that is already set. If the
435 /// conflict cannot be resolved, the callback function returns -1. If the
436 /// conflict can be resolved, the callback returns a non-negative number and
437 /// sets *DestNode to the resolved node. The returned non-negative number is
438 /// significant only for an array node; it is then the array index to start
439 /// populating at. That allows Merger to choose whether to merge array
440 /// elements (returns 0) or append new elements (returns existing size).
441 ///
442 /// If SrcNode is an array or map, the resolution must be that *DestNode is an
443 /// array or map respectively, although it could be the array or map
444 /// (respectively) that was already there. MapKey is the key if *DestNode is a
445 /// map entry, a nil node otherwise.
446 ///
447 /// The default for Merger is to disallow any conflict.
449 StringRef Blob, bool Multi,
450 function_ref<int(DocNode *DestNode, DocNode SrcNode, DocNode MapKey)>
451 Merger = [](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
452 return -1;
453 });
454
455 /// Write a MsgPack document to a binary MsgPack blob.
456 LLVM_ABI void writeToBlob(std::string &Blob);
457
458 /// Copy a string into the Document's strings list, and return the copy that
459 /// is owned by the Document.
461 Strings.push_back(std::unique_ptr<char[]>(new char[S.size()]));
462 memcpy(&Strings.back()[0], S.data(), S.size());
463 return StringRef(&Strings.back()[0], S.size());
464 }
465
466 /// Set whether YAML output uses hex for UInt. Default off.
467 void setHexMode(bool Val = true) { HexMode = Val; }
468
469 /// Get Hexmode flag.
470 bool getHexMode() const { return HexMode; }
471
472 /// Convert MsgPack Document to YAML text.
473 LLVM_ABI void toYAML(raw_ostream &OS);
474
475 /// Read YAML text into the MsgPack document. Returns false on failure.
477};
478
479} // namespace msgpack
480} // namespace llvm
481
482#endif // LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
#define I(x, y, z)
Definition MD5.cpp:57
#define T
This is a MessagePack reader.
R600 Vector Reg Merger
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:143
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:137
An efficient, type-erasing, non-owning reference to a callable.
A DocNode that is an array.
LLVM_ABI DocNode & operator[](size_t Index)
Element access. This extends the array if necessary, with empty nodes.
A node in a MsgPack Document.
MapDocNode & getMap(bool Convert=false)
Get a MapDocNode for a map node.
LLVM_ABI StringRef fromString(StringRef S, StringRef Tag="")
Convert the StringRef and use it to set this DocNode (assuming scalar).
friend bool operator!=(const DocNode &Lhs, const DocNode &Rhs)
Inequality operator.
std::map< DocNode, DocNode > MapTy
ArrayDocNode & getArray(bool Convert=false)
Get an ArrayDocNode for an array node.
MemoryBufferRef getBinary() const
uint64_t getUInt() const
StringRef getString() const
LLVM_ABI std::string toString() const
Convert this node to a string, assuming it is scalar.
std::vector< DocNode > ArrayTy
LLVM_ABI friend bool operator==(const DocNode &Lhs, const DocNode &Rhs)
Equality operator.
DocNode & operator=(const char *Val)
Convenience assignment operators.
friend bool operator<(const DocNode &Lhs, const DocNode &Rhs)
Comparison operator, used for map keys.
Document * getDocument() const
Simple in-memory representation of a document of msgpack objects with ability to find and create arra...
bool getHexMode() const
Get Hexmode flag.
DocNode getNode(unsigned V)
Create a UInt node associated with this Document.
DocNode getNode(StringRef V, bool Copy=false)
Create a String node associated with this Document.
DocNode getNode(double V)
Create a Float node associated with this Document.
LLVM_ABI DocNode copyNode(DocNode Src)
Deep copy a DocNode from any Document into this Document.
MapDocNode getMapNode()
Create an empty Map node associated with this Document.
DocNode getEmptyNode()
Create an empty node associated with this Document.
DocNode & getRoot()
Get ref to the document's root element.
DocNode getNode(uint64_t V)
Create a UInt node associated with this Document.
void clear()
Restore the Document to an empty state.
DocNode getNode()
Create a nil node associated with this Document.
ArrayDocNode getArrayNode()
Create an empty Array node associated with this Document.
DocNode getNode(int64_t V)
Create an Int node associated with this Document.
void setHexMode(bool Val=true)
Set whether YAML output uses hex for UInt. Default off.
LLVM_ABI void toYAML(raw_ostream &OS)
Convert MsgPack Document to YAML text.
DocNode getNode(bool V)
Create a Boolean node associated with this Document.
LLVM_ABI void writeToBlob(std::string &Blob)
Write a MsgPack document to a binary MsgPack blob.
LLVM_ABI bool readFromBlob(StringRef Blob, bool Multi, function_ref< int(DocNode *DestNode, DocNode SrcNode, DocNode MapKey)> Merger=[](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) { return -1;})
Read a document from a binary msgpack blob, merging into anything already in the Document.
StringRef addString(StringRef S)
Copy a string into the Document's strings list, and return the copy that is owned by the Document.
DocNode getNode(int V)
Create an Int node associated with this Document.
LLVM_ABI bool fromYAML(StringRef S)
Read YAML text into the MsgPack document. Returns false on failure.
DocNode getNode(const char *V, bool Copy=false)
Create a String node associated with this Document.
DocNode getNode(MemoryBufferRef V, bool Copy=false)
Create a Binary node associated with this Document.
A DocNode that is a map.
MapTy::iterator find(DocNode Key)
MapTy::iterator erase(MapTy::const_iterator First, MapTy::const_iterator Second)
size_t erase(DocNode Key)
LLVM_ABI DocNode & operator[](StringRef S)
Member access.
MapTy::iterator erase(MapTy::const_iterator I)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
LLVM_ABI bool operator==(const DocNode &Lhs, const DocNode &Rhs)
Namespace-scope declaration for the out-of-line friend operator==.
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
#define N
The kind of a DocNode and its owning Document.