summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--amount.h18
-rw-r--r--balance.cc10
-rw-r--r--balance.h164
-rw-r--r--config.cc1
-rw-r--r--valexpr.cc65
-rw-r--r--value.cc47
-rw-r--r--value.h8
-rw-r--r--walk.cc16
-rw-r--r--walk.h3
9 files changed, 202 insertions, 130 deletions
diff --git a/amount.h b/amount.h
index 6262caa9..d47aa575 100644
--- a/amount.h
+++ b/amount.h
@@ -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:
diff --git a/balance.cc b/balance.cc
index 01332fae..018113ad 100644
--- a/balance.cc
+++ b/balance.cc
@@ -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;
}
diff --git a/balance.h b/balance.h
index 929888d2..3863e68e 100644
--- a/balance.h
+++ b/balance.h
@@ -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() {
diff --git a/config.cc b/config.cc
index 069114fb..cc04ed8b 100644
--- a/config.cc
+++ b/config.cc
@@ -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);
diff --git a/valexpr.cc b/valexpr.cc
index 2b8f106e..70b534eb 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -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;
diff --git a/value.cc b/value.cc
index 1680ebd7..6038ca9e 100644
--- a/value.cc
+++ b/value.cc
@@ -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:
diff --git a/value.h b/value.h
index c7aad0e7..05bea81f 100644
--- a/value.h
+++ b/value.h
@@ -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) {
diff --git a/walk.cc b/walk.cc
index 075b8bd8..9f7ee8b1 100644
--- a/walk.cc
+++ b/walk.cc
@@ -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;
}
}
diff --git a/walk.h b/walk.h
index 0f8c6956..974cd575 100644
--- a/walk.h
+++ b/walk.h
@@ -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,