diff options
author | John Wiegley <johnw@newartisans.com> | 2009-02-23 19:07:30 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2009-02-23 19:07:30 -0400 |
commit | 944c63e6f26d1f05ba6f63c60f510d3796872f3e (patch) | |
tree | e1fc54319c2c42c16a64e95930acaca063658863 /src | |
parent | 057506ab6dddbfb75d1bb29289602f375ca57df5 (diff) | |
download | fork-ledger-944c63e6f26d1f05ba6f63c60f510d3796872f3e.tar.gz fork-ledger-944c63e6f26d1f05ba6f63c60f510d3796872f3e.tar.bz2 fork-ledger-944c63e6f26d1f05ba6f63c60f510d3796872f3e.zip |
The Great Renaming, Part II
The last commit did not contain the majority of changes because of a
slight mishap. This contains the real changeset.
Diffstat (limited to 'src')
-rw-r--r-- | src/account.h | 6 | ||||
-rw-r--r-- | src/chain.cc | 114 | ||||
-rw-r--r-- | src/chain.h | 10 | ||||
-rw-r--r-- | src/compare.cc | 14 | ||||
-rw-r--r-- | src/compare.h | 4 | ||||
-rw-r--r-- | src/derive.cc | 212 | ||||
-rw-r--r-- | src/derive.h | 6 | ||||
-rw-r--r-- | src/emacs.cc | 50 | ||||
-rw-r--r-- | src/emacs.h | 22 | ||||
-rw-r--r-- | src/entry.cc | 425 | ||||
-rw-r--r-- | src/entry.h | 255 | ||||
-rw-r--r-- | src/filters.cc | 586 | ||||
-rw-r--r-- | src/filters.h | 510 | ||||
-rw-r--r-- | src/format.cc | 18 | ||||
-rw-r--r-- | src/global.cc | 14 | ||||
-rw-r--r-- | src/item.h | 14 | ||||
-rw-r--r-- | src/iterators.cc | 108 | ||||
-rw-r--r-- | src/iterators.h | 118 | ||||
-rw-r--r-- | src/journal.cc | 46 | ||||
-rw-r--r-- | src/journal.h | 22 | ||||
-rw-r--r-- | src/output.cc | 120 | ||||
-rw-r--r-- | src/output.h | 34 | ||||
-rw-r--r-- | src/post.cc | 336 | ||||
-rw-r--r-- | src/post.h | 208 | ||||
-rw-r--r-- | src/precmd.cc | 16 | ||||
-rw-r--r-- | src/report.cc | 69 | ||||
-rw-r--r-- | src/report.h | 44 | ||||
-rw-r--r-- | src/session.cc | 26 | ||||
-rw-r--r-- | src/session.h | 6 | ||||
-rw-r--r-- | src/textual.cc | 294 | ||||
-rw-r--r-- | src/timelog.cc | 54 | ||||
-rw-r--r-- | src/timelog.h | 24 | ||||
-rw-r--r-- | src/utils.cc | 2 | ||||
-rw-r--r-- | src/utils.h | 2 | ||||
-rw-r--r-- | src/xact.cc | 518 | ||||
-rw-r--r-- | src/xact.h | 309 |
36 files changed, 2307 insertions, 2309 deletions
diff --git a/src/account.h b/src/account.h index 8b485ec2..29b3c682 100644 --- a/src/account.h +++ b/src/account.h @@ -130,8 +130,8 @@ class account_t : public scope_t value_t value; value_t total; - std::size_t count; // xacts counted toward amount - std::size_t total_count; // xacts counted toward total + std::size_t count; // posts counted toward amount + std::size_t total_count; // posts counted toward total std::size_t virtuals; std::list<sort_value_t> sort_values; @@ -158,7 +158,7 @@ class account_t : public scope_t }; // This variable holds optional "extended data" which is usually produced - // only during reporting, and only for the transaction set being reported. + // only during reporting, and only for the posting set being reported. // It's a memory-saving measure to delay allocation until the last possible // moment. mutable optional<xdata_t> xdata_; diff --git a/src/chain.cc b/src/chain.cc index 950afc32..0ad1709f 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -35,11 +35,11 @@ namespace ledger { -xact_handler_ptr chain_xact_handlers(report_t& report, - xact_handler_ptr base_handler, +post_handler_ptr chain_post_handlers(report_t& report, + post_handler_ptr base_handler, bool only_preliminaries) { - xact_handler_ptr handler(base_handler); + post_handler_ptr handler(base_handler); item_predicate display_predicate; item_predicate only_predicate; @@ -48,159 +48,159 @@ xact_handler_ptr chain_xact_handlers(report_t& report, expr.set_context(&report); if (! only_preliminaries) { - // Make sure only forecast transactions which match are allowed through + // Make sure only forecast postings which match are allowed through if (report.HANDLED(forecast_while_)) { - handler.reset(new filter_xacts + handler.reset(new filter_posts (handler, item_predicate(report.HANDLER(forecast_while_).str(), report.what_to_keep()), report)); } - // truncate_entries cuts off a certain number of _entries_ from being + // truncate_xacts cuts off a certain number of _xacts_ from being // displayed. It does not affect calculation. if (report.HANDLED(head_) || report.HANDLED(tail_)) handler.reset - (new truncate_entries(handler, + (new truncate_xacts(handler, report.HANDLED(head_) ? report.HANDLER(head_).value.to_long() : 0, report.HANDLED(tail_) ? report.HANDLER(tail_).value.to_long() : 0)); - // filter_xacts will only pass through xacts matching the + // filter_posts will only pass through posts matching the // `display_predicate'. if (report.HANDLED(display_)) { display_predicate = item_predicate(report.HANDLER(display_).str(), report.what_to_keep()); - handler.reset(new filter_xacts(handler, display_predicate, report)); + handler.reset(new filter_posts(handler, display_predicate, report)); } - // changed_value_xacts adds virtual xacts to the list to account for + // changed_value_posts adds virtual posts to the list to account for // changes in market value of commodities, which otherwise would affect // the running total unpredictably. if (report.HANDLED(revalued)) - handler.reset(new changed_value_xacts + handler.reset(new changed_value_posts (handler, report.HANDLED(revalued_total_) ? report.HANDLER(revalued_total_).expr : report.HANDLER(display_total_).expr, report, report.HANDLED(revalued_only))); - // calc_xacts computes the running total. When this appears will - // determine, for example, whether filtered xacts are included or excluded + // calc_posts computes the running total. When this appears will + // determine, for example, whether filtered posts are included or excluded // from the running total. - handler.reset(new calc_xacts(handler, expr)); + handler.reset(new calc_posts(handler, expr)); } - // filter_xacts will only pass through xacts matching the + // filter_posts will only pass through posts matching the // `secondary_predicate'. if (report.HANDLED(only_)) { only_predicate = item_predicate(report.HANDLER(only_).str(), report.what_to_keep()); - handler.reset(new filter_xacts(handler, only_predicate, report)); + handler.reset(new filter_posts(handler, only_predicate, report)); } if (! only_preliminaries) { - // sort_xacts will sort all the xacts it sees, based on the `sort_order' + // sort_posts will sort all the posts it sees, based on the `sort_order' // value expression. if (report.HANDLED(sort_)) { - if (report.HANDLED(sort_entries_)) - handler.reset(new sort_entries(handler, report.HANDLER(sort_).str())); - else + if (report.HANDLED(sort_xacts_)) handler.reset(new sort_xacts(handler, report.HANDLER(sort_).str())); + else + handler.reset(new sort_posts(handler, report.HANDLER(sort_).str())); } - // collapse_xacts causes entries with multiple xacts to appear as entries - // with a subtotaled xact for each commodity used. + // collapse_posts causes xacts with multiple posts to appear as xacts + // with a subtotaled post for each commodity used. if (report.HANDLED(collapse)) - handler.reset(new collapse_xacts(handler, expr, + handler.reset(new collapse_posts(handler, expr, display_predicate, only_predicate, report.HANDLED(collapse_if_zero))); - // subtotal_xacts combines all the xacts it receives into one subtotal - // entry, which has one xact for each commodity in each account. + // subtotal_posts combines all the posts it receives into one subtotal + // xact, which has one post for each commodity in each account. // - // period_xacts is like subtotal_xacts, but it subtotals according to time + // period_posts is like subtotal_posts, but it subtotals according to time // periods rather than totalling everything. // - // dow_xacts is like period_xacts, except that it reports all the xacts + // dow_posts is like period_posts, except that it reports all the posts // that fall on each subsequent day of the week. if (report.HANDLED(equity)) - handler.reset(new xacts_as_equity(handler, expr)); + handler.reset(new posts_as_equity(handler, expr)); else if (report.HANDLED(subtotal)) - handler.reset(new subtotal_xacts(handler, expr)); + handler.reset(new subtotal_posts(handler, expr)); } if (report.HANDLED(dow)) - handler.reset(new dow_xacts(handler, expr)); + handler.reset(new dow_posts(handler, expr)); else if (report.HANDLED(by_payee)) - handler.reset(new by_payee_xacts(handler, expr)); + handler.reset(new by_payee_posts(handler, expr)); - // interval_xacts groups xacts together based on a time period, such as + // interval_posts groups posts together based on a time period, such as // weekly or monthly. if (report.HANDLED(period_)) { - handler.reset(new interval_xacts(handler, expr, + handler.reset(new interval_posts(handler, expr, report.HANDLER(period_).str(), report.HANDLED(exact), report.HANDLED(empty))); - handler.reset(new sort_xacts(handler, "date")); + handler.reset(new sort_posts(handler, "date")); } - // related_xacts will pass along all xacts related to the xact received. If - // the `related_all' handler is on, then all the entry's xacts are passed; - // meaning that if one xact of an entry is to be printed, all the xact for - // that entry will be printed. + // related_posts will pass along all posts related to the post received. If + // the `related_all' handler is on, then all the xact's posts are passed; + // meaning that if one post of an xact is to be printed, all the post for + // that xact will be printed. if (report.HANDLED(related)) - handler.reset(new related_xacts(handler, report.HANDLED(related_all))); + handler.reset(new related_posts(handler, report.HANDLED(related_all))); - // anonymize_xacts removes all meaningful information from entry payee's and + // anonymize_posts removes all meaningful information from xact payee's and // account names, for the sake of creating useful bug reports. if (report.HANDLED(anon)) - handler.reset(new anonymize_xacts(handler)); + handler.reset(new anonymize_posts(handler)); - // This filter_xacts will only pass through xacts matching the `predicate'. + // This filter_posts will only pass through posts matching the `predicate'. if (report.HANDLED(limit_)) { DEBUG("report.predicate", "Report predicate expression = " << report.HANDLER(limit_).str()); - handler.reset(new filter_xacts + handler.reset(new filter_posts (handler, item_predicate(report.HANDLER(limit_).str(), report.what_to_keep()), report)); } - // budget_xacts takes a set of xacts from a data file and uses them to - // generate "budget xacts" which balance against the reported xacts. + // budget_posts takes a set of posts from a data file and uses them to + // generate "budget posts" which balance against the reported posts. // - // forecast_xacts is a lot like budget_xacts, except that it adds entries + // forecast_posts is a lot like budget_posts, except that it adds xacts // only for the future, and does not balance them against anything but the // future balance. if (report.budget_flags != BUDGET_NO_BUDGET) { - budget_xacts * budget_handler = new budget_xacts(handler, + budget_posts * budget_handler = new budget_posts(handler, report.budget_flags); - budget_handler->add_period_entries(report.session.journal->period_entries); + budget_handler->add_period_xacts(report.session.journal->period_xacts); handler.reset(budget_handler); - // Apply this before the budget handler, so that only matching xacts are - // calculated toward the budget. The use of filter_xacts above will - // further clean the results so that no automated xacts that don't match + // Apply this before the budget handler, so that only matching posts are + // calculated toward the budget. The use of filter_posts above will + // further clean the results so that no automated posts that don't match // the filter get reported. if (report.HANDLED(limit_)) - handler.reset(new filter_xacts + handler.reset(new filter_posts (handler, item_predicate(report.HANDLER(limit_).str(), report.what_to_keep()), report)); } else if (report.HANDLED(forecast_while_)) { - forecast_xacts * forecast_handler - = new forecast_xacts(handler, + forecast_posts * forecast_handler + = new forecast_posts(handler, item_predicate(report.HANDLER(forecast_while_).str(), report.what_to_keep()), report); - forecast_handler->add_period_entries(report.session.journal->period_entries); + forecast_handler->add_period_xacts(report.session.journal->period_xacts); handler.reset(forecast_handler); - // See above, under budget_xacts. + // See above, under budget_posts. if (report.HANDLED(limit_)) - handler.reset(new filter_xacts + handler.reset(new filter_posts (handler, item_predicate(report.HANDLER(limit_).str(), report.what_to_keep()), report)); diff --git a/src/chain.h b/src/chain.h index b064c4ed..89f4ab6e 100644 --- a/src/chain.h +++ b/src/chain.h @@ -46,7 +46,7 @@ #ifndef _CHAIN_H #define _CHAIN_H -#include "xact.h" +#include "post.h" #include "account.h" namespace ledger { @@ -84,13 +84,13 @@ public: } }; -typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr; +typedef shared_ptr<item_handler<post_t> > post_handler_ptr; typedef shared_ptr<item_handler<account_t> > acct_handler_ptr; class report_t; -xact_handler_ptr -chain_xact_handlers(report_t& report, - xact_handler_ptr base_handler, +post_handler_ptr +chain_post_handlers(report_t& report, + post_handler_ptr base_handler, bool only_preliminaries = false); } // namespace ledger diff --git a/src/compare.cc b/src/compare.cc index 79e49461..d716bcda 100644 --- a/src/compare.cc +++ b/src/compare.cc @@ -71,21 +71,21 @@ void compare_items<T>::find_sort_values(std::list<sort_value_t>& sort_values, } template <> -bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right) +bool compare_items<post_t>::operator()(post_t * left, post_t * right) { assert(left); assert(right); - xact_t::xdata_t& lxdata(left->xdata()); - if (! lxdata.has_flags(XACT_EXT_SORT_CALC)) { + post_t::xdata_t& lxdata(left->xdata()); + if (! lxdata.has_flags(POST_EXT_SORT_CALC)) { find_sort_values(lxdata.sort_values, left); - lxdata.add_flags(XACT_EXT_SORT_CALC); + lxdata.add_flags(POST_EXT_SORT_CALC); } - xact_t::xdata_t& rxdata(right->xdata()); - if (! rxdata.has_flags(XACT_EXT_SORT_CALC)) { + post_t::xdata_t& rxdata(right->xdata()); + if (! rxdata.has_flags(POST_EXT_SORT_CALC)) { find_sort_values(rxdata.sort_values, right); - rxdata.add_flags(XACT_EXT_SORT_CALC); + rxdata.add_flags(POST_EXT_SORT_CALC); } return sort_value_is_less_than(lxdata.sort_values, rxdata.sort_values); diff --git a/src/compare.h b/src/compare.h index bf85e1c7..92cee665 100644 --- a/src/compare.h +++ b/src/compare.h @@ -47,7 +47,7 @@ #define _COMPARE_H #include "expr.h" -#include "xact.h" +#include "post.h" #include "account.h" namespace ledger { @@ -91,7 +91,7 @@ bool compare_items<T>::operator()(T * left, T * right) } template <> -bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right); +bool compare_items<post_t>::operator()(post_t * left, post_t * right); template <> bool compare_items<account_t>::operator()(account_t * left, account_t * right); diff --git a/src/derive.cc b/src/derive.cc index 8ea07c87..f6b594e0 100644 --- a/src/derive.cc +++ b/src/derive.cc @@ -35,7 +35,7 @@ namespace ledger { namespace { - struct entry_template_t + struct xact_template_t { optional<date_t> date; optional<date_t> eff_date; @@ -43,17 +43,17 @@ namespace { optional<string> note; mask_t payee_mask; - struct xact_template_t { + struct post_template_t { bool from; optional<mask_t> account_mask; optional<amount_t> amount; - xact_template_t() : from(false) {} + post_template_t() : from(false) {} }; - std::list<xact_template_t> xacts; + std::list<post_template_t> posts; - entry_template_t() {} + xact_template_t() {} void dump(std::ostream& out) const { @@ -76,52 +76,52 @@ namespace { else out << "Payee mask: " << payee_mask << std::endl; - if (xacts.empty()) { + if (posts.empty()) { out << std::endl - << "<Transaction copied from last related entry>" + << "<Posting copied from last related transaction>" << std::endl; } else { bool has_only_from = true; bool has_only_to = true; - foreach (const xact_template_t& xact, xacts) { - if (xact.from) + foreach (const post_template_t& post, posts) { + if (post.from) has_only_to = false; else has_only_from = false; } - foreach (const xact_template_t& xact, xacts) { + foreach (const post_template_t& post, posts) { out << std::endl - << "[Transaction \"" << (xact.from ? "from" : "to") + << "[Posting \"" << (post.from ? "from" : "to") << "\"]" << std::endl; - if (xact.account_mask) - out << " Account mask: " << *xact.account_mask << std::endl; - else if (xact.from) + if (post.account_mask) + out << " Account mask: " << *post.account_mask << std::endl; + else if (post.from) out << " Account mask: <use last of last related accounts>" << std::endl; else out << " Account mask: <use first of last related accounts>" << std::endl; - if (xact.amount) - out << " Amount: " << *xact.amount << std::endl; + if (post.amount) + out << " Amount: " << *post.amount << std::endl; } } } }; - entry_template_t - args_to_entry_template(value_t::sequence_t::const_iterator begin, + xact_template_t + args_to_xact_template(value_t::sequence_t::const_iterator begin, value_t::sequence_t::const_iterator end) { regex date_mask("([0-9]+(?:[-/.][0-9]+)?(?:[-/.][0-9]+))?(?:=.*)?"); regex dow_mask("(sun|mon|tue|wed|thu|fri|sat)"); smatch what; - entry_template_t tmpl; + xact_template_t tmpl; bool check_for_date = true; - entry_template_t::xact_template_t * xact = NULL; + xact_template_t::post_template_t * post = NULL; for (; begin != end; begin++) { if (check_for_date && @@ -147,12 +147,12 @@ namespace { tmpl.payee_mask = (*++begin).to_string(); } else if (arg == "to" || arg == "from") { - if (! xact || xact->account_mask) { - tmpl.xacts.push_back(entry_template_t::xact_template_t()); - xact = &tmpl.xacts.back(); + if (! post || post->account_mask) { + tmpl.posts.push_back(xact_template_t::post_template_t()); + post = &tmpl.posts.back(); } - xact->account_mask = mask_t((*++begin).to_string()); - xact->from = arg == "from"; + post->account_mask = mask_t((*++begin).to_string()); + post->from = arg == "from"; } else if (arg == "on") { tmpl.date = parse_date((*++begin).to_string()); @@ -186,62 +186,62 @@ namespace { amount_t::PARSE_NO_MIGRATE)) account = mask_t(arg); - if (! xact || - (account && xact->account_mask) || - (! account && xact->amount)) { - tmpl.xacts.push_back(entry_template_t::xact_template_t()); - xact = &tmpl.xacts.back(); + if (! post || + (account && post->account_mask) || + (! account && post->amount)) { + tmpl.posts.push_back(xact_template_t::post_template_t()); + post = &tmpl.posts.back(); } if (account) { - xact->from = false; - xact->account_mask = account; + post->from = false; + post->account_mask = account; } else { - xact->amount = amt; + post->amount = amt; } } } } } - if (! tmpl.xacts.empty()) { + if (! tmpl.posts.empty()) { bool has_only_from = true; bool has_only_to = true; - foreach (entry_template_t::xact_template_t& xact, tmpl.xacts) { - if (xact.from) + foreach (xact_template_t::post_template_t& post, tmpl.posts) { + if (post.from) has_only_to = false; else has_only_from = false; } if (has_only_from) { - tmpl.xacts.push_front(entry_template_t::xact_template_t()); + tmpl.posts.push_front(xact_template_t::post_template_t()); } else if (has_only_to) { - tmpl.xacts.push_back(entry_template_t::xact_template_t()); - tmpl.xacts.back().from = true; + tmpl.posts.push_back(xact_template_t::post_template_t()); + tmpl.posts.back().from = true; } } return tmpl; } - entry_t * derive_entry_from_template(entry_template_t& tmpl, + xact_t * derive_xact_from_template(xact_template_t& tmpl, report_t& report) { if (tmpl.payee_mask.empty()) - throw std::runtime_error("'entry' command requires at least a payee"); + throw std::runtime_error("'xact' command requires at least a payee"); - entry_t * matching = NULL; + xact_t * matching = NULL; journal_t& journal(*report.session.journal.get()); - std::auto_ptr<entry_t> added(new entry_t); + std::auto_ptr<xact_t> added(new xact_t); - entries_list::reverse_iterator j; + xacts_list::reverse_iterator j; - for (j = journal.entries.rbegin(); - j != journal.entries.rend(); + for (j = journal.xacts.rbegin(); + j != journal.xacts.rend(); j++) { if (tmpl.payee_mask.match((*j)->payee)) { matching = *j; @@ -270,112 +270,114 @@ namespace { if (tmpl.note) added->note = tmpl.note; - if (tmpl.xacts.empty()) { + if (tmpl.posts.empty()) { if (matching) { - foreach (xact_t * xact, matching->xacts) - added->add_xact(new xact_t(*xact)); + foreach (post_t * post, matching->posts) + added->add_post(new post_t(*post)); } else { throw_(std::runtime_error, - "No accounts, and no past entry matching '" << tmpl.payee_mask <<"'"); + "No accounts, and no past transaction matching '" + << tmpl.payee_mask <<"'"); } } else { - bool any_xact_has_amount = false; - foreach (entry_template_t::xact_template_t& xact, tmpl.xacts) { - if (xact.amount) { - any_xact_has_amount = true; + bool any_post_has_amount = false; + foreach (xact_template_t::post_template_t& post, tmpl.posts) { + if (post.amount) { + any_post_has_amount = true; break; } } - foreach (entry_template_t::xact_template_t& xact, tmpl.xacts) { - std::auto_ptr<xact_t> new_xact; + foreach (xact_template_t::post_template_t& post, tmpl.posts) { + std::auto_ptr<post_t> new_post; commodity_t * found_commodity = NULL; if (matching) { - if (xact.account_mask) { - foreach (xact_t * x, matching->xacts) { - if (xact.account_mask->match(x->account->fullname())) { - new_xact.reset(new xact_t(*x)); + if (post.account_mask) { + foreach (post_t * x, matching->posts) { + if (post.account_mask->match(x->account->fullname())) { + new_post.reset(new post_t(*x)); break; } } } else { - if (xact.from) - new_xact.reset(new xact_t(*matching->xacts.back())); + if (post.from) + new_post.reset(new post_t(*matching->posts.back())); else - new_xact.reset(new xact_t(*matching->xacts.front())); + new_post.reset(new post_t(*matching->posts.front())); } } - if (! new_xact.get()) - new_xact.reset(new xact_t); + if (! new_post.get()) + new_post.reset(new post_t); - if (! new_xact->account) { - if (xact.account_mask) { + if (! new_post->account) { + if (post.account_mask) { account_t * acct = NULL; if (! acct) - acct = journal.find_account_re(xact.account_mask->expr.str()); + acct = journal.find_account_re(post.account_mask->expr.str()); if (! acct) - acct = journal.find_account(xact.account_mask->expr.str()); + acct = journal.find_account(post.account_mask->expr.str()); // Find out the default commodity to use by looking at the last // commodity used in that account - entries_list::reverse_iterator j; + xacts_list::reverse_iterator j; - for (j = journal.entries.rbegin(); - j != journal.entries.rend(); + for (j = journal.xacts.rbegin(); + j != journal.xacts.rend(); j++) { - foreach (xact_t * x, (*j)->xacts) { + foreach (post_t * x, (*j)->posts) { if (x->account == acct && ! x->amount.is_null()) { - new_xact.reset(new xact_t(*x)); + new_post.reset(new post_t(*x)); break; } } } - if (! new_xact.get()) - new_xact.reset(new xact_t); + if (! new_post.get()) + new_post.reset(new post_t); - new_xact->account = acct; + new_post->account = acct; } else { - if (xact.from) - new_xact->account = journal.find_account("Liabilities:Unknown"); + if (post.from) + new_post->account = journal.find_account("Liabilities:Unknown"); else - new_xact->account = journal.find_account("Expenses:Unknown"); + new_post->account = journal.find_account("Expenses:Unknown"); } } - if (new_xact.get() && ! new_xact->amount.is_null()) { - found_commodity = &new_xact->amount.commodity(); + if (new_post.get() && ! new_post->amount.is_null()) { + found_commodity = &new_post->amount.commodity(); - if (any_xact_has_amount) - new_xact->amount = amount_t(); + if (any_post_has_amount) + new_post->amount = amount_t(); else - any_xact_has_amount = true; + any_post_has_amount = true; } - if (xact.amount) { - new_xact->amount = *xact.amount; - if (xact.from) - new_xact->amount.in_place_negate(); + if (post.amount) { + new_post->amount = *post.amount; + if (post.from) + new_post->amount.in_place_negate(); } if (found_commodity && - ! new_xact->amount.is_null() && - ! new_xact->amount.has_commodity()) { - new_xact->amount.set_commodity(*found_commodity); - new_xact->amount = new_xact->amount.rounded(); + ! new_post->amount.is_null() && + ! new_post->amount.has_commodity()) { + new_post->amount.set_commodity(*found_commodity); + new_post->amount = new_post->amount.rounded(); } - added->add_xact(new_xact.release()); + added->add_post(new_post.release()); } } - if (! journal.entry_finalize_hooks.run_hooks(*added.get(), false) || + if (! journal.xact_finalize_hooks.run_hooks(*added.get(), false) || ! added->finalize() || - ! journal.entry_finalize_hooks.run_hooks(*added.get(), true)) - throw std::runtime_error("Failed to finalize derived entry (check commodities)"); + ! journal.xact_finalize_hooks.run_hooks(*added.get(), true)) + throw_(std::runtime_error, + "Failed to finalize derived transaction (check commodities)"); return added.release(); } @@ -393,27 +395,27 @@ value_t template_command(call_scope_t& args) args.value().dump(out); out << std::endl << std::endl; - entry_template_t tmpl = args_to_entry_template(begin, end); + xact_template_t tmpl = args_to_xact_template(begin, end); - out << "--- Entry template ---" << std::endl; + out << "--- Transaction template ---" << std::endl; tmpl.dump(out); return true; } -value_t entry_command(call_scope_t& args) +value_t xact_command(call_scope_t& args) { value_t::sequence_t::const_iterator begin = args.value().begin(); value_t::sequence_t::const_iterator end = args.value().end(); report_t& report(find_scope<report_t>(args)); - entry_template_t tmpl = args_to_entry_template(begin, end); - std::auto_ptr<entry_t> new_entry(derive_entry_from_template(tmpl, report)); + xact_template_t tmpl = args_to_xact_template(begin, end); + std::auto_ptr<xact_t> new_xact(derive_xact_from_template(tmpl, report)); - report.entry_report(xact_handler_ptr - (new format_xacts(report, + report.xact_report(post_handler_ptr + (new format_posts(report, report.HANDLER(print_format_).str())), - *new_entry.get()); + *new_xact.get()); return true; } diff --git a/src/derive.h b/src/derive.h index 2cefc3bf..9825d496 100644 --- a/src/derive.h +++ b/src/derive.h @@ -50,12 +50,12 @@ namespace ledger { -value_t entry_command(call_scope_t& args); +value_t xact_command(call_scope_t& args); value_t template_command(call_scope_t& args); -class entry_t; +class xact_t; class report_t; -entry_t * derive_new_entry(report_t& report, +xact_t * derive_new_xact(report_t& report, value_t::sequence_t::const_iterator i, value_t::sequence_t::const_iterator end); diff --git a/src/emacs.cc b/src/emacs.cc index 3c3c1b7b..fb54783b 100644 --- a/src/emacs.cc +++ b/src/emacs.cc @@ -34,50 +34,50 @@ namespace ledger { -void format_emacs_xacts::write_entry(entry_t& entry) +void format_emacs_posts::write_xact(xact_t& xact) { - out << "\"" << entry.pathname << "\" " - << (static_cast<std::size_t>(entry.beg_line) + 1) << " "; + out << "\"" << xact.pathname << "\" " + << (static_cast<std::size_t>(xact.beg_line) + 1) << " "; - tm when = gregorian::to_tm(entry.date()); + tm when = gregorian::to_tm(xact.date()); std::time_t date = std::mktime(&when); // jww (2008-04-20): Is this GMT or local? out << "(" << (date / 65536) << " " << (date % 65536) << " 0) "; - if (! entry.code) + if (! xact.code) out << "nil "; else - out << "\"" << *entry.code << "\" "; + out << "\"" << *xact.code << "\" "; - if (entry.payee.empty()) + if (xact.payee.empty()) out << "nil"; else - out << "\"" << entry.payee << "\""; + out << "\"" << xact.payee << "\""; out << "\n"; } -void format_emacs_xacts::operator()(xact_t& xact) +void format_emacs_posts::operator()(post_t& post) { - if (! xact.has_xdata() || - ! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) { - if (! last_entry) { + if (! post.has_xdata() || + ! post.xdata().has_flags(POST_EXT_DISPLAYED)) { + if (! last_xact) { out << "(("; - write_entry(*xact.entry); + write_xact(*post.xact); } - else if (xact.entry != last_entry) { + else if (post.xact != last_xact) { out << ")\n ("; - write_entry(*xact.entry); + write_xact(*post.xact); } else { out << "\n"; } - out << " (" << (static_cast<std::size_t>(xact.beg_line) + 1) << " "; - out << "\"" << xact.reported_account()->fullname() << "\" \"" - << xact.amount << "\""; + out << " (" << (static_cast<std::size_t>(post.beg_line) + 1) << " "; + out << "\"" << post.reported_account()->fullname() << "\" \"" + << post.amount << "\""; - switch (xact.state()) { + switch (post.state()) { case item_t::CLEARED: out << " t"; break; @@ -89,15 +89,15 @@ void format_emacs_xacts::operator()(xact_t& xact) break; } - if (xact.cost) - out << " \"" << *xact.cost << "\""; - if (xact.note) - out << " \"" << *xact.note << "\""; + if (post.cost) + out << " \"" << *post.cost << "\""; + if (post.note) + out << " \"" << *post.note << "\""; out << ")"; - last_entry = xact.entry; + last_xact = post.xact; - xact.xdata().add_flags(XACT_EXT_DISPLAYED); + post.xdata().add_flags(POST_EXT_DISPLAYED); } } diff --git a/src/emacs.h b/src/emacs.h index 868a899b..dec7d183 100644 --- a/src/emacs.h +++ b/src/emacs.h @@ -55,30 +55,30 @@ namespace ledger { * * Long. */ -class format_emacs_xacts : public item_handler<xact_t> +class format_emacs_posts : public item_handler<post_t> { - format_emacs_xacts(); + format_emacs_posts(); protected: std::ostream& out; - entry_t * last_entry; + xact_t * last_xact; public: - format_emacs_xacts(std::ostream& _out) - : out(_out), last_entry(NULL) { - TRACE_CTOR(format_emacs_xacts, "std::ostream&"); + format_emacs_posts(std::ostream& _out) + : out(_out), last_xact(NULL) { + TRACE_CTOR(format_emacs_posts, "std::ostream&"); } - ~format_emacs_xacts() { - TRACE_DTOR(format_emacs_xacts); + ~format_emacs_posts() { + TRACE_DTOR(format_emacs_posts); } - virtual void write_entry(entry_t& entry); + virtual void write_xact(xact_t& xact); virtual void flush() { - if (last_entry) + if (last_xact) out << "))\n"; out.flush(); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; } // namespace ledger diff --git a/src/entry.cc b/src/entry.cc deleted file mode 100644 index eceec5f7..00000000 --- a/src/entry.cc +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2003-2009, John Wiegley. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of New Artisans LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "entry.h" -#include "journal.h" -#include "account.h" -#include "format.h" - -namespace ledger { - -entry_base_t::entry_base_t(const entry_base_t&) - : item_t(), journal(NULL) -{ - TRACE_CTOR(entry_base_t, "copy"); -} - -entry_base_t::~entry_base_t() -{ - TRACE_DTOR(entry_base_t); - - foreach (xact_t * xact, xacts) { - // If the transaction is a temporary, it will be destructed when the - // temporary is. - if (! xact->has_flags(ITEM_TEMP)) - checked_delete(xact); - } -} - -item_t::state_t entry_base_t::state() const -{ - state_t result = CLEARED; - - foreach (xact_t * xact, xacts) { - if (xact->_state == UNCLEARED) - return UNCLEARED; - else if (xact->_state == PENDING) - result = PENDING; - } - return result; -} - -void entry_base_t::add_xact(xact_t * xact) -{ - xacts.push_back(xact); -} - -bool entry_base_t::remove_xact(xact_t * xact) -{ - xacts.remove(xact); - xact->entry = NULL; - return true; -} - -bool entry_base_t::finalize() -{ - // Scan through and compute the total balance for the entry. This is used - // for auto-calculating the value of entries with no cost, and the per-unit - // price of unpriced commodities. - - value_t balance; - xact_t * null_xact = NULL; - - foreach (xact_t * xact, xacts) { - if (xact->must_balance()) { - amount_t& p(xact->cost ? *xact->cost : xact->amount); - DEBUG("entry.finalize", "xact must balance = " << p); - if (! p.is_null()) { - if (p.keep_precision()) { - // If the amount was a cost, it very likely has the "keep_precision" - // flag set, meaning commodity display precision is ignored when - // displaying the amount. We never want this set for the balance, - // so we must clear the flag in a temporary to avoid it propagating - // into the balance. - add_or_set_value(balance, p.rounded()); - } else { - add_or_set_value(balance, p); - } - } else { - if (null_xact) - throw_(std::logic_error, - "Only one xact with null amount allowed per entry"); - else - null_xact = xact; - } - } - } - assert(balance.valid()); - - DEBUG("entry.finalize", "initial balance = " << balance); - - // If there is only one xact, balance against the default account if one has - // been set. - - if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) { - // jww (2008-07-24): Need to make the rest of the code aware of what to do - // when it sees a generated xact. - null_xact = new xact_t(journal->basket, ITEM_GENERATED); - null_xact->_state = (*xacts.begin())->_state; - add_xact(null_xact); - } - - if (null_xact != NULL) { - // If one xact has no value at all, its value will become the inverse of - // the rest. If multiple commodities are involved, multiple xacts are - // generated to balance them all. - - if (balance.is_balance()) { - bool first = true; - const balance_t& bal(balance.as_balance()); - foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) { - if (first) { - null_xact->amount = pair.second.negated(); - first = false; - } else { - add_xact(new xact_t(null_xact->account, pair.second.negated(), - ITEM_GENERATED)); - } - } - } - else if (balance.is_amount()) { - null_xact->amount = balance.as_amount().negated(); - null_xact->add_flags(XACT_CALCULATED); - } - else if (! balance.is_null() && ! balance.is_realzero()) { - throw_(balance_error, "Entry does not balance"); - } - balance = NULL_VALUE; - - } - else if (balance.is_balance() && - balance.as_balance().amounts.size() == 2) { - // When an entry involves two different commodities (regardless of how - // many xacts there are) determine the conversion ratio by dividing the - // total value of one commodity by the total value of the other. This - // establishes the per-unit cost for this xact for both commodities. - - DEBUG("entry.finalize", "there were exactly two commodities"); - - bool saw_cost = false; - xact_t * top_xact = NULL; - - foreach (xact_t * xact, xacts) { - if (! xact->amount.is_null()) - if (xact->amount.is_annotated()) - top_xact = xact; - else if (! top_xact) - top_xact = xact; - - if (xact->cost) { - saw_cost = true; - break; - } - } - - if (! saw_cost && top_xact) { - const balance_t& bal(balance.as_balance()); - - DEBUG("entry.finalize", "there were no costs, and a valid top_xact"); - - balance_t::amounts_map::const_iterator a = bal.amounts.begin(); - - const amount_t * x = &(*a++).second; - const amount_t * y = &(*a++).second; - - if (x->commodity() != top_xact->amount.commodity()) { - const amount_t * t = x; - x = y; - y = t; - } - - DEBUG("entry.finalize", "primary amount = " << *y); - DEBUG("entry.finalize", "secondary amount = " << *x); - - commodity_t& comm(x->commodity()); - amount_t per_unit_cost; - amount_t total_cost; - - foreach (xact_t * xact, xacts) { - if (xact != top_xact && xact->must_balance() && - ! xact->amount.is_null() && - xact->amount.is_annotated() && - xact->amount.annotation().price) { - amount_t temp = *xact->amount.annotation().price * xact->amount; - if (total_cost.is_null()) { - total_cost = temp; - y = &total_cost; - } else { - total_cost += temp; - } - DEBUG("entry.finalize", "total_cost = " << total_cost); - } - } - per_unit_cost = (*y / *x).abs(); - - DEBUG("entry.finalize", "per_unit_cost = " << per_unit_cost); - - foreach (xact_t * xact, xacts) { - const amount_t& amt(xact->amount); - - if (xact->must_balance() && amt.commodity() == comm) { - balance -= amt; - xact->cost = per_unit_cost * amt; - balance += *xact->cost; - - DEBUG("entry.finalize", "set xact->cost to = " << *xact->cost); - } - } - } - - DEBUG("entry.finalize", "resolved balance = " << balance); - } - - // Now that the xact list has its final form, calculate the balance once - // more in terms of total cost, accounting for any possible gain/loss - // amounts. - - foreach (xact_t * xact, xacts) { - if (xact->cost) { - if (xact->amount.commodity() == xact->cost->commodity()) - throw_(balance_error, "Transaction's cost must be of a different commodity"); - - commodity_t::cost_breakdown_t breakdown = - commodity_t::exchange(xact->amount, *xact->cost, false, - datetime_t(date(), time_duration(0, 0, 0, 0))); - - if (xact->amount.is_annotated() && - breakdown.basis_cost.commodity() == - breakdown.final_cost.commodity()) - add_or_set_value(balance, (breakdown.basis_cost - - breakdown.final_cost).rounded()); - else - xact->amount = breakdown.amount; - } - } - - DEBUG("entry.finalize", "final balance = " << balance); - - if (! balance.is_null() && ! balance.is_zero()) { - add_error_context(item_context(*this, "While balancing entry")); - add_error_context("Unbalanced remainder is:"); - add_error_context(value_context(balance)); - throw_(balance_error, "Entry does not balance"); - } - - // Add the final calculated totals each to their related account - - if (dynamic_cast<entry_t *>(this)) { - bool all_null = true; - foreach (xact_t * xact, xacts) { - if (! xact->amount.is_null()) { - all_null = false; - - // jww (2008-08-09): For now, this feature only works for non-specific - // commodities. - add_or_set_value(xact->account->xdata().value, xact->amount); - - DEBUG("entry.finalize.totals", - "Total for " << xact->account->fullname() << " + " - << xact->amount << ": " << xact->account->xdata().value); - } - } - if (all_null) - return false; // ignore this entry completely - } - - return true; -} - -entry_t::entry_t(const entry_t& e) - : entry_base_t(e), code(e.code), payee(e.payee) -{ - TRACE_CTOR(entry_t, "copy"); -} - -void entry_t::add_xact(xact_t * xact) -{ - xact->entry = this; - entry_base_t::add_xact(xact); -} - -namespace { - value_t get_code(entry_t& entry) { - if (entry.code) - return string_value(*entry.code); - else - return string_value(empty_string); - } - - value_t get_payee(entry_t& entry) { - return string_value(entry.payee); - } - - template <value_t (*Func)(entry_t&)> - value_t get_wrapper(call_scope_t& scope) { - return (*Func)(find_scope<entry_t>(scope)); - } -} - -expr_t::ptr_op_t entry_t::lookup(const string& name) -{ - switch (name[0]) { - case 'c': - if (name == "code") - return WRAP_FUNCTOR(get_wrapper<&get_code>); - break; - - case 'p': - if (name[1] == '\0' || name == "payee") - return WRAP_FUNCTOR(get_wrapper<&get_payee>); - break; - } - - return item_t::lookup(name); -} - -bool entry_t::valid() const -{ - if (! _date || ! journal) { - DEBUG("ledger.validate", "entry_t: ! _date || ! journal"); - return false; - } - - foreach (xact_t * xact, xacts) - if (xact->entry != this || ! xact->valid()) { - DEBUG("ledger.validate", "entry_t: xact not valid"); - return false; - } - - return true; -} - -void auto_entry_t::extend_entry(entry_base_t& entry, bool post) -{ - xacts_list initial_xacts(entry.xacts.begin(), entry.xacts.end()); - - foreach (xact_t * initial_xact, initial_xacts) { - if (! initial_xact->has_flags(XACT_AUTO) && predicate(*initial_xact)) { - foreach (xact_t * xact, xacts) { - amount_t amt; - assert(xact->amount); - if (! xact->amount.commodity()) { - if (! post) - continue; - assert(initial_xact->amount); - amt = initial_xact->amount * xact->amount; - } else { - if (post) - continue; - amt = xact->amount; - } - - IF_DEBUG("entry.extend") { - DEBUG("entry.extend", - "Initial xact on line " << initial_xact->beg_line << ": " - << "amount " << initial_xact->amount << " (precision " - << initial_xact->amount.precision() << ")"); - - if (initial_xact->amount.keep_precision()) - DEBUG("entry.extend", " precision is kept"); - - DEBUG("entry.extend", - "Transaction on line " << xact->beg_line << ": " - << "amount " << xact->amount << ", amt " << amt - << " (precision " << xact->amount.precision() - << " != " << amt.precision() << ")"); - - if (xact->amount.keep_precision()) - DEBUG("entry.extend", " precision is kept"); - if (amt.keep_precision()) - DEBUG("entry.extend", " amt precision is kept"); - } - - account_t * account = xact->account; - string fullname = account->fullname(); - assert(! fullname.empty()); - if (fullname == "$account" || fullname == "@account") - account = initial_xact->account; - - // Copy over details so that the resulting xact is a mirror of - // the automated entry's one. - xact_t * new_xact = new xact_t(account, amt); - new_xact->copy_details(*xact); - new_xact->add_flags(XACT_AUTO); - - entry.add_xact(new_xact); - } - } - } -} - -void extend_entry_base(journal_t * journal, entry_base_t& base, bool post) -{ - foreach (auto_entry_t * entry, journal->auto_entries) - entry->extend_entry(base, post); -} - -} // namespace ledger diff --git a/src/entry.h b/src/entry.h deleted file mode 100644 index 726b0c51..00000000 --- a/src/entry.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2003-2009, John Wiegley. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of New Artisans LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @addtogroup data - */ - -/** - * @file entry.h - * @author John Wiegley - * - * @ingroup data - * - * @brief Brief - * - * Long. - */ -#ifndef _ENTRY_H -#define _ENTRY_H - -#include "xact.h" -#include "predicate.h" - -namespace ledger { - -class journal_t; - -/** - * @brief Brief - * - * Long. - */ -class entry_base_t : public item_t -{ -public: - journal_t * journal; - - xacts_list xacts; - - entry_base_t() : item_t(), journal(NULL) { - TRACE_CTOR(entry_base_t, ""); - } - entry_base_t(const entry_base_t& e); - - virtual ~entry_base_t(); - - virtual state_t state() const; - - virtual void add_xact(xact_t * xact); - virtual bool remove_xact(xact_t * xact); - - virtual bool finalize(); - virtual bool valid() const = 0; -}; - -/** - * @brief Brief - * - * Long. - */ -class entry_t : public entry_base_t -{ -public: - optional<string> code; - string payee; - - entry_t() { - TRACE_CTOR(entry_t, ""); - } - entry_t(const entry_t& e); - - virtual ~entry_t() { - TRACE_DTOR(entry_t); - } - - virtual void add_xact(xact_t * xact); - - virtual expr_t::ptr_op_t lookup(const string& name); - - virtual bool valid() const; -}; - -/** - * @brief Brief - * - * Long. - */ -struct entry_finalizer_t { - virtual ~entry_finalizer_t() {} - virtual bool operator()(entry_t& entry, bool post) = 0; -}; - -/** - * @brief Brief - * - * Long. - */ -class auto_entry_t : public entry_base_t -{ -public: - item_predicate predicate; - - auto_entry_t() { - TRACE_CTOR(auto_entry_t, ""); - } - auto_entry_t(const auto_entry_t& other) - : entry_base_t(), predicate(other.predicate) { - TRACE_CTOR(auto_entry_t, "copy"); - } - auto_entry_t(const item_predicate& _predicate) - : predicate(_predicate) - { - TRACE_CTOR(auto_entry_t, "const item_predicate<xact_t>&"); - } - - virtual ~auto_entry_t() { - TRACE_DTOR(auto_entry_t); - } - - virtual void extend_entry(entry_base_t& entry, bool post); - virtual bool valid() const { - return true; - } -}; - -/** - * @brief Brief - * - * Long. - */ -struct auto_entry_finalizer_t : public entry_finalizer_t -{ - journal_t * journal; - - auto_entry_finalizer_t() : journal(NULL) { - TRACE_CTOR(auto_entry_finalizer_t, ""); - } - auto_entry_finalizer_t(const auto_entry_finalizer_t& other) - : entry_finalizer_t(), journal(other.journal) { - TRACE_CTOR(auto_entry_finalizer_t, "copy"); - } - auto_entry_finalizer_t(journal_t * _journal) : journal(_journal) { - TRACE_CTOR(auto_entry_finalizer_t, "journal_t *"); - } - ~auto_entry_finalizer_t() throw() { - TRACE_DTOR(auto_entry_finalizer_t); - } - - virtual bool operator()(entry_t& entry, bool post); -}; - -/** - * @brief Brief - * - * Long. - */ -class period_entry_t : public entry_base_t -{ - public: - interval_t period; - string period_string; - - period_entry_t() { - TRACE_CTOR(period_entry_t, ""); - } - period_entry_t(const period_entry_t& e) - : entry_base_t(e), period(e.period), period_string(e.period_string) { - TRACE_CTOR(period_entry_t, "copy"); - } - period_entry_t(const string& _period) - : period(_period), period_string(_period) { - TRACE_CTOR(period_entry_t, "const string&"); - } - - virtual ~period_entry_t() throw() { - TRACE_DTOR(period_entry_t); - } - - virtual bool valid() const { - return period; - } -}; - -/** - * @brief Brief - * - * Long. - */ -class func_finalizer_t : public entry_finalizer_t -{ - func_finalizer_t(); - -public: - typedef function<bool (entry_t& entry, bool post)> func_t; - - func_t func; - - func_finalizer_t(func_t _func) : func(_func) { - TRACE_CTOR(func_finalizer_t, "func_t"); - } - func_finalizer_t(const func_finalizer_t& other) : - entry_finalizer_t(), func(other.func) { - TRACE_CTOR(func_finalizer_t, "copy"); - } - ~func_finalizer_t() throw() { - TRACE_DTOR(func_finalizer_t); - } - - virtual bool operator()(entry_t& entry, bool post) { - return func(entry, post); - } -}; - -void extend_entry_base(journal_t * journal, entry_base_t& entry, bool post); - -inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) { - extend_entry_base(journal, entry, post); - return true; -} - -typedef std::list<entry_t *> entries_list; -typedef std::list<auto_entry_t *> auto_entries_list; -typedef std::list<period_entry_t *> period_entries_list; - -} // namespace ledger - -#endif // _ENTRY_H diff --git a/src/filters.cc b/src/filters.cc index e0c67024..ade349bd 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -37,46 +37,46 @@ namespace ledger { -pass_down_xacts::pass_down_xacts(xact_handler_ptr handler, - xacts_iterator& iter) - : item_handler<xact_t>(handler) +pass_down_posts::pass_down_posts(post_handler_ptr handler, + posts_iterator& iter) + : item_handler<post_t>(handler) { - TRACE_CTOR(pass_down_xacts, "xact_handler_ptr, xacts_iterator"); + TRACE_CTOR(pass_down_posts, "post_handler_ptr, posts_iterator"); - for (xact_t * xact = iter(); xact; xact = iter()) { + for (post_t * post = iter(); post; post = iter()) { try { - item_handler<xact_t>::operator()(*xact); + item_handler<post_t>::operator()(*post); } catch (const std::exception& err) { - add_error_context(item_context(*xact, "While handling transaction")); + add_error_context(item_context(*post, "While handling posting")); throw; } } - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } -void truncate_entries::flush() +void truncate_xacts::flush() { - if (! xacts.size()) + if (! posts.size()) return; - entry_t * last_entry = (*xacts.begin())->entry; + xact_t * last_xact = (*posts.begin())->xact; int l = 0; - foreach (xact_t * xact, xacts) - if (last_entry != xact->entry) { + foreach (post_t * post, posts) + if (last_xact != post->xact) { l++; - last_entry = xact->entry; + last_xact = post->xact; } l++; - last_entry = (*xacts.begin())->entry; + last_xact = (*posts.begin())->xact; int i = 0; - foreach (xact_t * xact, xacts) { - if (last_entry != xact->entry) { - last_entry = xact->entry; + foreach (post_t * post, posts) { + if (last_xact != post->xact) { + last_xact = post->xact; i++; } @@ -96,44 +96,44 @@ void truncate_entries::flush() } if (print) - item_handler<xact_t>::operator()(*xact); + item_handler<post_t>::operator()(*post); } - xacts.clear(); + posts.clear(); - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } -void set_account_value::operator()(xact_t& xact) +void set_account_value::operator()(post_t& post) { - account_t * acct = xact.reported_account(); + account_t * acct = post.reported_account(); account_t::xdata_t& xdata(acct->xdata()); DEBUG("account.sums", "Account value was = " << xdata.value); - xact.add_to_value(xdata.value, amount_expr); + post.add_to_value(xdata.value, amount_expr); DEBUG("account.sums", "Account value is = " << xdata.value); xdata.count++; - if (xact.has_flags(XACT_VIRTUAL)) + if (post.has_flags(POST_VIRTUAL)) xdata.virtuals++; DEBUG("account.display", - "Visiting account: " << xact.account->fullname()); - xact.account->xdata().add_flags(ACCOUNT_EXT_VISITED); + "Visiting account: " << post.account->fullname()); + post.account->xdata().add_flags(ACCOUNT_EXT_VISITED); - item_handler<xact_t>::operator()(xact); + item_handler<post_t>::operator()(post); } -void sort_xacts::post_accumulated_xacts() +void sort_posts::post_accumulated_posts() { - std::stable_sort(xacts.begin(), xacts.end(), - compare_items<xact_t>(sort_order)); + std::stable_sort(posts.begin(), posts.end(), + compare_items<post_t>(sort_order)); - foreach (xact_t * xact, xacts) { - xact->xdata().drop_flags(XACT_EXT_SORT_CALC); - item_handler<xact_t>::operator()(*xact); + foreach (post_t * post, posts) { + post->xdata().drop_flags(POST_EXT_SORT_CALC); + item_handler<post_t>::operator()(*post); } - xacts.clear(); + posts.clear(); } namespace { @@ -150,96 +150,96 @@ namespace { } } -void anonymize_xacts::operator()(xact_t& xact) +void anonymize_posts::operator()(post_t& post) { SHA1 sha; uint_least32_t message_digest[5]; - bool copy_entry_details = false; + bool copy_xact_details = false; - if (last_entry != xact.entry) { - entry_temps.push_back(*xact.entry); - last_entry = xact.entry; - copy_entry_details = true; + if (last_xact != post.xact) { + xact_temps.push_back(*post.xact); + last_xact = post.xact; + copy_xact_details = true; } - entry_t& entry = entry_temps.back(); + xact_t& xact = xact_temps.back(); - if (copy_entry_details) { - entry.copy_details(*xact.entry); + if (copy_xact_details) { + xact.copy_details(*post.xact); sha.Reset(); - sha << xact.entry->payee.c_str(); + sha << post.xact->payee.c_str(); sha.Result(message_digest); - entry.payee = to_hex(message_digest); - entry.note = none; + xact.payee = to_hex(message_digest); + xact.note = none; } - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; + post_temps.push_back(post); + post_t& temp = post_temps.back(); + temp.xact = &xact; sha.Reset(); - sha << xact.account->fullname().c_str(); + sha << post.account->fullname().c_str(); sha.Result(message_digest); - temp.copy_details(xact); + temp.copy_details(post); - temp.account = xact.entry->journal->find_account(to_hex(message_digest)); + temp.account = post.xact->journal->find_account(to_hex(message_digest)); temp.note = none; temp.add_flags(ITEM_TEMP); - entry.add_xact(&temp); + xact.add_post(&temp); (*handler)(temp); } -void calc_xacts::operator()(xact_t& xact) +void calc_posts::operator()(post_t& post) { - xact_t::xdata_t& xdata(xact.xdata()); + post_t::xdata_t& xdata(post.xdata()); - if (last_xact) { - assert(last_xact->has_xdata()); - add_or_set_value(xdata.total, last_xact->xdata().total); - xdata.count = last_xact->xdata().count + 1; + if (last_post) { + assert(last_post->has_xdata()); + add_or_set_value(xdata.total, last_post->xdata().total); + xdata.count = last_post->xdata().count + 1; } else { xdata.count = 1; } - xact.add_to_value(xdata.total, amount_expr); + post.add_to_value(xdata.total, amount_expr); - item_handler<xact_t>::operator()(xact); + item_handler<post_t>::operator()(post); - last_xact = &xact; + last_post = &post; } namespace { void handle_value(const value_t& value, account_t * account, - entry_t * entry, + xact_t * xact, unsigned int flags, - std::list<xact_t>& temps, - item_handler<xact_t>& handler, + std::list<post_t>& temps, + item_handler<post_t>& handler, const date_t& date = date_t(), const value_t& total = value_t()) { - temps.push_back(xact_t(account)); - xact_t& xact(temps.back()); - xact.entry = entry; - xact.add_flags(ITEM_TEMP); - entry->add_xact(&xact); + temps.push_back(post_t(account)); + post_t& post(temps.back()); + post.xact = xact; + post.add_flags(ITEM_TEMP); + xact->add_post(&post); - // If the account for this xact is all virtual, then report the xact as + // If the account for this post is all virtual, then report the post as // such. This allows subtotal reports to show "(Account)" for accounts - // that contain only virtual xacts. + // that contain only virtual posts. if (account && account->has_xdata()) { if (! account->xdata().has_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS)) { - xact.add_flags(XACT_VIRTUAL); + post.add_flags(POST_VIRTUAL); if (! account->xdata().has_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS)) - xact.add_flags(XACT_MUST_BALANCE); + post.add_flags(POST_MUST_BALANCE); } } - xact_t::xdata_t& xdata(xact.xdata()); + post_t::xdata_t& xdata(post.xdata()); if (is_valid(date)) xdata.date = date; @@ -253,13 +253,13 @@ namespace { // fall through... case value_t::AMOUNT: - xact.amount = temp.as_amount(); + post.amount = temp.as_amount(); break; case value_t::BALANCE: case value_t::SEQUENCE: xdata.value = temp; - flags |= XACT_EXT_COMPOUND; + flags |= POST_EXT_COMPOUND; break; case value_t::DATETIME: @@ -275,120 +275,120 @@ namespace { if (flags) xdata.add_flags(flags); - handler(xact); + handler(post); } } -void collapse_xacts::report_subtotal() +void collapse_posts::report_subtotal() { if (! count) return; std::size_t displayed_count = 0; - foreach (xact_t * xact, component_xacts) { - if (only_predicate(*xact) && display_predicate(*xact)) + foreach (post_t * post, component_posts) { + if (only_predicate(*post) && display_predicate(*post)) displayed_count++; } if (displayed_count == 1) { - item_handler<xact_t>::operator()(*last_xact); + item_handler<post_t>::operator()(*last_post); } else if (only_collapse_if_zero && ! subtotal.is_zero()) { - foreach (xact_t * xact, component_xacts) - item_handler<xact_t>::operator()(*xact); + foreach (post_t * post, component_posts) + item_handler<post_t>::operator()(*post); } else { date_t earliest_date; - foreach (xact_t * xact, component_xacts) { - date_t reported = xact->date(); + foreach (post_t * post, component_posts) { + date_t reported = post->date(); if (! is_valid(earliest_date) || reported < earliest_date) earliest_date = reported; } - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = last_entry->payee; - entry._date = (is_valid(earliest_date) ? - earliest_date : last_entry->_date); - DEBUG("filter.collapse", "Pseudo-entry date = " << *entry._date); + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = last_xact->payee; + xact._date = (is_valid(earliest_date) ? + earliest_date : last_xact->_date); + DEBUG("filter.collapse", "Pseudo-xact date = " << *xact._date); - handle_value(subtotal, &totals_account, &entry, 0, xact_temps, *handler); + handle_value(subtotal, &totals_account, &xact, 0, post_temps, *handler); } - component_xacts.clear(); + component_posts.clear(); - last_entry = NULL; - last_xact = NULL; + last_xact = NULL; + last_post = NULL; subtotal = 0L; count = 0; } -void collapse_xacts::operator()(xact_t& xact) +void collapse_posts::operator()(post_t& post) { - // If we've reached a new entry, report on the subtotal + // If we've reached a new xact, report on the subtotal // accumulated thus far. - if (last_entry != xact.entry && count > 0) + if (last_xact != post.xact && count > 0) report_subtotal(); - xact.add_to_value(subtotal, amount_expr); + post.add_to_value(subtotal, amount_expr); count++; - component_xacts.push_back(&xact); + component_posts.push_back(&post); - last_entry = xact.entry; - last_xact = &xact; + last_xact = post.xact; + last_post = &post; } -void related_xacts::flush() +void related_posts::flush() { - if (xacts.size() > 0) { - foreach (xact_t * xact, xacts) { - if (xact->entry) { - foreach (xact_t * r_xact, xact->entry->xacts) { - xact_t::xdata_t& xdata(r_xact->xdata()); - if (! xdata.has_flags(XACT_EXT_HANDLED) && - (! xdata.has_flags(XACT_EXT_RECEIVED) ? - ! r_xact->has_flags(XACT_AUTO | XACT_VIRTUAL) : + if (posts.size() > 0) { + foreach (post_t * post, posts) { + if (post->xact) { + foreach (post_t * r_post, post->xact->posts) { + post_t::xdata_t& xdata(r_post->xdata()); + if (! xdata.has_flags(POST_EXT_HANDLED) && + (! xdata.has_flags(POST_EXT_RECEIVED) ? + ! r_post->has_flags(POST_AUTO | POST_VIRTUAL) : also_matching)) { - xdata.add_flags(XACT_EXT_HANDLED); - item_handler<xact_t>::operator()(*r_xact); + xdata.add_flags(POST_EXT_HANDLED); + item_handler<post_t>::operator()(*r_post); } } } else { // This code should only be reachable from the "output" // command, since that is the only command which attempts to - // output auto or period entries. - xact_t::xdata_t& xdata(xact->xdata()); - if (! xdata.has_flags(XACT_EXT_HANDLED) && - ! xact->has_flags(XACT_AUTO)) { - xdata.add_flags(XACT_EXT_HANDLED); - item_handler<xact_t>::operator()(*xact); + // output auto or period xacts. + post_t::xdata_t& xdata(post->xdata()); + if (! xdata.has_flags(POST_EXT_HANDLED) && + ! post->has_flags(POST_AUTO)) { + xdata.add_flags(POST_EXT_HANDLED); + item_handler<post_t>::operator()(*post); } } } } - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } -void changed_value_xacts::output_diff(xact_t * xact, const date_t& date) +void changed_value_posts::output_diff(post_t * post, const date_t& date) { if (is_valid(date)) - xact->xdata().date = date; + post->xdata().date = date; value_t repriced_total; try { - bind_scope_t bound_scope(report, *xact); + bind_scope_t bound_scope(report, *post); repriced_total = total_expr.calc(bound_scope); } catch (...) { - xact->xdata().date = date_t(); + post->xdata().date = date_t(); throw; } - xact->xdata().date = date_t(); + post->xdata().date = date_t(); DEBUG("filter.changed_value", "output_diff(last_balance) = " << last_balance); @@ -399,49 +399,49 @@ void changed_value_xacts::output_diff(xact_t * xact, const date_t& date) DEBUG("filter.changed_value", "output_diff(strip(diff)) = " << diff.strip_annotations(report.what_to_keep())); - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = "Commodities revalued"; - entry._date = is_valid(date) ? date : xact->date(); + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = "Commodities revalued"; + xact._date = is_valid(date) ? date : post->date(); - handle_value(diff, &revalued_account, &entry, XACT_EXT_NO_TOTAL, - xact_temps, *handler, *entry._date, repriced_total); + handle_value(diff, &revalued_account, &xact, POST_EXT_NO_TOTAL, + post_temps, *handler, *xact._date, repriced_total); } } -void changed_value_xacts::operator()(xact_t& xact) +void changed_value_posts::operator()(post_t& post) { - if (last_xact) - output_diff(last_xact, xact.date()); + if (last_post) + output_diff(last_post, post.date()); if (changed_values_only) - xact.xdata().add_flags(XACT_EXT_DISPLAYED); + post.xdata().add_flags(POST_EXT_DISPLAYED); - item_handler<xact_t>::operator()(xact); + item_handler<post_t>::operator()(post); - bind_scope_t bound_scope(report, xact); + bind_scope_t bound_scope(report, post); last_balance = total_expr.calc(bound_scope); - last_xact = &xact; + last_post = &post; } -void subtotal_xacts::report_subtotal(const char * spec_fmt, +void subtotal_posts::report_subtotal(const char * spec_fmt, const date_t& start, const date_t& finish) { - if (component_xacts.empty()) + if (component_posts.empty()) return; date_t range_start = start; date_t range_finish = finish; - foreach (xact_t * xact, component_xacts) { - date_t date = xact->date(); + foreach (post_t * post, component_posts) { + date_t date = post->date(); if (! is_valid(range_start) || date < range_start) range_start = date; if (! is_valid(range_finish) || date > range_finish) range_finish = date; } - component_xacts.clear(); + component_posts.clear(); std::ostringstream out_date; if (spec_fmt) { @@ -456,61 +456,61 @@ void subtotal_xacts::report_subtotal(const char * spec_fmt, out_date << format_date(range_finish, std::string("- ") + output_date_format); } - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = out_date.str(); - entry._date = range_start; + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = out_date.str(); + xact._date = range_start; foreach (values_map::value_type& pair, values) - handle_value(pair.second.value, pair.second.account, &entry, 0, - xact_temps, *handler); + handle_value(pair.second.value, pair.second.account, &xact, 0, + post_temps, *handler); values.clear(); } -void subtotal_xacts::operator()(xact_t& xact) +void subtotal_posts::operator()(post_t& post) { - component_xacts.push_back(&xact); + component_posts.push_back(&post); - account_t * acct = xact.reported_account(); + account_t * acct = post.reported_account(); assert(acct); values_map::iterator i = values.find(acct->fullname()); if (i == values.end()) { value_t temp; - xact.add_to_value(temp, amount_expr); + post.add_to_value(temp, amount_expr); std::pair<values_map::iterator, bool> result = values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp))); assert(result.second); } else { - xact.add_to_value((*i).second.value, amount_expr); + post.add_to_value((*i).second.value, amount_expr); } - // If the account for this xact is all virtual, mark it as + // If the account for this post is all virtual, mark it as // such, so that `handle_value' can show "(Account)" for accounts - // that contain only virtual xacts. + // that contain only virtual posts. - if (! xact.has_flags(XACT_VIRTUAL)) - xact.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS); - else if (! xact.has_flags(XACT_MUST_BALANCE)) - xact.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS); + if (! post.has_flags(POST_VIRTUAL)) + post.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_NON_VIRTUALS); + else if (! post.has_flags(POST_MUST_BALANCE)) + post.reported_account()->xdata().add_flags(ACCOUNT_EXT_HAS_UNB_VIRTUALS); } -void interval_xacts::report_subtotal(const date_t& finish) +void interval_posts::report_subtotal(const date_t& finish) { - if (last_xact && interval) { + if (last_post && interval) { if (exact_periods) - subtotal_xacts::report_subtotal(); + subtotal_posts::report_subtotal(); else - subtotal_xacts::report_subtotal(NULL, interval.begin, finish); + subtotal_posts::report_subtotal(NULL, interval.begin, finish); } - last_xact = NULL; + last_post = NULL; } -void interval_xacts::operator()(xact_t& xact) +void interval_posts::operator()(post_t& post) { - date_t date = xact.date(); + date_t date = post.date(); if ((is_valid(interval.begin) && date < interval.begin) || (is_valid(interval.end) && date >= interval.end)) @@ -523,7 +523,7 @@ void interval_xacts::operator()(xact_t& xact) date_t quant = interval.increment(interval.begin); if (date >= quant) { - if (last_xact) + if (last_post) report_subtotal(quant - gregorian::days(1)); date_t temp; @@ -533,56 +533,56 @@ void interval_xacts::operator()(xact_t& xact) interval.begin = quant; quant = temp; - if (generate_empty_xacts) { - // Generate a null transaction, so the intervening periods can be + if (generate_empty_posts) { + // Generate a null posting, so the intervening periods can be // seen when -E is used, or if the calculated amount ends up being // non-zero - entry_temps.push_back(entry_t()); - entry_t& null_entry = entry_temps.back(); - null_entry.add_flags(ITEM_TEMP); - null_entry._date = quant - gregorian::days(1); - - xact_temps.push_back(xact_t(&empty_account)); + xact_temps.push_back(xact_t()); xact_t& null_xact = xact_temps.back(); - null_xact.add_flags(ITEM_TEMP | XACT_CALCULATED); - null_xact.amount = 0L; - null_entry.add_xact(&null_xact); + null_xact.add_flags(ITEM_TEMP); + null_xact._date = quant - gregorian::days(1); + + post_temps.push_back(post_t(&empty_account)); + post_t& null_post = post_temps.back(); + null_post.add_flags(ITEM_TEMP | POST_CALCULATED); + null_post.amount = 0L; + null_xact.add_post(&null_post); - last_xact = &null_xact; - subtotal_xacts::operator()(null_xact); + last_post = &null_post; + subtotal_posts::operator()(null_post); report_subtotal(quant - gregorian::days(1)); } } start = interval.begin = quant; } - subtotal_xacts::operator()(xact); + subtotal_posts::operator()(post); } else { - item_handler<xact_t>::operator()(xact); + item_handler<post_t>::operator()(post); } - last_xact = &xact; + last_post = &post; } -void xacts_as_equity::report_subtotal() +void posts_as_equity::report_subtotal() { date_t finish; - foreach (xact_t * xact, component_xacts) { - date_t date = xact->date(); + foreach (post_t * post, component_posts) { + date_t date = post->date(); if (! is_valid(finish) || date > finish) finish = date; } - component_xacts.clear(); + component_posts.clear(); - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = "Opening Balances"; - entry._date = finish; + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = "Opening Balances"; + xact._date = finish; value_t total = 0L; foreach (values_map::value_type& pair, values) { - handle_value(pair.second.value, pair.second.account, &entry, 0, - xact_temps, *handler); + handle_value(pair.second.value, pair.second.account, &xact, 0, + post_temps, *handler); total += pair.second.value; } values.clear(); @@ -590,40 +590,40 @@ void xacts_as_equity::report_subtotal() if (total.is_balance()) { foreach (balance_t::amounts_map::value_type pair, total.as_balance().amounts) { - xact_temps.push_back(xact_t(balance_account)); - xact_t& balance_xact = xact_temps.back(); - balance_xact.add_flags(ITEM_TEMP); - balance_xact.amount = - pair.second; - entry.add_xact(&balance_xact); - (*handler)(balance_xact); + post_temps.push_back(post_t(balance_account)); + post_t& balance_post = post_temps.back(); + balance_post.add_flags(ITEM_TEMP); + balance_post.amount = - pair.second; + xact.add_post(&balance_post); + (*handler)(balance_post); } } else { - xact_temps.push_back(xact_t(balance_account)); - xact_t& balance_xact = xact_temps.back(); - balance_xact.add_flags(ITEM_TEMP); - balance_xact.amount = - total.to_amount(); - entry.add_xact(&balance_xact); - (*handler)(balance_xact); + post_temps.push_back(post_t(balance_account)); + post_t& balance_post = post_temps.back(); + balance_post.add_flags(ITEM_TEMP); + balance_post.amount = - total.to_amount(); + xact.add_post(&balance_post); + (*handler)(balance_post); } } -void by_payee_xacts::flush() +void by_payee_posts::flush() { foreach (payee_subtotals_map::value_type& pair, payee_subtotals) pair.second->report_subtotal(pair.first.c_str()); - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); payee_subtotals.clear(); } -void by_payee_xacts::operator()(xact_t& xact) +void by_payee_posts::operator()(post_t& post) { - payee_subtotals_map::iterator i = payee_subtotals.find(xact.entry->payee); + payee_subtotals_map::iterator i = payee_subtotals.find(post.xact->payee); if (i == payee_subtotals.end()) { payee_subtotals_pair - temp(xact.entry->payee, - shared_ptr<subtotal_xacts>(new subtotal_xacts(handler, amount_expr))); + temp(post.xact->payee, + shared_ptr<subtotal_posts>(new subtotal_posts(handler, amount_expr))); std::pair<payee_subtotals_map::iterator, bool> result = payee_subtotals.insert(temp); @@ -633,27 +633,27 @@ void by_payee_xacts::operator()(xact_t& xact) i = result.first; } - (*(*i).second)(xact); + (*(*i).second)(post); } -void transfer_details::operator()(xact_t& xact) +void transfer_details::operator()(post_t& post) { - entry_temps.push_back(*xact.entry); - entry_t& entry = entry_temps.back(); - entry._date = xact.date(); - - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.set_state(xact.state()); + xact_temps.push_back(*post.xact); + xact_t& xact = xact_temps.back(); + xact._date = post.date(); + + post_temps.push_back(post); + post_t& temp = post_temps.back(); + temp.xact = &xact; + temp.set_state(post.state()); temp.add_flags(ITEM_TEMP); - entry.add_xact(&temp); + xact.add_post(&temp); bind_scope_t bound_scope(scope, temp); switch (which_element) { case SET_PAYEE: - entry.payee = expr.calc(bound_scope).to_string(); + xact.payee = expr.calc(bound_scope).to_string(); break; case SET_ACCOUNT: temp.account = master->find_account(expr.calc(bound_scope).to_string()); @@ -663,42 +663,42 @@ void transfer_details::operator()(xact_t& xact) break; } - item_handler<xact_t>::operator()(temp); + item_handler<post_t>::operator()(temp); } -void dow_xacts::flush() +void dow_posts::flush() { for (int i = 0; i < 7; i++) { - foreach (xact_t * xact, days_of_the_week[i]) - subtotal_xacts::operator()(*xact); - subtotal_xacts::report_subtotal("%As"); + foreach (post_t * post, days_of_the_week[i]) + subtotal_posts::operator()(*post); + subtotal_posts::report_subtotal("%As"); days_of_the_week[i].clear(); } - subtotal_xacts::flush(); + subtotal_posts::flush(); } -void generate_xacts::add_period_entries(period_entries_list& period_entries) +void generate_posts::add_period_xacts(period_xacts_list& period_xacts) { - foreach (period_entry_t * entry, period_entries) - foreach (xact_t * xact, entry->xacts) - add_xact(entry->period, *xact); + foreach (period_xact_t * xact, period_xacts) + foreach (post_t * post, xact->posts) + add_post(xact->period, *post); } -void generate_xacts::add_xact(const interval_t& period, xact_t& xact) +void generate_posts::add_post(const interval_t& period, post_t& post) { - pending_xacts.push_back(pending_xacts_pair(period, &xact)); + pending_posts.push_back(pending_posts_pair(period, &post)); } -void budget_xacts::report_budget_items(const date_t& date) +void budget_posts::report_budget_items(const date_t& date) { - if (pending_xacts.size() == 0) + if (pending_posts.size() == 0) return; bool reported; do { reported = false; - foreach (pending_xacts_list::value_type& pair, pending_xacts) { + foreach (pending_posts_list::value_type& pair, pending_posts) { date_t& begin = pair.first.begin; if (! is_valid(begin)) { pair.first.set_start(date); @@ -707,26 +707,26 @@ void budget_xacts::report_budget_items(const date_t& date) if (begin < date && (! is_valid(pair.first.end) || begin < pair.first.end)) { - xact_t& xact = *pair.second; + post_t& post = *pair.second; DEBUG("ledger.walk.budget", "Reporting budget for " - << xact.reported_account()->fullname()); + << post.reported_account()->fullname()); - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = "Budget entry"; - entry._date = begin; + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = "Budget transaction"; + xact._date = begin; - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.add_flags(XACT_AUTO | ITEM_TEMP); + post_temps.push_back(post); + post_t& temp = post_temps.back(); + temp.xact = &xact; + temp.add_flags(POST_AUTO | ITEM_TEMP); temp.amount.in_place_negate(); - entry.add_xact(&temp); + xact.add_post(&temp); begin = pair.first.increment(begin); - item_handler<xact_t>::operator()(temp); + item_handler<post_t>::operator()(temp); reported = true; } @@ -734,40 +734,40 @@ void budget_xacts::report_budget_items(const date_t& date) } while (reported); } -void budget_xacts::operator()(xact_t& xact) +void budget_posts::operator()(post_t& post) { - bool xact_in_budget = false; + bool post_in_budget = false; - foreach (pending_xacts_list::value_type& pair, pending_xacts) { - for (account_t * acct = xact.reported_account(); + foreach (pending_posts_list::value_type& pair, pending_posts) { + for (account_t * acct = post.reported_account(); acct; acct = acct->parent) { if (acct == (*pair.second).reported_account()) { - xact_in_budget = true; - // Report the xact as if it had occurred in the parent + post_in_budget = true; + // Report the post as if it had occurred in the parent // account. - if (xact.reported_account() != acct) - xact.xdata().account = acct; + if (post.reported_account() != acct) + post.xdata().account = acct; goto handle; } } } handle: - if (xact_in_budget && flags & BUDGET_BUDGETED) { - report_budget_items(xact.date()); - item_handler<xact_t>::operator()(xact); + if (post_in_budget && flags & BUDGET_BUDGETED) { + report_budget_items(post.date()); + item_handler<post_t>::operator()(post); } - else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) { - item_handler<xact_t>::operator()(xact); + else if (! post_in_budget && flags & BUDGET_UNBUDGETED) { + item_handler<post_t>::operator()(post); } } -void forecast_xacts::add_xact(const interval_t& period, xact_t& xact) +void forecast_posts::add_post(const interval_t& period, post_t& post) { - generate_xacts::add_xact(period, xact); + generate_posts::add_post(period, post); - interval_t& i = pending_xacts.back().first; + interval_t& i = pending_posts.back().first; if (! is_valid(i.begin)) { i.set_start(CURRENT_DATE()); i.begin = i.increment(i.begin); @@ -777,15 +777,15 @@ void forecast_xacts::add_xact(const interval_t& period, xact_t& xact) } } -void forecast_xacts::flush() +void forecast_posts::flush() { - xacts_list passed; + posts_list passed; date_t last; - while (pending_xacts.size() > 0) { - pending_xacts_list::iterator least = pending_xacts.begin(); - for (pending_xacts_list::iterator i = ++pending_xacts.begin(); - i != pending_xacts.end(); + while (pending_posts.size() > 0) { + pending_posts_list::iterator least = pending_posts.begin(); + for (pending_posts_list::iterator i = ++pending_posts.begin(); + i != pending_posts.end(); i++) if ((*i).first.begin < (*least).first.begin) least = i; @@ -793,33 +793,33 @@ void forecast_xacts::flush() date_t& begin = (*least).first.begin; if (is_valid((*least).first.end) && begin >= (*least).first.end) { - pending_xacts.erase(least); + pending_posts.erase(least); passed.remove((*least).second); continue; } - xact_t& xact = *(*least).second; + post_t& post = *(*least).second; - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - entry.payee = "Forecast entry"; - entry._date = begin; + xact_temps.push_back(xact_t()); + xact_t& xact = xact_temps.back(); + xact.payee = "Forecast transaction"; + xact._date = begin; - xact_temps.push_back(xact); - xact_t& temp = xact_temps.back(); - temp.entry = &entry; - temp.add_flags(XACT_AUTO | ITEM_TEMP); - entry.add_xact(&temp); + post_temps.push_back(post); + post_t& temp = post_temps.back(); + temp.xact = &xact; + temp.add_flags(POST_AUTO | ITEM_TEMP); + xact.add_post(&temp); date_t next = (*least).first.increment(begin); if (next < begin || (is_valid(last) && (next - last).days() > 365 * 5)) break; begin = next; - item_handler<xact_t>::operator()(temp); + item_handler<post_t>::operator()(temp); if (temp.has_xdata() && - temp.xdata().has_flags(XACT_EXT_MATCHES)) { + temp.xdata().has_flags(POST_EXT_MATCHES)) { bind_scope_t bound_scope(context, temp); if (! pred(bound_scope)) break; @@ -827,21 +827,21 @@ void forecast_xacts::flush() passed.clear(); } else { bool found = false; - foreach (xact_t * x, passed) - if (x == &xact) { + foreach (post_t * x, passed) + if (x == &post) { found = true; break; } if (! found) { - passed.push_back(&xact); - if (passed.size() >= pending_xacts.size()) + passed.push_back(&post); + if (passed.size() >= pending_posts.size()) break; } } } - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } pass_down_accounts::pass_down_accounts(acct_handler_ptr handler, diff --git a/src/filters.h b/src/filters.h index 3a8a5ab5..a2ab5aec 100644 --- a/src/filters.h +++ b/src/filters.h @@ -48,15 +48,15 @@ #include "chain.h" #include "predicate.h" -#include "entry.h" #include "xact.h" +#include "post.h" #include "account.h" namespace ledger { ////////////////////////////////////////////////////////////////////// // -// Transaction filters +// Posting filters // /** @@ -64,10 +64,10 @@ namespace ledger { * * Long. */ -class ignore_xacts : public item_handler<xact_t> +class ignore_posts : public item_handler<post_t> { public: - virtual void operator()(xact_t&) {} + virtual void operator()(post_t&) {} }; /** @@ -75,30 +75,30 @@ public: * * Long. */ -class clear_xact_xdata : public item_handler<xact_t> +class clear_post_xdata : public item_handler<post_t> { public: - virtual void operator()(xact_t& xact) { - xact.clear_xdata(); + virtual void operator()(post_t& post) { + post.clear_xdata(); } }; -class xacts_iterator; +class posts_iterator; /** * @brief Brief * * Long. */ -class pass_down_xacts : public item_handler<xact_t> +class pass_down_posts : public item_handler<post_t> { - pass_down_xacts(); + pass_down_posts(); public: - pass_down_xacts(xact_handler_ptr handler, xacts_iterator& iter); + pass_down_posts(post_handler_ptr handler, posts_iterator& iter); - virtual ~pass_down_xacts() { - TRACE_DTOR(pass_down_xacts); + virtual ~pass_down_posts() { + TRACE_DTOR(pass_down_posts); } }; @@ -107,22 +107,22 @@ public: * * Long. */ -class push_to_xacts_list : public item_handler<xact_t> +class push_to_posts_list : public item_handler<post_t> { - push_to_xacts_list(); + push_to_posts_list(); public: - xacts_list& xacts; + posts_list& posts; - push_to_xacts_list(xacts_list& _xacts) : xacts(_xacts) { - TRACE_CTOR(push_to_xacts_list, "xacts_list&"); + push_to_posts_list(posts_list& _posts) : posts(_posts) { + TRACE_CTOR(push_to_posts_list, "posts_list&"); } - virtual ~push_to_xacts_list() { - TRACE_DTOR(push_to_xacts_list); + virtual ~push_to_posts_list() { + TRACE_DTOR(push_to_posts_list); } - virtual void operator()(xact_t& xact) { - xacts.push_back(&xact); + virtual void operator()(post_t& post) { + posts.push_back(&post); } }; @@ -131,32 +131,32 @@ public: * * Long. */ -class truncate_entries : public item_handler<xact_t> +class truncate_xacts : public item_handler<post_t> { int head_count; int tail_count; - xacts_list xacts; + posts_list posts; - truncate_entries(); + truncate_xacts(); public: - truncate_entries(xact_handler_ptr handler, + truncate_xacts(post_handler_ptr handler, int _head_count, int _tail_count) - : item_handler<xact_t>(handler), + : item_handler<post_t>(handler), head_count(_head_count), tail_count(_tail_count) { - TRACE_CTOR(truncate_entries, "xact_handler_ptr, int, int"); + TRACE_CTOR(truncate_xacts, "post_handler_ptr, int, int"); } - virtual ~truncate_entries() { - TRACE_DTOR(truncate_entries); + virtual ~truncate_xacts() { + TRACE_DTOR(truncate_xacts); } virtual void flush(); - virtual void operator()(xact_t& xact) { + virtual void operator()(post_t& post) { if (! (tail_count == 0 && head_count > 0 && - static_cast<int>(xacts.size()) >= head_count)) - xacts.push_back(&xact); + static_cast<int>(posts.size()) >= head_count)) + posts.push_back(&post); } }; @@ -165,15 +165,15 @@ public: * * Long. */ -class set_account_value : public item_handler<xact_t> +class set_account_value : public item_handler<post_t> { expr_t& amount_expr; public: set_account_value(expr_t& _amount_expr) - : item_handler<xact_t>(), amount_expr(_amount_expr) {} + : item_handler<post_t>(), amount_expr(_amount_expr) {} - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -181,43 +181,43 @@ public: * * Long. */ -class sort_xacts : public item_handler<xact_t> +class sort_posts : public item_handler<post_t> { - typedef std::deque<xact_t *> xacts_deque; + typedef std::deque<post_t *> posts_deque; - xacts_deque xacts; + posts_deque posts; const expr_t sort_order; - sort_xacts(); + sort_posts(); public: - sort_xacts(xact_handler_ptr handler, + sort_posts(post_handler_ptr handler, const expr_t& _sort_order) - : item_handler<xact_t>(handler), + : item_handler<post_t>(handler), sort_order(_sort_order) { - TRACE_CTOR(sort_xacts, - "xact_handler_ptr, const value_expr&"); + TRACE_CTOR(sort_posts, + "post_handler_ptr, const value_expr&"); } - sort_xacts(xact_handler_ptr handler, + sort_posts(post_handler_ptr handler, const string& _sort_order) - : item_handler<xact_t>(handler), + : item_handler<post_t>(handler), sort_order(_sort_order) { - TRACE_CTOR(sort_xacts, - "xact_handler_ptr, const string&"); + TRACE_CTOR(sort_posts, + "post_handler_ptr, const string&"); } - virtual ~sort_xacts() { - TRACE_DTOR(sort_xacts); + virtual ~sort_posts() { + TRACE_DTOR(sort_posts); } - virtual void post_accumulated_xacts(); + virtual void post_accumulated_posts(); virtual void flush() { - post_accumulated_xacts(); - item_handler<xact_t>::flush(); + post_accumulated_posts(); + item_handler<post_t>::flush(); } - virtual void operator()(xact_t& xact) { - xacts.push_back(&xact); + virtual void operator()(post_t& post) { + posts.push_back(&post); } }; @@ -226,42 +226,42 @@ public: * * Long. */ -class sort_entries : public item_handler<xact_t> +class sort_xacts : public item_handler<post_t> { - sort_xacts sorter; - entry_t * last_entry; + sort_posts sorter; + xact_t * last_xact; - sort_entries(); + sort_xacts(); public: - sort_entries(xact_handler_ptr handler, + sort_xacts(post_handler_ptr handler, const expr_t& _sort_order) : sorter(handler, _sort_order) { - TRACE_CTOR(sort_entries, - "xact_handler_ptr, const value_expr&"); + TRACE_CTOR(sort_xacts, + "post_handler_ptr, const value_expr&"); } - sort_entries(xact_handler_ptr handler, + sort_xacts(post_handler_ptr handler, const string& _sort_order) : sorter(handler, _sort_order) { - TRACE_CTOR(sort_entries, - "xact_handler_ptr, const string&"); + TRACE_CTOR(sort_xacts, + "post_handler_ptr, const string&"); } - virtual ~sort_entries() { - TRACE_DTOR(sort_entries); + virtual ~sort_xacts() { + TRACE_DTOR(sort_xacts); } virtual void flush() { sorter.flush(); - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } - virtual void operator()(xact_t& xact) { - if (last_entry && xact.entry != last_entry) - sorter.post_accumulated_xacts(); + virtual void operator()(post_t& post) { + if (last_xact && post.xact != last_xact) + sorter.post_accumulated_posts(); - sorter(xact); + sorter(post); - last_entry = xact.entry; + last_xact = post.xact; } }; @@ -270,37 +270,37 @@ public: * * Long. */ -class filter_xacts : public item_handler<xact_t> +class filter_posts : public item_handler<post_t> { item_predicate pred; scope_t& context; - filter_xacts(); + filter_posts(); public: - filter_xacts(xact_handler_ptr handler, + filter_posts(post_handler_ptr handler, const item_predicate& predicate, scope_t& _context) - : item_handler<xact_t>(handler), pred(predicate), context(_context) { - TRACE_CTOR(filter_xacts, - "xact_handler_ptr, const item_predicate&, scope_t&"); + : item_handler<post_t>(handler), pred(predicate), context(_context) { + TRACE_CTOR(filter_posts, + "post_handler_ptr, const item_predicate&, scope_t&"); } - virtual ~filter_xacts() { - TRACE_DTOR(filter_xacts); + virtual ~filter_posts() { + TRACE_DTOR(filter_posts); } - virtual void operator()(xact_t& xact) { - bind_scope_t bound_scope(context, xact); + virtual void operator()(post_t& post) { + bind_scope_t bound_scope(context, post); if (pred(bound_scope)) { - xact.xdata().add_flags(XACT_EXT_MATCHES); - (*handler)(xact); + post.xdata().add_flags(POST_EXT_MATCHES); + (*handler)(post); } } }; -inline void clear_entries_xacts(std::list<entry_t>& entries_list) { - foreach (entry_t& entry, entries_list) - entry.xacts.clear(); +inline void clear_xacts_posts(std::list<xact_t>& xacts_list) { + foreach (xact_t& xact, xacts_list) + xact.posts.clear(); } /** @@ -308,26 +308,26 @@ inline void clear_entries_xacts(std::list<entry_t>& entries_list) { * * Long. */ -class anonymize_xacts : public item_handler<xact_t> +class anonymize_posts : public item_handler<post_t> { - std::list<entry_t> entry_temps; - std::list<xact_t> xact_temps; + std::list<xact_t> xact_temps; + std::list<post_t> post_temps; - entry_t * last_entry; + xact_t * last_xact; - anonymize_xacts(); + anonymize_posts(); public: - anonymize_xacts(xact_handler_ptr handler) - : item_handler<xact_t>(handler), last_entry(NULL) { - TRACE_CTOR(anonymize_xacts, "xact_handler_ptr"); + anonymize_posts(post_handler_ptr handler) + : item_handler<post_t>(handler), last_xact(NULL) { + TRACE_CTOR(anonymize_posts, "post_handler_ptr"); } - virtual ~anonymize_xacts() { - TRACE_DTOR(anonymize_xacts); - clear_entries_xacts(entry_temps); + virtual ~anonymize_posts() { + TRACE_DTOR(anonymize_posts); + clear_xacts_posts(xact_temps); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -335,25 +335,25 @@ public: * * Long. */ -class calc_xacts : public item_handler<xact_t> +class calc_posts : public item_handler<post_t> { - xact_t * last_xact; + post_t * last_post; expr_t& amount_expr; - calc_xacts(); + calc_posts(); public: - calc_xacts(xact_handler_ptr handler, + calc_posts(post_handler_ptr handler, expr_t& _amount_expr) - : item_handler<xact_t>(handler), - last_xact(NULL), amount_expr(_amount_expr) { - TRACE_CTOR(calc_xacts, "xact_handler_ptr, expr_t&"); + : item_handler<post_t>(handler), + last_post(NULL), amount_expr(_amount_expr) { + TRACE_CTOR(calc_posts, "post_handler_ptr, expr_t&"); } - virtual ~calc_xacts() { - TRACE_DTOR(calc_xacts); + virtual ~calc_posts() { + TRACE_DTOR(calc_posts); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -361,51 +361,51 @@ public: * * Long. */ -class collapse_xacts : public item_handler<xact_t> +class collapse_posts : public item_handler<post_t> { expr_t& amount_expr; item_predicate display_predicate; item_predicate only_predicate; value_t subtotal; std::size_t count; - entry_t * last_entry; xact_t * last_xact; + post_t * last_post; account_t totals_account; bool only_collapse_if_zero; - std::list<entry_t> entry_temps; - std::list<xact_t> xact_temps; - std::list<xact_t *> component_xacts; + std::list<xact_t> xact_temps; + std::list<post_t> post_temps; + std::list<post_t *> component_posts; - collapse_xacts(); + collapse_posts(); public: - collapse_xacts(xact_handler_ptr handler, + collapse_posts(post_handler_ptr handler, expr_t& _amount_expr, item_predicate _display_predicate, item_predicate _only_predicate, bool _only_collapse_if_zero = false) - : item_handler<xact_t>(handler), amount_expr(_amount_expr), + : item_handler<post_t>(handler), amount_expr(_amount_expr), display_predicate(_display_predicate), only_predicate(_only_predicate), count(0), - last_entry(NULL), last_xact(NULL), + last_xact(NULL), last_post(NULL), totals_account(NULL, "<Total>"), only_collapse_if_zero(_only_collapse_if_zero) { - TRACE_CTOR(collapse_xacts, "xact_handler_ptr"); + TRACE_CTOR(collapse_posts, "post_handler_ptr"); } - virtual ~collapse_xacts() { - TRACE_DTOR(collapse_xacts); - clear_entries_xacts(entry_temps); + virtual ~collapse_posts() { + TRACE_DTOR(collapse_posts); + clear_xacts_posts(xact_temps); } virtual void flush() { report_subtotal(); - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } void report_subtotal(); - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -413,29 +413,29 @@ public: * * Long. */ -class related_xacts : public item_handler<xact_t> +class related_posts : public item_handler<post_t> { - xacts_list xacts; + posts_list posts; bool also_matching; - related_xacts(); + related_posts(); public: - related_xacts(xact_handler_ptr handler, + related_posts(post_handler_ptr handler, const bool _also_matching = false) - : item_handler<xact_t>(handler), + : item_handler<post_t>(handler), also_matching(_also_matching) { - TRACE_CTOR(related_xacts, - "xact_handler_ptr, const bool"); + TRACE_CTOR(related_posts, + "post_handler_ptr, const bool"); } - virtual ~related_xacts() throw() { - TRACE_DTOR(related_xacts); + virtual ~related_posts() throw() { + TRACE_DTOR(related_posts); } virtual void flush(); - virtual void operator()(xact_t& xact) { - xact.xdata().add_flags(XACT_EXT_RECEIVED); - xacts.push_back(&xact); + virtual void operator()(post_t& post) { + post.xdata().add_flags(POST_EXT_RECEIVED); + posts.push_back(&post); } }; @@ -444,50 +444,50 @@ public: * * Long. */ -class changed_value_xacts : public item_handler<xact_t> +class changed_value_posts : public item_handler<post_t> { - // This filter requires that calc_xacts be used at some point + // This filter requires that calc_posts be used at some point // later in the chain. expr_t total_expr; report_t& report; bool changed_values_only; - xact_t * last_xact; + post_t * last_post; value_t last_balance; account_t revalued_account; - std::list<entry_t> entry_temps; - std::list<xact_t> xact_temps; + std::list<xact_t> xact_temps; + std::list<post_t> post_temps; - changed_value_xacts(); + changed_value_posts(); public: - changed_value_xacts(xact_handler_ptr handler, + changed_value_posts(post_handler_ptr handler, const expr_t& _total_expr, report_t& _report, bool _changed_values_only) - : item_handler<xact_t>(handler), total_expr(_total_expr), + : item_handler<post_t>(handler), total_expr(_total_expr), report(_report), changed_values_only(_changed_values_only), - last_xact(NULL), revalued_account(NULL, "<Revalued>") { - TRACE_CTOR(changed_value_xacts, - "xact_handler_ptr, const expr_t&, report_t&, bool"); + last_post(NULL), revalued_account(NULL, "<Revalued>") { + TRACE_CTOR(changed_value_posts, + "post_handler_ptr, const expr_t&, report_t&, bool"); } - virtual ~changed_value_xacts() { - TRACE_DTOR(changed_value_xacts); - clear_entries_xacts(entry_temps); + virtual ~changed_value_posts() { + TRACE_DTOR(changed_value_posts); + clear_xacts_posts(xact_temps); } virtual void flush() { - if (last_xact && last_xact->date() <= CURRENT_DATE()) { - output_diff(last_xact, CURRENT_DATE()); - last_xact = NULL; + if (last_post && last_post->date() <= CURRENT_DATE()) { + output_diff(last_post, CURRENT_DATE()); + last_post = NULL; } - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } - void output_diff(xact_t * xact, const date_t& current); + void output_diff(post_t * post, const date_t& current); - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -495,9 +495,9 @@ public: * * Long. */ -class subtotal_xacts : public item_handler<xact_t> +class subtotal_posts : public item_handler<post_t> { - subtotal_xacts(); + subtotal_posts(); protected: class acct_value_t @@ -530,21 +530,21 @@ protected: expr_t& amount_expr; values_map values; optional<string> date_format; - std::list<entry_t> entry_temps; - std::list<xact_t> xact_temps; - std::list<xact_t *> component_xacts; + std::list<xact_t> xact_temps; + std::list<post_t> post_temps; + std::list<post_t *> component_posts; public: - subtotal_xacts(xact_handler_ptr handler, expr_t& _amount_expr, + subtotal_posts(post_handler_ptr handler, expr_t& _amount_expr, const optional<string>& _date_format = none) - : item_handler<xact_t>(handler), amount_expr(_amount_expr), + : item_handler<post_t>(handler), amount_expr(_amount_expr), date_format(_date_format) { - TRACE_CTOR(subtotal_xacts, - "xact_handler_ptr, expr_t&, const optional<string>&"); + TRACE_CTOR(subtotal_posts, + "post_handler_ptr, expr_t&, const optional<string>&"); } - virtual ~subtotal_xacts() { - TRACE_DTOR(subtotal_xacts); - clear_entries_xacts(entry_temps); + virtual ~subtotal_posts() { + TRACE_DTOR(subtotal_posts); + clear_xacts_posts(xact_temps); } void report_subtotal(const char * spec_fmt = NULL, @@ -554,9 +554,9 @@ public: virtual void flush() { if (values.size() > 0) report_subtotal(); - item_handler<xact_t>::flush(); + item_handler<post_t>::flush(); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -564,70 +564,70 @@ public: * * Long. */ -class interval_xacts : public subtotal_xacts +class interval_posts : public subtotal_posts { interval_t interval; - xact_t * last_xact; + post_t * last_post; account_t empty_account; bool exact_periods; - bool generate_empty_xacts; + bool generate_empty_posts; date_t start; - interval_xacts(); + interval_posts(); public: - interval_xacts(xact_handler_ptr _handler, + interval_posts(post_handler_ptr _handler, expr_t& amount_expr, const interval_t& _interval, bool _exact_periods = false, - bool _generate_empty_xacts = false) - : subtotal_xacts(_handler, amount_expr), interval(_interval), - last_xact(NULL), empty_account(NULL, "<None>"), + bool _generate_empty_posts = false) + : subtotal_posts(_handler, amount_expr), interval(_interval), + last_post(NULL), empty_account(NULL, "<None>"), exact_periods(_exact_periods), - generate_empty_xacts(_generate_empty_xacts) { - TRACE_CTOR(interval_xacts, - "xact_handler_ptr, expr_t&, interval_t, account_t *, bool, bool"); + generate_empty_posts(_generate_empty_posts) { + TRACE_CTOR(interval_posts, + "post_handler_ptr, expr_t&, interval_t, account_t *, bool, bool"); } - virtual ~interval_xacts() throw() { - TRACE_DTOR(interval_xacts); + virtual ~interval_posts() throw() { + TRACE_DTOR(interval_posts); } void report_subtotal(const date_t& finish); virtual void flush() { - if (last_xact && interval) + if (last_post && interval) report_subtotal(interval.increment(interval.begin) - gregorian::days(1)); - subtotal_xacts::flush(); + subtotal_posts::flush(); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; -class xacts_as_equity : public subtotal_xacts +class posts_as_equity : public subtotal_posts { interval_t interval; - xact_t * last_xact; + post_t * last_post; account_t equity_account; account_t * balance_account; - xacts_as_equity(); + posts_as_equity(); public: - xacts_as_equity(xact_handler_ptr _handler, expr_t& amount_expr) - : subtotal_xacts(_handler, amount_expr), + posts_as_equity(post_handler_ptr _handler, expr_t& amount_expr) + : subtotal_posts(_handler, amount_expr), equity_account(NULL, "Equity") { - TRACE_CTOR(xacts_as_equity, "xact_handler_ptr, expr_t&"); + TRACE_CTOR(posts_as_equity, "post_handler_ptr, expr_t&"); balance_account = equity_account.find_account("Opening Balances"); } - virtual ~xacts_as_equity() throw() { - TRACE_DTOR(xacts_as_equity); + virtual ~posts_as_equity() throw() { + TRACE_DTOR(posts_as_equity); } void report_subtotal(); virtual void flush() { report_subtotal(); - subtotal_xacts::flush(); + subtotal_posts::flush(); } }; @@ -636,27 +636,27 @@ public: * * Long. */ -class by_payee_xacts : public item_handler<xact_t> +class by_payee_posts : public item_handler<post_t> { - typedef std::map<string, shared_ptr<subtotal_xacts> > payee_subtotals_map; - typedef std::pair<string, shared_ptr<subtotal_xacts> > payee_subtotals_pair; + typedef std::map<string, shared_ptr<subtotal_posts> > payee_subtotals_map; + typedef std::pair<string, shared_ptr<subtotal_posts> > payee_subtotals_pair; expr_t& amount_expr; payee_subtotals_map payee_subtotals; - by_payee_xacts(); + by_payee_posts(); public: - by_payee_xacts(xact_handler_ptr handler, expr_t& _amount_expr) - : item_handler<xact_t>(handler), amount_expr(_amount_expr) { - TRACE_CTOR(by_payee_xacts, "xact_handler_ptr, expr_t&"); + by_payee_posts(post_handler_ptr handler, expr_t& _amount_expr) + : item_handler<post_t>(handler), amount_expr(_amount_expr) { + TRACE_CTOR(by_payee_posts, "post_handler_ptr, expr_t&"); } - virtual ~by_payee_xacts() { - TRACE_DTOR(by_payee_xacts); + virtual ~by_payee_posts() { + TRACE_DTOR(by_payee_posts); } virtual void flush(); - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -664,10 +664,10 @@ class by_payee_xacts : public item_handler<xact_t> * * Long. */ -class transfer_details : public item_handler<xact_t> +class transfer_details : public item_handler<post_t> { - std::list<entry_t> entry_temps; - std::list<xact_t> xact_temps; + std::list<xact_t> xact_temps; + std::list<post_t> post_temps; account_t * master; expr_t expr; scope_t& scope; @@ -680,22 +680,22 @@ public: SET_ACCOUNT } which_element; - transfer_details(xact_handler_ptr handler, + transfer_details(post_handler_ptr handler, element_t _which_element, account_t * _master, const expr_t& _expr, scope_t& _scope) - : item_handler<xact_t>(handler), master(_master), + : item_handler<post_t>(handler), master(_master), expr(_expr), scope(_scope), which_element(_which_element) { TRACE_CTOR(transfer_details, - "xact_handler_ptr, element_t, account_t *, expr_t, scope_t&"); + "post_handler_ptr, element_t, account_t *, expr_t, scope_t&"); } virtual ~transfer_details() { TRACE_DTOR(transfer_details); - clear_entries_xacts(entry_temps); + clear_xacts_posts(xact_temps); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -703,24 +703,24 @@ public: * * Long. */ -class dow_xacts : public subtotal_xacts +class dow_posts : public subtotal_posts { - xacts_list days_of_the_week[7]; + posts_list days_of_the_week[7]; - dow_xacts(); + dow_posts(); public: - dow_xacts(xact_handler_ptr handler, expr_t& amount_expr) - : subtotal_xacts(handler, amount_expr) { - TRACE_CTOR(dow_xacts, "xact_handler_ptr, bool"); + dow_posts(post_handler_ptr handler, expr_t& amount_expr) + : subtotal_posts(handler, amount_expr) { + TRACE_CTOR(dow_posts, "post_handler_ptr, bool"); } - virtual ~dow_xacts() throw() { - TRACE_DTOR(dow_xacts); + virtual ~dow_posts() throw() { + TRACE_DTOR(dow_posts); } virtual void flush(); - virtual void operator()(xact_t& xact) { - days_of_the_week[xact.date().day_of_week()].push_back(&xact); + virtual void operator()(post_t& post) { + days_of_the_week[post.date().day_of_week()].push_back(&post); } }; @@ -729,32 +729,32 @@ public: * * Long. */ -class generate_xacts : public item_handler<xact_t> +class generate_posts : public item_handler<post_t> { - generate_xacts(); + generate_posts(); protected: - typedef std::pair<interval_t, xact_t *> pending_xacts_pair; - typedef std::list<pending_xacts_pair> pending_xacts_list; + typedef std::pair<interval_t, post_t *> pending_posts_pair; + typedef std::list<pending_posts_pair> pending_posts_list; - pending_xacts_list pending_xacts; - std::list<entry_t> entry_temps; - std::list<xact_t> xact_temps; + pending_posts_list pending_posts; + std::list<xact_t> xact_temps; + std::list<post_t> post_temps; public: - generate_xacts(xact_handler_ptr handler) - : item_handler<xact_t>(handler) { - TRACE_CTOR(generate_xacts, "xact_handler_ptr"); + generate_posts(post_handler_ptr handler) + : item_handler<post_t>(handler) { + TRACE_CTOR(generate_posts, "post_handler_ptr"); } - virtual ~generate_xacts() { - TRACE_DTOR(generate_xacts); - clear_entries_xacts(entry_temps); + virtual ~generate_posts() { + TRACE_DTOR(generate_posts); + clear_xacts_posts(xact_temps); } - void add_period_entries(period_entries_list& period_entries); + void add_period_xacts(period_xacts_list& period_xacts); - virtual void add_xact(const interval_t& period, xact_t& xact); + virtual void add_post(const interval_t& period, post_t& post); }; /** @@ -762,7 +762,7 @@ public: * * Long. */ -class budget_xacts : public generate_xacts +class budget_posts : public generate_posts { #define BUDGET_NO_BUDGET 0x00 #define BUDGET_BUDGETED 0x01 @@ -770,21 +770,21 @@ class budget_xacts : public generate_xacts uint_least8_t flags; - budget_xacts(); + budget_posts(); public: - budget_xacts(xact_handler_ptr handler, + budget_posts(post_handler_ptr handler, uint_least8_t _flags = BUDGET_BUDGETED) - : generate_xacts(handler), flags(_flags) { - TRACE_CTOR(budget_xacts, "xact_handler_ptr, uint_least8_t"); + : generate_posts(handler), flags(_flags) { + TRACE_CTOR(budget_posts, "post_handler_ptr, uint_least8_t"); } - virtual ~budget_xacts() throw() { - TRACE_DTOR(budget_xacts); + virtual ~budget_posts() throw() { + TRACE_DTOR(budget_posts); } void report_budget_items(const date_t& date); - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -792,24 +792,24 @@ public: * * Long. */ -class forecast_xacts : public generate_xacts +class forecast_posts : public generate_posts { item_predicate pred; scope_t& context; public: - forecast_xacts(xact_handler_ptr handler, + forecast_posts(post_handler_ptr handler, const item_predicate& predicate, scope_t& _context) - : generate_xacts(handler), pred(predicate), context(_context) { - TRACE_CTOR(forecast_xacts, - "xact_handler_ptr, const item_predicate&, scope_t&"); + : generate_posts(handler), pred(predicate), context(_context) { + TRACE_CTOR(forecast_posts, + "post_handler_ptr, const item_predicate&, scope_t&"); } - virtual ~forecast_xacts() throw() { - TRACE_DTOR(forecast_xacts); + virtual ~forecast_posts() throw() { + TRACE_DTOR(forecast_posts); } - virtual void add_xact(const interval_t& period, xact_t& xact); + virtual void add_post(const interval_t& period, post_t& post); virtual void flush(); }; diff --git a/src/format.cc b/src/format.cc index 5b813ee6..b4541a59 100644 --- a/src/format.cc +++ b/src/format.cc @@ -73,12 +73,12 @@ format_t::element_t * format_t::parse_elements(const string& fmt) // d: COMPLETE_DATE_STRING // D: DATE_STRING // S: SOURCE; break - // B: ENTRY_BEG_POS - // b: ENTRY_BEG_LINE - // E: ENTRY_END_POS - // e: ENTRY_END_LINE + // B: XACT_BEG_POS + // b: XACT_BEG_LINE + // E: XACT_END_POS + // e: XACT_END_LINE // X: CLEARED - // Y: ENTRY_CLEARED + // Y: XACT_CLEARED // C: CODE // P: PAYEE // W: OPT_ACCOUNT @@ -91,10 +91,10 @@ format_t::element_t * format_t::parse_elements(const string& fmt) // n: OPT_NOTE // _: DEPTH_SPACER // - // xB: XACT_BEG_POS - // xb: XACT_BEG_LINE - // xE: XACT_END_POS - // xe: XACT_END_LINE + // xB: POST_BEG_POS + // xb: POST_BEG_LINE + // xE: POST_END_POS + // xe: POST_END_LINE for (const char * p = fmt.c_str(); *p; p++) { if (*p != '%' && *p != '\\') { diff --git a/src/global.cc b/src/global.cc index 3416a3d4..e3969481 100644 --- a/src/global.cc +++ b/src/global.cc @@ -100,10 +100,10 @@ void global_scope_t::read_init() ifstream init(init_file); if (session().read_journal(init_file) > 0 || - session().journal->auto_entries.size() > 0 || - session().journal->period_entries.size() > 0) { - throw_(parse_error, - "Entries found in initialization file '" << init_file << "'"); + session().journal->auto_xacts.size() > 0 || + session().journal->period_xacts.size() > 0) { + throw_(parse_error, "Transactions found in initialization file '" + << init_file << "'"); } TRACE_FINISH(init, 1); @@ -385,7 +385,7 @@ void global_scope_t::normalize_report_options(const string& verb) // jww (2008-08-14): This code really needs to be rationalized away for 3.0. // I might be able to do it with command objects, like register_t, which // each know how to adjust the report based on its current option settings. - if (verb == "print" || verb == "entry" || verb == "dump") { + if (verb == "print" || verb == "xact" || verb == "dump") { rep.HANDLER(related).on_only(); rep.HANDLER(related_all).on_only(); } @@ -402,13 +402,13 @@ void global_scope_t::normalize_report_options(const string& verb) } if (! rep.HANDLED(empty)) - rep.HANDLER(display_).on("amount|(!xact&total)"); + rep.HANDLER(display_).on("amount|(!post&total)"); if (verb[0] != 'b' && verb[0] != 'r') rep.HANDLER(base).on_only(); if (rep.HANDLED(period_) && ! rep.HANDLED(sort_all_)) - rep.HANDLER(sort_entries_).on_only(); + rep.HANDLER(sort_xacts_).on_only(); long cols = 0; if (rep.HANDLED(columns_)) @@ -59,9 +59,9 @@ namespace ledger { class item_t : public supports_flags<>, public scope_t { public: -#define ITEM_NORMAL 0x00 // no flags at all, a basic transaction -#define ITEM_GENERATED 0x01 // transaction was not found in a journal -#define ITEM_TEMP 0x02 // transaction is a temporary object +#define ITEM_NORMAL 0x00 // no flags at all, a basic posting +#define ITEM_GENERATED 0x01 // posting was not found in a journal +#define ITEM_TEMP 0x02 // posting is a temporary object enum state_t { UNCLEARED = 0, CLEARED, PENDING }; @@ -112,11 +112,11 @@ public: end_line = item.end_line; } - virtual bool operator==(const item_t& entry) { - return this == &entry; + virtual bool operator==(const item_t& xact) { + return this == &xact; } - virtual bool operator!=(const item_t& entry) { - return ! (*this == entry); + virtual bool operator!=(const item_t& xact) { + return ! (*this == xact); } virtual bool has_tag(const string& tag) const; diff --git a/src/iterators.cc b/src/iterators.cc index 835fec9d..6a022772 100644 --- a/src/iterators.cc +++ b/src/iterators.cc @@ -35,57 +35,57 @@ namespace ledger { -void entries_iterator::reset(journal_t& journal) +void xacts_iterator::reset(journal_t& journal) { - entries_i = journal.entries.begin(); - entries_end = journal.entries.end(); - entries_uninitialized = false; + xacts_i = journal.xacts.begin(); + xacts_end = journal.xacts.end(); + xacts_uninitialized = false; } -entry_t * entries_iterator::operator()() +xact_t * xacts_iterator::operator()() { - if (entries_i != entries_end) - return *entries_i++; + if (xacts_i != xacts_end) + return *xacts_i++; else return NULL; } -void journal_xacts_iterator::reset(journal_t& journal) +void journal_posts_iterator::reset(journal_t& journal) { - entries.reset(journal); + xacts.reset(journal); - entry_t * entry = entries(); - if (entry != NULL) - xacts.reset(*entry); + xact_t * xact = xacts(); + if (xact != NULL) + posts.reset(*xact); } -xact_t * journal_xacts_iterator::operator()() +post_t * journal_posts_iterator::operator()() { - xact_t * xact = xacts(); - if (xact == NULL) { - entry_t * entry = entries(); - if (entry != NULL) { - xacts.reset(*entry); - xact = xacts(); + post_t * post = posts(); + if (post == NULL) { + xact_t * xact = xacts(); + if (xact != NULL) { + posts.reset(*xact); + post = posts(); } } - return xact; + return post; } -void xacts_commodities_iterator::reset(journal_t& journal) +void posts_commodities_iterator::reset(journal_t& journal) { - journal_xacts.reset(journal); + journal_posts.reset(journal); std::set<commodity_t *> commodities; - for (xact_t * xact = journal_xacts(); xact; xact = journal_xacts()) { - commodity_t& comm(xact->amount.commodity()); + for (post_t * post = journal_posts(); post; post = journal_posts()) { + commodity_t& comm(post->amount.commodity()); if (comm.flags() & COMMODITY_NOMARKET) continue; commodities.insert(&comm); } - std::map<string, entry_t *> entries_by_commodity; + std::map<string, xact_t *> xacts_by_commodity; foreach (commodity_t * comm, commodities) { optional<commodity_t::varied_history_t&> history = comm->varied_history(); @@ -98,55 +98,55 @@ void xacts_commodities_iterator::reset(journal_t& journal) history->histories) { foreach (commodity_t::base_t::history_map::value_type hpair, pair.second.prices) { - entry_t * entry; + xact_t * xact; string symbol = hpair.second.commodity().symbol(); - std::map<string, entry_t *>::iterator i = - entries_by_commodity.find(symbol); - if (i != entries_by_commodity.end()) { - entry = (*i).second; + std::map<string, xact_t *>::iterator i = + xacts_by_commodity.find(symbol); + if (i != xacts_by_commodity.end()) { + xact = (*i).second; } else { - entry_temps.push_back(new entry_t); - entry = entry_temps.back(); - entry->payee = symbol; - entry->_date = hpair.first.date(); - entries_by_commodity.insert - (std::pair<string, entry_t *>(symbol, entry)); + xact_temps.push_back(new xact_t); + xact = xact_temps.back(); + xact->payee = symbol; + xact->_date = hpair.first.date(); + xacts_by_commodity.insert + (std::pair<string, xact_t *>(symbol, xact)); } - xact_temps.push_back(xact_t(account)); - xact_t& temp = xact_temps.back(); + post_temps.push_back(post_t(account)); + post_t& temp = post_temps.back(); temp._date = hpair.first.date(); - temp.entry = entry; + temp.xact = xact; temp.amount = hpair.second; temp.set_flags(ITEM_GENERATED | ITEM_TEMP); - entry->add_xact(&temp); + xact->add_post(&temp); } } } - entries.entries_i = entry_temps.begin(); - entries.entries_end = entry_temps.end(); + xacts.xacts_i = xact_temps.begin(); + xacts.xacts_end = xact_temps.end(); - entries.entries_uninitialized = false; + xacts.xacts_uninitialized = false; - entry_t * entry = entries(); - if (entry != NULL) - xacts.reset(*entry); + xact_t * xact = xacts(); + if (xact != NULL) + posts.reset(*xact); } -xact_t * xacts_commodities_iterator::operator()() +post_t * posts_commodities_iterator::operator()() { - xact_t * xact = xacts(); - if (xact == NULL) { - entry_t * entry = entries(); - if (entry != NULL) { - xacts.reset(*entry); - xact = xacts(); + post_t * post = posts(); + if (post == NULL) { + xact_t * xact = xacts(); + if (xact != NULL) { + posts.reset(*xact); + post = posts(); } } - return xact; + return post; } account_t * basic_accounts_iterator::operator()() diff --git a/src/iterators.h b/src/iterators.h index 92f887d0..d4c99fbf 100644 --- a/src/iterators.h +++ b/src/iterators.h @@ -47,7 +47,7 @@ #define _ITERATORS_H #include "journal.h" -#include "entry.h" +#include "xact.h" #include "account.h" namespace ledger { @@ -57,11 +57,11 @@ namespace ledger { * * Long. */ -class xacts_iterator : public noncopyable +class posts_iterator : public noncopyable { public: - virtual ~xacts_iterator() throw() {} - virtual xact_t * operator()() = 0; + virtual ~posts_iterator() throw() {} + virtual post_t * operator()() = 0; }; /** @@ -69,37 +69,37 @@ public: * * Long. */ -class entry_xacts_iterator : public xacts_iterator +class xact_posts_iterator : public posts_iterator { - xacts_list::iterator xacts_i; - xacts_list::iterator xacts_end; + posts_list::iterator posts_i; + posts_list::iterator posts_end; - bool xacts_uninitialized; + bool posts_uninitialized; public: - entry_xacts_iterator() : xacts_uninitialized(true) { - TRACE_CTOR(entry_xacts_iterator, ""); + xact_posts_iterator() : posts_uninitialized(true) { + TRACE_CTOR(xact_posts_iterator, ""); } - entry_xacts_iterator(entry_t& entry) - : xacts_uninitialized(true) { - TRACE_CTOR(entry_xacts_iterator, "entry_t&"); - reset(entry); + xact_posts_iterator(xact_t& xact) + : posts_uninitialized(true) { + TRACE_CTOR(xact_posts_iterator, "xact_t&"); + reset(xact); } - virtual ~entry_xacts_iterator() throw() { - TRACE_DTOR(entry_xacts_iterator); + virtual ~xact_posts_iterator() throw() { + TRACE_DTOR(xact_posts_iterator); } - void reset(entry_t& entry) { - xacts_i = entry.xacts.begin(); - xacts_end = entry.xacts.end(); + void reset(xact_t& xact) { + posts_i = xact.posts.begin(); + posts_end = xact.posts.end(); - xacts_uninitialized = false; + posts_uninitialized = false; } - virtual xact_t * operator()() { - if (xacts_i == xacts_end || xacts_uninitialized) + virtual post_t * operator()() { + if (posts_i == posts_end || posts_uninitialized) return NULL; - return *xacts_i++; + return *posts_i++; } }; @@ -108,28 +108,28 @@ public: * * Long. */ -class entries_iterator : public noncopyable +class xacts_iterator : public noncopyable { public: - entries_list::iterator entries_i; - entries_list::iterator entries_end; + xacts_list::iterator xacts_i; + xacts_list::iterator xacts_end; - bool entries_uninitialized; + bool xacts_uninitialized; - entries_iterator() : entries_uninitialized(true) { - TRACE_CTOR(entries_iterator, ""); + xacts_iterator() : xacts_uninitialized(true) { + TRACE_CTOR(xacts_iterator, ""); } - entries_iterator(journal_t& journal) : entries_uninitialized(true) { - TRACE_CTOR(entries_iterator, "journal_t&"); + xacts_iterator(journal_t& journal) : xacts_uninitialized(true) { + TRACE_CTOR(xacts_iterator, "journal_t&"); reset(journal); } - virtual ~entries_iterator() throw() { - TRACE_DTOR(entries_iterator); + virtual ~xacts_iterator() throw() { + TRACE_DTOR(xacts_iterator); } void reset(journal_t& journal); - entry_t * operator()(); + xact_t * operator()(); }; /** @@ -137,26 +137,26 @@ public: * * Long. */ -class journal_xacts_iterator : public xacts_iterator +class journal_posts_iterator : public posts_iterator { - entries_iterator entries; - entry_xacts_iterator xacts; + xacts_iterator xacts; + xact_posts_iterator posts; public: - journal_xacts_iterator() { - TRACE_CTOR(journal_xacts_iterator, ""); + journal_posts_iterator() { + TRACE_CTOR(journal_posts_iterator, ""); } - journal_xacts_iterator(journal_t& journal) { - TRACE_CTOR(journal_xacts_iterator, "journal_t&"); + journal_posts_iterator(journal_t& journal) { + TRACE_CTOR(journal_posts_iterator, "journal_t&"); reset(journal); } - virtual ~journal_xacts_iterator() throw() { - TRACE_DTOR(journal_xacts_iterator); + virtual ~journal_posts_iterator() throw() { + TRACE_DTOR(journal_posts_iterator); } void reset(journal_t& journal); - virtual xact_t * operator()(); + virtual post_t * operator()(); }; /** @@ -164,34 +164,34 @@ public: * * Long. */ -class xacts_commodities_iterator : public xacts_iterator +class posts_commodities_iterator : public posts_iterator { protected: - journal_xacts_iterator journal_xacts; - entries_iterator entries; - entry_xacts_iterator xacts; + journal_posts_iterator journal_posts; + xacts_iterator xacts; + xact_posts_iterator posts; - std::list<xact_t> xact_temps; + std::list<post_t> post_temps; std::list<account_t> acct_temps; - entries_list entry_temps; + xacts_list xact_temps; public: - xacts_commodities_iterator() { - TRACE_CTOR(xacts_commodities_iterator, ""); + posts_commodities_iterator() { + TRACE_CTOR(posts_commodities_iterator, ""); } - xacts_commodities_iterator(journal_t& journal) { - TRACE_CTOR(xacts_commodities_iterator, "journal_t&"); + posts_commodities_iterator(journal_t& journal) { + TRACE_CTOR(posts_commodities_iterator, "journal_t&"); reset(journal); } - virtual ~xacts_commodities_iterator() throw() { - TRACE_DTOR(xacts_commodities_iterator); - foreach (entry_t * entry, entry_temps) - checked_delete(entry); + virtual ~posts_commodities_iterator() throw() { + TRACE_DTOR(posts_commodities_iterator); + foreach (xact_t * xact, xact_temps) + checked_delete(xact); } void reset(journal_t& journal); - virtual xact_t * operator()(); + virtual post_t * operator()(); }; /** diff --git a/src/journal.cc b/src/journal.cc index 823b31d0..d455939b 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -40,17 +40,17 @@ journal_t::~journal_t() { TRACE_DTOR(journal_t); - // Don't bother unhooking each entry's xacts from the + // Don't bother unhooking each xact's posts from the // accounts they refer to, because all accounts are about to // be deleted. - foreach (entry_t * entry, entries) - checked_delete(entry); + foreach (xact_t * xact, xacts) + checked_delete(xact); - foreach (auto_entry_t * entry, auto_entries) - checked_delete(entry); + foreach (auto_xact_t * xact, auto_xacts) + checked_delete(xact); - foreach (period_entry_t * entry, period_entries) - checked_delete(entry); + foreach (period_xact_t * xact, period_xacts) + checked_delete(xact); } void journal_t::add_account(account_t * acct) @@ -73,36 +73,36 @@ account_t * journal_t::find_account_re(const string& regexp) return master->find_account_re(regexp); } -bool journal_t::add_entry(entry_t * entry) +bool journal_t::add_xact(xact_t * xact) { - entry->journal = this; + xact->journal = this; - if (! entry_finalize_hooks.run_hooks(*entry, false) || - ! entry->finalize() || - ! entry_finalize_hooks.run_hooks(*entry, true)) { - entry->journal = NULL; + if (! xact_finalize_hooks.run_hooks(*xact, false) || + ! xact->finalize() || + ! xact_finalize_hooks.run_hooks(*xact, true)) { + xact->journal = NULL; return false; } - entries.push_back(entry); + xacts.push_back(xact); return true; } -bool journal_t::remove_entry(entry_t * entry) +bool journal_t::remove_xact(xact_t * xact) { bool found = false; - entries_list::iterator i; - for (i = entries.begin(); i != entries.end(); i++) - if (*i == entry) { + xacts_list::iterator i; + for (i = xacts.begin(); i != xacts.end(); i++) + if (*i == xact) { found = true; break; } if (! found) return false; - entries.erase(i); - entry->journal = NULL; + xacts.erase(i); + xact->journal = NULL; return true; } @@ -114,9 +114,9 @@ bool journal_t::valid() const return false; } - foreach (const entry_t * entry, entries) - if (! entry->valid()) { - DEBUG("ledger.validate", "journal_t: entry not valid"); + foreach (const xact_t * xact, xacts) + if (! xact->valid()) { + DEBUG("ledger.validate", "journal_t: xact not valid"); return false; } diff --git a/src/journal.h b/src/journal.h index b0d61c98..b8af8b00 100644 --- a/src/journal.h +++ b/src/journal.h @@ -48,7 +48,7 @@ #include "utils.h" #include "hooks.h" -#include "entry.h" +#include "xact.h" namespace ledger { @@ -66,12 +66,12 @@ class journal_t : public noncopyable public: account_t * master; account_t * basket; - entries_list entries; + xacts_list xacts; - auto_entries_list auto_entries; - period_entries_list period_entries; + auto_xacts_list auto_xacts; + period_xacts_list period_xacts; - hooks_t<entry_finalizer_t, entry_t> entry_finalize_hooks; + hooks_t<xact_finalizer_t, xact_t> xact_finalize_hooks; journal_t(account_t * _master = NULL) : master(_master) { TRACE_CTOR(journal_t, ""); @@ -85,14 +85,14 @@ public: account_t * find_account(const string& name, bool auto_create = true); account_t * find_account_re(const string& regexp); - bool add_entry(entry_t * entry); - bool remove_entry(entry_t * entry); + bool add_xact(xact_t * xact); + bool remove_xact(xact_t * xact); - void add_entry_finalizer(entry_finalizer_t * finalizer) { - entry_finalize_hooks.add_hook(finalizer); + void add_xact_finalizer(xact_finalizer_t * finalizer) { + xact_finalize_hooks.add_hook(finalizer); } - void remove_entry_finalizer(entry_finalizer_t * finalizer) { - entry_finalize_hooks.remove_hook(finalizer); + void remove_xact_finalizer(xact_finalizer_t * finalizer) { + xact_finalize_hooks.remove_hook(finalizer); } std::size_t parse(std::istream& in, diff --git a/src/output.cc b/src/output.cc index e33ae627..7daae417 100644 --- a/src/output.cc +++ b/src/output.cc @@ -33,13 +33,13 @@ namespace ledger { -format_xacts::format_xacts(report_t& _report, +format_posts::format_posts(report_t& _report, const string& format, bool _print_raw) - : report(_report), last_entry(NULL), last_xact(NULL), + : report(_report), last_xact(NULL), last_post(NULL), print_raw(_print_raw) { - TRACE_CTOR(format_xacts, "report&, const string&"); + TRACE_CTOR(format_posts, "report&, const string&"); const char * f = format.c_str(); @@ -58,46 +58,46 @@ format_xacts::format_xacts(report_t& _report, } } -void format_xacts::operator()(xact_t& xact) +void format_posts::operator()(post_t& post) { std::ostream& out(report.output_stream); if (print_raw) { - if (! xact.has_xdata() || - ! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) { - if (last_entry != xact.entry) { - if (last_entry) { - bind_scope_t entry_scope(report, *last_entry); - between_format.format(out, entry_scope); + if (! post.has_xdata() || + ! post.xdata().has_flags(POST_EXT_DISPLAYED)) { + if (last_xact != post.xact) { + if (last_xact) { + bind_scope_t xact_scope(report, *last_xact); + between_format.format(out, xact_scope); } - print_item(out, *xact.entry); + print_item(out, *post.xact); out << '\n'; - last_entry = xact.entry; + last_xact = post.xact; } - xact.xdata().add_flags(XACT_EXT_DISPLAYED); - last_xact = &xact; + post.xdata().add_flags(POST_EXT_DISPLAYED); + last_post = &post; } } - else if (! xact.has_xdata() || - ! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) { - bind_scope_t bound_scope(report, xact); - if (last_entry != xact.entry) { - if (last_entry) { - bind_scope_t entry_scope(report, *last_entry); - between_format.format(out, entry_scope); + else if (! post.has_xdata() || + ! post.xdata().has_flags(POST_EXT_DISPLAYED)) { + bind_scope_t bound_scope(report, post); + if (last_xact != post.xact) { + if (last_xact) { + bind_scope_t xact_scope(report, *last_xact); + between_format.format(out, xact_scope); } first_line_format.format(out, bound_scope); - last_entry = xact.entry; + last_xact = post.xact; } - else if (last_xact && last_xact->date() != xact.date()) { + else if (last_post && last_post->date() != post.date()) { first_line_format.format(out, bound_scope); } else { next_lines_format.format(out, bound_scope); } - xact.xdata().add_flags(XACT_EXT_DISPLAYED); - last_xact = &xact; + post.xdata().add_flags(POST_EXT_DISPLAYED); + last_post = &post; } } @@ -105,10 +105,10 @@ void gather_statistics::flush() { std::ostream& out(report.output_stream); - out << "Time period: " << statistics.earliest_xact << " to " - << statistics.latest_xact << std::endl << std::endl; + out << "Time period: " << statistics.earliest_post << " to " + << statistics.latest_post << std::endl << std::endl; - out << " Files these transactions came from:" << std::endl; + out << " Files these postings came from:" << std::endl; foreach (const path& pathname, statistics.filenames) if (! pathname.empty()) @@ -123,54 +123,54 @@ void gather_statistics::flush() out.width(8); out << std::right << statistics.accounts_referenced.size() << std::endl; - out << " Number of entries: " ; + out << " Number of transactions: " ; out.width(8); - out << std::right << statistics.total_entries << std::endl; + out << std::right << statistics.total_xacts << std::endl; - out << " Number of transactions: "; + out << " Number of postings: "; out.width(8); - out << std::right << statistics.total_xacts; + out << std::right << statistics.total_posts; out << " ("; out.precision(2); - out << (double((statistics.latest_xact - statistics.earliest_xact).days()) / - double(statistics.total_xacts)) << " per day)" << std::endl; + out << (double((statistics.latest_post - statistics.earliest_post).days()) / + double(statistics.total_posts)) << " per day)" << std::endl; - out << " Days since last xact: "; + out << " Days since last post: "; out.width(8); - out << std::right << (CURRENT_DATE() - statistics.latest_xact).days() + out << std::right << (CURRENT_DATE() - statistics.latest_post).days() << std::endl; - out << " Xacts in last 7 days: "; + out << " Posts in last 7 days: "; out.width(8); out << std::right << statistics.total_last_7_days << std::endl; - out << " Xacts in last 30 days: "; + out << " Posts in last 30 days: "; out.width(8); out << std::right << statistics.total_last_30_days << std::endl; - out << " Xacts seen this month: "; + out << " Posts seen this month: "; out.width(8); out << std::right << statistics.total_this_month << std::endl; - out << " Uncleared transactions: "; + out << " Uncleared postings: "; out.width(8); - out << std::right << statistics.total_uncleared_xacts << std::endl; + out << std::right << statistics.total_uncleared_posts << std::endl; out.flush(); } -void gather_statistics::operator()(xact_t& xact) +void gather_statistics::operator()(post_t& post) { - if (last_entry != xact.entry) { - statistics.total_entries++; - last_entry = xact.entry; - } - if (last_xact != &xact) { + if (last_xact != post.xact) { statistics.total_xacts++; - last_xact = &xact; + last_xact = post.xact; + } + if (last_post != &post) { + statistics.total_posts++; + last_post = &post; - statistics.filenames.insert(xact.pathname); + statistics.filenames.insert(post.pathname); - date_t date = xact.date(); + date_t date = post.date(); if (date.year() == CURRENT_DATE().year() && date.month() == CURRENT_DATE().month()) @@ -181,18 +181,18 @@ void gather_statistics::operator()(xact_t& xact) if ((CURRENT_DATE() - date).days() <= 7) statistics.total_last_7_days++; - if (xact.state() != item_t::CLEARED) - statistics.total_uncleared_xacts++; + if (post.state() != item_t::CLEARED) + statistics.total_uncleared_posts++; - if (! is_valid(statistics.earliest_xact) || - xact.date() < statistics.earliest_xact) - statistics.earliest_xact = xact.date(); - if (! is_valid(statistics.latest_xact) || - xact.date() > statistics.latest_xact) - statistics.latest_xact = xact.date(); + if (! is_valid(statistics.earliest_post) || + post.date() < statistics.earliest_post) + statistics.earliest_post = post.date(); + if (! is_valid(statistics.latest_post) || + post.date() > statistics.latest_post) + statistics.latest_post = post.date(); - statistics.accounts_referenced.insert(xact.account->fullname()); - statistics.payees_referenced.insert(xact.entry->payee); + statistics.accounts_referenced.insert(post.account->fullname()); + statistics.payees_referenced.insert(post.xact->payee); } } diff --git a/src/output.h b/src/output.h index fe007d42..93fd1d53 100644 --- a/src/output.h +++ b/src/output.h @@ -56,28 +56,28 @@ namespace ledger { * * Long. */ -class format_xacts : public item_handler<xact_t> +class format_posts : public item_handler<post_t> { protected: report_t& report; format_t first_line_format; format_t next_lines_format; format_t between_format; - entry_t * last_entry; - xact_t * last_xact; + xact_t * last_xact; + post_t * last_post; bool print_raw; public: - format_xacts(report_t& _report, const string& format, + format_posts(report_t& _report, const string& format, bool _print_raw = false); - virtual ~format_xacts() { - TRACE_DTOR(format_xacts); + virtual ~format_posts() { + TRACE_DTOR(format_posts); } virtual void flush() { report.output_stream.flush(); } - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** @@ -85,37 +85,37 @@ public: * * Long. */ -class gather_statistics : public item_handler<xact_t> +class gather_statistics : public item_handler<post_t> { protected: report_t& report; - entry_t * last_entry; - xact_t * last_xact; + xact_t * last_xact; + post_t * last_post; struct statistics_t { std::set<path> filenames; - std::size_t total_entries; std::size_t total_xacts; - std::size_t total_uncleared_xacts; + std::size_t total_posts; + std::size_t total_uncleared_posts; std::size_t total_last_7_days; std::size_t total_last_30_days; std::size_t total_this_month; - date_t earliest_xact; - date_t latest_xact; + date_t earliest_post; + date_t latest_post; std::set<string> accounts_referenced; std::set<string> payees_referenced; statistics_t() - : total_entries(0), total_xacts(0), total_uncleared_xacts(0), + : total_xacts(0), total_posts(0), total_uncleared_posts(0), total_last_7_days(0), total_last_30_days(0), total_this_month(0) {} } statistics; public: gather_statistics(report_t& _report) - : report(_report), last_entry(NULL), last_xact(NULL) { + : report(_report), last_xact(NULL), last_post(NULL) { TRACE_CTOR(gather_statistics, "report&"); } virtual ~gather_statistics() { @@ -123,7 +123,7 @@ public: } virtual void flush(); - virtual void operator()(xact_t& xact); + virtual void operator()(post_t& post); }; /** diff --git a/src/post.cc b/src/post.cc new file mode 100644 index 00000000..e87a1cbc --- /dev/null +++ b/src/post.cc @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2003-2009, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "post.h" +#include "journal.h" +#include "account.h" +#include "interactive.h" +#include "format.h" + +namespace ledger { + +bool post_t::has_tag(const string& tag) const +{ + if (item_t::has_tag(tag)) + return true; + if (xact) + return xact->has_tag(tag); + return false; +} + +bool post_t::has_tag(const mask_t& tag_mask, + const optional<mask_t>& value_mask) const +{ + if (item_t::has_tag(tag_mask, value_mask)) + return true; + if (xact) + return xact->has_tag(tag_mask, value_mask); + return false; +} + +optional<string> post_t::get_tag(const string& tag) const +{ + if (optional<string> value = item_t::get_tag(tag)) + return value; + if (xact) + return xact->get_tag(tag); + return none; +} + +optional<string> post_t::get_tag(const mask_t& tag_mask, + const optional<mask_t>& value_mask) const +{ + if (optional<string> value = item_t::get_tag(tag_mask, value_mask)) + return value; + if (xact) + return xact->get_tag(tag_mask, value_mask); + return none; +} + +date_t post_t::date() const +{ + if (xdata_ && is_valid(xdata_->date)) + return xdata_->date; + + if (item_t::use_effective_date) { + if (_date_eff) + return *_date_eff; + else if (xact && xact->_date_eff) + return *xact->_date_eff; + } + + if (! _date) { + assert(xact); + return xact->date(); + } + return *_date; +} + +optional<date_t> post_t::effective_date() const +{ + optional<date_t> date = item_t::effective_date(); + if (! date && xact) + return xact->effective_date(); + return date; +} + +item_t::state_t post_t::state() const +{ + if (xact) { + state_t xact_state = xact->state(); + if ((_state == UNCLEARED && xact_state != UNCLEARED) || + (_state == PENDING && xact_state == CLEARED)) + return xact_state; + } + return _state; +} + +namespace { + value_t get_this(post_t& post) { + return value_t(static_cast<scope_t *>(&post)); + } + + value_t get_is_calculated(post_t& post) { + return post.has_flags(POST_CALCULATED); + } + + value_t get_virtual(post_t& post) { + return post.has_flags(POST_VIRTUAL); + } + + value_t get_real(post_t& post) { + return ! post.has_flags(POST_VIRTUAL); + } + + value_t get_actual(post_t& post) { + return ! post.has_flags(POST_AUTO); + } + + value_t get_xact(post_t& post) { + return value_t(static_cast<scope_t *>(post.xact)); + } + + value_t get_code(post_t& post) { + if (post.xact->code) + return string_value(*post.xact->code); + else + return string_value(empty_string); + } + + value_t get_payee(post_t& post) { + return string_value(post.xact->payee); + } + + value_t get_amount(post_t& post) { + if (post.has_xdata() && + post.xdata().has_flags(POST_EXT_COMPOUND)) { + return post.xdata().value; + } else { + return post.amount; + } + } + + value_t get_commodity(post_t& post) { + return string_value(post.amount.commodity().symbol()); + } + + value_t get_commodity_is_primary(post_t& post) { + return post.amount.commodity().has_flags(COMMODITY_PRIMARY); + } + + value_t get_cost(post_t& post) { + if (post.has_xdata() && + post.xdata().has_flags(POST_EXT_COMPOUND)) { + return post.xdata().value; + } else { + if (post.cost) + return *post.cost; + else + return post.amount; + } + } + + value_t get_total(post_t& post) { + if (post.xdata_ && ! post.xdata_->total.is_null()) + return post.xdata_->total; + else + return post.amount; + } + + value_t get_count(post_t& post) { + if (post.xdata_) + return post.xdata_->count; + else + return 1L; + } + + value_t get_account(call_scope_t& scope) + { + in_context_t<post_t> env(scope, "&l"); + + string name = env->reported_account()->fullname(); + + if (env.has(0) && env.get<long>(0) > 2) + name = format_t::truncate(name, env.get<long>(0) - 2, true); + + if (env->has_flags(POST_VIRTUAL)) { + if (env->must_balance()) + name = string("[") + name + "]"; + else + name = string("(") + name + ")"; + } + return string_value(name); + } + + value_t get_account_base(post_t& post) { + return string_value(post.reported_account()->name); + } + + value_t get_account_depth(post_t& post) { + return long(post.reported_account()->depth); + } + + template <value_t (*Func)(post_t&)> + value_t get_wrapper(call_scope_t& scope) { + return (*Func)(find_scope<post_t>(scope)); + } +} + +expr_t::ptr_op_t post_t::lookup(const string& name) +{ + switch (name[0]) { + case 'a': + if (name[1] == '\0' || name == "amount") + return WRAP_FUNCTOR(get_wrapper<&get_amount>); + else if (name == "account") + return WRAP_FUNCTOR(get_account); + else if (name == "account_base") + return WRAP_FUNCTOR(get_wrapper<&get_account_base>); + else if (name == "actual") + return WRAP_FUNCTOR(get_wrapper<&get_actual>); + break; + + case 'c': + if (name == "code") + return WRAP_FUNCTOR(get_wrapper<&get_code>); + else if (name == "cost") + return WRAP_FUNCTOR(get_wrapper<&get_cost>); + else if (name == "count") + return WRAP_FUNCTOR(get_wrapper<&get_count>); + else if (name == "calculated") + return WRAP_FUNCTOR(get_wrapper<&get_is_calculated>); + else if (name == "commodity") + return WRAP_FUNCTOR(get_wrapper<&get_commodity>); + break; + + case 'd': + if (name == "depth") + return WRAP_FUNCTOR(get_wrapper<&get_account_depth>); + break; + + case 'r': + if (name == "real") + return WRAP_FUNCTOR(get_wrapper<&get_real>); + break; + + case 'p': + if (name == "post") + return WRAP_FUNCTOR(get_wrapper<&get_this>); + else if (name == "payee") + return WRAP_FUNCTOR(get_wrapper<&get_payee>); + else if (name == "primary") + return WRAP_FUNCTOR(get_wrapper<&get_commodity_is_primary>); + break; + + case 't': + if (name[1] == '\0' || name == "total") + return WRAP_FUNCTOR(get_wrapper<&get_total>); + break; + + case 'v': + if (name == "virtual") + return WRAP_FUNCTOR(get_wrapper<&get_virtual>); + break; + + case 'x': + if (name == "xact") + return WRAP_FUNCTOR(get_wrapper<&get_xact>); + break; + } + + return item_t::lookup(name); +} + +bool post_t::valid() const +{ + if (! xact) { + DEBUG("ledger.validate", "post_t: ! xact"); + return false; + } + + posts_list::const_iterator i = + std::find(xact->posts.begin(), + xact->posts.end(), this); + if (i == xact->posts.end()) { + DEBUG("ledger.validate", "post_t: ! found"); + return false; + } + + if (! account) { + DEBUG("ledger.validate", "post_t: ! account"); + return false; + } + + if (! amount.valid()) { + DEBUG("ledger.validate", "post_t: ! amount.valid()"); + return false; + } + + if (cost && ! cost->valid()) { + DEBUG("ledger.validate", "post_t: cost && ! cost->valid()"); + return false; + } + + return true; +} + +void post_t::add_to_value(value_t& value, expr_t& expr) +{ + if (xdata_ && xdata_->has_flags(POST_EXT_COMPOUND)) { + add_or_set_value(value, xdata_->value); + } + else if (! xdata_ || ! xdata_->has_flags(POST_EXT_NO_TOTAL)) { + bind_scope_t bound_scope(*expr.get_context(), *this); + add_or_set_value(value, expr.calc(bound_scope)); + } +} + +} // namespace ledger diff --git a/src/post.h b/src/post.h new file mode 100644 index 00000000..84c0d929 --- /dev/null +++ b/src/post.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2003-2009, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup data + */ + +/** + * @file post.h + * @author John Wiegley + * + * @ingroup data + * + * @brief Brief + * + * Long. + */ +#ifndef _POST_H +#define _POST_H + +#include "item.h" + +namespace ledger { + +class xact_t; +class account_t; + +class post_t; +typedef std::list<post_t *> posts_list; + +/** + * @brief Brief + * + * Long. + */ +class post_t : public item_t +{ +public: +#define POST_VIRTUAL 0x10 // the account was specified with (parens) +#define POST_MUST_BALANCE 0x20 // the account was specified with [brackets] +#define POST_AUTO 0x40 // posting created by automated xact +#define POST_CALCULATED 0x80 // posting's amount was auto-calculated + + xact_t * xact; // only set for posts of regular xacts + account_t * account; + + amount_t amount; // can be null until finalization + optional<amount_t> cost; + optional<amount_t> assigned_amount; + + post_t(account_t * _account = NULL, + flags_t _flags = ITEM_NORMAL) + : item_t(_flags), + xact(NULL), account(_account) + { + TRACE_CTOR(post_t, "account_t *, flags_t"); + } + post_t(account_t * _account, + const amount_t& _amount, + flags_t _flags = ITEM_NORMAL, + const optional<string>& _note = none) + : item_t(_flags, _note), + xact(NULL), account(_account), amount(_amount) + { + TRACE_CTOR(post_t, "account_t *, const amount_t&, flags_t, const optional<string>&"); + } + post_t(const post_t& post) + : item_t(post), + xact(post.xact), + account(post.account), + amount(post.amount), + cost(post.cost), + assigned_amount(post.assigned_amount), + xdata_(post.xdata_) + { + TRACE_CTOR(post_t, "copy"); + } + ~post_t() { + TRACE_DTOR(post_t); + } + + virtual bool has_tag(const string& tag) const; + virtual bool has_tag(const mask_t& tag_mask, + const optional<mask_t>& value_mask = none) const; + + virtual optional<string> get_tag(const string& tag) const; + virtual optional<string> get_tag(const mask_t& tag_mask, + const optional<mask_t>& value_mask = none) const; + + virtual date_t date() const; + virtual optional<date_t> effective_date() const; + + virtual state_t state() const; + + bool must_balance() const { + return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE); + } + + virtual expr_t::ptr_op_t lookup(const string& name); + + bool valid() const; + + struct xdata_t : public supports_flags<> + { +#define POST_EXT_RECEIVED 0x01 +#define POST_EXT_HANDLED 0x02 +#define POST_EXT_TO_DISPLAY 0x04 +#define POST_EXT_DISPLAYED 0x08 +#define POST_EXT_NO_TOTAL 0x10 +#define POST_EXT_SORT_CALC 0x20 +#define POST_EXT_COMPOUND 0x40 +#define POST_EXT_MATCHES 0x80 + + value_t total; + std::size_t count; + value_t value; + date_t date; + account_t * account; + void * ptr; + + std::list<sort_value_t> sort_values; + + xdata_t() + : supports_flags<>(), count(0), account(NULL), ptr(NULL) { + TRACE_CTOR(post_t::xdata_t, ""); + } + xdata_t(const xdata_t& other) + : supports_flags<>(other.flags()), + total(other.total), + count(other.count), + value(other.value), + date(other.date), + account(other.account), + ptr(NULL), + sort_values(other.sort_values) + { + TRACE_CTOR(post_t::xdata_t, "copy"); + } + ~xdata_t() throw() { + TRACE_DTOR(post_t::xdata_t); + } + }; + + // This variable holds optional "extended data" which is usually produced + // only during reporting, and only for the posting set being reported. + // It's a memory-saving measure to delay allocation until the last possible + // moment. + mutable optional<xdata_t> xdata_; + + bool has_xdata() const { + return xdata_; + } + void clear_xdata() { + xdata_ = none; + } + xdata_t& xdata() { + if (! xdata_) + xdata_ = xdata_t(); + return *xdata_; + } + + void add_to_value(value_t& value, expr_t& expr); + + account_t * reported_account() { + if (xdata_) + if (account_t * acct = xdata_->account) + return acct; + return account; + } + + const account_t * reported_account() const { + return const_cast<post_t *>(this)->reported_account(); + } + + friend class xact_t; +}; + +} // namespace ledger + +#endif // _POST_H diff --git a/src/precmd.cc b/src/precmd.cc index 4b623904..e890e2f5 100644 --- a/src/precmd.cc +++ b/src/precmd.cc @@ -36,7 +36,7 @@ namespace ledger { namespace { - xact_t * get_sample_xact(report_t& report) + post_t * get_sample_post(report_t& report) { { string str; @@ -52,7 +52,7 @@ namespace { std::ostream& out(report.output_stream); - out << "--- Context is first transaction of the following entry ---" + out << "--- Context is first posting of the following transaction ---" << std::endl << str << std::endl; { std::istringstream in(str); @@ -60,8 +60,8 @@ namespace { report.session.clean_accounts(); } } - entry_t * first = report.session.journal->entries.front(); - return first->xacts.front(); + xact_t * first = report.session.journal->xacts.front(); + return first->posts.front(); } } @@ -76,7 +76,7 @@ value_t parse_command(call_scope_t& args) report_t& report(find_scope<report_t>(args)); std::ostream& out(report.output_stream); - xact_t * xact = get_sample_xact(report); + post_t * post = get_sample_post(report); out << "--- Input expression ---" << std::endl; out << arg << std::endl; @@ -89,7 +89,7 @@ value_t parse_command(call_scope_t& args) out << std::endl << "--- Expression tree ---" << std::endl; expr.dump(out); - bind_scope_t bound_scope(args, *xact); + bind_scope_t bound_scope(args, *post); expr.compile(bound_scope); out << std::endl << "--- Compiled tree ---" << std::endl; expr.dump(out); @@ -125,7 +125,7 @@ value_t format_command(call_scope_t& args) report_t& report(find_scope<report_t>(args)); std::ostream& out(report.output_stream); - xact_t * xact = get_sample_xact(report); + post_t * post = get_sample_post(report); out << "--- Input format string ---" << std::endl; out << arg << std::endl << std::endl; @@ -135,7 +135,7 @@ value_t format_command(call_scope_t& args) fmt.dump(out); out << std::endl << "--- Formatted string ---" << std::endl; - bind_scope_t bound_scope(args, *xact); + bind_scope_t bound_scope(args, *post); out << '"'; fmt.format(out, bound_scope); out << "\"\n"; diff --git a/src/report.cc b/src/report.cc index 92fc2b34..316aa89b 100644 --- a/src/report.cc +++ b/src/report.cc @@ -41,18 +41,18 @@ namespace ledger { -void report_t::xacts_report(xact_handler_ptr handler) +void report_t::posts_report(post_handler_ptr handler) { - journal_xacts_iterator walker(*session.journal.get()); - pass_down_xacts(chain_xact_handlers(*this, handler), walker); - session.clean_xacts(); + journal_posts_iterator walker(*session.journal.get()); + pass_down_posts(chain_post_handlers(*this, handler), walker); + session.clean_posts(); } -void report_t::entry_report(xact_handler_ptr handler, entry_t& entry) +void report_t::xact_report(post_handler_ptr handler, xact_t& xact) { - entry_xacts_iterator walker(entry); - pass_down_xacts(chain_xact_handlers(*this, handler), walker); - session.clean_xacts(entry); + xact_posts_iterator walker(xact); + pass_down_posts(chain_post_handlers(*this, handler), walker); + session.clean_posts(xact); } void report_t::sum_all_accounts() @@ -60,9 +60,9 @@ void report_t::sum_all_accounts() expr_t& amount_expr(HANDLER(amount_).expr); amount_expr.set_context(this); - journal_xacts_iterator walker(*session.journal.get()); - pass_down_xacts(chain_xact_handlers - (*this, xact_handler_ptr(new set_account_value(amount_expr)), + journal_posts_iterator walker(*session.journal.get()); + pass_down_posts(chain_post_handlers + (*this, post_handler_ptr(new set_account_value(amount_expr)), true), walker); expr_t& account_amount_expr(HANDLER(account_amount_).expr); @@ -89,15 +89,15 @@ void report_t::accounts_report(acct_handler_ptr handler) else pass_down_accounts(handler, *iter.get()); - session.clean_xacts(); + session.clean_posts(); session.clean_accounts(); } -void report_t::commodities_report(xact_handler_ptr handler) +void report_t::commodities_report(post_handler_ptr handler) { - xacts_commodities_iterator walker(*session.journal.get()); - pass_down_xacts(chain_xact_handlers(*this, handler), walker); - session.clean_xacts(); + posts_commodities_iterator walker(*session.journal.get()); + pass_down_posts(chain_post_handlers(*this, handler), walker); + session.clean_posts(); } value_t report_t::fn_amount_expr(call_scope_t& scope) @@ -286,10 +286,10 @@ value_t report_t::fn_ansify_if(call_scope_t& scope) } namespace { - template <class Type = xact_t, - class handler_ptr = xact_handler_ptr, + template <class Type = post_t, + class handler_ptr = post_handler_ptr, void (report_t::*report_method)(handler_ptr) = - &report_t::xacts_report> + &report_t::posts_report> class reporter { shared_ptr<item_handler<Type> > handler; @@ -516,7 +516,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(set_price_); else OPT(sort_); else OPT(sort_all_); - else OPT(sort_entries_); + else OPT(sort_xacts_); else OPT_(subtotal); else OPT(start_of_week_); break; @@ -576,7 +576,7 @@ expr_t::ptr_op_t report_t::lookup(const string& name) if (is_eq(q, "csv")) return WRAP_FUNCTOR (reporter<> - (new format_xacts(*this, report_format(HANDLER(csv_format_))), + (new format_posts(*this, report_format(HANDLER(csv_format_))), *this)); break; @@ -584,30 +584,30 @@ expr_t::ptr_op_t report_t::lookup(const string& name) if (is_eq(q, "equity")) return WRAP_FUNCTOR (reporter<> - (new format_xacts(*this, report_format(HANDLER(print_format_))), + (new format_posts(*this, report_format(HANDLER(print_format_))), *this)); - else if (is_eq(q, "entry")) - return WRAP_FUNCTOR(entry_command); + else if (is_eq(q, "xact") || is_eq(q, "entry")) + return WRAP_FUNCTOR(xact_command); else if (is_eq(q, "emacs")) return WRAP_FUNCTOR - (reporter<>(new format_emacs_xacts(output_stream), *this)); + (reporter<>(new format_emacs_posts(output_stream), *this)); break; case 'p': if (*(q + 1) == '\0' || is_eq(q, "print")) return WRAP_FUNCTOR (reporter<> - (new format_xacts(*this, report_format(HANDLER(print_format_)), + (new format_posts(*this, report_format(HANDLER(print_format_)), HANDLED(raw)), *this)); else if (is_eq(q, "prices")) return expr_t::op_t::wrap_functor - (reporter<xact_t, xact_handler_ptr, &report_t::commodities_report> - (new format_xacts(*this, report_format(HANDLER(prices_format_))), + (reporter<post_t, post_handler_ptr, &report_t::commodities_report> + (new format_posts(*this, report_format(HANDLER(prices_format_))), *this)); else if (is_eq(q, "pricesdb")) return expr_t::op_t::wrap_functor - (reporter<xact_t, xact_handler_ptr, &report_t::commodities_report> - (new format_xacts(*this, report_format(HANDLER(pricesdb_format_))), + (reporter<post_t, post_handler_ptr, &report_t::commodities_report> + (new format_posts(*this, report_format(HANDLER(pricesdb_format_))), *this)); break; @@ -615,7 +615,7 @@ expr_t::ptr_op_t report_t::lookup(const string& name) if (*(q + 1) == '\0' || is_eq(q, "reg") || is_eq(q, "register")) return WRAP_FUNCTOR (reporter<> - (new format_xacts(*this, report_format(HANDLER(register_format_))), + (new format_posts(*this, report_format(HANDLER(register_format_))), *this)); else if (is_eq(q, "reload")) return MAKE_FUNCTOR(report_t::reload_command); @@ -700,6 +700,8 @@ expr_t::ptr_op_t report_t::lookup(const string& name) break; } } + else if (is_eq(p, "post")) + return MAKE_FUNCTOR(report_t::fn_false); break; case 'q': @@ -727,11 +729,6 @@ expr_t::ptr_op_t report_t::lookup(const string& name) else if (is_eq(p, "total_expr")) return MAKE_FUNCTOR(report_t::fn_total_expr); break; - - case 'x': - if (is_eq(p, "xact")) - return MAKE_FUNCTOR(report_t::fn_false); - break; } // Check if they are trying to access an option's setting or value. diff --git a/src/report.h b/src/report.h index 4f53e8ec..8fd28ff9 100644 --- a/src/report.h +++ b/src/report.h @@ -63,10 +63,10 @@ namespace ledger { // // 3. Mode of the report. Currently there are four modes: // -// a. Transaction or commodity iteration. In this mode, all the journal's -// entries, the transactions of a specific entry, or all the journal's +// a. Posting or commodity iteration. In this mode, all the journal's +// xacts, the postings of a specific xact, or all the journal's // commodities are walked. In the first two cases, it's the underlying -// transactions which are passed to #2; in the second case, each +// postings which are passed to #2; in the second case, each // commodity is passed to #2. // // b. Account iteration. This employs step 'a', but add a prologue and @@ -79,7 +79,7 @@ namespace ledger { // // c. Write journal. In this mode, a single function is called that output // the journal object as a textual file. #2 is used to print out each -// transaction in the journal. +// posting in the journal. // // d. Dump binary file. This is just like 'c', except that it dumps out a // binary file and #2 is completely ignored. @@ -87,8 +87,8 @@ namespace ledger { // 4. For 'a' and 'b' in #3, there is a different iteration function called, // depending on whether we're iterating: // -// a. The transactions of an entry: walk_transactions. -// b. The entries of a journal: walk_entries. +// a. The postings of an xact: walk_postings. +// b. The xacts of a journal: walk_xacts. // c. The commodities of a journal: walk_commodities. // // 5. Finally, for the 'a' and 'b' reporting modes, there is a variant which @@ -121,10 +121,10 @@ public: output_stream.close(); } - void xacts_report(xact_handler_ptr handler); - void entry_report(xact_handler_ptr handler, entry_t& entry); + void posts_report(post_handler_ptr handler); + void xact_report(post_handler_ptr handler, xact_t& xact); void accounts_report(acct_handler_ptr handler); - void commodities_report(xact_handler_ptr handler); + void commodities_report(post_handler_ptr handler); void sum_all_accounts(); @@ -277,8 +277,8 @@ public: OPTION_(report_t, collapse, DO() { // -n // Make sure that balance reports are collapsed too, but only apply it - // to account entries - parent->HANDLER(display_).on("xact|depth<=1"); + // to account xacts + parent->HANDLER(display_).on("post|depth<=1"); }); OPTION_(report_t, collapse_if_zero, DO() { @@ -292,8 +292,8 @@ public: "%(quoted(payee))," "%(quoted(account))," "%(quoted(scrub(display_amount)))," - "%(quoted((cleared or entry.cleared) ?" - " \"*\" : ((pending or entry.pending) ? \"!\" : \"\")))," + "%(quoted((cleared or xact.cleared) ?" + " \"*\" : ((pending or xact.pending) ? \"!\" : \"\")))," "%(quoted(code))," "%(quoted(join(note)))\n"); }); @@ -390,7 +390,7 @@ public: OPTION_(report_t, gain, DO() { // -G parent->HANDLER(revalued).on_only(); parent->HANDLER(amount_).set_expr("(amount, cost)"); - // Since we are displaying the amounts of revalued transactions, they + // Since we are displaying the amounts of revalued postings, they // will end up being composite totals, and hence a pair of pairs. parent->HANDLER(display_amount_) .set_expr("is_seq(get_at(amount_expr, 0)) ?" @@ -499,14 +499,14 @@ public: }); OPTION__(report_t, print_format_, CTOR(report_t, print_format_) { - on("%(format_date(entry.date, \"%Y/%m/%d\"))" - "%(entry.cleared ? \" *\" : (entry.pending ? \" !\" : \"\"))" - "%(code ? \" (\" + code + \")\" : \"\") %(payee)%(entry.comment | \"\")\n" - " %(entry.uncleared ? (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")" + on("%(format_date(xact.date, \"%Y/%m/%d\"))" + "%(xact.cleared ? \" *\" : (xact.pending ? \" !\" : \"\"))" + "%(code ? \" (\" + code + \")\" : \"\") %(payee)%(xact.comment | \"\")\n" + " %(xact.uncleared ? (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")" "%-34(account)" " %12(calculated ? \"\" : justify(scrub(amount), 12, -1, true))" "%(comment | \"\")\n%/" - " %(entry.uncleared ? (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")" + " %(xact.uncleared ? (cleared ? \"* \" : (pending ? \"! \" : \"\")) : \"\")" "%-34(account)" " %12(calculated ? \"\" : justify(scrub(amount), 12, -1, true))" "%(comment | \"\")\n%/\n"); @@ -574,16 +574,16 @@ public: OPTION_(report_t, sort_, DO_(args) { // -S on_with(args[0]); - parent->HANDLER(sort_entries_).off(); + parent->HANDLER(sort_xacts_).off(); parent->HANDLER(sort_all_).off(); }); OPTION_(report_t, sort_all_, DO_(args) { parent->HANDLER(sort_).on_with(args[0]); - parent->HANDLER(sort_entries_).off(); + parent->HANDLER(sort_xacts_).off(); }); - OPTION_(report_t, sort_entries_, DO_(args) { + OPTION_(report_t, sort_xacts_, DO_(args) { parent->HANDLER(sort_).on_with(args[0]); parent->HANDLER(sort_all_).off(); }); diff --git a/src/session.cc b/src/session.cc index 54fd8e4e..6fa07664 100644 --- a/src/session.cc +++ b/src/session.cc @@ -105,7 +105,7 @@ std::size_t session_t::read_data(const string& master_account) if (HANDLER(file_).data_files.empty()) throw_(parse_error, "No journal file was specified (please use -f)"); - std::size_t entry_count = 0; + std::size_t xact_count = 0; account_t * acct = journal->master; if (! master_account.empty()) @@ -114,7 +114,7 @@ std::size_t session_t::read_data(const string& master_account) if (HANDLED(price_db_)) { path price_db_path = resolve_path(HANDLER(price_db_).str()); if (exists(price_db_path) && read_journal(price_db_path) > 0) - throw_(parse_error, "Entries not allowed in price history file"); + throw_(parse_error, "Transactions not allowed in price history file"); } foreach (const path& pathname, HANDLER(file_).data_files) { @@ -135,10 +135,10 @@ std::size_t session_t::read_data(const string& master_account) std::istringstream buf_in(buffer.str()); - entry_count += read_journal(buf_in, "/dev/stdin", acct); + xact_count += read_journal(buf_in, "/dev/stdin", acct); } else if (exists(filename)) { - entry_count += read_journal(filename, acct); + xact_count += read_journal(filename, acct); } else { throw_(parse_error, "Could not read journal file '" << filename << "'"); @@ -147,7 +147,7 @@ std::size_t session_t::read_data(const string& master_account) VERIFY(journal->valid()); - return entry_count; + return xact_count; } void session_t::read_journal_files() @@ -160,12 +160,12 @@ void session_t::read_journal_files() std::size_t count = read_data(master_account); if (count == 0) - throw_(parse_error, "Failed to locate any journal entries; " + throw_(parse_error, "Failed to locate any transactions; " "did you specify a valid file with -f?"); INFO_FINISH(journal); - INFO("Found " << count << " entries"); + INFO("Found " << count << " transactions"); } void session_t::close_journal_files() @@ -181,16 +181,16 @@ void session_t::close_journal_files() journal.reset(new journal_t(master.get())); } -void session_t::clean_xacts() +void session_t::clean_posts() { - journal_xacts_iterator walker(*journal.get()); - pass_down_xacts(xact_handler_ptr(new clear_xact_xdata), walker); + journal_posts_iterator walker(*journal.get()); + pass_down_posts(post_handler_ptr(new clear_post_xdata), walker); } -void session_t::clean_xacts(entry_t& entry) +void session_t::clean_posts(xact_t& xact) { - entry_xacts_iterator walker(entry); - pass_down_xacts(xact_handler_ptr(new clear_xact_xdata), walker); + xact_posts_iterator walker(xact); + pass_down_posts(post_handler_ptr(new clear_post_xdata), walker); } void session_t::clean_accounts() diff --git a/src/session.h b/src/session.h index 280f8c3e..37c694fa 100644 --- a/src/session.h +++ b/src/session.h @@ -90,11 +90,11 @@ public: void read_journal_files(); void close_journal_files(); - void clean_xacts(); - void clean_xacts(entry_t& entry); + void clean_posts(); + void clean_posts(xact_t& xact); void clean_accounts(); void clean_all() { - clean_xacts(); + clean_posts(); clean_accounts(); } diff --git a/src/textual.cc b/src/textual.cc index 6803c78a..d53b4670 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -68,7 +68,7 @@ namespace { std::size_t count; std::size_t errors; - scoped_ptr<auto_entry_finalizer_t> auto_entry_finalizer; + scoped_ptr<auto_xact_finalizer_t> auto_xact_finalizer; instance_t(std::list<account_t *>& _account_stack, #if defined(TIMELOG_SUPPORT) @@ -100,13 +100,13 @@ namespace { void default_commodity_directive(char * line); void default_account_directive(char * line); void price_conversion_directive(char * line); - void price_entry_directive(char * line); + void price_xact_directive(char * line); void nomarket_directive(char * line); void year_directive(char * line); void option_directive(char * line); - void automated_entry_directive(char * line); - void period_entry_directive(char * line); - void entry_directive(char * line, std::streamsize len); + void automated_xact_directive(char * line); + void period_xact_directive(char * line); + void xact_directive(char * line, std::streamsize len); void include_directive(char * line); void account_directive(char * line); void end_directive(char * line); @@ -114,16 +114,16 @@ namespace { void define_directive(char * line); void general_directive(char * line); - xact_t * parse_xact(char * line, + post_t * parse_post(char * line, std::streamsize len, account_t * account, - entry_t * entry, + xact_t * xact, bool honor_strict = true); - bool parse_xacts(account_t * account, - entry_base_t& entry); + bool parse_posts(account_t * account, + xact_base_t& xact); - entry_t * parse_entry(char * line, + xact_t * parse_xact(char * line, std::streamsize len, account_t * account); @@ -133,7 +133,7 @@ namespace { void parse_amount_expr(scope_t& session_scope, std::istream& in, amount_t& amount, - xact_t * xact, + post_t * post, uint_least8_t flags = 0) { expr_t expr(in, flags | static_cast<uint_least8_t>(expr_t::PARSE_PARTIAL)); @@ -150,14 +150,14 @@ namespace { #endif if (expr) { - bind_scope_t bound_scope(session_scope, *xact); + bind_scope_t bound_scope(session_scope, *post); value_t result(expr.calc(bound_scope)); if (! result.is_amount()) - throw_(parse_error, "Transactions may only specify simple amounts"); + throw_(parse_error, "Postings may only specify simple amounts"); amount = result.as_amount(); - DEBUG("textual.parse", "The transaction amount is " << amount); + DEBUG("textual.parse", "The posting amount is " << amount); } } } @@ -199,8 +199,8 @@ instance_t::~instance_t() account_stack.pop_front(); - if (auto_entry_finalizer.get()) - journal.remove_entry_finalizer(auto_entry_finalizer.get()); + if (auto_xact_finalizer.get()) + journal.remove_xact_finalizer(auto_xact_finalizer.get()); } void instance_t::parse() @@ -331,13 +331,13 @@ void instance_t::read_next_directive() case '7': case '8': case '9': - entry_directive(line, len); + xact_directive(line, len); break; - case '=': // automated entry - automated_entry_directive(line); + case '=': // automated xact + automated_xact_directive(line); break; - case '~': // period entry - period_entry_directive(line); + case '~': // period xact + period_xact_directive(line); break; #if defined(TIMELOG_SUPPORT) @@ -360,20 +360,20 @@ void instance_t::read_next_directive() break; #endif // TIMELOG_SUPPORT - case 'A': // a default account for unbalanced xacts + case 'A': // a default account for unbalanced posts default_account_directive(line); break; case 'C': // a set of conversions price_conversion_directive(line); break; - case 'D': // a default commodity for "entry" + case 'D': // a default commodity for "xact" default_commodity_directive(line); break; case 'N': // don't download prices nomarket_directive(line); break; - case 'P': // a pricing entry - price_entry_directive(line); + case 'P': // a pricing xact + price_xact_directive(line); break; case 'Y': // set the current year year_directive(line); @@ -465,7 +465,7 @@ namespace { } } -void instance_t::price_entry_directive(char * line) +void instance_t::price_xact_directive(char * line) { char * date_field_ptr = skip_ws(line + 1); char * time_field_ptr = next_element(date_field_ptr); @@ -526,22 +526,22 @@ void instance_t::option_directive(char * line) process_option(line + 2, session_scope, p, line); } -void instance_t::automated_entry_directive(char * line) +void instance_t::automated_xact_directive(char * line) { - if (! auto_entry_finalizer.get()) { - auto_entry_finalizer.reset(new auto_entry_finalizer_t(&journal)); - journal.add_entry_finalizer(auto_entry_finalizer.get()); + if (! auto_xact_finalizer.get()) { + auto_xact_finalizer.reset(new auto_xact_finalizer_t(&journal)); + journal.add_xact_finalizer(auto_xact_finalizer.get()); } istream_pos_type pos = curr_pos; std::size_t lnum = linenum; - std::auto_ptr<auto_entry_t> ae - (new auto_entry_t(item_predicate(skip_ws(line + 1), + std::auto_ptr<auto_xact_t> ae + (new auto_xact_t(item_predicate(skip_ws(line + 1), keep_details_t(true, true, true)))); - if (parse_xacts(account_stack.front(), *ae.get())) { - journal.auto_entries.push_back(ae.get()); + if (parse_posts(account_stack.front(), *ae.get())) { + journal.auto_xacts.push_back(ae.get()); ae->pathname = pathname; ae->beg_pos = pos; @@ -553,20 +553,20 @@ void instance_t::automated_entry_directive(char * line) } } -void instance_t::period_entry_directive(char * line) +void instance_t::period_xact_directive(char * line) { - std::auto_ptr<period_entry_t> pe(new period_entry_t(skip_ws(line + 1))); + std::auto_ptr<period_xact_t> pe(new period_xact_t(skip_ws(line + 1))); if (! pe->period) throw_(parse_error, "Parsing time period '" << line << "'"); istream_pos_type pos = curr_pos; std::size_t lnum = linenum; - if (parse_xacts(account_stack.front(), *pe.get())) { + if (parse_posts(account_stack.front(), *pe.get())) { if (pe->finalize()) { - extend_entry_base(&journal, *pe.get(), true); + extend_xact_base(&journal, *pe.get(), true); - journal.period_entries.push_back(pe.get()); + journal.period_xacts.push_back(pe.get()); pe->pathname = pathname; pe->beg_pos = pos; @@ -576,30 +576,30 @@ void instance_t::period_entry_directive(char * line) pe.release(); } else { - throw parse_error("Period entry failed to balance"); + throw parse_error("Period transaction failed to balance"); } } } -void instance_t::entry_directive(char * line, std::streamsize len) +void instance_t::xact_directive(char * line, std::streamsize len) { - TRACE_START(entries, 1, "Time spent handling entries:"); + TRACE_START(xacts, 1, "Time spent handling transactions:"); - if (entry_t * entry = parse_entry(line, len, account_stack.front())) { - std::auto_ptr<entry_t> manager(entry); + if (xact_t * xact = parse_xact(line, len, account_stack.front())) { + std::auto_ptr<xact_t> manager(xact); - if (journal.add_entry(entry)) { + if (journal.add_xact(xact)) { manager.release(); // it's owned by the journal now count++; } - // It's perfectly valid for the journal to reject the entry, which it will - // do if the entry has no substantive effect (for example, a checking - // entry, all of whose transactions have null amounts). + // It's perfectly valid for the journal to reject the xact, which it will + // do if the xact has no substantive effect (for example, a checking + // xact, all of whose postings have null amounts). } else { - throw parse_error("Failed to parse entry"); + throw parse_error("Failed to parse transaction"); } - TRACE_STOP(entries, 1); + TRACE_STOP(xacts, 1); } void instance_t::include_directive(char * line) @@ -660,7 +660,7 @@ void instance_t::alias_directive(char * line) // Once we have an alias name (b) and the target account // name (e), add a reference to the account in the - // `account_aliases' map, which is used by the xact + // `account_aliases' map, which is used by the post // parser to resolve alias references. account_t * acct = account_stack.front()->find_account(e); std::pair<accounts_map::iterator, bool> result @@ -730,20 +730,20 @@ void instance_t::general_directive(char * line) } } -xact_t * instance_t::parse_xact(char * line, +post_t * instance_t::parse_post(char * line, std::streamsize len, account_t * account, - entry_t * entry, + xact_t * xact, bool honor_strict) { - TRACE_START(xact_details, 1, "Time spent parsing transactions:"); + TRACE_START(post_details, 1, "Time spent parsing postings:"); - std::auto_ptr<xact_t> xact(new xact_t); + std::auto_ptr<post_t> post(new post_t); - xact->entry = entry; // this could be NULL - xact->pathname = pathname; - xact->beg_pos = line_beg_pos; - xact->beg_line = linenum; + post->xact = xact; // this could be NULL + post->pathname = pathname; + post->beg_pos = line_beg_pos; + post->beg_line = linenum; char buf[MAX_LINE + 1]; std::strcpy(buf, line); @@ -760,42 +760,42 @@ xact_t * instance_t::parse_xact(char * line, switch (*p) { case '*': - xact->set_state(item_t::CLEARED); + post->set_state(item_t::CLEARED); p = skip_ws(p + 1); DEBUG("textual.parse", "line " << linenum << ": " << "Parsed the CLEARED flag"); break; case '!': - xact->set_state(item_t::PENDING); + post->set_state(item_t::PENDING); p = skip_ws(p + 1); DEBUG("textual.parse", "line " << linenum << ": " << "Parsed the PENDING flag"); break; } - if (entry && - ((entry->_state == item_t::CLEARED && xact->_state != item_t::CLEARED) || - (entry->_state == item_t::PENDING && xact->_state == item_t::UNCLEARED))) - xact->set_state(entry->_state); + if (xact && + ((xact->_state == item_t::CLEARED && post->_state != item_t::CLEARED) || + (xact->_state == item_t::PENDING && post->_state == item_t::UNCLEARED))) + post->set_state(xact->_state); // Parse the account name if (! *p) - throw parse_error("Transaction has no account"); + throw parse_error("Posting has no account"); char * next = next_element(p, true); char * e = p + std::strlen(p); if ((*p == '[' && *(e - 1) == ']') || (*p == '(' && *(e - 1) == ')')) { - xact->add_flags(XACT_VIRTUAL); + post->add_flags(POST_VIRTUAL); DEBUG("textual.parse", "line " << linenum << ": " << "Parsed a virtual account name"); if (*p == '[') { - xact->add_flags(XACT_MUST_BALANCE); + post->add_flags(POST_MUST_BALANCE); DEBUG("textual.parse", "line " << linenum << ": " - << "Transaction must balance"); + << "Posting must balance"); } p++; e--; } @@ -807,17 +807,17 @@ xact_t * instance_t::parse_xact(char * line, if (account_aliases.size() > 0) { accounts_map::const_iterator i = account_aliases.find(name); if (i != account_aliases.end()) - xact->account = (*i).second; + post->account = (*i).second; } - if (! xact->account) - xact->account = account->find_account(name); + if (! post->account) + post->account = account->find_account(name); - if (honor_strict && strict && ! xact->account->known) { - if (xact->_state == item_t::UNCLEARED) + if (honor_strict && strict && ! post->account->known) { + if (post->_state == item_t::UNCLEARED) std::cerr << "Warning: \"" << pathname << "\", line " << linenum - << ": Unknown account '" << xact->account->fullname() + << ": Unknown account '" << post->account->fullname() << "'" << std::endl; - xact->account->known = true; + post->account->known = true; } // Parse the optional amount @@ -831,31 +831,31 @@ xact_t * instance_t::parse_xact(char * line, ptristream stream(next, len - beg); if (*next != '(') // indicates a value expression - xact->amount.parse(stream, amount_t::PARSE_NO_REDUCE); + post->amount.parse(stream, amount_t::PARSE_NO_REDUCE); else - parse_amount_expr(session_scope, stream, xact->amount, xact.get(), + parse_amount_expr(session_scope, stream, post->amount, post.get(), static_cast<uint_least8_t>(expr_t::PARSE_NO_REDUCE) | static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN)); - if (! xact->amount.is_null() && honor_strict && strict && - xact->amount.has_commodity() && - ! xact->amount.commodity().has_flags(COMMODITY_KNOWN)) { - if (xact->_state == item_t::UNCLEARED) + if (! post->amount.is_null() && honor_strict && strict && + post->amount.has_commodity() && + ! post->amount.commodity().has_flags(COMMODITY_KNOWN)) { + if (post->_state == item_t::UNCLEARED) std::cerr << "Warning: \"" << pathname << "\", line " << linenum - << ": Unknown commodity '" << xact->amount.commodity() + << ": Unknown commodity '" << post->amount.commodity() << "'" << std::endl; - xact->amount.commodity().add_flags(COMMODITY_KNOWN); + post->amount.commodity().add_flags(COMMODITY_KNOWN); } #if 0 // jww (2009-02-12): This isn't quite working yet; it causes cost computes // to skyrocket, since the per-unit price isn't also being reduced by the // same factor. - if (! xact->amount.is_null()) - xact->amount.in_place_reduce(); + if (! post->amount.is_null()) + post->amount.in_place_reduce(); #endif DEBUG("textual.parse", "line " << linenum << ": " - << "xact amount = " << xact->amount); + << "post amount = " << post->amount); if (stream.eof()) { next = NULL; @@ -880,28 +880,28 @@ xact_t * instance_t::parse_xact(char * line, p = skip_ws(next); if (*p) { - xact->cost = amount_t(); + post->cost = amount_t(); beg = p - line; ptristream cstream(p, len - beg); if (*p != '(') // indicates a value expression - xact->cost->parse(cstream, amount_t::PARSE_NO_MIGRATE); + post->cost->parse(cstream, amount_t::PARSE_NO_MIGRATE); else - parse_amount_expr(session_scope, cstream, *xact->cost, xact.get(), + parse_amount_expr(session_scope, cstream, *post->cost, post.get(), static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE) | static_cast<uint_least8_t>(expr_t::PARSE_NO_ASSIGN)); - if (xact->cost->sign() < 0) - throw parse_error("A transaction's cost may not be negative"); + if (post->cost->sign() < 0) + throw parse_error("A posting's cost may not be negative"); if (per_unit) - *xact->cost *= xact->amount; + *post->cost *= post->amount; DEBUG("textual.parse", "line " << linenum << ": " - << "Total cost is " << *xact->cost); + << "Total cost is " << *post->cost); DEBUG("textual.parse", "line " << linenum << ": " - << "Annotated amount is " << xact->amount); + << "Annotated amount is " << post->amount); if (cstream.eof()) next = NULL; @@ -916,7 +916,7 @@ xact_t * instance_t::parse_xact(char * line, // Parse the optional balance assignment - if (entry && next && *next == '=') { + if (xact && next && *next == '=') { DEBUG("textual.parse", "line " << linenum << ": " << "Found a balance assignment indicator"); @@ -924,30 +924,30 @@ xact_t * instance_t::parse_xact(char * line, p = skip_ws(next); if (*p) { - xact->assigned_amount = amount_t(); + post->assigned_amount = amount_t(); beg = p - line; ptristream stream(p, len - beg); if (*p != '(') // indicates a value expression - xact->assigned_amount->parse(stream, amount_t::PARSE_NO_MIGRATE); + post->assigned_amount->parse(stream, amount_t::PARSE_NO_MIGRATE); else - parse_amount_expr(session_scope, stream, *xact->assigned_amount, xact.get(), + parse_amount_expr(session_scope, stream, *post->assigned_amount, post.get(), static_cast<uint_least8_t>(expr_t::PARSE_NO_MIGRATE)); - if (xact->assigned_amount->is_null()) + if (post->assigned_amount->is_null()) throw parse_error("An assigned balance must evaluate to a constant value"); DEBUG("textual.parse", "line " << linenum << ": " - << "XACT assign: parsed amt = " << *xact->assigned_amount); + << "POST assign: parsed amt = " << *post->assigned_amount); - account_t::xdata_t& xdata(xact->account->xdata()); - amount_t& amt(*xact->assigned_amount); + account_t::xdata_t& xdata(post->account->xdata()); + amount_t& amt(*post->assigned_amount); - DEBUG("xact.assign", "line " << linenum << ": " + DEBUG("post.assign", "line " << linenum << ": " "account balance = " << xdata.value); - DEBUG("xact.assign", "line " << linenum << ": " - "xact amount = " << amt); + DEBUG("post.assign", "line " << linenum << ": " + "post amount = " << amt); amount_t diff; @@ -969,26 +969,26 @@ xact_t * instance_t::parse_xact(char * line, break; } - DEBUG("xact.assign", "line " << linenum << ": " + DEBUG("post.assign", "line " << linenum << ": " << "diff = " << diff); DEBUG("textual.parse", "line " << linenum << ": " - << "XACT assign: diff = " << diff); + << "POST assign: diff = " << diff); if (! diff.is_zero()) { - if (! xact->amount.is_null()) { - diff -= xact->amount; + if (! post->amount.is_null()) { + diff -= post->amount; if (! diff.is_zero()) { - xact_t * temp = new xact_t(xact->account, diff, - ITEM_GENERATED | XACT_CALCULATED); - entry->add_xact(temp); + post_t * temp = new post_t(post->account, diff, + ITEM_GENERATED | POST_CALCULATED); + xact->add_post(temp); DEBUG("textual.parse", "line " << linenum << ": " - << "Created balancing transaction"); + << "Created balancing posting"); } } else { - xact->amount = diff; + post->amount = diff; DEBUG("textual.parse", "line " << linenum << ": " - << "Overwrite null transaction"); + << "Overwrite null posting"); } } @@ -1004,10 +1004,10 @@ xact_t * instance_t::parse_xact(char * line, // Parse the optional note if (next && *next == ';') { - xact->append_note(++next, current_year); + post->append_note(++next, current_year); next = line + len; DEBUG("textual.parse", "line " << linenum << ": " - << "Parsed a transaction note"); + << "Parsed a posting note"); } // There should be nothing more to read @@ -1016,25 +1016,25 @@ xact_t * instance_t::parse_xact(char * line, throw_(parse_error, "Unexpected char '" << *next << "' (Note: inline math requires parentheses)"); - xact->end_pos = curr_pos; - xact->end_line = linenum; + post->end_pos = curr_pos; + post->end_line = linenum; - TRACE_STOP(xact_details, 1); + TRACE_STOP(post_details, 1); - return xact.release(); + return post.release(); } catch (const std::exception& err) { - add_error_context("While parsing transaction:"); + add_error_context("While parsing posting:"); add_error_context(line_context(buf, beg, len)); throw; } } -bool instance_t::parse_xacts(account_t * account, - entry_base_t& entry) +bool instance_t::parse_posts(account_t * account, + xact_base_t& xact) { - TRACE_START(entry_xacts, 1, "Time spent parsing transactions:"); + TRACE_START(xact_posts, 1, "Time spent parsing postings:"); bool added = false; @@ -1043,24 +1043,24 @@ bool instance_t::parse_xacts(account_t * account, std::streamsize len = read_line(line); assert(len > 0); - if (xact_t * xact = parse_xact(line, len, account, NULL, false)) { - entry.add_xact(xact); + if (post_t * post = parse_post(line, len, account, NULL, false)) { + xact.add_post(post); added = true; } } - TRACE_STOP(entry_xacts, 1); + TRACE_STOP(xact_posts, 1); return added; } -entry_t * instance_t::parse_entry(char * line, +xact_t * instance_t::parse_xact(char * line, std::streamsize len, account_t * account) { - TRACE_START(entry_text, 1, "Time spent parsing entry text:"); + TRACE_START(xact_text, 1, "Time spent parsing transaction text:"); - std::auto_ptr<entry_t> curr(new entry_t); + std::auto_ptr<xact_t> curr(new xact_t); curr->pathname = pathname; curr->beg_pos = line_beg_pos; @@ -1110,18 +1110,18 @@ entry_t * instance_t::parse_entry(char * line, curr->payee = "<Unspecified payee>"; } - // Parse the entry note + // Parse the xact note if (next && *next == ';') curr->append_note(next, current_year); - TRACE_STOP(entry_text, 1); + TRACE_STOP(xact_text, 1); - // Parse all of the xacts associated with this entry + // Parse all of the posts associated with this xact - TRACE_START(entry_details, 1, "Time spent parsing entry details:"); + TRACE_START(xact_details, 1, "Time spent parsing transaction details:"); - xact_t * last_xact = NULL; + post_t * last_post = NULL; while (peek_whitespace_line()) { len = read_line(line); @@ -1132,8 +1132,8 @@ entry_t * instance_t::parse_entry(char * line, if (*p == ';') { item_t * item; - if (last_xact) - item = last_xact; + if (last_post) + item = last_post; else item = curr.get(); @@ -1142,17 +1142,17 @@ entry_t * instance_t::parse_entry(char * line, item->end_pos = curr_pos; item->end_line++; } - else if (xact_t * xact = parse_xact(p, len - (p - line), account, + else if (post_t * post = parse_post(p, len - (p - line), account, curr.get())) { - curr->add_xact(xact); - last_xact = xact; + curr->add_post(post); + last_post = post; } } curr->end_pos = curr_pos; curr->end_line = linenum; - TRACE_STOP(entry_details, 1); + TRACE_STOP(xact_details, 1); return curr.release(); } @@ -1186,10 +1186,10 @@ std::size_t journal_t::parse(std::istream& in, TRACE_STOP(parsing_total, 1); // These tracers were started in textual.cc - TRACE_FINISH(entry_text, 1); - TRACE_FINISH(entry_details, 1); - TRACE_FINISH(entry_xacts, 1); - TRACE_FINISH(entries, 1); + TRACE_FINISH(xact_text, 1); + TRACE_FINISH(xact_details, 1); + TRACE_FINISH(xact_posts, 1); + TRACE_FINISH(xacts, 1); TRACE_FINISH(instance_parse, 1); // report per-instance timers TRACE_FINISH(parsing_total, 1); diff --git a/src/timelog.cc b/src/timelog.cc index d52bccb0..6e3a8457 100644 --- a/src/timelog.cc +++ b/src/timelog.cc @@ -34,19 +34,19 @@ namespace ledger { namespace { - void clock_out_from_timelog(std::list<time_entry_t>& time_entries, + void clock_out_from_timelog(std::list<time_xact_t>& time_xacts, const datetime_t& when, account_t * account, const char * desc, journal_t& journal) { - time_entry_t event; + time_xact_t event; - if (time_entries.size() == 1) { - event = time_entries.back(); - time_entries.clear(); + if (time_xacts.size() == 1) { + event = time_xacts.back(); + time_xacts.clear(); } - else if (time_entries.empty()) { + else if (time_xacts.empty()) { throw parse_error("Timelog check-out event without a check-in"); } else if (! account) { @@ -56,13 +56,13 @@ namespace { else { bool found = false; - for (std::list<time_entry_t>::iterator i = time_entries.begin(); - i != time_entries.end(); + for (std::list<time_xact_t>::iterator i = time_xacts.begin(); + i != time_xacts.end(); i++) if (account == (*i).account) { event = *i; found = true; - time_entries.erase(i); + time_xacts.erase(i); break; } @@ -76,7 +76,7 @@ namespace { desc = NULL; } - std::auto_ptr<entry_t> curr(new entry_t); + std::auto_ptr<xact_t> curr(new xact_t); curr->_date = when.date(); curr->code = desc ? desc : ""; curr->payee = event.desc; @@ -91,12 +91,12 @@ namespace { amt.parse(buf); assert(amt.valid()); - xact_t * xact = new xact_t(event.account, amt, XACT_VIRTUAL); - xact->set_state(item_t::CLEARED); - curr->add_xact(xact); + post_t * post = new post_t(event.account, amt, POST_VIRTUAL); + post->set_state(item_t::CLEARED); + curr->add_post(post); - if (! journal.add_entry(curr.get())) - throw parse_error("Failed to record 'out' timelog entry"); + if (! journal.add_xact(curr.get())) + throw parse_error("Failed to record 'out' timelog transaction"); else curr.release(); } @@ -106,17 +106,17 @@ time_log_t::~time_log_t() { TRACE_DTOR(time_log_t); - if (! time_entries.empty()) { + if (! time_xacts.empty()) { std::list<account_t *> accounts; - foreach (time_entry_t& time_entry, time_entries) - accounts.push_back(time_entry.account); + foreach (time_xact_t& time_xact, time_xacts) + accounts.push_back(time_xact.account); foreach (account_t * account, accounts) - clock_out_from_timelog(time_entries, CURRENT_TIME(), account, NULL, + clock_out_from_timelog(time_xacts, CURRENT_TIME(), account, NULL, journal); - assert(time_entries.empty()); + assert(time_xacts.empty()); } } @@ -124,26 +124,26 @@ void time_log_t::clock_in(const datetime_t& checkin, account_t * account, const string& desc) { - time_entry_t event(checkin, account, desc); + time_xact_t event(checkin, account, desc); - if (! time_entries.empty()) { - foreach (time_entry_t& time_entry, time_entries) { - if (event.account == time_entry.account) + if (! time_xacts.empty()) { + foreach (time_xact_t& time_xact, time_xacts) { + if (event.account == time_xact.account) throw parse_error("Cannot double check-in to the same account"); } } - time_entries.push_back(event); + time_xacts.push_back(event); } void time_log_t::clock_out(const datetime_t& checkin, account_t * account, const string& desc) { - if (time_entries.empty()) + if (time_xacts.empty()) throw std::logic_error("Timelog check-out event without a check-in"); - clock_out_from_timelog(time_entries, checkin, account, desc.c_str(), + clock_out_from_timelog(time_xacts, checkin, account, desc.c_str(), journal); } diff --git a/src/timelog.h b/src/timelog.h index 9e69cd65..a704743c 100644 --- a/src/timelog.h +++ b/src/timelog.h @@ -55,29 +55,29 @@ namespace ledger { * * Long. */ -class time_entry_t +class time_xact_t { public: datetime_t checkin; account_t * account; string desc; - time_entry_t() : account(NULL) { - TRACE_CTOR(time_entry_t, ""); + time_xact_t() : account(NULL) { + TRACE_CTOR(time_xact_t, ""); } - time_entry_t(const datetime_t& _checkin, + time_xact_t(const datetime_t& _checkin, account_t * _account = NULL, const string& _desc = "") : checkin(_checkin), account(_account), desc(_desc) { - TRACE_CTOR(time_entry_t, "const datetime_t&, account_t *, const string&"); + TRACE_CTOR(time_xact_t, "const datetime_t&, account_t *, const string&"); } - time_entry_t(const time_entry_t& entry) - : checkin(entry.checkin), account(entry.account), - desc(entry.desc) { - TRACE_CTOR(time_entry_t, "copy"); + time_xact_t(const time_xact_t& xact) + : checkin(xact.checkin), account(xact.account), + desc(xact.desc) { + TRACE_CTOR(time_xact_t, "copy"); } - ~time_entry_t() throw() { - TRACE_DTOR(time_entry_t); + ~time_xact_t() throw() { + TRACE_DTOR(time_xact_t); } }; @@ -88,7 +88,7 @@ public: */ class time_log_t { - std::list<time_entry_t> time_entries; + std::list<time_xact_t> time_xacts; journal_t& journal; public: diff --git a/src/utils.cc b/src/utils.cc index 5f42eae5..70c6d5f8 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -529,7 +529,7 @@ struct __maybe_enable_debugging { /********************************************************************** * - * Timers (allows log entries to specify cumulative time spent) + * Timers (allows log xacts to specify cumulative time spent) */ #if defined(LOGGING_ON) && defined(TIMERS_ON) diff --git a/src/utils.h b/src/utils.h index 38fd2439..3da0a429 100644 --- a/src/utils.h +++ b/src/utils.h @@ -380,7 +380,7 @@ inline bool category_matches(const char * cat) { /** * @name Timers - * This allows log entries to specify cumulative time spent. + * This allows log xacts to specify cumulative time spent. */ /*@{*/ diff --git a/src/xact.cc b/src/xact.cc index 14464c6f..f62f8c09 100644 --- a/src/xact.cc +++ b/src/xact.cc @@ -32,190 +32,290 @@ #include "xact.h" #include "journal.h" #include "account.h" -#include "interactive.h" #include "format.h" namespace ledger { -bool xact_t::has_tag(const string& tag) const +xact_base_t::xact_base_t(const xact_base_t&) + : item_t(), journal(NULL) { - if (item_t::has_tag(tag)) - return true; - if (entry) - return entry->has_tag(tag); - return false; + TRACE_CTOR(xact_base_t, "copy"); } -bool xact_t::has_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask) const +xact_base_t::~xact_base_t() { - if (item_t::has_tag(tag_mask, value_mask)) - return true; - if (entry) - return entry->has_tag(tag_mask, value_mask); - return false; -} + TRACE_DTOR(xact_base_t); -optional<string> xact_t::get_tag(const string& tag) const -{ - if (optional<string> value = item_t::get_tag(tag)) - return value; - if (entry) - return entry->get_tag(tag); - return none; -} - -optional<string> xact_t::get_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask) const -{ - if (optional<string> value = item_t::get_tag(tag_mask, value_mask)) - return value; - if (entry) - return entry->get_tag(tag_mask, value_mask); - return none; + foreach (post_t * post, posts) { + // If the posting is a temporary, it will be destructed when the + // temporary is. + if (! post->has_flags(ITEM_TEMP)) + checked_delete(post); + } } -date_t xact_t::date() const +item_t::state_t xact_base_t::state() const { - if (xdata_ && is_valid(xdata_->date)) - return xdata_->date; - - if (item_t::use_effective_date) { - if (_date_eff) - return *_date_eff; - else if (entry && entry->_date_eff) - return *entry->_date_eff; - } + state_t result = CLEARED; - if (! _date) { - assert(entry); - return entry->date(); + foreach (post_t * post, posts) { + if (post->_state == UNCLEARED) + return UNCLEARED; + else if (post->_state == PENDING) + result = PENDING; } - return *_date; + return result; } -optional<date_t> xact_t::effective_date() const +void xact_base_t::add_post(post_t * post) { - optional<date_t> date = item_t::effective_date(); - if (! date && entry) - return entry->effective_date(); - return date; + posts.push_back(post); } -item_t::state_t xact_t::state() const +bool xact_base_t::remove_post(post_t * post) { - if (entry) { - state_t entry_state = entry->state(); - if ((_state == UNCLEARED && entry_state != UNCLEARED) || - (_state == PENDING && entry_state == CLEARED)) - return entry_state; - } - return _state; + posts.remove(post); + post->xact = NULL; + return true; } -namespace { - value_t get_this(xact_t& xact) { - return value_t(static_cast<scope_t *>(&xact)); +bool xact_base_t::finalize() +{ + // Scan through and compute the total balance for the xact. This is used + // for auto-calculating the value of xacts with no cost, and the per-unit + // price of unpriced commodities. + + value_t balance; + post_t * null_post = NULL; + + foreach (post_t * post, posts) { + if (post->must_balance()) { + amount_t& p(post->cost ? *post->cost : post->amount); + DEBUG("xact.finalize", "post must balance = " << p); + if (! p.is_null()) { + if (p.keep_precision()) { + // If the amount was a cost, it very likely has the "keep_precision" + // flag set, meaning commodity display precision is ignored when + // displaying the amount. We never want this set for the balance, + // so we must clear the flag in a temporary to avoid it propagating + // into the balance. + add_or_set_value(balance, p.rounded()); + } else { + add_or_set_value(balance, p); + } + } else { + if (null_post) + throw_(std::logic_error, + "Only one posting with null amount allowed per transaction"); + else + null_post = post; + } + } } + assert(balance.valid()); - value_t get_is_calculated(xact_t& xact) { - return xact.has_flags(XACT_CALCULATED); - } + DEBUG("xact.finalize", "initial balance = " << balance); - value_t get_virtual(xact_t& xact) { - return xact.has_flags(XACT_VIRTUAL); - } + // If there is only one post, balance against the default account if one has + // been set. - value_t get_real(xact_t& xact) { - return ! xact.has_flags(XACT_VIRTUAL); + if (journal && journal->basket && posts.size() == 1 && ! balance.is_null()) { + // jww (2008-07-24): Need to make the rest of the code aware of what to do + // when it sees a generated post. + null_post = new post_t(journal->basket, ITEM_GENERATED); + null_post->_state = (*posts.begin())->_state; + add_post(null_post); } - value_t get_actual(xact_t& xact) { - return ! xact.has_flags(XACT_AUTO); - } + if (null_post != NULL) { + // If one post has no value at all, its value will become the inverse of + // the rest. If multiple commodities are involved, multiple posts are + // generated to balance them all. + + if (balance.is_balance()) { + bool first = true; + const balance_t& bal(balance.as_balance()); + foreach (const balance_t::amounts_map::value_type& pair, bal.amounts) { + if (first) { + null_post->amount = pair.second.negated(); + first = false; + } else { + add_post(new post_t(null_post->account, pair.second.negated(), + ITEM_GENERATED)); + } + } + } + else if (balance.is_amount()) { + null_post->amount = balance.as_amount().negated(); + null_post->add_flags(POST_CALCULATED); + } + else if (! balance.is_null() && ! balance.is_realzero()) { + throw_(balance_error, "Transaction does not balance"); + } + balance = NULL_VALUE; - value_t get_entry(xact_t& xact) { - return value_t(static_cast<scope_t *>(xact.entry)); } + else if (balance.is_balance() && + balance.as_balance().amounts.size() == 2) { + // When an xact involves two different commodities (regardless of how + // many posts there are) determine the conversion ratio by dividing the + // total value of one commodity by the total value of the other. This + // establishes the per-unit cost for this post for both commodities. + + DEBUG("xact.finalize", "there were exactly two commodities"); + + bool saw_cost = false; + post_t * top_post = NULL; + + foreach (post_t * post, posts) { + if (! post->amount.is_null()) + if (post->amount.is_annotated()) + top_post = post; + else if (! top_post) + top_post = post; + + if (post->cost) { + saw_cost = true; + break; + } + } - value_t get_code(xact_t& xact) { - if (xact.entry->code) - return string_value(*xact.entry->code); - else - return string_value(empty_string); - } + if (! saw_cost && top_post) { + const balance_t& bal(balance.as_balance()); + + DEBUG("xact.finalize", "there were no costs, and a valid top_post"); + + balance_t::amounts_map::const_iterator a = bal.amounts.begin(); + + const amount_t * x = &(*a++).second; + const amount_t * y = &(*a++).second; + + if (x->commodity() != top_post->amount.commodity()) { + const amount_t * t = x; + x = y; + y = t; + } + + DEBUG("xact.finalize", "primary amount = " << *y); + DEBUG("xact.finalize", "secondary amount = " << *x); + + commodity_t& comm(x->commodity()); + amount_t per_unit_cost; + amount_t total_cost; + + foreach (post_t * post, posts) { + if (post != top_post && post->must_balance() && + ! post->amount.is_null() && + post->amount.is_annotated() && + post->amount.annotation().price) { + amount_t temp = *post->amount.annotation().price * post->amount; + if (total_cost.is_null()) { + total_cost = temp; + y = &total_cost; + } else { + total_cost += temp; + } + DEBUG("xact.finalize", "total_cost = " << total_cost); + } + } + per_unit_cost = (*y / *x).abs(); + + DEBUG("xact.finalize", "per_unit_cost = " << per_unit_cost); + + foreach (post_t * post, posts) { + const amount_t& amt(post->amount); + + if (post->must_balance() && amt.commodity() == comm) { + balance -= amt; + post->cost = per_unit_cost * amt; + balance += *post->cost; + + DEBUG("xact.finalize", "set post->cost to = " << *post->cost); + } + } + } - value_t get_payee(xact_t& xact) { - return string_value(xact.entry->payee); + DEBUG("xact.finalize", "resolved balance = " << balance); } - value_t get_amount(xact_t& xact) { - if (xact.has_xdata() && - xact.xdata().has_flags(XACT_EXT_COMPOUND)) { - return xact.xdata().value; - } else { - return xact.amount; - } - } + // Now that the post list has its final form, calculate the balance once + // more in terms of total cost, accounting for any possible gain/loss + // amounts. - value_t get_commodity(xact_t& xact) { - return string_value(xact.amount.commodity().symbol()); - } + foreach (post_t * post, posts) { + if (post->cost) { + if (post->amount.commodity() == post->cost->commodity()) + throw_(balance_error, "Posting's cost must be of a different commodity"); - value_t get_commodity_is_primary(xact_t& xact) { - return xact.amount.commodity().has_flags(COMMODITY_PRIMARY); - } + commodity_t::cost_breakdown_t breakdown = + commodity_t::exchange(post->amount, *post->cost, false, + datetime_t(date(), time_duration(0, 0, 0, 0))); - value_t get_cost(xact_t& xact) { - if (xact.has_xdata() && - xact.xdata().has_flags(XACT_EXT_COMPOUND)) { - return xact.xdata().value; - } else { - if (xact.cost) - return *xact.cost; + if (post->amount.is_annotated() && + breakdown.basis_cost.commodity() == + breakdown.final_cost.commodity()) + add_or_set_value(balance, (breakdown.basis_cost - + breakdown.final_cost).rounded()); else - return xact.amount; + post->amount = breakdown.amount; } } - value_t get_total(xact_t& xact) { - if (xact.xdata_ && ! xact.xdata_->total.is_null()) - return xact.xdata_->total; - else - return xact.amount; - } + DEBUG("xact.finalize", "final balance = " << balance); - value_t get_count(xact_t& xact) { - if (xact.xdata_) - return xact.xdata_->count; - else - return 1L; + if (! balance.is_null() && ! balance.is_zero()) { + add_error_context(item_context(*this, "While balancing transaction")); + add_error_context("Unbalanced remainder is:"); + add_error_context(value_context(balance)); + throw_(balance_error, "Transaction does not balance"); } - value_t get_account(call_scope_t& scope) - { - in_context_t<xact_t> env(scope, "&l"); + // Add the final calculated totals each to their related account - string name = env->reported_account()->fullname(); + if (dynamic_cast<xact_t *>(this)) { + bool all_null = true; + foreach (post_t * post, posts) { + if (! post->amount.is_null()) { + all_null = false; - if (env.has(0) && env.get<long>(0) > 2) - name = format_t::truncate(name, env.get<long>(0) - 2, true); + // jww (2008-08-09): For now, this feature only works for non-specific + // commodities. + add_or_set_value(post->account->xdata().value, post->amount); - if (env->has_flags(XACT_VIRTUAL)) { - if (env->must_balance()) - name = string("[") + name + "]"; - else - name = string("(") + name + ")"; + DEBUG("xact.finalize.totals", + "Total for " << post->account->fullname() << " + " + << post->amount << ": " << post->account->xdata().value); + } } - return string_value(name); + if (all_null) + return false; // ignore this xact completely } - value_t get_account_base(xact_t& xact) { - return string_value(xact.reported_account()->name); + return true; +} + +xact_t::xact_t(const xact_t& e) + : xact_base_t(e), code(e.code), payee(e.payee) +{ + TRACE_CTOR(xact_t, "copy"); +} + +void xact_t::add_post(post_t * post) +{ + post->xact = this; + xact_base_t::add_post(post); +} + +namespace { + value_t get_code(xact_t& xact) { + if (xact.code) + return string_value(*xact.code); + else + return string_value(empty_string); } - value_t get_account_depth(xact_t& xact) { - return long(xact.reported_account()->depth); + value_t get_payee(xact_t& xact) { + return string_value(xact.payee); } template <value_t (*Func)(xact_t&)> @@ -227,65 +327,14 @@ namespace { expr_t::ptr_op_t xact_t::lookup(const string& name) { switch (name[0]) { - case 'a': - if (name[1] == '\0' || name == "amount") - return WRAP_FUNCTOR(get_wrapper<&get_amount>); - else if (name == "account") - return WRAP_FUNCTOR(get_account); - else if (name == "account_base") - return WRAP_FUNCTOR(get_wrapper<&get_account_base>); - else if (name == "actual") - return WRAP_FUNCTOR(get_wrapper<&get_actual>); - break; - case 'c': if (name == "code") return WRAP_FUNCTOR(get_wrapper<&get_code>); - else if (name == "cost") - return WRAP_FUNCTOR(get_wrapper<&get_cost>); - else if (name == "count") - return WRAP_FUNCTOR(get_wrapper<&get_count>); - else if (name == "calculated") - return WRAP_FUNCTOR(get_wrapper<&get_is_calculated>); - else if (name == "commodity") - return WRAP_FUNCTOR(get_wrapper<&get_commodity>); - break; - - case 'd': - if (name == "depth") - return WRAP_FUNCTOR(get_wrapper<&get_account_depth>); - break; - - case 'e': - if (name == "entry") - return WRAP_FUNCTOR(get_wrapper<&get_entry>); - break; - - case 'r': - if (name == "real") - return WRAP_FUNCTOR(get_wrapper<&get_real>); break; case 'p': - if (name == "payee") + if (name[1] == '\0' || name == "payee") return WRAP_FUNCTOR(get_wrapper<&get_payee>); - else if (name == "primary") - return WRAP_FUNCTOR(get_wrapper<&get_commodity_is_primary>); - break; - - case 't': - if (name[1] == '\0' || name == "total") - return WRAP_FUNCTOR(get_wrapper<&get_total>); - break; - - case 'v': - if (name == "virtual") - return WRAP_FUNCTOR(get_wrapper<&get_virtual>); - break; - - case 'x': - if (name == "xact") - return WRAP_FUNCTOR(get_wrapper<&get_this>); break; } @@ -294,46 +343,85 @@ expr_t::ptr_op_t xact_t::lookup(const string& name) bool xact_t::valid() const { - if (! entry) { - DEBUG("ledger.validate", "xact_t: ! entry"); - return false; - } - - xacts_list::const_iterator i = - std::find(entry->xacts.begin(), - entry->xacts.end(), this); - if (i == entry->xacts.end()) { - DEBUG("ledger.validate", "xact_t: ! found"); + if (! _date || ! journal) { + DEBUG("ledger.validate", "xact_t: ! _date || ! journal"); return false; } - if (! account) { - DEBUG("ledger.validate", "xact_t: ! account"); - return false; - } - - if (! amount.valid()) { - DEBUG("ledger.validate", "xact_t: ! amount.valid()"); - return false; - } - - if (cost && ! cost->valid()) { - DEBUG("ledger.validate", "xact_t: cost && ! cost->valid()"); - return false; - } + foreach (post_t * post, posts) + if (post->xact != this || ! post->valid()) { + DEBUG("ledger.validate", "xact_t: post not valid"); + return false; + } return true; } -void xact_t::add_to_value(value_t& value, expr_t& expr) +void auto_xact_t::extend_xact(xact_base_t& xact, bool post_handler) { - if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) { - add_or_set_value(value, xdata_->value); - } - else if (! xdata_ || ! xdata_->has_flags(XACT_EXT_NO_TOTAL)) { - bind_scope_t bound_scope(*expr.get_context(), *this); - add_or_set_value(value, expr.calc(bound_scope)); + posts_list initial_posts(xact.posts.begin(), xact.posts.end()); + + foreach (post_t * initial_post, initial_posts) { + if (! initial_post->has_flags(POST_AUTO) && predicate(*initial_post)) { + foreach (post_t * post, posts) { + amount_t amt; + assert(post->amount); + if (! post->amount.commodity()) { + if (! post_handler) + continue; + assert(initial_post->amount); + amt = initial_post->amount * post->amount; + } else { + if (post_handler) + continue; + amt = post->amount; + } + + IF_DEBUG("xact.extend") { + DEBUG("xact.extend", + "Initial post on line " << initial_post->beg_line << ": " + << "amount " << initial_post->amount << " (precision " + << initial_post->amount.precision() << ")"); + + if (initial_post->amount.keep_precision()) + DEBUG("xact.extend", " precision is kept"); + + DEBUG("xact.extend", + "Posting on line " << post->beg_line << ": " + << "amount " << post->amount << ", amt " << amt + << " (precision " << post->amount.precision() + << " != " << amt.precision() << ")"); + + if (post->amount.keep_precision()) + DEBUG("xact.extend", " precision is kept"); + if (amt.keep_precision()) + DEBUG("xact.extend", " amt precision is kept"); + } + + account_t * account = post->account; + string fullname = account->fullname(); + assert(! fullname.empty()); + if (fullname == "$account" || fullname == "@account") + account = initial_post->account; + + // Copy over details so that the resulting post is a mirror of + // the automated xact's one. + post_t * new_post = new post_t(account, amt); + new_post->copy_details(*post); + new_post->add_flags(POST_AUTO); + + xact.add_post(new_post); + } + } } } +void extend_xact_base(journal_t * journal, + xact_base_t& base, + bool post_handler) +{ + foreach (auto_xact_t * xact, journal->auto_xacts) + xact->extend_xact(base, post_handler); +} + } // namespace ledger @@ -46,163 +46,210 @@ #ifndef _XACT_H #define _XACT_H -#include "item.h" +#include "post.h" +#include "predicate.h" namespace ledger { -class entry_t; -class account_t; +class journal_t; -class xact_t; -typedef std::list<xact_t *> xacts_list; +/** + * @brief Brief + * + * Long. + */ +class xact_base_t : public item_t +{ +public: + journal_t * journal; + + posts_list posts; + + xact_base_t() : item_t(), journal(NULL) { + TRACE_CTOR(xact_base_t, ""); + } + xact_base_t(const xact_base_t& e); + + virtual ~xact_base_t(); + + virtual state_t state() const; + + virtual void add_post(post_t * post); + virtual bool remove_post(post_t * post); + + virtual bool finalize(); + virtual bool valid() const = 0; +}; /** * @brief Brief * * Long. */ -class xact_t : public item_t +class xact_t : public xact_base_t { public: -#define XACT_VIRTUAL 0x10 // the account was specified with (parens) -#define XACT_MUST_BALANCE 0x20 // the account was specified with [brackets] -#define XACT_AUTO 0x40 // transaction created by automated entry -#define XACT_CALCULATED 0x80 // transaction's amount was auto-calculated - - entry_t * entry; // only set for xacts of regular entries - account_t * account; - - amount_t amount; // can be null until finalization - optional<amount_t> cost; - optional<amount_t> assigned_amount; - - xact_t(account_t * _account = NULL, - flags_t _flags = ITEM_NORMAL) - : item_t(_flags), - entry(NULL), account(_account) - { - TRACE_CTOR(xact_t, "account_t *, flags_t"); - } - xact_t(account_t * _account, - const amount_t& _amount, - flags_t _flags = ITEM_NORMAL, - const optional<string>& _note = none) - : item_t(_flags, _note), - entry(NULL), account(_account), amount(_amount) - { - TRACE_CTOR(xact_t, "account_t *, const amount_t&, flags_t, const optional<string>&"); - } - xact_t(const xact_t& xact) - : item_t(xact), - entry(xact.entry), - account(xact.account), - amount(xact.amount), - cost(xact.cost), - assigned_amount(xact.assigned_amount), - xdata_(xact.xdata_) - { - TRACE_CTOR(xact_t, "copy"); + optional<string> code; + string payee; + + xact_t() { + TRACE_CTOR(xact_t, ""); } - ~xact_t() { + xact_t(const xact_t& e); + + virtual ~xact_t() { TRACE_DTOR(xact_t); } - virtual bool has_tag(const string& tag) const; - virtual bool has_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask = none) const; + virtual void add_post(post_t * post); - virtual optional<string> get_tag(const string& tag) const; - virtual optional<string> get_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask = none) const; + virtual expr_t::ptr_op_t lookup(const string& name); - virtual date_t date() const; - virtual optional<date_t> effective_date() const; + virtual bool valid() const; +}; - virtual state_t state() const; +/** + * @brief Brief + * + * Long. + */ +struct xact_finalizer_t { + virtual ~xact_finalizer_t() {} + virtual bool operator()(xact_t& xact, bool post) = 0; +}; - bool must_balance() const { - return ! has_flags(XACT_VIRTUAL) || has_flags(XACT_MUST_BALANCE); +/** + * @brief Brief + * + * Long. + */ +class auto_xact_t : public xact_base_t +{ +public: + item_predicate predicate; + + auto_xact_t() { + TRACE_CTOR(auto_xact_t, ""); + } + auto_xact_t(const auto_xact_t& other) + : xact_base_t(), predicate(other.predicate) { + TRACE_CTOR(auto_xact_t, "copy"); + } + auto_xact_t(const item_predicate& _predicate) + : predicate(_predicate) + { + TRACE_CTOR(auto_xact_t, "const item_predicate<post_t>&"); } - virtual expr_t::ptr_op_t lookup(const string& name); + virtual ~auto_xact_t() { + TRACE_DTOR(auto_xact_t); + } - bool valid() const; + virtual void extend_xact(xact_base_t& xact, bool post); + virtual bool valid() const { + return true; + } +}; - struct xdata_t : public supports_flags<> - { -#define XACT_EXT_RECEIVED 0x01 -#define XACT_EXT_HANDLED 0x02 -#define XACT_EXT_TO_DISPLAY 0x04 -#define XACT_EXT_DISPLAYED 0x08 -#define XACT_EXT_NO_TOTAL 0x10 -#define XACT_EXT_SORT_CALC 0x20 -#define XACT_EXT_COMPOUND 0x40 -#define XACT_EXT_MATCHES 0x80 - - value_t total; - std::size_t count; - value_t value; - date_t date; - account_t * account; - void * ptr; - - std::list<sort_value_t> sort_values; - - xdata_t() - : supports_flags<>(), count(0), account(NULL), ptr(NULL) { - TRACE_CTOR(xact_t::xdata_t, ""); - } - xdata_t(const xdata_t& other) - : supports_flags<>(other.flags()), - total(other.total), - count(other.count), - value(other.value), - date(other.date), - account(other.account), - ptr(NULL), - sort_values(other.sort_values) - { - TRACE_CTOR(xact_t::xdata_t, "copy"); - } - ~xdata_t() throw() { - TRACE_DTOR(xact_t::xdata_t); - } - }; - - // This variable holds optional "extended data" which is usually produced - // only during reporting, and only for the transaction set being reported. - // It's a memory-saving measure to delay allocation until the last possible - // moment. - mutable optional<xdata_t> xdata_; - - bool has_xdata() const { - return xdata_; - } - void clear_xdata() { - xdata_ = none; - } - xdata_t& xdata() { - if (! xdata_) - xdata_ = xdata_t(); - return *xdata_; - } - - void add_to_value(value_t& value, expr_t& expr); - - account_t * reported_account() { - if (xdata_) - if (account_t * acct = xdata_->account) - return acct; - return account; - } - - const account_t * reported_account() const { - return const_cast<xact_t *>(this)->reported_account(); - } - - friend class entry_t; +/** + * @brief Brief + * + * Long. + */ +struct auto_xact_finalizer_t : public xact_finalizer_t +{ + journal_t * journal; + + auto_xact_finalizer_t() : journal(NULL) { + TRACE_CTOR(auto_xact_finalizer_t, ""); + } + auto_xact_finalizer_t(const auto_xact_finalizer_t& other) + : xact_finalizer_t(), journal(other.journal) { + TRACE_CTOR(auto_xact_finalizer_t, "copy"); + } + auto_xact_finalizer_t(journal_t * _journal) : journal(_journal) { + TRACE_CTOR(auto_xact_finalizer_t, "journal_t *"); + } + ~auto_xact_finalizer_t() throw() { + TRACE_DTOR(auto_xact_finalizer_t); + } + + virtual bool operator()(xact_t& xact, bool post); }; +/** + * @brief Brief + * + * Long. + */ +class period_xact_t : public xact_base_t +{ + public: + interval_t period; + string period_string; + + period_xact_t() { + TRACE_CTOR(period_xact_t, ""); + } + period_xact_t(const period_xact_t& e) + : xact_base_t(e), period(e.period), period_string(e.period_string) { + TRACE_CTOR(period_xact_t, "copy"); + } + period_xact_t(const string& _period) + : period(_period), period_string(_period) { + TRACE_CTOR(period_xact_t, "const string&"); + } + + virtual ~period_xact_t() throw() { + TRACE_DTOR(period_xact_t); + } + + virtual bool valid() const { + return period; + } +}; + +/** + * @brief Brief + * + * Long. + */ +class func_finalizer_t : public xact_finalizer_t +{ + func_finalizer_t(); + +public: + typedef function<bool (xact_t& xact, bool post)> func_t; + + func_t func; + + func_finalizer_t(func_t _func) : func(_func) { + TRACE_CTOR(func_finalizer_t, "func_t"); + } + func_finalizer_t(const func_finalizer_t& other) : + xact_finalizer_t(), func(other.func) { + TRACE_CTOR(func_finalizer_t, "copy"); + } + ~func_finalizer_t() throw() { + TRACE_DTOR(func_finalizer_t); + } + + virtual bool operator()(xact_t& xact, bool post) { + return func(xact, post); + } +}; + +void extend_xact_base(journal_t * journal, xact_base_t& xact, bool post); + +inline bool auto_xact_finalizer_t::operator()(xact_t& xact, bool post) { + extend_xact_base(journal, xact, post); + return true; +} + +typedef std::list<xact_t *> xacts_list; +typedef std::list<auto_xact_t *> auto_xacts_list; +typedef std::list<period_xact_t *> period_xacts_list; + } // namespace ledger #endif // _XACT_H |