Account->lots is a std::vector<GNCLot*>

This commit is contained in:
Christopher Lam 2024-10-28 06:48:26 +08:00
parent 35ecad8d21
commit 4c13c2a62b
4 changed files with 36 additions and 51 deletions

View File

@ -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<GNCLot*>(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<GNCLot*>(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<GList*>(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<GNCLot*>(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;

View File

@ -39,6 +39,7 @@
using SplitsVec = std::vector<Split*>;
using AccountVec = std::vector<Account*>;
using LotVec = std::vector<GNCLot*>;
const SplitsVec& xaccAccountGetSplits (const Account*);

View File

@ -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<GNCLot*> lots; /* list of lot pointers */
GNCPolicy *policy; /* Cached pointer to policy method */
char *notes;

View File

@ -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);