redid the way amount_t::commodity is handled; no more direct access
This commit is contained in:
parent
032afa5657
commit
2d62f7b633
15 changed files with 225 additions and 226 deletions
167
amount.cc
167
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)
|
||||
|
|
|
|||
66
amount.h
66
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
13
balance.cc
13
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)
|
||||
|
|
|
|||
80
balance.h
80
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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
1
binary.h
1
binary.h
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _BINARY_H
|
||||
#define _BINARY_H
|
||||
|
||||
#include "ledger.h"
|
||||
#include "parser.h"
|
||||
|
||||
#include <deque>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
19
journal.cc
19
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) {
|
||||
|
|
|
|||
2
qif.cc
2
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;
|
||||
|
|
|
|||
18
quotes.cc
18
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
quotes.h
2
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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
52
value.cc
52
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: {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue