#ifndef _CONSTRAINT_H #define _CONSTRAINT_H #include "ledger.h" #include "expr.h" #include "item.h" template class constrained_iterator { ForwardIterator iter, end; const Constraint& constraint; constrained_iterator& operator=(const constrained_iterator&); public: constrained_iterator(ForwardIterator begin, ForwardIterator _end, const Constraint& _constraint) : iter(begin), end(_end), constraint(_constraint) { skip_nonmatching(); } constrained_iterator(const constrained_iterator& other) : iter(other.iter), end(other.end), constraint(other.constraint) {} constrained_iterator operator++() const { ForwardIterator temp = iter; temp++; return constrained_iterator(temp, end); } constrained_iterator& operator++(int) { iter++; skip_nonmatching(); return *this; } bool operator==(ForwardIterator other) const { return iter == other; } bool operator!=(ForwardIterator other) const { return ! (*this == other); } ValueType operator*() const { return *iter; } void skip_nonmatching() { bool failed; do { if (iter == end) return; failed = false; if (! constraint(*iter)) { failed = true; iter++; } } while (failed); } }; namespace ledger { class constraints_t { public: bool show_expanded; bool show_related; bool show_inverted; bool show_subtotals; bool show_empty; node_t * predicate; explicit constraints_t() { show_expanded = false; show_related = false; show_inverted = false; show_subtotals = true; show_empty = false; predicate = NULL; } ~constraints_t() { if (predicate) delete predicate; } bool operator ()(const transaction_t * xact) const { if (! predicate) { return true; } else { item_t temp; temp.date = xact->entry->date; temp.payee = xact->entry->payee; temp.account = xact->account; return predicate->compute(&temp); } } bool operator ()(const entry_t * entry) const { if (! predicate) { return true; } else { item_t temp; temp.date = entry->date; temp.payee = entry->payee; // Although there may be conflicting account masks for the whole // set of transactions -- for example, /rent/&!/expenses/, which // might match one by not another transactions -- we let the // entry through if at least one of the transactions meets the // criterion for (transactions_list::const_iterator i = entry->transactions.begin(); i != entry->transactions.end(); i++) { temp.account = (*i)->account; if (predicate->compute(&temp)) return true; } return false; } } bool operator ()(const item_t * item) const { return ! predicate || predicate->compute(item); } }; typedef constrained_iterator constrained_transactions_list_const_iterator; typedef constrained_iterator constrained_transactions_list_iterator; typedef constrained_iterator constrained_entries_list_const_iterator; typedef constrained_iterator constrained_entries_list_iterator; typedef constrained_iterator constrained_items_deque_const_iterator; typedef constrained_iterator constrained_items_deque_iterator; } // namespace ledger #endif // _CONSTRAINT_H