summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-02-12 20:45:33 -0400
committerJohn Wiegley <johnw@newartisans.com>2009-02-12 20:45:33 -0400
commit092542a3bf056fac545f4b5a1062195569561fd3 (patch)
treef854942e66033567e47c8f227c357ef59daa7866
parente0e181d2af4aff5ac6c253fe25737bf93bfb6996 (diff)
downloadfork-ledger-092542a3bf056fac545f4b5a1062195569561fd3.tar.gz
fork-ledger-092542a3bf056fac545f4b5a1062195569561fd3.tar.bz2
fork-ledger-092542a3bf056fac545f4b5a1062195569561fd3.zip
Sorting expr now uses "-" to indicate descending
For example: -S payee,-date sorts 1) ascending by payee, then 2) descending by date.
-rw-r--r--src/account.h7
-rw-r--r--src/compare.cc68
-rw-r--r--src/compare.h11
-rw-r--r--src/value.cc21
-rw-r--r--src/value.h11
-rw-r--r--src/xact.h7
6 files changed, 79 insertions, 46 deletions
diff --git a/src/account.h b/src/account.h
index 24414403..494c25a2 100644
--- a/src/account.h
+++ b/src/account.h
@@ -126,12 +126,13 @@ class account_t : public scope_t
value_t value;
value_t total;
- value_t sort_value;
std::size_t count; // xacts counted toward amount
std::size_t total_count; // xacts counted toward total
std::size_t virtuals;
uint_least8_t dflags;
+ std::list<sort_value_t> sort_values;
+
xdata_t()
: supports_flags<>(), count(0), total_count(0),
virtuals(0), dflags(0)
@@ -142,11 +143,11 @@ class account_t : public scope_t
: supports_flags<>(other.flags()),
value(other.value),
total(other.total),
- sort_value(other.sort_value),
count(other.count),
total_count(other.total_count),
virtuals(other.virtuals),
- dflags(other.dflags)
+ dflags(other.dflags),
+ sort_values(other.sort_values)
{
TRACE_CTOR(account_t::xdata_t, "copy");
}
diff --git a/src/compare.cc b/src/compare.cc
index f34d5aa8..08f4e74c 100644
--- a/src/compare.cc
+++ b/src/compare.cc
@@ -30,38 +30,41 @@
*/
#include "compare.h"
+#include "op.h"
namespace ledger {
-bool value_is_less_than(const value_t& left, const value_t& right)
-{
- if (left.is_sequence()) {
- assert(right.is_sequence());
-
- const value_t::sequence_t& left_seq(left.as_sequence());
- value_t::sequence_t::const_iterator left_iter = left_seq.begin();
-
- const value_t::sequence_t& right_seq(right.as_sequence());
- value_t::sequence_t::const_iterator right_iter = right_seq.begin();
-
- while (left_iter != left_seq.end() &&
- right_iter != right_seq.end()) {
- if (*left_iter < *right_iter)
- return true;
- else if (*left_iter > *right_iter)
- return false;
- left_iter++; right_iter++;
+namespace {
+ template <typename T>
+ void push_sort_value(std::list<sort_value_t>& sort_values,
+ expr_t::ptr_op_t node, T * scope)
+ {
+ if (node->kind == expr_t::op_t::O_COMMA) {
+ push_sort_value(sort_values, node->left(), scope);
+ push_sort_value(sort_values, node->right(), scope);
}
+ else {
+ bool inverted = false;
- assert(left_iter == left_seq.end());
- assert(right_iter == right_seq.end());
+ if (node->kind == expr_t::op_t::O_NEG) {
+ inverted = true;
+ node = node->left();
+ }
- return true;
- } else {
- return left < right;
+ sort_values.push_back(sort_value_t());
+ sort_values.back().inverted = inverted;
+ sort_values.back().value = expr_t(node).calc(*scope).reduced();
+ }
}
}
+template <typename T>
+void compare_items<T>::find_sort_values(std::list<sort_value_t>& sort_values,
+ T * scope)
+{
+ push_sort_value(sort_values, sort_order.get_op(), scope);
+}
+
template <>
bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right)
{
@@ -70,24 +73,17 @@ bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right)
xact_t::xdata_t& lxdata(left->xdata());
if (! lxdata.has_flags(XACT_EXT_SORT_CALC)) {
- lxdata.sort_value = sort_order.calc(*left);
- lxdata.sort_value.reduce();
+ find_sort_values(lxdata.sort_values, left);
lxdata.add_flags(XACT_EXT_SORT_CALC);
}
xact_t::xdata_t& rxdata(right->xdata());
if (! rxdata.has_flags(XACT_EXT_SORT_CALC)) {
- rxdata.sort_value = sort_order.calc(*right);
- rxdata.sort_value.reduce();
+ find_sort_values(rxdata.sort_values, right);
rxdata.add_flags(XACT_EXT_SORT_CALC);
}
- DEBUG("ledger.walk.compare_items_xact",
- "lxdata.sort_value = " << lxdata.sort_value);
- DEBUG("ledger.walk.compare_items_xact",
- "rxdata.sort_value = " << rxdata.sort_value);
-
- return value_is_less_than(lxdata.sort_value, rxdata.sort_value);
+ return value_is_less_than(lxdata.sort_values, rxdata.sort_values);
}
template <>
@@ -98,17 +94,17 @@ bool compare_items<account_t>::operator()(account_t * left, account_t * right)
account_t::xdata_t& lxdata(left->xdata());
if (! lxdata.has_flags(ACCOUNT_EXT_SORT_CALC)) {
- lxdata.sort_value = sort_order.calc(*left);
+ find_sort_values(lxdata.sort_values, left);
lxdata.add_flags(ACCOUNT_EXT_SORT_CALC);
}
account_t::xdata_t& rxdata(right->xdata());
if (! rxdata.has_flags(ACCOUNT_EXT_SORT_CALC)) {
- rxdata.sort_value = sort_order.calc(*right);
+ find_sort_values(rxdata.sort_values, right);
rxdata.add_flags(ACCOUNT_EXT_SORT_CALC);
}
- return value_is_less_than(lxdata.sort_value, rxdata.sort_value);
+ return value_is_less_than(lxdata.sort_values, rxdata.sort_values);
}
} // namespace ledger
diff --git a/src/compare.h b/src/compare.h
index 70b44ed3..e4d68aa2 100644
--- a/src/compare.h
+++ b/src/compare.h
@@ -74,17 +74,20 @@ public:
~compare_items() throw() {
TRACE_DTOR(compare_items);
}
+
+ void find_sort_values(std::list<sort_value_t>& sort_values, T * scope);
+
bool operator()(T * left, T * right);
};
-bool value_is_less_than(const value_t& left, const value_t& right);
+sort_value_t calc_sort_value(const expr_t::ptr_op_t op);
template <typename T>
bool compare_items<T>::operator()(T * left, T * right)
{
- assert(left);
- assert(right);
- return sort_order.calc(*left) < sort_order.calc(*right);
+ assert(left); assert(right);
+ return value_is_less_than(find_sort_values(left),
+ find_sort_values(right));
}
template <>
diff --git a/src/value.cc b/src/value.cc
index 550ce8c7..8f9b3937 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1409,4 +1409,25 @@ bool value_t::valid() const
return true;
}
+bool value_is_less_than(const std::list<sort_value_t>& left_values,
+ const std::list<sort_value_t>& right_values)
+{
+ std::list<sort_value_t>::const_iterator left_iter = left_values.begin();
+ std::list<sort_value_t>::const_iterator right_iter = right_values.begin();
+
+ while (left_iter != left_values.end() &&
+ right_iter != right_values.end()) {
+ if ((*left_iter).value < (*right_iter).value)
+ return ! (*left_iter).inverted;
+ else if ((*left_iter).value > (*right_iter).value)
+ return (*left_iter).inverted;
+ left_iter++; right_iter++;
+ }
+
+ assert(left_iter == left_values.end());
+ assert(right_iter == right_values.end());
+
+ return true;
+}
+
} // namespace ledger
diff --git a/src/value.h b/src/value.h
index 049d3d01..c84f507c 100644
--- a/src/value.h
+++ b/src/value.h
@@ -931,6 +931,17 @@ inline value_t& add_or_set_value(value_t& lhs, const T& rhs) {
return lhs;
}
+struct sort_value_t
+{
+ bool inverted;
+ value_t value;
+
+ sort_value_t() : inverted(false) {}
+};
+
+bool value_is_less_than(const std::list<sort_value_t>& left_values,
+ const std::list<sort_value_t>& right_values);
+
} // namespace ledger
#endif // _VALUE_H
diff --git a/src/xact.h b/src/xact.h
index ed9c630b..cb89b512 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -132,23 +132,24 @@ public:
#define XACT_EXT_MATCHES 0x80
value_t total;
- value_t sort_value;
value_t value;
date_t date;
account_t * account;
void * ptr;
+ std::list<sort_value_t> sort_values;
+
xdata_t() : supports_flags<>(), account(NULL), ptr(NULL) {
TRACE_CTOR(xact_t::xdata_t, "");
}
xdata_t(const xdata_t& other)
: supports_flags<>(other.flags()),
total(other.total),
- sort_value(other.sort_value),
value(other.value),
date(other.date),
account(other.account),
- ptr(NULL)
+ ptr(NULL),
+ sort_values(other.sort_values)
{
TRACE_CTOR(xact_t::xdata_t, "copy");
}