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 "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)

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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() {

View file

@ -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);

View file

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

View file

@ -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;

View file

@ -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
View file

@ -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;

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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);

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?
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;
}

View file

@ -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: {