From 68f60fef6803fe1d0153c8af40dd5db835450b84 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Thu, 18 Apr 2024 00:19:10 +0800 Subject: [PATCH] [engine.i] gnc_get_match_commodity_splits from scheme to c++ The scheme version is very inefficient: (1) it uses QofQuery to retrieve all splits, and QofQuery is slow. (2) The whole splitlist typically is thousands splits long needs to be converted from C to guile via consing and reverse. (3) The scheme list is immediately filtered to select "interesting" splits only. This function performs all of the above using Account's efficient methods, selecting only interesting splits into a GList. This list is then converted to scheme via cons and reverse. --- bindings/engine.i | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/bindings/engine.i b/bindings/engine.i index 4ae6c427f3..0546363c68 100644 --- a/bindings/engine.i +++ b/bindings/engine.i @@ -41,6 +41,7 @@ #include "gnc-kvp-guile.h" #include "glib-guile.h" +#include "Account.hpp" #include "gncAddress.h" #include "gncBillTerm.h" #include "gncCustomer.h" @@ -56,6 +57,13 @@ %} #if defined(SWIGGUILE) //Always C++ %{ + +using SplitsVec = std::vector; +using AccountVec = std::vector; + +SplitsVec gnc_get_match_commodity_splits (AccountVec accounts, bool use_end_date, + time64 end_date, gnc_commodity *comm, bool sort); + extern "C" { SCM scm_init_sw_engine_module (void); @@ -117,6 +125,28 @@ static const GncGUID * gncPriceGetGUID(GNCPrice *x) { return qof_instance_get_guid(QOF_INSTANCE(x)); } static const GncGUID * gncBudgetGetGUID(GncBudget *x) { return qof_instance_get_guid(QOF_INSTANCE(x)); } + +SplitsVec gnc_get_match_commodity_splits (AccountVec accounts, bool use_end_date, + time64 end_date, gnc_commodity *comm, bool sort) +{ + auto match = [use_end_date, end_date, comm](const Split* s) -> bool + { + if (xaccSplitGetReconcile (s) == VREC) return false; + auto trans{xaccSplitGetParent (s)}; + if (use_end_date && xaccTransGetDate(trans) > end_date) return false; + auto txn_comm{xaccTransGetCurrency (trans)}; + auto acc_comm{xaccAccountGetCommodity (xaccSplitGetAccount (s))}; + return (txn_comm != acc_comm) && (!comm || comm == txn_comm || comm == acc_comm); + }; + std::vector rv; + auto maybe_accumulate_split = [&rv, match](auto s){ if (match(s)) rv.push_back (s); }; + for (const auto acc : accounts) + gnc_account_foreach_split (acc, maybe_accumulate_split, true); + if (sort) + std::sort (rv.begin(), rv.end(), [](auto a, auto b){ return xaccSplitOrder (a, b) < 0; }); + return rv; +} + %} /* NB: The object ownership annotations should already cover all the