10b57cec5SDimitry Andric //===-- MsgPackDocument.cpp - MsgPack Document --------------------------*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// This file implements a class that exposes a simple in-memory representation
100b57cec5SDimitry Andric /// of a document of MsgPack objects, that can be read from MsgPack, written to
110b57cec5SDimitry Andric /// MsgPack, and inspected and modified in memory. This is intended to be a
120b57cec5SDimitry Andric /// lighter-weight (in terms of memory allocations) replacement for
130b57cec5SDimitry Andric /// MsgPackTypes.
140b57cec5SDimitry Andric ///
150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/MsgPackDocument.h"
180b57cec5SDimitry Andric #include "llvm/BinaryFormat/MsgPackWriter.h"
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric using namespace msgpack;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric // Convert this DocNode into an empty array.
convertToArray()240b57cec5SDimitry Andric void DocNode::convertToArray() { *this = getDocument()->getArrayNode(); }
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric // Convert this DocNode into an empty map.
convertToMap()270b57cec5SDimitry Andric void DocNode::convertToMap() { *this = getDocument()->getMapNode(); }
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric /// Find the key in the MapDocNode.
find(StringRef S)300b57cec5SDimitry Andric DocNode::MapTy::iterator MapDocNode::find(StringRef S) {
310b57cec5SDimitry Andric return find(getDocument()->getNode(S));
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric /// Member access for MapDocNode. The string data must remain valid for the
350b57cec5SDimitry Andric /// lifetime of the Document.
operator [](StringRef S)360b57cec5SDimitry Andric DocNode &MapDocNode::operator[](StringRef S) {
370b57cec5SDimitry Andric return (*this)[getDocument()->getNode(S)];
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric /// Member access for MapDocNode.
operator [](DocNode Key)410b57cec5SDimitry Andric DocNode &MapDocNode::operator[](DocNode Key) {
420b57cec5SDimitry Andric assert(!Key.isEmpty());
435ffd83dbSDimitry Andric DocNode &N = (*Map)[Key];
445ffd83dbSDimitry Andric if (N.isEmpty()) {
450b57cec5SDimitry Andric // Ensure a new element has its KindAndDoc initialized.
465ffd83dbSDimitry Andric N = getDocument()->getEmptyNode();
470b57cec5SDimitry Andric }
485ffd83dbSDimitry Andric return N;
495ffd83dbSDimitry Andric }
505ffd83dbSDimitry Andric
515ffd83dbSDimitry Andric /// Member access for MapDocNode for integer key.
operator [](int Key)525ffd83dbSDimitry Andric DocNode &MapDocNode::operator[](int Key) {
535ffd83dbSDimitry Andric return (*this)[getDocument()->getNode(Key)];
545ffd83dbSDimitry Andric }
operator [](unsigned Key)555ffd83dbSDimitry Andric DocNode &MapDocNode::operator[](unsigned Key) {
565ffd83dbSDimitry Andric return (*this)[getDocument()->getNode(Key)];
575ffd83dbSDimitry Andric }
operator [](int64_t Key)585ffd83dbSDimitry Andric DocNode &MapDocNode::operator[](int64_t Key) {
595ffd83dbSDimitry Andric return (*this)[getDocument()->getNode(Key)];
605ffd83dbSDimitry Andric }
operator [](uint64_t Key)615ffd83dbSDimitry Andric DocNode &MapDocNode::operator[](uint64_t Key) {
625ffd83dbSDimitry Andric return (*this)[getDocument()->getNode(Key)];
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric /// Array element access. This extends the array if necessary.
operator [](size_t Index)660b57cec5SDimitry Andric DocNode &ArrayDocNode::operator[](size_t Index) {
670b57cec5SDimitry Andric if (size() <= Index) {
680b57cec5SDimitry Andric // Ensure new elements have their KindAndDoc initialized.
695ffd83dbSDimitry Andric Array->resize(Index + 1, getDocument()->getEmptyNode());
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric return (*Array)[Index];
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
745ffd83dbSDimitry Andric // Convenience assignment operators. This only works if the destination
755ffd83dbSDimitry Andric // DocNode has an associated Document, i.e. it was not constructed using the
765ffd83dbSDimitry Andric // default constructor. The string one does not copy, so the string must
775ffd83dbSDimitry Andric // remain valid for the lifetime of the Document. Use fromString to avoid
785ffd83dbSDimitry Andric // that restriction.
operator =(StringRef Val)795ffd83dbSDimitry Andric DocNode &DocNode::operator=(StringRef Val) {
805ffd83dbSDimitry Andric *this = getDocument()->getNode(Val);
815ffd83dbSDimitry Andric return *this;
825ffd83dbSDimitry Andric }
operator =(MemoryBufferRef Val)8306c3fb27SDimitry Andric DocNode &DocNode::operator=(MemoryBufferRef Val) {
8406c3fb27SDimitry Andric *this = getDocument()->getNode(Val);
8506c3fb27SDimitry Andric return *this;
8606c3fb27SDimitry Andric }
operator =(bool Val)875ffd83dbSDimitry Andric DocNode &DocNode::operator=(bool Val) {
885ffd83dbSDimitry Andric *this = getDocument()->getNode(Val);
895ffd83dbSDimitry Andric return *this;
905ffd83dbSDimitry Andric }
operator =(int Val)915ffd83dbSDimitry Andric DocNode &DocNode::operator=(int Val) {
925ffd83dbSDimitry Andric *this = getDocument()->getNode(Val);
935ffd83dbSDimitry Andric return *this;
945ffd83dbSDimitry Andric }
operator =(unsigned Val)955ffd83dbSDimitry Andric DocNode &DocNode::operator=(unsigned Val) {
965ffd83dbSDimitry Andric *this = getDocument()->getNode(Val);
975ffd83dbSDimitry Andric return *this;
985ffd83dbSDimitry Andric }
operator =(int64_t Val)995ffd83dbSDimitry Andric DocNode &DocNode::operator=(int64_t Val) {
1005ffd83dbSDimitry Andric *this = getDocument()->getNode(Val);
1015ffd83dbSDimitry Andric return *this;
1025ffd83dbSDimitry Andric }
operator =(uint64_t Val)1035ffd83dbSDimitry Andric DocNode &DocNode::operator=(uint64_t Val) {
1045ffd83dbSDimitry Andric *this = getDocument()->getNode(Val);
1055ffd83dbSDimitry Andric return *this;
1065ffd83dbSDimitry Andric }
1075ffd83dbSDimitry Andric
1080b57cec5SDimitry Andric // A level in the document reading stack.
1090b57cec5SDimitry Andric struct StackLevel {
StackLevelStackLevel1105ffd83dbSDimitry Andric StackLevel(DocNode Node, size_t StartIndex, size_t Length,
1115ffd83dbSDimitry Andric DocNode *MapEntry = nullptr)
1125ffd83dbSDimitry Andric : Node(Node), Index(StartIndex), End(StartIndex + Length),
1135ffd83dbSDimitry Andric MapEntry(MapEntry) {}
1140b57cec5SDimitry Andric DocNode Node;
1155ffd83dbSDimitry Andric size_t Index;
1165ffd83dbSDimitry Andric size_t End;
1170b57cec5SDimitry Andric // Points to map entry when we have just processed a map key.
1180b57cec5SDimitry Andric DocNode *MapEntry;
1195ffd83dbSDimitry Andric DocNode MapKey;
1200b57cec5SDimitry Andric };
1210b57cec5SDimitry Andric
1225ffd83dbSDimitry Andric // Read a document from a binary msgpack blob, merging into anything already in
1235ffd83dbSDimitry Andric // the Document.
1240b57cec5SDimitry Andric // The blob data must remain valid for the lifetime of this Document (because a
1250b57cec5SDimitry Andric // string object in the document contains a StringRef into the original blob).
1260b57cec5SDimitry Andric // If Multi, then this sets root to an array and adds top-level objects to it.
1270b57cec5SDimitry Andric // If !Multi, then it only reads a single top-level object, even if there are
1280b57cec5SDimitry Andric // more, and sets root to that.
1295ffd83dbSDimitry Andric // Returns false if failed due to illegal format or merge error.
1305ffd83dbSDimitry Andric
readFromBlob(StringRef Blob,bool Multi,function_ref<int (DocNode * DestNode,DocNode SrcNode,DocNode MapKey)> Merger)1315ffd83dbSDimitry Andric bool Document::readFromBlob(
1325ffd83dbSDimitry Andric StringRef Blob, bool Multi,
1335ffd83dbSDimitry Andric function_ref<int(DocNode *DestNode, DocNode SrcNode, DocNode MapKey)>
1345ffd83dbSDimitry Andric Merger) {
1350b57cec5SDimitry Andric msgpack::Reader MPReader(Blob);
1360b57cec5SDimitry Andric SmallVector<StackLevel, 4> Stack;
1370b57cec5SDimitry Andric if (Multi) {
1380b57cec5SDimitry Andric // Create the array for multiple top-level objects.
1390b57cec5SDimitry Andric Root = getArrayNode();
1405ffd83dbSDimitry Andric Stack.push_back(StackLevel(Root, 0, (size_t)-1));
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric do {
1430b57cec5SDimitry Andric // On to next element (or key if doing a map key next).
1440b57cec5SDimitry Andric // Read the value.
1450b57cec5SDimitry Andric Object Obj;
146*5f757f3fSDimitry Andric Expected<bool> ReadObj = MPReader.read(Obj);
147*5f757f3fSDimitry Andric if (!ReadObj) {
148*5f757f3fSDimitry Andric // FIXME: Propagate the Error to the caller.
149*5f757f3fSDimitry Andric consumeError(ReadObj.takeError());
150*5f757f3fSDimitry Andric return false;
151*5f757f3fSDimitry Andric }
152*5f757f3fSDimitry Andric if (!ReadObj.get()) {
1530b57cec5SDimitry Andric if (Multi && Stack.size() == 1) {
1540b57cec5SDimitry Andric // OK to finish here as we've just done a top-level element with Multi
1550b57cec5SDimitry Andric break;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric return false; // Finished too early
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric // Convert it into a DocNode.
1600b57cec5SDimitry Andric DocNode Node;
1610b57cec5SDimitry Andric switch (Obj.Kind) {
1620b57cec5SDimitry Andric case Type::Nil:
1630b57cec5SDimitry Andric Node = getNode();
1640b57cec5SDimitry Andric break;
1650b57cec5SDimitry Andric case Type::Int:
1660b57cec5SDimitry Andric Node = getNode(Obj.Int);
1670b57cec5SDimitry Andric break;
1680b57cec5SDimitry Andric case Type::UInt:
1690b57cec5SDimitry Andric Node = getNode(Obj.UInt);
1700b57cec5SDimitry Andric break;
1710b57cec5SDimitry Andric case Type::Boolean:
1720b57cec5SDimitry Andric Node = getNode(Obj.Bool);
1730b57cec5SDimitry Andric break;
1740b57cec5SDimitry Andric case Type::Float:
1750b57cec5SDimitry Andric Node = getNode(Obj.Float);
1760b57cec5SDimitry Andric break;
1770b57cec5SDimitry Andric case Type::String:
1780b57cec5SDimitry Andric Node = getNode(Obj.Raw);
1790b57cec5SDimitry Andric break;
18006c3fb27SDimitry Andric case Type::Binary:
18106c3fb27SDimitry Andric Node = getNode(MemoryBufferRef(Obj.Raw, ""));
18206c3fb27SDimitry Andric break;
1830b57cec5SDimitry Andric case Type::Map:
1840b57cec5SDimitry Andric Node = getMapNode();
1850b57cec5SDimitry Andric break;
1860b57cec5SDimitry Andric case Type::Array:
1870b57cec5SDimitry Andric Node = getArrayNode();
1880b57cec5SDimitry Andric break;
1890b57cec5SDimitry Andric default:
1900b57cec5SDimitry Andric return false; // Raw and Extension not supported
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andric // Store it.
1945ffd83dbSDimitry Andric DocNode *DestNode = nullptr;
1950b57cec5SDimitry Andric if (Stack.empty())
1965ffd83dbSDimitry Andric DestNode = &Root;
1970b57cec5SDimitry Andric else if (Stack.back().Node.getKind() == Type::Array) {
1980b57cec5SDimitry Andric // Reading an array entry.
1990b57cec5SDimitry Andric auto &Array = Stack.back().Node.getArray();
2005ffd83dbSDimitry Andric DestNode = &Array[Stack.back().Index++];
2010b57cec5SDimitry Andric } else {
2020b57cec5SDimitry Andric auto &Map = Stack.back().Node.getMap();
2030b57cec5SDimitry Andric if (!Stack.back().MapEntry) {
2040b57cec5SDimitry Andric // Reading a map key.
2055ffd83dbSDimitry Andric Stack.back().MapKey = Node;
2060b57cec5SDimitry Andric Stack.back().MapEntry = &Map[Node];
2075ffd83dbSDimitry Andric continue;
2085ffd83dbSDimitry Andric }
2090b57cec5SDimitry Andric // Reading the value for the map key read in the last iteration.
2105ffd83dbSDimitry Andric DestNode = Stack.back().MapEntry;
2110b57cec5SDimitry Andric Stack.back().MapEntry = nullptr;
2125ffd83dbSDimitry Andric ++Stack.back().Index;
2130b57cec5SDimitry Andric }
2145ffd83dbSDimitry Andric int MergeResult = 0;
2155ffd83dbSDimitry Andric if (!DestNode->isEmpty()) {
2165ffd83dbSDimitry Andric // In a merge, there is already a value at this position. Call the
2175ffd83dbSDimitry Andric // callback to attempt to resolve the conflict. The resolution must result
2185ffd83dbSDimitry Andric // in an array or map if Node is an array or map respectively.
2195ffd83dbSDimitry Andric DocNode MapKey = !Stack.empty() && !Stack.back().MapKey.isEmpty()
2205ffd83dbSDimitry Andric ? Stack.back().MapKey
2215ffd83dbSDimitry Andric : getNode();
2225ffd83dbSDimitry Andric MergeResult = Merger(DestNode, Node, MapKey);
2235ffd83dbSDimitry Andric if (MergeResult < 0)
2245ffd83dbSDimitry Andric return false; // Merge conflict resolution failed
2255ffd83dbSDimitry Andric assert(!((Node.isMap() && !DestNode->isMap()) ||
2265ffd83dbSDimitry Andric (Node.isArray() && !DestNode->isArray())));
2275ffd83dbSDimitry Andric } else
2285ffd83dbSDimitry Andric *DestNode = Node;
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric // See if we're starting a new array or map.
2315ffd83dbSDimitry Andric switch (DestNode->getKind()) {
2320b57cec5SDimitry Andric case msgpack::Type::Array:
2330b57cec5SDimitry Andric case msgpack::Type::Map:
2345ffd83dbSDimitry Andric Stack.push_back(StackLevel(*DestNode, MergeResult, Obj.Length, nullptr));
2350b57cec5SDimitry Andric break;
2360b57cec5SDimitry Andric default:
2370b57cec5SDimitry Andric break;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric // Pop finished stack levels.
2410b57cec5SDimitry Andric while (!Stack.empty()) {
2425ffd83dbSDimitry Andric if (Stack.back().MapEntry)
2430b57cec5SDimitry Andric break;
2445ffd83dbSDimitry Andric if (Stack.back().Index != Stack.back().End)
2450b57cec5SDimitry Andric break;
2460b57cec5SDimitry Andric Stack.pop_back();
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric } while (!Stack.empty());
2490b57cec5SDimitry Andric return true;
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric struct WriterStackLevel {
2530b57cec5SDimitry Andric DocNode Node;
2540b57cec5SDimitry Andric DocNode::MapTy::iterator MapIt;
2550b57cec5SDimitry Andric DocNode::ArrayTy::iterator ArrayIt;
2560b57cec5SDimitry Andric bool OnKey;
2570b57cec5SDimitry Andric };
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric /// Write a MsgPack document to a binary MsgPack blob.
writeToBlob(std::string & Blob)2600b57cec5SDimitry Andric void Document::writeToBlob(std::string &Blob) {
2610b57cec5SDimitry Andric Blob.clear();
2620b57cec5SDimitry Andric raw_string_ostream OS(Blob);
2630b57cec5SDimitry Andric msgpack::Writer MPWriter(OS);
2640b57cec5SDimitry Andric SmallVector<WriterStackLevel, 4> Stack;
2650b57cec5SDimitry Andric DocNode Node = getRoot();
2660b57cec5SDimitry Andric for (;;) {
2670b57cec5SDimitry Andric switch (Node.getKind()) {
2680b57cec5SDimitry Andric case Type::Array:
2690b57cec5SDimitry Andric MPWriter.writeArraySize(Node.getArray().size());
2700b57cec5SDimitry Andric Stack.push_back(
2710b57cec5SDimitry Andric {Node, DocNode::MapTy::iterator(), Node.getArray().begin(), false});
2720b57cec5SDimitry Andric break;
2730b57cec5SDimitry Andric case Type::Map:
2740b57cec5SDimitry Andric MPWriter.writeMapSize(Node.getMap().size());
2750b57cec5SDimitry Andric Stack.push_back(
2760b57cec5SDimitry Andric {Node, Node.getMap().begin(), DocNode::ArrayTy::iterator(), true});
2770b57cec5SDimitry Andric break;
2780b57cec5SDimitry Andric case Type::Nil:
2790b57cec5SDimitry Andric MPWriter.writeNil();
2800b57cec5SDimitry Andric break;
2810b57cec5SDimitry Andric case Type::Boolean:
2820b57cec5SDimitry Andric MPWriter.write(Node.getBool());
2830b57cec5SDimitry Andric break;
2840b57cec5SDimitry Andric case Type::Int:
2850b57cec5SDimitry Andric MPWriter.write(Node.getInt());
2860b57cec5SDimitry Andric break;
2870b57cec5SDimitry Andric case Type::UInt:
2880b57cec5SDimitry Andric MPWriter.write(Node.getUInt());
2890b57cec5SDimitry Andric break;
2900b57cec5SDimitry Andric case Type::String:
2910b57cec5SDimitry Andric MPWriter.write(Node.getString());
2920b57cec5SDimitry Andric break;
29306c3fb27SDimitry Andric case Type::Binary:
29406c3fb27SDimitry Andric MPWriter.write(Node.getBinary());
29506c3fb27SDimitry Andric break;
296e8d8bef9SDimitry Andric case Type::Empty:
297e8d8bef9SDimitry Andric llvm_unreachable("unhandled empty msgpack node");
2980b57cec5SDimitry Andric default:
2990b57cec5SDimitry Andric llvm_unreachable("unhandled msgpack object kind");
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric // Pop finished stack levels.
3020b57cec5SDimitry Andric while (!Stack.empty()) {
3030b57cec5SDimitry Andric if (Stack.back().Node.getKind() == Type::Map) {
3040b57cec5SDimitry Andric if (Stack.back().MapIt != Stack.back().Node.getMap().end())
3050b57cec5SDimitry Andric break;
3060b57cec5SDimitry Andric } else {
3070b57cec5SDimitry Andric if (Stack.back().ArrayIt != Stack.back().Node.getArray().end())
3080b57cec5SDimitry Andric break;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric Stack.pop_back();
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric if (Stack.empty())
3130b57cec5SDimitry Andric break;
3140b57cec5SDimitry Andric // Get the next value.
3150b57cec5SDimitry Andric if (Stack.back().Node.getKind() == Type::Map) {
3160b57cec5SDimitry Andric if (Stack.back().OnKey) {
3170b57cec5SDimitry Andric // Do the key of a key,value pair in a map.
3180b57cec5SDimitry Andric Node = Stack.back().MapIt->first;
3190b57cec5SDimitry Andric Stack.back().OnKey = false;
3200b57cec5SDimitry Andric } else {
3210b57cec5SDimitry Andric Node = Stack.back().MapIt->second;
3220b57cec5SDimitry Andric ++Stack.back().MapIt;
3230b57cec5SDimitry Andric Stack.back().OnKey = true;
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric } else {
3260b57cec5SDimitry Andric Node = *Stack.back().ArrayIt;
3270b57cec5SDimitry Andric ++Stack.back().ArrayIt;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric }
331