blob: d024bb0fcdb2302cb03c8c8a176ec747f60e8cdb [file] [log] [blame]
Scott Linder20f9cd82018-08-22 21:42:50 +00001//===- 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
18using namespace llvm;
19using namespace msgpack;
20
21Writer::Writer(raw_ostream &OS, bool Compatible)
22 : EW(OS, Endianness), Compatible(Compatible) {}
23
24void Writer::writeNil() { EW.write(FirstByte::Nil); }
25
26void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
27
28void 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
61void 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
89void Writer::write(double d) {
90 // If no loss of precision, encode as a Float32.
Scott Lindera755f4d2018-08-23 02:51:09 +000091 double a = std::fabs(d);
92 if (a >= std::numeric_limits<float>::min() &&
93 a <= std::numeric_limits<float>::max()) {
Scott Linder20f9cd82018-08-22 21:42:50 +000094 EW.write(FirstByte::Float32);
Scott Lindera755f4d2018-08-23 02:51:09 +000095 EW.write(static_cast<float>(d));
Scott Linder20f9cd82018-08-22 21:42:50 +000096 } else {
97 EW.write(FirstByte::Float64);
98 EW.write(d);
99 }
100}
101
102void 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
122void 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
142void 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
158void 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
174void 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}