diff options
-rw-r--r-- | datetime.cc | 6 | ||||
-rw-r--r-- | datetime.h | 13 | ||||
-rw-r--r-- | format.cc | 1 | ||||
-rw-r--r-- | main.cc | 83 | ||||
-rw-r--r-- | walk.cc | 2 | ||||
-rw-r--r-- | walk.h | 83 |
6 files changed, 126 insertions, 62 deletions
diff --git a/datetime.cc b/datetime.cc index 19f54f92..71393ebf 100644 --- a/datetime.cc +++ b/datetime.cc @@ -29,6 +29,12 @@ static const char * formats[] = { NULL }; +std::time_t interval_t::increment(const std::time_t moment) +{ + // jww (2004-08-11): NYI + return moment + seconds; +} + bool parse_date_mask(const char * date_str, struct std::tm * result) { for (const char ** f = formats; *f; f++) { @@ -5,6 +5,19 @@ namespace ledger { +struct interval_t +{ + unsigned long years; + unsigned long months; + unsigned long seconds; + + interval_t(unsigned long _seconds, unsigned long _months, + unsigned long _years) + : years(_years), months(_months), seconds(_seconds) {} + + std::time_t increment(const std::time_t); +}; + extern bool parse_date_mask(const char * date_str, struct std::tm * result); extern bool parse_date(const char * date_str, std::time_t * result, @@ -116,6 +116,7 @@ element_t * format_t::parse_elements(const std::string& fmt) case 'd': current->type = element_t::DATE_STRING; + // jww (2004-08-10): allow this to be changed current->chars = "%Y/%m/%d"; break; @@ -174,8 +174,8 @@ int main(int argc, char * argv[]) bool show_inverted = false; bool show_empty = false; - bool show_commodities_revalued = false; - bool show_commodities_revalued_only = false; + bool show_revalued = false; + bool show_revalued_only = false; #ifdef DEBUG_ENABLED if (char * p = std::getenv("DEBUG_FILE")) { @@ -362,15 +362,15 @@ int main(int argc, char * argv[]) break; case 'V': - show_commodities_revalued = true; + show_revalued = true; value_expr = "v"; total_expr = "V"; break; case 'G': - show_commodities_revalued = - show_commodities_revalued_only = true; + show_revalued = + show_revalued_only = true; value_expr = "c"; total_expr = "G"; @@ -615,37 +615,62 @@ int main(int argc, char * argv[]) handle_transaction(*i, formatter, xact_display_flags); } else { - std::auto_ptr<item_handler<transaction_t> > - formatter(new format_transactions(std::cout, format, nformat)); + std::auto_ptr<item_handler<transaction_t> > formatter; + // Stack up all the formatter needed to fulfills the user's + // requests. Some of these are order dependent, in terms of + // whether calc_transactions occurs before or after them. + + // format_transactions write each transaction received to the + // output stream. + formatter.reset(new format_transactions(std::cout, format, nformat)); + + // sort_transactions will sort all the transactions it sees, based + // on the `sort_order' value expression. + if (sort_order.get()) + formatter.reset(new sort_transactions(formatter.release(), + sort_order.get())); + + // filter_transactions will only pass through transactions + // matching the `display_predicate'. formatter.reset(new filter_transactions(formatter.release(), display_predicate)); - formatter.reset(new calc_transactions(formatter.release(), - show_inverted)); + + // calc_transactions computes the running total. When this + // appears will determine, for example, whether filtered + // transactions are included or excluded from the running total. + formatter.reset(new calc_transactions(formatter.release(), show_inverted)); + + // changed_value_transactions adds virtual transactions to the + // list to account for changes in market value of commodities, + // which otherwise would affect the running total unpredictably. + if (show_revalued) + formatter.reset(new changed_value_transactions(formatter.release() /*, + show_revalued_only*/)); + + // collapse_transactions causes entries with multiple transactions + // to appear as entries with a subtotaled transaction for each + // commodity used. if (! show_subtotals) formatter.reset(new collapse_transactions(formatter.release())); + + // subtotal_transactions combines all the transactions it receives + // into one subtotal entry, which has one transaction for each + // commodity in each account. + // + // interval_transactions is like subtotal_transactions, but it + // subtotals according to time intervals rather than totalling + // everything. if (show_expanded) formatter.reset(new subtotal_transactions(formatter.release())); -#if 0 - formatter.reset(new interval_transactions(formatter.release(), - 0, 0, 9676800)); -#endif - if (show_commodities_revalued) - formatter.reset(new changed_value_transactions(formatter.release())); - - if (! sort_order.get()) { - walk_entries(journal->entries.begin(), journal->entries.end(), - *formatter.get(), predicate, xact_display_flags); - } else { - transactions_deque transactions_pool; - collect_transactions handler(transactions_pool); - walk_entries(journal->entries.begin(), journal->entries.end(), - handler, predicate, xact_display_flags); - std::stable_sort(transactions_pool.begin(), transactions_pool.end(), - compare_items<transaction_t>(sort_order.get())); - walk_transactions(transactions_pool.begin(), transactions_pool.end(), - *formatter.get()); - } + else if (0) + formatter.reset(new interval_transactions(formatter.release(), 0, + interval_t(9676800, 0, 0))); + + // Once the filters are chained, walk `journal's entries and start + // feeding each transaction that matches `predicate' to the chain. + walk_entries(journal->entries.begin(), journal->entries.end(), + *formatter.get(), predicate, xact_display_flags); } // Save the cache, if need be @@ -92,7 +92,7 @@ void changed_value_transactions::operator()(transaction_t * xact) void subtotal_transactions::flush() { entry_t * entry = new entry_t; - entry->date = start; + entry->date = start; char buf[256]; // jww (2004-08-10): allow for a format string here @@ -4,6 +4,7 @@ #include "ledger.h" #include "balance.h" #include "valexpr.h" +#include "datetime.h" #include <iostream> #include <deque> @@ -50,26 +51,43 @@ struct ignore_transaction : public item_handler<transaction_t> virtual void operator()(transaction_t * xact) {} }; -class collect_transactions : public item_handler<transaction_t> +class sort_transactions : public item_handler<transaction_t> { - transactions_deque& transactions; + transactions_deque transactions; + const node_t * sort_order; + + item_handler<transaction_t> * handler; public: - collect_transactions(transactions_deque& _transactions) - : transactions(_transactions) {} + sort_transactions(item_handler<transaction_t> * _handler, + const node_t * _sort_order) + : sort_order(_sort_order), handler(_handler) {} + + virtual ~sort_transactions() { + flush(); + handler->flush(); + delete handler; + } + + virtual void 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++) + (*handler)(*i); + + transactions.clear(); + + handler->flush(); + } virtual void operator()(transaction_t * xact) { transactions.push_back(xact); } }; -inline void sort_transactions(transactions_deque& transactions, - const node_t * sort_order) -{ - std::stable_sort(transactions.begin(), transactions.end(), - compare_items<transaction_t>(sort_order)); -} - class filter_transactions : public item_handler<transaction_t> { item_predicate<transaction_t> pred; @@ -205,6 +223,7 @@ typedef std::pair<account_t *, balance_pair_t> balances_pair; class subtotal_transactions : public item_handler<transaction_t> { + protected: std::time_t start; std::time_t finish; balances_map balances; @@ -238,39 +257,39 @@ class subtotal_transactions : public item_handler<transaction_t> virtual void operator()(transaction_t * xact); }; -class interval_transactions : public item_handler<transaction_t> +class interval_transactions : public subtotal_transactions { - std::time_t start; - unsigned long months; - unsigned long seconds; + std::time_t begin; + interval_t interval; transaction_t * last_xact; - item_handler<transaction_t> * handler; - public: interval_transactions(item_handler<transaction_t> * _handler, - std::time_t _start, unsigned long _months, - unsigned long _seconds) - : start(_start), months(_months), seconds(_seconds), - last_xact(NULL), handler(_handler) {} + std::time_t _begin, const interval_t& _interval) + : subtotal_transactions(_handler), + begin(_begin), interval(_interval), last_xact(NULL) {} virtual ~interval_transactions() { - flush(); + start = begin; + finish = interval.increment(begin); } - virtual void flush() { - handler->flush(); - } virtual void operator()(transaction_t * xact) { - if (std::difftime(xact->entry->date, start + seconds) > 0) { - if (last_xact) - handler->flush(); - start += seconds; - while (std::difftime(xact->entry->date, start + seconds) > 0) - start += seconds; + if (std::difftime(xact->entry->date, interval.increment(begin)) > 0) { + if (last_xact) { + start = begin; + finish = interval.increment(begin); + flush(); + } + + begin = interval.increment(begin); + std::time_t temp; + while (std::difftime(xact->entry->date, + temp = interval.increment(begin)) > 0) + begin = temp; } - (*handler)(xact); + subtotal_transactions::operator()(xact); last_xact = xact; } |