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; 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) GList *gnc_account_list_name_violations (QofBook *book, const gchar *separator)
{ {
Account *root_account = gnc_book_get_root_account(book); g_return_val_if_fail (separator != NULL, nullptr);
GList *accounts, *node; if (!book) return nullptr;
GList *invalid_list = NULL; ViolationData cb = { nullptr, separator };
gnc_account_foreach_descendant (gnc_book_get_root_account (book),
g_return_val_if_fail (separator != NULL, NULL); (AccountCb)check_acct_name, &cb);
return cb.list;
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;
} }
/********************************************************************\ /********************************************************************\
@ -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 void
gnc_account_append_child (Account *new_parent, Account *child) 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)); 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 gint
gnc_account_n_descendants (const Account *account) gnc_account_n_descendants (const Account *account)
{ {
AccountPrivate *priv; int count {0};
GList *node; account_foreach_descendant (account, count_acct, &count, FALSE);
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;
}
return count; return count;
} }
@ -2921,118 +2943,53 @@ gnc_account_get_tree_depth (const Account *account)
return depth + 1; 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 * GList *
gnc_account_get_descendants (const Account *account) gnc_account_get_descendants (const Account *account)
{ {
AccountPrivate *priv; GList* list = nullptr;
GList *child, *descendants; account_foreach_descendant (account, collect_acct, &list, FALSE);
return g_list_reverse (list);
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 * GList *
gnc_account_get_descendants_sorted (const Account *account) gnc_account_get_descendants_sorted (const Account *account)
{ {
AccountPrivate *priv; GList* list = nullptr;
GList *child, *children, *descendants; 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 * Account *
gnc_account_lookup_by_name (const Account *parent, const char * name) gnc_account_lookup_by_name (const Account *parent, const char * name)
{ {
AccountPrivate *cpriv, *ppriv; return (Account*)gnc_account_foreach_descendant_until (parent, is_acct_name, (char*)name);
Account *child, *result;
GList *node;
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. static gpointer
* Recursively search each of the child accounts next */ is_acct_code (Account *account, gpointer user_data)
for (node = ppriv->children; node; node = node->next)
{ {
child = static_cast<Account*>(node->data); auto name {static_cast<gchar*>(user_data)};
result = gnc_account_lookup_by_name (child, name); return (g_strcmp0 (name, xaccAccountGetCode (account)) ? nullptr : account);
if (result)
return result;
}
return NULL;
} }
Account * Account *
gnc_account_lookup_by_code (const Account *parent, const char * code) gnc_account_lookup_by_code (const Account *parent, const char * code)
{ {
AccountPrivate *cpriv, *ppriv; return (Account*)gnc_account_foreach_descendant_until (parent, is_acct_code, (char*)code);
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;
} }
static gpointer static gpointer
@ -3183,20 +3140,7 @@ gnc_account_foreach_descendant (const Account *acc,
AccountCb thunk, AccountCb thunk,
gpointer user_data) gpointer user_data)
{ {
const AccountPrivate *priv; account_foreach_descendant (acc, thunk, user_data, FALSE);
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);
}
} }
gpointer gpointer
@ -3204,28 +3148,24 @@ gnc_account_foreach_descendant_until (const Account *acc,
AccountCb2 thunk, AccountCb2 thunk,
gpointer user_data) gpointer user_data)
{ {
const AccountPrivate *priv; gpointer result {nullptr};
GList *node;
Account *child;
gpointer result;
g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL); g_return_val_if_fail (GNC_IS_ACCOUNT(acc), nullptr);
g_return_val_if_fail(thunk, NULL); g_return_val_if_fail (thunk, nullptr);
priv = GET_PRIVATE(acc); auto priv{GET_PRIVATE(acc)};
for (node = priv->children; node; node = node->next)
for (auto node = priv->children; node; node = node->next)
{ {
child = static_cast<Account*>(node->data); auto child = static_cast<Account*>(node->data);
result = thunk (child, user_data); result = thunk (child, user_data);
if (result) if (result) break;
return(result);
result = gnc_account_foreach_descendant_until (child, thunk, user_data); result = gnc_account_foreach_descendant_until (child, thunk, user_data);
if (result) if (result) break;
return(result);
} }
return NULL; return result;
} }