From 04aab7cea3bc8ea47931dde98611668980ec4f65 Mon Sep 17 00:00:00 2001 From: Craig Date: Sat, 24 Aug 2019 05:45:31 +0200 Subject: [PATCH] Correctly parse decimals between 0 and -1. The negative sign was being lost because stoll("-0") is 0. Also permits parsing decimals between -1 and 1 without the leading 0. --- libgnucash/engine/gnc-numeric.cpp | 9 ++++++--- libgnucash/engine/test/gtest-gnc-numeric.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libgnucash/engine/gnc-numeric.cpp b/libgnucash/engine/gnc-numeric.cpp index a2cbf6d1c8..4e4250fdbc 100644 --- a/libgnucash/engine/gnc-numeric.cpp +++ b/libgnucash/engine/gnc-numeric.cpp @@ -120,7 +120,7 @@ using boost::smatch; using boost::regex_search; GncNumeric::GncNumeric(const std::string& str, bool autoround) { - static const std::string numer_frag("(-?[0-9]+)"); + static const std::string numer_frag("(-?[0-9]*)"); static const std::string denom_frag("([0-9]+)"); static const std::string hex_frag("(0x[a-f0-9]+)"); static const std::string slash( "[ \\t]*/[ \\t]*"); @@ -175,10 +175,13 @@ GncNumeric::GncNumeric(const std::string& str, bool autoround) } if (regex_search(str, m, decimal)) { - GncInt128 high(stoll(m[1].str())); + auto neg = (m[1].length() && m[1].str()[0] == '-'); + GncInt128 high((neg && m[1].length() > 1) || (!neg && m[1].length()) ? + stoll(m[1].str()) : 0); GncInt128 low(stoll(m[2].str())); int64_t d = powten(m[2].str().length()); - GncInt128 n = high * d + (high >= 0 ? low : -low); + GncInt128 n = high * d + (neg ? -low : low); + if (!autoround && n.isBig()) { std::ostringstream errmsg; diff --git a/libgnucash/engine/test/gtest-gnc-numeric.cpp b/libgnucash/engine/test/gtest-gnc-numeric.cpp index 680b6d82d9..5cbe5c724a 100644 --- a/libgnucash/engine/test/gtest-gnc-numeric.cpp +++ b/libgnucash/engine/test/gtest-gnc-numeric.cpp @@ -179,6 +179,12 @@ TEST(gncnumeric_constructors, test_string_constructor) std::out_of_range); EXPECT_THROW(GncNumeric bad_string("Four score and seven"), std::invalid_argument); + GncNumeric neg_decimal_frac("-0.12345"); + EXPECT_EQ(-12345, neg_decimal_frac.num()); + EXPECT_EQ(100000, neg_decimal_frac.denom()); + GncNumeric neg_decimal_frac_nozero("-.12345"); + EXPECT_EQ(-12345, neg_decimal_frac_nozero.num()); + EXPECT_EQ(100000, neg_decimal_frac_nozero.denom()); } TEST(gncnumeric_output, string_output)