diff options
-rw-r--r-- | src/account.h | 7 | ||||
-rw-r--r-- | src/compare.cc | 68 | ||||
-rw-r--r-- | src/compare.h | 11 | ||||
-rw-r--r-- | src/value.cc | 21 | ||||
-rw-r--r-- | src/value.h | 11 | ||||
-rw-r--r-- | src/xact.h | 7 |
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 @@ -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"); } |