mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge branch 'maint-leaks' into maint #1101
This commit is contained in:
commit
bedc85afa3
@ -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 */
|
static gpointer
|
||||||
g_return_val_if_fail(GNC_IS_ACCOUNT(account), NULL);
|
is_acct_name (Account *account, gpointer user_data)
|
||||||
|
{
|
||||||
/* optimizations */
|
auto name {static_cast<gchar*>(user_data)};
|
||||||
priv = GET_PRIVATE(account);
|
return (g_strcmp0 (name, xaccAccountGetName (account)) ? nullptr : 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
static gpointer
|
||||||
g_return_val_if_fail(name, NULL);
|
is_acct_code (Account *account, gpointer user_data)
|
||||||
|
{
|
||||||
/* first, look for accounts hanging off the current node */
|
auto name {static_cast<gchar*>(user_data)};
|
||||||
ppriv = GET_PRIVATE(parent);
|
return (g_strcmp0 (name, xaccAccountGetCode (account)) ? nullptr : account);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user