xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/BinaryFormat/MsgPackDocument.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===-- MsgPackDocument.h - MsgPack Document --------------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
8*82d56013Sjoerg /// \file
97330f729Sjoerg /// This file declares a class that exposes a simple in-memory representation
107330f729Sjoerg /// of a document of MsgPack objects, that can be read from MsgPack, written to
117330f729Sjoerg /// MsgPack, and inspected and modified in memory. This is intended to be a
127330f729Sjoerg /// lighter-weight (in terms of memory allocations) replacement for
137330f729Sjoerg /// MsgPackTypes.
147330f729Sjoerg ///
157330f729Sjoerg //===----------------------------------------------------------------------===//
167330f729Sjoerg 
177330f729Sjoerg #ifndef LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
187330f729Sjoerg #define LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
197330f729Sjoerg 
207330f729Sjoerg #include "llvm/BinaryFormat/MsgPackReader.h"
217330f729Sjoerg #include <map>
227330f729Sjoerg 
237330f729Sjoerg namespace llvm {
247330f729Sjoerg namespace msgpack {
257330f729Sjoerg 
267330f729Sjoerg class ArrayDocNode;
277330f729Sjoerg class Document;
287330f729Sjoerg class MapDocNode;
297330f729Sjoerg 
307330f729Sjoerg /// The kind of a DocNode and its owning Document.
317330f729Sjoerg struct KindAndDocument {
327330f729Sjoerg   Document *Doc;
337330f729Sjoerg   Type Kind;
347330f729Sjoerg };
357330f729Sjoerg 
367330f729Sjoerg /// A node in a MsgPack Document. This is a simple copyable and
377330f729Sjoerg /// passable-by-value type that does not own any memory.
387330f729Sjoerg class DocNode {
397330f729Sjoerg   friend Document;
407330f729Sjoerg 
417330f729Sjoerg public:
427330f729Sjoerg   typedef std::map<DocNode, DocNode> MapTy;
437330f729Sjoerg   typedef std::vector<DocNode> ArrayTy;
447330f729Sjoerg 
457330f729Sjoerg private:
467330f729Sjoerg   // Using KindAndDocument allows us to squeeze Kind and a pointer to the
477330f729Sjoerg   // owning Document into the same word. Having a pointer to the owning
487330f729Sjoerg   // Document makes the API of DocNode more convenient, and allows its use in
497330f729Sjoerg   // YAMLIO.
507330f729Sjoerg   const KindAndDocument *KindAndDoc;
517330f729Sjoerg 
527330f729Sjoerg protected:
537330f729Sjoerg   // The union of different values.
547330f729Sjoerg   union {
557330f729Sjoerg     int64_t Int;
567330f729Sjoerg     uint64_t UInt;
577330f729Sjoerg     bool Bool;
587330f729Sjoerg     double Float;
597330f729Sjoerg     StringRef Raw;
607330f729Sjoerg     ArrayTy *Array;
617330f729Sjoerg     MapTy *Map;
627330f729Sjoerg   };
637330f729Sjoerg 
647330f729Sjoerg public:
65*82d56013Sjoerg   // Default constructor gives an empty node with no associated Document. All
66*82d56013Sjoerg   // you can do with it is "isEmpty()".
DocNode()677330f729Sjoerg   DocNode() : KindAndDoc(nullptr) {}
687330f729Sjoerg 
697330f729Sjoerg   // Type methods
isMap()707330f729Sjoerg   bool isMap() const { return getKind() == Type::Map; }
isArray()717330f729Sjoerg   bool isArray() const { return getKind() == Type::Array; }
isScalar()727330f729Sjoerg   bool isScalar() const { return !isMap() && !isArray(); }
isString()737330f729Sjoerg   bool isString() const { return getKind() == Type::String; }
747330f729Sjoerg 
75*82d56013Sjoerg   // Accessors. isEmpty() returns true for both a default-constructed DocNode
76*82d56013Sjoerg   // that has no associated Document, and the result of getEmptyNode(), which
77*82d56013Sjoerg   // does have an associated document.
isEmpty()78*82d56013Sjoerg   bool isEmpty() const { return !KindAndDoc || getKind() == Type::Empty; }
getKind()797330f729Sjoerg   Type getKind() const { return KindAndDoc->Kind; }
getDocument()807330f729Sjoerg   Document *getDocument() const { return KindAndDoc->Doc; }
817330f729Sjoerg 
getInt()827330f729Sjoerg   int64_t &getInt() {
837330f729Sjoerg     assert(getKind() == Type::Int);
847330f729Sjoerg     return Int;
857330f729Sjoerg   }
867330f729Sjoerg 
getUInt()877330f729Sjoerg   uint64_t &getUInt() {
887330f729Sjoerg     assert(getKind() == Type::UInt);
897330f729Sjoerg     return UInt;
907330f729Sjoerg   }
917330f729Sjoerg 
getBool()927330f729Sjoerg   bool &getBool() {
937330f729Sjoerg     assert(getKind() == Type::Boolean);
947330f729Sjoerg     return Bool;
957330f729Sjoerg   }
967330f729Sjoerg 
getFloat()977330f729Sjoerg   double &getFloat() {
987330f729Sjoerg     assert(getKind() == Type::Float);
997330f729Sjoerg     return Float;
1007330f729Sjoerg   }
1017330f729Sjoerg 
getInt()1027330f729Sjoerg   int64_t getInt() const {
1037330f729Sjoerg     assert(getKind() == Type::Int);
1047330f729Sjoerg     return Int;
1057330f729Sjoerg   }
1067330f729Sjoerg 
getUInt()1077330f729Sjoerg   uint64_t getUInt() const {
1087330f729Sjoerg     assert(getKind() == Type::UInt);
1097330f729Sjoerg     return UInt;
1107330f729Sjoerg   }
1117330f729Sjoerg 
getBool()1127330f729Sjoerg   bool getBool() const {
1137330f729Sjoerg     assert(getKind() == Type::Boolean);
1147330f729Sjoerg     return Bool;
1157330f729Sjoerg   }
1167330f729Sjoerg 
getFloat()1177330f729Sjoerg   double getFloat() const {
1187330f729Sjoerg     assert(getKind() == Type::Float);
1197330f729Sjoerg     return Float;
1207330f729Sjoerg   }
1217330f729Sjoerg 
getString()1227330f729Sjoerg   StringRef getString() const {
1237330f729Sjoerg     assert(getKind() == Type::String);
1247330f729Sjoerg     return Raw;
1257330f729Sjoerg   }
1267330f729Sjoerg 
1277330f729Sjoerg   /// Get an ArrayDocNode for an array node. If Convert, convert the node to an
1287330f729Sjoerg   /// array node if necessary.
1297330f729Sjoerg   ArrayDocNode &getArray(bool Convert = false) {
1307330f729Sjoerg     if (getKind() != Type::Array) {
1317330f729Sjoerg       assert(Convert);
1327330f729Sjoerg       convertToArray();
1337330f729Sjoerg     }
1347330f729Sjoerg     // This could be a static_cast, except ArrayDocNode is a forward reference.
1357330f729Sjoerg     return *reinterpret_cast<ArrayDocNode *>(this);
1367330f729Sjoerg   }
1377330f729Sjoerg 
1387330f729Sjoerg   /// Get a MapDocNode for a map node. If Convert, convert the node to a map
1397330f729Sjoerg   /// node if necessary.
1407330f729Sjoerg   MapDocNode &getMap(bool Convert = false) {
1417330f729Sjoerg     if (getKind() != Type::Map) {
1427330f729Sjoerg       assert(Convert);
1437330f729Sjoerg       convertToMap();
1447330f729Sjoerg     }
1457330f729Sjoerg     // This could be a static_cast, except MapDocNode is a forward reference.
1467330f729Sjoerg     return *reinterpret_cast<MapDocNode *>(this);
1477330f729Sjoerg   }
1487330f729Sjoerg 
1497330f729Sjoerg   /// Comparison operator, used for map keys.
1507330f729Sjoerg   friend bool operator<(const DocNode &Lhs, const DocNode &Rhs) {
1517330f729Sjoerg     // This has to cope with one or both of the nodes being default-constructed,
1527330f729Sjoerg     // such that KindAndDoc is not set.
153*82d56013Sjoerg     if (Rhs.isEmpty())
1547330f729Sjoerg       return false;
155*82d56013Sjoerg     if (Lhs.KindAndDoc != Rhs.KindAndDoc) {
156*82d56013Sjoerg       if (Lhs.isEmpty())
1577330f729Sjoerg         return true;
1587330f729Sjoerg       return (unsigned)Lhs.getKind() < (unsigned)Rhs.getKind();
1597330f729Sjoerg     }
1607330f729Sjoerg     switch (Lhs.getKind()) {
1617330f729Sjoerg     case Type::Int:
1627330f729Sjoerg       return Lhs.Int < Rhs.Int;
1637330f729Sjoerg     case Type::UInt:
1647330f729Sjoerg       return Lhs.UInt < Rhs.UInt;
1657330f729Sjoerg     case Type::Nil:
1667330f729Sjoerg       return false;
1677330f729Sjoerg     case Type::Boolean:
1687330f729Sjoerg       return Lhs.Bool < Rhs.Bool;
1697330f729Sjoerg     case Type::Float:
1707330f729Sjoerg       return Lhs.Float < Rhs.Float;
1717330f729Sjoerg     case Type::String:
1727330f729Sjoerg     case Type::Binary:
1737330f729Sjoerg       return Lhs.Raw < Rhs.Raw;
1747330f729Sjoerg     default:
1757330f729Sjoerg       llvm_unreachable("bad map key type");
1767330f729Sjoerg     }
1777330f729Sjoerg   }
1787330f729Sjoerg 
1797330f729Sjoerg   /// Equality operator
1807330f729Sjoerg   friend bool operator==(const DocNode &Lhs, const DocNode &Rhs) {
1817330f729Sjoerg     return !(Lhs < Rhs) && !(Rhs < Lhs);
1827330f729Sjoerg   }
1837330f729Sjoerg 
184*82d56013Sjoerg   /// Inequality operator
185*82d56013Sjoerg   friend bool operator!=(const DocNode &Lhs, const DocNode &Rhs) {
186*82d56013Sjoerg     return !(Lhs == Rhs);
187*82d56013Sjoerg   }
188*82d56013Sjoerg 
1897330f729Sjoerg   /// Convert this node to a string, assuming it is scalar.
1907330f729Sjoerg   std::string toString() const;
1917330f729Sjoerg 
1927330f729Sjoerg   /// Convert the StringRef and use it to set this DocNode (assuming scalar). If
1937330f729Sjoerg   /// it is a string, copy the string into the Document's strings list so we do
1947330f729Sjoerg   /// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
1957330f729Sjoerg   StringRef fromString(StringRef S, StringRef Tag = "");
1967330f729Sjoerg 
197*82d56013Sjoerg   /// Convenience assignment operators. This only works if the destination
198*82d56013Sjoerg   /// DocNode has an associated Document, i.e. it was not constructed using the
199*82d56013Sjoerg   /// default constructor. The string one does not copy, so the string must
200*82d56013Sjoerg   /// remain valid for the lifetime of the Document. Use fromString to avoid
201*82d56013Sjoerg   /// that restriction.
202*82d56013Sjoerg   DocNode &operator=(const char *Val) { return *this = StringRef(Val); }
203*82d56013Sjoerg   DocNode &operator=(StringRef Val);
204*82d56013Sjoerg   DocNode &operator=(bool Val);
205*82d56013Sjoerg   DocNode &operator=(int Val);
206*82d56013Sjoerg   DocNode &operator=(unsigned Val);
207*82d56013Sjoerg   DocNode &operator=(int64_t Val);
208*82d56013Sjoerg   DocNode &operator=(uint64_t Val);
209*82d56013Sjoerg 
2107330f729Sjoerg private:
2117330f729Sjoerg   // Private constructor setting KindAndDoc, used by methods in Document.
DocNode(const KindAndDocument * KindAndDoc)2127330f729Sjoerg   DocNode(const KindAndDocument *KindAndDoc) : KindAndDoc(KindAndDoc) {}
2137330f729Sjoerg 
2147330f729Sjoerg   void convertToArray();
2157330f729Sjoerg   void convertToMap();
2167330f729Sjoerg };
2177330f729Sjoerg 
2187330f729Sjoerg /// A DocNode that is a map.
2197330f729Sjoerg class MapDocNode : public DocNode {
2207330f729Sjoerg public:
MapDocNode()2217330f729Sjoerg   MapDocNode() {}
MapDocNode(DocNode & N)2227330f729Sjoerg   MapDocNode(DocNode &N) : DocNode(N) { assert(getKind() == Type::Map); }
2237330f729Sjoerg 
2247330f729Sjoerg   // Map access methods.
size()2257330f729Sjoerg   size_t size() const { return Map->size(); }
empty()2267330f729Sjoerg   bool empty() const { return !size(); }
begin()2277330f729Sjoerg   MapTy::iterator begin() { return Map->begin(); }
end()2287330f729Sjoerg   MapTy::iterator end() { return Map->end(); }
find(DocNode Key)2297330f729Sjoerg   MapTy::iterator find(DocNode Key) { return Map->find(Key); }
2307330f729Sjoerg   MapTy::iterator find(StringRef Key);
erase(MapTy::const_iterator I)231*82d56013Sjoerg   MapTy::iterator erase(MapTy::const_iterator I) { return Map->erase(I); }
erase(DocNode Key)232*82d56013Sjoerg   size_t erase(DocNode Key) { return Map->erase(Key); }
erase(MapTy::const_iterator First,MapTy::const_iterator Second)233*82d56013Sjoerg   MapTy::iterator erase(MapTy::const_iterator First,
234*82d56013Sjoerg                         MapTy::const_iterator Second) {
235*82d56013Sjoerg     return Map->erase(First, Second);
236*82d56013Sjoerg   }
2377330f729Sjoerg   /// Member access. The string data must remain valid for the lifetime of the
2387330f729Sjoerg   /// Document.
2397330f729Sjoerg   DocNode &operator[](StringRef S);
240*82d56013Sjoerg   /// Member access, with convenience versions for an integer key.
2417330f729Sjoerg   DocNode &operator[](DocNode Key);
242*82d56013Sjoerg   DocNode &operator[](int Key);
243*82d56013Sjoerg   DocNode &operator[](unsigned Key);
244*82d56013Sjoerg   DocNode &operator[](int64_t Key);
245*82d56013Sjoerg   DocNode &operator[](uint64_t Key);
2467330f729Sjoerg };
2477330f729Sjoerg 
2487330f729Sjoerg /// A DocNode that is an array.
2497330f729Sjoerg class ArrayDocNode : public DocNode {
2507330f729Sjoerg public:
ArrayDocNode()2517330f729Sjoerg   ArrayDocNode() {}
ArrayDocNode(DocNode & N)2527330f729Sjoerg   ArrayDocNode(DocNode &N) : DocNode(N) { assert(getKind() == Type::Array); }
2537330f729Sjoerg 
2547330f729Sjoerg   // Array access methods.
size()2557330f729Sjoerg   size_t size() const { return Array->size(); }
empty()2567330f729Sjoerg   bool empty() const { return !size(); }
back()257*82d56013Sjoerg   DocNode &back() const { return Array->back(); }
begin()2587330f729Sjoerg   ArrayTy::iterator begin() { return Array->begin(); }
end()2597330f729Sjoerg   ArrayTy::iterator end() { return Array->end(); }
push_back(DocNode N)2607330f729Sjoerg   void push_back(DocNode N) {
261*82d56013Sjoerg     assert(N.isEmpty() || N.getDocument() == getDocument());
2627330f729Sjoerg     Array->push_back(N);
2637330f729Sjoerg   }
2647330f729Sjoerg 
265*82d56013Sjoerg   /// Element access. This extends the array if necessary, with empty nodes.
2667330f729Sjoerg   DocNode &operator[](size_t Index);
2677330f729Sjoerg };
2687330f729Sjoerg 
2697330f729Sjoerg /// Simple in-memory representation of a document of msgpack objects with
2707330f729Sjoerg /// ability to find and create array and map elements.  Does not currently cope
2717330f729Sjoerg /// with any extension types.
2727330f729Sjoerg class Document {
2737330f729Sjoerg   // Maps, arrays and strings used by nodes in the document. No attempt is made
2747330f729Sjoerg   // to free unused ones.
2757330f729Sjoerg   std::vector<std::unique_ptr<DocNode::MapTy>> Maps;
2767330f729Sjoerg   std::vector<std::unique_ptr<DocNode::ArrayTy>> Arrays;
2777330f729Sjoerg   std::vector<std::unique_ptr<char[]>> Strings;
2787330f729Sjoerg 
2797330f729Sjoerg   // The root node of the document.
2807330f729Sjoerg   DocNode Root;
2817330f729Sjoerg 
2827330f729Sjoerg   // The KindAndDocument structs pointed to by nodes in the document.
283*82d56013Sjoerg   KindAndDocument KindAndDocs[size_t(Type::Empty) + 1];
2847330f729Sjoerg 
2857330f729Sjoerg   // Whether YAML output uses hex for UInt.
2867330f729Sjoerg   bool HexMode = false;
2877330f729Sjoerg 
2887330f729Sjoerg public:
Document()2897330f729Sjoerg   Document() {
2907330f729Sjoerg     clear();
291*82d56013Sjoerg     for (unsigned T = 0; T != unsigned(Type::Empty) + 1; ++T)
2927330f729Sjoerg       KindAndDocs[T] = {this, Type(T)};
2937330f729Sjoerg   }
2947330f729Sjoerg 
2957330f729Sjoerg   /// Get ref to the document's root element.
getRoot()2967330f729Sjoerg   DocNode &getRoot() { return Root; }
2977330f729Sjoerg 
2987330f729Sjoerg   /// Restore the Document to an empty state.
clear()299*82d56013Sjoerg   void clear() { getRoot() = getEmptyNode(); }
300*82d56013Sjoerg 
301*82d56013Sjoerg   /// Create an empty node associated with this Document.
getEmptyNode()302*82d56013Sjoerg   DocNode getEmptyNode() {
303*82d56013Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Empty)]);
304*82d56013Sjoerg     return N;
305*82d56013Sjoerg   }
3067330f729Sjoerg 
3077330f729Sjoerg   /// Create a nil node associated with this Document.
getNode()3087330f729Sjoerg   DocNode getNode() {
3097330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Nil)]);
3107330f729Sjoerg     return N;
3117330f729Sjoerg   }
3127330f729Sjoerg 
3137330f729Sjoerg   /// Create an Int node associated with this Document.
getNode(int64_t V)3147330f729Sjoerg   DocNode getNode(int64_t V) {
3157330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
3167330f729Sjoerg     N.Int = V;
3177330f729Sjoerg     return N;
3187330f729Sjoerg   }
3197330f729Sjoerg 
3207330f729Sjoerg   /// Create an Int node associated with this Document.
getNode(int V)3217330f729Sjoerg   DocNode getNode(int V) {
3227330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Int)]);
3237330f729Sjoerg     N.Int = V;
3247330f729Sjoerg     return N;
3257330f729Sjoerg   }
3267330f729Sjoerg 
3277330f729Sjoerg   /// Create a UInt node associated with this Document.
getNode(uint64_t V)3287330f729Sjoerg   DocNode getNode(uint64_t V) {
3297330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
3307330f729Sjoerg     N.UInt = V;
3317330f729Sjoerg     return N;
3327330f729Sjoerg   }
3337330f729Sjoerg 
3347330f729Sjoerg   /// Create a UInt node associated with this Document.
getNode(unsigned V)3357330f729Sjoerg   DocNode getNode(unsigned V) {
3367330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]);
3377330f729Sjoerg     N.UInt = V;
3387330f729Sjoerg     return N;
3397330f729Sjoerg   }
3407330f729Sjoerg 
3417330f729Sjoerg   /// Create a Boolean node associated with this Document.
getNode(bool V)3427330f729Sjoerg   DocNode getNode(bool V) {
3437330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Boolean)]);
3447330f729Sjoerg     N.Bool = V;
3457330f729Sjoerg     return N;
3467330f729Sjoerg   }
3477330f729Sjoerg 
3487330f729Sjoerg   /// Create a Float node associated with this Document.
getNode(double V)3497330f729Sjoerg   DocNode getNode(double V) {
3507330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Float)]);
3517330f729Sjoerg     N.Float = V;
3527330f729Sjoerg     return N;
3537330f729Sjoerg   }
3547330f729Sjoerg 
3557330f729Sjoerg   /// Create a String node associated with this Document. If !Copy, the passed
3567330f729Sjoerg   /// string must remain valid for the lifetime of the Document.
3577330f729Sjoerg   DocNode getNode(StringRef V, bool Copy = false) {
3587330f729Sjoerg     if (Copy)
3597330f729Sjoerg       V = addString(V);
3607330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::String)]);
3617330f729Sjoerg     N.Raw = V;
3627330f729Sjoerg     return N;
3637330f729Sjoerg   }
3647330f729Sjoerg 
3657330f729Sjoerg   /// Create a String node associated with this Document. If !Copy, the passed
3667330f729Sjoerg   /// string must remain valid for the lifetime of the Document.
3677330f729Sjoerg   DocNode getNode(const char *V, bool Copy = false) {
3687330f729Sjoerg     return getNode(StringRef(V), Copy);
3697330f729Sjoerg   }
3707330f729Sjoerg 
3717330f729Sjoerg   /// Create an empty Map node associated with this Document.
getMapNode()3727330f729Sjoerg   MapDocNode getMapNode() {
3737330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Map)]);
3747330f729Sjoerg     Maps.push_back(std::unique_ptr<DocNode::MapTy>(new DocNode::MapTy));
3757330f729Sjoerg     N.Map = Maps.back().get();
3767330f729Sjoerg     return N.getMap();
3777330f729Sjoerg   }
3787330f729Sjoerg 
3797330f729Sjoerg   /// Create an empty Array node associated with this Document.
getArrayNode()3807330f729Sjoerg   ArrayDocNode getArrayNode() {
3817330f729Sjoerg     auto N = DocNode(&KindAndDocs[size_t(Type::Array)]);
3827330f729Sjoerg     Arrays.push_back(std::unique_ptr<DocNode::ArrayTy>(new DocNode::ArrayTy));
3837330f729Sjoerg     N.Array = Arrays.back().get();
3847330f729Sjoerg     return N.getArray();
3857330f729Sjoerg   }
3867330f729Sjoerg 
387*82d56013Sjoerg   /// Read a document from a binary msgpack blob, merging into anything already
388*82d56013Sjoerg   /// in the Document. The blob data must remain valid for the lifetime of this
389*82d56013Sjoerg   /// Document (because a string object in the document contains a StringRef
390*82d56013Sjoerg   /// into the original blob). If Multi, then this sets root to an array and
391*82d56013Sjoerg   /// adds top-level objects to it. If !Multi, then it only reads a single
392*82d56013Sjoerg   /// top-level object, even if there are more, and sets root to that. Returns
393*82d56013Sjoerg   /// false if failed due to illegal format or merge error.
394*82d56013Sjoerg   ///
395*82d56013Sjoerg   /// The Merger arg is a callback function that is called when the merge has a
396*82d56013Sjoerg   /// conflict, that is, it is trying to set an item that is already set. If the
397*82d56013Sjoerg   /// conflict cannot be resolved, the callback function returns -1. If the
398*82d56013Sjoerg   /// conflict can be resolved, the callback returns a non-negative number and
399*82d56013Sjoerg   /// sets *DestNode to the resolved node. The returned non-negative number is
400*82d56013Sjoerg   /// significant only for an array node; it is then the array index to start
401*82d56013Sjoerg   /// populating at. That allows Merger to choose whether to merge array
402*82d56013Sjoerg   /// elements (returns 0) or append new elements (returns existing size).
403*82d56013Sjoerg   ///
404*82d56013Sjoerg   /// If SrcNode is an array or map, the resolution must be that *DestNode is an
405*82d56013Sjoerg   /// array or map respectively, although it could be the array or map
406*82d56013Sjoerg   /// (respectively) that was already there. MapKey is the key if *DestNode is a
407*82d56013Sjoerg   /// map entry, a nil node otherwise.
408*82d56013Sjoerg   ///
409*82d56013Sjoerg   /// The default for Merger is to disallow any conflict.
410*82d56013Sjoerg   bool readFromBlob(
411*82d56013Sjoerg       StringRef Blob, bool Multi,
412*82d56013Sjoerg       function_ref<int(DocNode *DestNode, DocNode SrcNode, DocNode MapKey)>
413*82d56013Sjoerg           Merger = [](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
414*82d56013Sjoerg             return -1;
415*82d56013Sjoerg           });
4167330f729Sjoerg 
4177330f729Sjoerg   /// Write a MsgPack document to a binary MsgPack blob.
4187330f729Sjoerg   void writeToBlob(std::string &Blob);
4197330f729Sjoerg 
4207330f729Sjoerg   /// Copy a string into the Document's strings list, and return the copy that
4217330f729Sjoerg   /// is owned by the Document.
addString(StringRef S)4227330f729Sjoerg   StringRef addString(StringRef S) {
4237330f729Sjoerg     Strings.push_back(std::unique_ptr<char[]>(new char[S.size()]));
4247330f729Sjoerg     memcpy(&Strings.back()[0], S.data(), S.size());
4257330f729Sjoerg     return StringRef(&Strings.back()[0], S.size());
4267330f729Sjoerg   }
4277330f729Sjoerg 
4287330f729Sjoerg   /// Set whether YAML output uses hex for UInt. Default off.
4297330f729Sjoerg   void setHexMode(bool Val = true) { HexMode = Val; }
4307330f729Sjoerg 
4317330f729Sjoerg   /// Get Hexmode flag.
getHexMode()4327330f729Sjoerg   bool getHexMode() const { return HexMode; }
4337330f729Sjoerg 
4347330f729Sjoerg   /// Convert MsgPack Document to YAML text.
4357330f729Sjoerg   void toYAML(raw_ostream &OS);
4367330f729Sjoerg 
4377330f729Sjoerg   /// Read YAML text into the MsgPack document. Returns false on failure.
4387330f729Sjoerg   bool fromYAML(StringRef S);
4397330f729Sjoerg };
4407330f729Sjoerg 
4417330f729Sjoerg } // namespace msgpack
4427330f729Sjoerg } // namespace llvm
4437330f729Sjoerg 
4447330f729Sjoerg #endif // LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H
445