From 7bf86bc48a564ffffa46461c15ae2ab34b258fe8 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 30 Sep 2003 00:09:43 +0000 Subject: *** empty log message *** --- balance.cc | 196 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 121 insertions(+), 75 deletions(-) (limited to 'balance.cc') diff --git a/balance.cc b/balance.cc index b3ecf593..fd09bae1 100644 --- a/balance.cc +++ b/balance.cc @@ -1,10 +1,7 @@ -#include -#include +#include "ledger.h" #include // Perl regular expression library -#include "ledger.h" - namespace ledger { ////////////////////////////////////////////////////////////////////// @@ -12,10 +9,38 @@ namespace ledger { // Balance report. // -void report_balances(std::ostream& out, std::vector& ledger, - bool show_children, bool show_empty) +static inline bool matches(const std::list& regexps, + const std::string& str) { + for (std::list::const_iterator r = regexps.begin(); + r != regexps.end(); + r++) { + int ovec[3]; + if (pcre_exec(*r, NULL, str.c_str(), str.length(), 0, 0, ovec, 3) >= 0) + return true; + } + + return false; +} + +void report_balances(int argc, char *argv[], std::ostream& out) { -#if 0 + bool show_current = false; + bool show_cleared = false; + bool show_children = false; + bool show_empty = false; + bool no_subtotals = false; + + int c; + while (-1 != (c = getopt(argc, argv, "cCsSn"))) { + switch (char(c)) { + case 'c': show_current = true; break; + case 'C': show_cleared = true; break; + case 's': show_children = true; break; + case 'S': show_empty = true; break; + case 'n': no_subtotals = true; break; + } + } + // Compile the list of specified regular expressions, which can be // specified on the command line, or using an include/exclude file. @@ -26,97 +51,118 @@ void report_balances(std::ostream& out, std::vector& ledger, int erroffset; pcre * re = pcre_compile(argv[optind], PCRE_CASELESS, &error, &erroffset, NULL); - assert(re); - regexps.push_back(re); + if (! re) + std::cerr << "Warning: Failed to compile regexp: " << argv[optind] + << std::endl; + else + regexps.push_back(re); } -#endif - // The balance of all accounts must equal zero - totals future_balance; - totals current_balance; - totals cleared_balance; + // Walk through all of the ledger entries, computing the account + // totals + + std::map balances; + + std::time_t now = std::time(NULL); + + for (ledger_iterator i = ledger.begin(); i != ledger.end(); i++) { + for (std::list::iterator x = (*i)->xacts.begin(); + x != (*i)->xacts.end(); + x++) { + account * acct = (*x)->acct; + if (! regexps.empty() && ! matches(regexps, acct->name)) + continue; + + while (acct) { + totals * balance = NULL; + + std::map::iterator t = balances.find(acct); + if (t == balances.end()) { + balance = new totals; + balances.insert(std::pair(acct, balance)); + } else { + balance = (*t).second; + } + + if (show_current) { + if (difftime((*i)->date, now) < 0) + balance->credit((*x)->cost); + } + else if (show_cleared) { + if ((*i)->cleared) + balance->credit((*x)->cost); + } + else { + balance->credit((*x)->cost); + } + + if (no_subtotals) + acct = NULL; + else + acct = acct->parent; + } + } + } + + // Print out the balance report header + + std::string which = "Future"; + if (show_current) + which = "Current"; + else if (show_cleared) + which = "Cleared"; std::cout.width(10); - std::cout << std::right << "Future" << " "; - std::cout.width(10); - std::cout << std::right << "Current" << " "; - std::cout.width(10); - std::cout << std::right << "Cleared" << std::endl; + std::cout << std::right << which << std::endl; - for (accounts_iterator i = accounts.begin(); - i != accounts.end(); - i++) { - if (! show_empty && ! (*i).second->future) + // Walk through the accounts, given the balance report for each + + totals total_balance; + + for (accounts_iterator i = accounts.begin(); i != accounts.end(); i++) { + account * acct = (*i).second; + + if (! regexps.empty() && ! matches(regexps, acct->name)) continue; int depth = 0; - account * acct = (*i).second; - while (acct->parent) { + for (account * a = acct; a; a = a->parent) depth++; - acct = acct->parent; - } -#if 0 - if (! regexps.empty()) { - bool matches = false; - for (std::list::iterator r = regexps.begin(); - r != regexps.end(); - r++) { - int ovector[30]; - if (pcre_exec(*r, NULL, (*i).first.c_str(), (*i).first.length(), - 0, 0, ovector, 30) >= 0) { - matches = true; - break; - } - } + if (! show_children && depth) + continue; - if (! matches) - continue; - } - else -#endif - if (! show_children && depth) { + totals * balance = balances[acct]; + + if (! show_empty && ! *balance) continue; - } std::cout.width(10); - std::cout << (*i).second->future << " "; - std::cout.width(10); - std::cout << (*i).second->current << " "; - std::cout.width(10); - std::cout << (*i).second->cleared << " "; + std::cout << *balance << " "; + + total_balance.credit(*balance); if (depth) { while (--depth >= 0) std::cout << " "; - std::cout << (*i).second->name << std::endl; + std::cout << acct->name << std::endl; } else { - std::cout << (*i).first << std::endl; - -#if 0 - if (regexps.empty()) { -#endif - future_balance.credit((*i).second->future); - current_balance.credit((*i).second->current); - cleared_balance.credit((*i).second->cleared); -#if 0 - } -#endif + std::cout << *acct << std::endl; } } -#if 0 - if (regexps.empty()) { -#endif - std::cout.width(10); - std::cout << std::right << future_balance << " "; - std::cout.width(10); - std::cout << std::right << current_balance << " "; - std::cout.width(10); - std::cout << std::right << cleared_balance << std::endl; -#if 0 + // Print the total of all the balances shown + + std::cout.width(10); + std::cout << std::right << total_balance << std::endl; + + // Free up temporary variables created on the heap + + for (std::map::iterator i = balances.begin(); + i != balances.end(); + i++) { + delete (*i).second; } -#endif } } // namespace ledger -- cgit v1.2.3