From cd04e805e338aeed72195ce2fdbf4c003734a2a1 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Sun, 18 Nov 2018 17:23:14 +0100 Subject: [PATCH] Bug 796919 - Leading '+' character not accepted in amount when value surrounded by quotes Use a variant of xaccParseAmount that allows to ignore the locale's positive_sign character or the + sign if locale doesn't define a positive_sign character. In a future redesign it would probably be better to replace use of xaccParseAmount with some variant of the gnc-expression-parser but that would require more that a few tweaks to get right. --- .../csv-imp/gnc-imp-props-price.cpp | 2 +- .../csv-imp/gnc-imp-props-tx.cpp | 2 +- libgnucash/app-utils/gnc-ui-util.c | 21 ++++++++++++++++++- libgnucash/app-utils/gnc-ui-util.h | 13 ++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-price.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-price.cpp index c989ae8bae..874d218baa 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-price.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-price.cpp @@ -72,7 +72,7 @@ GncNumeric parse_amount_price (const std::string &str, int currency_format) { case 0: /* Currency locale */ - if (!(xaccParseAmount (str_no_symbols.c_str(), TRUE, &val, &endptr))) + if (!(xaccParseAmountPosSign (str_no_symbols.c_str(), TRUE, &val, &endptr, TRUE))) throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format.")); break; case 1: diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp index 7e0a35f8ad..25ec7b7ac1 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp @@ -120,7 +120,7 @@ GncNumeric parse_amount (const std::string &str, int currency_format) { case 0: /* Currency locale */ - if (!(xaccParseAmount (str_no_symbols.c_str(), TRUE, &val, &endptr))) + if (!(xaccParseAmountPosSign (str_no_symbols.c_str(), TRUE, &val, &endptr, TRUE))) throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format.")); break; case 1: diff --git a/libgnucash/app-utils/gnc-ui-util.c b/libgnucash/app-utils/gnc-ui-util.c index 8936fa460a..1c5f78dc0f 100644 --- a/libgnucash/app-utils/gnc-ui-util.c +++ b/libgnucash/app-utils/gnc-ui-util.c @@ -1985,12 +1985,21 @@ multiplier (int num_decimals) gboolean xaccParseAmount (const char * in_str, gboolean monetary, gnc_numeric *result, char **endstr) +{ + return xaccParseAmountPosSign (in_str, monetary, result, endstr, FALSE); +} + +gboolean +xaccParseAmountPosSign (const char * in_str, gboolean monetary, gnc_numeric *result, + char **endstr, gboolean skip) { struct lconv *lc = gnc_localeconv(); gunichar negative_sign; gunichar decimal_point; gunichar group_separator; + gchar *ignore = NULL; + char *plus_sign = "+"; char *group; negative_sign = g_utf8_get_char(lc->negative_sign); @@ -2007,8 +2016,18 @@ xaccParseAmount (const char * in_str, gboolean monetary, gnc_numeric *result, group = lc->grouping; } + if (skip) + { + /* We want the locale's positive sign to be ignored. + * If the locale doesn't specify one, we assume "+" as + * an optional positive sign and ignore that */ + ignore = lc->positive_sign; + if (!ignore || !*ignore) + ignore = plus_sign; + } + return xaccParseAmountExtended(in_str, monetary, negative_sign, decimal_point, - group_separator, group, NULL, result, endstr); + group_separator, group, ignore, result, endstr); } /* Note: xaccParseAmountExtended causes test-print-parse-amount diff --git a/libgnucash/app-utils/gnc-ui-util.h b/libgnucash/app-utils/gnc-ui-util.h index 884bdc6214..03e889358c 100644 --- a/libgnucash/app-utils/gnc-ui-util.h +++ b/libgnucash/app-utils/gnc-ui-util.h @@ -321,6 +321,19 @@ gchar *numeric_to_words(gnc_numeric val); gboolean xaccParseAmount (const char * in_str, gboolean monetary, gnc_numeric *result, char **endstr); +/* + * xaccParseAmountPosSign is just like xaccParseAmount except the + * caller can choose whether the locale's postive sign (or in absense + * the '+') character is ignored. Setting skip to TRUE will cause + * the function to ignore any positive sign. Setting it to FALSE, + * and positive signs will be treated as unrecognized characters. + * xaccParseAmount will run as if skip is FALSE for compatibility + * reasons (gnc-expression-parser depends on this behaviour). + */ +gboolean +xaccParseAmountPosSign (const char * in_str, gboolean monetary, gnc_numeric *result, + char **endstr, gboolean skip); + /* * xaccParseAmountExtended is just like xaccParseAmount except the * caller must provide all the locale-specific information.