diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp index 241bdcf9d7..c3bc18f7fc 100644 --- a/libgnucash/engine/Account.cpp +++ b/libgnucash/engine/Account.cpp @@ -3254,12 +3254,6 @@ gnc_account_get_all_parents (const Account *account) gchar * gnc_account_get_full_name(const Account *account) { - AccountPrivate *priv; - const Account *a; - char *fullname; - const gchar **names; - int level; - /* So much for hardening the API. Too many callers to this function don't * bother to check if they have a non-nullptr pointer before calling. */ if (nullptr == account) @@ -3268,35 +3262,24 @@ gnc_account_get_full_name(const Account *account) /* errors */ g_return_val_if_fail(GNC_IS_ACCOUNT(account), g_strdup("")); - /* optimizations */ - priv = GET_PRIVATE(account); - if (!priv->parent) - return g_strdup(""); + auto path{gnc_account_get_all_parents (account)}; + auto seps_size{path.empty() ? 0 : strlen (account_separator) * (path.size() - 1)}; + auto alloc_size{std::accumulate (path.begin(), path.end(), seps_size, + [](auto sum, auto acc) + { return sum + strlen (xaccAccountGetName (acc)); })}; + auto rv = g_new (char, alloc_size + 1); + auto p = rv; - /* Figure out how much space is needed by counting the nodes up to - * the root. */ - level = 0; - for (a = account; a; a = priv->parent) - { - priv = GET_PRIVATE(a); - level++; - } + std::for_each (path.rbegin(), path.rend(), + [&p, rv](auto a) + { + if (p != rv) + p = stpcpy (p, account_separator); + p = stpcpy (p, xaccAccountGetName (a)); + }); + *p = '\0'; - /* Get all the pointers in the right order. The root node "entry" - * becomes the terminating nullptr pointer for the array of strings. */ - names = (const gchar **)g_malloc(level * sizeof(gchar *)); - names[--level] = nullptr; - for (a = account; level > 0; a = priv->parent) - { - priv = GET_PRIVATE(a); - names[--level] = priv->accountName; - } - - /* Build the full name */ - fullname = g_strjoinv(account_separator, (gchar **)names); - g_free(names); - - return fullname; + return rv; } const char * diff --git a/libgnucash/engine/Split.cpp b/libgnucash/engine/Split.cpp index d1b5c37365..64d982214e 100644 --- a/libgnucash/engine/Split.cpp +++ b/libgnucash/engine/Split.cpp @@ -48,6 +48,7 @@ #include "qofbook.h" #include "Split.h" #include "AccountP.hpp" +#include "Account.hpp" #include "Scrub.h" #include "TransactionP.hpp" #include "TransLog.h" @@ -1653,20 +1654,23 @@ int xaccSplitCompareAccountFullNames(const Split *sa, const Split *sb) { Account *aa, *ab; - char *full_a, *full_b; - int retval; - if (!sa && !sb) return 0; + if (sa == sb) return 0; if (!sa) return -1; if (!sb) return 1; aa = sa->acc; ab = sb->acc; - full_a = gnc_account_get_full_name(aa); - full_b = gnc_account_get_full_name(ab); - retval = g_utf8_collate(full_a, full_b); - g_free(full_a); - g_free(full_b); - return retval; + if (aa == ab) return 0; + + auto path_a = gnc_account_get_all_parents (aa); + auto path_b = gnc_account_get_all_parents (ab); + auto mismatch_pair = std::mismatch (path_a.rbegin(), path_a.rend(), + path_b.rbegin(), path_b.rend()); + + return mismatch_pair.first == path_a.rend() ? -1 + : mismatch_pair.second == path_b.rend() ? 1 + : g_utf8_collate (xaccAccountGetName (*mismatch_pair.first), + xaccAccountGetName (*mismatch_pair.second)); }