LLVM 22.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.
35};
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 { return KindAndDoc->Kind; }
81 Document *getDocument() const { return KindAndDoc->Doc; }
82
83 int64_t &getInt() {
85 return Int;
86 }
87
90 return UInt;
91 }
92
93 bool &getBool() {
95 return Bool;
96 }
97
98 double &getFloat() {
100 return Float;
101 }
102
103 int64_t getInt() const {
105 return Int;
106 }
107
110 return UInt;
111 }
112
113 bool getBool() const {
115 return Bool;
116 }
117
118 double getFloat() const {
120 return Float;
121 }
122
125 return Raw;
126 }
127
130 return MemoryBufferRef(Raw, "");
131 }
132
133 /// Get an ArrayDocNode for an array node. If Convert, convert the node to an
134 /// array node if necessary.
135 ArrayDocNode &getArray(bool Convert = false) {
136 if (getKind() != Type::Array) {
137 assert(Convert);
138 convertToArray();
139 }
140 // This could be a static_cast, except ArrayDocNode is a forward reference.
141 return *reinterpret_cast<ArrayDocNode *>(this);
142 }
143
144 /// Get a MapDocNode for a map node. If Convert, convert the node to a map
145 /// node if necessary.
146 MapDocNode &getMap(bool Convert = false) {
147 if (getKind() != Type::Map) {
148 assert(Convert);
149 convertToMap();
150 }
151 // This could be a static_cast, except MapDocNode is a forward reference.
152 return *reinterpret_cast<MapDocNode *>(this);
153 }
154
155 /// Comparison operator, used for map keys.
156 friend bool operator<(const DocNode &Lhs, const DocNode &Rhs) {
157 // This has to cope with one or both of the nodes being default-constructed,
158 // such that KindAndDoc is not set.
159 if (Rhs.isEmpty())
160 return false;
161 if (Lhs.KindAndDoc != Rhs.KindAndDoc) {
162 if (Lhs.isEmpty())
163 return true;
164 return (unsigned)Lhs.getKind() < (unsigned)Rhs.getKind();
165 }
166 switch (Lhs.getKind()) {
167 case Type::Int:
168 return Lhs.Int < Rhs.Int;
169 case Type::UInt:
170 return Lhs.UInt < Rhs.UInt;
171 case Type::Nil:
172 return false;
173 case Type::Boolean:
174 return Lhs.Bool < Rhs.Bool;
175 case Type::Float:
176 return Lhs.Float < Rhs.Float;
177 case Type::String:
178 case Type::Binary:
179 return Lhs.Raw < Rhs.Raw;
180 default:
181 llvm_unreachable("bad map key type");
182 }
183 }
184
185 /// Equality operator
186 friend bool operator==(const DocNode &Lhs, const DocNode &Rhs) {
187 return !(Lhs < Rhs) && !(Rhs < Lhs);
188 }
189
190 /// Inequality operator
191 friend bool operator!=(const DocNode &Lhs, const DocNode &Rhs) {
192 return !(Lhs == Rhs);
193 }
194
195 /// Convert this node to a string, assuming it is scalar.
196 LLVM_ABI std::string toString() const;
197
198 /// Convert the StringRef and use it to set this DocNode (assuming scalar). If
199 /// it is a string, copy the string into the Document's strings list so we do
200 /// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
202
203 /// Convenience assignment operators. This only works if the destination
204 /// DocNode has an associated Document, i.e. it was not constructed using the
205 /// default constructor. The string one does not copy, so the string must
206 /// remain valid for the lifetime of the Document. Use fromString to avoid
207 /// that restriction.
208 DocNode &operator=(const char *Val) { return *this = StringRef(Val); }
211 LLVM_ABI DocNode &operator=(bool Val);
212 LLVM_ABI DocNode &operator=(int Val);
213 LLVM_ABI DocNode &operator=(unsigned Val);
214 LLVM_ABI DocNode &operator=(int64_t Val);
216 LLVM_ABI DocNode &operator=(double Val);
217
218private:
219 // Private constructor setting KindAndDoc, used by methods in Document.
220 DocNode(const KindAndDocument *KindAndDoc) : KindAndDoc(KindAndDoc) {}
221
222 LLVM_ABI void convertToArray();
223 LLVM_ABI void convertToMap();
224};
225
226/// A DocNode that is a map.
227class MapDocNode : public DocNode {
228public:
229 MapDocNode() = default;
231
232 // Map access methods.
233 size_t size() const { return Map->size(); }
234 bool empty() const { return !size(); }
235 MapTy::iterator begin() { return Map->begin(); }
236 MapTy::iterator end() { return Map->end(); }
237 MapTy::iterator find(DocNode Key) { return Map->find(Key); }
238 LLVM_ABI MapTy::iterator find(StringRef Key);
239 MapTy::iterator erase(MapTy::const_iterator I) { return Map->erase(I); }
240 size_t erase(DocNode Key) { return Map->erase(Key); }
241 MapTy::iterator erase(MapTy::const_iterator First,
242 MapTy::const_iterator Second) {
243 return Map->erase(First, Second);
244 }
245 /// Member access. The string data must remain valid for the lifetime of the
246 /// Document.
248 /// Member access, with convenience versions for an integer key.
250 LLVM_ABI DocNode &operator[](int Key);
251 LLVM_ABI DocNode &operator[](unsigned Key);
252 LLVM_ABI DocNode &operator[](int64_t Key);
254};
255
256/// A DocNode that is an array.
257class ArrayDocNode : public DocNode {
258public:
259 ArrayDocNode() = default;
261
262 // Array access methods.
263 size_t size() const { return Array->size(); }
264 bool empty() const { return !size(); }
265 DocNode &back() const { return Array->back(); }
266 ArrayTy::iterator begin() { return Array->begin(); }
267 ArrayTy::iterator end() { return Array->end(); }
269 assert(N.isEmpty() || N.getDocument() == getDocument());
270 Array->push_back(N);
271 }
272
273 /// Element access. This extends the array if necessary, with empty nodes.
275};
276
277/// Simple in-memory representation of a document of msgpack objects with
278/// ability to find and create array and map elements. Does not currently cope
279/// with any extension types.
280class Document {
281 // Maps, arrays and strings used by nodes in the document. No attempt is made
282 // to free unused ones.
283 std::vector<std::unique_ptr<DocNode::MapTy>> Maps;
284 std::vector<std::unique_ptr<DocNode::ArrayTy>> Arrays;
285 std::vector<std::unique_ptr<char[]>> Strings;
286
287 // The root node of the document.
288 DocNode Root;
289
290 // The KindAndDocument structs pointed to by nodes in the document.
291 KindAndDocument KindAndDocs[size_t(Type::Empty) + 1];
292
293 // Whether YAML output uses hex for UInt.
294 bool HexMode = false;
295
296public:
298 clear();
299 for (unsigned T = 0; T != unsigned(Type::Empty) + 1; ++T)
300 KindAndDocs[T] = {this, Type(T)};
301 }
302
303 /// Get ref to the document's root element.
304 DocNode &getRoot() { return Root; }
305
306 /// Restore the Document to an empty state.
307 void clear() { getRoot() = getEmptyNode(); }
308
309 /// Create an empty node associated with this Document.
311 auto N = DocNode(&KindAndDocs[size_t(Type::Empty)]);
312 return N;
313 }
314
315 /// Create a nil node associated with this Document.
317 auto N = DocNode(&KindAndDocs[size_t(Type::Nil)]);
318 return N;
319 }
320
321 /// Create an Int node associated with this Document.
322 DocNode getNode(int64_t V) {
323 auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
324 N.Int = V;
325 return N;
326 }
327
328 /// Create an Int node associated with this Document.
330 auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
331 N.Int = V;
332 return N;
333 }
334
335 /// Create a UInt node associated with this Document.
337 auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
338 N.UInt = V;
339 return N;
340 }
341
342 /// Create a UInt node associated with this Document.
343 DocNode getNode(unsigned V) {
344 auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
345 N.UInt = V;
346 return N;
347 }
348
349 /// Create a Boolean node associated with this Document.
350 DocNode getNode(bool V) {
351 auto N = DocNode(&KindAndDocs[size_t(Type::Boolean)]);
352 N.Bool = V;
353 return N;
354 }
355
356 /// Create a Float node associated with this Document.
357 DocNode getNode(double V) {
358 auto N = DocNode(&KindAndDocs[size_t(Type::Float)]);
359 N.Float = V;
360 return N;
361 }
362
363 /// Create a String node associated with this Document. If !Copy, the passed
364 /// string must remain valid for the lifetime of the Document.
365 DocNode getNode(StringRef V, bool Copy = false) {
366 if (Copy)
367 V = addString(V);
368 auto N = DocNode(&KindAndDocs[size_t(Type::String)]);
369 N.Raw = V;
370 return N;
371 }
372
373 /// Create a String node associated with this Document. If !Copy, the passed
374 /// string must remain valid for the lifetime of the Document.
375 DocNode getNode(const char *V, bool Copy = false) {
376 return getNode(StringRef(V), Copy);
377 }
378
379 /// Create a Binary node associated with this Document. If !Copy, the passed
380 /// buffer must remain valid for the lifetime of the Document.
381 DocNode getNode(MemoryBufferRef V, bool Copy = false) {
382 auto Raw = V.getBuffer();
383 if (Copy)
384 Raw = addString(Raw);
385 auto N = DocNode(&KindAndDocs[size_t(Type::Binary)]);
386 N.Raw = Raw;
387 return N;
388 }
389
390 /// Create an empty Map node associated with this Document.
392 auto N = DocNode(&KindAndDocs[size_t(Type::Map)]);
393 Maps.push_back(std::make_unique<DocNode::MapTy>());
394 N.Map = Maps.back().get();
395 return N.getMap();
396 }
397
398 /// Create an empty Array node associated with this Document.
400 auto N = DocNode(&KindAndDocs[size_t(Type::Array)]);
401 Arrays.push_back(std::make_unique<DocNode::ArrayTy>());
402 N.Array = Arrays.back().get();
403 return N.getArray();
404 }
405
406 /// Read a document from a binary msgpack blob, merging into anything already
407 /// in the Document. The blob data must remain valid for the lifetime of this
408 /// Document (because a string object in the document contains a StringRef
409 /// into the original blob). If Multi, then this sets root to an array and
410 /// adds top-level objects to it. If !Multi, then it only reads a single
411 /// top-level object, even if there are more, and sets root to that. Returns
412 /// false if failed due to illegal format or merge error.
413 ///
414 /// The Merger arg is a callback function that is called when the merge has a
415 /// conflict, that is, it is trying to set an item that is already set. If the
416 /// conflict cannot be resolved, the callback function returns -1. If the
417 /// conflict can be resolved, the callback returns a non-negative number and
418 /// sets *DestNode to the resolved node. The returned non-negative number is
419 /// significant only for an array node; it is then the array index to start
420 /// populating at. That allows Merger to choose whether to merge array
421 /// elements (returns 0) or append new elements (returns existing size).
422 ///
423 /// If SrcNode is an array or map, the resolution must be that *DestNode is an
424 /// array or map respectively, although it could be the array or map
425 /// (respectively) that was already there. MapKey is the key if *DestNode is a
426 /// map entry, a nil node otherwise.
427 ///
428 /// The default for Merger is to disallow any conflict.
430 StringRef Blob, bool Multi,
431 function_ref<int(DocNode *DestNode, DocNode SrcNode, DocNode MapKey)>
432 Merger = [](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
433 return -1;
434 });
435
436 /// Write a MsgPack document to a binary MsgPack blob.
437 LLVM_ABI void writeToBlob(std::string &Blob);
438
439 /// Copy a string into the Document's strings list, and return the copy that
440 /// is owned by the Document.
442 Strings.push_back(std::unique_ptr<char[]>(new char[S.size()]));
443 memcpy(&Strings.back()[0], S.data(), S.size());
444 return StringRef(&Strings.back()[0], S.size());
445 }
446
447 /// Set whether YAML output uses hex for UInt. Default off.
448 void setHexMode(bool Val = true) { HexMode = Val; }
449
450 /// Get Hexmode flag.
451 bool getHexMode() const { return HexMode; }
452
453 /// Convert MsgPack Document to YAML text.
455
456 /// Read YAML text into the MsgPack document. Returns false on failure.
458};
459
460} // namespace msgpack
461} // namespace llvm
462
463#endif // LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition: Compiler.h:213
uint32_t Index
#define I(x, y, z)
Definition: MD5.cpp:58
#define T
R600 Vector Reg Merger
raw_pwrite_stream & OS
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:154
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:148
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.
ArrayTy::iterator begin()
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
int64_t getInt() const
StringRef getString() const
LLVM_ABI std::string toString() const
Convert this node to a string, assuming it is scalar.
std::vector< DocNode > ArrayTy
DocNode & operator=(const char *Val)
Convenience assignment operators.
friend bool operator==(const DocNode &Lhs, const DocNode &Rhs)
Equality operator.
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.
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
Definition: MsgPackReader.h:54
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
#define N
The kind of a DocNode and its owning Document.