summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2011-07-19 23:29:41 -0500
committerJohn Wiegley <johnw@newartisans.com>2011-07-19 23:29:41 -0500
commitcf35984971341b8a8688eb02a22bcbc1772991d1 (patch)
tree8defec43b26a6cf9a216dac8b41d79504c32ad93 /src
parent966b6fc359bacad6b22e79fd5afbec0ea80e8d6a (diff)
downloadfork-ledger-cf35984971341b8a8688eb02a22bcbc1772991d1.tar.gz
fork-ledger-cf35984971341b8a8688eb02a22bcbc1772991d1.tar.bz2
fork-ledger-cf35984971341b8a8688eb02a22bcbc1772991d1.zip
Use Boost iterator_facade to create new iterators
Diffstat (limited to 'src')
-rw-r--r--src/convert.cc6
-rw-r--r--src/filters.cc40
-rw-r--r--src/filters.h42
-rw-r--r--src/generate.cc10
-rw-r--r--src/generate.h6
-rw-r--r--src/iterators.cc111
-rw-r--r--src/iterators.h110
-rw-r--r--src/py_journal.cc2
-rw-r--r--src/report.cc49
-rw-r--r--src/system.hh.in1
10 files changed, 211 insertions, 166 deletions
diff --git a/src/convert.cc b/src/convert.cc
index 3a9a143d..5d4925c4 100644
--- a/src/convert.cc
+++ b/src/convert.cc
@@ -62,10 +62,10 @@ value_t convert_command(call_scope_t& args)
post_map_t post_map;
xacts_iterator journal_iter(journal);
- while (xact_t * xact = journal_iter()) {
+ while (xact_t * xact = *journal_iter++) {
post_t * post = NULL;
xact_posts_iterator xact_iter(*xact);
- while ((post = xact_iter()) != NULL) {
+ while ((post = *xact_iter++) != NULL) {
if (post->account == bucket)
break;
}
@@ -137,7 +137,7 @@ value_t convert_command(call_scope_t& args)
}
else {
xact_posts_iterator xact_iter(*xact);
- while (post_t * post = xact_iter())
+ while (post_t * post = *xact_iter++)
formatter(*post);
}
}
diff --git a/src/filters.cc b/src/filters.cc
index 27227ee9..b7e96366 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -83,25 +83,6 @@ void post_splitter::operator()(post_t& post)
}
}
-pass_down_posts::pass_down_posts(post_handler_ptr handler,
- posts_iterator& iter)
- : item_handler<post_t>(handler)
-{
- TRACE_CTOR(pass_down_posts, "post_handler_ptr, posts_iterator");
-
- for (post_t * post = iter(); post; post = iter()) {
- try {
- item_handler<post_t>::operator()(*post);
- }
- catch (const std::exception&) {
- add_error_context(item_context(*post, _("While handling posting")));
- throw;
- }
- }
-
- item_handler<post_t>::flush();
-}
-
void truncate_xacts::flush()
{
if (! posts.size())
@@ -1419,25 +1400,4 @@ void inject_posts::operator()(post_t& post)
item_handler<post_t>::operator()(post);
}
-pass_down_accounts::pass_down_accounts(acct_handler_ptr handler,
- accounts_iterator& iter,
- const optional<predicate_t>& _pred,
- const optional<scope_t&>& _context)
- : item_handler<account_t>(handler), pred(_pred), context(_context)
-{
- TRACE_CTOR(pass_down_accounts, "acct_handler_ptr, accounts_iterator, ...");
-
- for (account_t * account = iter(); account; account = iter()) {
- if (! pred) {
- item_handler<account_t>::operator()(*account);
- } else {
- bind_scope_t bound_scope(*context, *account);
- if ((*pred)(bound_scope))
- item_handler<account_t>::operator()(*account);
- }
- }
-
- item_handler<account_t>::flush();
-}
-
} // namespace ledger
diff --git a/src/filters.h b/src/filters.h
index 2fcf0961..4c096571 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -146,14 +146,28 @@ public:
}
};
-class posts_iterator;
-
+template <typename Iterator>
class pass_down_posts : public item_handler<post_t>
{
pass_down_posts();
public:
- pass_down_posts(post_handler_ptr handler, posts_iterator& iter);
+ pass_down_posts(post_handler_ptr handler, Iterator& iter)
+ : item_handler<post_t>(handler) {
+ TRACE_CTOR(pass_down_posts, "post_handler_ptr, posts_iterator");
+
+ while (post_t * post = *iter++) {
+ try {
+ item_handler<post_t>::operator()(*post);
+ }
+ catch (const std::exception&) {
+ add_error_context(item_context(*post, _("While handling posting")));
+ throw;
+ }
+ }
+
+ item_handler<post_t>::flush();
+ }
virtual ~pass_down_posts() {
TRACE_DTOR(pass_down_posts);
@@ -986,8 +1000,7 @@ class inject_posts : public item_handler<post_t>
// Account filters
//
-class accounts_iterator;
-
+template <typename Iterator>
class pass_down_accounts : public item_handler<account_t>
{
pass_down_accounts();
@@ -997,9 +1010,24 @@ class pass_down_accounts : public item_handler<account_t>
public:
pass_down_accounts(acct_handler_ptr handler,
- accounts_iterator& iter,
+ Iterator& iter,
const optional<predicate_t>& _pred = none,
- const optional<scope_t&>& _context = none);
+ const optional<scope_t&>& _context = none)
+ : item_handler<account_t>(handler), pred(_pred), context(_context) {
+ TRACE_CTOR(pass_down_accounts, "acct_handler_ptr, accounts_iterator, ...");
+
+ while (account_t * account = *iter++) {
+ if (! pred) {
+ item_handler<account_t>::operator()(*account);
+ } else {
+ bind_scope_t bound_scope(*context, *account);
+ if ((*pred)(bound_scope))
+ item_handler<account_t>::operator()(*account);
+ }
+ }
+
+ item_handler<account_t>::flush();
+ }
virtual ~pass_down_accounts() {
TRACE_DTOR(pass_down_accounts);
diff --git a/src/generate.cc b/src/generate.cc
index 05f754e6..60c6955e 100644
--- a/src/generate.cc
+++ b/src/generate.cc
@@ -350,9 +350,10 @@ void generate_posts_iterator::generate_xact(std::ostream& out)
out << '\n';
}
-post_t * generate_posts_iterator::operator()()
+void generate_posts_iterator::increment()
{
- post_t * post = posts();
+ post_t * post = *posts++;
+
if (post == NULL && quantity > 0) {
std::ostringstream buf;
generate_xact(buf);
@@ -364,7 +365,7 @@ post_t * generate_posts_iterator::operator()()
if (session.journal->parse(in, session) != 0) {
VERIFY(session.journal->xacts.back()->valid());
posts.reset(*session.journal->xacts.back());
- post = posts();
+ post = *posts++;
}
}
catch (std::exception&) {
@@ -382,7 +383,8 @@ post_t * generate_posts_iterator::operator()()
quantity--;
}
- return post;
+
+ m_node = post;
}
} // namespace ledger
diff --git a/src/generate.h b/src/generate.h
index 25ad41ea..f9207ff5 100644
--- a/src/generate.h
+++ b/src/generate.h
@@ -48,7 +48,9 @@ namespace ledger {
class session_t;
-class generate_posts_iterator : public posts_iterator
+class generate_posts_iterator
+ : public iterator_facade_base<generate_posts_iterator, post_t *,
+ boost::forward_traversal_tag>
{
session_t& session;
unsigned int seed;
@@ -105,7 +107,7 @@ public:
TRACE_DTOR(generate_posts_iterator);
}
- virtual post_t * operator()();
+ virtual void increment();
protected:
void generate_string(std::ostream& out, int len, bool only_alpha = false);
diff --git a/src/iterators.cc b/src/iterators.cc
index b63a10e9..bb7a587c 100644
--- a/src/iterators.cc
+++ b/src/iterators.cc
@@ -41,37 +41,38 @@ void xacts_iterator::reset(journal_t& journal)
{
xacts_i = journal.xacts.begin();
xacts_end = journal.xacts.end();
+
xacts_uninitialized = false;
+
+ increment();
}
-xact_t * xacts_iterator::operator()()
+void xacts_iterator::increment()
{
if (xacts_i != xacts_end)
- return *xacts_i++;
+ m_node = *xacts_i++;
else
- return NULL;
+ m_node = NULL;
}
void journal_posts_iterator::reset(journal_t& journal)
{
xacts.reset(journal);
-
- xact_t * xact = xacts();
- if (xact != NULL)
- posts.reset(*xact);
+ increment();
}
-post_t * journal_posts_iterator::operator()()
+void journal_posts_iterator::increment()
{
- post_t * post = posts();
- if (post == NULL) {
- xact_t * xact = xacts();
- if (xact != NULL) {
- posts.reset(*xact);
- post = posts();
- }
+ if (post_t * post = *posts++) {
+ m_node = post;
+ }
+ else if (xact_t * xact = *xacts++) {
+ posts.reset(*xact);
+ m_node = *posts++;
+ }
+ else {
+ m_node = NULL;
}
- return post;
}
void posts_commodities_iterator::reset(journal_t& journal)
@@ -80,7 +81,7 @@ void posts_commodities_iterator::reset(journal_t& journal)
std::set<commodity_t *> commodities;
- for (post_t * post = journal_posts(); post; post = journal_posts()) {
+ while (const post_t * post = *journal_posts++) {
commodity_t& comm(post->amount.commodity());
if (comm.flags() & COMMODITY_NOMARKET)
continue;
@@ -136,47 +137,44 @@ void posts_commodities_iterator::reset(journal_t& journal)
}
}
- xacts.xacts_i = xact_temps.begin();
- xacts.xacts_end = xact_temps.end();
+ xacts.reset(xact_temps.begin(), xact_temps.end());
- xacts.xacts_uninitialized = false;
-
- xact_t * xact = xacts();
- if (xact != NULL)
- posts.reset(*xact);
+ increment();
}
-post_t * posts_commodities_iterator::operator()()
+void posts_commodities_iterator::increment()
{
- post_t * post = posts();
- if (post == NULL) {
- xact_t * xact = xacts();
- if (xact != NULL) {
- posts.reset(*xact);
- post = posts();
- }
+ if (post_t * post = *posts++) {
+ m_node = post;
+ }
+ else if (xact_t * xact = *xacts++) {
+ posts.reset(*xact);
+ m_node = *posts++;
+ }
+ else {
+ m_node = NULL;
}
- return post;
}
-account_t * basic_accounts_iterator::operator()()
+void basic_accounts_iterator::increment()
{
- while (! accounts_i.empty() &&
- accounts_i.back() == accounts_end.back()) {
+ while (! accounts_i.empty() && accounts_i.back() == accounts_end.back()) {
accounts_i.pop_back();
accounts_end.pop_back();
}
- if (accounts_i.empty())
- return NULL;
- account_t * account = (*(accounts_i.back()++)).second;
- assert(account);
+ if (accounts_i.empty()) {
+ m_node = NULL;
+ } else {
+ account_t * account = (*(accounts_i.back()++)).second;
+ assert(account);
- // If this account has children, queue them up to be iterated next.
- if (! account->accounts.empty())
- push_back(*account);
+ // If this account has children, queue them up to be iterated next.
+ if (! account->accounts.empty())
+ push_back(*account);
- return account;
+ m_node = account;
+ }
}
void sorted_accounts_iterator::push_back(account_t& account)
@@ -231,7 +229,7 @@ void sorted_accounts_iterator::sort_accounts(account_t& account,
#endif
}
-account_t * sorted_accounts_iterator::operator()()
+void sorted_accounts_iterator::increment()
{
while (! sorted_accounts_i.empty() &&
sorted_accounts_i.back() == sorted_accounts_end.back()) {
@@ -240,19 +238,22 @@ account_t * sorted_accounts_iterator::operator()()
assert(! accounts_list.empty());
accounts_list.pop_back();
}
- if (sorted_accounts_i.empty())
- return NULL;
- account_t * account = *sorted_accounts_i.back()++;
- assert(account);
+ if (sorted_accounts_i.empty()) {
+ m_node = NULL;
+ } else {
+ account_t * account = *sorted_accounts_i.back()++;
+ assert(account);
+
+ // If this account has children, queue them up to be iterated next.
+ if (! flatten_all && ! account->accounts.empty())
+ push_back(*account);
- // If this account has children, queue them up to be iterated next.
- if (! flatten_all && ! account->accounts.empty())
- push_back(*account);
+ // Make sure the sorting value gets recalculated for this account
+ account->xdata().drop_flags(ACCOUNT_EXT_SORT_CALC);
- // Make sure the sorting value gets recalculated for this account
- account->xdata().drop_flags(ACCOUNT_EXT_SORT_CALC);
- return account;
+ m_node = account;
+ }
}
} // namespace ledger
diff --git a/src/iterators.h b/src/iterators.h
index 5113d3b2..696b5911 100644
--- a/src/iterators.h
+++ b/src/iterators.h
@@ -51,14 +51,35 @@ namespace ledger {
class journal_t;
-class posts_iterator : public noncopyable
+template <typename Derived, typename Value, typename CategoryOrTraversal>
+class iterator_facade_base
+ : public boost::iterator_facade<Derived, Value, CategoryOrTraversal>
{
+ typedef Value node_base;
+
public:
- virtual ~posts_iterator() throw() {}
- virtual post_t * operator()() = 0;
+ iterator_facade_base() : m_node(NULL) {}
+
+ explicit iterator_facade_base(node_base p) : m_node(p) {}
+
+ void increment();
+
+private:
+ friend class boost::iterator_core_access;
+
+ bool equal(iterator_facade_base const& other) const {
+ return this->m_node == other.m_node;
+ }
+
+ node_base& dereference() const { return const_cast<node_base&>(m_node); }
+
+protected:
+ node_base m_node;
};
-class xact_posts_iterator : public posts_iterator
+class xact_posts_iterator
+ : public iterator_facade_base<xact_posts_iterator, post_t *,
+ boost::forward_traversal_tag>
{
posts_list::iterator posts_i;
posts_list::iterator posts_end;
@@ -74,7 +95,7 @@ public:
TRACE_CTOR(xact_posts_iterator, "xact_t&");
reset(xact);
}
- virtual ~xact_posts_iterator() throw() {
+ ~xact_posts_iterator() throw() {
TRACE_DTOR(xact_posts_iterator);
}
@@ -83,16 +104,21 @@ public:
posts_end = xact.posts.end();
posts_uninitialized = false;
+
+ increment();
}
- virtual post_t * operator()() {
+ void increment() {
if (posts_uninitialized || posts_i == posts_end)
- return NULL;
- return *posts_i++;
+ m_node = NULL;
+ else
+ m_node = *posts_i++;
}
};
-class xacts_iterator : public noncopyable
+class xacts_iterator
+ : public iterator_facade_base<xacts_iterator, xact_t *,
+ boost::forward_traversal_tag>
{
public:
xacts_list::iterator xacts_i;
@@ -103,22 +129,35 @@ public:
xacts_iterator() : xacts_uninitialized(true) {
TRACE_CTOR(xacts_iterator, "");
}
- xacts_iterator(journal_t& journal) : xacts_uninitialized(true) {
+ xacts_iterator(journal_t& journal) : xacts_uninitialized(false) {
TRACE_CTOR(xacts_iterator, "journal_t&");
reset(journal);
}
- virtual ~xacts_iterator() throw() {
+ xacts_iterator(xacts_list::iterator beg,
+ xacts_list::iterator end) : xacts_uninitialized(false) {
+ TRACE_CTOR(xacts_iterator, "xacts_list::iterator, xacts_list::iterator");
+ reset(beg, end);
+ }
+ ~xacts_iterator() throw() {
TRACE_DTOR(xacts_iterator);
}
void reset(journal_t& journal);
- xact_t * operator()();
+ void reset(xacts_list::iterator beg, xacts_list::iterator end) {
+ xacts_i = beg;
+ xacts_end = end;
+ increment();
+ }
+
+ void increment();
};
-class journal_posts_iterator : public posts_iterator
+class journal_posts_iterator
+ : public iterator_facade_base<journal_posts_iterator, post_t *,
+ boost::forward_traversal_tag>
{
- xacts_iterator xacts;
+ xacts_iterator xacts;
xact_posts_iterator posts;
public:
@@ -129,16 +168,18 @@ public:
TRACE_CTOR(journal_posts_iterator, "journal_t&");
reset(journal);
}
- virtual ~journal_posts_iterator() throw() {
+ ~journal_posts_iterator() throw() {
TRACE_DTOR(journal_posts_iterator);
}
void reset(journal_t& journal);
- virtual post_t * operator()();
+ void increment();
};
-class posts_commodities_iterator : public posts_iterator
+class posts_commodities_iterator
+ : public iterator_facade_base<posts_commodities_iterator, post_t *,
+ boost::forward_traversal_tag>
{
protected:
journal_posts_iterator journal_posts;
@@ -155,23 +196,18 @@ public:
TRACE_CTOR(posts_commodities_iterator, "journal_t&");
reset(journal);
}
- virtual ~posts_commodities_iterator() throw() {
+ ~posts_commodities_iterator() throw() {
TRACE_DTOR(posts_commodities_iterator);
}
void reset(journal_t& journal);
- virtual post_t * operator()();
-};
-
-class accounts_iterator : public noncopyable
-{
-public:
- virtual ~accounts_iterator() throw() {}
- virtual account_t * operator()() = 0;
+ void increment();
};
-class basic_accounts_iterator : public accounts_iterator
+class basic_accounts_iterator
+ : public iterator_facade_base<basic_accounts_iterator, account_t *,
+ boost::forward_traversal_tag>
{
std::list<accounts_map::const_iterator> accounts_i;
std::list<accounts_map::const_iterator> accounts_end;
@@ -183,20 +219,24 @@ public:
basic_accounts_iterator(account_t& account) {
TRACE_CTOR(basic_accounts_iterator, "account_t&");
push_back(account);
+ increment();
}
- virtual ~basic_accounts_iterator() throw() {
+ ~basic_accounts_iterator() throw() {
TRACE_DTOR(basic_accounts_iterator);
}
+ void increment();
+
+private:
void push_back(account_t& account) {
accounts_i.push_back(account.accounts.begin());
accounts_end.push_back(account.accounts.end());
}
-
- virtual account_t * operator()();
};
-class sorted_accounts_iterator : public accounts_iterator
+class sorted_accounts_iterator
+ : public iterator_facade_base<sorted_accounts_iterator, account_t *,
+ boost::forward_traversal_tag>
{
expr_t sort_cmp;
bool flatten_all;
@@ -213,16 +253,18 @@ public:
: sort_cmp(_sort_cmp), flatten_all(_flatten_all) {
TRACE_CTOR(sorted_accounts_iterator, "const expr_t&, bool, account_t&");
push_back(account);
+ increment();
}
- virtual ~sorted_accounts_iterator() throw() {
+ ~sorted_accounts_iterator() throw() {
TRACE_DTOR(sorted_accounts_iterator);
}
+ void increment();
+
+private:
void push_back(account_t& account);
void push_all(account_t& account, accounts_deque_t& deque);
void sort_accounts(account_t& account, accounts_deque_t& deque);
-
- virtual account_t * operator()();
};
} // namespace ledger
diff --git a/src/py_journal.cc b/src/py_journal.cc
index a06ef8e2..cb629f62 100644
--- a/src/py_journal.cc
+++ b/src/py_journal.cc
@@ -191,7 +191,7 @@ namespace {
coll->chain =
chain_post_handlers(post_handler_ptr(coll->posts_collector),
coll->report);
- pass_down_posts(coll->chain, walker);
+ pass_down_posts<journal_posts_iterator>(coll->chain, walker);
}
catch (...) {
current_report.session.journal.release();
diff --git a/src/report.cc b/src/report.cc
index 5fff77c7..91b9025d 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -318,7 +318,7 @@ void report_t::posts_report(post_handler_ptr handler)
handler = chain_pre_post_handlers(handler, *this);
journal_posts_iterator walker(*session.journal.get());
- pass_down_posts(handler, walker);
+ pass_down_posts<journal_posts_iterator>(handler, walker);
if (! HANDLED(group_by_))
posts_flusher(handler, *this)(value_t());
@@ -334,7 +334,7 @@ void report_t::generate_report(post_handler_ptr handler)
HANDLED(head_) ?
static_cast<unsigned int>(HANDLER(head_).value.to_long()) : 50);
- pass_down_posts(handler, walker);
+ pass_down_posts<generate_posts_iterator>(handler, walker);
}
void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
@@ -342,7 +342,7 @@ void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
handler = chain_handlers(handler, *this);
xact_posts_iterator walker(xact);
- pass_down_posts(handler, walker);
+ pass_down_posts<xact_posts_iterator>(handler, walker);
xact.clear_xdata();
}
@@ -382,25 +382,34 @@ namespace {
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);
+ if (! report.HANDLED(sort_)) {
+ basic_accounts_iterator iter(*report.session.journal->master);
+ pass_down_accounts<basic_accounts_iterator>
+ (handler, iter, predicate_t(report.HANDLER(display_).str(),
+ report.what_to_keep()), report);
+ } else {
+ expr_t sort_expr(report.HANDLER(sort_).str());
+ sort_expr.set_context(&report);
+ sorted_accounts_iterator iter(*report.session.journal->master,
+ sort_expr, report.HANDLED(flat));
+ pass_down_accounts<sorted_accounts_iterator>
+ (handler, iter, predicate_t(report.HANDLER(display_).str(),
+ report.what_to_keep()), report);
+ }
} else {
- pass_down_accounts(handler, *iter.get());
+ if (! report.HANDLED(sort_)) {
+ basic_accounts_iterator iter(*report.session.journal->master);
+ pass_down_accounts<basic_accounts_iterator>(handler, iter);
+ } else {
+ expr_t sort_expr(report.HANDLER(sort_).str());
+ sort_expr.set_context(&report);
+ sorted_accounts_iterator iter(*report.session.journal->master,
+ sort_expr, report.HANDLED(flat));
+ pass_down_accounts<sorted_accounts_iterator>(handler, iter);
+ }
}
report.session.journal->clear_xdata();
@@ -428,7 +437,7 @@ void report_t::accounts_report(acct_handler_ptr handler)
// 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);
+ pass_down_posts<journal_posts_iterator>(chain, walker);
if (! HANDLED(group_by_))
accounts_flusher(handler, *this)(value_t());
@@ -439,7 +448,7 @@ void report_t::commodities_report(post_handler_ptr handler)
handler = chain_handlers(handler, *this);
posts_commodities_iterator walker(*session.journal.get());
- pass_down_posts(handler, walker);
+ pass_down_posts<posts_commodities_iterator>(handler, walker);
session.journal->clear_xdata();
}
diff --git a/src/system.hh.in b/src/system.hh.in
index f71dce68..2077d3a8 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -158,6 +158,7 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/iostreams/write.hpp>
#define BOOST_IOSTREAMS_USE_DEPRECATED 1
#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/operators.hpp>