//===- 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 Node::readArray(Reader &MPReader, size_t Length) { auto A = std::make_shared(); 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( "Insufficient array elements", std::make_error_code(std::errc::invalid_argument)); A->push_back(std::move(**OptNodeOrErr)); } return OptNodePtr(std::move(A)); } Expected Node::readMap(Reader &MPReader, size_t Length) { auto M = std::make_shared(); 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( "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( "Insufficient map elements", std::make_error_code(std::errc::invalid_argument)); auto *Key = dyn_cast((*OptKeyOrErr)->get()); if (!Key) return make_error( "Only string map keys are supported", std::make_error_code(std::errc::invalid_argument)); if (Key->getScalarKind() != ScalarNode::SK_String) return make_error( "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 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(Obj.Int)); case Type::UInt: return OptNodePtr(std::make_shared(Obj.UInt)); case Type::Nil: return OptNodePtr(std::make_shared()); case Type::Boolean: return OptNodePtr(std::make_shared(Obj.Bool)); case Type::Float: return OptNodePtr(std::make_shared(Obj.Float)); case Type::String: return OptNodePtr(std::make_shared(Obj.Raw)); case Type::Binary: return OptNodePtr(std::make_shared(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( "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(IntValue)) {} ScalarNode::ScalarNode(uint64_t UIntValue) : Node(NK_Scalar), SKind(SK_UInt), UIntValue(UIntValue) {} ScalarNode::ScalarNode(uint32_t IntValue) : ScalarNode(static_cast(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::input(ScalarStr, nullptr, IntValue); case SK_UInt: return yaml::ScalarTraits::input(ScalarStr, nullptr, UIntValue); case SK_Nil: return StringRef(); case SK_Boolean: return yaml::ScalarTraits::input(ScalarStr, nullptr, BoolValue); case SK_Float: return yaml::ScalarTraits::input(ScalarStr, nullptr, FloatValue); case SK_Binary: case SK_String: return yaml::ScalarTraits::input(ScalarStr, nullptr, StringValue); } llvm_unreachable("unrecognized ScalarKind"); } void ScalarNode::outputYAML(raw_ostream &OS) const { switch (SKind) { case SK_Int: yaml::ScalarTraits::output(IntValue, nullptr, OS); break; case SK_UInt: yaml::ScalarTraits::output(UIntValue, nullptr, OS); break; case SK_Nil: yaml::ScalarTraits::output("", nullptr, OS); break; case SK_Boolean: yaml::ScalarTraits::output(BoolValue, nullptr, OS); break; case SK_Float: yaml::ScalarTraits::output(FloatValue, nullptr, OS); break; case SK_Binary: case SK_String: yaml::ScalarTraits::output(StringValue, nullptr, OS); break; } } yaml::QuotingType ScalarNode::mustQuoteYAML(StringRef ScalarStr) const { switch (SKind) { case SK_Int: return yaml::ScalarTraits::mustQuote(ScalarStr); case SK_UInt: return yaml::ScalarTraits::mustQuote(ScalarStr); case SK_Nil: return yaml::ScalarTraits::mustQuote(ScalarStr); case SK_Boolean: return yaml::ScalarTraits::mustQuote(ScalarStr); case SK_Float: return yaml::ScalarTraits::mustQuote(ScalarStr); case SK_Binary: case SK_String: return yaml::ScalarTraits::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; } }