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