Skip to content

Commit

Permalink
Trim trailing zeros and nuls from C++ encoded floats
Browse files Browse the repository at this point in the history
  • Loading branch information
tuokri committed Nov 24, 2023
1 parent 695df6c commit 5538981
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
10 changes: 8 additions & 2 deletions include/umb/coding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <string>
#include <vector>

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>

#include "umb/constants.hpp"

Expand Down Expand Up @@ -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<float>::max_digits10 : 32;
constexpr auto longest_float = std::numeric_limits<float>::digits
- std::numeric_limits<float>::min_exponent;
constexpr auto max_str = longest_float + 8;
Expand All @@ -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
Expand Down
18 changes: 18 additions & 0 deletions tests/test_coding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down

0 comments on commit 5538981

Please sign in to comment.