diff options
-rw-r--r-- | src/filters.cc | 43 | ||||
-rw-r--r-- | src/filters.h | 50 |
2 files changed, 92 insertions, 1 deletions
diff --git a/src/filters.cc b/src/filters.cc index 57c95cd3..6915144d 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -39,8 +39,49 @@ namespace ledger { +void post_splitter::print_title(const value_t& val) +{ + if (! report.HANDLED(no_titles)) { + std::ostringstream buf; + val.print(buf); + post_chain->title(buf.str()); + } +} + +void post_splitter::flush() +{ + foreach (value_to_posts_map::value_type pair, posts_map) { + preflush_func(pair.first); + + foreach (post_t * post, pair.second) + (*post_chain)(*post); + + post_chain->flush(); + post_chain->clear(); + + if (postflush_func) + (*postflush_func)(pair.first); + } +} + +void post_splitter::operator()(post_t& post) +{ + bind_scope_t bound_scope(report, post); + value_t result(group_by_expr.calc(bound_scope)); + + value_to_posts_map::iterator i = posts_map.find(result); + if (i != posts_map.end()) { + (*i).second.push_back(&post); + } else { + std::pair<value_to_posts_map::iterator, bool> inserted + = posts_map.insert(value_to_posts_map::value_type(result, posts_list())); + assert(inserted.second); + (*inserted.first).second.push_back(&post); + } +} + pass_down_posts::pass_down_posts(post_handler_ptr handler, - posts_iterator& iter) + posts_iterator& iter) : item_handler<post_t>(handler) { TRACE_CTOR(pass_down_posts, "post_handler_ptr, posts_iterator"); diff --git a/src/filters.h b/src/filters.h index 3f3e3d34..dd6b3b1a 100644 --- a/src/filters.h +++ b/src/filters.h @@ -52,6 +52,56 @@ namespace ledger { ////////////////////////////////////////////////////////////////////// // +// Posting collector +// + +class post_splitter : public item_handler<post_t> +{ +public: + typedef std::map<value_t, posts_list> value_to_posts_map; + typedef function<void (const value_t&)> custom_flusher_t; + +protected: + value_to_posts_map posts_map; + report_t& report; + post_handler_ptr post_chain; + expr_t group_by_expr; + custom_flusher_t preflush_func; + optional<custom_flusher_t> postflush_func; + +public: + post_splitter(report_t& _report, + post_handler_ptr _post_chain, + expr_t _group_by_expr) + : report(_report), post_chain(_post_chain), + group_by_expr(_group_by_expr), + preflush_func(bind(&post_splitter::print_title, this, _1)) { + TRACE_CTOR(post_splitter, "scope_t&, post_handler_ptr, expr_t"); + } + virtual ~post_splitter() { + TRACE_DTOR(post_splitter); + } + + void set_preflush_func(custom_flusher_t functor) { + preflush_func = functor; + } + void set_postflush_func(custom_flusher_t functor) { + postflush_func = functor; + } + + virtual void print_title(const value_t& val); + + virtual void flush(); + virtual void operator()(post_t& post); + + virtual void clear() { + posts_map.clear(); + post_chain->clear(); + } +}; + +////////////////////////////////////////////////////////////////////// +// // Posting filters // |