1343171Sdim//===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===// 2343171Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6343171Sdim// 7343171Sdim//===----------------------------------------------------------------------===// 8343171Sdim/// 9343171Sdim/// \file 10343171Sdim/// This file implements a MessagePack writer. 11343171Sdim/// 12343171Sdim//===----------------------------------------------------------------------===// 13343171Sdim 14343171Sdim#include "llvm/BinaryFormat/MsgPackWriter.h" 15343171Sdim#include "llvm/BinaryFormat/MsgPack.h" 16343171Sdim 17343171Sdimusing namespace llvm; 18343171Sdimusing namespace msgpack; 19343171Sdim 20343171SdimWriter::Writer(raw_ostream &OS, bool Compatible) 21343171Sdim : EW(OS, Endianness), Compatible(Compatible) {} 22343171Sdim 23343171Sdimvoid Writer::writeNil() { EW.write(FirstByte::Nil); } 24343171Sdim 25343171Sdimvoid Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); } 26343171Sdim 27343171Sdimvoid Writer::write(int64_t i) { 28343171Sdim if (i >= 0) { 29343171Sdim write(static_cast<uint64_t>(i)); 30343171Sdim return; 31343171Sdim } 32343171Sdim 33343171Sdim if (i >= FixMin::NegativeInt) { 34343171Sdim EW.write(static_cast<int8_t>(i)); 35343171Sdim return; 36343171Sdim } 37343171Sdim 38343171Sdim if (i >= INT8_MIN) { 39343171Sdim EW.write(FirstByte::Int8); 40343171Sdim EW.write(static_cast<int8_t>(i)); 41343171Sdim return; 42343171Sdim } 43343171Sdim 44343171Sdim if (i >= INT16_MIN) { 45343171Sdim EW.write(FirstByte::Int16); 46343171Sdim EW.write(static_cast<int16_t>(i)); 47343171Sdim return; 48343171Sdim } 49343171Sdim 50343171Sdim if (i >= INT32_MIN) { 51343171Sdim EW.write(FirstByte::Int32); 52343171Sdim EW.write(static_cast<int32_t>(i)); 53343171Sdim return; 54343171Sdim } 55343171Sdim 56343171Sdim EW.write(FirstByte::Int64); 57343171Sdim EW.write(i); 58343171Sdim} 59343171Sdim 60343171Sdimvoid Writer::write(uint64_t u) { 61343171Sdim if (u <= FixMax::PositiveInt) { 62343171Sdim EW.write(static_cast<uint8_t>(u)); 63343171Sdim return; 64343171Sdim } 65343171Sdim 66343171Sdim if (u <= UINT8_MAX) { 67343171Sdim EW.write(FirstByte::UInt8); 68343171Sdim EW.write(static_cast<uint8_t>(u)); 69343171Sdim return; 70343171Sdim } 71343171Sdim 72343171Sdim if (u <= UINT16_MAX) { 73343171Sdim EW.write(FirstByte::UInt16); 74343171Sdim EW.write(static_cast<uint16_t>(u)); 75343171Sdim return; 76343171Sdim } 77343171Sdim 78343171Sdim if (u <= UINT32_MAX) { 79343171Sdim EW.write(FirstByte::UInt32); 80343171Sdim EW.write(static_cast<uint32_t>(u)); 81343171Sdim return; 82343171Sdim } 83343171Sdim 84343171Sdim EW.write(FirstByte::UInt64); 85343171Sdim EW.write(u); 86343171Sdim} 87343171Sdim 88343171Sdimvoid Writer::write(double d) { 89343171Sdim // If no loss of precision, encode as a Float32. 90343171Sdim double a = std::fabs(d); 91343171Sdim if (a >= std::numeric_limits<float>::min() && 92343171Sdim a <= std::numeric_limits<float>::max()) { 93343171Sdim EW.write(FirstByte::Float32); 94343171Sdim EW.write(static_cast<float>(d)); 95343171Sdim } else { 96343171Sdim EW.write(FirstByte::Float64); 97343171Sdim EW.write(d); 98343171Sdim } 99343171Sdim} 100343171Sdim 101343171Sdimvoid Writer::write(StringRef s) { 102343171Sdim size_t Size = s.size(); 103343171Sdim 104343171Sdim if (Size <= FixMax::String) 105343171Sdim EW.write(static_cast<uint8_t>(FixBits::String | Size)); 106343171Sdim else if (!Compatible && Size <= UINT8_MAX) { 107343171Sdim EW.write(FirstByte::Str8); 108343171Sdim EW.write(static_cast<uint8_t>(Size)); 109343171Sdim } else if (Size <= UINT16_MAX) { 110343171Sdim EW.write(FirstByte::Str16); 111343171Sdim EW.write(static_cast<uint16_t>(Size)); 112343171Sdim } else { 113343171Sdim assert(Size <= UINT32_MAX && "String object too long to be encoded"); 114343171Sdim EW.write(FirstByte::Str32); 115343171Sdim EW.write(static_cast<uint32_t>(Size)); 116343171Sdim } 117343171Sdim 118343171Sdim EW.OS << s; 119343171Sdim} 120343171Sdim 121343171Sdimvoid Writer::write(MemoryBufferRef Buffer) { 122343171Sdim assert(!Compatible && "Attempt to write Bin format in compatible mode"); 123343171Sdim 124343171Sdim size_t Size = Buffer.getBufferSize(); 125343171Sdim 126343171Sdim if (Size <= UINT8_MAX) { 127343171Sdim EW.write(FirstByte::Bin8); 128343171Sdim EW.write(static_cast<uint8_t>(Size)); 129343171Sdim } else if (Size <= UINT16_MAX) { 130343171Sdim EW.write(FirstByte::Bin16); 131343171Sdim EW.write(static_cast<uint16_t>(Size)); 132343171Sdim } else { 133343171Sdim assert(Size <= UINT32_MAX && "Binary object too long to be encoded"); 134343171Sdim EW.write(FirstByte::Bin32); 135343171Sdim EW.write(static_cast<uint32_t>(Size)); 136343171Sdim } 137343171Sdim 138343171Sdim EW.OS.write(Buffer.getBufferStart(), Size); 139343171Sdim} 140343171Sdim 141343171Sdimvoid Writer::writeArraySize(uint32_t Size) { 142343171Sdim if (Size <= FixMax::Array) { 143343171Sdim EW.write(static_cast<uint8_t>(FixBits::Array | Size)); 144343171Sdim return; 145343171Sdim } 146343171Sdim 147343171Sdim if (Size <= UINT16_MAX) { 148343171Sdim EW.write(FirstByte::Array16); 149343171Sdim EW.write(static_cast<uint16_t>(Size)); 150343171Sdim return; 151343171Sdim } 152343171Sdim 153343171Sdim EW.write(FirstByte::Array32); 154343171Sdim EW.write(Size); 155343171Sdim} 156343171Sdim 157343171Sdimvoid Writer::writeMapSize(uint32_t Size) { 158343171Sdim if (Size <= FixMax::Map) { 159343171Sdim EW.write(static_cast<uint8_t>(FixBits::Map | Size)); 160343171Sdim return; 161343171Sdim } 162343171Sdim 163343171Sdim if (Size <= UINT16_MAX) { 164343171Sdim EW.write(FirstByte::Map16); 165343171Sdim EW.write(static_cast<uint16_t>(Size)); 166343171Sdim return; 167343171Sdim } 168343171Sdim 169343171Sdim EW.write(FirstByte::Map32); 170343171Sdim EW.write(Size); 171343171Sdim} 172343171Sdim 173343171Sdimvoid Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) { 174343171Sdim size_t Size = Buffer.getBufferSize(); 175343171Sdim 176343171Sdim switch (Size) { 177343171Sdim case FixLen::Ext1: 178343171Sdim EW.write(FirstByte::FixExt1); 179343171Sdim break; 180343171Sdim case FixLen::Ext2: 181343171Sdim EW.write(FirstByte::FixExt2); 182343171Sdim break; 183343171Sdim case FixLen::Ext4: 184343171Sdim EW.write(FirstByte::FixExt4); 185343171Sdim break; 186343171Sdim case FixLen::Ext8: 187343171Sdim EW.write(FirstByte::FixExt8); 188343171Sdim break; 189343171Sdim case FixLen::Ext16: 190343171Sdim EW.write(FirstByte::FixExt16); 191343171Sdim break; 192343171Sdim default: 193343171Sdim if (Size <= UINT8_MAX) { 194343171Sdim EW.write(FirstByte::Ext8); 195343171Sdim EW.write(static_cast<uint8_t>(Size)); 196343171Sdim } else if (Size <= UINT16_MAX) { 197343171Sdim EW.write(FirstByte::Ext16); 198343171Sdim EW.write(static_cast<uint16_t>(Size)); 199343171Sdim } else { 200343171Sdim assert(Size <= UINT32_MAX && "Ext size too large to be encoded"); 201343171Sdim EW.write(FirstByte::Ext32); 202343171Sdim EW.write(static_cast<uint32_t>(Size)); 203343171Sdim } 204343171Sdim } 205343171Sdim 206343171Sdim EW.write(Type); 207343171Sdim EW.OS.write(Buffer.getBufferStart(), Size); 208343171Sdim} 209