Recovered/ holds the code linked only into the standalone exe (scripts/exe/build_exe.py), outside the Clank source dirs: - jsoncons/ and nProtect/ moved from scripts/exe/; GameGuard stand-in follows main's renamed entry points. - GPak/PakAuxiliary.cpp: Extract (virtualised in every build; 02-19 jumps out at 0x0065861E) rebuilt from the open GRF Editor decoder, after the visible 02-19 prologue; inline key and kRO keys 1-4. Apply traps (unreachable in 02-19). - GGHash/GGHash.cpp: CGGHash::Load/Check/VerifyHash trap (RagHash.dat check unreachable in 02-19). The whole client links: 984 units, 0 unresolved.
753 lines
29 KiB
C++
753 lines
29 KiB
C++
// Copyright 2013-2023 Daniel Parker
|
|
// Distributed under the Boost license, Version 1.0.
|
|
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// See https://github.com/danielaparker/jsoncons for latest version
|
|
|
|
#ifndef JSONCONS_MSGPACK_MSGPACK_ENCODER_HPP
|
|
#define JSONCONS_MSGPACK_MSGPACK_ENCODER_HPP
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <limits> // std::numeric_limits
|
|
#include <memory>
|
|
#include <utility> // std::move
|
|
#include <jsoncons/json_exception.hpp>
|
|
#include <jsoncons/json_visitor.hpp>
|
|
#include <jsoncons/config/jsoncons_config.hpp>
|
|
#include <jsoncons/sink.hpp>
|
|
#include <jsoncons/detail/parse_number.hpp>
|
|
#include <jsoncons_ext/msgpack/msgpack_type.hpp>
|
|
#include <jsoncons_ext/msgpack/msgpack_error.hpp>
|
|
#include <jsoncons_ext/msgpack/msgpack_options.hpp>
|
|
|
|
namespace jsoncons {
|
|
namespace msgpack {
|
|
|
|
enum class msgpack_container_type {object, array};
|
|
|
|
template<class Sink=jsoncons::binary_stream_sink,class Allocator=std::allocator<char>>
|
|
class basic_msgpack_encoder final : public basic_json_visitor<char>
|
|
{
|
|
enum class decimal_parse_state { start, integer, exp1, exp2, fraction1 };
|
|
|
|
static constexpr int64_t nanos_in_milli = 1000000;
|
|
static constexpr int64_t nanos_in_second = 1000000000;
|
|
static constexpr int64_t millis_in_second = 1000;
|
|
public:
|
|
using allocator_type = Allocator;
|
|
using char_type = char;
|
|
using typename basic_json_visitor<char>::string_view_type;
|
|
using sink_type = Sink;
|
|
|
|
private:
|
|
struct stack_item
|
|
{
|
|
msgpack_container_type type_;
|
|
std::size_t length_;
|
|
std::size_t count_;
|
|
|
|
stack_item(msgpack_container_type type, std::size_t length = 0) noexcept
|
|
: type_(type), length_(length), count_(0)
|
|
{
|
|
}
|
|
|
|
std::size_t length() const
|
|
{
|
|
return length_;
|
|
}
|
|
|
|
std::size_t count() const
|
|
{
|
|
return count_;
|
|
}
|
|
|
|
bool is_object() const
|
|
{
|
|
return type_ == msgpack_container_type::object;
|
|
}
|
|
};
|
|
|
|
Sink sink_;
|
|
const msgpack_encode_options options_;
|
|
allocator_type alloc_;
|
|
|
|
std::vector<stack_item> stack_;
|
|
int nesting_depth_;
|
|
|
|
// Noncopyable and nonmoveable
|
|
basic_msgpack_encoder(const basic_msgpack_encoder&) = delete;
|
|
basic_msgpack_encoder& operator=(const basic_msgpack_encoder&) = delete;
|
|
public:
|
|
explicit basic_msgpack_encoder(Sink&& sink,
|
|
const Allocator& alloc = Allocator())
|
|
: basic_msgpack_encoder(std::forward<Sink>(sink), msgpack_encode_options(), alloc)
|
|
{
|
|
}
|
|
|
|
explicit basic_msgpack_encoder(Sink&& sink,
|
|
const msgpack_encode_options& options,
|
|
const Allocator& alloc = Allocator())
|
|
: sink_(std::forward<Sink>(sink)),
|
|
options_(options),
|
|
alloc_(alloc),
|
|
nesting_depth_(0)
|
|
{
|
|
}
|
|
|
|
~basic_msgpack_encoder() noexcept
|
|
{
|
|
sink_.flush();
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
stack_.clear();
|
|
nesting_depth_ = 0;
|
|
}
|
|
|
|
void reset(Sink&& sink)
|
|
{
|
|
sink_ = std::move(sink);
|
|
reset();
|
|
}
|
|
|
|
private:
|
|
// Implementing methods
|
|
|
|
void visit_flush() override
|
|
{
|
|
sink_.flush();
|
|
}
|
|
|
|
bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override
|
|
{
|
|
ec = msgpack_errc::object_length_required;
|
|
return false;
|
|
}
|
|
|
|
bool visit_begin_object(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) override
|
|
{
|
|
if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth()))
|
|
{
|
|
ec = msgpack_errc::max_nesting_depth_exceeded;
|
|
return false;
|
|
}
|
|
stack_.emplace_back(msgpack_container_type::object, length);
|
|
|
|
if (length <= 15)
|
|
{
|
|
// fixmap
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixmap_base_type | (length & 0xf));
|
|
}
|
|
else if (length <= 65535)
|
|
{
|
|
// map 16
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::map16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(length),
|
|
std::back_inserter(sink_));
|
|
}
|
|
else if (length <= 4294967295)
|
|
{
|
|
// map 32
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::map32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(length),
|
|
std::back_inserter(sink_));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool visit_end_object(const ser_context&, std::error_code& ec) override
|
|
{
|
|
JSONCONS_ASSERT(!stack_.empty());
|
|
--nesting_depth_;
|
|
|
|
if (stack_.back().count() < stack_.back().length())
|
|
{
|
|
ec = msgpack_errc::too_few_items;
|
|
return false;
|
|
}
|
|
else if (stack_.back().count() > stack_.back().length())
|
|
{
|
|
ec = msgpack_errc::too_many_items;
|
|
return false;
|
|
}
|
|
|
|
stack_.pop_back();
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override
|
|
{
|
|
ec = msgpack_errc::array_length_required;
|
|
return false;
|
|
}
|
|
|
|
bool visit_begin_array(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) override
|
|
{
|
|
if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth()))
|
|
{
|
|
ec = msgpack_errc::max_nesting_depth_exceeded;
|
|
return false;
|
|
}
|
|
stack_.emplace_back(msgpack_container_type::array, length);
|
|
if (length <= 15)
|
|
{
|
|
// fixarray
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixarray_base_type | (length & 0xf));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint16_t>::max)())
|
|
{
|
|
// array 16
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::array16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(length),std::back_inserter(sink_));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint32_t>::max)())
|
|
{
|
|
// array 32
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::array32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool visit_end_array(const ser_context&, std::error_code& ec) override
|
|
{
|
|
JSONCONS_ASSERT(!stack_.empty());
|
|
|
|
--nesting_depth_;
|
|
|
|
if (stack_.back().count() < stack_.back().length())
|
|
{
|
|
ec = msgpack_errc::too_few_items;
|
|
return false;
|
|
}
|
|
else if (stack_.back().count() > stack_.back().length())
|
|
{
|
|
ec = msgpack_errc::too_many_items;
|
|
return false;
|
|
}
|
|
|
|
stack_.pop_back();
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
|
|
{
|
|
write_string_value(name);
|
|
return true;
|
|
}
|
|
|
|
bool visit_null(semantic_tag, const ser_context&, std::error_code&) override
|
|
{
|
|
// nil
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::nil_type);
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
void write_timestamp(int64_t seconds, int64_t nanoseconds)
|
|
{
|
|
if ((seconds >> 34) == 0)
|
|
{
|
|
uint64_t data64 = (nanoseconds << 34) | seconds;
|
|
if ((data64 & 0xffffffff00000000L) == 0)
|
|
{
|
|
// timestamp 32
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
|
|
sink_.push_back(0xff);
|
|
binary::native_to_big(static_cast<uint32_t>(data64), std::back_inserter(sink_));
|
|
}
|
|
else
|
|
{
|
|
// timestamp 64
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
|
|
sink_.push_back(0xff);
|
|
binary::native_to_big(static_cast<uint64_t>(data64), std::back_inserter(sink_));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// timestamp 96
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
|
|
sink_.push_back(0x0c); // 12
|
|
sink_.push_back(0xff);
|
|
binary::native_to_big(static_cast<uint32_t>(nanoseconds), std::back_inserter(sink_));
|
|
binary::native_to_big(static_cast<uint64_t>(seconds), std::back_inserter(sink_));
|
|
}
|
|
}
|
|
|
|
bool visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) override
|
|
{
|
|
switch (tag)
|
|
{
|
|
case semantic_tag::epoch_second:
|
|
{
|
|
int64_t seconds;
|
|
auto result = jsoncons::detail::to_integer(sv.data(), sv.length(), seconds);
|
|
if (!result)
|
|
{
|
|
ec = msgpack_errc::invalid_timestamp;
|
|
return false;
|
|
}
|
|
write_timestamp(seconds, 0);
|
|
break;
|
|
}
|
|
case semantic_tag::epoch_milli:
|
|
{
|
|
bigint n = bigint::from_string(sv.data(), sv.length());
|
|
if (n != 0)
|
|
{
|
|
bigint q;
|
|
bigint rem;
|
|
n.divide(millis_in_second, q, rem, true);
|
|
int64_t seconds = static_cast<int64_t>(q);
|
|
int64_t nanoseconds = static_cast<int64_t>(rem) * nanos_in_milli;
|
|
if (nanoseconds < 0)
|
|
{
|
|
nanoseconds = -nanoseconds;
|
|
}
|
|
write_timestamp(seconds, nanoseconds);
|
|
}
|
|
else
|
|
{
|
|
write_timestamp(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case semantic_tag::epoch_nano:
|
|
{
|
|
bigint n = bigint::from_string(sv.data(), sv.length());
|
|
if (n != 0)
|
|
{
|
|
bigint q;
|
|
bigint rem;
|
|
n.divide(nanos_in_second, q, rem, true);
|
|
int64_t seconds = static_cast<int64_t>(q);
|
|
int64_t nanoseconds = static_cast<int64_t>(rem);
|
|
if (nanoseconds < 0)
|
|
{
|
|
nanoseconds = -nanoseconds;
|
|
}
|
|
write_timestamp(seconds, nanoseconds);
|
|
}
|
|
else
|
|
{
|
|
write_timestamp(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
write_string_value(sv);
|
|
end_value();
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void write_string_value(const string_view_type& sv)
|
|
{
|
|
auto sink = unicode_traits::validate(sv.data(), sv.size());
|
|
if (sink.ec != unicode_traits::conv_errc())
|
|
{
|
|
JSONCONS_THROW(ser_error(msgpack_errc::invalid_utf8_text_string));
|
|
}
|
|
|
|
const size_t length = sv.length();
|
|
if (length <= 31)
|
|
{
|
|
// fixstr stores a byte array whose length is upto 31 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixstr_base_type | static_cast<uint8_t>(length));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint8_t>::max)())
|
|
{
|
|
// str 8 stores a byte array whose length is upto (2^8)-1 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::str8_type);
|
|
sink_.push_back(static_cast<uint8_t>(length));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint16_t>::max)())
|
|
{
|
|
// str 16 stores a byte array whose length is upto (2^16)-1 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::str16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint32_t>::max)())
|
|
{
|
|
// str 32 stores a byte array whose length is upto (2^32)-1 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::str32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
|
|
}
|
|
|
|
for (auto c : sv)
|
|
{
|
|
sink_.push_back(c);
|
|
}
|
|
}
|
|
|
|
bool visit_byte_string(const byte_string_view& b,
|
|
semantic_tag,
|
|
const ser_context&,
|
|
std::error_code&) override
|
|
{
|
|
|
|
const std::size_t length = b.size();
|
|
if (length <= (std::numeric_limits<uint8_t>::max)())
|
|
{
|
|
// bin 8 stores a byte array whose length is upto (2^8)-1 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::bin8_type);
|
|
sink_.push_back(static_cast<uint8_t>(length));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint16_t>::max)())
|
|
{
|
|
// bin 16 stores a byte array whose length is upto (2^16)-1 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::bin16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint32_t>::max)())
|
|
{
|
|
// bin 32 stores a byte array whose length is upto (2^32)-1 bytes
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::bin32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
|
|
}
|
|
|
|
for (auto c : b)
|
|
{
|
|
sink_.push_back(c);
|
|
}
|
|
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_byte_string(const byte_string_view& b,
|
|
uint64_t ext_tag,
|
|
const ser_context&,
|
|
std::error_code&) override
|
|
{
|
|
const std::size_t length = b.size();
|
|
switch (length)
|
|
{
|
|
case 1:
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext1_type);
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
break;
|
|
case 2:
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext2_type);
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
break;
|
|
case 4:
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type);
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
break;
|
|
case 8:
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type);
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
break;
|
|
case 16:
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::fixext16_type);
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
break;
|
|
default:
|
|
if (length <= (std::numeric_limits<uint8_t>::max)())
|
|
{
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type);
|
|
sink_.push_back(static_cast<uint8_t>(length));
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint16_t>::max)())
|
|
{
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::ext16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(length), std::back_inserter(sink_));
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
}
|
|
else if (length <= (std::numeric_limits<uint32_t>::max)())
|
|
{
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::ext32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(length),std::back_inserter(sink_));
|
|
sink_.push_back(static_cast<uint8_t>(ext_tag));
|
|
}
|
|
break;
|
|
}
|
|
|
|
for (auto c : b)
|
|
{
|
|
sink_.push_back(c);
|
|
}
|
|
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_double(double val,
|
|
semantic_tag,
|
|
const ser_context&,
|
|
std::error_code&) override
|
|
{
|
|
float valf = (float)val;
|
|
if ((double)valf == val)
|
|
{
|
|
// float 32
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::float32_type);
|
|
binary::native_to_big(valf,std::back_inserter(sink_));
|
|
}
|
|
else
|
|
{
|
|
// float 64
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::float64_type);
|
|
binary::native_to_big(val,std::back_inserter(sink_));
|
|
}
|
|
|
|
// write double
|
|
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_int64(int64_t val,
|
|
semantic_tag tag,
|
|
const ser_context&,
|
|
std::error_code&) override
|
|
{
|
|
switch (tag)
|
|
{
|
|
case semantic_tag::epoch_second:
|
|
write_timestamp(val, 0);
|
|
break;
|
|
case semantic_tag::epoch_milli:
|
|
{
|
|
if (val != 0)
|
|
{
|
|
auto dv = std::div(val,millis_in_second);
|
|
int64_t seconds = dv.quot;
|
|
int64_t nanoseconds = dv.rem*nanos_in_milli;
|
|
if (nanoseconds < 0)
|
|
{
|
|
nanoseconds = -nanoseconds;
|
|
}
|
|
write_timestamp(seconds, nanoseconds);
|
|
}
|
|
else
|
|
{
|
|
write_timestamp(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case semantic_tag::epoch_nano:
|
|
{
|
|
if (val != 0)
|
|
{
|
|
auto dv = std::div(val,static_cast<int64_t>(nanos_in_second));
|
|
int64_t seconds = dv.quot;
|
|
int64_t nanoseconds = dv.rem;
|
|
if (nanoseconds < 0)
|
|
{
|
|
nanoseconds = -nanoseconds;
|
|
}
|
|
write_timestamp(seconds, nanoseconds);
|
|
}
|
|
else
|
|
{
|
|
write_timestamp(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if (val >= 0)
|
|
{
|
|
if (val <= 0x7f)
|
|
{
|
|
// positive fixnum stores 7-bit positive integer
|
|
sink_.push_back(static_cast<uint8_t>(val));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint8_t>::max)())
|
|
{
|
|
// uint 8 stores a 8-bit unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
|
|
sink_.push_back(static_cast<uint8_t>(val));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint16_t>::max)())
|
|
{
|
|
// uint 16 stores a 16-bit big-endian unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint32_t>::max)())
|
|
{
|
|
// uint 32 stores a 32-bit big-endian unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val <= (std::numeric_limits<int64_t>::max)())
|
|
{
|
|
// int 64 stores a 64-bit big-endian signed integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
|
|
binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (val >= -32)
|
|
{
|
|
// negative fixnum stores 5-bit negative integer
|
|
binary::native_to_big(static_cast<int8_t>(val), std::back_inserter(sink_));
|
|
}
|
|
else if (val >= (std::numeric_limits<int8_t>::lowest)())
|
|
{
|
|
// int 8 stores a 8-bit signed integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::int8_type);
|
|
binary::native_to_big(static_cast<int8_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val >= (std::numeric_limits<int16_t>::lowest)())
|
|
{
|
|
// int 16 stores a 16-bit big-endian signed integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::int16_type);
|
|
binary::native_to_big(static_cast<int16_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val >= (std::numeric_limits<int32_t>::lowest)())
|
|
{
|
|
// int 32 stores a 32-bit big-endian signed integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::int32_type);
|
|
binary::native_to_big(static_cast<int32_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val >= (std::numeric_limits<int64_t>::lowest)())
|
|
{
|
|
// int 64 stores a 64-bit big-endian signed integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::int64_type);
|
|
binary::native_to_big(static_cast<int64_t>(val),std::back_inserter(sink_));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_uint64(uint64_t val,
|
|
semantic_tag tag,
|
|
const ser_context&,
|
|
std::error_code&) override
|
|
{
|
|
switch (tag)
|
|
{
|
|
case semantic_tag::epoch_second:
|
|
write_timestamp(static_cast<int64_t>(val), 0);
|
|
break;
|
|
case semantic_tag::epoch_milli:
|
|
{
|
|
if (val != 0)
|
|
{
|
|
auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(millis_in_second));
|
|
int64_t seconds = dv.quot;
|
|
int64_t nanoseconds = dv.rem*nanos_in_milli;
|
|
if (nanoseconds < 0)
|
|
{
|
|
nanoseconds = -nanoseconds;
|
|
}
|
|
write_timestamp(seconds, nanoseconds);
|
|
}
|
|
else
|
|
{
|
|
write_timestamp(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
case semantic_tag::epoch_nano:
|
|
{
|
|
if (val != 0)
|
|
{
|
|
auto dv = std::div(static_cast<int64_t>(val), static_cast<int64_t>(nanos_in_second));
|
|
int64_t seconds = dv.quot;
|
|
int64_t nanoseconds = dv.rem;
|
|
if (nanoseconds < 0)
|
|
{
|
|
nanoseconds = -nanoseconds;
|
|
}
|
|
write_timestamp(seconds, nanoseconds);
|
|
}
|
|
else
|
|
{
|
|
write_timestamp(0, 0);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if (val <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
|
|
{
|
|
// positive fixnum stores 7-bit positive integer
|
|
sink_.push_back(static_cast<uint8_t>(val));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint8_t>::max)())
|
|
{
|
|
// uint 8 stores a 8-bit unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type);
|
|
sink_.push_back(static_cast<uint8_t>(val));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint16_t>::max)())
|
|
{
|
|
// uint 16 stores a 16-bit big-endian unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type);
|
|
binary::native_to_big(static_cast<uint16_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint32_t>::max)())
|
|
{
|
|
// uint 32 stores a 32-bit big-endian unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type);
|
|
binary::native_to_big(static_cast<uint32_t>(val),std::back_inserter(sink_));
|
|
}
|
|
else if (val <= (std::numeric_limits<uint64_t>::max)())
|
|
{
|
|
// uint 64 stores a 64-bit big-endian unsigned integer
|
|
sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type);
|
|
binary::native_to_big(static_cast<uint64_t>(val),std::back_inserter(sink_));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) override
|
|
{
|
|
// true and false
|
|
sink_.push_back(static_cast<uint8_t>(val ? jsoncons::msgpack::msgpack_type::true_type : jsoncons::msgpack::msgpack_type::false_type));
|
|
|
|
end_value();
|
|
return true;
|
|
}
|
|
|
|
void end_value()
|
|
{
|
|
if (!stack_.empty())
|
|
{
|
|
++stack_.back().count_;
|
|
}
|
|
}
|
|
};
|
|
|
|
using msgpack_stream_encoder = basic_msgpack_encoder<jsoncons::binary_stream_sink>;
|
|
using msgpack_bytes_encoder = basic_msgpack_encoder<jsoncons::bytes_sink<std::vector<uint8_t>>>;
|
|
|
|
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_encoder") typedef msgpack_bytes_encoder msgpack_bytes_serializer;
|
|
|
|
template<class Sink=jsoncons::binary_stream_sink>
|
|
using basic_msgpack_serializer = basic_msgpack_encoder<Sink>;
|
|
|
|
JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_encoder") typedef msgpack_stream_encoder msgpack_encoder;
|
|
JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_encoder") typedef msgpack_stream_encoder msgpack_serializer;
|
|
JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_encoder") typedef msgpack_bytes_encoder msgpack_buffer_serializer;
|
|
#endif
|
|
|
|
} // namespace msgpack
|
|
} // namespace jsoncons
|
|
|
|
#endif
|