gnucash unstable: Revert "Partial fix to exception crashes on Windows."

John Ralls jralls at code.gnucash.org
Thu Oct 26 16:44:06 EDT 2017


Updated	 via  https://github.com/Gnucash/gnucash/commit/4be82605 (commit)
	from  https://github.com/Gnucash/gnucash/commit/a3003043 (commit)



commit 4be826055aa9b3255d7c6fcadadfa0468be758e0
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Oct 26 13:08:36 2017 -0700

    Revert "Partial fix to exception crashes on Windows."
    
    This reverts commit 47460546355baaf511940d2cdc9367465e239470.
    a300384 is the correct fix for this problem.

diff --git a/libgnucash/engine/gnc-numeric.cpp b/libgnucash/engine/gnc-numeric.cpp
index 6bbc212..0fc47d5 100644
--- a/libgnucash/engine/gnc-numeric.cpp
+++ b/libgnucash/engine/gnc-numeric.cpp
@@ -85,13 +85,9 @@ GncNumeric::GncNumeric(double d) : m_num(0), m_den(1)
     static uint64_t max_leg_value{INT64_C(1000000000000000000)};
     if (std::isnan(d) || fabs(d) > max_leg_value)
     {
-#ifdef __MINGW32__
-	throw std::invalid_argument("Bad double");
-#else
-	std::ostringstream msg;
+        std::ostringstream msg;
         msg << "Unable to construct a GncNumeric from " << d << ".\n";
         throw std::invalid_argument(msg.str());
-#endif
     }
     constexpr auto max_num = static_cast<double>(INT64_MAX);
     auto logval = log10(fabs(d));
@@ -121,83 +117,6 @@ GncNumeric::GncNumeric(double d) : m_num(0), m_den(1)
 using boost::regex;
 using boost::smatch;
 using boost::regex_search;
-
-static bool
-string_regex (const std::string& str, const regex& expr,
-	      std::string& first, std::string& second)
-{
-    smatch m;
-    if (regex_search(str, m, expr))
-    {
-	first = m[1].str();
-	second = m[2].str();
-	return true;
-    }
-    return false;
-}
-
-static bool
-string_regex (const std::string& str, const regex& expr, std::string& string)
-{
-    smatch m;
-    if (regex_search(str, m, expr))
-    {
-	string = m[1].str();
-	return true;
-    }
-    return false;
-}
-
-
-static bool
-numeric_regex (const std::string& str, const regex& expr,
-	       int64_t& num, int64_t& denom, int base1, int base2)
-{
-    std::string first, second;
-    if (string_regex(str, expr, first, second))
-    {
-	num = stoll(first, nullptr, base1);
-	denom = stoll(second, nullptr, base2);
-	return true;
-    }
-    return false;
-}
-
-numeric_regex (const std::string& str, const regex& expr, int64_t& num,
-	       int base)
-{
-    std::string result;
-    if (string_regex(str, expr, result))
-    {
-	num = stoll(result, nullptr, base);
-	return true;
-    }
-    return false;
-}
-
-static bool
-numeric_regex (const std::string& str, const regex& expr,
-	       GncInt128& num, int64_t& den)
-{
-    std::string first, second;
-    if (string_regex(str, expr, first, second))
-    {
-	GncInt128 high(stoll(first));
-	GncInt128 low(stoll(second));
-	den = powten(second.length());
-	num = high * den + (high > 0 ? low : -low);
-	return true;
-    }
-    return false;
-}
-
-static void
-check_for_zero_denom (int64_t denom)
-{
-    if (denom == 0)
-	throw std::invalid_argument("GncNumeric denominator can't be 0.");
-}
-
 GncNumeric::GncNumeric(const std::string& str, bool autoround)
 {
     static const std::string numer_frag("(-?[0-9]+)");
@@ -215,70 +134,91 @@ GncNumeric::GncNumeric(const std::string& str, bool autoround)
     static const regex hex_over_num(hex_frag + slash + denom_frag);
     static const regex num_over_hex(numer_frag + slash + hex_frag);
     static const regex decimal(numer_frag + "[.,]" + denom_frag);
+    smatch m;
 /* The order of testing the regexes is from the more restrictve to the less
  * restrictive, as less-restrictive ones will match patterns that would also
  * match the more-restrictive and so invoke the wrong construction.
  */
     if (str.empty())
         throw std::invalid_argument("Can't construct a GncNumeric from an empty string.");
-    if (numeric_regex(str, hex_rational, m_num, m_den, 16, 16) ||
-	numeric_regex(str, hex_over_num, m_num, m_den, 16, 10) ||
-	numeric_regex(str, num_over_hex, m_num, m_den, 10, 16) ||
-	numeric_regex(str, numeral_rational, m_num, m_den, 10, 10))
+    if (regex_search(str, m, hex_rational))
+    {
+        GncNumeric n(stoll(m[1].str(), nullptr, 16),
+                     stoll(m[2].str(), nullptr, 16));
+        m_num = n.num();
+        m_den = n.denom();
+        return;
+    }
+    if (regex_search(str, m, hex_over_num))
     {
-	check_for_zero_denom(m_den);
-	return;
+        GncNumeric n(stoll(m[1].str(), nullptr, 16),
+                     stoll(m[2].str()));
+        m_num = n.num();
+        m_den = n.denom();
+        return;
+    }
+    if (regex_search(str, m, num_over_hex))
+    {
+        GncNumeric n(stoll(m[1].str()),
+                     stoll(m[2].str(), nullptr, 16));
+        m_num = n.num();
+        m_den = n.denom();
+        return;
     }
-    GncInt128 n;
-    int64_t d;
-    if (numeric_regex(str, decimal, n, d))
+    if (regex_search(str, m, numeral_rational))
     {
+        GncNumeric n(stoll(m[1].str()), stoll(m[2].str()));
+        m_num = n.num();
+        m_den = n.denom();
+        return;
+    }
+    if (regex_search(str, m, decimal))
+    {
+        GncInt128 high(stoll(m[1].str()));
+        GncInt128 low(stoll(m[2].str()));
+        int64_t d = powten(m[2].str().length());
+        GncInt128 n = high * d + (high > 0 ? low : -low);
         if (!autoround && n.isBig())
         {
-#ifdef __MINGW32__
-	    throw std::overflow_error("String overflowed, rounding.");
-#else
-	    std::ostringstream errmsg;
-            errmsg << "Decimal string " << str
-                   << " can't be represented in a GncNumeric without rounding.";
+            std::ostringstream errmsg;
+            errmsg << "Decimal string " << m[1].str() << "." << m[2].str()
+                   << "can't be represented in a GncNumeric without rounding.";
             throw std::overflow_error(errmsg.str());
-#endif
-
         }
         while (n.isBig() && d > 0)
         {
             n >>= 1;
             d >>= 1;
         }
-        if (d == 0 || n.isBig()) //Shouldn't happen, of course
+        if (n.isBig()) //Shouldn't happen, of course
         {
-	    d = d ? d : 1;
-#ifdef __MINGW32__
-	    throw std::overflow_error("String overflowed, reducing.");
-#else
             std::ostringstream errmsg;
-            errmsg << "Decimal string " << str
+            errmsg << "Decimal string " << m[1].str() << "." << m[2].str()
             << " can't be represented in a GncNumeric, even after reducing denom to " << d;
             throw std::overflow_error(errmsg.str());
-#endif
         }
-        m_num = static_cast<int64_t>(n);
-	m_den = d;
-	return;
+        GncNumeric gncn(static_cast<int64_t>(n), d);
+        m_num = gncn.num();
+        m_den = gncn.denom();
+        return;
     }
-    if (numeric_regex(str, hex, m_num, 16) ||
-	numeric_regex(str, numeral, m_num, 10))
+    if (regex_search(str, m, hex))
     {
-        m_den = 1;
+        GncNumeric n(stoll(m[1].str(), nullptr, 16),INT64_C(1));
+        m_num = n.num();
+        m_den = n.denom();
+        return;
+    }
+    if (regex_search(str, m, numeral))
+    {
+        GncNumeric n(stoll(m[1].str()), INT64_C(1));
+        m_num = n.num();
+        m_den = n.denom();
         return;
     }
-#ifdef __MINGW32__
-    throw std::invalid_argument("No numeric.");
-#else
     std::ostringstream errmsg;
     errmsg << "String " << str << " contains no recognizable numeric value.";
     throw std::invalid_argument(errmsg.str());
-#endif
 }
 
 GncNumeric::operator gnc_numeric() const noexcept
@@ -403,15 +343,11 @@ GncNumeric::to_decimal(unsigned int max_places) const
         auto excess = m_den / powten(max_places);
         if (m_num % excess)
         {
-#ifdef __MINGW32__
-	    throw std::range_error("Number couldn't be reprensented without rounding");
-#else
             std::ostringstream msg;
             msg << "GncNumeric " << *this
                 << " could not be represented in " << max_places
                 << " decimal places without rounding.\n";
             throw std::range_error(msg.str());
-#endif
         }
         return GncNumeric(m_num / excess, powten(max_places));
     }
@@ -442,25 +378,17 @@ GncNumeric::to_decimal(unsigned int max_places) const
     }
     catch (const std::invalid_argument& err)
     {
-#ifdef __MINGW32__
-	throw std::range_error("Number couldn't be represented without rounding");
-#else
         std::ostringstream msg;
         msg << "GncNumeric " << *this
             << " could not be represented as a decimal without rounding.\n";
         throw std::range_error(msg.str());
-#endif
     }
     catch (const std::overflow_error& err)
     {
-#ifdef __MINGW32__
-	throw std::range_error("Number overflows as a decimal.");
-#else
         std::ostringstream msg;
         msg << "GncNumeric " << *this
             << " overflows when attempting to convert it to decimal.\n";
         throw std::range_error(msg.str());
-#endif
     }
 }
 



Summary of changes:
 libgnucash/engine/gnc-numeric.cpp | 184 ++++++++++++--------------------------
 1 file changed, 56 insertions(+), 128 deletions(-)



More information about the gnucash-changes mailing list