10b57cec5SDimitry Andric //===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements a MessagePack writer.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "llvm/BinaryFormat/MsgPackWriter.h"
150b57cec5SDimitry Andric #include "llvm/BinaryFormat/MsgPack.h"
160b57cec5SDimitry Andric
17*bdd1243dSDimitry Andric #include <cmath>
18*bdd1243dSDimitry Andric
190b57cec5SDimitry Andric using namespace llvm;
200b57cec5SDimitry Andric using namespace msgpack;
210b57cec5SDimitry Andric
Writer(raw_ostream & OS,bool Compatible)220b57cec5SDimitry Andric Writer::Writer(raw_ostream &OS, bool Compatible)
230b57cec5SDimitry Andric : EW(OS, Endianness), Compatible(Compatible) {}
240b57cec5SDimitry Andric
writeNil()250b57cec5SDimitry Andric void Writer::writeNil() { EW.write(FirstByte::Nil); }
260b57cec5SDimitry Andric
write(bool b)270b57cec5SDimitry Andric void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
280b57cec5SDimitry Andric
write(int64_t i)290b57cec5SDimitry Andric void Writer::write(int64_t i) {
300b57cec5SDimitry Andric if (i >= 0) {
310b57cec5SDimitry Andric write(static_cast<uint64_t>(i));
320b57cec5SDimitry Andric return;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric if (i >= FixMin::NegativeInt) {
360b57cec5SDimitry Andric EW.write(static_cast<int8_t>(i));
370b57cec5SDimitry Andric return;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric if (i >= INT8_MIN) {
410b57cec5SDimitry Andric EW.write(FirstByte::Int8);
420b57cec5SDimitry Andric EW.write(static_cast<int8_t>(i));
430b57cec5SDimitry Andric return;
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric if (i >= INT16_MIN) {
470b57cec5SDimitry Andric EW.write(FirstByte::Int16);
480b57cec5SDimitry Andric EW.write(static_cast<int16_t>(i));
490b57cec5SDimitry Andric return;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric if (i >= INT32_MIN) {
530b57cec5SDimitry Andric EW.write(FirstByte::Int32);
540b57cec5SDimitry Andric EW.write(static_cast<int32_t>(i));
550b57cec5SDimitry Andric return;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric EW.write(FirstByte::Int64);
590b57cec5SDimitry Andric EW.write(i);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
write(uint64_t u)620b57cec5SDimitry Andric void Writer::write(uint64_t u) {
630b57cec5SDimitry Andric if (u <= FixMax::PositiveInt) {
640b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(u));
650b57cec5SDimitry Andric return;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric if (u <= UINT8_MAX) {
690b57cec5SDimitry Andric EW.write(FirstByte::UInt8);
700b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(u));
710b57cec5SDimitry Andric return;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric if (u <= UINT16_MAX) {
750b57cec5SDimitry Andric EW.write(FirstByte::UInt16);
760b57cec5SDimitry Andric EW.write(static_cast<uint16_t>(u));
770b57cec5SDimitry Andric return;
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric if (u <= UINT32_MAX) {
810b57cec5SDimitry Andric EW.write(FirstByte::UInt32);
820b57cec5SDimitry Andric EW.write(static_cast<uint32_t>(u));
830b57cec5SDimitry Andric return;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric EW.write(FirstByte::UInt64);
870b57cec5SDimitry Andric EW.write(u);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
write(double d)900b57cec5SDimitry Andric void Writer::write(double d) {
910b57cec5SDimitry Andric // If no loss of precision, encode as a Float32.
920b57cec5SDimitry Andric double a = std::fabs(d);
930b57cec5SDimitry Andric if (a >= std::numeric_limits<float>::min() &&
940b57cec5SDimitry Andric a <= std::numeric_limits<float>::max()) {
950b57cec5SDimitry Andric EW.write(FirstByte::Float32);
960b57cec5SDimitry Andric EW.write(static_cast<float>(d));
970b57cec5SDimitry Andric } else {
980b57cec5SDimitry Andric EW.write(FirstByte::Float64);
990b57cec5SDimitry Andric EW.write(d);
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
write(StringRef s)1030b57cec5SDimitry Andric void Writer::write(StringRef s) {
1040b57cec5SDimitry Andric size_t Size = s.size();
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric if (Size <= FixMax::String)
1070b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(FixBits::String | Size));
1080b57cec5SDimitry Andric else if (!Compatible && Size <= UINT8_MAX) {
1090b57cec5SDimitry Andric EW.write(FirstByte::Str8);
1100b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(Size));
1110b57cec5SDimitry Andric } else if (Size <= UINT16_MAX) {
1120b57cec5SDimitry Andric EW.write(FirstByte::Str16);
1130b57cec5SDimitry Andric EW.write(static_cast<uint16_t>(Size));
1140b57cec5SDimitry Andric } else {
1150b57cec5SDimitry Andric assert(Size <= UINT32_MAX && "String object too long to be encoded");
1160b57cec5SDimitry Andric EW.write(FirstByte::Str32);
1170b57cec5SDimitry Andric EW.write(static_cast<uint32_t>(Size));
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric EW.OS << s;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
write(MemoryBufferRef Buffer)1230b57cec5SDimitry Andric void Writer::write(MemoryBufferRef Buffer) {
1240b57cec5SDimitry Andric assert(!Compatible && "Attempt to write Bin format in compatible mode");
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric size_t Size = Buffer.getBufferSize();
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric if (Size <= UINT8_MAX) {
1290b57cec5SDimitry Andric EW.write(FirstByte::Bin8);
1300b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(Size));
1310b57cec5SDimitry Andric } else if (Size <= UINT16_MAX) {
1320b57cec5SDimitry Andric EW.write(FirstByte::Bin16);
1330b57cec5SDimitry Andric EW.write(static_cast<uint16_t>(Size));
1340b57cec5SDimitry Andric } else {
1350b57cec5SDimitry Andric assert(Size <= UINT32_MAX && "Binary object too long to be encoded");
1360b57cec5SDimitry Andric EW.write(FirstByte::Bin32);
1370b57cec5SDimitry Andric EW.write(static_cast<uint32_t>(Size));
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric EW.OS.write(Buffer.getBufferStart(), Size);
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
writeArraySize(uint32_t Size)1430b57cec5SDimitry Andric void Writer::writeArraySize(uint32_t Size) {
1440b57cec5SDimitry Andric if (Size <= FixMax::Array) {
1450b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(FixBits::Array | Size));
1460b57cec5SDimitry Andric return;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric if (Size <= UINT16_MAX) {
1500b57cec5SDimitry Andric EW.write(FirstByte::Array16);
1510b57cec5SDimitry Andric EW.write(static_cast<uint16_t>(Size));
1520b57cec5SDimitry Andric return;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric EW.write(FirstByte::Array32);
1560b57cec5SDimitry Andric EW.write(Size);
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric
writeMapSize(uint32_t Size)1590b57cec5SDimitry Andric void Writer::writeMapSize(uint32_t Size) {
1600b57cec5SDimitry Andric if (Size <= FixMax::Map) {
1610b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(FixBits::Map | Size));
1620b57cec5SDimitry Andric return;
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric if (Size <= UINT16_MAX) {
1660b57cec5SDimitry Andric EW.write(FirstByte::Map16);
1670b57cec5SDimitry Andric EW.write(static_cast<uint16_t>(Size));
1680b57cec5SDimitry Andric return;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric EW.write(FirstByte::Map32);
1720b57cec5SDimitry Andric EW.write(Size);
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
writeExt(int8_t Type,MemoryBufferRef Buffer)1750b57cec5SDimitry Andric void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {
1760b57cec5SDimitry Andric size_t Size = Buffer.getBufferSize();
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric switch (Size) {
1790b57cec5SDimitry Andric case FixLen::Ext1:
1800b57cec5SDimitry Andric EW.write(FirstByte::FixExt1);
1810b57cec5SDimitry Andric break;
1820b57cec5SDimitry Andric case FixLen::Ext2:
1830b57cec5SDimitry Andric EW.write(FirstByte::FixExt2);
1840b57cec5SDimitry Andric break;
1850b57cec5SDimitry Andric case FixLen::Ext4:
1860b57cec5SDimitry Andric EW.write(FirstByte::FixExt4);
1870b57cec5SDimitry Andric break;
1880b57cec5SDimitry Andric case FixLen::Ext8:
1890b57cec5SDimitry Andric EW.write(FirstByte::FixExt8);
1900b57cec5SDimitry Andric break;
1910b57cec5SDimitry Andric case FixLen::Ext16:
1920b57cec5SDimitry Andric EW.write(FirstByte::FixExt16);
1930b57cec5SDimitry Andric break;
1940b57cec5SDimitry Andric default:
1950b57cec5SDimitry Andric if (Size <= UINT8_MAX) {
1960b57cec5SDimitry Andric EW.write(FirstByte::Ext8);
1970b57cec5SDimitry Andric EW.write(static_cast<uint8_t>(Size));
1980b57cec5SDimitry Andric } else if (Size <= UINT16_MAX) {
1990b57cec5SDimitry Andric EW.write(FirstByte::Ext16);
2000b57cec5SDimitry Andric EW.write(static_cast<uint16_t>(Size));
2010b57cec5SDimitry Andric } else {
2020b57cec5SDimitry Andric assert(Size <= UINT32_MAX && "Ext size too large to be encoded");
2030b57cec5SDimitry Andric EW.write(FirstByte::Ext32);
2040b57cec5SDimitry Andric EW.write(static_cast<uint32_t>(Size));
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric EW.write(Type);
2090b57cec5SDimitry Andric EW.OS.write(Buffer.getBufferStart(), Size);
2100b57cec5SDimitry Andric }
211