diff options
-rw-r--r-- | amount.cc | 167 | ||||
-rw-r--r-- | amount.h | 66 | ||||
-rw-r--r-- | autoxact.cc | 2 | ||||
-rw-r--r-- | balance.cc | 13 | ||||
-rw-r--r-- | balance.h | 80 | ||||
-rw-r--r-- | binary.cc | 8 | ||||
-rw-r--r-- | binary.h | 1 | ||||
-rw-r--r-- | gnucash.cc | 4 | ||||
-rw-r--r-- | journal.cc | 19 | ||||
-rw-r--r-- | qif.cc | 2 | ||||
-rw-r--r-- | quotes.cc | 18 | ||||
-rw-r--r-- | quotes.h | 2 | ||||
-rw-r--r-- | textual.cc | 9 | ||||
-rw-r--r-- | valexpr.cc | 8 | ||||
-rw-r--r-- | value.cc | 52 |
15 files changed, 225 insertions, 226 deletions
@@ -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) @@ -15,6 +15,10 @@ class commodity_t; class amount_t { + public: + class bigint_t; + + protected: void _init(); void _copy(const amount_t& amt); void _release(); @@ -23,23 +27,21 @@ class amount_t void _clear() { if (quantity) { - assert(commodity); + assert(commodity_); _release(); - quantity = NULL; - commodity = NULL; + quantity = NULL; + commodity_ = NULL; } else { - assert(! commodity); + assert(! commodity_); } } - public: - class bigint_t; - bigint_t * quantity; - commodity_t * commodity; + commodity_t * commodity_; + public: // constructors - amount_t() : quantity(NULL), commodity(NULL) { + amount_t() : quantity(NULL), commodity_(NULL) { DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); } amount_t(const amount_t& amt) : quantity(NULL) { @@ -47,7 +49,7 @@ class amount_t if (amt.quantity) _copy(amt); else - commodity = NULL; + commodity_ = NULL; } amount_t(const std::string& value) : quantity(NULL) { DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); @@ -69,6 +71,11 @@ class amount_t _release(); } + commodity_t& commodity() const; + void set_commodity(commodity_t& comm) { + commodity_ = &comm; + } + // assignment operator amount_t& operator=(const amount_t& amt); amount_t& operator=(const std::string& value); @@ -149,7 +156,7 @@ class amount_t bool operator>=(const amount_t& amt) const; bool operator==(const amount_t& amt) const; bool operator!=(const amount_t& amt) const { - if (commodity != amt.commodity) + if (commodity_ != amt.commodity_) return true; return ! (*this == amt); } @@ -164,13 +171,27 @@ class amount_t void parse(std::istream& in); void parse(const std::string& str); - void write_quantity(std::ostream& out) const; void read_quantity(char *& data); - void read_quantity(std::istream& in); + void write_quantity(std::ostream& out) const; bool valid() const; + // Classes that are friends, and help to implement this class + + friend std::ostream& operator<<(std::ostream& out, const amount_t& amt); friend std::istream& operator>>(std::istream& in, amount_t& amt); + + friend unsigned int sizeof_bigint_t(); + + friend void read_binary_amount(char *& data, amount_t& amt); + friend void write_binary_amount(std::ostream& out, const amount_t& amt); + + // This function is special, and exists only to support a custom + // optimization in binary.cc (which offers a significant enough gain + // to be worth the trouble). + + friend void clean_commodity_history(char * item_pool, + char * item_pool_end); }; unsigned int sizeof_bigint_t(); @@ -209,7 +230,7 @@ class commodity_t class updater_t { public: virtual ~updater_t() {} - virtual void operator()(commodity_t * commodity, + virtual void operator()(commodity_t& commodity, const std::time_t moment, const std::time_t date, const std::time_t last, @@ -273,6 +294,16 @@ class commodity_t } #endif + operator bool() const { + return this != null_commodity; + } + bool operator==(const commodity_t& comm) const { + return this == &comm; + } + bool operator!=(const commodity_t& comm) const { + return this != &comm; + } + void check_symbol() { for (const char * p = symbol.c_str(); *p; p++) if (std::isspace(*p) || std::isdigit(*p) || *p == '-' || *p == '.') { @@ -310,6 +341,13 @@ class commodity_t } }; +inline commodity_t& amount_t::commodity() const { + if (! commodity_) + return *commodity_t::null_commodity; + else + return *commodity_; + } + } // namespace ledger #endif // _AMOUNT_H diff --git a/autoxact.cc b/autoxact.cc index 9672d4d2..165ebede 100644 --- a/autoxact.cc +++ b/autoxact.cc @@ -15,7 +15,7 @@ void automated_transaction_t::extend_entry(entry_t * entry) t != transactions.end(); t++) { amount_t amt; - if ((*t)->amount.commodity->symbol.empty()) + if ((*t)->amount.commodity().symbol.empty()) amt = (*i)->amount * (*t)->amount; else amt = (*t)->amount; @@ -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) @@ -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,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; @@ -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) { @@ -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; @@ -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; } } @@ -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; } @@ -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: { |