summaryrefslogtreecommitdiff
path: root/walk.cc
diff options
context:
space:
mode:
Diffstat (limited to 'walk.cc')
-rw-r--r--walk.cc290
1 files changed, 193 insertions, 97 deletions
diff --git a/walk.cc b/walk.cc
index 88b5461a..40185543 100644
--- a/walk.cc
+++ b/walk.cc
@@ -1,7 +1,7 @@
#include "walk.h"
+#include "session.h"
#include "format.h"
#include "textual.h"
-#include "util.h"
#include <algorithm>
@@ -16,22 +16,22 @@ bool compare_items<transaction_t>::operator()(const transaction_t * left,
transaction_xdata_t& lxdata(transaction_xdata(*left));
if (! (lxdata.dflags & TRANSACTION_SORT_CALC)) {
- guarded_compute(sort_order, lxdata.sort_value, details_t(*left));
+ sort_order.compute(lxdata.sort_value, details_t(*left));
lxdata.sort_value.reduce();
lxdata.dflags |= TRANSACTION_SORT_CALC;
}
transaction_xdata_t& rxdata(transaction_xdata(*right));
if (! (rxdata.dflags & TRANSACTION_SORT_CALC)) {
- guarded_compute(sort_order, rxdata.sort_value, details_t(*right));
+ sort_order.compute(rxdata.sort_value, details_t(*right));
rxdata.sort_value.reduce();
rxdata.dflags |= TRANSACTION_SORT_CALC;
}
- DEBUG_PRINT("ledger.walk.compare_items_xact",
- "lxdata.sort_value = " << lxdata.sort_value);
- DEBUG_PRINT("ledger.walk.compare_items_xact",
- "rxdata.sort_value = " << rxdata.sort_value);
+ DEBUG("ledger.walk.compare_items_xact",
+ "lxdata.sort_value = " << lxdata.sort_value);
+ DEBUG("ledger.walk.compare_items_xact",
+ "rxdata.sort_value = " << rxdata.sort_value);
return lxdata.sort_value < rxdata.sort_value;
}
@@ -49,14 +49,66 @@ void add_transaction_to(const transaction_t& xact, value_t& value)
transaction_xdata_(xact).dflags & TRANSACTION_COMPOUND) {
value += transaction_xdata_(xact).value;
}
- else if (xact.cost || ! value.realzero()) {
- value.add(xact.amount, xact.cost);
+ else if (xact.cost || (! value.is_null() && ! value.is_realzero())) {
+ // jww (2008-04-24): Is this costly?
+ value.add(xact.amount, xact.cost ? optional<amount_t>(*xact.cost) : none);
}
else {
value = xact.amount;
}
}
+void entries_iterator::reset(session_t& session)
+{
+ journals_i = session.journals.begin();
+ journals_end = session.journals.end();
+
+ journals_uninitialized = false;
+
+ if (journals_i != journals_end) {
+ entries_i = (*journals_i).entries.begin();
+ entries_end = (*journals_i).entries.end();
+
+ entries_uninitialized = false;
+ } else {
+ entries_uninitialized = true;
+ }
+}
+
+entry_t * entries_iterator::operator()()
+{
+ if (entries_i == entries_end) {
+ journals_i++;
+ if (journals_i == journals_end)
+ return NULL;
+
+ entries_i = (*journals_i).entries.begin();
+ entries_end = (*journals_i).entries.end();
+ }
+ return *entries_i++;
+}
+
+void session_transactions_iterator::reset(session_t& session)
+{
+ entries.reset(session);
+ entry_t * entry = entries();
+ if (entry != NULL)
+ xacts.reset(*entry);
+}
+
+transaction_t * session_transactions_iterator::operator()()
+{
+ transaction_t * xact = xacts();
+ if (xact == NULL) {
+ entry_t * entry = entries();
+ if (entry != NULL) {
+ xacts.reset(*entry);
+ xact = xacts();
+ }
+ }
+ return xact;
+}
+
void truncate_entries::flush()
{
if (! xacts.size())
@@ -117,7 +169,7 @@ void set_account_value::operator()(transaction_t& xact)
add_transaction_to(xact, xdata.value);
xdata.count++;
- if (xact.flags & TRANSACTION_VIRTUAL)
+ if (xact.has_flags(TRANSACTION_VIRTUAL))
xdata.virtuals++;
item_handler<transaction_t>::operator()(xact);
@@ -194,7 +246,7 @@ void handle_value(const value_t& value,
temps.push_back(transaction_t(account));
transaction_t& xact(temps.back());
xact.entry = entry;
- xact.flags |= TRANSACTION_BULK_ALLOC;
+ xact.add_flags(TRANSACTION_BULK_ALLOC);
entry->add_transaction(&xact);
// If there are component transactions to associate with this
@@ -209,19 +261,19 @@ void handle_value(const value_t& value,
if (account && account_has_xdata(*account))
if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_NON_VIRTUALS)) {
- xact.flags |= TRANSACTION_VIRTUAL;
+ xact.add_flags(TRANSACTION_VIRTUAL);
if (! (account_xdata_(*account).dflags & ACCOUNT_HAS_UNB_VIRTUALS))
- xact.flags |= TRANSACTION_BALANCE;
+ xact.add_flags(TRANSACTION_BALANCE);
}
transaction_xdata_t& xdata(transaction_xdata(xact));
- if (date)
+ if (is_valid(date))
xdata.date = date;
value_t temp(value);
- switch (value.type) {
+ switch (value.type()) {
case value_t::BOOLEAN:
case value_t::DATETIME:
case value_t::INTEGER:
@@ -229,7 +281,7 @@ void handle_value(const value_t& value,
// fall through...
case value_t::AMOUNT:
- xact.amount = *((amount_t *) temp.data);
+ xact.amount = temp.as_amount();
break;
case value_t::BALANCE:
@@ -237,6 +289,10 @@ void handle_value(const value_t& value,
xdata.value = temp;
flags |= TRANSACTION_COMPOUND;
break;
+
+ default:
+ assert(false); // jww (2008-04-24): What to do here?
+ break;
}
if (flags)
@@ -295,7 +351,7 @@ void related_transactions::flush()
transaction_xdata_t& xdata = transaction_xdata(**j);
if (! (xdata.dflags & TRANSACTION_HANDLED) &&
(! (xdata.dflags & TRANSACTION_RECEIVED) ?
- ! ((*j)->flags & (TRANSACTION_AUTO | TRANSACTION_VIRTUAL)) :
+ ! (*j)->has_flags(TRANSACTION_AUTO | TRANSACTION_VIRTUAL) :
also_matching)) {
xdata.dflags |= TRANSACTION_HANDLED;
item_handler<transaction_t>::operator()(**j);
@@ -307,7 +363,7 @@ void related_transactions::flush()
// output auto or period entries.
transaction_xdata_t& xdata = transaction_xdata(**i);
if (! (xdata.dflags & TRANSACTION_HANDLED) &&
- ! ((*i)->flags & TRANSACTION_AUTO)) {
+ ! (*i)->has_flags(TRANSACTION_AUTO)) {
xdata.dflags |= TRANSACTION_HANDLED;
item_handler<transaction_t>::operator()(**i);
}
@@ -325,7 +381,10 @@ void changed_value_transactions::output_diff(const datetime_t& current)
transaction_xdata(*last_xact).date = current;
compute_total(cur_bal, details_t(*last_xact));
cur_bal.round();
+ // jww (2008-04-24): What does this do?
+#if 0
transaction_xdata(*last_xact).date = 0;
+#endif
if (value_t diff = cur_bal - last_balance) {
entry_temps.push_back(entry_t());
@@ -375,11 +434,16 @@ void subtotal_transactions::report_subtotal(const char * spec_fmt)
{
std::ostringstream out_date;
if (! spec_fmt) {
- std::string fmt = "- ";
- fmt += date_t::output_format;
+ string fmt = "- ";
+ fmt += output_time_format; // jww (2008-04-24): output_date_format?
+ // jww (2008-04-24): There is no date output function?
+#if 0
finish.write(out_date, fmt);
+#endif
} else {
+#if 0
finish.write(out_date, spec_fmt);
+#endif
}
entry_temps.push_back(entry_t());
@@ -398,9 +462,9 @@ void subtotal_transactions::report_subtotal(const char * spec_fmt)
void subtotal_transactions::operator()(transaction_t& xact)
{
- if (! start || xact.date() < start)
+ if (! is_valid(start) || xact.date() < start)
start = xact.date();
- if (! finish || xact.date() > finish)
+ if (! is_valid(finish) || xact.date() > finish)
finish = xact.date();
account_t * acct = xact_account(xact);
@@ -411,8 +475,7 @@ void subtotal_transactions::operator()(transaction_t& xact)
value_t temp;
add_transaction_to(xact, temp);
std::pair<values_map::iterator, bool> result
- = values.insert(values_pair(acct->fullname(),
- acct_value_t(acct, temp)));
+ = values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp)));
assert(result.second);
if (remember_components)
@@ -428,9 +491,9 @@ void subtotal_transactions::operator()(transaction_t& xact)
// such, so that `handle_value' can show "(Account)" for accounts
// that contain only virtual transactions.
- if (! (xact.flags & TRANSACTION_VIRTUAL))
+ if (! xact.has_flags(TRANSACTION_VIRTUAL))
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
- else if (! (xact.flags & TRANSACTION_BALANCE))
+ else if (! xact.has_flags(TRANSACTION_BALANCE))
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
}
@@ -439,8 +502,13 @@ void interval_transactions::report_subtotal(const datetime_t& moment)
assert(last_xact);
start = interval.begin;
- if (moment)
+ if (is_valid(moment))
+ // jww (2008-04-24): How to change this back into a datetime?
+#if 0
finish = moment - 86400L;
+#else
+ ;
+#endif
else
finish = last_xact->date();
@@ -453,13 +521,13 @@ void interval_transactions::operator()(transaction_t& xact)
{
const datetime_t date = xact.date();
- if ((interval.begin && date < interval.begin) ||
- (interval.end && date >= interval.end))
+ if ((is_valid(interval.begin) && date < interval.begin) ||
+ (is_valid(interval.end) && date >= interval.end))
return;
if (interval) {
if (! started) {
- if (! interval.begin)
+ if (! is_valid(interval.begin))
interval.start(date);
start = interval.begin;
started = true;
@@ -489,10 +557,12 @@ void interval_transactions::operator()(transaction_t& xact)
by_payee_transactions::~by_payee_transactions()
{
+ TRACE_DTOR(by_payee_transactions);
+
for (payee_subtotals_map::iterator i = payee_subtotals.begin();
i != payee_subtotals.end();
i++)
- delete (*i).second;
+ checked_delete((*i).second);
}
void by_payee_transactions::flush()
@@ -545,7 +615,7 @@ void set_comm_as_payee::operator()(transaction_t& xact)
transaction_t& temp = xact_temps.back();
temp.entry = &entry;
temp.state = xact.state;
- temp.flags |= TRANSACTION_BULK_ALLOC;
+ temp.add_flags(TRANSACTION_BULK_ALLOC);
entry.add_transaction(&temp);
@@ -558,8 +628,8 @@ void set_code_as_payee::operator()(transaction_t& xact)
entry_t& entry = entry_temps.back();
entry._date = xact.date();
- if (! xact.entry->code.empty())
- entry.payee = xact.entry->code;
+ if (xact.entry->code)
+ entry.payee = *xact.entry->code;
else
entry.payee = "<none>";
@@ -567,7 +637,7 @@ void set_code_as_payee::operator()(transaction_t& xact)
transaction_t& temp = xact_temps.back();
temp.entry = &entry;
temp.state = xact.state;
- temp.flags |= TRANSACTION_BULK_ALLOC;
+ temp.add_flags(TRANSACTION_BULK_ALLOC);
entry.add_transaction(&temp);
@@ -577,7 +647,10 @@ void set_code_as_payee::operator()(transaction_t& xact)
void dow_transactions::flush()
{
for (int i = 0; i < 7; i++) {
+ // jww (2008-04-24): What to use here?
+#if 0
start = finish = 0;
+#endif
for (transactions_list::iterator d = days_of_the_week[i].begin();
d != days_of_the_week[i].end();
d++)
@@ -619,19 +692,22 @@ void budget_transactions::report_budget_items(const datetime_t& moment)
i != pending_xacts.end();
i++) {
datetime_t& begin = (*i).first.begin;
- if (! begin) {
+ if (! is_valid(begin)) {
(*i).first.start(moment);
begin = (*i).first.begin;
}
if (begin < moment &&
- (! (*i).first.end || begin < (*i).first.end)) {
+ (! is_valid((*i).first.end) || begin < (*i).first.end)) {
transaction_t& xact = *(*i).second;
- DEBUG_PRINT("ledger.walk.budget", "Reporting budget for "
+ DEBUG("ledger.walk.budget", "Reporting budget for "
<< xact_account(xact)->fullname());
- DEBUG_PRINT_TIME("ledger.walk.budget", begin);
- DEBUG_PRINT_TIME("ledger.walk.budget", moment);
+#if 0
+ // jww (2008-04-24): Need a new debug macro here
+ DEBUG_TIME("ledger.walk.budget", begin);
+ DEBUG_TIME("ledger.walk.budget", moment);
+#endif
entry_temps.push_back(entry_t());
entry_t& entry = entry_temps.back();
@@ -640,8 +716,8 @@ void budget_transactions::report_budget_items(const datetime_t& moment)
xact_temps.push_back(xact);
transaction_t& temp = xact_temps.back();
- temp.entry = &entry;
- temp.flags |= TRANSACTION_AUTO | TRANSACTION_BULK_ALLOC;
+ temp.entry = &entry;
+ temp.add_flags(TRANSACTION_AUTO | TRANSACTION_BULK_ALLOC);
temp.amount.negate();
entry.add_transaction(&temp);
@@ -691,11 +767,11 @@ void forecast_transactions::add_transaction(const interval_t& period,
generate_transactions::add_transaction(period, xact);
interval_t& i = pending_xacts.back().first;
- if (! i.begin) {
- i.start(datetime_t::now);
+ if (! is_valid(i.begin)) {
+ i.start(current_moment);
i.begin = i.increment(i.begin);
} else {
- while (i.begin < datetime_t::now)
+ while (i.begin < current_moment)
i.begin = i.increment(i.begin);
}
}
@@ -715,7 +791,7 @@ void forecast_transactions::flush()
datetime_t& begin = (*least).first.begin;
- if ((*least).first.end && begin >= (*least).first.end) {
+ if (is_valid((*least).first.end) && begin >= (*least).first.end) {
pending_xacts.erase(least);
passed.remove((*least).second);
continue;
@@ -731,13 +807,13 @@ void forecast_transactions::flush()
xact_temps.push_back(xact);
transaction_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.flags |= TRANSACTION_AUTO;
- temp.flags |= TRANSACTION_BULK_ALLOC;
+ temp.add_flags(TRANSACTION_AUTO | TRANSACTION_BULK_ALLOC);
entry.add_transaction(&temp);
datetime_t next = (*least).first.increment(begin);
+ // jww (2008-04-24): Does seconds() here give the total seconds?
if (next < begin || // wraparound
- (last && (next - last) > 365 * 5 * 24 * 3600))
+ (is_valid(last) && (next - last).seconds() > 365 * 5 * 24 * 3600))
break;
begin = next;
@@ -779,13 +855,13 @@ bool compare_items<account_t>::operator()(const account_t * left,
account_xdata_t& lxdata(account_xdata(*left));
if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) {
- guarded_compute(sort_order, lxdata.sort_value, details_t(*left));
+ sort_order.compute(lxdata.sort_value, details_t(*left));
lxdata.dflags |= ACCOUNT_SORT_CALC;
}
account_xdata_t& rxdata(account_xdata(*right));
if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) {
- guarded_compute(sort_order, rxdata.sort_value, details_t(*right));
+ sort_order.compute(rxdata.sort_value, details_t(*right));
rxdata.dflags |= ACCOUNT_SORT_CALC;
}
@@ -816,79 +892,86 @@ void sum_accounts(account_t& account)
value_t result;
compute_amount(result, details_t(account));
- if (! result.realzero())
+ if (! result.is_realzero())
xdata.total += result;
xdata.total_count += xdata.count;
}
-void sort_accounts(account_t& account,
- const value_expr_t * sort_order,
- accounts_deque& accounts)
+account_t * accounts_iterator::operator()()
{
- for (accounts_map::iterator i = account.accounts.begin();
- i != account.accounts.end();
- i++)
- accounts.push_back((*i).second);
+ while (! accounts_i.empty() &&
+ accounts_i.back() == accounts_end.back()) {
+ accounts_i.pop_back();
+ accounts_end.pop_back();
+ }
+ if (accounts_i.empty())
+ return NULL;
+
+ account_t * account = (*(accounts_i.back()++)).second;
+ assert(account);
+
+ // If this account has children, queue them up to be iterated next.
+ if (! account->accounts.empty())
+ push_back(*account);
- std::stable_sort(accounts.begin(), accounts.end(),
- compare_items<account_t>(sort_order));
+ return account;
}
-void walk_accounts(account_t& account,
- item_handler<account_t>& handler,
- const value_expr_t * sort_order)
+void sorted_accounts_iterator::sort_accounts(account_t& account,
+ accounts_deque_t& deque)
{
- handler(account);
+ for (accounts_map::iterator i = account.accounts.begin();
+ i != account.accounts.end();
+ i++)
+ deque.push_back((*i).second);
- if (sort_order) {
- accounts_deque accounts;
- sort_accounts(account, sort_order, accounts);
- for (accounts_deque::const_iterator i = accounts.begin();
- i != accounts.end();
- i++) {
- account_xdata(**i).dflags &= ~ACCOUNT_SORT_CALC;
- walk_accounts(**i, handler, sort_order);
- }
- } else {
- for (accounts_map::const_iterator i = account.accounts.begin();
- i != account.accounts.end();
- i++)
- walk_accounts(*(*i).second, handler, NULL);
- }
+ std::stable_sort(deque.begin(), deque.end(),
+ compare_items<account_t>(sort_cmp));
}
-void walk_accounts(account_t& account,
- item_handler<account_t>& handler,
- const std::string& sort_string)
+account_t * sorted_accounts_iterator::operator()()
{
- if (! sort_string.empty()) {
- value_expr sort_order;
- sort_order.reset(parse_value_expr(sort_string));
- walk_accounts(account, handler, sort_order.get());
- } else {
- walk_accounts(account, handler);
+ while (! sorted_accounts_i.empty() &&
+ sorted_accounts_i.back() == sorted_accounts_end.back()) {
+ sorted_accounts_i.pop_back();
+ sorted_accounts_end.pop_back();
+ assert(! accounts_list.empty());
+ accounts_list.pop_back();
}
+ if (sorted_accounts_i.empty())
+ return NULL;
+
+ account_t * account = *sorted_accounts_i.back()++;
+ assert(account);
+
+ // If this account has children, queue them up to be iterated next.
+ if (! account->accounts.empty())
+ push_back(*account);
+
+ account_xdata(*account).dflags &= ~ACCOUNT_SORT_CALC;
+ return account;
}
-void walk_commodities(commodities_map& commodities,
+void walk_commodities(commodity_pool_t::commodities_by_ident& commodities,
item_handler<transaction_t>& handler)
{
std::list<transaction_t> xact_temps;
std::list<entry_t> entry_temps;
std::list<account_t> acct_temps;
- for (commodities_map::iterator i = commodities.begin();
+ for (commodity_pool_t::commodities_by_ident::iterator
+ i = commodities.begin();
i != commodities.end();
i++) {
- if ((*i).second->flags() & COMMODITY_STYLE_NOMARKET)
+ if ((*i)->has_flags(COMMODITY_STYLE_NOMARKET))
continue;
entry_temps.push_back(entry_t());
- acct_temps.push_back(account_t(NULL, (*i).second->symbol()));
+ acct_temps.push_back(account_t(NULL, (*i)->symbol()));
- if ((*i).second->history())
- for (history_map::iterator j = (*i).second->history()->prices.begin();
- j != (*i).second->history()->prices.end();
+ if ((*i)->history())
+ for (commodity_t::history_map::iterator j = (*i)->history()->prices.begin();
+ j != (*i)->history()->prices.end();
j++) {
entry_temps.back()._date = (*j).first;
@@ -896,7 +979,7 @@ void walk_commodities(commodities_map& commodities,
transaction_t& temp = xact_temps.back();
temp.entry = &entry_temps.back();
temp.amount = (*j).second;
- temp.flags |= TRANSACTION_BULK_ALLOC;
+ temp.add_flags(TRANSACTION_BULK_ALLOC);
entry_temps.back().add_transaction(&temp);
handler(xact_temps.back());
@@ -908,4 +991,17 @@ void walk_commodities(commodities_map& commodities,
clear_entries_transactions(entry_temps);
}
+void journals_iterator::reset(session_t& session)
+{
+ journals_i = session.journals.begin();
+ journals_end = session.journals.end();
+}
+
+journal_t * journals_iterator::operator()()
+{
+ if (journals_i == journals_end)
+ return NULL;
+ return &(*journals_i++);
+}
+
} // namespace ledger