summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2006-03-19 23:16:31 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 02:41:31 -0400
commitc8ebf53ed88210f5ff76ed32a0e7980bf735e3dc (patch)
tree4957d2cd05043f740f9b7b94427b4f6bcacf7aaf
parent32bdfe20d98f1c8e6c0aabe9b26f0507326d2baa (diff)
downloadfork-ledger-c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc.tar.gz
fork-ledger-c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc.tar.bz2
fork-ledger-c8ebf53ed88210f5ff76ed32a0e7980bf735e3dc.zip
*** empty log message ***
-rw-r--r--amount.cc77
-rw-r--r--amount.h24
-rw-r--r--config.cc96
-rw-r--r--config.h4
-rw-r--r--walk.cc3
-rw-r--r--walk.h58
6 files changed, 156 insertions, 106 deletions
diff --git a/amount.cc b/amount.cc
index d0cd5ef9..2040ffa8 100644
--- a/amount.cc
+++ b/amount.cc
@@ -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
{
diff --git a/amount.h b/amount.h
index c9ea7948..b0712ca3 100644
--- a/amount.h
+++ b/amount.h
@@ -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) {
diff --git a/config.cc b/config.cc
index 85db5a7c..278da258 100644
--- a/config.cc
+++ b/config.cc
@@ -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 },
diff --git a/config.h b/config.h
index 2758d5de..83248296 100644
--- a/config.h
+++ b/config.h
@@ -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);
diff --git a/walk.cc b/walk.cc
index a91bf189..3a8ce640 100644
--- a/walk.cc
+++ b/walk.cc
@@ -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;
}
diff --git a/walk.h b/walk.h
index 6da2e9d2..505d27a7 100644
--- a/walk.h
+++ b/walk.h
@@ -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);