redid the way amount_t::commodity is handled; no more direct access

This commit is contained in:
John Wiegley 2004-08-29 04:31:59 -04:00
parent 032afa5657
commit 2d62f7b633
15 changed files with 225 additions and 226 deletions

167
amount.cc
View file

@ -1,4 +1,3 @@
#include "ledger.h"
#include "amount.h" #include "amount.h"
#include "binary.h" #include "binary.h"
#include "error.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 // Since the journal in which this price was bulk alloc'd (on
// reading from a binary file) is going away, we must make a // reading from a binary file) is going away, we must make a
// new copy of the value, which other journals might still be // new copy of the value, because other journals might still
// using. // be using it.
amount_t::bigint_t * q = new amount_t::bigint_t(*quantity); amount_t::bigint_t * q = new amount_t::bigint_t(*quantity);
if (--quantity->ref == 0) if (--quantity->ref == 0)
@ -168,11 +167,10 @@ amount_t::amount_t(const bool value)
if (value) { if (value) {
quantity = &true_value; quantity = &true_value;
quantity->ref++; quantity->ref++;
commodity = commodity_t::null_commodity;
} else { } else {
quantity = NULL; quantity = NULL;
commodity = NULL;
} }
commodity_ = NULL;
} }
amount_t::amount_t(const int value) amount_t::amount_t(const int value)
@ -182,11 +180,10 @@ amount_t::amount_t(const int value)
if (value != 0) { if (value != 0) {
quantity = new bigint_t; quantity = new bigint_t;
mpz_set_si(MPZ(quantity), value); mpz_set_si(MPZ(quantity), value);
commodity = commodity_t::null_commodity;
} else { } else {
quantity = NULL; quantity = NULL;
commodity = NULL;
} }
commodity_ = NULL;
} }
amount_t::amount_t(const unsigned int value) amount_t::amount_t(const unsigned int value)
@ -196,11 +193,10 @@ amount_t::amount_t(const unsigned int value)
if (value != 0) { if (value != 0) {
quantity = new bigint_t; quantity = new bigint_t;
mpz_set_ui(MPZ(quantity), value); mpz_set_ui(MPZ(quantity), value);
commodity = commodity_t::null_commodity;
} else { } else {
quantity = NULL; quantity = NULL;
commodity = NULL;
} }
commodity_ = NULL;
} }
amount_t::amount_t(const double value) amount_t::amount_t(const double value)
@ -211,11 +207,10 @@ amount_t::amount_t(const double value)
quantity = new bigint_t; quantity = new bigint_t;
mpz_set_d(MPZ(quantity), value); mpz_set_d(MPZ(quantity), value);
// jww (2004-08-20): How do I calculate this? // jww (2004-08-20): How do I calculate this?
commodity = commodity_t::null_commodity;
} else { } else {
quantity = NULL; quantity = NULL;
commodity = NULL;
} }
commodity_ = NULL;
} }
void amount_t::_release() void amount_t::_release()
@ -257,7 +252,7 @@ void amount_t::_copy(const amount_t& amt)
quantity = amt.quantity; quantity = amt.quantity;
quantity->ref++; quantity->ref++;
} }
commodity = amt.commodity; commodity_ = amt.commodity_;
} }
amount_t& amount_t::operator=(const std::string& value) amount_t& amount_t::operator=(const std::string& value)
@ -293,7 +288,7 @@ amount_t& amount_t::operator=(const bool value)
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
commodity = commodity_t::null_commodity; commodity_ = NULL;
if (quantity) if (quantity)
_release(); _release();
quantity = &true_value; quantity = &true_value;
@ -308,7 +303,7 @@ amount_t& amount_t::operator=(const int value)
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
commodity = commodity_t::null_commodity; commodity_ = NULL;
_init(); _init();
mpz_set_si(MPZ(quantity), value); mpz_set_si(MPZ(quantity), value);
} }
@ -321,7 +316,7 @@ amount_t& amount_t::operator=(const unsigned int value)
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
commodity = commodity_t::null_commodity; commodity_ = NULL;
_init(); _init();
mpz_set_ui(MPZ(quantity), value); mpz_set_ui(MPZ(quantity), value);
} }
@ -334,7 +329,7 @@ amount_t& amount_t::operator=(const double value)
if (quantity) if (quantity)
_clear(); _clear();
} else { } else {
commodity = commodity_t::null_commodity; commodity_ = NULL;
_init(); _init();
// jww (2004-08-20): How do I calculate precision? // jww (2004-08-20): How do I calculate precision?
mpz_set_d(MPZ(quantity), value); mpz_set_d(MPZ(quantity), value);
@ -376,7 +371,7 @@ amount_t& amount_t::operator+=(const amount_t& amt)
_dup(); _dup();
if (commodity != amt.commodity) if (commodity_ != amt.commodity_)
throw amount_error("Adding amounts with different commodities"); throw amount_error("Adding amounts with different commodities");
if (quantity->prec == amt.quantity->prec) { if (quantity->prec == amt.quantity->prec) {
@ -401,14 +396,14 @@ amount_t& amount_t::operator-=(const amount_t& amt)
if (! quantity) { if (! quantity) {
quantity = new bigint_t(*amt.quantity); quantity = new bigint_t(*amt.quantity);
commodity = amt.commodity; commodity_ = amt.commodity_;
mpz_neg(MPZ(quantity), MPZ(quantity)); mpz_neg(MPZ(quantity), MPZ(quantity));
return *this; return *this;
} }
_dup(); _dup();
if (commodity != amt.commodity) if (commodity_ != amt.commodity_)
throw amount_error("Subtracting amounts with different commodities"); throw amount_error("Subtracting amounts with different commodities");
if (quantity->prec == amt.quantity->prec) { 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)); mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
quantity->prec += amt.quantity->prec; quantity->prec += amt.quantity->prec;
if (quantity->prec > commodity->precision + 6U) { unsigned int comm_prec = commodity().precision;
mpz_round(MPZ(quantity), MPZ(quantity), if (quantity->prec > comm_prec + 6U) {
quantity->prec, commodity->precision + 6U); mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
quantity->prec = commodity->precision + 6U; quantity->prec = comm_prec + 6U;
} }
return *this; 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)); mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
quantity->prec += 6; quantity->prec += 6;
if (quantity->prec > commodity->precision + 6U) { unsigned int comm_prec = commodity().precision;
mpz_round(MPZ(quantity), MPZ(quantity), if (quantity->prec > comm_prec + 6U) {
quantity->prec, commodity->precision + 6U); mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
quantity->prec = commodity->precision + 6U; quantity->prec = comm_prec + 6U;
} }
return *this; return *this;
@ -536,9 +531,8 @@ bool amount_t::operator OP(const amount_t& amt) const \
if (! amt.quantity) \ if (! amt.quantity) \
return *this < 0; \ return *this < 0; \
\ \
if (commodity != amt.commodity && \ if (commodity() && amt.commodity() && \
commodity != commodity_t::null_commodity && \ commodity() != amt.commodity()) \
amt.commodity != commodity_t::null_commodity) \
return false; \ return false; \
\ \
if (quantity->prec == amt.quantity->prec) { \ if (quantity->prec == amt.quantity->prec) { \
@ -567,12 +561,12 @@ amount_t::operator bool() const
if (! quantity) if (! quantity)
return false; return false;
if (quantity->prec <= commodity->precision) { if (quantity->prec <= commodity().precision) {
return mpz_sgn(MPZ(quantity)) != 0; return mpz_sgn(MPZ(quantity)) != 0;
} else { } else {
assert(commodity); assert(commodity_);
mpz_set(temp, MPZ(quantity)); 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); mpz_tdiv_q(temp, temp, divisor);
bool zero = mpz_sgn(temp) == 0; bool zero = mpz_sgn(temp) == 0;
return ! zero; return ! zero;
@ -581,9 +575,9 @@ amount_t::operator bool() const
amount_t amount_t::value(const std::time_t moment) const amount_t amount_t::value(const std::time_t moment) const
{ {
if (quantity && ! (commodity->flags & COMMODITY_STYLE_NOMARKET)) if (quantity && ! (commodity().flags & COMMODITY_STYLE_NOMARKET))
if (amount_t amt = commodity->value(moment)) if (amount_t amt = commodity().value(moment))
return (amt * *this).round(commodity->precision); return (amt * *this).round(commodity().precision);
return *this; 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 // Ensure the value is rounded to the commodity's precision before
// outputting it. NOTE: `rquotient' is used here as a temp variable! // 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, mpz_round(rquotient, MPZ(amt.quantity), amt.quantity->prec,
amt.commodity->precision); commodity.precision);
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision); mpz_ui_pow_ui(divisor, 10, commodity.precision);
mpz_tdiv_qr(quotient, remainder, rquotient, divisor); mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
} }
else if (amt.commodity->precision > amt.quantity->prec) { else if (commodity.precision > amt.quantity->prec) {
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision - amt.quantity->prec); mpz_ui_pow_ui(divisor, 10, commodity.precision - amt.quantity->prec);
mpz_mul(rquotient, MPZ(amt.quantity), divisor); 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); mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
} }
else if (amt.quantity->prec) { else if (amt.quantity->prec) {
@ -651,12 +647,12 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
} }
mpz_set(rquotient, remainder); mpz_set(rquotient, remainder);
if (! (amt.commodity->flags & COMMODITY_STYLE_SUFFIXED)) { if (! (commodity.flags & COMMODITY_STYLE_SUFFIXED)) {
if (amt.commodity->quote) if (commodity.quote)
out << "\"" << amt.commodity->symbol << "\""; out << "\"" << commodity.symbol << "\"";
else else
out << amt.commodity->symbol; out << commodity.symbol;
if (amt.commodity->flags & COMMODITY_STYLE_SEPARATED) if (commodity.flags & COMMODITY_STYLE_SEPARATED)
out << " "; out << " ";
} }
@ -666,7 +662,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
if (mpz_sgn(quotient) == 0) { if (mpz_sgn(quotient) == 0) {
out << '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); char * p = mpz_get_str(NULL, 10, quotient);
out << p; out << p;
std::free(p); std::free(p);
@ -695,7 +691,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
i != strs.rend(); i != strs.rend();
i++) { i++) {
if (printed) { if (printed) {
out << (amt.commodity->flags & COMMODITY_STYLE_EUROPEAN ? '.' : ','); out << (commodity.flags & COMMODITY_STYLE_EUROPEAN ? '.' : ',');
out.width(3); out.width(3);
out.fill('0'); out.fill('0');
} }
@ -705,10 +701,10 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
} }
} }
if (amt.commodity->precision) { if (commodity.precision) {
out << ((amt.commodity->flags & COMMODITY_STYLE_EUROPEAN) ? ',' : '.'); out << ((commodity.flags & COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
out.width(amt.commodity->precision); out.width(commodity.precision);
out.fill('0'); out.fill('0');
char * p = mpz_get_str(NULL, 10, rquotient); 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); std::free(p);
} }
if (amt.commodity->flags & COMMODITY_STYLE_SUFFIXED) { if (commodity.flags & COMMODITY_STYLE_SUFFIXED) {
if (amt.commodity->flags & COMMODITY_STYLE_SEPARATED) if (commodity.flags & COMMODITY_STYLE_SEPARATED)
out << " "; out << " ";
if (amt.commodity->quote) if (commodity.quote)
out << "\"" << amt.commodity->symbol << "\""; out << "\"" << commodity.symbol << "\"";
else else
out << amt.commodity->symbol; out << commodity.symbol;
} }
mpz_clear(quotient); mpz_clear(quotient);
@ -825,10 +821,10 @@ void amount_t::parse(std::istream& in)
} }
// Create the commodity if has not already been seen. // Create the commodity if has not already been seen.
commodity = commodity_t::find_commodity(symbol, true); commodity_ = commodity_t::find_commodity(symbol, true);
commodity->flags |= flags; commodity_->flags |= flags;
if (quantity->prec > commodity->precision) if (quantity->prec > commodity_->precision)
commodity->precision = quantity->prec; commodity_->precision = quantity->prec;
// Now we have the final number. Remove commas and periods, if // Now we have the final number. Remove commas and periods, if
// necessary. // 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 bool amount_t::valid() const
{ {
if (quantity) { if (quantity) {
if (! commodity) if (! commodity_)
return false; return false;
if (quantity->ref == 0) if (quantity->ref == 0)
return false; return false;
} }
else if (commodity) { else if (commodity_) {
return false; return false;
} }
@ -1029,9 +993,8 @@ amount_t commodity_t::value(const std::time_t moment)
} }
if (updater) if (updater)
(*updater)(this, moment, age, (*updater)(*this, moment, age, (history.size() > 0 ?
history.size() > 0 ? (*history.rbegin()).first : 0, price); (*history.rbegin()).first : 0), price);
return price; return price;
} }
@ -1053,7 +1016,7 @@ struct commodity_updater_wrap : public commodity_t::updater_t
PyObject * self; PyObject * self;
commodity_updater_wrap(PyObject * self_) : self(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 moment,
const std::time_t date, const std::time_t date,
const std::time_t last, const std::time_t last,
@ -1073,7 +1036,9 @@ void export_amount()
.def(init<unsigned int>()) .def(init<unsigned int>())
.def(init<double>()) .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)
.def(self + self) .def(self + self)
@ -1127,8 +1092,6 @@ void export_amount()
.def_readwrite("conversion", &commodity_t::conversion) .def_readwrite("conversion", &commodity_t::conversion)
.def_readwrite("ident", &commodity_t::ident) .def_readwrite("ident", &commodity_t::ident)
.def_readwrite("updater", &commodity_t::updater) .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("add_commodity", &commodity_t::add_commodity)
.def("remove_commodity", &commodity_t::remove_commodity) .def("remove_commodity", &commodity_t::remove_commodity)

View file

@ -15,6 +15,10 @@ class commodity_t;
class amount_t class amount_t
{ {
public:
class bigint_t;
protected:
void _init(); void _init();
void _copy(const amount_t& amt); void _copy(const amount_t& amt);
void _release(); void _release();
@ -23,23 +27,21 @@ class amount_t
void _clear() { void _clear() {
if (quantity) { if (quantity) {
assert(commodity); assert(commodity_);
_release(); _release();
quantity = NULL; quantity = NULL;
commodity = NULL; commodity_ = NULL;
} else { } else {
assert(! commodity); assert(! commodity_);
} }
} }
public:
class bigint_t;
bigint_t * quantity; bigint_t * quantity;
commodity_t * commodity; commodity_t * commodity_;
public:
// constructors // constructors
amount_t() : quantity(NULL), commodity(NULL) { amount_t() : quantity(NULL), commodity_(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
} }
amount_t(const amount_t& amt) : quantity(NULL) { amount_t(const amount_t& amt) : quantity(NULL) {
@ -47,7 +49,7 @@ class amount_t
if (amt.quantity) if (amt.quantity)
_copy(amt); _copy(amt);
else else
commodity = NULL; commodity_ = NULL;
} }
amount_t(const std::string& value) : quantity(NULL) { amount_t(const std::string& value) : quantity(NULL) {
DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
@ -69,6 +71,11 @@ class amount_t
_release(); _release();
} }
commodity_t& commodity() const;
void set_commodity(commodity_t& comm) {
commodity_ = &comm;
}
// assignment operator // assignment operator
amount_t& operator=(const amount_t& amt); amount_t& operator=(const amount_t& amt);
amount_t& operator=(const std::string& value); 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; 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 true;
return ! (*this == amt); return ! (*this == amt);
} }
@ -164,13 +171,27 @@ class amount_t
void parse(std::istream& in); void parse(std::istream& in);
void parse(const std::string& str); void parse(const std::string& str);
void write_quantity(std::ostream& out) const;
void read_quantity(char *& data); void read_quantity(char *& data);
void read_quantity(std::istream& in); void write_quantity(std::ostream& out) const;
bool valid() 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 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(); unsigned int sizeof_bigint_t();
@ -209,7 +230,7 @@ class commodity_t
class updater_t { class updater_t {
public: public:
virtual ~updater_t() {} virtual ~updater_t() {}
virtual void operator()(commodity_t * commodity, virtual void operator()(commodity_t& commodity,
const std::time_t moment, const std::time_t moment,
const std::time_t date, const std::time_t date,
const std::time_t last, const std::time_t last,
@ -273,6 +294,16 @@ class commodity_t
} }
#endif #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() { void check_symbol() {
for (const char * p = symbol.c_str(); *p; p++) for (const char * p = symbol.c_str(); *p; p++)
if (std::isspace(*p) || std::isdigit(*p) || *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 } // namespace ledger
#endif // _AMOUNT_H #endif // _AMOUNT_H

View file

@ -15,7 +15,7 @@ void automated_transaction_t::extend_entry(entry_t * entry)
t != transactions.end(); t != transactions.end();
t++) { t++) {
amount_t amt; amount_t amt;
if ((*t)->amount.commodity->symbol.empty()) if ((*t)->amount.commodity().symbol.empty())
amt = (*i)->amount * (*t)->amount; amt = (*i)->amount * (*t)->amount;
else else
amt = (*t)->amount; amt = (*t)->amount;

View file

@ -5,7 +5,7 @@
namespace ledger { 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 (! commodity) {
if (amounts.size() == 1) { if (amounts.size() == 1) {
@ -14,7 +14,7 @@ amount_t balance_t::amount(const commodity_t * commodity) const
} }
} }
else if (amounts.size() > 0) { 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()) if (i != amounts.end())
return (*i).second; return (*i).second;
} }
@ -35,7 +35,7 @@ balance_t balance_t::value(const std::time_t moment) const
struct compare_amount_commodities { struct compare_amount_commodities {
bool operator()(const amount_t * left, const amount_t * right) const { 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<unsigned int>())
.def(init<double>()) .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 += self)
.def(self += other<amount_t>()) .def(self += other<amount_t>())
.def(self + self) .def(self + self)

View file

@ -6,6 +6,7 @@
#include <iostream> #include <iostream>
#include "amount.h" #include "amount.h"
#include "error.h"
namespace ledger { namespace ledger {
@ -40,25 +41,25 @@ class balance_t
balance_t(const amount_t& amt) { balance_t(const amount_t& amt) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
if (amt) if (amt)
amounts.insert(amounts_pair(amt.commodity, amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
} }
balance_t(const int value) { balance_t(const int value) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
amount_t amt(value); amount_t amt(value);
if (amt) if (amt)
amounts.insert(amounts_pair(amt.commodity, amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
} }
balance_t(const unsigned int value) { balance_t(const unsigned int value) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
amount_t amt(value); amount_t amt(value);
if (amt) if (amt)
amounts.insert(amounts_pair(amt.commodity, amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
} }
balance_t(const double value) { balance_t(const double value) {
DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
amount_t amt(value); amount_t amt(value);
if (amt) if (amt)
amounts.insert(amounts_pair(amt.commodity, amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
} }
// destructor // destructor
@ -109,11 +110,11 @@ class balance_t
return *this; return *this;
} }
balance_t& operator+=(const amount_t& amt) { 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()) if (i != amounts.end())
(*i).second += amt; (*i).second += amt;
else if (amt) else if (amt)
amounts.insert(amounts_pair(amt.commodity, amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
return *this; return *this;
} }
balance_t& operator-=(const balance_t& bal) { balance_t& operator-=(const balance_t& bal) {
@ -124,11 +125,11 @@ class balance_t
return *this; return *this;
} }
balance_t& operator-=(const amount_t& amt) { 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()) if (i != amounts.end())
(*i).second -= amt; (*i).second -= amt;
else if (amt) else if (amt)
amounts.insert(amounts_pair(amt.commodity, amt)); amounts.insert(amounts_pair(&amt.commodity(), amt));
return *this; return *this;
} }
@ -165,13 +166,13 @@ class balance_t
balance_t& operator*=(const amount_t& amt) { balance_t& operator*=(const amount_t& amt) {
// Multiplying by the null commodity causes all amounts to be // Multiplying by the null commodity causes all amounts to be
// increased by the same factor. // increased by the same factor.
if (amt.commodity->symbol.empty()) { if (amt.commodity().symbol.empty()) {
for (amounts_map::iterator i = amounts.begin(); for (amounts_map::iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) i++)
(*i).second *= amt; (*i).second *= amt;
} else { } else {
amounts_map::iterator i = amounts.find(amt.commodity); amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end()) if (i != amounts.end())
(*i).second *= amt; (*i).second *= amt;
} }
@ -188,13 +189,13 @@ class balance_t
balance_t& operator/=(const amount_t& amt) { balance_t& operator/=(const amount_t& amt) {
// Dividing by the null commodity causes all amounts to be // Dividing by the null commodity causes all amounts to be
// increased by the same factor. // increased by the same factor.
if (amt.commodity->symbol.empty()) { if (amt.commodity().symbol.empty()) {
for (amounts_map::iterator i = amounts.begin(); for (amounts_map::iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) i++)
(*i).second /= amt; (*i).second /= amt;
} else { } else {
amounts_map::iterator i = amounts.find(amt.commodity); amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end()) if (i != amounts.end())
(*i).second /= amt; (*i).second /= amt;
} }
@ -228,13 +229,13 @@ class balance_t
for (amounts_map::const_iterator i = bal.amounts.begin(); for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end(); i != bal.amounts.end();
i++) i++)
if (! (amount((*i).first) < (*i).second)) if (! (amount(*(*i).first) < (*i).second))
return false; return false;
for (amounts_map::const_iterator i = amounts.begin(); for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) i++)
if (! ((*i).second < bal.amount((*i).first))) if (! ((*i).second < bal.amount(*(*i).first)))
return false; return false;
if (bal.amounts.size() == 0 && amounts.size() == 0) if (bal.amounts.size() == 0 && amounts.size() == 0)
@ -246,41 +247,43 @@ class balance_t
for (amounts_map::const_iterator i = bal.amounts.begin(); for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end(); i != bal.amounts.end();
i++) i++)
if (! (amount((*i).first) <= (*i).second)) if (! (amount(*(*i).first) <= (*i).second))
return false; return false;
for (amounts_map::const_iterator i = amounts.begin(); for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) i++)
if (! ((*i).second <= bal.amount((*i).first))) if (! ((*i).second <= bal.amount(*(*i).first)))
return false; return false;
return true; return true;
} }
bool operator<(const amount_t& amt) const { bool operator<(const amount_t& amt) const {
return amount(amt.commodity) < amt; return amount(amt.commodity()) < amt;
} }
bool operator<=(const amount_t& amt) const { 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 { bool operator<(const unsigned int val) const {
return amount() < val; return amount() < val;
} }
bool operator<=(const unsigned int val) const { bool operator<=(const unsigned int val) const {
return amount() <= val; return amount() <= val;
} }
#endif
bool operator>(const balance_t& bal) const { bool operator>(const balance_t& bal) const {
for (amounts_map::const_iterator i = bal.amounts.begin(); for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end(); i != bal.amounts.end();
i++) i++)
if (! (amount((*i).first) > (*i).second)) if (! (amount(*(*i).first) > (*i).second))
return false; return false;
for (amounts_map::const_iterator i = amounts.begin(); for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) i++)
if (! ((*i).second > bal.amount((*i).first))) if (! ((*i).second > bal.amount(*(*i).first)))
return false; return false;
if (bal.amounts.size() == 0 && amounts.size() == 0) if (bal.amounts.size() == 0 && amounts.size() == 0)
@ -292,29 +295,31 @@ class balance_t
for (amounts_map::const_iterator i = bal.amounts.begin(); for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end(); i != bal.amounts.end();
i++) i++)
if (! (amount((*i).first) >= (*i).second)) if (! (amount(*(*i).first) >= (*i).second))
return false; return false;
for (amounts_map::const_iterator i = amounts.begin(); for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end(); i != amounts.end();
i++) i++)
if (! ((*i).second >= bal.amount((*i).first))) if (! ((*i).second >= bal.amount(*(*i).first)))
return false; return false;
return true; return true;
} }
bool operator>(const amount_t& amt) const { bool operator>(const amount_t& amt) const {
return amount(amt.commodity) > amt; return amount(amt.commodity()) > amt;
} }
bool operator>=(const amount_t& amt) const { 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 { bool operator>(const unsigned int val) const {
return amount() > val; return amount() > val;
} }
bool operator>=(const unsigned int val) const { bool operator>=(const unsigned int val) const {
return amount() >= val; return amount() >= val;
} }
#endif
bool operator==(const balance_t& bal) const { bool operator==(const balance_t& bal) const {
amounts_map::const_iterator i, j; amounts_map::const_iterator i, j;
@ -327,21 +332,23 @@ class balance_t
} }
return i == amounts.end() && j == bal.amounts.end(); 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 { bool operator!=(const balance_t& bal) const {
return ! (*this == bal); 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 { bool operator!=(const amount_t& amt) const {
return ! (*this == amt); return ! (*this == amt);
} }
#if 0
bool operator==(const unsigned int val) const {
return amount() == val;
}
bool operator!=(const unsigned int val) const { bool operator!=(const unsigned int val) const {
return ! (*this == val); return ! (*this == val);
} }
#endif
// unary negation // unary negation
balance_t& negate() { balance_t& negate() {
@ -362,7 +369,10 @@ class balance_t
// conversion operators // conversion operators
operator amount_t() const { 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 { operator bool() const {
for (amounts_map::const_iterator i = amounts.begin(); for (amounts_map::const_iterator i = amounts.begin();
@ -373,7 +383,7 @@ class balance_t
return false; 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; balance_t value(const std::time_t moment) const;
void write(std::ostream& out, void write(std::ostream& out,
@ -754,8 +764,10 @@ class balance_pair_t
return quantity; return quantity;
} }
operator amount_t() const { operator amount_t() const {
assert(0); if (quantity.amounts.size() == 1)
return quantity.amount(); return (*quantity.amounts.begin()).second;
else
throw error("Cannot convert a balance pair with multiple commodities to an amount");
} }
void abs() { void abs() {

View file

@ -165,9 +165,9 @@ inline void read_binary_amount(char *& data, amount_t& amt)
commodity_t::ident_t ident; commodity_t::ident_t ident;
read_binary_number(data, ident); read_binary_number(data, ident);
if (ident == 0xffffffff) if (ident == 0xffffffff)
amt.commodity = NULL; amt.commodity_ = NULL;
else else
amt.commodity = commodities[ident - 1]; amt.commodity_ = commodities[ident - 1];
amt.read_quantity(data); 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) void write_binary_amount(std::ostream& out, const amount_t& amt)
{ {
if (amt.commodity) if (amt.commodity_)
write_binary_number(out, amt.commodity->ident); write_binary_number(out, amt.commodity().ident);
else else
write_binary_number<commodity_t::ident_t>(out, 0xffffffff); write_binary_number<commodity_t::ident_t>(out, 0xffffffff);

View file

@ -1,6 +1,7 @@
#ifndef _BINARY_H #ifndef _BINARY_H
#define _BINARY_H #define _BINARY_H
#include "ledger.h"
#include "parser.h" #include "parser.h"
#include <deque> #include <deque>

View file

@ -235,10 +235,10 @@ static void dataHandler(void *userData, const char *s, int len)
} }
commodity_t * default_commodity = (*ac).second; 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); amount_t value = curr_quant.round(default_commodity->precision);
if (curr_value.commodity == default_commodity) if (curr_value.commodity() == *default_commodity)
curr_value = value; curr_value = value;
xact->amount = value; xact->amount = value;

View file

@ -246,12 +246,9 @@ bool journal_t::add_entry(entry_t * entry)
i != entry->transactions.end(); i != entry->transactions.end();
i++) { i++) {
(*i)->account->add_transaction(*i); (*i)->account->add_transaction(*i);
if ((*i)->cost)
if ((*i)->cost) { (*i)->amount.commodity().add_price(entry->date,
assert((*i)->cost->commodity); *(*i)->cost / (*i)->amount);
(*i)->amount.commodity->add_price(entry->date,
*(*i)->cost / (*i)->amount);
}
} }
return true; 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); first = xact = new transaction_t(m_xact->account, amt);
added->add_transaction(xact); added->add_transaction(xact);
if (xact->amount.commodity->symbol.empty()) if (xact->amount.commodity().symbol.empty())
xact->amount.commodity = m_xact->amount.commodity; xact->amount.set_commodity(m_xact->amount.commodity());
m_xact = matching->transactions.back(); m_xact = matching->transactions.back();
@ -355,7 +352,7 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
x++) { x++) {
if (acct_regex.match((*x)->account->fullname())) { if (acct_regex.match((*x)->account->fullname())) {
acct = (*x)->account; acct = (*x)->account;
cmdty = (*x)->amount.commodity; cmdty = &(*x)->amount.commodity();
break; break;
} }
} }
@ -379,8 +376,8 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
transaction_t * xact = new transaction_t(acct, amt); transaction_t * xact = new transaction_t(acct, amt);
added->add_transaction(xact); added->add_transaction(xact);
if (! xact->amount.commodity) if (! xact->amount.commodity())
xact->amount.commodity = cmdty; xact->amount.set_commodity(*cmdty);
} }
if (i != end && std::string(*i++) == "-from" && i != end) { if (i != end && std::string(*i++) == "-from" && i != end) {

2
qif.cc
View file

@ -96,7 +96,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
xact->amount.parse(line); xact->amount.parse(line);
if (! def_commodity) if (! def_commodity)
def_commodity = commodity_t::find_commodity("$", true); def_commodity = commodity_t::find_commodity("$", true);
xact->amount.commodity = def_commodity; xact->amount.set_commodity(*def_commodity);
if (c == '$') if (c == '$')
xact->amount.negate(); xact->amount.negate();
break; break;

View file

@ -6,7 +6,7 @@
namespace ledger { 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 moment,
const std::time_t date, const std::time_t date,
const std::time_t last, const std::time_t last,
@ -14,25 +14,25 @@ void quotes_by_script::operator()(commodity_t * commodity,
{ {
DEBUG_CLASS("ledger.quotes.download"); DEBUG_CLASS("ledger.quotes.download");
DEBUG_PRINT_("commodity: " << commodity->symbol); DEBUG_PRINT_("commodity: " << commodity.symbol);
DEBUG_PRINT_TIME_(now); DEBUG_PRINT_TIME_(now);
DEBUG_PRINT_TIME_(moment); DEBUG_PRINT_TIME_(moment);
DEBUG_PRINT_TIME_(date); DEBUG_PRINT_TIME_(date);
DEBUG_PRINT_TIME_(last); DEBUG_PRINT_TIME_(last);
DEBUG_PRINT_TIME_(commodity->last_lookup); DEBUG_PRINT_TIME_(commodity.last_lookup);
DEBUG_PRINT_("pricing_leeway is " << pricing_leeway); 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 || std::difftime(now, last) < pricing_leeway ||
(price && std::difftime(moment, date) <= pricing_leeway)) (price && std::difftime(moment, date) <= pricing_leeway))
return; return;
using namespace std; 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 // Only consult the Internet once for any commodity
commodity->last_lookup = now; commodity.last_lookup = now;
cache_dirty = true; cache_dirty = true;
char buf[256]; char buf[256];
@ -41,7 +41,7 @@ void quotes_by_script::operator()(commodity_t * commodity,
bool success = true; bool success = true;
if (FILE * fp = popen((string("getquote ") + if (FILE * fp = popen((string("getquote ") +
commodity->symbol).c_str(), "r")) { commodity.symbol).c_str(), "r")) {
if (feof(fp) || ! fgets(buf, 255, fp)) if (feof(fp) || ! fgets(buf, 255, fp))
success = false; success = false;
fclose(fp); fclose(fp);
@ -54,13 +54,13 @@ void quotes_by_script::operator()(commodity_t * commodity,
DEBUG_PRINT_("downloaded quote: " << buf); DEBUG_PRINT_("downloaded quote: " << buf);
price.parse(buf); price.parse(buf);
commodity->add_price(now, price); commodity.add_price(now, price);
if (price && ! price_db.empty()) { if (price && ! price_db.empty()) {
char buf[128]; char buf[128];
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", localtime(&now)); strftime(buf, 127, "%Y/%m/%d %H:%M:%S", localtime(&now));
ofstream database(price_db.c_str(), ios_base::out | ios_base::app); ofstream database(price_db.c_str(), ios_base::out | ios_base::app);
database << "P " << buf << " " << commodity->symbol database << "P " << buf << " " << commodity.symbol
<< " " << price << endl; << " " << price << endl;
} }
} }

View file

@ -18,7 +18,7 @@ class quotes_by_script : public commodity_t::updater_t
: price_db(_price_db), pricing_leeway(_pricing_leeway), : price_db(_price_db), pricing_leeway(_pricing_leeway),
cache_dirty(_cache_dirty) {} 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 moment,
const std::time_t date, const std::time_t date,
const std::time_t last, const std::time_t last,

View file

@ -100,11 +100,6 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
xact->account = account->find_account(p); 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(); return xact.release();
} }
@ -180,7 +175,7 @@ bool finalize_entry(entry_t * entry)
= ((balance_t *) balance.data)->amounts.begin(); = ((balance_t *) balance.data)->amounts.begin();
i != ((balance_t *) balance.data)->amounts.end(); i != ((balance_t *) balance.data)->amounts.end();
i++) i++)
if ((*i).second.commodity != (*x)->amount.commodity) { if ((*i).second.commodity() != (*x)->amount.commodity()) {
assert((*x)->amount); assert((*x)->amount);
balance -= (*x)->amount; balance -= (*x)->amount;
assert(! (*x)->cost); assert(! (*x)->cost);
@ -401,7 +396,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
std::sprintf(buf, "%fh", diff); std::sprintf(buf, "%fh", diff);
amount_t amt; amount_t amt;
amt.parse(buf); amt.parse(buf);
time_commodity = amt.commodity; time_commodity = &amt.commodity();
transaction_t * xact transaction_t * xact
= new transaction_t(last_account, amt, TRANSACTION_VIRTUAL); = new transaction_t(last_account, amt, TRANSACTION_VIRTUAL);

View file

@ -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? // jww (2004-08-17): do something smarter here?
result.cast(value_t::AMOUNT); result.cast(value_t::AMOUNT);
} }
if (result.type == value_t::AMOUNT) { // jww (2004-08-29): maybe this should be strip_commodity?
amount_t amt = result; if (result.type == value_t::AMOUNT)
amt.commodity = commodity_t::null_commodity; ((amount_t *) result.data)->set_commodity(*commodity_t::null_commodity);
result = amt;
}
break; break;
} }

View file

@ -1,5 +1,6 @@
#include "value.h" #include "value.h"
#include "ledger.h" #include "ledger.h"
#include "error.h"
namespace ledger { namespace ledger {
@ -97,9 +98,8 @@ value_t& value_t::operator OP(const value_t& value) \
cast(AMOUNT); \ cast(AMOUNT); \
\ \
case AMOUNT: \ case AMOUNT: \
if (((amount_t *) data)->commodity && \ if (((amount_t *) data)->commodity() != \
((amount_t *) data)->commodity != \ ((amount_t *) value.data)->commodity()) { \
((amount_t *) value.data)->commodity) { \
cast(BALANCE); \ cast(BALANCE); \
return *this OP value; \ return *this OP value; \
} \ } \
@ -183,8 +183,7 @@ value_t& value_t::operator +=(const transaction_t& xact)
cast(BALANCE_PAIR); cast(BALANCE_PAIR);
return *this += xact; return *this += xact;
} }
else if (((amount_t *) data)->commodity && else if (((amount_t *) data)->commodity() != xact.amount.commodity()) {
((amount_t *) data)->commodity != xact.amount.commodity) {
cast(BALANCE); cast(BALANCE);
return *this += xact; 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); \ return *((amount_t *) data) OP *((amount_t *) value.data); \
\ \
case BALANCE: \ 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: \ 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: \ default: \
assert(0); \ assert(0); \
@ -435,16 +434,17 @@ void value_t::cast(type_t cast_type)
*((bool *)data) = temp; *((bool *)data) = temp;
break; break;
} }
case INTEGER: { case INTEGER:
unsigned int temp = ((balance_t *) data)->amount(); throw error("Cannot convert a balance to an integer");
destroy();
*((unsigned int *)data) = temp;
break;
}
case AMOUNT: { case AMOUNT: {
amount_t temp = ((balance_t *) data)->amount(); balance_t * temp = (balance_t *) data;
destroy(); if (temp->amounts.size() == 1) {
new((amount_t *)data) amount_t(temp); 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; break;
} }
case BALANCE: case BALANCE:
@ -470,16 +470,18 @@ void value_t::cast(type_t cast_type)
*((bool *)data) = temp; *((bool *)data) = temp;
break; break;
} }
case INTEGER: { case INTEGER:
unsigned int temp = ((balance_pair_t *) data)->quantity.amount(); throw error("Cannot convert a balance pair to an integer");
destroy();
*((unsigned int *)data) = temp;
break;
}
case AMOUNT: { case AMOUNT: {
amount_t temp = ((balance_pair_t *) data)->quantity.amount(); balance_t * temp = &((balance_pair_t *) data)->quantity;
destroy(); if (temp->amounts.size() == 1) {
new((amount_t *)data) amount_t(temp); 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; break;
} }
case BALANCE: { case BALANCE: {