xref: /llvm-project/llvm/lib/BinaryFormat/MsgPackWriter.cpp (revision a755f4d1a076b3fefd46be8cd398aeaa7d60beb9)
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