Skip to content

Commit 0ff737f

Browse files
[engine.i] convert gnc_account_accumulate_at_dates to c++
traversal of account->splits through std::vector instead of scm_list
1 parent 212effe commit 0ff737f

File tree

2 files changed

+56
-35
lines changed

2 files changed

+56
-35
lines changed

bindings/engine.i

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ using AccountVec = std::vector<Account*>;
6666
SplitsVec gnc_get_match_commodity_splits (AccountVec accounts, bool use_end_date,
6767
time64 end_date, gnc_commodity *comm, bool sort);
6868

69+
SCM gnc_account_accumulate_at_dates (const Account *acc, SCM dates, SCM last_result,
70+
SCM split_to_date, SCM split_to_elt);
71+
6972
AccountVec gnc_accounts_and_all_descendants (AccountVec accounts);
7073

7174
extern "C"
@@ -160,6 +163,58 @@ SplitsVec gnc_get_match_commodity_splits (AccountVec accounts, bool use_end_date
160163
return rv;
161164
}
162165

166+
SCM
167+
gnc_account_accumulate_at_dates (const Account *acc, SCM dates, SCM last_result,
168+
SCM split_to_date, SCM split_to_elt)
169+
{
170+
std::function<SCM(Split*)> get_date;
171+
if (scm_is_false (split_to_date))
172+
get_date = [&](auto s){ return scm_from_int64 (xaccTransGetDate (xaccSplitGetParent (s))); };
173+
else
174+
get_date = [&](auto s){ return scm_call_1 (split_to_date, gnc_split_to_scm (s)); };
175+
176+
// because the guile < function understands +inf.0
177+
auto less_scm = [&](SCM a, SCM b){ return scm_is_true (scm_less_p (a, b)); };
178+
179+
// make a copy of splits vector
180+
auto splits{xaccAccountGetSplits (acc)};
181+
if (!scm_is_false (split_to_date))
182+
std::sort (splits.begin(), splits.end(),
183+
[&](auto a, auto b){ return less_scm (get_date (a), get_date (b)); });
184+
185+
SCM rv = SCM_EOL;
186+
for (auto splits_it = splits.begin(); !scm_is_null (dates); )
187+
{
188+
auto after_date = [&](auto s){ return less_scm (scm_car (dates), get_date (s)); };
189+
auto get_result = [&]() { return scm_call_1 (split_to_elt, gnc_split_to_scm (*splits_it)); };
190+
if (splits_it == splits.end())
191+
{
192+
rv = scm_cons (last_result, rv);
193+
dates = scm_cdr (dates);
194+
}
195+
else if (auto nx_it = std::next (splits_it); nx_it != splits.end() && !after_date (*nx_it))
196+
{
197+
last_result = get_result();
198+
splits_it++;
199+
}
200+
else if (after_date (*splits_it))
201+
{
202+
rv = scm_cons (last_result, rv);
203+
dates = scm_cdr (dates);
204+
}
205+
else
206+
{
207+
last_result = get_result();
208+
rv = scm_cons (last_result, rv);
209+
dates = scm_cdr (dates);
210+
splits_it++;
211+
}
212+
}
213+
214+
return scm_reverse (rv);
215+
}
216+
217+
163218
using AccountSet = std::unordered_set<Account*>;
164219
static void maybe_add_descendants (Account* acc, AccountSet* accset)
165220
{

gnucash/report/report-utilities.scm

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -472,41 +472,7 @@
472472
(nosplit->elt #f)
473473
(split->date #f)
474474
(split->elt xaccSplitGetBalance))
475-
(define to-date (or split->date (compose xaccTransGetDate xaccSplitGetParent)))
476-
(define (less? a b) (< (to-date a) (to-date b)))
477-
478-
(let lp ((splits (if split->date
479-
(sort (xaccAccountGetSplits acc) less?)
480-
(xaccAccountGetSplits acc)))
481-
(dates (sort dates <))
482-
(result '())
483-
(last-result nosplit->elt))
484-
(match dates
485-
486-
;; end of dates. job done!
487-
(() (reverse result))
488-
489-
((date . rest)
490-
(define (before-date? s) (<= (to-date s) date))
491-
(define (after-date? s) (< date (to-date s)))
492-
(cond
493-
494-
;; end of splits, but still has dates. pad with last-result
495-
;; until end of dates.
496-
((null? splits) (lp '() rest (cons last-result result) last-result))
497-
498-
;; the next split is still before date.
499-
((and (pair? (cdr splits)) (before-date? (cadr splits)))
500-
(lp (cdr splits) dates result (split->elt (car splits))))
501-
502-
;; head split after date, accumulate previous result
503-
((after-date? (car splits))
504-
(lp splits rest (cons last-result result) last-result))
505-
506-
;; head split before date, next split after date, or end.
507-
(else
508-
(let ((head-result (split->elt (car splits))))
509-
(lp (cdr splits) rest (cons head-result result) head-result))))))))
475+
(gnc-account-accumulate-at-dates acc dates nosplit->elt split->date split->elt))
510476

511477
;; This works similar as above but returns a commodity-collector,
512478
;; thus takes care of children accounts with different currencies.

0 commit comments

Comments
 (0)