304 lines
8.6 KiB
C++
304 lines
8.6 KiB
C++
//===- 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;
|
|
}
|
|
}
|