From 4c13c2a62b3d504fba70a103428b7e755a169674 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Mon, 28 Oct 2024 06:48:26 +0800 Subject: [PATCH] Account->lots is a std::vector --- libgnucash/engine/Account.cpp | 58 +++++++++--------------- libgnucash/engine/Account.hpp | 1 + libgnucash/engine/AccountP.hpp | 2 +- libgnucash/engine/test/utest-Account.cpp | 26 +++++------ 4 files changed, 36 insertions(+), 51 deletions(-) diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp index afcb7697997..ee3855c127f 100644 --- a/libgnucash/engine/Account.cpp +++ b/libgnucash/engine/Account.cpp @@ -311,7 +311,6 @@ gnc_account_init(Account* acc) priv->mark = 0; priv->policy = xaccGetFIFOPolicy(); - priv->lots = nullptr; priv->commodity = nullptr; priv->commodity_scu = 0; @@ -327,6 +326,7 @@ gnc_account_init(Account* acc) priv->starting_reconciled_balance = gnc_numeric_zero(); priv->balance_dirty = FALSE; + new (&priv->lots) LotVec (); new (&priv->children) AccountVec (); new (&priv->splits) SplitsVec (); priv->splits_hash = g_hash_table_new (g_direct_hash, g_direct_equal); @@ -1372,7 +1372,6 @@ static void xaccFreeAccount (Account *acc) { AccountPrivate *priv; - GList *lp; g_return_if_fail(GNC_IS_ACCOUNT(acc)); @@ -1395,18 +1394,13 @@ xaccFreeAccount (Account *acc) } /* remove lots -- although these should be gone by now. */ - if (priv->lots) + if (!priv->lots.empty()) { PERR (" instead of calling xaccFreeAccount(), please call\n" " xaccAccountBeginEdit(); xaccAccountDestroy();\n"); - for (lp = priv->lots; lp; lp = lp->next) - { - GNCLot *lot = static_cast(lp->data); - gnc_lot_destroy (lot); - } - g_list_free (priv->lots); - priv->lots = nullptr; + std::for_each (priv->lots.rbegin(), priv->lots.rend(), gnc_lot_destroy); + priv->lots.~LotVec(); } /* Next, clean up the splits */ @@ -1566,14 +1560,10 @@ xaccAccountCommitEdit (Account *acc) qof_collection_foreach(col, destroy_pending_splits_for_account, acc); /* the lots should be empty by now */ - for (auto lp = priv->lots; lp; lp = lp->next) - { - GNCLot *lot = static_cast(lp->data); - gnc_lot_destroy (lot); - } + std::for_each (priv->lots.rbegin(), priv->lots.rend(), gnc_lot_destroy); } - g_list_free(priv->lots); - priv->lots = nullptr; + priv->lots.clear(); // this is crucial otherwise test-engine fails + priv->lots.~LotVec(); qof_instance_set_dirty(&acc->inst); qof_instance_decrease_editlevel(acc); @@ -2109,10 +2099,10 @@ xaccAccountRemoveLot (Account *acc, GNCLot *lot) g_return_if_fail(GNC_IS_LOT(lot)); priv = GET_PRIVATE(acc); - g_return_if_fail(priv->lots); + g_return_if_fail(!priv->lots.empty()); ENTER ("(acc=%p, lot=%p)", acc, lot); - priv->lots = g_list_remove(priv->lots, lot); + priv->lots.erase (std::remove (priv->lots.begin(), priv->lots.end(), lot), priv->lots.end()); qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_REMOVE, nullptr); qof_event_gen (&acc->inst, QOF_EVENT_MODIFY, nullptr); LEAVE ("(acc=%p, lot=%p)", acc, lot); @@ -2121,16 +2111,12 @@ xaccAccountRemoveLot (Account *acc, GNCLot *lot) void xaccAccountInsertLot (Account *acc, GNCLot *lot) { - AccountPrivate *priv, *opriv; - Account * old_acc = nullptr; - Account* lot_account; - /* errors */ g_return_if_fail(GNC_IS_ACCOUNT(acc)); g_return_if_fail(GNC_IS_LOT(lot)); /* optimizations */ - lot_account = gnc_lot_get_account(lot); + auto lot_account = gnc_lot_get_account(lot); if (lot_account == acc) return; @@ -2139,13 +2125,12 @@ xaccAccountInsertLot (Account *acc, GNCLot *lot) /* pull it out of the old account */ if (lot_account) { - old_acc = lot_account; - opriv = GET_PRIVATE(old_acc); - opriv->lots = g_list_remove(opriv->lots, lot); + auto& lot_acc_lots = GET_PRIVATE(lot_account)->lots; + lot_acc_lots.erase (std::remove (lot_acc_lots.begin(), lot_acc_lots.end(), lot), + lot_acc_lots.end()); } - priv = GET_PRIVATE(acc); - priv->lots = g_list_prepend(priv->lots, lot); + GET_PRIVATE(acc)->lots.push_back (lot); gnc_lot_set_account(lot, acc); /* Don't move the splits to the new account. The caller will do this @@ -2221,7 +2206,7 @@ xaccAccountMoveAllSplits (Account *accfrom, Account *accto) /* Finally empty accfrom. */ g_assert(from_priv->splits.empty()); - g_assert(from_priv->lots == nullptr); + g_assert(from_priv->lots.empty()); xaccAccountCommitEdit(accfrom); xaccAccountCommitEdit(accto); @@ -3918,7 +3903,9 @@ LotList * xaccAccountGetLotList (const Account *acc) { g_return_val_if_fail(GNC_IS_ACCOUNT(acc), nullptr); - return g_list_copy(GET_PRIVATE(acc)->lots); + auto priv = GET_PRIVATE (acc); + return std::accumulate (priv->lots.rbegin(), priv->lots.rend(), + static_cast(nullptr), g_list_prepend); } LotList * @@ -3928,16 +3915,13 @@ xaccAccountFindOpenLots (const Account *acc, gpointer user_data, GCompareFunc sort_func) { AccountPrivate *priv; - GList *lot_list; GList *retval = nullptr; g_return_val_if_fail(GNC_IS_ACCOUNT(acc), nullptr); priv = GET_PRIVATE(acc); - for (lot_list = priv->lots; lot_list; lot_list = lot_list->next) + for (auto lot : priv->lots) { - GNCLot *lot = static_cast(lot_list->data); - /* If this lot is closed, then ignore it */ if (gnc_lot_is_closed (lot)) continue; @@ -3962,8 +3946,8 @@ xaccAccountForEachLot(const Account *acc, g_return_val_if_fail(GNC_IS_ACCOUNT(acc), nullptr); g_return_val_if_fail(proc, nullptr); - for (auto node = GET_PRIVATE(acc)->lots; node; node = node->next) - if (auto result = proc(GNC_LOT(node->data), data)) + for (auto lot : GET_PRIVATE(acc)->lots) + if (auto result = proc(lot, data)) return result; return nullptr; diff --git a/libgnucash/engine/Account.hpp b/libgnucash/engine/Account.hpp index 89649acfc48..6d13b1c5d08 100644 --- a/libgnucash/engine/Account.hpp +++ b/libgnucash/engine/Account.hpp @@ -39,6 +39,7 @@ using SplitsVec = std::vector; using AccountVec = std::vector; +using LotVec = std::vector; const SplitsVec& xaccAccountGetSplits (const Account*); diff --git a/libgnucash/engine/AccountP.hpp b/libgnucash/engine/AccountP.hpp index ea617fe0118..9945fe5289a 100644 --- a/libgnucash/engine/AccountP.hpp +++ b/libgnucash/engine/AccountP.hpp @@ -119,7 +119,7 @@ typedef struct AccountPrivate GHashTable* splits_hash; gboolean sort_dirty; /* sort order of splits is bad */ - LotList *lots; /* list of lot pointers */ + std::vector lots; /* list of lot pointers */ GNCPolicy *policy; /* Cached pointer to policy method */ char *notes; diff --git a/libgnucash/engine/test/utest-Account.cpp b/libgnucash/engine/test/utest-Account.cpp index 7f8585c17de..69ed1dd3349 100644 --- a/libgnucash/engine/test/utest-Account.cpp +++ b/libgnucash/engine/test/utest-Account.cpp @@ -881,7 +881,7 @@ test_xaccFreeAccount (Fixture *fixture, gconstpointer pData) xaccAccountSetCommodity (parent, commodity); /* Check that we've got children, lots, and splits to remove */ g_assert_true (!p_priv->children.empty()); - g_assert_true (p_priv->lots != NULL); + g_assert_true (!p_priv->lots.empty()); g_assert_true (p_priv->splits.size()); g_assert_true (p_priv->parent != NULL); g_assert_true (p_priv->commodity != NULL); @@ -982,7 +982,7 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData) xaccAccountSetCommodity (parent, commodity); /* Check that we've got children, lots, and splits to remove */ g_assert_true (!p_priv->children.empty()); - g_assert_true (p_priv->lots != NULL); + g_assert_true (!p_priv->lots.empty()); g_assert_true (p_priv->splits.size()); g_assert_true (p_priv->parent != NULL); g_assert_true (p_priv->commodity != NULL); @@ -997,7 +997,7 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData) test_signal_assert_hits (sig1, 1); test_signal_assert_hits (sig2, 0); g_assert_true (!p_priv->children.empty()); - g_assert_true (p_priv->lots != NULL); + g_assert_true (!p_priv->lots.empty()); g_assert_true (p_priv->splits.size()); g_assert_true (p_priv->parent != NULL); g_assert_true (p_priv->commodity != NULL); @@ -1530,24 +1530,24 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData) AccountPrivate *a_priv = fixture->func->get_private (fixture->acct); AccountPrivate *p_priv = fixture->func->get_private (parent); - g_assert_cmpuint (g_list_length (a_priv->lots), == , 0); - g_assert_cmpuint (g_list_length (p_priv->lots), == , 0); + g_assert_cmpuint (a_priv->lots.size(), == , 0); + g_assert_cmpuint (p_priv->lots.size(), == , 0); xaccAccountInsertLot (fixture->acct, lot); g_assert_true (gnc_lot_get_account (lot) == fixture->acct); - g_assert_cmpuint (g_list_length (a_priv->lots), == , 1); + g_assert_cmpuint (a_priv->lots.size(), == , 1); test_signal_assert_hits (sig1, 1); test_signal_assert_hits (sig2, 1); /* Make sure that inserting again doesn't do anything */ xaccAccountInsertLot (fixture->acct, lot); g_assert_true (gnc_lot_get_account (lot) == fixture->acct); - g_assert_cmpuint (g_list_length (a_priv->lots), == , 1); + g_assert_cmpuint (a_priv->lots.size(), == , 1); test_signal_assert_hits (sig1, 1); test_signal_assert_hits (sig2, 1); /* Check that inserting the lot into a different account changes the lot */ xaccAccountInsertLot (parent, lot); g_assert_true (gnc_lot_get_account (lot) == parent); - g_assert_cmpuint (g_list_length (a_priv->lots), == , 0); - g_assert_cmpuint (g_list_length (p_priv->lots), == , 1); + g_assert_cmpuint (a_priv->lots.size(), == , 0); + g_assert_cmpuint (p_priv->lots.size(), == , 1); test_signal_assert_hits (sig1, 2); test_signal_assert_hits (sig4, 1); test_signal_assert_hits (sig2, 1); @@ -1557,8 +1557,8 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData) * error in the routine: When removing a lot from an account, the * account reference in the lot object should be NULLed. */ g_assert_true (gnc_lot_get_account (lot) != NULL); - g_assert_cmpuint (g_list_length (a_priv->lots), == , 0); - g_assert_cmpuint (g_list_length (p_priv->lots), == , 0); + g_assert_cmpuint (a_priv->lots.size(), == , 0); + g_assert_cmpuint (p_priv->lots.size(), == , 0); test_signal_assert_hits (sig3, 1); test_signal_assert_hits (sig4, 2); test_signal_assert_hits (sig2, 1); @@ -1567,11 +1567,11 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData) * is removed, we have to do that for the next test to work: */ gnc_lot_set_account (lot, NULL); xaccAccountInsertLot (parent, lot); - g_assert_cmpuint (g_list_length (p_priv->lots), == , 1); + g_assert_cmpuint (p_priv->lots.size(), == , 1); g_assert_true (gnc_lot_get_account (lot) == parent); gnc_lot_destroy (lot); /* Destroying the lot should remove it from the account. */ - g_assert_cmpuint (g_list_length (p_priv->lots), == , 0); + g_assert_cmpuint (p_priv->lots.size(), == , 0); test_signal_assert_hits (sig1, 3); test_signal_assert_hits (sig3, 2); test_signal_assert_hits (sig4, 4);