diff --git a/bindings/engine-common.i b/bindings/engine-common.i index 4d360f481e..b0397a479e 100644 --- a/bindings/engine-common.i +++ b/bindings/engine-common.i @@ -32,7 +32,6 @@ static const GncGUID * gncAccountGetGUID(Account *x) %typemap(newfree) TransList * "g_list_free($1);" %typemap(newfree) PriceList * "g_list_free($1);" %typemap(newfree) LotList * "g_list_free($1);" -%typemap(newfree) CommodityList * "g_list_free($1);" %typemap(freearg) AccountList * "g_list_free($1);" diff --git a/bindings/engine.i b/bindings/engine.i index 4b7adbafe7..c9970d943f 100644 --- a/bindings/engine.i +++ b/bindings/engine.i @@ -84,7 +84,7 @@ GLIST_HELPER_INOUT(LotList, SWIGTYPE_p_GNCLot); GLIST_HELPER_INOUT(AccountList, SWIGTYPE_p_Account); GLIST_HELPER_INOUT(PriceList, SWIGTYPE_p_GNCPrice); // TODO: free PriceList? -GLIST_HELPER_INOUT(CommodityList, SWIGTYPE_p_gnc_commodity); +VECTOR_HELPER_INOUT(CommVec, SWIGTYPE_p_gnc_commodity, gnc_commodity); VECTOR_HELPER_INOUT(SplitsVec, SWIGTYPE_p_Split, Split); VECTORREF_HELPER_INOUT(SplitsVec&, SWIGTYPE_p_Split, Split); VECTOR_HELPER_INOUT(AccountVec, SWIGTYPE_p_Account, Account); diff --git a/bindings/guile/gnc-optiondb.i b/bindings/guile/gnc-optiondb.i index 5e8a3df693..ec810d5fc0 100644 --- a/bindings/guile/gnc-optiondb.i +++ b/bindings/guile/gnc-optiondb.i @@ -64,6 +64,7 @@ namespace std { %begin %{ +#include #include #include #include @@ -1975,26 +1976,13 @@ gnc_register_multichoice_callback_option(GncOptionDBPtr& db, const char* key, const char* doc_string, const char *value) { - gnc_commodity* commodity{}; const auto book{qof_session_get_book(gnc_get_current_session())}; const auto commodity_table{gnc_commodity_table_get_table(book)}; - const auto namespaces{gnc_commodity_table_get_namespaces(commodity_table)}; - GncOption* rv = nullptr; - for (auto node = namespaces; node && commodity == nullptr; - node = g_list_next(node)) - { - commodity = gnc_commodity_table_lookup(commodity_table, - (const char*)(node->data), - value); - - if (commodity) - { - rv = gnc_make_commodity_option(section, name, key, doc_string, commodity); - break; - } - } - g_list_free (namespaces); - return rv; + for (const auto& name_space : gnc_commodity_table_get_namespaces(commodity_table)) + if (auto commodity = gnc_commodity_table_lookup (commodity_table, name_space.c_str(), + value)) + return gnc_make_commodity_option(section, name, key, doc_string, commodity); + return nullptr; } static GncOption* diff --git a/bindings/python/gnucash_core.py b/bindings/python/gnucash_core.py index 993ad8919b..27ee2897d5 100644 --- a/bindings/python/gnucash_core.py +++ b/bindings/python/gnucash_core.py @@ -791,6 +791,14 @@ class GncCommodityTable(GnuCashCoreClass): which includes most of the world's currencies. """ + def get_quotable_commodities (self): + print ("hello from get_quotable_commodities") + return + + def get_commodities(self): + print ("hello from get_commodities") + return + def _get_namespaces_py(self): return [ns.get_name() for ns in self.get_namespaces_list()] diff --git a/common/base-typemaps.i b/common/base-typemaps.i index 2a878a0122..0ecb449ff4 100644 --- a/common/base-typemaps.i +++ b/common/base-typemaps.i @@ -289,7 +289,7 @@ typedef char gchar; } } -%typemap(out) GList *, CommodityList *, SplitList *, AccountList *, LotList *, +%typemap(out) GList *, SplitList *, AccountList *, LotList *, MonetaryList *, PriceList *, EntryList * { gpointer data; GList *l; @@ -332,4 +332,45 @@ typedef char gchar; } $result = list; } + +%typemap(out) CommodityVec +{ + PyObject *list = PyList_New(0); + for (auto data : $1) + { + if (GNC_IS_ACCOUNT(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_Account, 0)); + else if (GNC_IS_SPLIT(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_Split, 0)); + else if (GNC_IS_TRANSACTION(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_Transaction, 0)); + else if (GNC_IS_COMMODITY(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_gnc_commodity, 0)); + else if (GNC_IS_COMMODITY_NAMESPACE(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_gnc_commodity_namespace, 0)); + else if (GNC_IS_LOT(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_GNCLot, 0)); + else if (GNC_IS_PRICE(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_GNCPrice, 0)); + else if (GNC_IS_INVOICE(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncInvoice, 0)); + else if (GNC_IS_ENTRY(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncEntry, 0)); + else if (GNC_IS_CUSTOMER(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncCustomer, 0)); + else if (GNC_IS_VENDOR(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncVendor, 0)); + else if (GNC_IS_EMPLOYEE(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncEmployee, 0)); + else if (GNC_IS_JOB(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncJob, 0)); + else if (GNC_IS_TAXTABLE(data)) + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p__gncTaxTable, 0)); + else if ($1_descriptor == $descriptor(MonetaryList *)) + PyList_Append(list, SWIG_NewPointerObj(data, $descriptor(gnc_monetary *), 0)); + else + PyList_Append(list, SWIG_NewPointerObj(data, SWIGTYPE_p_void, 0)); + } + $result = list; +} #endif diff --git a/gnucash/gnome-utils/dialog-commodity.cpp b/gnucash/gnome-utils/dialog-commodity.cpp index 743b6c2a22..87880a8b1e 100644 --- a/gnucash/gnome-utils/dialog-commodity.cpp +++ b/gnucash/gnome-utils/dialog-commodity.cpp @@ -42,12 +42,15 @@ #include "dialog-commodity.h" #include "dialog-utils.h" +#include "gnc-commodity.hpp" #include "gnc-engine.h" #include "gnc-gtk-utils.h" #include "gnc-gui-query.h" #include "gnc-ui-util.h" #include "gnc-ui.h" +#include + /* This static indicates the debugging module that this .o belongs to. */ static QofLogModule log_module = GNC_MOD_GUI; @@ -426,15 +429,6 @@ gnc_ui_select_commodity_namespace_changed_cb (GtkComboBox *cbwe, /******************************************************************** * gnc_ui_update_commodity_picker ********************************************************************/ -static int -collate(gconstpointer a, gconstpointer b) -{ - if (!a) - return -1; - if (!b) - return 1; - return g_utf8_collate (static_cast(a), static_cast(b)); -} void @@ -442,16 +436,13 @@ gnc_ui_update_commodity_picker (GtkWidget *cbwe, const gchar * name_space, const gchar * init_string) { - GList * commodities; - GList * iterator = nullptr; - GList * commodity_items = nullptr; + std::vector commodity_items; GtkComboBox *combo_box; GtkEntry *entry; GtkTreeModel *model; GtkTreeIter iter; gnc_commodity_table *table; gint current = 0, match = 0; - gchar *name; g_return_if_fail(GTK_IS_COMBO_BOX(cbwe)); g_return_if_fail(name_space); @@ -468,29 +459,23 @@ gnc_ui_update_commodity_picker (GtkWidget *cbwe, gtk_combo_box_set_active(combo_box, -1); table = gnc_commodity_table_get_table (gnc_get_current_book ()); - commodities = gnc_commodity_table_get_commodities(table, name_space); - for (iterator = commodities; iterator; iterator = iterator->next) - { - commodity_items = - g_list_prepend (commodity_items, - (gpointer) gnc_commodity_get_printname(GNC_COMMODITY(iterator->data))); - } - g_list_free(commodities); - commodity_items = g_list_sort(commodity_items, collate); - for (iterator = commodity_items; iterator; iterator = iterator->next) + for (auto comm : gnc_commodity_table_get_commodities(table, name_space)) + commodity_items.push_back (gnc_commodity_get_printname(comm)); + + std::sort (commodity_items.end(), commodity_items.begin()); + + for (auto name : commodity_items) { - name = (char *)iterator->data; gtk_list_store_append(GTK_LIST_STORE(model), &iter); - gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, name, -1); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, name.c_str(), -1); - if (init_string && g_utf8_collate(name, init_string) == 0) + if (init_string && name == init_string) match = current; current++; } gtk_combo_box_set_active(combo_box, match); - g_list_free(commodity_items); } @@ -560,7 +545,7 @@ gnc_ui_update_namespace_picker (GtkWidget *cbwe, GtkComboBox *combo_box; GtkTreeModel *model; GtkTreeIter iter, match; - GList *namespaces, *node; + std::vector namespaces; gboolean matched = FALSE; g_return_if_fail(GTK_IS_COMBO_BOX (cbwe)); @@ -582,12 +567,10 @@ gnc_ui_update_namespace_picker (GtkWidget *cbwe, case DIAG_COMM_NON_CURRENCY_SELECT: namespaces = gnc_commodity_table_get_namespaces (gnc_get_current_commodities()); - node = g_list_find_custom (namespaces, GNC_COMMODITY_NS_CURRENCY, collate); - if (node) - { - namespaces = g_list_remove_link (namespaces, node); - g_list_free_1 (node); - } + + if (auto it = std::find (namespaces.begin(), namespaces.end(), GNC_COMMODITY_NS_CURRENCY); + it != namespaces.end()) + namespaces.erase (it); if (gnc_commodity_namespace_is_iso (init_string)) init_string = nullptr; @@ -595,7 +578,7 @@ gnc_ui_update_namespace_picker (GtkWidget *cbwe, case DIAG_COMM_CURRENCY: default: - namespaces = g_list_prepend (nullptr, (gpointer)GNC_COMMODITY_NS_CURRENCY); + namespaces = { GNC_COMMODITY_NS_CURRENCY }; break; } @@ -623,10 +606,10 @@ gnc_ui_update_namespace_picker (GtkWidget *cbwe, } /* add all others to the combobox */ - namespaces = g_list_sort(namespaces, collate); - for (node = namespaces; node; node = node->next) + std::sort (namespaces.begin(), namespaces.end()); + for (const auto& ns_str : namespaces) { - auto ns = static_cast(node->data); + auto ns = ns_str.c_str(); /* Skip template, legacy and currency namespaces. The latter was added as first entry earlier */ if ((g_utf8_collate(ns, GNC_COMMODITY_NS_LEGACY) == 0) || @@ -650,7 +633,6 @@ gnc_ui_update_namespace_picker (GtkWidget *cbwe, if (matched) gtk_combo_box_set_active_iter (combo_box, &match); - g_list_free(namespaces); } diff --git a/gnucash/gnome-utils/gnc-currency-edit.cpp b/gnucash/gnome-utils/gnc-currency-edit.cpp index 0481e5b45f..307f626cf2 100644 --- a/gnucash/gnome-utils/gnc-currency-edit.cpp +++ b/gnucash/gnome-utils/gnc-currency-edit.cpp @@ -48,6 +48,8 @@ #include +#include + #include #include #include @@ -56,6 +58,7 @@ #include "gnc-currency-edit.h" #include "gnc-commodity.h" +#include "gnc-commodity.hpp" #include "gnc-gtk-utils.h" #include "gnc-ui-util.h" #include "gnc-engine.h" @@ -311,12 +314,10 @@ add_item(gnc_commodity *commodity, GNCCurrencyEdit *gce) static void fill_currencies(GNCCurrencyEdit *gce) { - GList *currencies; - - currencies = gnc_commodity_table_get_commodities + auto currencies = gnc_commodity_table_get_commodities (gnc_get_current_commodities (), GNC_COMMODITY_NS_CURRENCY); - g_list_foreach(currencies, (GFunc)add_item, gce); - g_list_free(currencies); + std::for_each (currencies.begin(), currencies.end(), + [gce](auto comm){ add_item (comm, gce); }); } diff --git a/gnucash/gnome/dialog-price-edit-db.cpp b/gnucash/gnome/dialog-price-edit-db.cpp index c129a0f8ab..8052b873c0 100644 --- a/gnucash/gnome/dialog-price-edit-db.cpp +++ b/gnucash/gnome/dialog-price-edit-db.cpp @@ -242,16 +242,13 @@ gnc_prices_dialog_load_view (GtkTreeView *view, GNCPriceDB *pdb) auto oldest = gnc_time (nullptr); auto model = gtk_tree_view_get_model (view); const auto commodity_table = gnc_get_current_commodities (); - auto namespace_list = gnc_commodity_table_get_namespaces (commodity_table); - for (auto node_n = namespace_list; node_n; node_n = g_list_next (node_n)) + for (const auto& tmp_namespace_str : gnc_commodity_table_get_namespaces (commodity_table)) { - auto tmp_namespace = static_cast(node_n->data); + auto tmp_namespace = tmp_namespace_str.c_str(); DEBUG("Looking at namespace %s", tmp_namespace); - auto commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace); - for (auto node_c = commodity_list; node_c; node_c = g_list_next (node_c)) + for (auto tmp_commodity : gnc_commodity_table_get_commodities (commodity_table, tmp_namespace)) { - auto tmp_commodity = static_cast(node_c->data); auto num = gnc_pricedb_num_prices (pdb, tmp_commodity); DEBUG("Looking at commodity %s, Number of prices %d", gnc_commodity_get_fullname (tmp_commodity), num); @@ -279,9 +276,7 @@ gnc_prices_dialog_load_view (GtkTreeView *view, GNCPriceDB *pdb) g_list_free_full (list, (GDestroyNotify)gnc_price_unref); } } - g_list_free (commodity_list); } - g_list_free (namespace_list); return oldest; } diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp index 3543b51747..15b4bfc18d 100644 --- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp +++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp @@ -40,6 +40,7 @@ #include "gnc-uri-utils.h" #include "gnc-ui-util.h" #include "dialog-utils.h" +#include "gnc-commodity.hpp" #include "gnc-component-manager.h" @@ -445,9 +446,6 @@ GtkTreeModel *get_model (bool all_commodity) { GtkTreeModel *store, *model; const gnc_commodity_table *commodity_table = gnc_get_current_commodities (); - gnc_commodity *tmp_commodity = nullptr; - char *tmp_namespace = nullptr; - GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table); GtkTreeIter iter; store = GTK_TREE_MODEL(gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, @@ -460,9 +458,9 @@ GtkTreeModel *get_model (bool all_commodity) gtk_list_store_set (GTK_LIST_STORE(store), &iter, DISPLAYED_COMM, " ", SORT_COMM, " ", COMM_PTR, nullptr, SEP, false, -1); - for (auto node = namespace_list; node; node = g_list_next (node)) + for (const auto& tmp_namespace_str : gnc_commodity_table_get_namespaces (commodity_table)) { - tmp_namespace = (char*)node->data; + auto tmp_namespace = tmp_namespace_str.c_str(); DEBUG("Looking at namespace %s", tmp_namespace); /* Hide the template entry */ @@ -470,8 +468,6 @@ GtkTreeModel *get_model (bool all_commodity) { if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true)) { - auto comm_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace); - // if this is the CURRENCY, add a row to be identified as a separator row if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY) == 0) && (all_commodity == true)) { @@ -480,11 +476,10 @@ GtkTreeModel *get_model (bool all_commodity) SORT_COMM, "CURRENCY-", COMM_PTR, nullptr, SEP, true, -1); } - for (auto node = comm_list; node; node = g_list_next (node)) + for (auto tmp_commodity : gnc_commodity_table_get_commodities (commodity_table, tmp_namespace)) { const gchar *name_str; gchar *sort_str; - tmp_commodity = (gnc_commodity*)node->data; DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity)); name_str = gnc_commodity_get_printname (tmp_commodity); @@ -502,11 +497,9 @@ GtkTreeModel *get_model (bool all_commodity) g_free (sort_str); } - g_list_free (comm_list); } } } - g_list_free (namespace_list); g_object_unref (store); return model; 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 760623b943..dd09938c5e 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp @@ -32,6 +32,7 @@ #include "gnc-ui-util.h" #include "Account.h" #include "Transaction.h" +#include "gnc-commodity.hpp" #include "gnc-pricedb.h" #include @@ -201,19 +202,16 @@ gnc_commodity* parse_commodity (const std::string& comm_str) if (!comm) { /* If that fails try mnemonic in all other namespaces */ - auto namespaces = gnc_commodity_table_get_namespaces(table); - for (auto ns = namespaces; ns; ns = ns->next) + for (const auto& ns_str : gnc_commodity_table_get_namespaces(table)) { - gchar* ns_str = (gchar*)ns->data; - if (g_utf8_collate(ns_str, GNC_COMMODITY_NS_CURRENCY) == 0) + if (ns_str == GNC_COMMODITY_NS_CURRENCY) continue; comm = gnc_commodity_table_lookup (table, - ns_str, comm_str.c_str()); + ns_str.c_str(), comm_str.c_str()); if (comm) break; } - g_list_free (namespaces); } if (!comm) diff --git a/gnucash/import-export/import-commodity-matcher.cpp b/gnucash/import-export/import-commodity-matcher.cpp index afd5d58949..cbf27fa839 100644 --- a/gnucash/import-export/import-commodity-matcher.cpp +++ b/gnucash/import-export/import-commodity-matcher.cpp @@ -24,6 +24,7 @@ @author Copyright (C) 2002 Benoit Grégoire */ #include +#include #include #include @@ -34,6 +35,7 @@ #include "Account.h" #include "Transaction.h" #include "dialog-commodity.h" +#include "gnc-commodity.hpp" #include "gnc-engine.h" #include "gnc-ui-util.h" @@ -64,28 +66,23 @@ gnc_commodity * gnc_import_select_commodity(const char * cusip, DEBUG("Looking for commodity with exchange_code: %s", cusip); g_assert(commodity_table); - GList *namespace_list = gnc_commodity_table_get_namespaces(commodity_table); - for (GList *n = namespace_list; !retval && n; n = g_list_next (n)) + for (const auto& ns_str : gnc_commodity_table_get_namespaces(commodity_table)) { - auto ns = static_cast(n->data); + auto ns = ns_str.c_str(); DEBUG("Looking at namespace %s", ns); - GList *comm_list = gnc_commodity_table_get_commodities (commodity_table, ns); - for (GList *m = comm_list; !retval && m; m = g_list_next (m)) + auto commodities{gnc_commodity_table_get_commodities (commodity_table, ns)}; + auto it = std::find_if (commodities.begin(), commodities.end(), + [cusip](auto com) + { return !g_strcmp0 (gnc_commodity_get_cusip (com), cusip); }); + if (it != commodities.end()) { - auto com = static_cast(m->data); - DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (com)); - if (!g_strcmp0 (gnc_commodity_get_cusip (com), cusip)) - { - retval = com; - DEBUG("Commodity %s matches.", gnc_commodity_get_fullname (com)); - } - } - g_list_free (comm_list); + retval = *it; + DEBUG("Commodity %s matches.", gnc_commodity_get_fullname (*it)); + break; + }; } - g_list_free(namespace_list); - if (retval == NULL && ask_on_unknown != 0) { const gchar *message = diff --git a/libgnucash/app-utils/gnc-quotes.cpp b/libgnucash/app-utils/gnc-quotes.cpp index 1fdf64a385..ac3938cf86 100644 --- a/libgnucash/app-utils/gnc-quotes.cpp +++ b/libgnucash/app-utils/gnc-quotes.cpp @@ -989,8 +989,6 @@ CommVec gnc_quotes_get_quotable_commodities (const gnc_commodity_table * table) { gnc_commodity_namespace * ns = NULL; - const char *name_space; - GList * nslist, * tmp; CommVec l; regex_t pattern; const char *expression = gnc_prefs_get_namespace_regexp (); @@ -1007,10 +1005,9 @@ gnc_quotes_get_quotable_commodities (const gnc_commodity_table * table) return CommVec (); } - nslist = gnc_commodity_table_get_namespaces (table); - for (tmp = nslist; tmp; tmp = tmp->next) + for (const auto& name_space_str : gnc_commodity_table_get_namespaces (table)) { - name_space = static_cast (tmp->data); + auto name_space = name_space_str.c_str(); if (regexec (&pattern, name_space, 0, NULL, 0) == 0) { // DEBUG ("Running list of %s commodities", name_space); @@ -1023,7 +1020,6 @@ gnc_quotes_get_quotable_commodities (const gnc_commodity_table * table) } } } - g_list_free (nslist); regfree (&pattern); } else diff --git a/libgnucash/backend/xml/io-gncxml-v2.cpp b/libgnucash/backend/xml/io-gncxml-v2.cpp index 562d685cfd..13cbde5d0b 100644 --- a/libgnucash/backend/xml/io-gncxml-v2.cpp +++ b/libgnucash/backend/xml/io-gncxml-v2.cpp @@ -46,6 +46,7 @@ #include #include +#include "gnc-commodity.hpp" #include "gnc-engine.h" #include "gnc-pricedb-p.h" #include "Scrub.h" @@ -930,20 +931,9 @@ write_counts (FILE* out, ...) } static gint -compare_namespaces (gconstpointer a, gconstpointer b) +compare_commodity_less (gnc_commodity* a, gnc_commodity* b) { - const gchar* sa = (const gchar*) a; - const gchar* sb = (const gchar*) b; - return (g_strcmp0 (sa, sb)); -} - -static gint -compare_commodity_ids (gconstpointer a, gconstpointer b) -{ - const gnc_commodity* ca = (const gnc_commodity*) a; - const gnc_commodity* cb = (const gnc_commodity*) b; - return (g_strcmp0 (gnc_commodity_get_mnemonic (ca), - gnc_commodity_get_mnemonic (cb))); + return (g_strcmp0 (gnc_commodity_get_mnemonic (a), gnc_commodity_get_mnemonic (b)) < 0); } static gboolean write_pricedb (FILE* out, QofBook* book, sixtp_gdv2* gd); @@ -1039,31 +1029,24 @@ gboolean write_commodities (FILE* out, QofBook* book, sixtp_gdv2* gd) { gnc_commodity_table* tbl; - GList* namespaces; - GList* lp; gboolean success = TRUE; tbl = gnc_commodity_table_get_table (book); - namespaces = gnc_commodity_table_get_namespaces (tbl); - if (namespaces) - { - namespaces = g_list_sort (namespaces, compare_namespaces); - } + auto namespaces = gnc_commodity_table_get_namespaces (tbl); - for (lp = namespaces; success && lp; lp = lp->next) + std::sort (namespaces.begin(), namespaces.end()); + + for (const auto& name_space : namespaces) { - GList* comms, *lp2; xmlNodePtr comnode; - comms = gnc_commodity_table_get_commodities (tbl, - static_cast (lp->data)); - comms = g_list_sort (comms, compare_commodity_ids); + auto comms = gnc_commodity_table_get_commodities (tbl, name_space.c_str()); + std::sort (comms.begin(), comms.end(), compare_commodity_less); - for (lp2 = comms; lp2; lp2 = lp2->next) + for (auto comm : comms) { - comnode = gnc_commodity_dom_tree_create (static_cast - (lp2->data)); + comnode = gnc_commodity_dom_tree_create (comm); if (comnode == NULL) continue; @@ -1079,11 +1062,10 @@ write_commodities (FILE* out, QofBook* book, sixtp_gdv2* gd) sixtp_run_callback (gd, "commodities"); } - g_list_free (comms); + if (!success) + break; } - if (namespaces) g_list_free (namespaces); - return success; } diff --git a/libgnucash/engine/gnc-commodity.cpp b/libgnucash/engine/gnc-commodity.cpp index 6a25851a7a..824b93677a 100644 --- a/libgnucash/engine/gnc-commodity.cpp +++ b/libgnucash/engine/gnc-commodity.cpp @@ -107,13 +107,16 @@ struct _GncCommodityClass static void commodity_free(gnc_commodity * cm); static void gnc_commodity_set_default_symbol(gnc_commodity *, const char *); +using StrCommodityMap = std::unordered_map; +using StrCommodityNSMap = std::unordered_map; + struct gnc_commodity_namespace_s { QofInstance inst; const gchar *name; gboolean iso4217; - GHashTable * cm_table; + StrCommodityMap cm_table; GList * cm_list; }; @@ -124,7 +127,7 @@ struct _GncCommodityNamespaceClass struct gnc_commodity_table_s { - GHashTable * ns_table; + StrCommodityNSMap ns_table; GList * ns_list; }; @@ -1614,7 +1617,7 @@ gnc_commodity_table * gnc_commodity_table_new(void) { gnc_commodity_table * retval = g_new0(gnc_commodity_table, 1); - retval->ns_table = g_hash_table_new(&g_str_hash, &g_str_equal); + new (&retval->ns_table) StrCommodityNSMap (); retval->ns_list = nullptr; return retval; } @@ -1657,12 +1660,12 @@ gnc_commodity_obtain_twin (const gnc_commodity *from, QofBook *book) ********************************************************************/ static void -count_coms(gpointer key, gpointer value, gpointer user_data) +count_coms(const std::string key, gpointer value, gpointer user_data) { - GHashTable *tbl = ((gnc_commodity_namespace*)value)->cm_table; + auto tbl = ((gnc_commodity_namespace*)value)->cm_table; guint *count = (guint*)user_data; - if (g_strcmp0((char*)key, GNC_COMMODITY_NS_CURRENCY) == 0) + if (key == GNC_COMMODITY_NS_CURRENCY) { /* don't count default commodities */ return; @@ -1670,7 +1673,7 @@ count_coms(gpointer key, gpointer value, gpointer user_data) if (!value) return; - *count += g_hash_table_size(tbl); + *count += tbl.size(); } guint @@ -1678,9 +1681,9 @@ gnc_commodity_table_get_size(const gnc_commodity_table* tbl) { guint count = 0; g_return_val_if_fail(tbl, 0); - g_return_val_if_fail(tbl->ns_table, 0); - g_hash_table_foreach(tbl->ns_table, count_coms, (gpointer)&count); + std::for_each (tbl->ns_table.begin(), tbl->ns_table.end(), + [&count](auto it){ count_coms (it.first, it.second, &count); }); return count; } @@ -1712,7 +1715,7 @@ gnc_commodity_table_lookup(const gnc_commodity_table * table, if (it != gnc_new_iso_codes.end()) mnemonic = it->second.c_str(); } - return GNC_COMMODITY(g_hash_table_lookup(nsp->cm_table, (gpointer)mnemonic)); + return GNC_COMMODITY(nsp->cm_table[mnemonic]); } else { @@ -1763,29 +1766,15 @@ gnc_commodity_table_find_full(const gnc_commodity_table * table, const char * name_space, const char * fullname) { - gnc_commodity * retval = nullptr; - GList * all; - GList * iterator; - if (!fullname || (fullname[0] == '\0')) return nullptr; - all = gnc_commodity_table_get_commodities(table, name_space); + auto commodities{gnc_commodity_table_get_commodities(table, name_space)}; + auto it = std::find_if (commodities.begin(), commodities.end(), + [fullname](auto comm) + { return !g_strcmp0 (fullname, gnc_commodity_get_printname(comm)); }); - for (iterator = all; iterator; iterator = iterator->next) - { - auto commodity = GNC_COMMODITY (iterator->data); - if (!strcmp(fullname, - gnc_commodity_get_printname(commodity))) - { - retval = commodity; - break; - } - } - - g_list_free (all); - - return retval; + return it == commodities.end() ? nullptr : *it;; } @@ -1852,10 +1841,8 @@ gnc_commodity_table_insert(gnc_commodity_table * table, nsp = gnc_commodity_table_add_namespace(table, ns_name, book); PINFO ("insert %p %s into nsp=%p %s", priv->mnemonic, priv->mnemonic, - nsp->cm_table, nsp->name); - g_hash_table_insert(nsp->cm_table, - (gpointer)CACHE_INSERT(priv->mnemonic), - (gpointer)comm); + &nsp->cm_table, nsp->name); + nsp->cm_table [priv->mnemonic] = comm; nsp->cm_list = g_list_append(nsp->cm_list, comm); qof_event_gen (&comm->inst, QOF_EVENT_ADD, nullptr); @@ -1891,7 +1878,7 @@ gnc_commodity_table_remove(gnc_commodity_table * table, if (!nsp) return; nsp->cm_list = g_list_remove(nsp->cm_list, comm); - g_hash_table_remove (nsp->cm_table, priv->mnemonic); + nsp->cm_table.erase (priv->mnemonic); /* XXX minor mem leak, should remove the key as well */ } @@ -1922,48 +1909,21 @@ gnc_commodity_table_has_namespace(const gnc_commodity_table * table, } } -static void -hash_keys_helper(gpointer key, gpointer value, gpointer data) -{ - auto l = (GList**)data; - *l = g_list_prepend(*l, key); -} - -static GList * -g_hash_table_keys(GHashTable * table) -{ - GList * l = nullptr; - g_hash_table_foreach(table, &hash_keys_helper, (gpointer) &l); - return l; -} - -static void -hash_values_helper(gpointer key, gpointer value, gpointer data) -{ - auto l = (GList**)data; - *l = g_list_prepend(*l, value); -} - -static GList * -g_hash_table_values(GHashTable * table) -{ - GList * l = nullptr; - g_hash_table_foreach(table, &hash_values_helper, (gpointer) &l); - return l; -} - /******************************************************************** * gnc_commodity_table_get_namespaces * see if any commodities in the namespace exist ********************************************************************/ -GList * +std::vector gnc_commodity_table_get_namespaces(const gnc_commodity_table * table) { + std::vector rv; if (!table) - return nullptr; + return rv; - return g_hash_table_keys(table->ns_table); + std::for_each (table->ns_table.begin(), table->ns_table.end(), + [&rv](auto it){ rv.push_back (it.first); }); + return rv; } GList * @@ -2009,41 +1969,41 @@ gnc_commodity_is_currency(const gnc_commodity *cm) * list commodities in a given namespace ********************************************************************/ -static CommodityList* +static CommVec commodity_table_get_all_noncurrency_commodities(const gnc_commodity_table* table) { - GList *node = nullptr, *nslist = gnc_commodity_table_get_namespaces(table); - CommodityList *retval = nullptr; - for (node = nslist; node; node=g_list_next(node)) + CommVec retval; + for (const auto& name_space : gnc_commodity_table_get_namespaces(table)) { - gnc_commodity_namespace *ns = nullptr; - if (g_strcmp0((char*)(node->data), GNC_COMMODITY_NS_CURRENCY) == 0 - || g_strcmp0((char*)(node->data), GNC_COMMODITY_NS_TEMPLATE) == 0) + gnc_commodity_namespace *ns = NULL; + if (name_space == GNC_COMMODITY_NS_CURRENCY || name_space == GNC_COMMODITY_NS_TEMPLATE) continue; - ns = gnc_commodity_table_find_namespace(table, (char*)(node->data)); + ns = gnc_commodity_table_find_namespace(table, name_space.c_str()); if (!ns) continue; - retval = g_list_concat(g_hash_table_values(ns->cm_table), retval); + std::for_each (ns->cm_table.begin(), ns->cm_table.end(), + [&retval](auto it){ retval.push_back (it.second); }); } - g_list_free(nslist); return retval; } -CommodityList * +CommVec gnc_commodity_table_get_commodities(const gnc_commodity_table * table, const char * name_space) { - gnc_commodity_namespace * ns = nullptr; + CommVec retval; if (!table) - return nullptr; + return retval; if (g_strcmp0(name_space, GNC_COMMODITY_NS_NONISO_GUI) == 0) return commodity_table_get_all_noncurrency_commodities(table); - ns = gnc_commodity_table_find_namespace(table, name_space); + auto ns = gnc_commodity_table_find_namespace(table, name_space); if (!ns) - return nullptr; + return retval; - return g_hash_table_values(ns->cm_table); + std::for_each (ns->cm_table.begin(), ns->cm_table.end(), + [&retval](auto it){ retval.push_back (it.second); }); + return retval; } /******************************************************************** @@ -2054,73 +2014,70 @@ gnc_commodity_table_get_commodities(const gnc_commodity_table * table, static void get_quotables_helper1(gpointer key, gpointer value, gpointer data) { - auto comm = GNC_COMMODITY(value); + auto comm{GNC_COMMODITY(value)}; + auto rv{static_cast(data)}; gnc_commodityPrivate* priv = GET_PRIVATE(comm); - auto l = static_cast(data); if (!priv->quote_flag || !priv->quote_source || !priv->quote_source->get_supported()) return; - *l = g_list_prepend(*l, value); + rv->push_back (comm); } static gboolean get_quotables_helper2 (gnc_commodity *comm, gpointer data) { - auto l = static_cast(data); gnc_commodityPrivate* priv = GET_PRIVATE(comm); + auto rv{static_cast(data)}; if (!priv->quote_flag || priv->quote_source || !priv->quote_source->get_supported()) return TRUE; - *l = g_list_prepend(*l, comm); + rv->push_back (comm); return TRUE; } -CommodityList * +CommVec gnc_commodity_table_get_quotable_commodities(const gnc_commodity_table * table) { gnc_commodity_namespace * ns = nullptr; - const char *name_space; - GList * nslist, * tmp; - GList * l = nullptr; + CommVec rv; regex_t pattern; const char *expression = gnc_prefs_get_namespace_regexp(); ENTER("table=%p, expression=%s", table, expression); if (!table) - return nullptr; + return {}; if (expression && *expression) { if (regcomp(&pattern, expression, REG_EXTENDED | REG_ICASE) != 0) { LEAVE("Cannot compile regex"); - return nullptr; + return {}; } - nslist = gnc_commodity_table_get_namespaces(table); - for (tmp = nslist; tmp; tmp = tmp->next) + for (const auto& name_space_str : gnc_commodity_table_get_namespaces(table)) { - name_space = static_cast(tmp->data); - if (regexec(&pattern, name_space, 0, nullptr, 0) == 0) + auto name_space = name_space_str.c_str(); + if (regexec(&pattern, name_space, 0, NULL, 0) == 0) { DEBUG("Running list of %s commodities", name_space); ns = gnc_commodity_table_find_namespace(table, name_space); if (ns) { - g_hash_table_foreach(ns->cm_table, &get_quotables_helper1, (gpointer) &l); + std::for_each (ns->cm_table.begin(), ns->cm_table.end(), + [&rv](auto it) + { get_quotables_helper1 (nullptr, it.second, &rv); }); } } } - g_list_free(nslist); regfree(&pattern); } else { - gnc_commodity_table_foreach_commodity(table, get_quotables_helper2, - (gpointer) &l); + gnc_commodity_table_foreach_commodity(table, get_quotables_helper2, &rv); } - LEAVE("list head %p", l); - return l; + LEAVE("list head %p", &rv); + return rv; } /******************************************************************** @@ -2160,15 +2117,13 @@ gnc_commodity_table_add_namespace(gnc_commodity_table * table, if (!ns) { ns = static_cast(g_object_new(GNC_TYPE_COMMODITY_NAMESPACE, nullptr)); - ns->cm_table = g_hash_table_new(g_str_hash, g_str_equal); + new (&ns->cm_table) StrCommodityMap (); ns->name = CACHE_INSERT(static_cast(name_space)); ns->iso4217 = gnc_commodity_namespace_is_iso(name_space); qof_instance_init_data (&ns->inst, GNC_ID_COMMODITY_NAMESPACE, book); qof_event_gen (&ns->inst, QOF_EVENT_CREATE, nullptr); - g_hash_table_insert(table->ns_table, - (gpointer) ns->name, - (gpointer) ns); + table->ns_table[ns->name] = ns; table->ns_list = g_list_append(table->ns_list, ns); qof_event_gen (&ns->inst, QOF_EVENT_ADD, nullptr); } @@ -2184,7 +2139,12 @@ gnc_commodity_table_find_namespace(const gnc_commodity_table * table, return nullptr; name_space = gnc_commodity_table_map_namespace(name_space); - return static_cast(g_hash_table_lookup(table->ns_table, (gpointer)name_space)); + + auto it = table->ns_table.find(name_space); + if (it == table->ns_table.end()) + return nullptr; + else + return it->second; } @@ -2202,15 +2162,6 @@ gnc_commodity_find_commodity_by_guid(const GncGUID *guid, QofBook *book) * delete a namespace ********************************************************************/ -static int -ns_helper(gpointer key, gpointer value, gpointer user_data) -{ - auto c = GNC_COMMODITY(value); - gnc_commodity_destroy(c); - CACHE_REMOVE(static_cast(key)); /* key is commodity mnemonic */ - return TRUE; -} - void gnc_commodity_table_delete_namespace(gnc_commodity_table * table, const char * name_space) @@ -2224,14 +2175,15 @@ gnc_commodity_table_delete_namespace(gnc_commodity_table * table, return; qof_event_gen (&ns->inst, QOF_EVENT_REMOVE, nullptr); - g_hash_table_remove(table->ns_table, name_space); + table->ns_table.erase (name_space); table->ns_list = g_list_remove(table->ns_list, ns); g_list_free(ns->cm_list); ns->cm_list = nullptr; - g_hash_table_foreach_remove(ns->cm_table, ns_helper, nullptr); - g_hash_table_destroy(ns->cm_table); + std::for_each (ns->cm_table.begin(), ns->cm_table.end(), + [](auto it){ gnc_commodity_destroy (it.second); }); + ns->cm_table.~StrCommodityMap (); CACHE_REMOVE(ns->name); qof_event_gen (&ns->inst, QOF_EVENT_DESTROY, nullptr); @@ -2267,8 +2219,9 @@ iter_commodity (gpointer key, gpointer value, gpointer user_data) static void iter_namespace (gpointer key, gpointer value, gpointer user_data) { - GHashTable *namespace_hash = ((gnc_commodity_namespace *) value)->cm_table; - g_hash_table_foreach (namespace_hash, iter_commodity, user_data); + auto namespace_hash = ((gnc_commodity_namespace *) value)->cm_table; + std::for_each (namespace_hash.begin(), namespace_hash.end(), + [user_data](auto it){ iter_commodity (nullptr, it.second, user_data); }); } gboolean @@ -2284,7 +2237,8 @@ gnc_commodity_table_foreach_commodity (const gnc_commodity_table * tbl, iter_data.func = f; iter_data.user_data = user_data; - g_hash_table_foreach(tbl->ns_table, iter_namespace, (gpointer)&iter_data); + std::for_each (tbl->ns_table.begin(), tbl->ns_table.end(), + [&iter_data](auto it){ iter_namespace (nullptr, it.second, &iter_data); }); return iter_data.ok; } @@ -2312,8 +2266,7 @@ gnc_commodity_table_destroy(gnc_commodity_table * t) g_list_free(t->ns_list); t->ns_list = nullptr; - g_hash_table_destroy(t->ns_table); - t->ns_table = nullptr; + t->ns_table.~StrCommodityNSMap(); LEAVE ("table=%p", t); g_free(t); } diff --git a/libgnucash/engine/gnc-commodity.h b/libgnucash/engine/gnc-commodity.h index 6bef47643e..8b05ede069 100644 --- a/libgnucash/engine/gnc-commodity.h +++ b/libgnucash/engine/gnc-commodity.h @@ -115,8 +115,6 @@ GType gnc_commodity_namespace_get_type(void); */ #define GNC_COMMODITY_MAX_FRACTION 1000000000 -typedef GList CommodityList; - /** @name Commodity Quote Source functions @{ */ @@ -829,15 +827,6 @@ GList * gnc_commodity_namespace_get_commodity_list(const gnc_commodity_namespace int gnc_commodity_table_has_namespace(const gnc_commodity_table * table, const char * commodity_namespace); -/** Return a list of all namespaces in the commodity table. This - * returns both system and user defined namespaces. - * - * @return A pointer to the list of names. NULL if an invalid - * argument was supplied. - * - * @note It is the callers responsibility to free the list. */ -GList * gnc_commodity_table_get_namespaces(const gnc_commodity_table * t); - /** Return a list of all namespace data structures in the commodity table. This * returns both system and user defined namespace structures. * @@ -897,41 +886,6 @@ void gnc_commodity_table_delete_namespace(gnc_commodity_table * table, * commodities, or the routine was passed a bad argument. */ guint gnc_commodity_table_get_size(const gnc_commodity_table* tbl); -/** Return a list of all commodities in the commodity table that are - * in the given namespace. - * - * @param table A pointer to the commodity table - * - * @param commodity_namespace A string indicating which commodities should be - * returned. It is a required argument. - * - * @return A pointer to the list of commodities. NULL if an invalid - * argument was supplied, or the namespace could not be found. - * - * @note It is the callers responsibility to free the list. */ -CommodityList * gnc_commodity_table_get_commodities( - const gnc_commodity_table * table, const char * commodity_namespace); - -/** This function returns a list of commodities for which price quotes - * should be retrieved. It will scan the entire commodity table (or - * a subset) and check each commodity to see if the price_quote_flag - * field has been set. All matching commodities are queued onto a - * list, and the head of that list is returned. Use the command-line - * given expression as a filter on the commodities to be returned. If - * non-null, only commodities in namespace that match the specified - * regular expression are checked. If none was given, all - * commodities are checked. - * - * @param table A pointer to the commodity table - * - * @return A pointer to a list of commodities. NULL if invalid - * arguments were supplied or if there no commodities are flagged for - * quote retrieval. - * - * @note It is the callers responsibility to free the list. */ -CommodityList * gnc_commodity_table_get_quotable_commodities( - const gnc_commodity_table * table); - /** Call a function once for each commodity in the commodity table. * This table walk returns whenever the end of the table is reached, * or the function returns FALSE. diff --git a/libgnucash/engine/gnc-commodity.hpp b/libgnucash/engine/gnc-commodity.hpp index 223d9abe72..00e02e01e4 100644 --- a/libgnucash/engine/gnc-commodity.hpp +++ b/libgnucash/engine/gnc-commodity.hpp @@ -34,6 +34,7 @@ #define GNC_COMMODITY_HPP #include +#include #include @@ -51,6 +52,48 @@ using CommVec = std::vector; void gnc_quote_source_set_fq_installed (const char* version_string, const std::vector& sources_list); + +/** Return a list of all namespaces in the commodity table. This + * returns both system and user defined namespaces. + * + * @return A vector to the list of names. An empty vector if an + * invalid argument was supplied. */ +std::vector gnc_commodity_table_get_namespaces (const gnc_commodity_table * t); + + +/** Return a vector of all commodities in the commodity table that are + * in the given namespace. + * + * @param table A pointer to the commodity table + * + * @param commodity_namespace A string indicating which commodities should be + * returned. It is a required argument. + * + * @return A pointer to the list of commodities. NULL if an invalid + * argument was supplied, or the namespace could not be found. + */ + +CommVec gnc_commodity_table_get_commodities (const gnc_commodity_table *, const char *); + +/** This function returns a vector of commodities for which price + * quotes should be retrieved. It will scan the entire commodity + * table (or a subset) and check each commodity to see if the + * price_quote_flag field has been set. All matching commodities are + * queued onto a list, and the head of that list is returned. Use + * the command-line given expression as a filter on the commodities + * to be returned. If non-null, only commodities in namespace that + * match the specified regular expression are checked. If none was + * given, all commodities are checked. + * + * @param table A pointer to the commodity table + * + * @return A pointer to a list of commodities. NULL if invalid + * arguments were supplied or if there no commodities are flagged for + * quote retrieval. + */ + +CommVec gnc_commodity_table_get_quotable_commodities (const gnc_commodity_table*); + #endif /* GNC_COMMODITY_HPP */ /** @} */ /** @} */ diff --git a/libgnucash/engine/gnc-optiondb.cpp b/libgnucash/engine/gnc-optiondb.cpp index 17d23d8fb6..fee7e0d57b 100644 --- a/libgnucash/engine/gnc-optiondb.cpp +++ b/libgnucash/engine/gnc-optiondb.cpp @@ -31,6 +31,7 @@ #include "kvp-frame.hpp" #include "qofbookslots.h" #include "guid.hpp" +#include "gnc-commodity.hpp" #include "gnc-optiondb.h" #include "gnc-optiondb.hpp" #include "gnc-optiondb-impl.hpp" @@ -693,13 +694,9 @@ gnc_register_commodity_option(GncOptionDB* db, const char* section, gnc_commodity* commodity{}; const auto book{qof_session_get_book(gnc_get_current_session())}; const auto commodity_table{gnc_commodity_table_get_table(book)}; - const auto namespaces{gnc_commodity_table_get_namespaces(commodity_table)}; - for (auto node = namespaces; node && commodity == nullptr; - node = g_list_next(node)) + for (const auto& name_space : gnc_commodity_table_get_namespaces(commodity_table)) { - commodity = gnc_commodity_table_lookup(commodity_table, - (const char*)(node->data), - value); + commodity = gnc_commodity_table_lookup(commodity_table, name_space.c_str(), value); if (commodity) break; } @@ -707,7 +704,6 @@ gnc_register_commodity_option(GncOptionDB* db, const char* section, commodity, GncOptionUIType::COMMODITY}}; db->register_option(section, std::move(option)); - g_list_free (namespaces); } void diff --git a/libgnucash/engine/test-core/test-engine-stuff.cpp b/libgnucash/engine/test-core/test-engine-stuff.cpp index 3baf38f78d..7c781ced92 100644 --- a/libgnucash/engine/test-core/test-engine-stuff.cpp +++ b/libgnucash/engine/test-core/test-engine-stuff.cpp @@ -58,6 +58,7 @@ #include "Account.h" #include "AccountP.hpp" +#include "gnc-commodity.hpp" #include "gnc-engine.h" #include "gnc-session.h" #include "Transaction.h" @@ -446,34 +447,22 @@ get_random_commodity_namespace(void) static gnc_commodity * get_random_commodity_from_table (gnc_commodity_table *table) { - GList *namespaces; gnc_commodity *com = NULL; g_return_val_if_fail (table, NULL); - namespaces = gnc_commodity_table_get_namespaces (table); + auto namespaces = gnc_commodity_table_get_namespaces (table); do { - GList *commodities; - char *name_space; + auto name_space = namespaces.at (get_random_int_in_range (0, namespaces.size() - 1)); - name_space = static_cast(get_random_list_element (namespaces)); - - commodities = gnc_commodity_table_get_commodities (table, name_space); - if (!commodities) - continue; - - com = static_cast(get_random_list_element (commodities)); - - g_list_free (commodities); + auto commodities = gnc_commodity_table_get_commodities (table, name_space.c_str()); + com = commodities[std::rand() % commodities.size()]; } while (!com); - - g_list_free (namespaces); - return com; } @@ -557,37 +546,24 @@ make_random_changes_to_commodity (gnc_commodity *com) void make_random_changes_to_commodity_table (gnc_commodity_table *table) { - GList *namespaces; - GList *node; - g_return_if_fail (table); - namespaces = gnc_commodity_table_get_namespaces (table); + auto namespaces = gnc_commodity_table_get_namespaces (table); - for (node = namespaces; node; node = node->next) + for (const auto& ns_str : namespaces) { - auto ns = static_cast(node->data); - GList *commodities; - GList *com_node; + auto ns = ns_str.c_str(); if (gnc_commodity_namespace_is_iso (ns)) continue; - commodities = gnc_commodity_table_get_commodities (table, ns); - - for (com_node = commodities; com_node; com_node = com_node->next) + for (auto com : gnc_commodity_table_get_commodities (table, ns)) { - auto com = static_cast(com_node->data); - gnc_commodity_table_remove (table, com); make_random_changes_to_commodity (com); gnc_commodity_table_insert (table, com); } - - g_list_free (commodities); } - - g_list_free (namespaces); } /* ================================================================= */ /* Price stuff */