diff options
Diffstat (limited to 'walk.cc')
-rw-r--r-- | walk.cc | 290 |
1 files changed, 193 insertions, 97 deletions
@@ -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 |