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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// 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 19 using namespace llvm; 20 using namespace msgpack; 21 22 Writer::Writer(raw_ostream &OS, bool Compatible) 23 : EW(OS, Endianness), Compatible(Compatible) {} 24 25 void Writer::writeNil() { EW.write(FirstByte::Nil); } 26 27 void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); } 28 29 void 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 62 void 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 90 void 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 103 void 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 123 void 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 143 void 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 159 void 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 175 void 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