|  | //===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | ///  \file | 
|  | ///  This file implements a MessagePack writer. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/BinaryFormat/MsgPackWriter.h" | 
|  | #include "llvm/BinaryFormat/MsgPack.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace msgpack; | 
|  |  | 
|  | Writer::Writer(raw_ostream &OS, bool Compatible) | 
|  | : EW(OS, Endianness), Compatible(Compatible) {} | 
|  |  | 
|  | void Writer::writeNil() { EW.write(FirstByte::Nil); } | 
|  |  | 
|  | void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); } | 
|  |  | 
|  | void Writer::write(int64_t i) { | 
|  | if (i >= 0) { | 
|  | write(static_cast<uint64_t>(i)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (i >= FixMin::NegativeInt) { | 
|  | EW.write(static_cast<int8_t>(i)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (i >= INT8_MIN) { | 
|  | EW.write(FirstByte::Int8); | 
|  | EW.write(static_cast<int8_t>(i)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (i >= INT16_MIN) { | 
|  | EW.write(FirstByte::Int16); | 
|  | EW.write(static_cast<int16_t>(i)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (i >= INT32_MIN) { | 
|  | EW.write(FirstByte::Int32); | 
|  | EW.write(static_cast<int32_t>(i)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | EW.write(FirstByte::Int64); | 
|  | EW.write(i); | 
|  | } | 
|  |  | 
|  | void Writer::write(uint64_t u) { | 
|  | if (u <= FixMax::PositiveInt) { | 
|  | EW.write(static_cast<uint8_t>(u)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (u <= UINT8_MAX) { | 
|  | EW.write(FirstByte::UInt8); | 
|  | EW.write(static_cast<uint8_t>(u)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (u <= UINT16_MAX) { | 
|  | EW.write(FirstByte::UInt16); | 
|  | EW.write(static_cast<uint16_t>(u)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (u <= UINT32_MAX) { | 
|  | EW.write(FirstByte::UInt32); | 
|  | EW.write(static_cast<uint32_t>(u)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | EW.write(FirstByte::UInt64); | 
|  | EW.write(u); | 
|  | } | 
|  |  | 
|  | void Writer::write(double d) { | 
|  | // If no loss of precision, encode as a Float32. | 
|  | double a = std::fabs(d); | 
|  | if (a >= std::numeric_limits<float>::min() && | 
|  | a <= std::numeric_limits<float>::max()) { | 
|  | EW.write(FirstByte::Float32); | 
|  | EW.write(static_cast<float>(d)); | 
|  | } else { | 
|  | EW.write(FirstByte::Float64); | 
|  | EW.write(d); | 
|  | } | 
|  | } | 
|  |  | 
|  | void Writer::write(StringRef s) { | 
|  | size_t Size = s.size(); | 
|  |  | 
|  | if (Size <= FixMax::String) | 
|  | EW.write(static_cast<uint8_t>(FixBits::String | Size)); | 
|  | else if (!Compatible && Size <= UINT8_MAX) { | 
|  | EW.write(FirstByte::Str8); | 
|  | EW.write(static_cast<uint8_t>(Size)); | 
|  | } else if (Size <= UINT16_MAX) { | 
|  | EW.write(FirstByte::Str16); | 
|  | EW.write(static_cast<uint16_t>(Size)); | 
|  | } else { | 
|  | assert(Size <= UINT32_MAX && "String object too long to be encoded"); | 
|  | EW.write(FirstByte::Str32); | 
|  | EW.write(static_cast<uint32_t>(Size)); | 
|  | } | 
|  |  | 
|  | EW.OS << s; | 
|  | } | 
|  |  | 
|  | void Writer::write(MemoryBufferRef Buffer) { | 
|  | assert(!Compatible && "Attempt to write Bin format in compatible mode"); | 
|  |  | 
|  | size_t Size = Buffer.getBufferSize(); | 
|  |  | 
|  | if (Size <= UINT8_MAX) { | 
|  | EW.write(FirstByte::Bin8); | 
|  | EW.write(static_cast<uint8_t>(Size)); | 
|  | } else if (Size <= UINT16_MAX) { | 
|  | EW.write(FirstByte::Bin16); | 
|  | EW.write(static_cast<uint16_t>(Size)); | 
|  | } else { | 
|  | assert(Size <= UINT32_MAX && "Binary object too long to be encoded"); | 
|  | EW.write(FirstByte::Bin32); | 
|  | EW.write(static_cast<uint32_t>(Size)); | 
|  | } | 
|  |  | 
|  | EW.OS.write(Buffer.getBufferStart(), Size); | 
|  | } | 
|  |  | 
|  | void Writer::writeArraySize(uint32_t Size) { | 
|  | if (Size <= FixMax::Array) { | 
|  | EW.write(static_cast<uint8_t>(FixBits::Array | Size)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (Size <= UINT16_MAX) { | 
|  | EW.write(FirstByte::Array16); | 
|  | EW.write(static_cast<uint16_t>(Size)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | EW.write(FirstByte::Array32); | 
|  | EW.write(Size); | 
|  | } | 
|  |  | 
|  | void Writer::writeMapSize(uint32_t Size) { | 
|  | if (Size <= FixMax::Map) { | 
|  | EW.write(static_cast<uint8_t>(FixBits::Map | Size)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (Size <= UINT16_MAX) { | 
|  | EW.write(FirstByte::Map16); | 
|  | EW.write(static_cast<uint16_t>(Size)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | EW.write(FirstByte::Map32); | 
|  | EW.write(Size); | 
|  | } | 
|  |  | 
|  | void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) { | 
|  | size_t Size = Buffer.getBufferSize(); | 
|  |  | 
|  | switch (Size) { | 
|  | case FixLen::Ext1: | 
|  | EW.write(FirstByte::FixExt1); | 
|  | break; | 
|  | case FixLen::Ext2: | 
|  | EW.write(FirstByte::FixExt2); | 
|  | break; | 
|  | case FixLen::Ext4: | 
|  | EW.write(FirstByte::FixExt4); | 
|  | break; | 
|  | case FixLen::Ext8: | 
|  | EW.write(FirstByte::FixExt8); | 
|  | break; | 
|  | case FixLen::Ext16: | 
|  | EW.write(FirstByte::FixExt16); | 
|  | break; | 
|  | default: | 
|  | if (Size <= UINT8_MAX) { | 
|  | EW.write(FirstByte::Ext8); | 
|  | EW.write(static_cast<uint8_t>(Size)); | 
|  | } else if (Size <= UINT16_MAX) { | 
|  | EW.write(FirstByte::Ext16); | 
|  | EW.write(static_cast<uint16_t>(Size)); | 
|  | } else { | 
|  | assert(Size <= UINT32_MAX && "Ext size too large to be encoded"); | 
|  | EW.write(FirstByte::Ext32); | 
|  | EW.write(static_cast<uint32_t>(Size)); | 
|  | } | 
|  | } | 
|  |  | 
|  | EW.write(Type); | 
|  | EW.OS.write(Buffer.getBufferStart(), Size); | 
|  | } |