Convert::ToString(double): handle integral values too large for long long correctly

Even if a double represents an integer value, it might not be safe to cast it
to long long as it may overflow the type. Instead just use print the double
value with 0 decimals using std::setprecision.

Before:

    <1> => 18446744073709551616.to_string()
    "-9223372036854775808"

After:

    <1> => 18446744073709551616.to_string()
    "18446744073709551616"
This commit is contained in:
Julian Brost 2021-04-27 17:24:03 +02:00
parent 17c8e7a1f7
commit 2d6d87d10f
2 changed files with 6 additions and 3 deletions

View File

@ -3,6 +3,7 @@
#include "base/convert.hpp"
#include "base/datetime.hpp"
#include <boost/lexical_cast.hpp>
#include <iomanip>
using namespace icinga;
@ -21,10 +22,10 @@ String Convert::ToString(double val)
double integral;
double fractional = std::modf(val, &integral);
if (fractional == 0)
return Convert::ToString(static_cast<long long>(val));
std::ostringstream msgbuf;
if (fractional == 0) {
msgbuf << std::setprecision(0);
}
msgbuf << std::fixed << val;
return msgbuf.str();
}

View File

@ -33,12 +33,14 @@ BOOST_AUTO_TEST_CASE(tostring)
BOOST_CHECK(Convert::ToString(7) == "7");
BOOST_CHECK(Convert::ToString(7.5) == "7.500000");
BOOST_CHECK(Convert::ToString("hello") == "hello");
BOOST_CHECK(Convert::ToString(18446744073709551616.0) == "18446744073709551616"); // pow(2, 64)
String str = "hello";
BOOST_CHECK(Convert::ToString(str) == "hello");
BOOST_CHECK(Convert::ToString(Value(7)) == "7");
BOOST_CHECK(Convert::ToString(Value(7.5)) == "7.500000");
BOOST_CHECK(Convert::ToString(Value(18446744073709551616.0)) == "18446744073709551616"); // pow(2, 64)
BOOST_CHECK(Convert::ToString(Value("hello")) == "hello");
BOOST_CHECK(Convert::ToString(Value("hello hello")) == "hello hello");
}