diff options
author | John Wiegley <johnw@newartisans.com> | 2006-03-19 23:16:31 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 02:41:31 -0400 |
commit | c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc (patch) | |
tree | 4957d2cd05043f740f9b7b94427b4f6bcacf7aaf | |
parent | 32bdfe20d98f1c8e6c0aabe9b26f0507326d2baa (diff) | |
download | fork-ledger-c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc.tar.gz fork-ledger-c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc.tar.bz2 fork-ledger-c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc.zip |
*** empty log message ***
-rw-r--r-- | amount.cc | 77 | ||||
-rw-r--r-- | amount.h | 24 | ||||
-rw-r--r-- | config.cc | 96 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | walk.cc | 3 | ||||
-rw-r--r-- | walk.h | 58 |
6 files changed, 156 insertions, 106 deletions
@@ -496,39 +496,50 @@ int amount_t::sign() const return quantity ? mpz_sgn(MPZ(quantity)) : 0; } -// comparisons between amounts -#define AMOUNT_CMP_AMOUNT(OP) \ -bool amount_t::operator OP(const amount_t& amt) const \ -{ \ - if (! quantity) \ - return amt OP 0; \ - if (! amt.quantity) \ - return *this OP 0; \ - \ - if (commodity() && amt.commodity() && \ - commodity() != amt.commodity()) \ - return false; \ - \ - if (quantity->prec == amt.quantity->prec) { \ - return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) OP 0; \ - } \ - else if (quantity->prec < amt.quantity->prec) { \ - amount_t temp = *this; \ - temp._resize(amt.quantity->prec); \ - return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)) OP 0; \ - } \ - else { \ - amount_t temp = amt; \ - temp._resize(quantity->prec); \ - return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)) OP 0; \ - } \ -} - -AMOUNT_CMP_AMOUNT(<) -AMOUNT_CMP_AMOUNT(<=) -AMOUNT_CMP_AMOUNT(>) -AMOUNT_CMP_AMOUNT(>=) -AMOUNT_CMP_AMOUNT(==) +int amount_t::compare(const amount_t& amt) const +{ + if (! quantity) { + if (! amt.quantity) + return 0; + return - amt.sign(); + } + if (! amt.quantity) + return sign(); + + if (commodity() && amt.commodity() && + commodity() != amt.commodity()) + throw new amount_error + (std::string("Cannot compare amounts with different commodities: ") + + commodity().symbol() + " and " + amt.commodity().symbol()); + + if (quantity->prec == amt.quantity->prec) { + return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)); + } + else if (quantity->prec < amt.quantity->prec) { + amount_t temp = *this; + temp._resize(amt.quantity->prec); + return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)); + } + else { + amount_t temp = amt; + temp._resize(quantity->prec); + return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)); + } +} + +bool amount_t::operator==(const amount_t& amt) const +{ + if (commodity() != amt.commodity()) + return false; + return compare(amt) == 0; +} + +bool amount_t::operator!=(const amount_t& amt) const +{ + if (commodity() != amt.commodity()) + return true; + return compare(amt) != 0; +} amount_t::operator bool() const { @@ -202,16 +202,22 @@ class amount_t bool realzero() const; // comparisons between amounts - bool operator<(const amount_t& amt) const; - bool operator<=(const amount_t& amt) const; - bool operator>(const amount_t& amt) const; - bool operator>=(const amount_t& amt) const; - bool operator==(const amount_t& amt) const; - bool operator!=(const amount_t& amt) const { - if (commodity_ != amt.commodity_) - return true; - return ! (*this == amt); + int compare(const amount_t& amt) const; + + bool operator<(const amount_t& amt) const { + return compare(amt) < 0; + } + bool operator<=(const amount_t& amt) const { + return compare(amt) <= 0; } + bool operator>(const amount_t& amt) const { + return compare(amt) > 0; + } + bool operator>=(const amount_t& amt) const { + return compare(amt) >= 0; + } + bool operator==(const amount_t& amt) const; + bool operator!=(const amount_t& amt) const; template <typename T> void parse_num(T num) { @@ -163,6 +163,8 @@ void config_t::reset() keep_price = false; keep_date = false; keep_tag = false; + entry_sort = false; + sort_all = false; use_cache = false; cache_dirty = false; @@ -381,6 +383,9 @@ void config_t::process_options(const std::string& command, amount_t::keep_price = keep_price; amount_t::keep_date = keep_date; amount_t::keep_tag = keep_tag; + + if (! report_period.empty() && ! sort_all) + entry_sort = true; } item_handler<transaction_t> * @@ -451,7 +456,7 @@ config_t::chain_xact_handlers(const std::string& command, parse_date(reconcile_date.c_str(), &cutoff); ptrs.push_back(formatter = new reconcile_transactions - (formatter, value_t(reconcile_balance), cutoff)); + (formatter, value_t(reconcile_balance), cutoff)); } // filter_transactions will only pass through transactions @@ -463,9 +468,14 @@ config_t::chain_xact_handlers(const std::string& command, // sort_transactions will sort all the transactions it sees, based // on the `sort_order' value expression. - if (! sort_string.empty()) - ptrs.push_back(formatter = - new sort_transactions(formatter, sort_string)); + if (! sort_string.empty()) { + if (entry_sort) + ptrs.push_back(formatter = + new sort_entries(formatter, sort_string)); + else + ptrs.push_back(formatter = + new sort_transactions(formatter, sort_string)); + } // changed_value_transactions adds virtual transactions to the // list to account for changes in market value of commodities, @@ -480,37 +490,37 @@ config_t::chain_xact_handlers(const std::string& command, // commodity used. if (show_collapsed) ptrs.push_back(formatter = new collapse_transactions(formatter)); - } - // subtotal_transactions combines all the transactions it receives - // into one subtotal entry, which has one transaction for each - // commodity in each account. - // - // period_transactions is like subtotal_transactions, but it - // subtotals according to time periods rather than totalling - // everything. - // - // dow_transactions is like period_transactions, except that it - // reports all the transactions that fall on each subsequent day - // of the week. - if (show_subtotal && ! (command == "b" || command == "E")) - ptrs.push_back(formatter = - new subtotal_transactions(formatter, remember_components)); + // subtotal_transactions combines all the transactions it receives + // into one subtotal entry, which has one transaction for each + // commodity in each account. + // + // period_transactions is like subtotal_transactions, but it + // subtotals according to time periods rather than totalling + // everything. + // + // dow_transactions is like period_transactions, except that it + // reports all the transactions that fall on each subsequent day + // of the week. + if (show_subtotal) + ptrs.push_back(formatter = + new subtotal_transactions(formatter, remember_components)); - if (days_of_the_week) - ptrs.push_back(formatter = - new dow_transactions(formatter, remember_components)); - else if (by_payee) - ptrs.push_back(formatter = - new by_payee_transactions(formatter, remember_components)); + if (days_of_the_week) + ptrs.push_back(formatter = + new dow_transactions(formatter, remember_components)); + else if (by_payee) + ptrs.push_back(formatter = + new by_payee_transactions(formatter, remember_components)); - if (! report_period.empty()) { - ptrs.push_back(formatter = - new interval_transactions(formatter, - report_period, - report_period_sort, - remember_components)); - ptrs.push_back(formatter = new sort_transactions(formatter, "d")); + // interval_transactions groups transactions together based on a + // time period, such as weekly or monthly. + if (! report_period.empty()) { + ptrs.push_back(formatter = + new interval_transactions(formatter, report_period, + remember_components)); + ptrs.push_back(formatter = new sort_transactions(formatter, "d")); + } } // invert_transactions inverts the value of the transactions it @@ -1037,6 +1047,22 @@ OPT_BEGIN(sort, "S:") { config->sort_string = optarg; } OPT_END(sort); +OPT_BEGIN(sort_entries, "") { + config->sort_string = optarg; + config->entry_sort = true; +} OPT_END(sort_entries); + +OPT_BEGIN(sort_all, "") { + config->sort_string = optarg; + config->entry_sort = false; + config->sort_all = true; +} OPT_END(sort_all); + +OPT_BEGIN(period_sort, ":") { + config->sort_string = optarg; + config->entry_sort = true; +} OPT_END(period_sort); + OPT_BEGIN(related, "r") { config->show_related = true; } OPT_END(related); @@ -1096,10 +1122,6 @@ OPT_BEGIN(period, "p:") { } } OPT_END(period); -OPT_BEGIN(period_sort, ":") { - config->report_period_sort = optarg; -} OPT_END(period_sort); - OPT_BEGIN(daily, "") { if (config->report_period.empty()) config->report_period = "daily"; @@ -1392,6 +1414,8 @@ option_t config_options[CONFIG_OPTIONS_SIZE] = { { "related", 'r', false, opt_related, false }, { "set-price", '\0', true, opt_set_price, false }, { "sort", 'S', true, opt_sort, false }, + { "sort-all", '\0', true, opt_sort_all, false }, + { "sort-entries", '\0', true, opt_sort_entries, false }, { "subtotal", 's', false, opt_subtotal, false }, { "tail", '\0', true, opt_tail, false }, { "total", 'T', true, opt_total, false }, @@ -74,6 +74,8 @@ class config_t bool keep_price; bool keep_date; bool keep_tag; + bool entry_sort; + bool sort_all; config_t() { reset(); @@ -107,7 +109,7 @@ class config_t std::list<item_handler<transaction_t> *>& ptrs); }; -#define CONFIG_OPTIONS_SIZE 91 +#define CONFIG_OPTIONS_SIZE 93 extern option_t config_options[CONFIG_OPTIONS_SIZE]; void option_help(std::ostream& out); @@ -439,9 +439,6 @@ void interval_transactions::report_subtotal(const std::time_t moment) subtotal_transactions::report_subtotal(); - if (sorter) - sorter->post_accumulated_xacts(); - last_xact = NULL; } @@ -252,7 +252,7 @@ class sort_transactions : public item_handler<transaction_t> sort_transactions(item_handler<transaction_t> * handler, const value_expr_t * _sort_order) : item_handler<transaction_t>(handler), - sort_order(_sort_order) {} + sort_order(_sort_order->acquire()) {} sort_transactions(item_handler<transaction_t> * handler, const std::string& _sort_order) @@ -278,6 +278,35 @@ class sort_transactions : public item_handler<transaction_t> } }; +class sort_entries : public item_handler<transaction_t> +{ + sort_transactions sorter; + entry_t * last_entry; + + public: + sort_entries(item_handler<transaction_t> * handler, + const value_expr_t * _sort_order) + : sorter(handler, _sort_order) {} + + sort_entries(item_handler<transaction_t> * handler, + const std::string& _sort_order) + : sorter(handler, _sort_order) {} + + virtual void flush() { + sorter.flush(); + item_handler<transaction_t>::flush(); + } + + virtual void operator()(transaction_t& xact) { + if (last_entry && xact.entry != last_entry) + sorter.post_accumulated_xacts(); + + sorter(xact); + + last_entry = xact.entry; + } +}; + class filter_transactions : public item_handler<transaction_t> { item_predicate<transaction_t> pred; @@ -492,37 +521,18 @@ class interval_transactions : public subtotal_transactions transaction_t * last_xact; bool started; - sort_transactions * sorter; - public: interval_transactions(item_handler<transaction_t> * _handler, - const interval_t& _interval, - const value_expr_t * sort_order = NULL, + const interval_t& _interval, bool remember_components = false) : subtotal_transactions(_handler, remember_components), - interval(_interval), last_xact(NULL), started(false), - sorter(NULL) { - if (sort_order) { - sorter = new sort_transactions(handler, sort_order); - handler = sorter; - } - } + interval(_interval), last_xact(NULL), started(false) {} + interval_transactions(item_handler<transaction_t> * _handler, const std::string& _interval, - const std::string& sort_order = "", bool remember_components = false) : subtotal_transactions(_handler, remember_components), - interval(_interval), last_xact(NULL), started(false), - sorter(NULL) { - if (! sort_order.empty()) { - sorter = new sort_transactions(handler, sort_order); - handler = sorter; - } - } - virtual ~interval_transactions() { - if (sorter) - delete sorter; - } + interval(_interval), last_xact(NULL), started(false) {} void report_subtotal(const std::time_t moment = 0); |