diff --git a/libgnucash/backend/dbi/gnc-backend-dbi.cpp b/libgnucash/backend/dbi/gnc-backend-dbi.cpp index 68b893379a..4017066117 100644 --- a/libgnucash/backend/dbi/gnc-backend-dbi.cpp +++ b/libgnucash/backend/dbi/gnc-backend-dbi.cpp @@ -1177,7 +1177,7 @@ dbi_library_test (dbi_conn conn) return GNC_DBI_FAIL_SETUP; } dbi_result_free (result); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); result = dbi_conn_query (conn, "SELECT * FROM numtest"); if (result == nullptr) { @@ -1186,7 +1186,7 @@ dbi_library_test (dbi_conn conn) PWARN ("Test_DBI_Library: Failed to retrieve test row into table: %s", errmsg); dbi_conn_query (conn, "DROP TABLE numtest"); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return GNC_DBI_FAIL_SETUP; } while (dbi_result_next_row (result)) @@ -1196,7 +1196,7 @@ dbi_library_test (dbi_conn conn) resultdouble = dbi_result_get_double (result, "test_double"); } dbi_conn_query (conn, "DROP TABLE numtest"); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); if (testlonglong != resultlonglong) { PWARN ("Test_DBI_Library: LongLong Failed %" PRId64 " != % " PRId64, diff --git a/libgnucash/backend/dbi/gnc-backend-dbi.hpp b/libgnucash/backend/dbi/gnc-backend-dbi.hpp index 5d027324b2..07b92e68bf 100644 --- a/libgnucash/backend/dbi/gnc-backend-dbi.hpp +++ b/libgnucash/backend/dbi/gnc-backend-dbi.hpp @@ -118,6 +118,21 @@ private: bool m_exists; // Does the database exist? }; +/* locale-stack */ +inline std::string +gnc_push_locale(const int category, const std::string locale) +{ + std::string retval(setlocale(category, nullptr)); + setlocale(category, locale.c_str()); + return retval; +} + +inline void +gnc_pop_locale(const int category, std::string locale) +{ + setlocale(category, locale.c_str()); +} + /* external access required for tests */ std::string adjust_sql_options_string(const std::string&); diff --git a/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp b/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp index a4172f4a35..f24f6939b6 100644 --- a/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp +++ b/libgnucash/backend/dbi/gnc-dbisqlconnection.cpp @@ -252,7 +252,7 @@ GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt) dbi_result result; DEBUG ("SQL: %s\n", stmt->to_sql()); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); do { init_error (); @@ -261,7 +261,7 @@ GncDbiSqlConnection::execute_select_statement (const GncSqlStatementPtr& stmt) while (m_retry); if (result == nullptr) PERR ("Error executing SQL %s\n", stmt->to_sql()); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return GncSqlResultPtr(new GncDbiSqlResult (this, result)); } diff --git a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp index a686fa40a5..5b2a784e2a 100644 --- a/libgnucash/backend/dbi/gnc-dbisqlresult.cpp +++ b/libgnucash/backend/dbi/gnc-dbisqlresult.cpp @@ -117,9 +117,9 @@ GncDbiSqlResult::IteratorImpl::get_float_at_col(const char* col) const if(type != DBI_TYPE_DECIMAL || (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE4) throw (std::invalid_argument{"Requested float from non-float column."}); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); auto retval = dbi_result_get_float(m_inst->m_dbi_result, col); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return retval; } @@ -131,9 +131,9 @@ GncDbiSqlResult::IteratorImpl::get_double_at_col(const char* col) const if(type != DBI_TYPE_DECIMAL || (attrs & DBI_DECIMAL_SIZEMASK) != DBI_DECIMAL_SIZE8) throw (std::invalid_argument{"Requested double from non-double column."}); - gnc_push_locale (LC_NUMERIC, "C"); + auto locale = gnc_push_locale (LC_NUMERIC, "C"); auto retval = dbi_result_get_double(m_inst->m_dbi_result, col); - gnc_pop_locale (LC_NUMERIC); + gnc_pop_locale (LC_NUMERIC, locale); return retval; } @@ -160,7 +160,6 @@ GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const auto attrs = dbi_result_get_field_attribs (result, col); if (type != DBI_TYPE_DATETIME) throw (std::invalid_argument{"Requested time64 from non-time64 column."}); - gnc_push_locale (LC_NUMERIC, "C"); #if HAVE_LIBDBI_TO_LONGLONG /* A less evil hack than the one required by libdbi-0.8, but * still necessary to work around the same bug. @@ -179,7 +178,6 @@ GncDbiSqlResult::IteratorImpl::get_time64_at_col (const char* col) const #endif //HAVE_LIBDBI_TO_LONGLONG if (retval < MINTIME || retval > MAXTIME) retval = 0; - gnc_pop_locale (LC_NUMERIC); return retval; } diff --git a/libgnucash/core-utils/gnc-locale-utils.c b/libgnucash/core-utils/gnc-locale-utils.c index 94b1e1dc28..7af53593b6 100644 --- a/libgnucash/core-utils/gnc-locale-utils.c +++ b/libgnucash/core-utils/gnc-locale-utils.c @@ -150,43 +150,3 @@ gnc_locale_decimal_places (void) return places; } - - -static GList *locale_stack = NULL; - -void -gnc_push_locale (int category, const char *locale) -{ - char *saved_locale; - - g_return_if_fail (locale != NULL); - -# ifdef G_OS_WIN32 - /* On win32, setlocale() doesn't say anything useful. Use - glib's function instead. */ - saved_locale = g_win32_getlocale(); -# else - saved_locale = g_strdup(setlocale(category, NULL) ? - setlocale(category, NULL) : "C"); -#endif - locale_stack = g_list_prepend (locale_stack, saved_locale); - setlocale (category, locale); -} - -void -gnc_pop_locale (int category) -{ - char *saved_locale; - GList *node; - - g_return_if_fail (locale_stack != NULL); - - node = locale_stack; - saved_locale = node->data; - - setlocale (category, saved_locale); - - locale_stack = g_list_remove_link (locale_stack, node); - g_list_free_1 (node); - g_free (saved_locale); -} diff --git a/libgnucash/core-utils/gnc-locale-utils.h b/libgnucash/core-utils/gnc-locale-utils.h index 5dbe4b1fa8..5d9063865c 100644 --- a/libgnucash/core-utils/gnc-locale-utils.h +++ b/libgnucash/core-utils/gnc-locale-utils.h @@ -37,26 +37,4 @@ const char * gnc_locale_default_iso_currency_code (void); /* Returns the number of decimal place to print in the current locale */ int gnc_locale_decimal_places (void); -/** Temporarily change locale, pushing the old one onto a stack - * Currently, this has no effect on gnc_localeconv. i.e., after the - * first call to gnc_localeconv, subsequent calls will return the same - * information. - * - * WARNING: Be careful to maintain the correct nesting order of pushes - * or pops; otherwise, the localization results might be - * interesting. Note that the stack does not keep track of which - * category a locale was pushed from, so careless use will alse - * produce interesting results. - * - * @param category: The locale category (e.g. LC_ALL, LC_NUMERIC) to push onto - * @param locale: The new locale to set - */ -void gnc_push_locale (int category, const char *locale); - -/** Restore the last-pushed locale. - * @param category: The locale category to restore the locale to. - */ -void gnc_pop_locale (int category); - - #endif /* GNC_LOCALE_UTILS_H */