diff options
Diffstat (limited to 'valexpr.h')
-rw-r--r-- | valexpr.h | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/valexpr.h b/valexpr.h new file mode 100644 index 00000000..938ce27d --- /dev/null +++ b/valexpr.h @@ -0,0 +1,202 @@ +#ifndef _VALEXPR_H +#define _VALEXPR_H + +#include "journal.h" +#include "value.h" +#include "error.h" +#include "mask.h" + +#include <memory> + +namespace ledger { + +struct details_t +{ + const entry_t * entry; + const transaction_t * xact; + const account_t * account; + + details_t(const entry_t& _entry) + : entry(&_entry), xact(NULL), account(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor details_t"); + } + details_t(const transaction_t& _xact) + : entry(_xact.entry), xact(&_xact), account(_xact.account) { + DEBUG_PRINT("ledger.memory.ctors", "ctor details_t"); + } + details_t(const account_t& _account) + : entry(NULL), xact(NULL), account(&_account) { + DEBUG_PRINT("ledger.memory.ctors", "ctor details_t"); + } +#ifdef DEBUG_ENABLED + ~details_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor details_t"); + } +#endif +}; + +struct value_expr_t +{ + enum kind_t { + // Constants + CONSTANT_I, + CONSTANT_T, + CONSTANT_A, + + // Item details + AMOUNT, + COST, + DATE, + CLEARED, + REAL, + ACTUAL, + INDEX, + DEPTH, + + // Item totals + COUNT, + TOTAL, + COST_TOTAL, + + // Relating to format_t + VALUE_EXPR, + TOTAL_EXPR, + + // Functions + F_PARENT, + F_ARITH_MEAN, + F_VALUE, + F_NEG, + F_ABS, + F_STRIP, + F_PAYEE_MASK, + F_ACCOUNT_MASK, + F_SHORT_ACCOUNT_MASK, + F_INTERP_FUNC, + + // Binary operators + O_ADD, + O_SUB, + O_MUL, + O_DIV, + O_EQ, + O_LT, + O_LTE, + O_GT, + O_GTE, + O_NOT, + O_AND, + O_OR, + O_QUES, + O_COL, + O_ARG, + + LAST + }; + + kind_t kind; + value_expr_t * left; + value_expr_t * right; + + union { + std::time_t constant_t; + long constant_i; + }; + std::string constant_s; + amount_t constant_a; + mask_t * mask; + + value_expr_t(const kind_t _kind) + : kind(_kind), left(NULL), right(NULL), mask(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t"); + } + + ~value_expr_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr_t"); + if (mask) delete mask; + if (left) delete left; + if (right) delete right; + } + + void compute(value_t& result, const details_t& details) const; +}; + +extern std::auto_ptr<value_expr_t> amount_expr; +extern std::auto_ptr<value_expr_t> total_expr; + +inline void compute_amount(value_t& result, const details_t& details) { + if (amount_expr.get()) + amount_expr->compute(result, details); +} + +inline void compute_total(value_t& result, const details_t& details) { + if (total_expr.get()) + total_expr->compute(result, details); +} + +value_expr_t * parse_value_expr(std::istream& in, + const bool partial = false); + +inline value_expr_t * parse_value_expr(const char * p, + const bool partial = false) { + std::istringstream stream(p); + return parse_value_expr(stream, partial); +} + +inline value_expr_t * parse_value_expr(const std::string& str, + const bool partial = false) { + return parse_value_expr(str.c_str()); +} + +#ifdef DEBUG_ENABLED +void dump_value_expr(std::ostream& out, const value_expr_t * node); +#endif + +////////////////////////////////////////////////////////////////////// + +template <typename T> +class item_predicate +{ + const value_expr_t * predicate; + bool allocated; + + public: + item_predicate(const std::string& _predicate) + : predicate(NULL), allocated(false) { + DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>"); + if (! _predicate.empty()) { + try { + predicate = parse_value_expr(_predicate); + allocated = true; + } + catch (value_expr_error& err) { + throw value_expr_error(std::string("In predicate '") + + _predicate + "': " + err.what()); + } + } + } + item_predicate(const value_expr_t * _predicate = NULL) + : predicate(_predicate), allocated(false) { + DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>"); + } + + ~item_predicate() { + DEBUG_PRINT("ledger.memory.dtors", "dtor item_predicate<T>"); + if (predicate && allocated) + delete predicate; + } + + bool operator()(const T& item) const { + if (predicate) { + value_t result; + predicate->compute(result, details_t(item)); + return result; + } else { + return true; + } + } +}; + +} // namespace ledger + +#endif // _VALEXPR_H |