diff options
author | Scott Linder <scott@scottlinder.com> | 2018-11-15 18:50:01 +0000 |
---|---|---|
committer | Scott Linder <scott@scottlinder.com> | 2018-11-15 18:50:01 +0000 |
commit | 919fbbbcca6a6c137b2319aecf70cfb0f48136a0 (patch) | |
tree | 60ddbab178d0fbdb895335d91ac13ec8ecabff5b /llvm/lib | |
parent | 6cda87463fbb32c310d43e840684133a210963dd (diff) | |
download | bcm5719-llvm-919fbbbcca6a6c137b2319aecf70cfb0f48136a0.tar.gz bcm5719-llvm-919fbbbcca6a6c137b2319aecf70cfb0f48136a0.zip |
[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
llvm-svn: 346978
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/BinaryFormat/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/BinaryFormat/MsgPackTypes.cpp | 303 |
2 files changed, 304 insertions, 0 deletions
diff --git a/llvm/lib/BinaryFormat/CMakeLists.txt b/llvm/lib/BinaryFormat/CMakeLists.txt index 93bb8b07763..94d08ee3a15 100644 --- a/llvm/lib/BinaryFormat/CMakeLists.txt +++ b/llvm/lib/BinaryFormat/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_library(LLVMBinaryFormat Dwarf.cpp Magic.cpp MsgPackReader.cpp + MsgPackTypes.cpp MsgPackWriter.cpp Wasm.cpp diff --git a/llvm/lib/BinaryFormat/MsgPackTypes.cpp b/llvm/lib/BinaryFormat/MsgPackTypes.cpp new file mode 100644 index 00000000000..4a8f70b10fb --- /dev/null +++ b/llvm/lib/BinaryFormat/MsgPackTypes.cpp @@ -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; + } +} |