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