summaryrefslogtreecommitdiff
path: root/walk.h
diff options
context:
space:
mode:
Diffstat (limited to 'walk.h')
-rw-r--r--walk.h234
1 files changed, 234 insertions, 0 deletions
diff --git a/walk.h b/walk.h
new file mode 100644
index 00000000..b509d1dc
--- /dev/null
+++ b/walk.h
@@ -0,0 +1,234 @@
+#ifndef _WALK_H
+#define _WALK_H
+
+#include "ledger.h"
+#include "balance.h"
+#include "format.h"
+#include "valexpr.h"
+
+#include <iostream>
+
+namespace ledger {
+
+class item_predicate
+{
+ const node_t * predicate;
+ balance_pair_t * balance;
+ unsigned int * index;
+
+ public:
+ item_predicate(const node_t * _predicate,
+ balance_pair_t * _balance = NULL,
+ unsigned int * _index = NULL)
+ : predicate(_predicate), balance(_balance), index(_index) {}
+
+ bool operator()(const entry_t * entry) const {
+ if (predicate) {
+ balance_t result;
+ predicate->compute(result, details_t(entry, balance, index));
+ return result;
+ } else {
+ return true;
+ }
+ }
+
+ bool operator()(const transaction_t * xact) const {
+ if (predicate) {
+ balance_t result;
+ predicate->compute(result, details_t(xact, balance, index));
+ return result;
+ } else {
+ return true;
+ }
+ }
+
+ bool operator()(const account_t * account) const {
+ if (predicate) {
+ balance_t result;
+ predicate->compute(result, details_t(account));
+ return result;
+ } else {
+ return true;
+ }
+ }
+};
+
+inline void add_to_balance_pair(balance_pair_t& balance,
+ transaction_t * xact,
+ const bool inverted = false)
+{
+ if (inverted) {
+ balance.quantity += - xact->amount;
+ balance.cost += - xact->cost;
+ } else {
+ balance += *xact;
+ }
+}
+
+class format_transaction
+{
+ std::ostream& output_stream;
+ const format_t& first_line_format;
+ const format_t& next_lines_format;
+ mutable entry_t * last_entry;
+
+ public:
+ format_transaction(std::ostream& _output_stream,
+ const format_t& _first_line_format,
+ const format_t& _next_lines_format)
+ : output_stream(_output_stream),
+ first_line_format(_first_line_format),
+ next_lines_format(_next_lines_format),
+ last_entry(NULL) {}
+
+ void operator()(transaction_t * xact,
+ balance_pair_t * balance,
+ unsigned int * index,
+ const bool inverted) const;
+};
+
+class ignore_transaction
+{
+ public:
+ void operator()(transaction_t * xact,
+ balance_pair_t * balance,
+ unsigned int * index,
+ const bool inverted) const {}
+};
+
+template <typename Function>
+void handle_transaction(transaction_t * xact,
+ Function functor,
+ item_predicate& pred_functor,
+ const bool related,
+ const bool inverted,
+ balance_pair_t * balance = NULL,
+ unsigned int * index = NULL)
+{
+ // If inverted is true, it implies related.
+ if (! inverted && ! (xact->flags & TRANSACTION_HANDLED)) {
+ xact->flags |= TRANSACTION_HANDLED;
+ if (pred_functor(xact)) {
+ xact->flags |= TRANSACTION_DISPLAYED;
+ functor(xact, balance, index, inverted);
+ }
+ }
+
+ if (related)
+ for (transactions_list::iterator i = xact->entry->transactions.begin();
+ i != xact->entry->transactions.end();
+ i++) {
+ if (*i == xact || ((*i)->flags & (TRANSACTION_AUTO |
+ TRANSACTION_HANDLED)))
+ continue;
+
+ (*i)->flags |= TRANSACTION_HANDLED;
+ if (pred_functor(xact)) {
+ xact->flags |= TRANSACTION_DISPLAYED;
+ functor(*i, balance, index, inverted);
+ }
+ }
+}
+
+template <typename Function>
+void walk_entries(entries_list::iterator begin,
+ entries_list::iterator end,
+ Function functor,
+ const node_t * predicate,
+ const bool related,
+ const bool inverted,
+ const node_t * display_predicate = NULL)
+{
+ balance_pair_t balance;
+ unsigned int index;
+ item_predicate pred_functor(predicate, &balance, &index);
+ item_predicate disp_pred_functor(display_predicate, &balance, &index);
+
+ for (entries_list::iterator i = begin; i != end; i++)
+ for (transactions_list::iterator j = (*i)->transactions.begin();
+ j != (*i)->transactions.end();
+ j++)
+ if (pred_functor(*j))
+ handle_transaction(*j, functor, disp_pred_functor,
+ related, inverted, &balance, &index);
+}
+
+class format_account
+{
+ std::ostream& output_stream;
+ const format_t& format;
+
+ mutable const account_t * last_account;
+
+ public:
+ format_account(std::ostream& _output_stream, const format_t& _format)
+ : output_stream(_output_stream), format(_format) {}
+
+ void operator()(const account_t * account, bool report_top = false);
+};
+
+void calc__accounts(account_t * account,
+ const node_t * predicate,
+ const bool related,
+ const bool inverted,
+ const bool calc_subtotals);
+
+template <typename Function>
+void walk__accounts(const account_t * account,
+ Function functor,
+ const node_t * display_predicate)
+{
+ if (! display_predicate || item_predicate(display_predicate)(account))
+ functor(account);
+
+ for (accounts_map::const_iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++)
+ walk__accounts((*i).second, functor, display_predicate);
+}
+
+template <typename Function>
+void walk_accounts(account_t * account,
+ Function functor,
+ const node_t * predicate,
+ const bool related,
+ const bool inverted,
+ const bool calc_subtotals,
+ const node_t * display_predicate = NULL)
+{
+ calc__accounts(account, predicate, related, inverted, calc_subtotals);
+ walk__accounts<Function>(account, functor, display_predicate);
+}
+
+#if 0
+
+void sum_entries(entries_list& entries,
+ account_t * account,
+ const bool show_subtotals)
+{
+ for (entries_list::const_iterator i = entries.begin();
+ i != entries.end();
+ i++)
+ for (transactions_list::const_iterator j = (*i)->transactions.begin();
+ j != (*i)->transactions.end();
+ j++)
+ if ((*j)->account == account) {
+ account->value += *(*j);
+ if (show_subtotals)
+ for (account_t * a = account;
+ a;
+ a = a->parent)
+ a->total += *(*j);
+ }
+
+ for (accounts_map::iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++)
+ sum_items(entries, *i, show_subtotals);
+}
+
+#endif
+
+} // namespace ledger
+
+#endif // _WALK_H