120f9cd88SScott Linder //===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//
220f9cd88SScott Linder //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
620f9cd88SScott Linder //
720f9cd88SScott Linder //===----------------------------------------------------------------------===//
820f9cd88SScott Linder ///
920f9cd88SScott Linder /// \file
1020f9cd88SScott Linder /// This file implements a MessagePack writer.
1120f9cd88SScott Linder ///
1220f9cd88SScott Linder //===----------------------------------------------------------------------===//
1320f9cd88SScott Linder
1420f9cd88SScott Linder #include "llvm/BinaryFormat/MsgPackWriter.h"
1520f9cd88SScott Linder #include "llvm/BinaryFormat/MsgPack.h"
1620f9cd88SScott Linder
17*16544cbeSserge-sans-paille #include <cmath>
18*16544cbeSserge-sans-paille
1920f9cd88SScott Linder using namespace llvm;
2020f9cd88SScott Linder using namespace msgpack;
2120f9cd88SScott Linder
Writer(raw_ostream & OS,bool Compatible)2220f9cd88SScott Linder Writer::Writer(raw_ostream &OS, bool Compatible)
2320f9cd88SScott Linder : EW(OS, Endianness), Compatible(Compatible) {}
2420f9cd88SScott Linder
writeNil()2520f9cd88SScott Linder void Writer::writeNil() { EW.write(FirstByte::Nil); }
2620f9cd88SScott Linder
write(bool b)2720f9cd88SScott Linder void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
2820f9cd88SScott Linder
write(int64_t i)2920f9cd88SScott Linder void Writer::write(int64_t i) {
3020f9cd88SScott Linder if (i >= 0) {
3120f9cd88SScott Linder write(static_cast<uint64_t>(i));
3220f9cd88SScott Linder return;
3320f9cd88SScott Linder }
3420f9cd88SScott Linder
3520f9cd88SScott Linder if (i >= FixMin::NegativeInt) {
3620f9cd88SScott Linder EW.write(static_cast<int8_t>(i));
3720f9cd88SScott Linder return;
3820f9cd88SScott Linder }
3920f9cd88SScott Linder
4020f9cd88SScott Linder if (i >= INT8_MIN) {
4120f9cd88SScott Linder EW.write(FirstByte::Int8);
4220f9cd88SScott Linder EW.write(static_cast<int8_t>(i));
4320f9cd88SScott Linder return;
4420f9cd88SScott Linder }
4520f9cd88SScott Linder
4620f9cd88SScott Linder if (i >= INT16_MIN) {
4720f9cd88SScott Linder EW.write(FirstByte::Int16);
4820f9cd88SScott Linder EW.write(static_cast<int16_t>(i));
4920f9cd88SScott Linder return;
5020f9cd88SScott Linder }
5120f9cd88SScott Linder
5220f9cd88SScott Linder if (i >= INT32_MIN) {
5320f9cd88SScott Linder EW.write(FirstByte::Int32);
5420f9cd88SScott Linder EW.write(static_cast<int32_t>(i));
5520f9cd88SScott Linder return;
5620f9cd88SScott Linder }
5720f9cd88SScott Linder
5820f9cd88SScott Linder EW.write(FirstByte::Int64);
5920f9cd88SScott Linder EW.write(i);
6020f9cd88SScott Linder }
6120f9cd88SScott Linder
write(uint64_t u)6220f9cd88SScott Linder void Writer::write(uint64_t u) {
6320f9cd88SScott Linder if (u <= FixMax::PositiveInt) {
6420f9cd88SScott Linder EW.write(static_cast<uint8_t>(u));
6520f9cd88SScott Linder return;
6620f9cd88SScott Linder }
6720f9cd88SScott Linder
6820f9cd88SScott Linder if (u <= UINT8_MAX) {
6920f9cd88SScott Linder EW.write(FirstByte::UInt8);
7020f9cd88SScott Linder EW.write(static_cast<uint8_t>(u));
7120f9cd88SScott Linder return;
7220f9cd88SScott Linder }
7320f9cd88SScott Linder
7420f9cd88SScott Linder if (u <= UINT16_MAX) {
7520f9cd88SScott Linder EW.write(FirstByte::UInt16);
7620f9cd88SScott Linder EW.write(static_cast<uint16_t>(u));
7720f9cd88SScott Linder return;
7820f9cd88SScott Linder }
7920f9cd88SScott Linder
8020f9cd88SScott Linder if (u <= UINT32_MAX) {
8120f9cd88SScott Linder EW.write(FirstByte::UInt32);
8220f9cd88SScott Linder EW.write(static_cast<uint32_t>(u));
8320f9cd88SScott Linder return;
8420f9cd88SScott Linder }
8520f9cd88SScott Linder
8620f9cd88SScott Linder EW.write(FirstByte::UInt64);
8720f9cd88SScott Linder EW.write(u);
8820f9cd88SScott Linder }
8920f9cd88SScott Linder
write(double d)9020f9cd88SScott Linder void Writer::write(double d) {
9120f9cd88SScott Linder // If no loss of precision, encode as a Float32.
92a755f4d1SScott Linder double a = std::fabs(d);
93a755f4d1SScott Linder if (a >= std::numeric_limits<float>::min() &&
94a755f4d1SScott Linder a <= std::numeric_limits<float>::max()) {
9520f9cd88SScott Linder EW.write(FirstByte::Float32);
96a755f4d1SScott Linder EW.write(static_cast<float>(d));
9720f9cd88SScott Linder } else {
9820f9cd88SScott Linder EW.write(FirstByte::Float64);
9920f9cd88SScott Linder EW.write(d);
10020f9cd88SScott Linder }
10120f9cd88SScott Linder }
10220f9cd88SScott Linder
write(StringRef s)10320f9cd88SScott Linder void Writer::write(StringRef s) {
10420f9cd88SScott Linder size_t Size = s.size();
10520f9cd88SScott Linder
10620f9cd88SScott Linder if (Size <= FixMax::String)
10720f9cd88SScott Linder EW.write(static_cast<uint8_t>(FixBits::String | Size));
10820f9cd88SScott Linder else if (!Compatible && Size <= UINT8_MAX) {
10920f9cd88SScott Linder EW.write(FirstByte::Str8);
11020f9cd88SScott Linder EW.write(static_cast<uint8_t>(Size));
11120f9cd88SScott Linder } else if (Size <= UINT16_MAX) {
11220f9cd88SScott Linder EW.write(FirstByte::Str16);
11320f9cd88SScott Linder EW.write(static_cast<uint16_t>(Size));
11420f9cd88SScott Linder } else {
11520f9cd88SScott Linder assert(Size <= UINT32_MAX && "String object too long to be encoded");
11620f9cd88SScott Linder EW.write(FirstByte::Str32);
11720f9cd88SScott Linder EW.write(static_cast<uint32_t>(Size));
11820f9cd88SScott Linder }
11920f9cd88SScott Linder
12020f9cd88SScott Linder EW.OS << s;
12120f9cd88SScott Linder }
12220f9cd88SScott Linder
write(MemoryBufferRef Buffer)12320f9cd88SScott Linder void Writer::write(MemoryBufferRef Buffer) {
12420f9cd88SScott Linder assert(!Compatible && "Attempt to write Bin format in compatible mode");
12520f9cd88SScott Linder
12620f9cd88SScott Linder size_t Size = Buffer.getBufferSize();
12720f9cd88SScott Linder
12820f9cd88SScott Linder if (Size <= UINT8_MAX) {
12920f9cd88SScott Linder EW.write(FirstByte::Bin8);
13020f9cd88SScott Linder EW.write(static_cast<uint8_t>(Size));
13120f9cd88SScott Linder } else if (Size <= UINT16_MAX) {
13220f9cd88SScott Linder EW.write(FirstByte::Bin16);
13320f9cd88SScott Linder EW.write(static_cast<uint16_t>(Size));
13420f9cd88SScott Linder } else {
13520f9cd88SScott Linder assert(Size <= UINT32_MAX && "Binary object too long to be encoded");
13620f9cd88SScott Linder EW.write(FirstByte::Bin32);
13720f9cd88SScott Linder EW.write(static_cast<uint32_t>(Size));
13820f9cd88SScott Linder }
13920f9cd88SScott Linder
14020f9cd88SScott Linder EW.OS.write(Buffer.getBufferStart(), Size);
14120f9cd88SScott Linder }
14220f9cd88SScott Linder
writeArraySize(uint32_t Size)14320f9cd88SScott Linder void Writer::writeArraySize(uint32_t Size) {
14420f9cd88SScott Linder if (Size <= FixMax::Array) {
14520f9cd88SScott Linder EW.write(static_cast<uint8_t>(FixBits::Array | Size));
14620f9cd88SScott Linder return;
14720f9cd88SScott Linder }
14820f9cd88SScott Linder
14920f9cd88SScott Linder if (Size <= UINT16_MAX) {
15020f9cd88SScott Linder EW.write(FirstByte::Array16);
15120f9cd88SScott Linder EW.write(static_cast<uint16_t>(Size));
15220f9cd88SScott Linder return;
15320f9cd88SScott Linder }
15420f9cd88SScott Linder
15520f9cd88SScott Linder EW.write(FirstByte::Array32);
15620f9cd88SScott Linder EW.write(Size);
15720f9cd88SScott Linder }
15820f9cd88SScott Linder
writeMapSize(uint32_t Size)15920f9cd88SScott Linder void Writer::writeMapSize(uint32_t Size) {
16020f9cd88SScott Linder if (Size <= FixMax::Map) {
16120f9cd88SScott Linder EW.write(static_cast<uint8_t>(FixBits::Map | Size));
16220f9cd88SScott Linder return;
16320f9cd88SScott Linder }
16420f9cd88SScott Linder
16520f9cd88SScott Linder if (Size <= UINT16_MAX) {
16620f9cd88SScott Linder EW.write(FirstByte::Map16);
16720f9cd88SScott Linder EW.write(static_cast<uint16_t>(Size));
16820f9cd88SScott Linder return;
16920f9cd88SScott Linder }
17020f9cd88SScott Linder
17120f9cd88SScott Linder EW.write(FirstByte::Map32);
17220f9cd88SScott Linder EW.write(Size);
17320f9cd88SScott Linder }
17420f9cd88SScott Linder
writeExt(int8_t Type,MemoryBufferRef Buffer)17520f9cd88SScott Linder void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {
17620f9cd88SScott Linder size_t Size = Buffer.getBufferSize();
17720f9cd88SScott Linder
17820f9cd88SScott Linder switch (Size) {
17920f9cd88SScott Linder case FixLen::Ext1:
18020f9cd88SScott Linder EW.write(FirstByte::FixExt1);
18120f9cd88SScott Linder break;
18220f9cd88SScott Linder case FixLen::Ext2:
18320f9cd88SScott Linder EW.write(FirstByte::FixExt2);
18420f9cd88SScott Linder break;
18520f9cd88SScott Linder case FixLen::Ext4:
18620f9cd88SScott Linder EW.write(FirstByte::FixExt4);
18720f9cd88SScott Linder break;
18820f9cd88SScott Linder case FixLen::Ext8:
18920f9cd88SScott Linder EW.write(FirstByte::FixExt8);
19020f9cd88SScott Linder break;
19120f9cd88SScott Linder case FixLen::Ext16:
19220f9cd88SScott Linder EW.write(FirstByte::FixExt16);
19320f9cd88SScott Linder break;
19420f9cd88SScott Linder default:
19520f9cd88SScott Linder if (Size <= UINT8_MAX) {
19620f9cd88SScott Linder EW.write(FirstByte::Ext8);
19720f9cd88SScott Linder EW.write(static_cast<uint8_t>(Size));
19820f9cd88SScott Linder } else if (Size <= UINT16_MAX) {
19920f9cd88SScott Linder EW.write(FirstByte::Ext16);
20020f9cd88SScott Linder EW.write(static_cast<uint16_t>(Size));
20120f9cd88SScott Linder } else {
20220f9cd88SScott Linder assert(Size <= UINT32_MAX && "Ext size too large to be encoded");
20320f9cd88SScott Linder EW.write(FirstByte::Ext32);
20420f9cd88SScott Linder EW.write(static_cast<uint32_t>(Size));
20520f9cd88SScott Linder }
20620f9cd88SScott Linder }
20720f9cd88SScott Linder
20820f9cd88SScott Linder EW.write(Type);
20920f9cd88SScott Linder EW.OS.write(Buffer.getBufferStart(), Size);
21020f9cd88SScott Linder }
211