summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--amount.cc167
-rw-r--r--amount.h66
-rw-r--r--autoxact.cc2
-rw-r--r--balance.cc13
-rw-r--r--balance.h80
-rw-r--r--binary.cc8
-rw-r--r--binary.h1
-rw-r--r--gnucash.cc4
-rw-r--r--journal.cc19
-rw-r--r--qif.cc2
-rw-r--r--quotes.cc18
-rw-r--r--quotes.h2
-rw-r--r--textual.cc9
-rw-r--r--valexpr.cc8
-rw-r--r--value.cc52
15 files changed, 225 insertions, 226 deletions
diff --git a/amount.cc b/amount.cc
index 9ebf0c80..c4293aee 100644
--- a/amount.cc
+++ b/amount.cc
@@ -1,4 +1,3 @@
-#include "ledger.h"
#include "amount.h"
#include "binary.h"
#include "error.h"
@@ -84,8 +83,8 @@ void clean_commodity_history(char * item_pool, char * item_pool_end)
// Since the journal in which this price was bulk alloc'd (on
// reading from a binary file) is going away, we must make a
- // new copy of the value, which other journals might still be
- // using.
+ // new copy of the value, because other journals might still
+ // be using it.
amount_t::bigint_t * q = new amount_t::bigint_t(*quantity);
if (--quantity->ref == 0)
@@ -168,11 +167,10 @@ amount_t::amount_t(const bool value)
if (value) {
quantity = &true_value;
quantity->ref++;
- commodity = commodity_t::null_commodity;
} else {
quantity = NULL;
- commodity = NULL;
}
+ commodity_ = NULL;
}
amount_t::amount_t(const int value)
@@ -182,11 +180,10 @@ amount_t::amount_t(const int value)
if (value != 0) {
quantity = new bigint_t;
mpz_set_si(MPZ(quantity), value);
- commodity = commodity_t::null_commodity;
} else {
quantity = NULL;
- commodity = NULL;
}
+ commodity_ = NULL;
}
amount_t::amount_t(const unsigned int value)
@@ -196,11 +193,10 @@ amount_t::amount_t(const unsigned int value)
if (value != 0) {
quantity = new bigint_t;
mpz_set_ui(MPZ(quantity), value);
- commodity = commodity_t::null_commodity;
} else {
quantity = NULL;
- commodity = NULL;
}
+ commodity_ = NULL;
}
amount_t::amount_t(const double value)
@@ -211,11 +207,10 @@ amount_t::amount_t(const double value)
quantity = new bigint_t;
mpz_set_d(MPZ(quantity), value);
// jww (2004-08-20): How do I calculate this?
- commodity = commodity_t::null_commodity;
} else {
quantity = NULL;
- commodity = NULL;
}
+ commodity_ = NULL;
}
void amount_t::_release()
@@ -257,7 +252,7 @@ void amount_t::_copy(const amount_t& amt)
quantity = amt.quantity;
quantity->ref++;
}
- commodity = amt.commodity;
+ commodity_ = amt.commodity_;
}
amount_t& amount_t::operator=(const std::string& value)
@@ -293,7 +288,7 @@ amount_t& amount_t::operator=(const bool value)
if (quantity)
_clear();
} else {
- commodity = commodity_t::null_commodity;
+ commodity_ = NULL;
if (quantity)
_release();
quantity = &true_value;
@@ -308,7 +303,7 @@ amount_t& amount_t::operator=(const int value)
if (quantity)
_clear();
} else {
- commodity = commodity_t::null_commodity;
+ commodity_ = NULL;
_init();
mpz_set_si(MPZ(quantity), value);
}
@@ -321,7 +316,7 @@ amount_t& amount_t::operator=(const unsigned int value)
if (quantity)
_clear();
} else {
- commodity = commodity_t::null_commodity;
+ commodity_ = NULL;
_init();
mpz_set_ui(MPZ(quantity), value);
}
@@ -334,7 +329,7 @@ amount_t& amount_t::operator=(const double value)
if (quantity)
_clear();
} else {
- commodity = commodity_t::null_commodity;
+ commodity_ = NULL;
_init();
// jww (2004-08-20): How do I calculate precision?
mpz_set_d(MPZ(quantity), value);
@@ -376,7 +371,7 @@ amount_t& amount_t::operator+=(const amount_t& amt)
_dup();
- if (commodity != amt.commodity)
+ if (commodity_ != amt.commodity_)
throw amount_error("Adding amounts with different commodities");
if (quantity->prec == amt.quantity->prec) {
@@ -401,14 +396,14 @@ amount_t& amount_t::operator-=(const amount_t& amt)
if (! quantity) {
quantity = new bigint_t(*amt.quantity);
- commodity = amt.commodity;
+ commodity_ = amt.commodity_;
mpz_neg(MPZ(quantity), MPZ(quantity));
return *this;
}
_dup();
- if (commodity != amt.commodity)
+ if (commodity_ != amt.commodity_)
throw amount_error("Subtracting amounts with different commodities");
if (quantity->prec == amt.quantity->prec) {
@@ -436,10 +431,10 @@ amount_t& amount_t::operator*=(const amount_t& amt)
mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
quantity->prec += amt.quantity->prec;
- if (quantity->prec > commodity->precision + 6U) {
- mpz_round(MPZ(quantity), MPZ(quantity),
- quantity->prec, commodity->precision + 6U);
- quantity->prec = commodity->precision + 6U;
+ unsigned int comm_prec = commodity().precision;
+ if (quantity->prec > comm_prec + 6U) {
+ mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
+ quantity->prec = comm_prec + 6U;
}
return *this;
@@ -461,10 +456,10 @@ amount_t& amount_t::operator/=(const amount_t& amt)
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
quantity->prec += 6;
- if (quantity->prec > commodity->precision + 6U) {
- mpz_round(MPZ(quantity), MPZ(quantity),
- quantity->prec, commodity->precision + 6U);
- quantity->prec = commodity->precision + 6U;
+ unsigned int comm_prec = commodity().precision;
+ if (quantity->prec > comm_prec + 6U) {
+ mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
+ quantity->prec = comm_prec + 6U;
}
return *this;
@@ -536,9 +531,8 @@ bool amount_t::operator OP(const amount_t& amt) const \
if (! amt.quantity) \
return *this < 0; \
\
- if (commodity != amt.commodity && \
- commodity != commodity_t::null_commodity && \
- amt.commodity != commodity_t::null_commodity) \
+ if (commodity() && amt.commodity() && \
+ commodity() != amt.commodity()) \
return false; \
\
if (quantity->prec == amt.quantity->prec) { \
@@ -567,12 +561,12 @@ amount_t::operator bool() const
if (! quantity)
return false;
- if (quantity->prec <= commodity->precision) {
+ if (quantity->prec <= commodity().precision) {
return mpz_sgn(MPZ(quantity)) != 0;
} else {
- assert(commodity);
+ assert(commodity_);
mpz_set(temp, MPZ(quantity));
- mpz_ui_pow_ui(divisor, 10, quantity->prec - commodity->precision);
+ mpz_ui_pow_ui(divisor, 10, quantity->prec - commodity().precision);
mpz_tdiv_q(temp, temp, divisor);
bool zero = mpz_sgn(temp) == 0;
return ! zero;
@@ -581,9 +575,9 @@ amount_t::operator bool() const
amount_t amount_t::value(const std::time_t moment) const
{
- if (quantity && ! (commodity->flags & COMMODITY_STYLE_NOMARKET))
- if (amount_t amt = commodity->value(moment))
- return (amt * *this).round(commodity->precision);
+ if (quantity && ! (commodity().flags & COMMODITY_STYLE_NOMARKET))
+ if (amount_t amt = commodity().value(moment))
+ return (amt * *this).round(commodity().precision);
return *this;
}
@@ -622,16 +616,18 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
// Ensure the value is rounded to the commodity's precision before
// outputting it. NOTE: `rquotient' is used here as a temp variable!
- if (amt.commodity->precision < amt.quantity->prec) {
+ commodity_t& commodity(amt.commodity());
+
+ if (commodity.precision < amt.quantity->prec) {
mpz_round(rquotient, MPZ(amt.quantity), amt.quantity->prec,
- amt.commodity->precision);
- mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
+ commodity.precision);
+ mpz_ui_pow_ui(divisor, 10, commodity.precision);
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
}
- else if (amt.commodity->precision > amt.quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, amt.commodity->precision - amt.quantity->prec);
+ else if (commodity.precision > amt.quantity->prec) {
+ mpz_ui_pow_ui(divisor, 10, commodity.precision - amt.quantity->prec);
mpz_mul(rquotient, MPZ(amt.quantity), divisor);
- mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
+ mpz_ui_pow_ui(divisor, 10, commodity.precision);
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
}
else if (amt.quantity->prec) {
@@ -651,12 +647,12 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
}
mpz_set(rquotient, remainder);
- if (! (amt.commodity->flags & COMMODITY_STYLE_SUFFIXED)) {
- if (amt.commodity->quote)
- out << "\"" << amt.commodity->symbol << "\"";
+ if (! (commodity.flags & COMMODITY_STYLE_SUFFIXED)) {
+ if (commodity.quote)
+ out << "\"" << commodity.symbol << "\"";
else
- out << amt.commodity->symbol;
- if (amt.commodity->flags & COMMODITY_STYLE_SEPARATED)
+ out << commodity.symbol;
+ if (commodity.flags & COMMODITY_STYLE_SEPARATED)
out << " ";
}
@@ -666,7 +662,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
if (mpz_sgn(quotient) == 0) {
out << '0';
}
- else if (! (amt.commodity->flags & COMMODITY_STYLE_THOUSANDS)) {
+ else if (! (commodity.flags & COMMODITY_STYLE_THOUSANDS)) {
char * p = mpz_get_str(NULL, 10, quotient);
out << p;
std::free(p);
@@ -695,7 +691,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
i != strs.rend();
i++) {
if (printed) {
- out << (amt.commodity->flags & COMMODITY_STYLE_EUROPEAN ? '.' : ',');
+ out << (commodity.flags & COMMODITY_STYLE_EUROPEAN ? '.' : ',');
out.width(3);
out.fill('0');
}
@@ -705,10 +701,10 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
}
}
- if (amt.commodity->precision) {
- out << ((amt.commodity->flags & COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
+ if (commodity.precision) {
+ out << ((commodity.flags & COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
- out.width(amt.commodity->precision);
+ out.width(commodity.precision);
out.fill('0');
char * p = mpz_get_str(NULL, 10, rquotient);
@@ -716,13 +712,13 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
std::free(p);
}
- if (amt.commodity->flags & COMMODITY_STYLE_SUFFIXED) {
- if (amt.commodity->flags & COMMODITY_STYLE_SEPARATED)
+ if (commodity.flags & COMMODITY_STYLE_SUFFIXED) {
+ if (commodity.flags & COMMODITY_STYLE_SEPARATED)
out << " ";
- if (amt.commodity->quote)
- out << "\"" << amt.commodity->symbol << "\"";
+ if (commodity.quote)
+ out << "\"" << commodity.symbol << "\"";
else
- out << amt.commodity->symbol;
+ out << commodity.symbol;
}
mpz_clear(quotient);
@@ -825,10 +821,10 @@ void amount_t::parse(std::istream& in)
}
// Create the commodity if has not already been seen.
- commodity = commodity_t::find_commodity(symbol, true);
- commodity->flags |= flags;
- if (quantity->prec > commodity->precision)
- commodity->precision = quantity->prec;
+ commodity_ = commodity_t::find_commodity(symbol, true);
+ commodity_->flags |= flags;
+ if (quantity->prec > commodity_->precision)
+ commodity_->precision = quantity->prec;
// Now we have the final number. Remove commas and periods, if
// necessary.
@@ -937,48 +933,16 @@ void amount_t::read_quantity(char *& data)
}
}
-void amount_t::read_quantity(std::istream& in)
-{
- char byte;
- in.read(&byte, sizeof(byte));
-
- if (byte == 0) {
- quantity = NULL;
- }
- else if (byte == 1) {
- quantity = new(bigints_next++) bigint_t;
- quantity->flags |= BIGINT_BULK_ALLOC;
-
- unsigned short len;
- in.read((char *)&len, sizeof(len));
- in.read(buf, len);
- mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short),
- 0, 0, buf);
-
- char negative;
- in.read(&negative, sizeof(negative));
- if (negative)
- mpz_neg(MPZ(quantity), MPZ(quantity));
-
- in.read((char *)&quantity->prec, sizeof(quantity->prec));
- } else {
- unsigned int index;
- in.read((char *)&index, sizeof(index));
- quantity = bigints + (index - 1);
- quantity->ref++;
- }
-}
-
bool amount_t::valid() const
{
if (quantity) {
- if (! commodity)
+ if (! commodity_)
return false;
if (quantity->ref == 0)
return false;
}
- else if (commodity) {
+ else if (commodity_) {
return false;
}
@@ -1029,9 +993,8 @@ amount_t commodity_t::value(const std::time_t moment)
}
if (updater)
- (*updater)(this, moment, age,
- history.size() > 0 ? (*history.rbegin()).first : 0, price);
-
+ (*updater)(*this, moment, age, (history.size() > 0 ?
+ (*history.rbegin()).first : 0), price);
return price;
}
@@ -1053,7 +1016,7 @@ struct commodity_updater_wrap : public commodity_t::updater_t
PyObject * self;
commodity_updater_wrap(PyObject * self_) : self(self_) {}
- virtual void operator()(commodity_t * commodity,
+ virtual void operator()(commodity_t& commodity,
const std::time_t moment,
const std::time_t date,
const std::time_t last,
@@ -1073,7 +1036,9 @@ void export_amount()
.def(init<unsigned int>())
.def(init<double>())
- .def_readonly("commodity", &amount_t::commodity)
+ .def("commodity", &amount_t::commodity,
+ return_value_policy<reference_existing_object>())
+ .def("set_commodity", &amount_t::set_commodity)
.def(self += self)
.def(self + self)
@@ -1127,8 +1092,6 @@ void export_amount()
.def_readwrite("conversion", &commodity_t::conversion)
.def_readwrite("ident", &commodity_t::ident)
.def_readwrite("updater", &commodity_t::updater)
- .def_readwrite("commodities", &commodity_t::commodities)
- .def_readwrite("null_commodity", &commodity_t::null_commodity)
.def("add_commodity", &commodity_t::add_commodity)
.def("remove_commodity", &commodity_t::remove_commodity)
diff --git a/amount.h b/amount.h
index bd0acce9..bf7457f0 100644
--- a/amount.h
+++ b/amount.h
@@ -15,6 +15,10 @@ class commodity_t;
class amount_t
{
+ public:
+ class bigint_t;
+
+ protected:
void _init();
void _copy(const amount_t& amt);
void _release();
@@ -23,23 +27,21 @@ class amount_t
void _clear() {
if (quantity) {
- assert(commodity);
+ assert(commodity_);
_release();
- quantity = NULL;
- commodity = NULL;
+ quantity = NULL;
+ commodity_ = NULL;
} else {
- assert(! commodity);
+ assert(! commodity_);
}
}
- public:
- class bigint_t;
-
bigint_t * quantity;
- commodity_t * commodity;
+ commodity_t * commodity_;
+ public:
// constructors
- amount_t() : quantity(NULL), commodity(NULL) {
+ amount_t() : quantity(NULL), commodity_(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
}
amount_t(const amount_t& amt) : quantity(NULL) {
@@ -47,7 +49,7 @@ class amount_t
if (amt.quantity)
_copy(amt);
else
- commodity = NULL;
+ commodity_ = NULL;
}
amount_t(const std::string& value) : quantity(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
@@ -69,6 +71,11 @@ class amount_t
_release();
}
+ commodity_t& commodity() const;
+ void set_commodity(commodity_t& comm) {
+ commodity_ = &comm;
+ }
+
// assignment operator
amount_t& operator=(const amount_t& amt);
amount_t& operator=(const std::string& value);
@@ -149,7 +156,7 @@ class amount_t
bool operator>=(const amount_t& amt) const;
bool operator==(const amount_t& amt) const;
bool operator!=(const amount_t& amt) const {
- if (commodity != amt.commodity)
+ if (commodity_ != amt.commodity_)
return true;
return ! (*this == amt);
}
@@ -164,13 +171,27 @@ class amount_t
void parse(std::istream& in);
void parse(const std::string& str);
- void write_quantity(std::ostream& out) const;
void read_quantity(char *& data);
- void read_quantity(std::istream& in);
+ void write_quantity(std::ostream& out) const;
bool valid() const;
+ // Classes that are friends, and help to implement this class
+
+ friend std::ostream& operator<<(std::ostream& out, const amount_t& amt);
friend std::istream& operator>>(std::istream& in, amount_t& amt);
+
+ friend unsigned int sizeof_bigint_t();
+
+ friend void read_binary_amount(char *& data, amount_t& amt);
+ friend void write_binary_amount(std::ostream& out, const amount_t& amt);
+
+ // This function is special, and exists only to support a custom
+ // optimization in binary.cc (which offers a significant enough gain
+ // to be worth the trouble).
+
+ friend void clean_commodity_history(char * item_pool,
+ char * item_pool_end);
};
unsigned int sizeof_bigint_t();
@@ -209,7 +230,7 @@ class commodity_t
class updater_t {
public:
virtual ~updater_t() {}
- virtual void operator()(commodity_t * commodity,
+ virtual void operator()(commodity_t& commodity,
const std::time_t moment,
const std::time_t date,
const std::time_t last,
@@ -273,6 +294,16 @@ class commodity_t
}
#endif
+ operator bool() const {
+ return this != null_commodity;
+ }
+ bool operator==(const commodity_t& comm) const {
+ return this == &comm;
+ }
+ bool operator!=(const commodity_t& comm) const {
+ return this != &comm;
+ }
+
void check_symbol() {
for (const char * p = symbol.c_str(); *p; p++)
if (std::isspace(*p) || std::isdigit(*p) || *p == '-' || *p == '.') {
@@ -310,6 +341,13 @@ class commodity_t
}
};
+inline commodity_t& amount_t::commodity() const {
+ if (! commodity_)
+ return *commodity_t::null_commodity;
+ else
+ return *commodity_;
+ }
+
} // namespace ledger
#endif // _AMOUNT_H
diff --git a/autoxact.cc b/autoxact.cc
index 9672d4d2..165ebede 100644
--- a/autoxact.cc
+++ b/autoxact.cc
@@ -15,7 +15,7 @@ void automated_transaction_t::extend_entry(entry_t * entry)
t != transactions.end();
t++) {
amount_t amt;
- if ((*t)->amount.commodity->symbol.empty())
+ if ((*t)->amount.commodity().symbol.empty())
amt = (*i)->amount * (*t)->amount;
else
amt = (*t)->amount;
diff --git a/balance.cc b/balance.cc
index f6392536..69066f97 100644
--- a/balance.cc
+++ b/balance.cc
@@ -5,7 +5,7 @@
namespace ledger {
-amount_t balance_t::amount(const commodity_t * commodity) const
+amount_t balance_t::amount(const commodity_t& commodity) const
{
if (! commodity) {
if (amounts.size() == 1) {
@@ -14,7 +14,7 @@ amount_t balance_t::amount(const commodity_t * commodity) const
}
}
else if (amounts.size() > 0) {
- amounts_map::const_iterator i = amounts.find(commodity);
+ amounts_map::const_iterator i = amounts.find(&commodity);
if (i != amounts.end())
return (*i).second;
}
@@ -35,7 +35,7 @@ balance_t balance_t::value(const std::time_t moment) const
struct compare_amount_commodities {
bool operator()(const amount_t * left, const amount_t * right) const {
- return left->commodity->symbol < right->commodity->symbol;
+ return left->commodity().symbol < right->commodity().symbol;
}
};
@@ -136,13 +136,6 @@ void export_balance()
.def(init<unsigned int>())
.def(init<double>())
- .def(self < other<unsigned int>())
- .def(self <= other<unsigned int>())
- .def(self > other<unsigned int>())
- .def(self >= other<unsigned int>())
- .def(self == other<unsigned int>())
- .def(self != other<unsigned int>())
-
.def(self += self)
.def(self += other<amount_t>())
.def(self + self)
diff --git a/balance.h b/balance.h
index f88f3114..2c2683f0 100644
--- a/balance.h
+++ b/balance.h
@@ -6,6 +6,7 @@
#include <iostream>
#include "amount.h"
+#include "error.h"
namespace ledger {
@@ -40,25 +41,25 @@ class balance_t
balance_t(const amount_t& amt) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
if (amt)
- amounts.insert(amounts_pair(amt.commodity, amt));
+ amounts.insert(amounts_pair(&amt.commodity(), amt));
}
balance_t(const int value) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
amount_t amt(value);
if (amt)
- amounts.insert(amounts_pair(amt.commodity, amt));
+ amounts.insert(amounts_pair(&amt.commodity(), amt));
}
balance_t(const unsigned int value) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
amount_t amt(value);
if (amt)
- amounts.insert(amounts_pair(amt.commodity, amt));
+ amounts.insert(amounts_pair(&amt.commodity(), amt));
}
balance_t(const double value) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
amount_t amt(value);
if (amt)
- amounts.insert(amounts_pair(amt.commodity, amt));
+ amounts.insert(amounts_pair(&amt.commodity(), amt));
}
// destructor
@@ -109,11 +110,11 @@ class balance_t
return *this;
}
balance_t& operator+=(const amount_t& amt) {
- amounts_map::iterator i = amounts.find(amt.commodity);
+ amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end())
(*i).second += amt;
else if (amt)
- amounts.insert(amounts_pair(amt.commodity, amt));
+ amounts.insert(amounts_pair(&amt.commodity(), amt));
return *this;
}
balance_t& operator-=(const balance_t& bal) {
@@ -124,11 +125,11 @@ class balance_t
return *this;
}
balance_t& operator-=(const amount_t& amt) {
- amounts_map::iterator i = amounts.find(amt.commodity);
+ amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end())
(*i).second -= amt;
else if (amt)
- amounts.insert(amounts_pair(amt.commodity, amt));
+ amounts.insert(amounts_pair(&amt.commodity(), amt));
return *this;
}
@@ -165,13 +166,13 @@ class balance_t
balance_t& operator*=(const amount_t& amt) {
// Multiplying by the null commodity causes all amounts to be
// increased by the same factor.
- if (amt.commodity->symbol.empty()) {
+ if (amt.commodity().symbol.empty()) {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)
(*i).second *= amt;
} else {
- amounts_map::iterator i = amounts.find(amt.commodity);
+ amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end())
(*i).second *= amt;
}
@@ -188,13 +189,13 @@ class balance_t
balance_t& operator/=(const amount_t& amt) {
// Dividing by the null commodity causes all amounts to be
// increased by the same factor.
- if (amt.commodity->symbol.empty()) {
+ if (amt.commodity().symbol.empty()) {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)
(*i).second /= amt;
} else {
- amounts_map::iterator i = amounts.find(amt.commodity);
+ amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end())
(*i).second /= amt;
}
@@ -228,13 +229,13 @@ class balance_t
for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end();
i++)
- if (! (amount((*i).first) < (*i).second))
+ if (! (amount(*(*i).first) < (*i).second))
return false;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++)
- if (! ((*i).second < bal.amount((*i).first)))
+ if (! ((*i).second < bal.amount(*(*i).first)))
return false;
if (bal.amounts.size() == 0 && amounts.size() == 0)
@@ -246,41 +247,43 @@ class balance_t
for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end();
i++)
- if (! (amount((*i).first) <= (*i).second))
+ if (! (amount(*(*i).first) <= (*i).second))
return false;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++)
- if (! ((*i).second <= bal.amount((*i).first)))
+ if (! ((*i).second <= bal.amount(*(*i).first)))
return false;
return true;
}
bool operator<(const amount_t& amt) const {
- return amount(amt.commodity) < amt;
+ return amount(amt.commodity()) < amt;
}
bool operator<=(const amount_t& amt) const {
- return amount(amt.commodity) <= amt;
+ return amount(amt.commodity()) <= amt;
}
+#if 0
bool operator<(const unsigned int val) const {
return amount() < val;
}
bool operator<=(const unsigned int val) const {
return amount() <= val;
}
+#endif
bool operator>(const balance_t& bal) const {
for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end();
i++)
- if (! (amount((*i).first) > (*i).second))
+ if (! (amount(*(*i).first) > (*i).second))
return false;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++)
- if (! ((*i).second > bal.amount((*i).first)))
+ if (! ((*i).second > bal.amount(*(*i).first)))
return false;
if (bal.amounts.size() == 0 && amounts.size() == 0)
@@ -292,29 +295,31 @@ class balance_t
for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end();
i++)
- if (! (amount((*i).first) >= (*i).second))
+ if (! (amount(*(*i).first) >= (*i).second))
return false;
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
i++)
- if (! ((*i).second >= bal.amount((*i).first)))
+ if (! ((*i).second >= bal.amount(*(*i).first)))
return false;
return true;
}
bool operator>(const amount_t& amt) const {
- return amount(amt.commodity) > amt;
+ return amount(amt.commodity()) > amt;
}
bool operator>=(const amount_t& amt) const {
- return amount(amt.commodity) >= amt;
+ return amount(amt.commodity()) >= amt;
}
+#if 0
bool operator>(const unsigned int val) const {
return amount() > val;
}
bool operator>=(const unsigned int val) const {
return amount() >= val;
}
+#endif
bool operator==(const balance_t& bal) const {
amounts_map::const_iterator i, j;
@@ -327,21 +332,23 @@ class balance_t
}
return i == amounts.end() && j == bal.amounts.end();
}
- bool operator==(const amount_t& amt) const {
- return amounts.size() == 1 && (*amounts.begin()).second == amt;
- }
- bool operator==(const unsigned int val) const {
- return amount() == val;
- }
bool operator!=(const balance_t& bal) const {
return ! (*this == bal);
}
+ bool operator==(const amount_t& amt) const {
+ return amounts.size() == 1 && (*amounts.begin()).second == amt;
+ }
bool operator!=(const amount_t& amt) const {
return ! (*this == amt);
}
+#if 0
+ bool operator==(const unsigned int val) const {
+ return amount() == val;
+ }
bool operator!=(const unsigned int val) const {
return ! (*this == val);
}
+#endif
// unary negation
balance_t& negate() {
@@ -362,7 +369,10 @@ class balance_t
// conversion operators
operator amount_t() const {
- return amount();
+ if (amounts.size() == 1)
+ return (*amounts.begin()).second;
+ else
+ throw error("Cannot convert a balance with multiple commodities to an amount");
}
operator bool() const {
for (amounts_map::const_iterator i = amounts.begin();
@@ -373,7 +383,7 @@ class balance_t
return false;
}
- amount_t amount(const commodity_t * commodity = NULL) const;
+ amount_t amount(const commodity_t& commodity) const;
balance_t value(const std::time_t moment) const;
void write(std::ostream& out,
@@ -754,8 +764,10 @@ class balance_pair_t
return quantity;
}
operator amount_t() const {
- assert(0);
- return quantity.amount();
+ if (quantity.amounts.size() == 1)
+ return (*quantity.amounts.begin()).second;
+ else
+ throw error("Cannot convert a balance pair with multiple commodities to an amount");
}
void abs() {
diff --git a/binary.cc b/binary.cc
index 088a6bd8..0a712972 100644
--- a/binary.cc
+++ b/binary.cc
@@ -165,9 +165,9 @@ inline void read_binary_amount(char *& data, amount_t& amt)
commodity_t::ident_t ident;
read_binary_number(data, ident);
if (ident == 0xffffffff)
- amt.commodity = NULL;
+ amt.commodity_ = NULL;
else
- amt.commodity = commodities[ident - 1];
+ amt.commodity_ = commodities[ident - 1];
amt.read_quantity(data);
}
@@ -431,8 +431,8 @@ inline void write_binary_string(std::ostream& out, const std::string& str)
void write_binary_amount(std::ostream& out, const amount_t& amt)
{
- if (amt.commodity)
- write_binary_number(out, amt.commodity->ident);
+ if (amt.commodity_)
+ write_binary_number(out, amt.commodity().ident);
else
write_binary_number<commodity_t::ident_t>(out, 0xffffffff);
diff --git a/binary.h b/binary.h
index 2cc4b5b4..40621e19 100644
--- a/binary.h
+++ b/binary.h
@@ -1,6 +1,7 @@
#ifndef _BINARY_H
#define _BINARY_H
+#include "ledger.h"
#include "parser.h"
#include <deque>
diff --git a/gnucash.cc b/gnucash.cc
index c5b4dcc3..424ea1ae 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -235,10 +235,10 @@ static void dataHandler(void *userData, const char *s, int len)
}
commodity_t * default_commodity = (*ac).second;
- curr_quant.commodity = default_commodity;
+ curr_quant.set_commodity(*default_commodity);
amount_t value = curr_quant.round(default_commodity->precision);
- if (curr_value.commodity == default_commodity)
+ if (curr_value.commodity() == *default_commodity)
curr_value = value;
xact->amount = value;
diff --git a/journal.cc b/journal.cc
index 30d258f1..2d8cc4bb 100644
--- a/journal.cc
+++ b/journal.cc
@@ -246,12 +246,9 @@ bool journal_t::add_entry(entry_t * entry)
i != entry->transactions.end();
i++) {
(*i)->account->add_transaction(*i);
-
- if ((*i)->cost) {
- assert((*i)->cost->commodity);
- (*i)->amount.commodity->add_price(entry->date,
- *(*i)->cost / (*i)->amount);
- }
+ if ((*i)->cost)
+ (*i)->amount.commodity().add_price(entry->date,
+ *(*i)->cost / (*i)->amount);
}
return true;
@@ -330,8 +327,8 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
first = xact = new transaction_t(m_xact->account, amt);
added->add_transaction(xact);
- if (xact->amount.commodity->symbol.empty())
- xact->amount.commodity = m_xact->amount.commodity;
+ if (xact->amount.commodity().symbol.empty())
+ xact->amount.set_commodity(m_xact->amount.commodity());
m_xact = matching->transactions.back();
@@ -355,7 +352,7 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
x++) {
if (acct_regex.match((*x)->account->fullname())) {
acct = (*x)->account;
- cmdty = (*x)->amount.commodity;
+ cmdty = &(*x)->amount.commodity();
break;
}
}
@@ -379,8 +376,8 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
transaction_t * xact = new transaction_t(acct, amt);
added->add_transaction(xact);
- if (! xact->amount.commodity)
- xact->amount.commodity = cmdty;
+ if (! xact->amount.commodity())
+ xact->amount.set_commodity(*cmdty);
}
if (i != end && std::string(*i++) == "-from" && i != end) {
diff --git a/qif.cc b/qif.cc
index c5e007a7..987dc65c 100644
--- a/qif.cc
+++ b/qif.cc
@@ -96,7 +96,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
xact->amount.parse(line);
if (! def_commodity)
def_commodity = commodity_t::find_commodity("$", true);
- xact->amount.commodity = def_commodity;
+ xact->amount.set_commodity(*def_commodity);
if (c == '$')
xact->amount.negate();
break;
diff --git a/quotes.cc b/quotes.cc
index 8f27f01e..b994c630 100644
--- a/quotes.cc
+++ b/quotes.cc
@@ -6,7 +6,7 @@
namespace ledger {
-void quotes_by_script::operator()(commodity_t * commodity,
+void quotes_by_script::operator()(commodity_t& commodity,
const std::time_t moment,
const std::time_t date,
const std::time_t last,
@@ -14,25 +14,25 @@ void quotes_by_script::operator()(commodity_t * commodity,
{
DEBUG_CLASS("ledger.quotes.download");
- DEBUG_PRINT_("commodity: " << commodity->symbol);
+ DEBUG_PRINT_("commodity: " << commodity.symbol);
DEBUG_PRINT_TIME_(now);
DEBUG_PRINT_TIME_(moment);
DEBUG_PRINT_TIME_(date);
DEBUG_PRINT_TIME_(last);
- DEBUG_PRINT_TIME_(commodity->last_lookup);
+ DEBUG_PRINT_TIME_(commodity.last_lookup);
DEBUG_PRINT_("pricing_leeway is " << pricing_leeway);
- if (std::difftime(now, commodity->last_lookup) < pricing_leeway ||
+ if (std::difftime(now, commodity.last_lookup) < pricing_leeway ||
std::difftime(now, last) < pricing_leeway ||
(price && std::difftime(moment, date) <= pricing_leeway))
return;
using namespace std;
- DEBUG_PRINT_("downloading quote for symbol " << commodity->symbol);
+ DEBUG_PRINT_("downloading quote for symbol " << commodity.symbol);
// Only consult the Internet once for any commodity
- commodity->last_lookup = now;
+ commodity.last_lookup = now;
cache_dirty = true;
char buf[256];
@@ -41,7 +41,7 @@ void quotes_by_script::operator()(commodity_t * commodity,
bool success = true;
if (FILE * fp = popen((string("getquote ") +
- commodity->symbol).c_str(), "r")) {
+ commodity.symbol).c_str(), "r")) {
if (feof(fp) || ! fgets(buf, 255, fp))
success = false;
fclose(fp);
@@ -54,13 +54,13 @@ void quotes_by_script::operator()(commodity_t * commodity,
DEBUG_PRINT_("downloaded quote: " << buf);
price.parse(buf);
- commodity->add_price(now, price);
+ commodity.add_price(now, price);
if (price && ! price_db.empty()) {
char buf[128];
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", localtime(&now));
ofstream database(price_db.c_str(), ios_base::out | ios_base::app);
- database << "P " << buf << " " << commodity->symbol
+ database << "P " << buf << " " << commodity.symbol
<< " " << price << endl;
}
}
diff --git a/quotes.h b/quotes.h
index 8418b074..53008aa0 100644
--- a/quotes.h
+++ b/quotes.h
@@ -18,7 +18,7 @@ class quotes_by_script : public commodity_t::updater_t
: price_db(_price_db), pricing_leeway(_pricing_leeway),
cache_dirty(_cache_dirty) {}
- virtual void operator()(commodity_t * commodity,
+ virtual void operator()(commodity_t& commodity,
const std::time_t moment,
const std::time_t date,
const std::time_t last,
diff --git a/textual.cc b/textual.cc
index 0e8bdee1..1c50d725 100644
--- a/textual.cc
+++ b/textual.cc
@@ -100,11 +100,6 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
xact->account = account->find_account(p);
- if (! xact->amount.commodity)
- xact->amount.commodity = commodity_t::null_commodity;
- if (xact->cost && ! xact->cost->commodity)
- xact->cost->commodity = commodity_t::null_commodity;
-
return xact.release();
}
@@ -180,7 +175,7 @@ bool finalize_entry(entry_t * entry)
= ((balance_t *) balance.data)->amounts.begin();
i != ((balance_t *) balance.data)->amounts.end();
i++)
- if ((*i).second.commodity != (*x)->amount.commodity) {
+ if ((*i).second.commodity() != (*x)->amount.commodity()) {
assert((*x)->amount);
balance -= (*x)->amount;
assert(! (*x)->cost);
@@ -401,7 +396,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
std::sprintf(buf, "%fh", diff);
amount_t amt;
amt.parse(buf);
- time_commodity = amt.commodity;
+ time_commodity = &amt.commodity();
transaction_t * xact
= new transaction_t(last_account, amt, TRANSACTION_VIRTUAL);
diff --git a/valexpr.cc b/valexpr.cc
index 07f11995..2618553e 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -218,11 +218,9 @@ void value_expr_t::compute(value_t& result, const details_t& details) const
// jww (2004-08-17): do something smarter here?
result.cast(value_t::AMOUNT);
}
- if (result.type == value_t::AMOUNT) {
- amount_t amt = result;
- amt.commodity = commodity_t::null_commodity;
- result = amt;
- }
+ // jww (2004-08-29): maybe this should be strip_commodity?
+ if (result.type == value_t::AMOUNT)
+ ((amount_t *) result.data)->set_commodity(*commodity_t::null_commodity);
break;
}
diff --git a/value.cc b/value.cc
index 8d28e506..aa1e184e 100644
--- a/value.cc
+++ b/value.cc
@@ -1,5 +1,6 @@
#include "value.h"
#include "ledger.h"
+#include "error.h"
namespace ledger {
@@ -97,9 +98,8 @@ value_t& value_t::operator OP(const value_t& value) \
cast(AMOUNT); \
\
case AMOUNT: \
- if (((amount_t *) data)->commodity && \
- ((amount_t *) data)->commodity != \
- ((amount_t *) value.data)->commodity) { \
+ if (((amount_t *) data)->commodity() != \
+ ((amount_t *) value.data)->commodity()) { \
cast(BALANCE); \
return *this OP value; \
} \
@@ -183,8 +183,7 @@ value_t& value_t::operator +=(const transaction_t& xact)
cast(BALANCE_PAIR);
return *this += xact;
}
- else if (((amount_t *) data)->commodity &&
- ((amount_t *) data)->commodity != xact.amount.commodity) {
+ else if (((amount_t *) data)->commodity() != xact.amount.commodity()) {
cast(BALANCE);
return *this += xact;
}
@@ -273,10 +272,10 @@ bool value_t::operator OP(const value_t& value) \
return *((amount_t *) data) OP *((amount_t *) value.data); \
\
case BALANCE: \
- return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) OP *((amount_t *) value.data); \
+ return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity()) OP *((amount_t *) value.data); \
\
case BALANCE_PAIR: \
- return ((balance_pair_t *) data)->quantity.amount(((amount_t *) value.data)->commodity) OP *((amount_t *) value.data); \
+ return ((balance_pair_t *) data)->quantity.amount(((amount_t *) value.data)->commodity()) OP *((amount_t *) value.data); \
\
default: \
assert(0); \
@@ -435,16 +434,17 @@ void value_t::cast(type_t cast_type)
*((bool *)data) = temp;
break;
}
- case INTEGER: {
- unsigned int temp = ((balance_t *) data)->amount();
- destroy();
- *((unsigned int *)data) = temp;
- break;
- }
+ case INTEGER:
+ throw error("Cannot convert a balance to an integer");
case AMOUNT: {
- amount_t temp = ((balance_t *) data)->amount();
- destroy();
- new((amount_t *)data) amount_t(temp);
+ balance_t * temp = (balance_t *) data;
+ if (temp->amounts.size() == 1) {
+ amount_t amt = (*temp->amounts.begin()).second;
+ destroy();
+ new((amount_t *)data) amount_t(amt);
+ } else {
+ throw error("Cannot convert a balance with multiple commodities to an amount");
+ }
break;
}
case BALANCE:
@@ -470,16 +470,18 @@ void value_t::cast(type_t cast_type)
*((bool *)data) = temp;
break;
}
- case INTEGER: {
- unsigned int temp = ((balance_pair_t *) data)->quantity.amount();
- destroy();
- *((unsigned int *)data) = temp;
- break;
- }
+ case INTEGER:
+ throw error("Cannot convert a balance pair to an integer");
+
case AMOUNT: {
- amount_t temp = ((balance_pair_t *) data)->quantity.amount();
- destroy();
- new((amount_t *)data) amount_t(temp);
+ balance_t * temp = &((balance_pair_t *) data)->quantity;
+ if (temp->amounts.size() == 1) {
+ amount_t amt = (*temp->amounts.begin()).second;
+ destroy();
+ new((amount_t *)data) amount_t(amt);
+ } else {
+ throw error("Cannot convert a balance pair with multiple commodities to an amount");
+ }
break;
}
case BALANCE: {