211 lines · cpp
1//===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements a MessagePack writer.11///12//===----------------------------------------------------------------------===//13 14#include "llvm/BinaryFormat/MsgPackWriter.h"15#include "llvm/BinaryFormat/MsgPack.h"16 17#include <cmath>18 19using namespace llvm;20using namespace msgpack;21 22Writer::Writer(raw_ostream &OS, bool Compatible)23 : EW(OS, Endianness), Compatible(Compatible) {}24 25void Writer::writeNil() { EW.write(FirstByte::Nil); }26 27void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }28 29void Writer::write(int64_t i) {30 if (i >= 0) {31 write(static_cast<uint64_t>(i));32 return;33 }34 35 if (i >= FixMin::NegativeInt) {36 EW.write(static_cast<int8_t>(i));37 return;38 }39 40 if (i >= INT8_MIN) {41 EW.write(FirstByte::Int8);42 EW.write(static_cast<int8_t>(i));43 return;44 }45 46 if (i >= INT16_MIN) {47 EW.write(FirstByte::Int16);48 EW.write(static_cast<int16_t>(i));49 return;50 }51 52 if (i >= INT32_MIN) {53 EW.write(FirstByte::Int32);54 EW.write(static_cast<int32_t>(i));55 return;56 }57 58 EW.write(FirstByte::Int64);59 EW.write(i);60}61 62void Writer::write(uint64_t u) {63 if (u <= FixMax::PositiveInt) {64 EW.write(static_cast<uint8_t>(u));65 return;66 }67 68 if (u <= UINT8_MAX) {69 EW.write(FirstByte::UInt8);70 EW.write(static_cast<uint8_t>(u));71 return;72 }73 74 if (u <= UINT16_MAX) {75 EW.write(FirstByte::UInt16);76 EW.write(static_cast<uint16_t>(u));77 return;78 }79 80 if (u <= UINT32_MAX) {81 EW.write(FirstByte::UInt32);82 EW.write(static_cast<uint32_t>(u));83 return;84 }85 86 EW.write(FirstByte::UInt64);87 EW.write(u);88}89 90void Writer::write(double d) {91 // If no loss of precision, encode as a Float32.92 double a = std::fabs(d);93 if (a >= std::numeric_limits<float>::min() &&94 a <= std::numeric_limits<float>::max()) {95 EW.write(FirstByte::Float32);96 EW.write(static_cast<float>(d));97 } else {98 EW.write(FirstByte::Float64);99 EW.write(d);100 }101}102 103void Writer::write(StringRef s) {104 size_t Size = s.size();105 106 if (Size <= FixMax::String)107 EW.write(static_cast<uint8_t>(FixBits::String | Size));108 else if (!Compatible && Size <= UINT8_MAX) {109 EW.write(FirstByte::Str8);110 EW.write(static_cast<uint8_t>(Size));111 } else if (Size <= UINT16_MAX) {112 EW.write(FirstByte::Str16);113 EW.write(static_cast<uint16_t>(Size));114 } else {115 assert(Size <= UINT32_MAX && "String object too long to be encoded");116 EW.write(FirstByte::Str32);117 EW.write(static_cast<uint32_t>(Size));118 }119 120 EW.OS << s;121}122 123void Writer::write(MemoryBufferRef Buffer) {124 assert(!Compatible && "Attempt to write Bin format in compatible mode");125 126 size_t Size = Buffer.getBufferSize();127 128 if (Size <= UINT8_MAX) {129 EW.write(FirstByte::Bin8);130 EW.write(static_cast<uint8_t>(Size));131 } else if (Size <= UINT16_MAX) {132 EW.write(FirstByte::Bin16);133 EW.write(static_cast<uint16_t>(Size));134 } else {135 assert(Size <= UINT32_MAX && "Binary object too long to be encoded");136 EW.write(FirstByte::Bin32);137 EW.write(static_cast<uint32_t>(Size));138 }139 140 EW.OS.write(Buffer.getBufferStart(), Size);141}142 143void Writer::writeArraySize(uint32_t Size) {144 if (Size <= FixMax::Array) {145 EW.write(static_cast<uint8_t>(FixBits::Array | Size));146 return;147 }148 149 if (Size <= UINT16_MAX) {150 EW.write(FirstByte::Array16);151 EW.write(static_cast<uint16_t>(Size));152 return;153 }154 155 EW.write(FirstByte::Array32);156 EW.write(Size);157}158 159void Writer::writeMapSize(uint32_t Size) {160 if (Size <= FixMax::Map) {161 EW.write(static_cast<uint8_t>(FixBits::Map | Size));162 return;163 }164 165 if (Size <= UINT16_MAX) {166 EW.write(FirstByte::Map16);167 EW.write(static_cast<uint16_t>(Size));168 return;169 }170 171 EW.write(FirstByte::Map32);172 EW.write(Size);173}174 175void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {176 size_t Size = Buffer.getBufferSize();177 178 switch (Size) {179 case FixLen::Ext1:180 EW.write(FirstByte::FixExt1);181 break;182 case FixLen::Ext2:183 EW.write(FirstByte::FixExt2);184 break;185 case FixLen::Ext4:186 EW.write(FirstByte::FixExt4);187 break;188 case FixLen::Ext8:189 EW.write(FirstByte::FixExt8);190 break;191 case FixLen::Ext16:192 EW.write(FirstByte::FixExt16);193 break;194 default:195 if (Size <= UINT8_MAX) {196 EW.write(FirstByte::Ext8);197 EW.write(static_cast<uint8_t>(Size));198 } else if (Size <= UINT16_MAX) {199 EW.write(FirstByte::Ext16);200 EW.write(static_cast<uint16_t>(Size));201 } else {202 assert(Size <= UINT32_MAX && "Ext size too large to be encoded");203 EW.write(FirstByte::Ext32);204 EW.write(static_cast<uint32_t>(Size));205 }206 }207 208 EW.write(Type);209 EW.OS.write(Buffer.getBufferStart(), Size);210}211