Skip to content

Commit d13d933

Browse files
authored
Merge pull request msgpack#1018 from GeorgFritze/cpp_master
pack double and float more size efficient
2 parents 05f654f + 33ff3a4 commit d13d933

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

include/msgpack/v1/pack.hpp

+22
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,17 @@ inline packer<Stream>& packer<Stream>::pack_unsigned_long_long(unsigned long lon
11381138
template <typename Stream>
11391139
inline packer<Stream>& packer<Stream>::pack_float(float d)
11401140
{
1141+
if(d == d) { // check for nan
1142+
// compare d to limits to avoid undefined behaviour
1143+
if(d >= 0 && d <= float(std::numeric_limits<uint64_t>::max()) && d == float(uint64_t(d))) {
1144+
pack_imp_uint64(uint64_t(d));
1145+
return *this;
1146+
} else if(d < 0 && d >= float(std::numeric_limits<int64_t>::min()) && d == float(int64_t(d))) {
1147+
pack_imp_int64(int64_t(d));
1148+
return *this;
1149+
}
1150+
}
1151+
11411152
union { float f; uint32_t i; } mem;
11421153
mem.f = d;
11431154
char buf[5];
@@ -1149,6 +1160,17 @@ inline packer<Stream>& packer<Stream>::pack_float(float d)
11491160
template <typename Stream>
11501161
inline packer<Stream>& packer<Stream>::pack_double(double d)
11511162
{
1163+
if(d == d) { // check for nan
1164+
// compare d to limits to avoid undefined behaviour
1165+
if(d >= 0 && d <= double(std::numeric_limits<uint64_t>::max()) && d == double(uint64_t(d))) {
1166+
pack_imp_uint64(uint64_t(d));
1167+
return *this;
1168+
} else if(d < 0 && d >= double(std::numeric_limits<int64_t>::min()) && d == double(int64_t(d))) {
1169+
pack_imp_int64(int64_t(d));
1170+
return *this;
1171+
}
1172+
}
1173+
11521174
union { double f; uint64_t i; } mem;
11531175
mem.f = d;
11541176
char buf[9];

test/msgpack_basic.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ BOOST_AUTO_TEST_CASE(simple_buffer_float)
154154
v.push_back(-0.0);
155155
v.push_back(1.0);
156156
v.push_back(-1.0);
157+
v.push_back(1.1f);
158+
v.push_back(-1.1f);
157159
v.push_back(numeric_limits<float>::min());
158160
v.push_back(numeric_limits<float>::max());
159161
v.push_back(nanf("tag"));
@@ -186,6 +188,12 @@ BOOST_AUTO_TEST_CASE(simple_buffer_float)
186188
BOOST_CHECK(std::isinf(val2));
187189
else
188190
BOOST_CHECK(fabs(val2 - val1) <= kEPS);
191+
192+
// check for compact storing of float
193+
if (val1 == val1 && val1 >= float(std::numeric_limits<int64_t>::min()) && val1 <= float(std::numeric_limits<int64_t>::max()) && val1 == float(int64_t(val1)))
194+
BOOST_REQUIRE_EQUAL(sbuf.size(),1);
195+
else
196+
BOOST_REQUIRE_EQUAL(sbuf.data()[0],char(0xca));
189197
}
190198
}
191199

@@ -236,6 +244,8 @@ BOOST_AUTO_TEST_CASE(simple_buffer_double)
236244
v.push_back(-0.0);
237245
v.push_back(1.0);
238246
v.push_back(-1.0);
247+
v.push_back(1.1);
248+
v.push_back(-1.1);
239249
v.push_back(numeric_limits<double>::min());
240250
v.push_back(numeric_limits<double>::max());
241251
v.push_back(nanf("tag"));
@@ -272,6 +282,12 @@ BOOST_AUTO_TEST_CASE(simple_buffer_double)
272282
BOOST_CHECK(std::isinf(val2));
273283
else
274284
BOOST_CHECK(fabs(val2 - val1) <= kEPS);
285+
286+
// check for compact storing of double
287+
if (val1 == val1 && val1 >= double(std::numeric_limits<int64_t>::min()) && val1 <= double(std::numeric_limits<int64_t>::max()) && val1 == double(int64_t(val1)))
288+
BOOST_REQUIRE_EQUAL(sbuf.size(),1);
289+
else
290+
BOOST_REQUIRE_EQUAL(uint8_t(sbuf.data()[0]),uint8_t(0xcb));
275291
}
276292
}
277293

0 commit comments

Comments
 (0)