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