Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions include/msgpack/v1/pack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,28 @@ class packer {
*/
packer<Stream>& pack_fix_int64(int64_t d);

/// Packing float (fixed packed type).
/**
* The packed type is always float32.
* See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float
*
* @param d a packing object.
*
* @return The reference of `*this`.
*/
packer<Stream>& pack_fix_float(float d);

/// Packing double (fixed packed type).
/**
* The packed type is always float64.
* See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float
*
* @param d a packing object.
*
* @return The reference of `*this`.
*/
packer<Stream>& pack_fix_double(double d);


/// Packing char
/**
Expand Down Expand Up @@ -827,6 +849,36 @@ inline packer<Stream>& packer<Stream>::pack_fix_int64(int64_t d)
return *this;
}

template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_fix_float(float d)
{
union { float f; uint32_t i; } mem;
mem.f = d;
char buf[5];
buf[0] = static_cast<char>(0xcau); _msgpack_store32(&buf[1], mem.i);
append_buffer(buf, 5);
return *this;
}

template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_fix_double(double d)
{
union { double f; uint64_t i; } mem;
mem.f = d;
char buf[9];
buf[0] = static_cast<char>(0xcbu);

#if defined(TARGET_OS_IPHONE)
// ok
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
// https://github.com/msgpack/msgpack-perl/pull/1
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
#endif
_msgpack_store64(&buf[1], mem.i);
append_buffer(buf, 9);
return *this;
}


template <typename Stream>
inline packer<Stream>& packer<Stream>::pack_char(char d)
Expand Down
90 changes: 90 additions & 0 deletions test/msgpack_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,49 @@ BOOST_AUTO_TEST_CASE(simple_buffer_float)
}
}

BOOST_AUTO_TEST_CASE(simple_buffer_pack_fix_float)
{
vector<float> v;
v.push_back(0.0);
v.push_back(-0.0);
v.push_back(1.0);
v.push_back(-1.0);
v.push_back(numeric_limits<float>::min());
v.push_back(numeric_limits<float>::max());
v.push_back(nanf("tag"));
if (numeric_limits<float>::has_infinity) {
v.push_back(numeric_limits<float>::infinity());
v.push_back(-numeric_limits<float>::infinity());
}
if (numeric_limits<float>::has_quiet_NaN) {
v.push_back(numeric_limits<float>::quiet_NaN());
}
if (numeric_limits<float>::has_signaling_NaN) {
v.push_back(numeric_limits<float>::signaling_NaN());
}

for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(static_cast<float>(msgpack_rand()));
v.push_back(static_cast<float>(-msgpack_rand()));
}
for (unsigned int i = 0; i < v.size() ; i++) {
msgpack::sbuffer sbuf;
msgpack::packer<msgpack::sbuffer> packer(sbuf);
float val1 = v[i];
packer.pack_fix_float(val1);
msgpack::object_handle oh =
msgpack::unpack(sbuf.data(), sbuf.size());
float val2 = oh.get().as<float>();

if (std::isnan(val1))
BOOST_CHECK(std::isnan(val2));
else if (std::isinf(val1))
BOOST_CHECK(std::isinf(val2));
else
BOOST_CHECK(fabs(val2 - val1) <= kEPS);
}
}

#endif // !defined(_MSC_VER) || _MSC_VER >=1800

namespace {
Expand Down Expand Up @@ -275,6 +318,53 @@ BOOST_AUTO_TEST_CASE(simple_buffer_double)
}
}

BOOST_AUTO_TEST_CASE(simple_buffer_pack_fix_double)
{
vector<double> v;
v.push_back(0.0);
v.push_back(-0.0);
v.push_back(1.0);
v.push_back(-1.0);
v.push_back(numeric_limits<double>::min());
v.push_back(numeric_limits<double>::max());
v.push_back(nanf("tag"));
if (numeric_limits<double>::has_infinity) {
v.push_back(numeric_limits<double>::infinity());
v.push_back(-numeric_limits<double>::infinity());
}
if (numeric_limits<double>::has_quiet_NaN) {
v.push_back(numeric_limits<double>::quiet_NaN());
}
if (numeric_limits<double>::has_signaling_NaN) {
v.push_back(numeric_limits<double>::signaling_NaN());
}
for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(msgpack_rand());
v.push_back(-msgpack_rand());
}

for (unsigned int i = 0; i < kLoop; i++) {
v.push_back(msgpack_rand());
v.push_back(-msgpack_rand());
}
for (unsigned int i = 0; i < v.size() ; i++) {
msgpack::sbuffer sbuf;
msgpack::packer<msgpack::sbuffer> packer(sbuf);
double val1 = v[i];
packer.pack_fix_double(val1);
msgpack::object_handle oh =
msgpack::unpack(sbuf.data(), sbuf.size());
double val2 = oh.get().as<double>();

if (std::isnan(val1))
BOOST_CHECK(std::isnan(val2));
else if (std::isinf(val1))
BOOST_CHECK(std::isinf(val2));
else
BOOST_CHECK(fabs(val2 - val1) <= kEPS);
}
}

#endif // !defined(_MSC_VER) || _MSC_VER >=1800

BOOST_AUTO_TEST_CASE(simple_buffer_nil)
Expand Down
Loading