Skip to content

Commit 80633d7

Browse files
Add packing functions for fixed float and double types
1 parent a0b2ec0 commit 80633d7

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

include/msgpack/v1/pack.hpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,28 @@ class packer {
257257
*/
258258
packer<Stream>& pack_fix_int64(int64_t d);
259259

260+
/// Packing float (fixed packed type).
261+
/**
262+
* The packed type is always float32.
263+
* See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float
264+
*
265+
* @param d a packing object.
266+
*
267+
* @return The reference of `*this`.
268+
*/
269+
packer<Stream>& pack_fix_float(float d);
270+
271+
/// Packing double (fixed packed type).
272+
/**
273+
* The packed type is always float64.
274+
* See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float
275+
*
276+
* @param d a packing object.
277+
*
278+
* @return The reference of `*this`.
279+
*/
280+
packer<Stream>& pack_fix_double(double d);
281+
260282

261283
/// Packing char
262284
/**
@@ -827,6 +849,36 @@ inline packer<Stream>& packer<Stream>::pack_fix_int64(int64_t d)
827849
return *this;
828850
}
829851

852+
template <typename Stream>
853+
inline packer<Stream>& packer<Stream>::pack_fix_float(float d)
854+
{
855+
union { float f; uint32_t i; } mem;
856+
mem.f = d;
857+
char buf[5];
858+
buf[0] = static_cast<char>(0xcau); _msgpack_store32(&buf[1], mem.i);
859+
append_buffer(buf, 5);
860+
return *this;
861+
}
862+
863+
template <typename Stream>
864+
inline packer<Stream>& packer<Stream>::pack_fix_double(double d)
865+
{
866+
union { double f; uint64_t i; } mem;
867+
mem.f = d;
868+
char buf[9];
869+
buf[0] = static_cast<char>(0xcbu);
870+
871+
#if defined(TARGET_OS_IPHONE)
872+
// ok
873+
#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
874+
// https://github.com/msgpack/msgpack-perl/pull/1
875+
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
876+
#endif
877+
_msgpack_store64(&buf[1], mem.i);
878+
append_buffer(buf, 9);
879+
return *this;
880+
}
881+
830882

831883
template <typename Stream>
832884
inline packer<Stream>& packer<Stream>::pack_char(char d)

test/msgpack_basic.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,49 @@ BOOST_AUTO_TEST_CASE(simple_buffer_float)
189189
}
190190
}
191191

192+
BOOST_AUTO_TEST_CASE(simple_buffer_pack_fix_float)
193+
{
194+
vector<float> v;
195+
v.push_back(0.0);
196+
v.push_back(-0.0);
197+
v.push_back(1.0);
198+
v.push_back(-1.0);
199+
v.push_back(numeric_limits<float>::min());
200+
v.push_back(numeric_limits<float>::max());
201+
v.push_back(nanf("tag"));
202+
if (numeric_limits<float>::has_infinity) {
203+
v.push_back(numeric_limits<float>::infinity());
204+
v.push_back(-numeric_limits<float>::infinity());
205+
}
206+
if (numeric_limits<float>::has_quiet_NaN) {
207+
v.push_back(numeric_limits<float>::quiet_NaN());
208+
}
209+
if (numeric_limits<float>::has_signaling_NaN) {
210+
v.push_back(numeric_limits<float>::signaling_NaN());
211+
}
212+
213+
for (unsigned int i = 0; i < kLoop; i++) {
214+
v.push_back(static_cast<float>(msgpack_rand()));
215+
v.push_back(static_cast<float>(-msgpack_rand()));
216+
}
217+
for (unsigned int i = 0; i < v.size() ; i++) {
218+
msgpack::sbuffer sbuf;
219+
msgpack::packer<msgpack::sbuffer> packer(sbuf);
220+
float val1 = v[i];
221+
packer.pack_fix_float(val1);
222+
msgpack::object_handle oh =
223+
msgpack::unpack(sbuf.data(), sbuf.size());
224+
float val2 = oh.get().as<float>();
225+
226+
if (std::isnan(val1))
227+
BOOST_CHECK(std::isnan(val2));
228+
else if (std::isinf(val1))
229+
BOOST_CHECK(std::isinf(val2));
230+
else
231+
BOOST_CHECK(fabs(val2 - val1) <= kEPS);
232+
}
233+
}
234+
192235
#endif // !defined(_MSC_VER) || _MSC_VER >=1800
193236

194237
namespace {
@@ -275,6 +318,53 @@ BOOST_AUTO_TEST_CASE(simple_buffer_double)
275318
}
276319
}
277320

321+
BOOST_AUTO_TEST_CASE(simple_buffer_pack_fix_double)
322+
{
323+
vector<double> v;
324+
v.push_back(0.0);
325+
v.push_back(-0.0);
326+
v.push_back(1.0);
327+
v.push_back(-1.0);
328+
v.push_back(numeric_limits<double>::min());
329+
v.push_back(numeric_limits<double>::max());
330+
v.push_back(nanf("tag"));
331+
if (numeric_limits<double>::has_infinity) {
332+
v.push_back(numeric_limits<double>::infinity());
333+
v.push_back(-numeric_limits<double>::infinity());
334+
}
335+
if (numeric_limits<double>::has_quiet_NaN) {
336+
v.push_back(numeric_limits<double>::quiet_NaN());
337+
}
338+
if (numeric_limits<double>::has_signaling_NaN) {
339+
v.push_back(numeric_limits<double>::signaling_NaN());
340+
}
341+
for (unsigned int i = 0; i < kLoop; i++) {
342+
v.push_back(msgpack_rand());
343+
v.push_back(-msgpack_rand());
344+
}
345+
346+
for (unsigned int i = 0; i < kLoop; i++) {
347+
v.push_back(msgpack_rand());
348+
v.push_back(-msgpack_rand());
349+
}
350+
for (unsigned int i = 0; i < v.size() ; i++) {
351+
msgpack::sbuffer sbuf;
352+
msgpack::packer<msgpack::sbuffer> packer(sbuf);
353+
double val1 = v[i];
354+
packer.pack_fix_double(val1);
355+
msgpack::object_handle oh =
356+
msgpack::unpack(sbuf.data(), sbuf.size());
357+
double val2 = oh.get().as<double>();
358+
359+
if (std::isnan(val1))
360+
BOOST_CHECK(std::isnan(val2));
361+
else if (std::isinf(val1))
362+
BOOST_CHECK(std::isinf(val2));
363+
else
364+
BOOST_CHECK(fabs(val2 - val1) <= kEPS);
365+
}
366+
}
367+
278368
#endif // !defined(_MSC_VER) || _MSC_VER >=1800
279369

280370
BOOST_AUTO_TEST_CASE(simple_buffer_nil)

0 commit comments

Comments
 (0)