Sorting expr now uses "-" to indicate descending

For example: -S payee,-date sorts 1) ascending by payee, then 2)
descending by date.
This commit is contained in:
John Wiegley 2009-02-12 20:45:33 -04:00
parent e0e181d2af
commit 092542a3bf
6 changed files with 79 additions and 46 deletions

View file

@ -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");
}

View file

@ -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

View file

@ -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 <>

View file

@ -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

View file

@ -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

View file

@ -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");
}