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