use polymorphism, instead of templates, for walking items

This commit is contained in:
John Wiegley 2004-08-10 18:19:36 -04:00
parent 8792945e76
commit a2efee0a8e
5 changed files with 102 additions and 114 deletions

View file

@ -366,7 +366,7 @@ void format_transaction::operator()(transaction_t * xact) const
xact->total += *xact; xact->total += *xact;
xact->index = last_xact ? last_xact->index + 1 : 0; xact->index = last_xact ? last_xact->index + 1 : 0;
if (disp_pred_functor(xact)) { if (disp_pred(xact)) {
xact->dflags |= TRANSACTION_DISPLAYED; xact->dflags |= TRANSACTION_DISPLAYED;
// This makes the assumption that transactions from a single entry // This makes the assumption that transactions from a single entry
@ -407,7 +407,7 @@ void format_transaction::operator()(transaction_t * xact) const
bool format_account::disp_subaccounts_p(const account_t * account, bool format_account::disp_subaccounts_p(const account_t * account,
const item_predicate<account_t>& const item_predicate<account_t>&
disp_pred_functor, disp_pred,
const account_t *& to_show) const account_t *& to_show)
{ {
bool display = false; bool display = false;
@ -423,7 +423,7 @@ bool format_account::disp_subaccounts_p(const account_t * account,
// expression is equivalent between a parent account and a lone // expression is equivalent between a parent account and a lone
// displayed child, then don't display the parent." // displayed child, then don't display the parent."
if (! (*i).second->total || ! disp_pred_functor((*i).second)) if (! (*i).second->total || ! disp_pred((*i).second))
continue; continue;
if ((*i).second->total != account->total || counted > 0) { if ((*i).second->total != account->total || counted > 0) {
@ -438,8 +438,7 @@ bool format_account::disp_subaccounts_p(const account_t * account,
} }
bool format_account::display_account(const account_t * account, bool format_account::display_account(const account_t * account,
const item_predicate<account_t>& const item_predicate<account_t>& disp_pred)
disp_pred_functor)
{ {
// Never display the master account, or an account that has already // Never display the master account, or an account that has already
// been displayed. // been displayed.
@ -454,10 +453,10 @@ bool format_account::display_account(const account_t * account,
// the predicate. // the predicate.
const account_t * account_to_show = NULL; const account_t * account_to_show = NULL;
if (disp_subaccounts_p(account, disp_pred_functor, account_to_show)) if (disp_subaccounts_p(account, disp_pred, account_to_show))
return true; return true;
return ! account_to_show && disp_pred_functor(account); return ! account_to_show && disp_pred(account);
} }
} // namespace ledger } // namespace ledger

View file

@ -3,6 +3,7 @@
#include "ledger.h" #include "ledger.h"
#include "valexpr.h" #include "valexpr.h"
#include "walk.h"
namespace ledger { namespace ledger {
@ -84,7 +85,7 @@ struct format_t
#define COLLAPSED_REGISTER 1 // support collapsed registers #define COLLAPSED_REGISTER 1 // support collapsed registers
class format_transaction class format_transaction : public item_handler<transaction_t>
{ {
std::ostream& output_stream; std::ostream& output_stream;
const format_t& first_line_format; const format_t& first_line_format;
@ -94,7 +95,7 @@ class format_transaction
#endif #endif
const bool inverted; const bool inverted;
item_predicate<transaction_t> disp_pred_functor; item_predicate<transaction_t> disp_pred;
#ifdef COLLAPSED_REGISTER #ifdef COLLAPSED_REGISTER
mutable balance_pair_t subtotal; mutable balance_pair_t subtotal;
@ -118,14 +119,14 @@ class format_transaction
#ifdef COLLAPSED_REGISTER #ifdef COLLAPSED_REGISTER
collapsed(_collapsed), collapsed(_collapsed),
#endif #endif
inverted(_inverted), disp_pred_functor(display_predicate), inverted(_inverted), disp_pred(display_predicate),
#ifdef COLLAPSED_REGISTER #ifdef COLLAPSED_REGISTER
count(0), count(0),
#endif #endif
last_entry(NULL), last_xact(NULL) {} last_entry(NULL), last_xact(NULL) {}
#ifdef COLLAPSED_REGISTER #ifdef COLLAPSED_REGISTER
~format_transaction() { virtual ~format_transaction() {
if (subtotal) if (subtotal)
report_cumulative_subtotal(); report_cumulative_subtotal();
} }
@ -133,27 +134,26 @@ class format_transaction
void report_cumulative_subtotal() const; void report_cumulative_subtotal() const;
#endif #endif
void operator()(transaction_t * xact) const; virtual void operator()(transaction_t * xact) const;
}; };
template <typename Function> class changed_value_filter : public item_handler<transaction_t>
class changed_value_filter
{ {
const Function& functor; const item_handler<transaction_t>& handler;
mutable entry_t modified_entry; mutable entry_t modified_entry;
mutable transaction_t modified_xact; mutable transaction_t modified_xact;
mutable transaction_t * last_xact; mutable transaction_t * last_xact;
public: public:
changed_value_filter(const Function& _functor) changed_value_filter(const item_handler<transaction_t>& _handler)
: functor(_functor), modified_xact(&modified_entry, NULL), : handler(_handler), modified_xact(&modified_entry, NULL),
last_xact(NULL) { last_xact(NULL) {
modified_entry.payee = "Commodities revalued"; modified_entry.payee = "Commodities revalued";
} }
~changed_value_filter() { virtual ~changed_value_filter() {
(*this)(NULL); (*this)(NULL);
} }
@ -178,35 +178,35 @@ class changed_value_filter
modified_xact.total = diff; modified_xact.total = diff;
modified_xact.total.negate(); modified_xact.total.negate();
functor(&modified_xact); handler(&modified_xact);
} }
} }
if (xact) if (xact)
functor(xact); handler(xact);
last_xact = xact; last_xact = xact;
} }
}; };
class format_account class format_account : public item_handler<account_t>
{ {
std::ostream& output_stream; std::ostream& output_stream;
const format_t& format; const format_t& format;
item_predicate<account_t> disp_pred_functor; item_predicate<account_t> disp_pred;
public: public:
format_account(std::ostream& _output_stream, format_account(std::ostream& _output_stream,
const format_t& _format, const format_t& _format,
const std::string& display_predicate = NULL) const std::string& display_predicate = NULL)
: output_stream(_output_stream), format(_format), : output_stream(_output_stream), format(_format),
disp_pred_functor(display_predicate) {} disp_pred(display_predicate) {}
virtual ~format_account() {}
static bool disp_subaccounts_p(const account_t * account, static bool disp_subaccounts_p(const account_t * account,
const item_predicate<account_t>& const item_predicate<account_t>& disp_pred,
disp_pred_functor,
const account_t *& to_show); const account_t *& to_show);
static bool disp_subaccounts_p(const account_t * account) { static bool disp_subaccounts_p(const account_t * account) {
const account_t * temp; const account_t * temp;
@ -214,11 +214,10 @@ class format_account
} }
static bool display_account(const account_t * account, static bool display_account(const account_t * account,
const item_predicate<account_t>& const item_predicate<account_t>& disp_pred);
disp_pred_functor);
void operator()(const account_t * account) const { virtual void operator()(account_t * account) const {
if (display_account(account, disp_pred_functor)) { if (display_account(account, disp_pred)) {
format.format_elements(output_stream, details_t(account)); format.format_elements(output_stream, details_t(account));
account->dflags |= ACCOUNT_DISPLAYED; account->dflags |= ACCOUNT_DISPLAYED;
} }
@ -226,13 +225,13 @@ class format_account
}; };
class format_equity class format_equity : public item_handler<account_t>
{ {
std::ostream& output_stream; std::ostream& output_stream;
const format_t& first_line_format; const format_t& first_line_format;
const format_t& next_lines_format; const format_t& next_lines_format;
item_predicate<account_t> disp_pred_functor; item_predicate<account_t> disp_pred;
mutable balance_t total; mutable balance_t total;
@ -244,21 +243,21 @@ class format_equity
: output_stream(_output_stream), : output_stream(_output_stream),
first_line_format(_first_line_format), first_line_format(_first_line_format),
next_lines_format(_next_lines_format), next_lines_format(_next_lines_format),
disp_pred_functor(display_predicate) { disp_pred(display_predicate) {
entry_t header_entry; entry_t header_entry;
header_entry.payee = "Opening Balances"; header_entry.payee = "Opening Balances";
header_entry.date = std::time(NULL); header_entry.date = std::time(NULL);
first_line_format.format_elements(output_stream, details_t(&header_entry)); first_line_format.format_elements(output_stream, details_t(&header_entry));
} }
~format_equity() { virtual ~format_equity() {
account_t summary(NULL, "Equity:Opening Balances"); account_t summary(NULL, "Equity:Opening Balances");
summary.value = - total; summary.value = - total;
next_lines_format.format_elements(output_stream, details_t(&summary)); next_lines_format.format_elements(output_stream, details_t(&summary));
} }
void operator()(const account_t * account) const { virtual void operator()(account_t * account) const {
if (format_account::display_account(account, disp_pred_functor)) { if (format_account::display_account(account, disp_pred)) {
next_lines_format.format_elements(output_stream, details_t(account)); next_lines_format.format_elements(output_stream, details_t(account));
account->dflags |= ACCOUNT_DISPLAYED; account->dflags |= ACCOUNT_DISPLAYED;
total += account->value.quantity; total += account->value.quantity;

View file

@ -626,8 +626,7 @@ int main(int argc, char * argv[])
show_inverted); show_inverted);
if (! sort_order.get()) { if (! sort_order.get()) {
if (show_commodities_revalued) { if (show_commodities_revalued) {
changed_value_filter<format_transaction> changed_value_filter filtered_formatter(formatter);
filtered_formatter(formatter);
walk_entries(journal->entries.begin(), journal->entries.end(), walk_entries(journal->entries.begin(), journal->entries.end(),
filtered_formatter, predicate, xact_display_flags); filtered_formatter, predicate, xact_display_flags);
} else { } else {
@ -643,8 +642,7 @@ int main(int argc, char * argv[])
compare_items<transaction_t>(sort_order.get())); compare_items<transaction_t>(sort_order.get()));
if (show_commodities_revalued) { if (show_commodities_revalued) {
changed_value_filter<format_transaction> changed_value_filter filtered_formatter(formatter);
filtered_formatter(formatter);
walk_transactions(transactions_pool.begin(), transactions_pool.end(), walk_transactions(transactions_pool.begin(), transactions_pool.end(),
filtered_formatter); filtered_formatter);
} else { } else {

16
walk.cc
View file

@ -2,30 +2,28 @@
namespace ledger { namespace ledger {
class sum_in_account struct sum_in_account : public item_handler<transaction_t> {
{ virtual void operator()(transaction_t * xact) const {
public:
void operator()(transaction_t * xact) const {
xact->account->value += *xact; xact->account->value += *xact;
} }
}; };
void calc__accounts(account_t * account, void calc__accounts(account_t * account,
const item_predicate<transaction_t>& pred_functor, const item_predicate<transaction_t>& pred,
unsigned int flags) unsigned int flags)
{ {
sum_in_account functor; sum_in_account handler;
for (transactions_list::iterator i = account->transactions.begin(); for (transactions_list::iterator i = account->transactions.begin();
i != account->transactions.end(); i != account->transactions.end();
i++) i++)
if (pred_functor(*i)) if (pred(*i))
handle_transaction(*i, functor, flags); handle_transaction(*i, handler, flags);
for (accounts_map::iterator i = account->accounts.begin(); for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end(); i != account->accounts.end();
i++) i++)
calc__accounts((*i).second, pred_functor, flags); calc__accounts((*i).second, pred, flags);
} }
} // namespace ledger } // namespace ledger

126
walk.h
View file

@ -10,6 +10,11 @@
namespace ledger { namespace ledger {
template <typename T>
struct item_handler {
virtual void operator()(T * item) const = 0;
};
template <typename T> template <typename T>
struct compare_items { struct compare_items {
const node_t * sort_order; const node_t * sort_order;
@ -32,15 +37,14 @@ struct compare_items {
typedef std::deque<transaction_t *> transactions_deque; typedef std::deque<transaction_t *> transactions_deque;
class collect_transactions class collect_transactions : public item_handler<transaction_t> {
{
transactions_deque& transactions; transactions_deque& transactions;
public: public:
collect_transactions(transactions_deque& _transactions) collect_transactions(transactions_deque& _transactions)
: transactions(_transactions) {} : transactions(_transactions) {}
void operator()(transaction_t * xact) const { virtual void operator()(transaction_t * xact) const {
transactions.push_back(xact); transactions.push_back(xact);
} }
}; };
@ -52,19 +56,16 @@ inline void sort_transactions(transactions_deque& transactions,
compare_items<transaction_t>(sort_order)); compare_items<transaction_t>(sort_order));
} }
class ignore_transaction struct ignore_transaction : public item_handler<transaction_t> {
{ virtual void operator()(transaction_t * xact) const {}
public:
void operator()(transaction_t * xact) const {}
}; };
#define MATCHING_TRANSACTIONS 0x01 #define MATCHING_TRANSACTIONS 0x01
#define OTHER_TRANSACTIONS 0x02 #define OTHER_TRANSACTIONS 0x02
template <typename Function> inline void handle_transaction(transaction_t * xact,
void handle_transaction(transaction_t * xact, const item_handler<transaction_t>& handler,
const Function& functor, unsigned int flags)
unsigned int flags)
{ {
for (transactions_list::iterator i = xact->entry->transactions.begin(); for (transactions_list::iterator i = xact->entry->transactions.begin();
i != xact->entry->transactions.end(); i != xact->entry->transactions.end();
@ -75,42 +76,39 @@ void handle_transaction(transaction_t * xact,
(*i == xact ? (*i == xact ?
(flags & MATCHING_TRANSACTIONS) : (flags & OTHER_TRANSACTIONS))) { (flags & MATCHING_TRANSACTIONS) : (flags & OTHER_TRANSACTIONS))) {
(*i)->dflags |= TRANSACTION_HANDLED; (*i)->dflags |= TRANSACTION_HANDLED;
functor(*i); handler(*i);
} }
} }
template <typename Function> inline void walk_entries(entries_list::iterator begin,
void walk_entries(entries_list::iterator begin, entries_list::iterator end,
entries_list::iterator end, const item_handler<transaction_t>& handler,
const Function& functor, const std::string& predicate,
const std::string& predicate, unsigned int flags)
unsigned int flags)
{ {
item_predicate<transaction_t> pred_functor(predicate); item_predicate<transaction_t> pred(predicate);
for (entries_list::iterator i = begin; i != end; i++) for (entries_list::iterator i = begin; i != end; i++)
for (transactions_list::iterator j = (*i)->transactions.begin(); for (transactions_list::iterator j = (*i)->transactions.begin();
j != (*i)->transactions.end(); j != (*i)->transactions.end();
j++) j++)
if (pred_functor(*j)) if (pred(*j))
handle_transaction(*j, functor, flags); handle_transaction(*j, handler, flags);
} }
template <typename Function> inline void walk_entries(entries_list::iterator begin,
void walk_entries(entries_list::iterator begin, entries_list::iterator end,
entries_list::iterator end, const Function& functor) const item_handler<transaction_t>& handler)
{ {
for (entries_list::iterator i = begin; i != end; i++) for (entries_list::iterator i = begin; i != end; i++)
for (transactions_list::iterator j = (*i)->transactions.begin(); for (transactions_list::iterator j = (*i)->transactions.begin();
j != (*i)->transactions.end(); j != (*i)->transactions.end();
j++) j++)
functor(*j); handler(*j);
} }
class clear_flags struct clear_flags : public item_handler<transaction_t> {
{ virtual void operator()(transaction_t * xact) const {
public:
void operator()(transaction_t * xact) const {
xact->dflags = 0; xact->dflags = 0;
} }
}; };
@ -118,25 +116,23 @@ class clear_flags
inline void clear_transaction_display_flags(entries_list::iterator begin, inline void clear_transaction_display_flags(entries_list::iterator begin,
entries_list::iterator end) entries_list::iterator end)
{ {
walk_entries<clear_flags>(begin, end, clear_flags()); walk_entries(begin, end, clear_flags());
} }
template <typename Function> inline void walk_transactions(transactions_list::iterator begin,
void walk_transactions(transactions_list::iterator begin, transactions_list::iterator end,
transactions_list::iterator end, const item_handler<transaction_t>& handler)
const Function& functor)
{ {
for (transactions_list::iterator i = begin; i != end; i++) for (transactions_list::iterator i = begin; i != end; i++)
functor(*i); handler(*i);
} }
template <typename Function> inline void walk_transactions(transactions_deque::iterator begin,
void walk_transactions(transactions_deque::iterator begin, transactions_deque::iterator end,
transactions_deque::iterator end, const item_handler<transaction_t>& handler)
const Function& functor)
{ {
for (transactions_deque::iterator i = begin; i != end; i++) for (transactions_deque::iterator i = begin; i != end; i++)
functor(*i); handler(*i);
} }
typedef std::deque<account_t *> accounts_deque; typedef std::deque<account_t *> accounts_deque;
@ -154,23 +150,22 @@ inline void sort_accounts(account_t * account,
compare_items<account_t>(sort_order)); compare_items<account_t>(sort_order));
} }
template <typename Function> inline void walk__accounts(account_t * account,
void walk__accounts(account_t * account, const Function& functor) const item_handler<account_t>& handler)
{ {
functor(account); handler(account);
for (accounts_map::const_iterator i = account->accounts.begin(); for (accounts_map::const_iterator i = account->accounts.begin();
i != account->accounts.end(); i != account->accounts.end();
i++) i++)
walk__accounts((*i).second, functor); walk__accounts((*i).second, handler);
} }
template <typename Function> inline void walk__accounts_sorted(account_t * account,
void walk__accounts_sorted(account_t * account, const item_handler<account_t>& handler,
const Function& functor, const node_t * sort_order)
const node_t * sort_order)
{ {
functor(account); handler(account);
accounts_deque accounts; accounts_deque accounts;
@ -185,22 +180,22 @@ void walk__accounts_sorted(account_t * account,
for (accounts_deque::const_iterator i = accounts.begin(); for (accounts_deque::const_iterator i = accounts.begin();
i != accounts.end(); i != accounts.end();
i++) i++)
walk__accounts_sorted(*i, functor, sort_order); walk__accounts_sorted(*i, handler, sort_order);
} }
template <typename Function> inline void for_each_account(account_t * account,
void for_each_account(account_t * account, const Function& functor) const item_handler<account_t>& handler)
{ {
functor(account); handler(account);
for (accounts_map::iterator i = account->accounts.begin(); for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end(); i != account->accounts.end();
i++) i++)
walk__accounts((*i).second, functor); walk__accounts((*i).second, handler);
} }
void calc__accounts(account_t * account, void calc__accounts(account_t * account,
const item_predicate<transaction_t>& pred_functor, const item_predicate<transaction_t>& pred,
unsigned int flags); unsigned int flags);
inline void sum__accounts(account_t * account) inline void sum__accounts(account_t * account)
@ -214,24 +209,23 @@ inline void sum__accounts(account_t * account)
account->total += account->value; account->total += account->value;
} }
template <typename Function> inline void walk_accounts(account_t * account,
void walk_accounts(account_t * account, const item_handler<account_t>& handler,
const Function& functor, const std::string& predicate,
const std::string& predicate, unsigned int flags,
unsigned int flags, const bool calc_subtotals,
const bool calc_subtotals, const node_t * sort_order = NULL)
const node_t * sort_order = NULL)
{ {
item_predicate<transaction_t> pred_functor(predicate); item_predicate<transaction_t> pred(predicate);
calc__accounts(account, pred_functor, flags); calc__accounts(account, pred, flags);
if (calc_subtotals) if (calc_subtotals)
sum__accounts(account); sum__accounts(account);
if (sort_order) if (sort_order)
walk__accounts_sorted<Function>(account, functor, sort_order); walk__accounts_sorted(account, handler, sort_order);
else else
walk__accounts<Function>(account, functor); walk__accounts(account, handler);
} }
} // namespace ledger } // namespace ledger