diff options
Diffstat (limited to 'walk.cc')
-rw-r--r-- | walk.cc | 662 |
1 files changed, 0 insertions, 662 deletions
diff --git a/walk.cc b/walk.cc deleted file mode 100644 index 2683aa2d..00000000 --- a/walk.cc +++ /dev/null @@ -1,662 +0,0 @@ -#include "walk.h" -#include "format.h" - -namespace ledger { - -std::list<transaction_xdata_t> transactions_xdata; -std::list<void **> transactions_xdata_ptrs; - -std::list<account_xdata_t> accounts_xdata; -std::list<void **> accounts_xdata_ptrs; - -template <> -bool compare_items<transaction_t>::operator()(const transaction_t * left, - const transaction_t * right) -{ - assert(left); - assert(right); - - transaction_xdata_t& lxdata(transaction_xdata(*left)); - if (! (lxdata.dflags & TRANSACTION_SORT_CALC)) { - sort_order->compute(lxdata.sort_value, details_t(*left)); - lxdata.dflags |= TRANSACTION_SORT_CALC; - } - - transaction_xdata_t& rxdata(transaction_xdata(*right)); - if (! (rxdata.dflags & TRANSACTION_SORT_CALC)) { - sort_order->compute(rxdata.sort_value, details_t(*right)); - rxdata.dflags |= TRANSACTION_SORT_CALC; - } - - return lxdata.sort_value < rxdata.sort_value; -} - -void sort_transactions::flush() -{ - std::stable_sort(transactions.begin(), transactions.end(), - compare_items<transaction_t>(sort_order)); - - for (transactions_deque::iterator i = transactions.begin(); - i != transactions.end(); - i++) { - transaction_xdata(**i).dflags &= ~TRANSACTION_SORT_CALC; - (*handler)(**i); - } - - transactions.clear(); - - item_handler<transaction_t>::flush(); -} - -void calc_transactions::operator()(transaction_t& xact) -{ - if (last_xact && transaction_has_xdata(*last_xact)) { - transaction_xdata(xact).total += transaction_xdata(*last_xact).total; - transaction_xdata(xact).index = transaction_xdata(*last_xact).index + 1; - } else { - transaction_xdata(xact).index = 0; - } - - if (inverted) { - xact.amount.negate(); - if (xact.cost) - xact.cost->negate(); - } - - if (! (transaction_xdata(xact).dflags & TRANSACTION_NO_TOTAL)) - add_transaction_to(xact, transaction_xdata(xact).total); - - (*handler)(xact); - - if (inverted) { - xact.amount.negate(); - if (xact.cost) - xact.cost->negate(); - } - - last_xact = &xact; -} - - -static void handle_value(const value_t& value, - account_t * account, - entry_t * entry, - unsigned int flags, - std::list<transaction_t>& temps, - item_handler<transaction_t> * handler) -{ - balance_t * bal = NULL; - - switch (value.type) { - case value_t::BOOLEAN: - case value_t::INTEGER: - case value_t::AMOUNT: { - temps.push_back(transaction_t(account)); - transaction_t& xact = temps.back(); - - xact.entry = entry; - switch (value.type) { - case value_t::BOOLEAN: - xact.amount = *((bool *) value.data); - break; - case value_t::INTEGER: - xact.amount = *((unsigned int *) value.data); - break; - case value_t::AMOUNT: - xact.amount = *((amount_t *) value.data); - break; - default: - assert(0); - break; - } - - if (flags) - transaction_xdata(xact).dflags |= flags; - - (*handler)(xact); - break; - } - - case value_t::BALANCE_PAIR: - bal = &((balance_pair_t *) value.data)->quantity; - // fall through... - - case value_t::BALANCE: - if (! bal) - bal = (balance_t *) value.data; - - for (amounts_map::const_iterator i = bal->amounts.begin(); - i != bal->amounts.end(); - i++) { - temps.push_back(transaction_t(account)); - transaction_t& xact = temps.back(); - - xact.entry = entry; - xact.amount = (*i).second; - - if (flags) - transaction_xdata(xact).dflags |= flags; - - (*handler)(xact); - } - break; - - default: - assert(0); - break; - } -} - -static inline void determine_amount(value_t& result, balance_pair_t& bal_pair) -{ - account_xdata_t xdata; - xdata.value = bal_pair; - account_t temp_account; - temp_account.data = &xdata; - format_t::compute_amount(result, details_t(temp_account)); -} - -void collapse_transactions::report_cumulative_subtotal() -{ - if (count == 1) { - (*handler)(*last_xact); - } else { - assert(count > 1); - - value_t result; - determine_amount(result, subtotal); - handle_value(result, &totals_account, last_entry, 0, xact_temps, handler); - } - - last_entry = NULL; - last_xact = NULL; - subtotal = 0; - count = 0; -} - -void changed_value_transactions::output_diff(const std::time_t current) -{ - value_t prev_bal; - value_t cur_bal; - std::time_t prev_date = last_xact->entry->date; - - format_t::compute_total(prev_bal, details_t(*last_xact)); - - last_xact->entry->date = current; - format_t::compute_total(cur_bal, details_t(*last_xact)); - last_xact->entry->date = prev_date; - - cur_bal -= prev_bal; - if (cur_bal) { - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - - entry.payee = "Commodities revalued"; - entry.date = current; - - handle_value(cur_bal, NULL, &entry, TRANSACTION_NO_TOTAL, xact_temps, - handler); - } -} - -void changed_value_transactions::operator()(transaction_t& xact) -{ - if (last_xact) - output_diff(xact.entry->date); - - if (changed_values_only) - transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED; - - (*handler)(xact); - - last_xact = &xact; -} - -void subtotal_transactions::report_subtotal(const char * spec_fmt) -{ - char buf[256]; - - if (! spec_fmt) { - std::string fmt = "- "; - fmt += format_t::date_format; - - // Make sure the end date is inclusive - if (start != finish) - finish -= 86400; - - std::strftime(buf, 255, fmt.c_str(), std::localtime(&finish)); - } else { - std::strftime(buf, 255, spec_fmt, std::localtime(&finish)); - } - - entry_temps.push_back(entry_t()); - entry_t& entry = entry_temps.back(); - - entry.payee = buf; - - value_t result; - - for (balances_map::iterator i = balances.begin(); - i != balances.end(); - i++) { - entry.date = finish; - value_t result; - determine_amount(result, (*i).second); - entry.date = start; - - handle_value(result, (*i).first, &entry, 0, xact_temps, handler); - } - - balances.clear(); -} - -void subtotal_transactions::operator()(transaction_t& xact) -{ - if (balances.size() == 0) { - start = finish = xact.entry->date; - } else { - if (std::difftime(xact.entry->date, start) < 0) - start = xact.entry->date; - if (std::difftime(xact.entry->date, finish) > 0) - finish = xact.entry->date; - } - - balances_map::iterator i = balances.find(xact.account); - if (i == balances.end()) { - balance_pair_t temp; - add_transaction_to(xact, temp); - balances.insert(balances_pair(xact.account, temp)); - } else { - add_transaction_to(xact, (*i).second); - } -} - -void interval_transactions::operator()(transaction_t& xact) -{ - if ((interval.begin && - std::difftime(xact.entry->date, interval.begin) < 0) || - (interval.end && - std::difftime(xact.entry->date, interval.end) >= 0)) - return; - - if (interval) { - std::time_t quant = interval.increment(interval.begin); - if (std::difftime(xact.entry->date, quant) >= 0) { - if (last_xact) { - start = interval.begin; - finish = quant; - report_subtotal(); - } - - if (! interval.seconds) { - struct std::tm * desc = std::localtime(&xact.entry->date); - if (interval.years) - desc->tm_mon = 0; - desc->tm_mday = 1; - desc->tm_hour = 0; - desc->tm_min = 0; - desc->tm_sec = 0; - quant = std::mktime(desc); - } - - std::time_t temp; -#if DEBUG_LEVEL >= RELEASE - int cutoff = 10000; -#endif - while (std::difftime(xact.entry->date, - temp = interval.increment(quant)) > 0) { - if (quant == temp) - break; - quant = temp; -#if DEBUG_LEVEL >= RELEASE - assert(--cutoff > 0); -#endif - } - interval.begin = quant; - } - - subtotal_transactions::operator()(xact); - } else { - (*handler)(xact); - } - - last_xact = &xact; -} - -void dow_transactions::flush() -{ - for (int i = 0; i < 7; i++) { - for (transactions_list::iterator d = days_of_the_week[i].begin(); - d != days_of_the_week[i].end(); - d++) - subtotal_transactions::operator()(**d); - subtotal_transactions::report_subtotal("%As"); - days_of_the_week[i].clear(); - } - - subtotal_transactions::flush(); -} - -void clear_transactions_xdata() -{ - transactions_xdata.clear(); - - for (std::list<void **>::iterator i = transactions_xdata_ptrs.begin(); - i != transactions_xdata_ptrs.end(); - i++) - **i = NULL; -} - -template <> -bool compare_items<account_t>::operator()(const account_t * left, - const account_t * right) -{ - assert(left); - assert(right); - - account_xdata_t& lxdata(account_xdata(*left)); - if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) { - 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)) { - sort_order->compute(rxdata.sort_value, details_t(*right)); - rxdata.dflags |= ACCOUNT_SORT_CALC; - } - - return lxdata.sort_value < rxdata.sort_value; -} - -void sum_accounts(account_t& account) -{ - for (accounts_map::iterator i = account.accounts.begin(); - i != account.accounts.end(); - i++) { - sum_accounts(*(*i).second); - account_xdata(account).total += account_xdata(*(*i).second).total; - account_xdata(account).count += (account_xdata(*(*i).second).count + - account_xdata(*(*i).second).subcount); - } - account_xdata(account).total += account_xdata(account).value; - account_xdata(account).count += account_xdata(account).subcount; -} - -void sort_accounts(account_t& account, - const value_expr_t * sort_order, - accounts_deque& accounts) -{ - for (accounts_map::iterator i = account.accounts.begin(); - i != account.accounts.end(); - i++) - accounts.push_back((*i).second); - - std::stable_sort(accounts.begin(), accounts.end(), - compare_items<account_t>(sort_order)); -} - -void walk_accounts(account_t& account, - item_handler<account_t>& handler, - const value_expr_t * sort_order) -{ - handler(account); - - 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); - } -} - -void walk_accounts(account_t& account, - item_handler<account_t>& handler, - const std::string& sort_string) -{ - if (! sort_string.empty()) { - std::auto_ptr<value_expr_t> sort_order; - try { - sort_order.reset(parse_value_expr(sort_string)); - } - catch (value_expr_error& err) { - throw error(std::string("In sort string '" + sort_string + "': " + - err.what())); - } - walk_accounts(account, handler, sort_order.get()); - } else { - walk_accounts(account, handler); - } -} - -void clear_accounts_xdata() -{ - accounts_xdata.clear(); - - for (std::list<void **>::iterator i = accounts_xdata_ptrs.begin(); - i != accounts_xdata_ptrs.end(); - i++) - **i = NULL; -} - -} // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -template <typename T> -struct item_handler_wrap : public item_handler<T> -{ - PyObject* self; - - item_handler_wrap(PyObject * self_) : self(self_) {} - item_handler_wrap(PyObject * self_, const item_handler<T>& handler) - : item_handler<T>(const_cast<item_handler<T> *>(&handler)), self(self_) {} - - virtual void flush() { - call_method<void>(self, "flush"); - } - void default_flush() { - item_handler<T>::flush(); - } - - virtual void operator()(T& item) { - call_method<void>(self, "__call__", ptr(&item)); - } - void default_call(T& item) { - item_handler<T>::operator()(item); - } -}; - -void (subtotal_transactions::*subtotal_transactions_flush)() = - &subtotal_transactions::flush; - -void py_walk_entries(journal_t& journal, item_handler<transaction_t>& handler) -{ - walk_entries(journal.entries, handler); -} - -void py_walk_transactions(entry_t& entry, item_handler<transaction_t>& handler) -{ - walk_transactions(entry.transactions, handler); -} - -void py_walk_accounts_1(account_t& account, - item_handler<account_t>& handler) -{ - walk_accounts(account, handler); -} - -void py_walk_accounts_2(account_t& account, - item_handler<account_t>& handler, - const value_expr_t * sort_order) -{ - walk_accounts(account, handler, sort_order); -} - -void py_walk_accounts_3(account_t& account, - item_handler<account_t>& handler, - const std::string& sort_string) -{ - walk_accounts(account, handler, sort_string); -} - -void export_walk() -{ - typedef item_handler<transaction_t> xact_handler_t; - - scope().attr("TRANSACTION_HANDLED") = TRANSACTION_HANDLED; - scope().attr("TRANSACTION_TO_DISPLAY") = TRANSACTION_TO_DISPLAY; - scope().attr("TRANSACTION_DISPLAYED") = TRANSACTION_DISPLAYED; - scope().attr("TRANSACTION_NO_TOTAL") = TRANSACTION_NO_TOTAL; - - class_< transaction_xdata_t > ("TransactionXData") - .def_readwrite("total", &transaction_xdata_t::total) - .def_readwrite("index", &transaction_xdata_t::index) - .def_readwrite("dflags", &transaction_xdata_t::dflags) - ; - - def("transaction_has_xdata", transaction_has_xdata); - def("transaction_xdata", transaction_xdata, return_internal_reference<1>()); - def("clear_transactions_xdata", clear_transactions_xdata); - - class_< xact_handler_t, item_handler_wrap<transaction_t> > - ("TransactionHandler") - .def(init<xact_handler_t *>()) - - .def("flush", &xact_handler_t::flush, - &item_handler_wrap<transaction_t>::default_flush) - .def("__call__", &xact_handler_t::operator(), - &item_handler_wrap<transaction_t>::default_call) - ; - - class_< ignore_transactions, bases<xact_handler_t> > - ("IgnoreTransactions") - .def("flush", &xact_handler_t::flush) - .def("__call__", &ignore_transactions::operator()); - ; - - class_< set_account_value, bases<xact_handler_t> > ("SetAccountValue") - .def(init<xact_handler_t *>()[with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &set_account_value::operator()); - ; - - class_< sort_transactions, bases<xact_handler_t> > - ("SortTransactions", init<xact_handler_t *, const value_expr_t *>() - [with_custodian_and_ward<1, 2>()]) - .def(init<xact_handler_t *, const std::string&>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &sort_transactions::flush) - .def("__call__", &sort_transactions::operator()); - ; - - class_< filter_transactions, bases<xact_handler_t> > - ("FilterTransactions", init<xact_handler_t *, std::string>() - [with_custodian_and_ward<1, 2>()]) - .def(init<xact_handler_t *, const std::string&>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &filter_transactions::operator()); - ; - - class_< calc_transactions, bases<xact_handler_t> > - ("CalcTransactions", init<xact_handler_t *, optional<bool> >() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &calc_transactions::operator()); - ; - - class_< collapse_transactions, bases<xact_handler_t> > - ("CollapseTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &collapse_transactions::flush) - .def("__call__", &collapse_transactions::operator()); - ; - - class_< changed_value_transactions, bases<xact_handler_t> > - ("ChangeValueTransactions", init<xact_handler_t *, bool>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &changed_value_transactions::flush) - .def("__call__", &changed_value_transactions::operator()); - ; - - class_< subtotal_transactions, bases<xact_handler_t> > - ("SubtotalTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", subtotal_transactions_flush) - .def("__call__", &subtotal_transactions::operator()); - ; - - class_< interval_transactions, bases<xact_handler_t> > - ("IntervalTransactions", init<xact_handler_t *, interval_t>() - [with_custodian_and_ward<1, 2>()]) - .def(init<xact_handler_t *, const std::string&>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &interval_transactions::operator()); - ; - - class_< dow_transactions, bases<xact_handler_t> > - ("DowTransactions", init<xact_handler_t *>() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &dow_transactions::flush) - .def("__call__", &dow_transactions::operator()); - ; - - class_< related_transactions, bases<xact_handler_t> > - ("RelatedTransactions", init<xact_handler_t *, optional<bool> >() - [with_custodian_and_ward<1, 2>()]) - .def("flush", &xact_handler_t::flush) - .def("__call__", &related_transactions::operator()); - ; - - def("walk_entries", py_walk_entries); - def("walk_transactions", py_walk_transactions); - - typedef item_handler<account_t> account_handler_t; - - scope().attr("ACCOUNT_TO_DISPLAY") = ACCOUNT_TO_DISPLAY; - scope().attr("ACCOUNT_DISPLAYED") = ACCOUNT_DISPLAYED; - - class_< account_xdata_t > ("AccountXData") - .def_readwrite("value", &account_xdata_t::value) - .def_readwrite("total", &account_xdata_t::total) - .def_readwrite("count", &account_xdata_t::count) - .def_readwrite("subcount", &account_xdata_t::subcount) - .def_readwrite("dflags", &account_xdata_t::dflags) - ; - - def("account_has_xdata", account_has_xdata); - def("account_xdata", account_xdata, return_internal_reference<1>()); - def("clear_accounts_xdata", clear_accounts_xdata); - - class_< account_handler_t, item_handler_wrap<account_t> > ("AccountHandler") - .def(init<account_handler_t *>()) - - .def("flush", &account_handler_t::flush, - &item_handler_wrap<account_t>::default_flush) - .def("__call__", &account_handler_t::operator(), - &item_handler_wrap<account_t>::default_call) - ; - - def("sum_accounts", sum_accounts); - def("walk_accounts", py_walk_accounts_1); - def("walk_accounts", py_walk_accounts_2); - def("walk_accounts", py_walk_accounts_3); -} - -#endif // USE_BOOST_PYTHON |