diff options
-rw-r--r-- | amount.h | 18 | ||||
-rw-r--r-- | balance.cc | 10 | ||||
-rw-r--r-- | balance.h | 164 | ||||
-rw-r--r-- | config.cc | 1 | ||||
-rw-r--r-- | valexpr.cc | 65 | ||||
-rw-r--r-- | value.cc | 47 | ||||
-rw-r--r-- | value.h | 8 | ||||
-rw-r--r-- | walk.cc | 16 | ||||
-rw-r--r-- | walk.h | 3 |
9 files changed, 202 insertions, 130 deletions
@@ -73,7 +73,8 @@ class amount_t void clear_commodity() { commodity_ = NULL; } - amount_t base_amount() const; + amount_t base() const; + amount_t price() const; bool null() const { return ! quantity && ! commodity_; @@ -274,6 +275,9 @@ inline amount_t abs(const amount_t& amt) { return amt < 0 ? amt.negated() : amt; } +#define base_amount(amt) \ + ((! show_lots && amt.commodity().price) ? amt.base() : amt) + std::ostream& operator<<(std::ostream& out, const amount_t& amt); inline std::istream& operator>>(std::istream& in, amount_t& amt) { @@ -445,7 +449,7 @@ inline commodity_t& amount_t::commodity() const { return *commodity_; } -inline amount_t amount_t::base_amount() const { +inline amount_t amount_t::base() const { if (commodity_ && commodity_->price) { amount_t temp(*this); assert(commodity_->base); @@ -456,6 +460,16 @@ inline amount_t amount_t::base_amount() const { } } +inline amount_t amount_t::price() const { + if (commodity_ && commodity_->price) { + amount_t temp(*commodity_->price); + temp *= *this; + return temp; + } else { + return 0L; + } +} + class amount_error : public std::exception { std::string reason; public: @@ -34,18 +34,14 @@ balance_t balance_t::value(const std::time_t moment) const return temp; } -balance_t balance_t::factor_price() const +balance_t balance_t::price() const { balance_t temp; for (amounts_map::const_iterator i = amounts.begin(); i != amounts.end(); - i++) { - if ((*i).second.commodity().price) - temp += *((*i).second.commodity().price) * (*i).second; - else - temp += (*i).second; - } + i++) + temp += (*i).second.price(); return temp; } @@ -426,7 +426,7 @@ class balance_t amount_t amount(const commodity_t& commodity) const; balance_t value(const std::time_t moment) const; - balance_t factor_price() const; + balance_t price() const; void write(std::ostream& out, const int first_width, @@ -463,44 +463,57 @@ inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) { class balance_pair_t { public: - balance_t quantity; + balance_t quantity; + balance_t * price; balance_t * cost; // constructors - balance_pair_t() : cost(NULL) {} + balance_pair_t() : price(NULL), cost(NULL) {} balance_pair_t(const balance_pair_t& bal_pair) - : quantity(bal_pair.quantity), cost(NULL) { + : quantity(bal_pair.quantity), price(NULL), cost(NULL) { + if (bal_pair.price) + price = new balance_t(*bal_pair.price); if (bal_pair.cost) cost = new balance_t(*bal_pair.cost); } balance_pair_t(const balance_t& _quantity) - : quantity(_quantity), cost(NULL) {} + : quantity(_quantity), price(NULL), cost(NULL) {} balance_pair_t(const amount_t& _quantity) - : quantity(_quantity), cost(NULL) {} + : quantity(_quantity), price(NULL), cost(NULL) {} template <typename T> - balance_pair_t(T value) : quantity(value), cost(NULL) {} + balance_pair_t(T value) : quantity(value), price(NULL), cost(NULL) {} // destructor ~balance_pair_t() { - if (cost) - delete cost; + if (price) delete price; + if (cost) delete cost; } // assignment operator balance_pair_t& operator=(const balance_pair_t& bal_pair) { if (this != &bal_pair) { + if (price) { + delete price; + price = NULL; + } if (cost) { delete cost; cost = NULL; } quantity = bal_pair.quantity; + if (bal_pair.price) + price = new balance_t(*bal_pair.price); if (bal_pair.cost) cost = new balance_t(*bal_pair.cost); } return *this; } balance_pair_t& operator=(const balance_t& bal) { + if (price) { + delete price; + price = NULL; + } if (cost) { delete cost; cost = NULL; @@ -509,6 +522,10 @@ class balance_pair_t return *this; } balance_pair_t& operator=(const amount_t& amt) { + if (price) { + delete price; + price = NULL; + } if (cost) { delete cost; cost = NULL; @@ -518,6 +535,10 @@ class balance_pair_t } template <typename T> balance_pair_t& operator=(T value) { + if (price) { + delete price; + price = NULL; + } if (cost) { delete cost; cost = NULL; @@ -528,26 +549,29 @@ class balance_pair_t // in-place arithmetic balance_pair_t& operator+=(const balance_pair_t& bal_pair) { - if (bal_pair.cost && ! cost) - cost = new balance_t(quantity); - quantity += bal_pair.quantity; - if (cost) - *cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; + if (bal_pair.price) { + if (price) + *price += *bal_pair.price; + else + price = new balance_t(*bal_pair.price); + } + if (bal_pair.cost) { + if (cost) + *cost += *bal_pair.cost; + else + cost = new balance_t(*bal_pair.cost); + } return *this; } balance_pair_t& operator+=(const balance_t& bal) { quantity += bal; - if (cost) - *cost += bal; return *this; } balance_pair_t& operator+=(const amount_t& amt) { quantity += amt; - if (cost) - *cost += amt; return *this; } template <typename T> @@ -556,26 +580,29 @@ class balance_pair_t } balance_pair_t& operator-=(const balance_pair_t& bal_pair) { - if (bal_pair.cost && ! cost) - cost = new balance_t(quantity); - quantity -= bal_pair.quantity; - if (cost) - *cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; + if (bal_pair.price) { + if (price) + *price -= *bal_pair.price; + else + price = new balance_t(- *bal_pair.price); + } + if (bal_pair.cost) { + if (cost) + *cost -= *bal_pair.cost; + else + cost = new balance_t(- *bal_pair.cost); + } return *this; } balance_pair_t& operator-=(const balance_t& bal) { quantity -= bal; - if (cost) - *cost -= bal; return *this; } balance_pair_t& operator-=(const amount_t& amt) { quantity -= amt; - if (cost) - *cost -= amt; return *this; } template <typename T> @@ -630,25 +657,35 @@ class balance_pair_t // multiplication and division balance_pair_t& operator*=(const balance_pair_t& bal_pair) { - if (bal_pair.cost && ! cost) - cost = new balance_t(quantity); - quantity *= bal_pair.quantity; - if (cost) - *cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; + + if (bal_pair.price) { + if (price) + *price *= *bal_pair.price; + } else { + if (price) { + delete price; + price = NULL; + } + } + if (bal_pair.cost) { + if (cost) + *cost *= *bal_pair.cost; + } else { + if (cost) { + delete cost; + cost = NULL; + } + } return *this; } balance_pair_t& operator*=(const balance_t& bal) { quantity *= bal; - if (cost) - *cost *= bal; return *this; } balance_pair_t& operator*=(const amount_t& amt) { quantity *= amt; - if (cost) - *cost *= amt; return *this; } template <typename T> @@ -657,25 +694,29 @@ class balance_pair_t } balance_pair_t& operator/=(const balance_pair_t& bal_pair) { - if (bal_pair.cost && ! cost) - cost = new balance_t(quantity); - quantity /= bal_pair.quantity; - if (cost) - *cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; + + if (bal_pair.price) { + if (price) + *price /= *bal_pair.price; + } else { + throw amount_error("Attempt to divide by zero"); + } + if (bal_pair.cost) { + if (cost) + *cost /= *bal_pair.cost; + } else { + throw amount_error("Attempt to divide by zero"); + } return *this; } balance_pair_t& operator/=(const balance_t& bal) { quantity /= bal; - if (cost) - *cost /= bal; return *this; } balance_pair_t& operator/=(const amount_t& amt) { quantity /= amt; - if (cost) - *cost /= amt; return *this; } template <typename T> @@ -815,8 +856,8 @@ class balance_pair_t // unary negation void negate() { quantity.negate(); - if (cost) - cost->negate(); + if (price) price->negate(); + if (cost) cost->negate(); } balance_pair_t negated() const { balance_pair_t temp = *this; @@ -840,8 +881,8 @@ class balance_pair_t void abs() { quantity.abs(); - if (cost) - cost->abs(); + if (price) price->abs(); + if (cost) cost->abs(); } amount_t amount(const commodity_t& commodity) const { @@ -857,19 +898,30 @@ class balance_pair_t } balance_pair_t& add(const amount_t& amount, - const amount_t * a_cost = NULL) { - if (a_cost && ! cost) - cost = new balance_t(quantity); - + const amount_t * a_price = NULL, + const amount_t * a_cost = NULL) + { quantity += amount; - if (cost) - *cost += a_cost ? *a_cost : amount; + + if (a_price) { + if (price) + *price += *a_price; + else + price = new balance_t(*a_price); + } + if (a_cost) { + if (cost) + *cost += *a_cost; + else + cost = new balance_t(*a_cost); + } return *this; } bool valid() { - return quantity.valid() && (! cost || cost->valid()); + return (quantity.valid() && + (! price || price->valid()) && (! cost || cost->valid())); } void round() { @@ -1041,7 +1041,6 @@ OPT_BEGIN(basis, "B") { } OPT_END(basis); OPT_BEGIN(price, "I") { - show_lots = true; // don't show them, but use in calculations config->amount_expr = "i"; config->total_expr = "I"; } OPT_END(price); @@ -158,13 +158,12 @@ void value_expr_t::compute(value_t& result, const details_t& details, break; case AMOUNT: - case PRICE: if (details.xact) { if (transaction_has_xdata(*details.xact) && transaction_xdata_(*details.xact).dflags & TRANSACTION_COMPOSITE) result = transaction_xdata_(*details.xact).composite_amount; else - result = translate_amount(details.xact->amount); + result = base_amount(details.xact->amount); } else if (details.account && account_has_xdata(*details.account)) { result = account_xdata(*details.account).value; @@ -172,8 +171,27 @@ void value_expr_t::compute(value_t& result, const details_t& details, else { result = 0L; } - if (kind == PRICE) - result = result.factor_price(); + break; + + case PRICE: + if (details.xact) { + bool set = false; + if (transaction_has_xdata(*details.xact)) { + transaction_xdata_t& xdata(transaction_xdata_(*details.xact)); + if (xdata.dflags & TRANSACTION_COMPOSITE) { + result = xdata.composite_amount.price(); + set = true; + } + } + if (! set) + result = details.xact->amount.price(); + } + else if (details.account && account_has_xdata(*details.account)) { + result = account_xdata(*details.account).value.price(); + } + else { + result = 0L; + } break; case COST: @@ -182,11 +200,7 @@ void value_expr_t::compute(value_t& result, const details_t& details, if (transaction_has_xdata(*details.xact)) { transaction_xdata_t& xdata(transaction_xdata_(*details.xact)); if (xdata.dflags & TRANSACTION_COMPOSITE) { - if (xdata.composite_amount.type == value_t::BALANCE_PAIR && - ((balance_pair_t *) xdata.composite_amount.data)->cost) - result = *((balance_pair_t *) xdata.composite_amount.data)->cost; - else - result = xdata.composite_amount; + result = xdata.composite_amount.cost(); set = true; } } @@ -195,7 +209,7 @@ void value_expr_t::compute(value_t& result, const details_t& details, if (details.xact->cost) result = *details.xact->cost; else - result = translate_amount(details.xact->amount); + result = base_amount(details.xact->amount); } } else if (details.account && account_has_xdata(*details.account)) { @@ -207,15 +221,20 @@ void value_expr_t::compute(value_t& result, const details_t& details, break; case TOTAL: - case PRICE_TOTAL: if (details.xact && transaction_has_xdata(*details.xact)) result = transaction_xdata_(*details.xact).total; else if (details.account && account_has_xdata(*details.account)) result = account_xdata(*details.account).total; else result = 0L; - if (kind == PRICE_TOTAL) - result = result.factor_price(); + break; + case PRICE_TOTAL: + if (details.xact && transaction_has_xdata(*details.xact)) + result = transaction_xdata_(*details.xact).total.price(); + else if (details.account && account_has_xdata(*details.account)) + result = account_xdata(*details.account).total.price(); + else + result = 0L; break; case COST_TOTAL: if (details.xact && transaction_has_xdata(*details.xact)) @@ -1140,14 +1159,14 @@ void init_value_expr() globals->define("a", node); globals->define("amount", node); - node = new value_expr_t(value_expr_t::COST); - globals->define("b", node); - globals->define("cost", node); - node = new value_expr_t(value_expr_t::PRICE); globals->define("i", node); globals->define("price", node); + node = new value_expr_t(value_expr_t::COST); + globals->define("b", node); + globals->define("cost", node); + node = new value_expr_t(value_expr_t::DATE); globals->define("d", node); globals->define("date", node); @@ -1184,14 +1203,14 @@ void init_value_expr() globals->define("O", node); globals->define("total", node); - node = new value_expr_t(value_expr_t::COST_TOTAL); - globals->define("B", node); - globals->define("cost_total", node); - node = new value_expr_t(value_expr_t::PRICE_TOTAL); globals->define("I", node); globals->define("price_total", node); + node = new value_expr_t(value_expr_t::COST_TOTAL); + globals->define("B", node); + globals->define("cost_total", node); + // Relating to format_t globals->define("t", new value_expr_t(value_expr_t::VALUE_EXPR)); globals->define("T", new value_expr_t(value_expr_t::TOTAL_EXPR)); @@ -1340,8 +1359,8 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node, break; case value_expr_t::AMOUNT: out << "AMOUNT"; break; - case value_expr_t::COST: out << "COST"; break; case value_expr_t::PRICE: out << "PRICE"; break; + case value_expr_t::COST: out << "COST"; break; case value_expr_t::DATE: out << "DATE"; break; case value_expr_t::CLEARED: out << "CLEARED"; break; case value_expr_t::PENDING: out << "PENDING"; break; @@ -1351,8 +1370,8 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node, case value_expr_t::COUNT: out << "COUNT"; break; case value_expr_t::DEPTH: out << "DEPTH"; break; case value_expr_t::TOTAL: out << "TOTAL"; break; - case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break; case value_expr_t::PRICE_TOTAL: out << "PRICE_TOTAL"; break; + case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break; case value_expr_t::F_NOW: out << "F_NOW"; break; case value_expr_t::F_ARITH_MEAN: out << "F_ARITH_MEAN"; break; @@ -723,7 +723,7 @@ void value_t::abs() } } -value_t value_t::cost() const +value_t value_t::price() const { switch (type) { case BOOLEAN: @@ -733,9 +733,9 @@ value_t value_t::cost() const return *this; case BALANCE_PAIR: - assert(((balance_pair_t *) data)->cost); - if (((balance_pair_t *) data)->cost) - return *(((balance_pair_t *) data)->cost); + assert(((balance_pair_t *) data)->price); + if (((balance_pair_t *) data)->price) + return *(((balance_pair_t *) data)->price); else return ((balance_pair_t *) data)->quantity; @@ -747,29 +747,21 @@ value_t value_t::cost() const return value_t(); } -value_t value_t::factor_price() const +value_t value_t::cost() const { switch (type) { case BOOLEAN: case INTEGER: - return *this; - - case AMOUNT: { - commodity_t& comm = ((amount_t *) data)->commodity(); - if (comm.price != NULL) - return value_t(*comm.price * *((amount_t *) data)); - return *this; - } - + case AMOUNT: case BALANCE: - return ((balance_t *) data)->factor_price(); + return *this; - case BALANCE_PAIR: { - balance_pair_t temp(((balance_pair_t *) data)->quantity.factor_price()); + case BALANCE_PAIR: + assert(((balance_pair_t *) data)->cost); if (((balance_pair_t *) data)->cost) - temp.cost = new balance_t(((balance_pair_t *) data)->cost); - return temp; - } + return *(((balance_pair_t *) data)->cost); + else + return ((balance_pair_t *) data)->quantity; default: assert(0); @@ -779,21 +771,22 @@ value_t value_t::factor_price() const return value_t(); } -value_t& value_t::add(const amount_t& amount, const amount_t * cost) +value_t& value_t::add(const amount_t& amount, + const amount_t * price, const amount_t * cost) { switch (type) { case BOOLEAN: case INTEGER: case AMOUNT: - if (cost) { + if (price || cost) { cast(BALANCE_PAIR); - return add(amount, cost); + return add(amount, price, cost); } else if ((type == AMOUNT && ((amount_t *) data)->commodity() != amount.commodity()) || (type != AMOUNT && amount.commodity())) { cast(BALANCE); - return add(amount, cost); + return add(amount, price, cost); } else if (type != AMOUNT) { cast(AMOUNT); @@ -802,15 +795,15 @@ value_t& value_t::add(const amount_t& amount, const amount_t * cost) break; case BALANCE: - if (cost) { + if (price || cost) { cast(BALANCE_PAIR); - return add(amount, cost); + return add(amount, price, cost); } *((balance_t *) data) += amount; break; case BALANCE_PAIR: - ((balance_pair_t *) data)->add(amount, cost); + ((balance_pair_t *) data)->add(amount, price, cost); break; default: @@ -145,7 +145,7 @@ class value_t } value_t& operator=(const balance_pair_t& value) { if ((balance_pair_t *) data != &value) { - if (! value.cost) { + if (! value.price && ! value.cost) { return *this = value.quantity; } else { destroy(); @@ -266,8 +266,10 @@ class value_t void abs(); void cast(type_t cast_type); value_t cost() const; - value_t factor_price() const; - value_t& add(const amount_t& amount, const amount_t * cost = NULL); + value_t price() const; + value_t& add(const amount_t& amount, + const amount_t * price = NULL, + const amount_t * cost = NULL); value_t value(const std::time_t moment) const { switch (type) { @@ -44,16 +44,16 @@ void add_transaction_to(const transaction_t& xact, value_t& value) transaction_xdata_(xact).dflags & TRANSACTION_COMPOSITE) { value += transaction_xdata_(xact).composite_amount; } - else if (xact.cost || value) { - amount_t * cost = xact.cost; - if (cost && cost->commodity().price) - cost = new amount_t(cost->base_amount()); - value.add(translate_amount(xact.amount), cost); - if (cost != xact.cost) - delete cost; + else if (xact.cost || xact.amount.commodity().price || value) { + std::auto_ptr<amount_t> price; + amount_t * cost = xact.cost; + if (xact.amount.commodity().price) + price.reset(new amount_t(*xact.amount.commodity().price * + xact.amount)); + value.add(base_amount(xact.amount), price.get(), cost); } else { - value = translate_amount(xact.amount); + value = xact.amount; } } @@ -122,9 +122,6 @@ inline const account_t * xact_account(const transaction_t& xact) { extern bool show_lots; -#define translate_amount(amt) \ - ((! show_lots && amt.commodity().price) ? amt.base_amount() : amt) - ////////////////////////////////////////////////////////////////////// inline void walk_transactions(transactions_list::iterator begin, |