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:
		| @@ -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; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user