summaryrefslogtreecommitdiff
path: root/lib/BinaryFormat/MsgPackWriter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/BinaryFormat/MsgPackWriter.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/BinaryFormat/MsgPackWriter.cpp')
-rw-r--r--lib/BinaryFormat/MsgPackWriter.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/lib/BinaryFormat/MsgPackWriter.cpp b/lib/BinaryFormat/MsgPackWriter.cpp
new file mode 100644
index 000000000000..d024bb0fcdb2
--- /dev/null
+++ b/lib/BinaryFormat/MsgPackWriter.cpp
@@ -0,0 +1,209 @@
+//===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a MessagePack writer.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackWriter.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+
+using namespace llvm;
+using namespace msgpack;
+
+Writer::Writer(raw_ostream &OS, bool Compatible)
+ : EW(OS, Endianness), Compatible(Compatible) {}
+
+void Writer::writeNil() { EW.write(FirstByte::Nil); }
+
+void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
+
+void Writer::write(int64_t i) {
+ if (i >= 0) {
+ write(static_cast<uint64_t>(i));
+ return;
+ }
+
+ if (i >= FixMin::NegativeInt) {
+ EW.write(static_cast<int8_t>(i));
+ return;
+ }
+
+ if (i >= INT8_MIN) {
+ EW.write(FirstByte::Int8);
+ EW.write(static_cast<int8_t>(i));
+ return;
+ }
+
+ if (i >= INT16_MIN) {
+ EW.write(FirstByte::Int16);
+ EW.write(static_cast<int16_t>(i));
+ return;
+ }
+
+ if (i >= INT32_MIN) {
+ EW.write(FirstByte::Int32);
+ EW.write(static_cast<int32_t>(i));
+ return;
+ }
+
+ EW.write(FirstByte::Int64);
+ EW.write(i);
+}
+
+void Writer::write(uint64_t u) {
+ if (u <= FixMax::PositiveInt) {
+ EW.write(static_cast<uint8_t>(u));
+ return;
+ }
+
+ if (u <= UINT8_MAX) {
+ EW.write(FirstByte::UInt8);
+ EW.write(static_cast<uint8_t>(u));
+ return;
+ }
+
+ if (u <= UINT16_MAX) {
+ EW.write(FirstByte::UInt16);
+ EW.write(static_cast<uint16_t>(u));
+ return;
+ }
+
+ if (u <= UINT32_MAX) {
+ EW.write(FirstByte::UInt32);
+ EW.write(static_cast<uint32_t>(u));
+ return;
+ }
+
+ EW.write(FirstByte::UInt64);
+ EW.write(u);
+}
+
+void Writer::write(double d) {
+ // If no loss of precision, encode as a Float32.
+ double a = std::fabs(d);
+ if (a >= std::numeric_limits<float>::min() &&
+ a <= std::numeric_limits<float>::max()) {
+ EW.write(FirstByte::Float32);
+ EW.write(static_cast<float>(d));
+ } else {
+ EW.write(FirstByte::Float64);
+ EW.write(d);
+ }
+}
+
+void Writer::write(StringRef s) {
+ size_t Size = s.size();
+
+ if (Size <= FixMax::String)
+ EW.write(static_cast<uint8_t>(FixBits::String | Size));
+ else if (!Compatible && Size <= UINT8_MAX) {
+ EW.write(FirstByte::Str8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Str16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "String object too long to be encoded");
+ EW.write(FirstByte::Str32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+
+ EW.OS << s;
+}
+
+void Writer::write(MemoryBufferRef Buffer) {
+ assert(!Compatible && "Attempt to write Bin format in compatible mode");
+
+ size_t Size = Buffer.getBufferSize();
+
+ if (Size <= UINT8_MAX) {
+ EW.write(FirstByte::Bin8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Bin16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "Binary object too long to be encoded");
+ EW.write(FirstByte::Bin32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+
+ EW.OS.write(Buffer.getBufferStart(), Size);
+}
+
+void Writer::writeArraySize(uint32_t Size) {
+ if (Size <= FixMax::Array) {
+ EW.write(static_cast<uint8_t>(FixBits::Array | Size));
+ return;
+ }
+
+ if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Array16);
+ EW.write(static_cast<uint16_t>(Size));
+ return;
+ }
+
+ EW.write(FirstByte::Array32);
+ EW.write(Size);
+}
+
+void Writer::writeMapSize(uint32_t Size) {
+ if (Size <= FixMax::Map) {
+ EW.write(static_cast<uint8_t>(FixBits::Map | Size));
+ return;
+ }
+
+ if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Map16);
+ EW.write(static_cast<uint16_t>(Size));
+ return;
+ }
+
+ EW.write(FirstByte::Map32);
+ EW.write(Size);
+}
+
+void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {
+ size_t Size = Buffer.getBufferSize();
+
+ switch (Size) {
+ case FixLen::Ext1:
+ EW.write(FirstByte::FixExt1);
+ break;
+ case FixLen::Ext2:
+ EW.write(FirstByte::FixExt2);
+ break;
+ case FixLen::Ext4:
+ EW.write(FirstByte::FixExt4);
+ break;
+ case FixLen::Ext8:
+ EW.write(FirstByte::FixExt8);
+ break;
+ case FixLen::Ext16:
+ EW.write(FirstByte::FixExt16);
+ break;
+ default:
+ if (Size <= UINT8_MAX) {
+ EW.write(FirstByte::Ext8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Ext16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "Ext size too large to be encoded");
+ EW.write(FirstByte::Ext32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+ }
+
+ EW.write(Type);
+ EW.OS.write(Buffer.getBufferStart(), Size);
+}