summaryrefslogtreecommitdiff
path: root/src/report.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/report.cc')
-rw-r--r--src/report.cc150
1 files changed, 116 insertions, 34 deletions
diff --git a/src/report.cc b/src/report.cc
index f3186e0b..dcb56319 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -274,10 +274,35 @@ void report_t::parse_query_args(const value_t& args, const string& whence)
}
}
+namespace {
+ struct posts_flusher
+ {
+ report_t& report;
+ post_handler_ptr handler;
+
+ posts_flusher(report_t& _report, post_handler_ptr _handler)
+ : report(_report), handler(_handler) {}
+
+ void operator()(const value_t&) {
+ report.session.journal->clear_xdata();
+ }
+ };
+}
+
void report_t::posts_report(post_handler_ptr handler)
{
+ handler = chain_post_handlers(*this, handler);
+ if (HANDLED(group_by_)) {
+ std::auto_ptr<post_splitter>
+ splitter(new post_splitter(*this, handler, HANDLER(group_by_).expr));
+ splitter->set_postflush_func(posts_flusher(*this, handler));
+ handler = post_handler_ptr(splitter.release());
+ }
+ handler = chain_pre_post_handlers(*this, handler);
+
journal_posts_iterator walker(*session.journal.get());
- pass_down_posts(chain_post_handlers(*this, handler), walker);
+ pass_down_posts(handler, walker);
+
session.journal->clear_xdata();
}
@@ -285,66 +310,121 @@ void report_t::generate_report(post_handler_ptr handler)
{
HANDLER(limit_).on(string("#generate"), "actual");
+ handler = chain_handlers(*this, handler);
+
generate_posts_iterator walker
(session, HANDLED(seed_) ?
static_cast<unsigned int>(HANDLER(seed_).value.to_long()) : 0,
HANDLED(head_) ?
static_cast<unsigned int>(HANDLER(head_).value.to_long()) : 50);
- pass_down_posts(chain_post_handlers(*this, handler), walker);
+ pass_down_posts(handler, walker);
}
void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
{
+ handler = chain_handlers(*this, handler);
+
xact_posts_iterator walker(xact);
- pass_down_posts(chain_post_handlers(*this, handler), walker);
+ pass_down_posts(handler, walker);
+
xact.clear_xdata();
}
+namespace {
+ struct accounts_title_printer
+ {
+ report_t& report;
+ acct_handler_ptr handler;
+
+ accounts_title_printer(report_t& _report, acct_handler_ptr _handler)
+ : report(_report), handler(_handler) {}
+
+ void operator()(const value_t& val)
+ {
+ if (! report.HANDLED(no_titles)) {
+ std::ostringstream buf;
+ val.print(buf);
+ handler->title(buf.str());
+ }
+ }
+ };
+
+ struct accounts_flusher
+ {
+ report_t& report;
+ acct_handler_ptr handler;
+
+ accounts_flusher(report_t& _report, acct_handler_ptr _handler)
+ : report(_report), handler(_handler) {}
+
+ void operator()(const value_t&)
+ {
+ report.HANDLER(amount_).expr.mark_uncompiled();
+ report.HANDLER(total_).expr.mark_uncompiled();
+ report.HANDLER(display_amount_).expr.mark_uncompiled();
+ report.HANDLER(display_total_).expr.mark_uncompiled();
+ report.HANDLER(revalued_total_).expr.mark_uncompiled();
+
+ scoped_ptr<accounts_iterator> iter;
+ if (! report.HANDLED(sort_)) {
+ iter.reset(new basic_accounts_iterator(*report.session.journal->master));
+ } else {
+ expr_t sort_expr(report.HANDLER(sort_).str());
+ sort_expr.set_context(&report);
+ iter.reset(new sorted_accounts_iterator(*report.session.journal->master,
+ sort_expr, report.HANDLED(flat)));
+ }
+
+ if (report.HANDLED(display_)) {
+ DEBUG("report.predicate",
+ "Display predicate = " << report.HANDLER(display_).str());
+ pass_down_accounts(handler, *iter.get(),
+ predicate_t(report.HANDLER(display_).str(),
+ report.what_to_keep()),
+ report);
+ } else {
+ pass_down_accounts(handler, *iter.get());
+ }
+
+ report.session.journal->clear_xdata();
+ }
+ };
+}
+
void report_t::accounts_report(acct_handler_ptr handler)
{
- journal_posts_iterator walker(*session.journal.get());
-
- // The lifetime of the chain object controls the lifetime of all temporary
- // objects created within it during the call to pass_down_posts, which will
- // be needed later by the pass_down_accounts.
post_handler_ptr chain =
- chain_post_handlers(*this, post_handler_ptr(new ignore_posts), true);
- pass_down_posts(chain, walker);
+ chain_post_handlers(*this, post_handler_ptr(new ignore_posts),
+ /* for_accounts_report= */ true);
+ if (HANDLED(group_by_)) {
+ std::auto_ptr<post_splitter>
+ splitter(new post_splitter(*this, chain, HANDLER(group_by_).expr));
- HANDLER(amount_).expr.mark_uncompiled();
- HANDLER(total_).expr.mark_uncompiled();
- HANDLER(display_amount_).expr.mark_uncompiled();
- HANDLER(display_total_).expr.mark_uncompiled();
- HANDLER(revalued_total_).expr.mark_uncompiled();
+ splitter->set_preflush_func(accounts_title_printer(*this, handler));
+ splitter->set_postflush_func(accounts_flusher(*this, handler));
- scoped_ptr<accounts_iterator> iter;
- if (! HANDLED(sort_)) {
- iter.reset(new basic_accounts_iterator(*session.journal->master));
- } else {
- expr_t sort_expr(HANDLER(sort_).str());
- sort_expr.set_context(this);
- iter.reset(new sorted_accounts_iterator(*session.journal->master,
- sort_expr, HANDLED(flat)));
+ chain = post_handler_ptr(splitter.release());
}
+ chain = chain_pre_post_handlers(*this, chain);
- if (HANDLED(display_)) {
- DEBUG("report.predicate",
- "Display predicate = " << HANDLER(display_).str());
- pass_down_accounts(handler, *iter.get(),
- predicate_t(HANDLER(display_).str(), what_to_keep()),
- *this);
- } else {
- pass_down_accounts(handler, *iter.get());
- }
+ // The lifetime of the chain object controls the lifetime of all temporary
+ // objects created within it during the call to pass_down_posts, which will
+ // be needed later by the pass_down_accounts.
+ journal_posts_iterator walker(*session.journal.get());
+ pass_down_posts(chain, walker);
- session.journal->clear_xdata();
+ if (! HANDLED(group_by_))
+ accounts_flusher(*this, handler)(value_t());
}
void report_t::commodities_report(post_handler_ptr handler)
{
+ handler = chain_handlers(*this, handler);
+
posts_commodities_iterator walker(*session.journal.get());
- pass_down_posts(chain_post_handlers(*this, handler), walker);
+ pass_down_posts(handler, walker);
+
session.journal->clear_xdata();
}
@@ -888,6 +968,8 @@ option_t<report_t> * report_t::lookup_option(const char * p)
break;
case 'g':
OPT(gain);
+ else OPT(group_by_);
+ else OPT(group_title_format_);
break;
case 'h':
OPT(head_);