Merge branch 'maint-leaks' into maint #1101

This commit is contained in:
Christopher Lam 2021-08-06 19:30:01 +08:00
commit bedc85afa3

View File

@ -262,34 +262,29 @@ gchar *gnc_account_name_violations_errmsg (const gchar *separator, GList* invali
return message;
}
struct ViolationData
{
GList *list;
const gchar *separator;
};
static void
check_acct_name (Account *acct, gpointer user_data)
{
auto cb {static_cast<ViolationData*>(user_data)};
auto name {xaccAccountGetName (acct)};
if (g_strstr_len (name, -1, cb->separator))
cb->list = g_list_prepend (cb->list, g_strdup (name));
}
GList *gnc_account_list_name_violations (QofBook *book, const gchar *separator)
{
Account *root_account = gnc_book_get_root_account(book);
GList *accounts, *node;
GList *invalid_list = NULL;
g_return_val_if_fail (separator != NULL, NULL);
if (root_account == NULL)
return NULL;
accounts = gnc_account_get_descendants (root_account);
for (node = accounts; node; node = g_list_next(node))
{
Account *acct = (Account*)node->data;
gchar *acct_name = g_strdup ( xaccAccountGetName ( acct ) );
if ( g_strstr_len ( acct_name, -1, separator ) )
invalid_list = g_list_prepend ( invalid_list, (gpointer) acct_name );
else
g_free ( acct_name );
}
if (accounts != NULL)
{
g_list_free(accounts);
}
return invalid_list;
g_return_val_if_fail (separator != NULL, nullptr);
if (!book) return nullptr;
ViolationData cb = { nullptr, separator };
gnc_account_foreach_descendant (gnc_book_get_root_account (book),
(AccountCb)check_acct_name, &cb);
return cb.list;
}
/********************************************************************\
@ -2691,6 +2686,35 @@ DxaccAccountSetCurrency (Account * acc, gnc_commodity * currency)
/********************************************************************\
\********************************************************************/
static void
account_foreach_descendant (const Account *acc, AccountCb thunk,
void* user_data, bool sort)
{
GList *children;
g_return_if_fail (GNC_IS_ACCOUNT(acc));
g_return_if_fail (thunk);
auto priv{GET_PRIVATE(acc)};
if (sort)
{
children = g_list_copy (priv->children);
children = g_list_sort (children, (GCompareFunc)xaccAccountOrder);
}
else
children = priv->children;
for (auto node = children; node; node = node->next)
{
auto child = static_cast<Account*>(node->data);
thunk (child, user_data);
account_foreach_descendant (child, thunk, user_data, sort);
}
if (sort)
g_list_free (children);
}
void
gnc_account_append_child (Account *new_parent, Account *child)
{
@ -2864,20 +2888,18 @@ gnc_account_nth_child (const Account *parent, gint num)
return static_cast<Account*>(g_list_nth_data(GET_PRIVATE(parent)->children, num));
}
static void
count_acct (Account *account, gpointer user_data)
{
auto count {static_cast<int*>(user_data)};
++*count;
}
gint
gnc_account_n_descendants (const Account *account)
{
AccountPrivate *priv;
GList *node;
gint count = 0;
g_return_val_if_fail(GNC_IS_ACCOUNT(account), 0);
priv = GET_PRIVATE(account);
for (node = priv->children; node; node = g_list_next(node))
{
count += gnc_account_n_descendants(static_cast<Account*>(node->data)) + 1;
}
int count {0};
account_foreach_descendant (account, count_acct, &count, FALSE);
return count;
}
@ -2921,118 +2943,53 @@ gnc_account_get_tree_depth (const Account *account)
return depth + 1;
}
static void
collect_acct (Account *account, gpointer user_data)
{
auto listptr{static_cast<GList**>(user_data)};
*listptr = g_list_prepend (*listptr, account);
}
GList *
gnc_account_get_descendants (const Account *account)
{
AccountPrivate *priv;
GList *child, *descendants;
g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
priv = GET_PRIVATE(account);
if (!priv->children)
return NULL;
descendants = NULL;
for (child = priv->children; child; child = g_list_next(child))
{
descendants = g_list_append(descendants, child->data);
descendants = g_list_concat(descendants,
gnc_account_get_descendants(static_cast<Account const *>(child->data)));
}
return descendants;
GList* list = nullptr;
account_foreach_descendant (account, collect_acct, &list, FALSE);
return g_list_reverse (list);
}
GList *
gnc_account_get_descendants_sorted (const Account *account)
{
AccountPrivate *priv;
GList *child, *children, *descendants;
GList* list = nullptr;
account_foreach_descendant (account, collect_acct, &list, TRUE);
return g_list_reverse (list);
}
/* errors */
g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
/* optimizations */
priv = GET_PRIVATE(account);
if (!priv->children)
return NULL;
descendants = NULL;
children = g_list_sort(g_list_copy(priv->children), (GCompareFunc)xaccAccountOrder);
for (child = children; child; child = g_list_next(child))
{
descendants = g_list_append(descendants, child->data);
descendants = g_list_concat(descendants,
gnc_account_get_descendants_sorted(static_cast<Account const *>(child->data)));
}
g_list_free(children);
return descendants;
static gpointer
is_acct_name (Account *account, gpointer user_data)
{
auto name {static_cast<gchar*>(user_data)};
return (g_strcmp0 (name, xaccAccountGetName (account)) ? nullptr : account);
}
Account *
gnc_account_lookup_by_name (const Account *parent, const char * name)
{
AccountPrivate *cpriv, *ppriv;
Account *child, *result;
GList *node;
return (Account*)gnc_account_foreach_descendant_until (parent, is_acct_name, (char*)name);
}
g_return_val_if_fail(GNC_IS_ACCOUNT(parent), NULL);
g_return_val_if_fail(name, NULL);
/* first, look for accounts hanging off the current node */
ppriv = GET_PRIVATE(parent);
for (node = ppriv->children; node; node = node->next)
{
child = static_cast<Account*>(node->data);
cpriv = GET_PRIVATE(child);
if (g_strcmp0(cpriv->accountName, name) == 0)
return child;
}
/* if we are still here, then we haven't found the account yet.
* Recursively search each of the child accounts next */
for (node = ppriv->children; node; node = node->next)
{
child = static_cast<Account*>(node->data);
result = gnc_account_lookup_by_name (child, name);
if (result)
return result;
}
return NULL;
static gpointer
is_acct_code (Account *account, gpointer user_data)
{
auto name {static_cast<gchar*>(user_data)};
return (g_strcmp0 (name, xaccAccountGetCode (account)) ? nullptr : account);
}
Account *
gnc_account_lookup_by_code (const Account *parent, const char * code)
{
AccountPrivate *cpriv, *ppriv;
Account *child, *result;
GList *node;
g_return_val_if_fail(GNC_IS_ACCOUNT(parent), NULL);
g_return_val_if_fail(code, NULL);
/* first, look for accounts hanging off the current node */
ppriv = GET_PRIVATE(parent);
for (node = ppriv->children; node; node = node->next)
{
child = static_cast<Account*>(node->data);
cpriv = GET_PRIVATE(child);
if (g_strcmp0(cpriv->accountCode, code) == 0)
return child;
}
/* if we are still here, then we haven't found the account yet.
* Recursively search each of the child accounts next */
for (node = ppriv->children; node; node = node->next)
{
child = static_cast<Account*>(node->data);
result = gnc_account_lookup_by_code (child, code);
if (result)
return result;
}
return NULL;
return (Account*)gnc_account_foreach_descendant_until (parent, is_acct_code, (char*)code);
}
static gpointer
@ -3183,20 +3140,7 @@ gnc_account_foreach_descendant (const Account *acc,
AccountCb thunk,
gpointer user_data)
{
const AccountPrivate *priv;
GList *node;
Account *child;
g_return_if_fail(GNC_IS_ACCOUNT(acc));
g_return_if_fail(thunk);
priv = GET_PRIVATE(acc);
for (node = priv->children; node; node = node->next)
{
child = static_cast<Account*>(node->data);
thunk(child, user_data);
gnc_account_foreach_descendant(child, thunk, user_data);
}
account_foreach_descendant (acc, thunk, user_data, FALSE);
}
gpointer
@ -3204,28 +3148,24 @@ gnc_account_foreach_descendant_until (const Account *acc,
AccountCb2 thunk,
gpointer user_data)
{
const AccountPrivate *priv;
GList *node;
Account *child;
gpointer result;
gpointer result {nullptr};
g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
g_return_val_if_fail(thunk, NULL);
g_return_val_if_fail (GNC_IS_ACCOUNT(acc), nullptr);
g_return_val_if_fail (thunk, nullptr);
priv = GET_PRIVATE(acc);
for (node = priv->children; node; node = node->next)
auto priv{GET_PRIVATE(acc)};
for (auto node = priv->children; node; node = node->next)
{
child = static_cast<Account*>(node->data);
result = thunk(child, user_data);
if (result)
return(result);
auto child = static_cast<Account*>(node->data);
result = thunk (child, user_data);
if (result) break;
result = gnc_account_foreach_descendant_until(child, thunk, user_data);
if (result)
return(result);
result = gnc_account_foreach_descendant_until (child, thunk, user_data);
if (result) break;
}
return NULL;
return result;
}