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:
parent
e0e181d2af
commit
092542a3bf
6 changed files with 79 additions and 46 deletions
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <>
|
||||
|
|
|
|||
21
src/value.cc
21
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
|
||||
|
|
|
|||
11
src/value.h
11
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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue