diff options
Diffstat (limited to 'walk.h')
-rw-r--r-- | walk.h | 234 |
1 files changed, 234 insertions, 0 deletions
@@ -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 |