[llvm] r346978 - [BinaryFormat] Add MsgPackTypes
Scott Linder via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 15 10:50:01 PST 2018
Author: scott.linder
Date: Thu Nov 15 10:50:01 2018
New Revision: 346978
URL: http://llvm.org/viewvc/llvm-project?rev=346978&view=rev
Log:
[BinaryFormat] Add MsgPackTypes
Add data structure to represent MessagePack "documents" and convert
to/from both MessagePack and YAML encodings.
Differential Revision: https://reviews.llvm.org/D48175
Added:
llvm/trunk/include/llvm/BinaryFormat/MsgPackTypes.h
llvm/trunk/lib/BinaryFormat/MsgPackTypes.cpp
llvm/trunk/unittests/BinaryFormat/MsgPackTypesTest.cpp
Modified:
llvm/trunk/lib/BinaryFormat/CMakeLists.txt
llvm/trunk/unittests/BinaryFormat/CMakeLists.txt
Added: llvm/trunk/include/llvm/BinaryFormat/MsgPackTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MsgPackTypes.h?rev=346978&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MsgPackTypes.h (added)
+++ llvm/trunk/include/llvm/BinaryFormat/MsgPackTypes.h Thu Nov 15 10:50:01 2018
@@ -0,0 +1,372 @@
+//===- MsgPackTypes.h - MsgPack Types ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This is a data structure for representing MessagePack "documents", with
+/// methods to go to and from MessagePack. The types also specialize YAMLIO
+/// traits in order to go to and from YAML.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/BinaryFormat/MsgPackReader.h"
+#include "llvm/BinaryFormat/MsgPackWriter.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <vector>
+
+#ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H
+#define LLVM_BINARYFORMAT_MSGPACKTYPES_H
+
+namespace llvm {
+namespace msgpack {
+
+class Node;
+
+/// Short-hand for a Node pointer.
+using NodePtr = std::shared_ptr<Node>;
+
+/// Short-hand for an Optional Node pointer.
+using OptNodePtr = Optional<NodePtr>;
+
+/// Abstract base-class which can be any MessagePack type.
+class Node {
+public:
+ enum NodeKind {
+ NK_Scalar,
+ NK_Array,
+ NK_Map,
+ };
+
+private:
+ virtual void anchor() = 0;
+ const NodeKind Kind;
+
+ static Expected<OptNodePtr> readArray(Reader &MPReader, size_t Length);
+ static Expected<OptNodePtr> readMap(Reader &MPReader, size_t Length);
+
+public:
+ NodeKind getKind() const { return Kind; }
+
+ /// Construct a Node. Used by derived classes to track kind information.
+ Node(NodeKind Kind) : Kind(Kind) {}
+
+ virtual ~Node() = default;
+
+ /// Read from a MessagePack reader \p MPReader, returning an error if one is
+ /// encountered, or None if \p MPReader is at the end of stream, or some Node
+ /// pointer if some type is read.
+ static Expected<OptNodePtr> read(Reader &MPReader);
+
+ /// Write to a MessagePack writer \p MPWriter.
+ virtual void write(Writer &MPWriter) = 0;
+};
+
+/// A MessagePack scalar.
+class ScalarNode : public Node {
+public:
+ enum ScalarKind {
+ SK_Int,
+ SK_UInt,
+ SK_Nil,
+ SK_Boolean,
+ SK_Float,
+ SK_String,
+ SK_Binary,
+ };
+
+private:
+ void anchor() override;
+
+ void destroy();
+
+ ScalarKind SKind;
+
+ union {
+ int64_t IntValue;
+ uint64_t UIntValue;
+ bool BoolValue;
+ double FloatValue;
+ std::string StringValue;
+ };
+
+public:
+ /// Construct an Int ScalarNode.
+ ScalarNode(int64_t IntValue);
+ /// Construct an Int ScalarNode.
+ ScalarNode(int32_t IntValue);
+ /// Construct an UInt ScalarNode.
+ ScalarNode(uint64_t UIntValue);
+ /// Construct an UInt ScalarNode.
+ ScalarNode(uint32_t UIntValue);
+ /// Construct a Nil ScalarNode.
+ ScalarNode();
+ /// Construct a Boolean ScalarNode.
+ ScalarNode(bool BoolValue);
+ /// Construct a Float ScalarNode.
+ ScalarNode(double FloatValue);
+ /// Construct a String ScalarNode.
+ ScalarNode(StringRef StringValue);
+ /// Construct a String ScalarNode.
+ ScalarNode(const char *StringValue);
+ /// Construct a String ScalarNode.
+ ScalarNode(std::string &&StringValue);
+ /// Construct a Binary ScalarNode.
+ ScalarNode(MemoryBufferRef BinaryValue);
+
+ ~ScalarNode();
+
+ ScalarNode &operator=(const ScalarNode &RHS) = delete;
+ /// A ScalarNode can only be move assigned.
+ ScalarNode &operator=(ScalarNode &&RHS);
+
+ /// Change the kind of this ScalarNode, zero initializing it to the new type.
+ void setScalarKind(ScalarKind SKind) {
+ switch (SKind) {
+ case SK_Int:
+ *this = int64_t(0);
+ break;
+ case SK_UInt:
+ *this = uint64_t(0);
+ break;
+ case SK_Boolean:
+ *this = false;
+ break;
+ case SK_Float:
+ *this = 0.0;
+ break;
+ case SK_String:
+ *this = StringRef();
+ break;
+ case SK_Binary:
+ *this = MemoryBufferRef("", "");
+ break;
+ case SK_Nil:
+ *this = ScalarNode();
+ break;
+ }
+ }
+
+ /// Get the current kind of ScalarNode.
+ ScalarKind getScalarKind() { return SKind; }
+
+ /// Get the value of an Int scalar.
+ ///
+ /// \warning Assumes getScalarKind() == SK_Int
+ int64_t getInt() {
+ assert(SKind == SK_Int);
+ return IntValue;
+ }
+
+ /// Get the value of a UInt scalar.
+ ///
+ /// \warning Assumes getScalarKind() == SK_UInt
+ uint64_t getUInt() {
+ assert(SKind == SK_UInt);
+ return UIntValue;
+ }
+
+ /// Get the value of an Boolean scalar.
+ ///
+ /// \warning Assumes getScalarKind() == SK_Boolean
+ bool getBool() {
+ assert(SKind == SK_Boolean);
+ return BoolValue;
+ }
+
+ /// Get the value of an Float scalar.
+ ///
+ /// \warning Assumes getScalarKind() == SK_Float
+ double getFloat() {
+ assert(SKind == SK_Float);
+ return FloatValue;
+ }
+
+ /// Get the value of a String scalar.
+ ///
+ /// \warning Assumes getScalarKind() == SK_String
+ StringRef getString() {
+ assert(SKind == SK_String);
+ return StringValue;
+ }
+
+ /// Get the value of a Binary scalar.
+ ///
+ /// \warning Assumes getScalarKind() == SK_Binary
+ StringRef getBinary() {
+ assert(SKind == SK_Binary);
+ return StringValue;
+ }
+
+ static bool classof(const Node *N) { return N->getKind() == NK_Scalar; }
+
+ void write(Writer &MPWriter) override;
+
+ /// Parse a YAML scalar of the current ScalarKind from \p ScalarStr.
+ ///
+ /// \returns An empty string on success, otherwise an error message.
+ StringRef inputYAML(StringRef ScalarStr);
+
+ /// Output a YAML scalar of the current ScalarKind into \p OS.
+ void outputYAML(raw_ostream &OS) const;
+
+ /// Determine which YAML quoting type the current value would need when
+ /// output.
+ yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const;
+
+ /// Get the YAML tag for the current ScalarKind.
+ StringRef getYAMLTag() const;
+
+ /// Flag which affects how the type handles YAML tags when reading and
+ /// writing.
+ ///
+ /// When false, tags are used when reading and writing. When reading, the tag
+ /// is used to decide the ScalarKind before parsing. When writing, the tag is
+ /// output along with the value.
+ ///
+ /// When true, tags are ignored when reading and writing. When reading, the
+ /// ScalarKind is always assumed to be String. When writing, the tag is not
+ /// output.
+ bool IgnoreTag = false;
+
+ static const char *IntTag;
+ static const char *NilTag;
+ static const char *BooleanTag;
+ static const char *FloatTag;
+ static const char *StringTag;
+ static const char *BinaryTag;
+};
+
+class ArrayNode : public Node, public std::vector<NodePtr> {
+ void anchor() override;
+
+public:
+ ArrayNode() : Node(NK_Array) {}
+ static bool classof(const Node *N) { return N->getKind() == NK_Array; }
+
+ void write(Writer &MPWriter) override {
+ MPWriter.writeArraySize(this->size());
+ for (auto &N : *this)
+ N->write(MPWriter);
+ }
+};
+
+class MapNode : public Node, public StringMap<NodePtr> {
+ void anchor() override;
+
+public:
+ MapNode() : Node(NK_Map) {}
+ static bool classof(const Node *N) { return N->getKind() == NK_Map; }
+
+ void write(Writer &MPWriter) override {
+ MPWriter.writeMapSize(this->size());
+ for (auto &N : *this) {
+ MPWriter.write(N.first());
+ N.second->write(MPWriter);
+ }
+ }
+};
+
+} // end namespace msgpack
+
+namespace yaml {
+
+template <> struct PolymorphicTraits<msgpack::NodePtr> {
+ static NodeKind getKind(const msgpack::NodePtr &N) {
+ if (isa<msgpack::ScalarNode>(*N))
+ return NodeKind::Scalar;
+ if (isa<msgpack::MapNode>(*N))
+ return NodeKind::Map;
+ if (isa<msgpack::ArrayNode>(*N))
+ return NodeKind::Sequence;
+ llvm_unreachable("NodeKind not supported");
+ }
+ static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) {
+ if (!N || !isa<msgpack::ScalarNode>(*N))
+ N.reset(new msgpack::ScalarNode());
+ return *cast<msgpack::ScalarNode>(N.get());
+ }
+ static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) {
+ if (!N || !isa<msgpack::MapNode>(*N))
+ N.reset(new msgpack::MapNode());
+ return *cast<msgpack::MapNode>(N.get());
+ }
+ static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) {
+ if (!N || !isa<msgpack::ArrayNode>(*N))
+ N.reset(new msgpack::ArrayNode());
+ return *cast<msgpack::ArrayNode>(N.get());
+ }
+};
+
+template <> struct TaggedScalarTraits<msgpack::ScalarNode> {
+ static void output(const msgpack::ScalarNode &S, void *Ctxt,
+ raw_ostream &ScalarOS, raw_ostream &TagOS) {
+ if (!S.IgnoreTag)
+ TagOS << S.getYAMLTag();
+ S.outputYAML(ScalarOS);
+ }
+
+ static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt,
+ msgpack::ScalarNode &S) {
+ if (Tag == msgpack::ScalarNode::IntTag) {
+ S.setScalarKind(msgpack::ScalarNode::SK_UInt);
+ if (S.inputYAML(ScalarStr) == StringRef())
+ return StringRef();
+ S.setScalarKind(msgpack::ScalarNode::SK_Int);
+ return S.inputYAML(ScalarStr);
+ }
+
+ if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag ||
+ Tag == "tag:yaml.org,2002:str")
+ S.setScalarKind(msgpack::ScalarNode::SK_String);
+ else if (Tag == msgpack::ScalarNode::NilTag)
+ S.setScalarKind(msgpack::ScalarNode::SK_Nil);
+ else if (Tag == msgpack::ScalarNode::BooleanTag)
+ S.setScalarKind(msgpack::ScalarNode::SK_Boolean);
+ else if (Tag == msgpack::ScalarNode::FloatTag)
+ S.setScalarKind(msgpack::ScalarNode::SK_Float);
+ else if (Tag == msgpack::ScalarNode::StringTag)
+ S.setScalarKind(msgpack::ScalarNode::SK_String);
+ else if (Tag == msgpack::ScalarNode::BinaryTag)
+ S.setScalarKind(msgpack::ScalarNode::SK_Binary);
+ else
+ return "Unsupported messagepack tag";
+
+ return S.inputYAML(ScalarStr);
+ }
+
+ static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) {
+ return S.mustQuoteYAML(Str);
+ }
+};
+
+template <> struct CustomMappingTraits<msgpack::MapNode> {
+ static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) {
+ IO.mapRequired(Key.str().c_str(), M[Key]);
+ }
+ static void output(IO &IO, msgpack::MapNode &M) {
+ for (auto &N : M)
+ IO.mapRequired(N.getKey().str().c_str(), N.getValue());
+ }
+};
+
+template <> struct SequenceTraits<msgpack::ArrayNode> {
+ static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); }
+ static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A,
+ size_t Index) {
+ if (Index >= A.size())
+ A.resize(Index + 1);
+ return A[Index];
+ }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_BINARYFORMAT_MSGPACKTYPES_H
Modified: llvm/trunk/lib/BinaryFormat/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/CMakeLists.txt?rev=346978&r1=346977&r2=346978&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/CMakeLists.txt (original)
+++ llvm/trunk/lib/BinaryFormat/CMakeLists.txt Thu Nov 15 10:50:01 2018
@@ -2,6 +2,7 @@ add_llvm_library(LLVMBinaryFormat
Dwarf.cpp
Magic.cpp
MsgPackReader.cpp
+ MsgPackTypes.cpp
MsgPackWriter.cpp
Wasm.cpp
Added: llvm/trunk/lib/BinaryFormat/MsgPackTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/MsgPackTypes.cpp?rev=346978&view=auto
==============================================================================
--- llvm/trunk/lib/BinaryFormat/MsgPackTypes.cpp (added)
+++ llvm/trunk/lib/BinaryFormat/MsgPackTypes.cpp Thu Nov 15 10:50:01 2018
@@ -0,0 +1,303 @@
+//===- MsgPackTypes.cpp - MsgPack Types -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Implementation of types representing MessagePack "documents".
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackTypes.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace msgpack;
+
+namespace llvm {
+namespace msgpack {
+void ScalarNode::anchor() {}
+void ArrayNode::anchor() {}
+void MapNode::anchor() {}
+}
+}
+
+Expected<OptNodePtr> Node::readArray(Reader &MPReader, size_t Length) {
+ auto A = std::make_shared<ArrayNode>();
+ for (size_t I = 0; I < Length; ++I) {
+ auto OptNodeOrErr = Node::read(MPReader);
+ if (auto Err = OptNodeOrErr.takeError())
+ return std::move(Err);
+ if (!*OptNodeOrErr)
+ return make_error<StringError>(
+ "Insufficient array elements",
+ std::make_error_code(std::errc::invalid_argument));
+ A->push_back(std::move(**OptNodeOrErr));
+ }
+ return OptNodePtr(std::move(A));
+}
+
+Expected<OptNodePtr> Node::readMap(Reader &MPReader, size_t Length) {
+ auto M = std::make_shared<MapNode>();
+ for (size_t I = 0; I < Length; ++I) {
+ auto OptKeyOrErr = Node::read(MPReader);
+ if (auto Err = OptKeyOrErr.takeError())
+ return std::move(Err);
+ if (!*OptKeyOrErr)
+ return make_error<StringError>(
+ "Insufficient map elements",
+ std::make_error_code(std::errc::invalid_argument));
+ auto OptValOrErr = Node::read(MPReader);
+ if (auto Err = OptValOrErr.takeError())
+ return std::move(Err);
+ if (!*OptValOrErr)
+ return make_error<StringError>(
+ "Insufficient map elements",
+ std::make_error_code(std::errc::invalid_argument));
+ auto *Key = dyn_cast<ScalarNode>((*OptKeyOrErr)->get());
+ if (!Key)
+ return make_error<StringError>(
+ "Only string map keys are supported",
+ std::make_error_code(std::errc::invalid_argument));
+ if (Key->getScalarKind() != ScalarNode::SK_String)
+ return make_error<StringError>(
+ "Only string map keys are supported",
+ std::make_error_code(std::errc::invalid_argument));
+ M->try_emplace(Key->getString(), std::move(**OptValOrErr));
+ }
+ return OptNodePtr(std::move(M));
+}
+
+Expected<OptNodePtr> Node::read(Reader &MPReader) {
+ Object Obj;
+
+ auto ContinueOrErr = MPReader.read(Obj);
+ if (auto Err = ContinueOrErr.takeError())
+ return std::move(Err);
+ if (!*ContinueOrErr)
+ return None;
+
+ switch (Obj.Kind) {
+ case Type::Int:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Int));
+ case Type::UInt:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.UInt));
+ case Type::Nil:
+ return OptNodePtr(std::make_shared<ScalarNode>());
+ case Type::Boolean:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Bool));
+ case Type::Float:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Float));
+ case Type::String:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Raw));
+ case Type::Binary:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Raw));
+ case Type::Array:
+ return Node::readArray(MPReader, Obj.Length);
+ case Type::Map:
+ return Node::readMap(MPReader, Obj.Length);
+ case Type::Extension:
+ return make_error<StringError>(
+ "Extension types are not supported",
+ std::make_error_code(std::errc::invalid_argument));
+ }
+ llvm_unreachable("msgpack::Type not handled");
+}
+
+void ScalarNode::destroy() {
+ switch (SKind) {
+ case SK_String:
+ case SK_Binary:
+ StringValue.~basic_string();
+ break;
+ default:
+ // POD types do not require destruction
+ break;
+ }
+}
+
+ScalarNode::ScalarNode(int64_t IntValue)
+ : Node(NK_Scalar), SKind(SK_Int), IntValue(IntValue) {}
+
+ScalarNode::ScalarNode(int32_t IntValue)
+ : ScalarNode(static_cast<int64_t>(IntValue)) {}
+
+ScalarNode::ScalarNode(uint64_t UIntValue)
+ : Node(NK_Scalar), SKind(SK_UInt), UIntValue(UIntValue) {}
+
+ScalarNode::ScalarNode(uint32_t IntValue)
+ : ScalarNode(static_cast<uint64_t>(IntValue)) {}
+
+ScalarNode::ScalarNode() : Node(NK_Scalar), SKind(SK_Nil) {}
+
+ScalarNode::ScalarNode(bool BoolValue)
+ : Node(NK_Scalar), SKind(SK_Boolean), BoolValue(BoolValue) {}
+
+ScalarNode::ScalarNode(double FloatValue)
+ : Node(NK_Scalar), SKind(SK_Float), BoolValue(FloatValue) {}
+
+ScalarNode::ScalarNode(StringRef StringValue)
+ : Node(NK_Scalar), SKind(SK_String) {
+ new (&this->StringValue) std::string(StringValue);
+}
+
+ScalarNode::ScalarNode(const char *StringValue)
+ : ScalarNode(StringRef(StringValue)) {}
+
+ScalarNode::ScalarNode(std::string &&StringValue)
+ : Node(NK_Scalar), SKind(SK_String) {
+ new (&this->StringValue) std::string(StringValue);
+}
+
+ScalarNode::ScalarNode(MemoryBufferRef BinaryValue)
+ : Node(NK_Scalar), SKind(SK_Binary) {
+ new (&StringValue) std::string(BinaryValue.getBuffer());
+}
+
+ScalarNode::~ScalarNode() { destroy(); }
+
+ScalarNode &ScalarNode::operator=(ScalarNode &&RHS) {
+ destroy();
+ switch (SKind = RHS.SKind) {
+ case SK_Int:
+ IntValue = RHS.IntValue;
+ break;
+ case SK_UInt:
+ UIntValue = RHS.UIntValue;
+ break;
+ case SK_Boolean:
+ BoolValue = RHS.BoolValue;
+ break;
+ case SK_Float:
+ FloatValue = RHS.FloatValue;
+ break;
+ case SK_String:
+ case SK_Binary:
+ new (&StringValue) std::string(std::move(RHS.StringValue));
+ break;
+ case SK_Nil:
+ // pass
+ break;
+ }
+ return *this;
+}
+
+StringRef ScalarNode::inputYAML(StringRef ScalarStr) {
+ switch (SKind) {
+ case SK_Int:
+ return yaml::ScalarTraits<int64_t>::input(ScalarStr, nullptr, IntValue);
+ case SK_UInt:
+ return yaml::ScalarTraits<uint64_t>::input(ScalarStr, nullptr, UIntValue);
+ case SK_Nil:
+ return StringRef();
+ case SK_Boolean:
+ return yaml::ScalarTraits<bool>::input(ScalarStr, nullptr, BoolValue);
+ case SK_Float:
+ return yaml::ScalarTraits<double>::input(ScalarStr, nullptr, FloatValue);
+ case SK_Binary:
+ case SK_String:
+ return yaml::ScalarTraits<std::string>::input(ScalarStr, nullptr,
+ StringValue);
+ }
+ llvm_unreachable("unrecognized ScalarKind");
+}
+
+void ScalarNode::outputYAML(raw_ostream &OS) const {
+ switch (SKind) {
+ case SK_Int:
+ yaml::ScalarTraits<int64_t>::output(IntValue, nullptr, OS);
+ break;
+ case SK_UInt:
+ yaml::ScalarTraits<uint64_t>::output(UIntValue, nullptr, OS);
+ break;
+ case SK_Nil:
+ yaml::ScalarTraits<StringRef>::output("", nullptr, OS);
+ break;
+ case SK_Boolean:
+ yaml::ScalarTraits<bool>::output(BoolValue, nullptr, OS);
+ break;
+ case SK_Float:
+ yaml::ScalarTraits<double>::output(FloatValue, nullptr, OS);
+ break;
+ case SK_Binary:
+ case SK_String:
+ yaml::ScalarTraits<std::string>::output(StringValue, nullptr, OS);
+ break;
+ }
+}
+
+yaml::QuotingType ScalarNode::mustQuoteYAML(StringRef ScalarStr) const {
+ switch (SKind) {
+ case SK_Int:
+ return yaml::ScalarTraits<int64_t>::mustQuote(ScalarStr);
+ case SK_UInt:
+ return yaml::ScalarTraits<uint64_t>::mustQuote(ScalarStr);
+ case SK_Nil:
+ return yaml::ScalarTraits<StringRef>::mustQuote(ScalarStr);
+ case SK_Boolean:
+ return yaml::ScalarTraits<bool>::mustQuote(ScalarStr);
+ case SK_Float:
+ return yaml::ScalarTraits<double>::mustQuote(ScalarStr);
+ case SK_Binary:
+ case SK_String:
+ return yaml::ScalarTraits<std::string>::mustQuote(ScalarStr);
+ }
+ llvm_unreachable("unrecognized ScalarKind");
+}
+
+const char *ScalarNode::IntTag = "!int";
+const char *ScalarNode::NilTag = "!nil";
+const char *ScalarNode::BooleanTag = "!bool";
+const char *ScalarNode::FloatTag = "!float";
+const char *ScalarNode::StringTag = "!str";
+const char *ScalarNode::BinaryTag = "!bin";
+
+StringRef ScalarNode::getYAMLTag() const {
+ switch (SKind) {
+ case SK_Int:
+ return IntTag;
+ case SK_UInt:
+ return IntTag;
+ case SK_Nil:
+ return NilTag;
+ case SK_Boolean:
+ return BooleanTag;
+ case SK_Float:
+ return FloatTag;
+ case SK_String:
+ return StringTag;
+ case SK_Binary:
+ return BinaryTag;
+ }
+ llvm_unreachable("unrecognized ScalarKind");
+}
+
+void ScalarNode::write(Writer &MPWriter) {
+ switch (SKind) {
+ case SK_Int:
+ MPWriter.write(IntValue);
+ break;
+ case SK_UInt:
+ MPWriter.write(UIntValue);
+ break;
+ case SK_Nil:
+ MPWriter.writeNil();
+ break;
+ case SK_Boolean:
+ MPWriter.write(BoolValue);
+ break;
+ case SK_Float:
+ MPWriter.write(FloatValue);
+ break;
+ case SK_String:
+ MPWriter.write(StringValue);
+ break;
+ case SK_Binary:
+ MPWriter.write(MemoryBufferRef(StringValue, ""));
+ break;
+ }
+}
Modified: llvm/trunk/unittests/BinaryFormat/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/BinaryFormat/CMakeLists.txt?rev=346978&r1=346977&r2=346978&view=diff
==============================================================================
--- llvm/trunk/unittests/BinaryFormat/CMakeLists.txt (original)
+++ llvm/trunk/unittests/BinaryFormat/CMakeLists.txt Thu Nov 15 10:50:01 2018
@@ -6,6 +6,7 @@ add_llvm_unittest(BinaryFormatTests
DwarfTest.cpp
MachOTest.cpp
MsgPackReaderTest.cpp
+ MsgPackTypesTest.cpp
MsgPackWriterTest.cpp
TestFileMagic.cpp
)
Added: llvm/trunk/unittests/BinaryFormat/MsgPackTypesTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/BinaryFormat/MsgPackTypesTest.cpp?rev=346978&view=auto
==============================================================================
--- llvm/trunk/unittests/BinaryFormat/MsgPackTypesTest.cpp (added)
+++ llvm/trunk/unittests/BinaryFormat/MsgPackTypesTest.cpp Thu Nov 15 10:50:01 2018
@@ -0,0 +1,188 @@
+//===- MsgPackTypesTest.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackTypes.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace msgpack;
+
+TEST(MsgPackTypes, TestReadInt) {
+ Reader MPReader(StringRef("\xd0\x00", 2));
+ auto OptNodeOrErr = Node::read(MPReader);
+ ASSERT_TRUE(static_cast<bool>(OptNodeOrErr));
+ ASSERT_TRUE(*OptNodeOrErr);
+ auto *S = dyn_cast<ScalarNode>((*OptNodeOrErr)->get());
+ ASSERT_TRUE(S);
+ ASSERT_EQ(S->getScalarKind(), ScalarNode::SK_Int);
+ ASSERT_EQ(S->getInt(), 0);
+}
+
+TEST(MsgPackTypes, TestReadArray) {
+ Reader MPReader(StringRef("\x92\xd0\x01\xc0"));
+ auto OptNodeOrErr = Node::read(MPReader);
+ ASSERT_TRUE(static_cast<bool>(OptNodeOrErr));
+ ASSERT_TRUE(*OptNodeOrErr);
+ auto *A = dyn_cast<ArrayNode>((*OptNodeOrErr)->get());
+ ASSERT_TRUE(A);
+ ASSERT_EQ(A->size(), 2u);
+ auto *SI = dyn_cast<ScalarNode>((*A)[0].get());
+ ASSERT_TRUE(SI);
+ ASSERT_EQ(SI->getScalarKind(), ScalarNode::SK_Int);
+ ASSERT_EQ(SI->getInt(), 1);
+ auto *SN = dyn_cast<ScalarNode>((*A)[1].get());
+ ASSERT_TRUE(SN);
+ ASSERT_EQ(SN->getScalarKind(), ScalarNode::SK_Nil);
+}
+
+TEST(MsgPackTypes, TestReadMap) {
+ Reader MPReader(StringRef("\x82\xa3"
+ "foo"
+ "\xd0\x01\xa3"
+ "bar"
+ "\xd0\x02"));
+ auto OptNodeOrErr = Node::read(MPReader);
+ ASSERT_TRUE(static_cast<bool>(OptNodeOrErr));
+ ASSERT_TRUE(*OptNodeOrErr);
+ auto *A = dyn_cast<MapNode>((*OptNodeOrErr)->get());
+ ASSERT_TRUE(A);
+ ASSERT_EQ(A->size(), 2u);
+ auto *FooS = dyn_cast<ScalarNode>((*A)["foo"].get());
+ ASSERT_TRUE(FooS);
+ ASSERT_EQ(FooS->getScalarKind(), ScalarNode::SK_Int);
+ ASSERT_EQ(FooS->getInt(), 1);
+ auto *BarS = dyn_cast<ScalarNode>((*A)["bar"].get());
+ ASSERT_TRUE(BarS);
+ ASSERT_EQ(BarS->getScalarKind(), ScalarNode::SK_Int);
+ ASSERT_EQ(BarS->getInt(), 2);
+}
+
+TEST(MsgPackTypes, TestWriteInt) {
+ std::string Buffer;
+ raw_string_ostream OStream(Buffer);
+ Writer MPWriter(OStream);
+ ScalarNode I(int64_t(1));
+ I.write(MPWriter);
+ ASSERT_EQ(OStream.str(), "\x01");
+}
+
+TEST(MsgPackTypes, TestWriteArray) {
+ std::string Buffer;
+ raw_string_ostream OStream(Buffer);
+ Writer MPWriter(OStream);
+ ArrayNode A;
+ A.push_back(std::make_shared<ScalarNode>(int64_t(1)));
+ A.push_back(std::make_shared<ScalarNode>());
+ A.write(MPWriter);
+ ASSERT_EQ(OStream.str(), "\x92\x01\xc0");
+}
+
+TEST(MsgPackTypes, TestWriteMap) {
+ std::string Buffer;
+ raw_string_ostream OStream(Buffer);
+ Writer MPWriter(OStream);
+ MapNode M;
+ M["foo"] = std::make_shared<ScalarNode>(int64_t(1));
+ M["bar"] = std::make_shared<ScalarNode>(int64_t(2));
+ M.write(MPWriter);
+ ASSERT_EQ(OStream.str(), "\x82\xa3"
+ "foo"
+ "\x01\xa3"
+ "bar"
+ "\x02");
+}
+
+TEST(MsgPackTypes, TestOutputYAMLArray) {
+ std::string Buffer;
+ raw_string_ostream OStream(Buffer);
+ yaml::Output yout(OStream);
+ ArrayNode A;
+ A.push_back(std::make_shared<ScalarNode>(int64_t(1)));
+ A.push_back(std::make_shared<ScalarNode>(int64_t(2)));
+ yout << A;
+ ASSERT_EQ(OStream.str(), "---\n- !int 1\n- !int 2\n...\n");
+}
+
+TEST(MsgPackTypes, TestInputYAMLArray) {
+ NodePtr RootNode;
+ yaml::Input yin("---\n- !int 1\n- !str 2\n...\n");
+ yin >> RootNode;
+ auto *A = dyn_cast<ArrayNode>(RootNode.get());
+ ASSERT_TRUE(A);
+ ASSERT_EQ(A->size(), 2u);
+ auto *SI = dyn_cast<ScalarNode>((*A)[0].get());
+ ASSERT_TRUE(SI);
+ ASSERT_EQ(SI->getScalarKind(), ScalarNode::SK_UInt);
+ ASSERT_EQ(SI->getUInt(), 1u);
+ auto *SS = dyn_cast<ScalarNode>((*A)[1].get());
+ ASSERT_TRUE(SS);
+ ASSERT_EQ(SS->getScalarKind(), ScalarNode::SK_String);
+ ASSERT_EQ(SS->getString(), "2");
+}
+
+TEST(MsgPackTypes, TestOutputYAMLMap) {
+ std::string Buffer;
+ raw_string_ostream OStream(Buffer);
+ yaml::Output yout(OStream);
+ MapNode M;
+ M["foo"] = std::make_shared<ScalarNode>(int64_t(1));
+ M["bar"] = std::make_shared<ScalarNode>(uint64_t(2));
+ auto N = std::make_shared<MapNode>();
+ (*N)["baz"] = std::make_shared<ScalarNode>(true);
+ M["qux"] = std::move(N);
+ yout << M;
+ ASSERT_EQ(OStream.str(), "---\nfoo: !int 1\nbar: "
+ "!int 2\nqux: \n baz: "
+ "!bool true\n...\n");
+}
+
+TEST(MsgPackTypes, TestInputYAMLMap) {
+ NodePtr RootNode;
+ yaml::Input yin("---\nfoo: !int 1\nbaz: !str 2\n...\n");
+ yin >> RootNode;
+ auto *M = dyn_cast<MapNode>(RootNode.get());
+ ASSERT_TRUE(M);
+ ASSERT_EQ(M->size(), 2u);
+ auto *SI = dyn_cast<ScalarNode>((*M)["foo"].get());
+ ASSERT_TRUE(SI);
+ ASSERT_EQ(SI->getScalarKind(), ScalarNode::SK_UInt);
+ ASSERT_EQ(SI->getUInt(), 1u);
+ auto *SS = dyn_cast<ScalarNode>((*M)["baz"].get());
+ ASSERT_TRUE(SS);
+ ASSERT_EQ(SS->getScalarKind(), ScalarNode::SK_String);
+ ASSERT_EQ(SS->getString(), "2");
+}
+
+// Test that the document is parsed into a tree of shared_ptr where each node
+// can have multiple owners.
+TEST(MsgPackTypes, TestInputShared) {
+ yaml::Input yin("---\nfoo:\n bar: !int 1\n...\n");
+ NodePtr InnerMap;
+ NodePtr IntNode;
+ {
+ {
+ {
+ NodePtr RootNode;
+ yin >> RootNode;
+ auto *M = dyn_cast<MapNode>(RootNode.get());
+ ASSERT_TRUE(M);
+ ASSERT_EQ(M->size(), 1u);
+ InnerMap = (*M)["foo"];
+ }
+ auto *N = dyn_cast<MapNode>(InnerMap.get());
+ ASSERT_TRUE(N);
+ ASSERT_EQ(N->size(), 1u);
+ IntNode = (*N)["bar"];
+ }
+ auto *S = dyn_cast<ScalarNode>(IntNode.get());
+ ASSERT_TRUE(S);
+ ASSERT_EQ(S->getScalarKind(), ScalarNode::SK_UInt);
+ ASSERT_EQ(S->getUInt(), 1u);
+ }
+}
More information about the llvm-commits
mailing list