diff options
Diffstat (limited to 'src/report.cc')
-rw-r--r-- | src/report.cc | 150 |
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_); |