//===- 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" #include 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(i)); return; } if (i >= FixMin::NegativeInt) { EW.write(static_cast(i)); return; } if (i >= INT8_MIN) { EW.write(FirstByte::Int8); EW.write(static_cast(i)); return; } if (i >= INT16_MIN) { EW.write(FirstByte::Int16); EW.write(static_cast(i)); return; } if (i >= INT32_MIN) { EW.write(FirstByte::Int32); EW.write(static_cast(i)); return; } EW.write(FirstByte::Int64); EW.write(i); } void Writer::write(uint64_t u) { if (u <= FixMax::PositiveInt) { EW.write(static_cast(u)); return; } if (u <= UINT8_MAX) { EW.write(FirstByte::UInt8); EW.write(static_cast(u)); return; } if (u <= UINT16_MAX) { EW.write(FirstByte::UInt16); EW.write(static_cast(u)); return; } if (u <= UINT32_MAX) { EW.write(FirstByte::UInt32); EW.write(static_cast(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::min() && a <= std::numeric_limits::max()) { EW.write(FirstByte::Float32); EW.write(static_cast(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(FixBits::String | Size)); else if (!Compatible && Size <= UINT8_MAX) { EW.write(FirstByte::Str8); EW.write(static_cast(Size)); } else if (Size <= UINT16_MAX) { EW.write(FirstByte::Str16); EW.write(static_cast(Size)); } else { assert(Size <= UINT32_MAX && "String object too long to be encoded"); EW.write(FirstByte::Str32); EW.write(static_cast(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(Size)); } else if (Size <= UINT16_MAX) { EW.write(FirstByte::Bin16); EW.write(static_cast(Size)); } else { assert(Size <= UINT32_MAX && "Binary object too long to be encoded"); EW.write(FirstByte::Bin32); EW.write(static_cast(Size)); } EW.OS.write(Buffer.getBufferStart(), Size); } void Writer::writeArraySize(uint32_t Size) { if (Size <= FixMax::Array) { EW.write(static_cast(FixBits::Array | Size)); return; } if (Size <= UINT16_MAX) { EW.write(FirstByte::Array16); EW.write(static_cast(Size)); return; } EW.write(FirstByte::Array32); EW.write(Size); } void Writer::writeMapSize(uint32_t Size) { if (Size <= FixMax::Map) { EW.write(static_cast(FixBits::Map | Size)); return; } if (Size <= UINT16_MAX) { EW.write(FirstByte::Map16); EW.write(static_cast(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(Size)); } else if (Size <= UINT16_MAX) { EW.write(FirstByte::Ext16); EW.write(static_cast(Size)); } else { assert(Size <= UINT32_MAX && "Ext size too large to be encoded"); EW.write(FirstByte::Ext32); EW.write(static_cast(Size)); } } EW.write(Type); EW.OS.write(Buffer.getBufferStart(), Size); }