From 55389813a0f42fdf61f51a227e4dcb25c1bf5a80 Mon Sep 17 00:00:00 2001 From: Tuomo Kriikkula Date: Fri, 24 Nov 2023 16:01:53 +0200 Subject: [PATCH] Trim trailing zeros and nuls from C++ encoded floats --- include/umb/coding.hpp | 10 ++++++++-- tests/test_coding.cpp | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/include/umb/coding.hpp b/include/umb/coding.hpp index 2d44050..f2858b3 100644 --- a/include/umb/coding.hpp +++ b/include/umb/coding.hpp @@ -31,7 +31,7 @@ #include #include -#include +#include #include "umb/constants.hpp" @@ -506,7 +506,7 @@ encode_float(float f, std::string& out) { std::string str; // TODO: consider this precision. Does it even make sense? - constexpr auto pre = 64; + const auto pre = f > 0 ? std::numeric_limits::max_digits10 : 32; constexpr auto longest_float = std::numeric_limits::digits - std::numeric_limits::min_exponent; constexpr auto max_str = longest_float + 8; @@ -515,6 +515,12 @@ encode_float(float f, std::string& out) const auto [ptr, ec] = std::to_chars(str.data(), str.data() + str.size(), f, fmt, pre); if (ec == std::errc()) { + str.erase(str.find('\0')); + // If the string has trailing zeros, trim them. + if ((str.size() > 1) && (str.find('0') == (str.size() - 1))) + { + boost::algorithm::trim_right_if(str, boost::algorithm::is_any_of("0")); + } out = std::move(str); } else diff --git a/tests/test_coding.cpp b/tests/test_coding.cpp index 336446b..5298533 100644 --- a/tests/test_coding.cpp +++ b/tests/test_coding.cpp @@ -327,6 +327,24 @@ TEST_CASE("encode decode float fields") REQUIRE(jatm1.some_floatVAR() == doctest::Approx(jatm2.some_floatVAR())); CHECK(Float(jatm1.some_floatVAR()).AlmostEquals(Float(jatm2.some_floatVAR()))); CHECK_EQ(jatm1, jatm2); + + jatm1.set_some_floatVAR(-8553588573958e-27); + vec = jatm1.to_bytes(); + ok = jatm2.from_bytes(vec); + CHECK(ok); + + REQUIRE(jatm1.some_floatVAR() == doctest::Approx(jatm2.some_floatVAR())); + CHECK(Float(jatm1.some_floatVAR()).AlmostEquals(Float(jatm2.some_floatVAR()))); + CHECK_EQ(jatm1, jatm2); + + jatm1.set_some_floatVAR(-0.0); + vec = jatm1.to_bytes(); + ok = jatm2.from_bytes(vec); + CHECK(ok); + + REQUIRE(jatm1.some_floatVAR() == doctest::Approx(jatm2.some_floatVAR())); + CHECK(Float(jatm1.some_floatVAR()).AlmostEquals(Float(jatm2.some_floatVAR()))); + CHECK_EQ(jatm1, jatm2); } TEST_CASE("encode decode float inf/nan fields")