diff --git a/amount.cc b/amount.cc index 4c3fb03f..21f5bf6d 100644 --- a/amount.cc +++ b/amount.cc @@ -1279,14 +1279,13 @@ void amount_t::annotate_commodity(const amount_t& price, DEBUG_PRINT("amounts.commodities", " Annotated amount is " << *this); } -void amount_t::reduce_commodity(const bool keep_price, - const bool keep_date, - const bool keep_tag) +amount_t amount_t::reduce_commodity(const bool keep_price, + const bool keep_date, + const bool keep_tag) const { - if (! commodity().annotated) - return; - if (keep_price && keep_date && keep_tag) - return; + if (! commodity().annotated || + (keep_price && keep_date && keep_tag)) + return *this; DEBUG_PRINT("amounts.commodities", "Reducing commodity for amount " << *this << std::endl @@ -1297,16 +1296,27 @@ void amount_t::reduce_commodity(const bool keep_price, annotated_commodity_t& ann_comm(static_cast(commodity())); - annotated_commodity_t * new_ann_comm = - annotated_commodity_t::find_or_create(*ann_comm.base, - keep_price ? - ann_comm.price : amount_t(), - keep_date ? ann_comm.date : 0, - keep_tag ? ann_comm.tag : ""); - assert(new_ann_comm); - set_commodity(*new_ann_comm); + commodity_t * new_comm; - DEBUG_PRINT("amounts.commodities", " Reduced amount is " << *this); + if ((keep_price && ann_comm.price) || + (keep_date && ann_comm.date) || + (keep_tag && ! ann_comm.tag.empty())) + { + new_comm = annotated_commodity_t::find_or_create + (*ann_comm.base, keep_price ? ann_comm.price : amount_t(), + keep_date ? ann_comm.date : 0, keep_tag ? ann_comm.tag : ""); + } else { + new_comm = commodity_t::find_or_create(ann_comm.base_symbol()); + } + + assert(new_comm); + + amount_t temp(*this); + temp.set_commodity(*new_comm); + + DEBUG_PRINT("amounts.commodities", " Reduced amount is " << temp); + + return temp; } @@ -1347,6 +1357,22 @@ bool commodity_t::needs_quotes(const std::string& symbol) return false; } +bool commodity_t::valid() const +{ + if (symbol().empty() && this != null_commodity) + return false; + +#if 0 + if (annotated && ! base) + return false; +#endif + + if (precision() > 16) + return false; + + return true; +} + commodity_t * commodity_t::create(const std::string& symbol) { std::auto_ptr commodity(new commodity_t); @@ -1497,8 +1523,11 @@ annotated_commodity_t::create(const commodity_t& comm, commodity->price = price; commodity->date = date; commodity->tag = tag; + commodity->base = &comm; + assert(commodity->base); commodity->ptr = comm.ptr; + assert(commodity->ptr); commodity->qualified_symbol = comm.symbol(); diff --git a/amount.h b/amount.h index b209adfc..be6f65b7 100644 --- a/amount.h +++ b/amount.h @@ -75,9 +75,9 @@ class amount_t void annotate_commodity(const amount_t& price, const std::time_t date = 0, const std::string& tag = ""); - void reduce_commodity(const bool keep_price = false, - const bool keep_date = false, - const bool keep_tag = false); + amount_t reduce_commodity(const bool keep_price = false, + const bool keep_date = false, + const bool keep_tag = false) const; void clear_commodity() { commodity_ = NULL; } @@ -282,9 +282,6 @@ inline amount_t abs(const amount_t& amt) { return amt < 0 ? amt.negated() : amt; } -#define base_amount(amt) \ - ((! show_lots && amt.commodity().price) ? amt.base() : amt) - std::ostream& operator<<(std::ostream& out, const amount_t& amt); inline std::istream& operator>>(std::istream& in, amount_t& amt) { @@ -499,15 +496,7 @@ class commodity_t return ptr->value(moment); } - bool valid() const { - if (symbol().empty() && this != null_commodity) - return false; - - if (precision() > 16) - return false; - - return true; - } + bool valid() const; }; class annotated_commodity_t : public commodity_t diff --git a/balance.cc b/balance.cc index 07d4afc8..13acef22 100644 --- a/balance.cc +++ b/balance.cc @@ -46,6 +46,19 @@ balance_t balance_t::price() const return temp; } +balance_t balance_t::reduce(const bool keep_price, const bool keep_date, + const bool keep_tag) const +{ + balance_t temp; + + for (amounts_map::const_iterator i = amounts.begin(); + i != amounts.end(); + i++) + temp += (*i).second.reduce_commodity(keep_price, keep_date, keep_tag); + + return temp; +} + struct compare_amount_commodities { bool operator()(const amount_t * left, const amount_t * right) const { return left->commodity().symbol() < right->commodity().symbol(); @@ -160,14 +173,10 @@ balance_pair_t& balance_pair_t::operator/=(const balance_pair_t& bal_pair) quantity /= bal_pair.quantity; if (cost) *cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; - - if (bal_pair.price && *bal_pair.price && price) - *price /= *bal_pair.price; return *this; } balance_pair_t& balance_pair_t::add(const amount_t& amount, - const amount_t * a_price, const amount_t * a_cost) { if (a_cost && ! cost) @@ -175,13 +184,6 @@ balance_pair_t& balance_pair_t::add(const amount_t& amount, quantity += amount; if (cost) *cost += a_cost ? *a_cost : amount; - - if (a_price) { - if (! price) - price = new balance_t(*a_price); - else - *price += *a_price; - } return *this; } @@ -290,8 +292,10 @@ void export_balance() .def("negate", &balance_t::negate) .def("amount", &balance_t::amount) .def("value", &balance_t::value) + .def("price", &balance_t::price) + .def("reduce", &balance_t::reduce) .def("write", &balance_t::write) - .def("valid", &balance_t::valid) + .def("valid", &balance_t::valid) ; class_< balance_pair_t > ("BalancePair") @@ -368,9 +372,6 @@ void export_balance() .def("__len__", balance_pair_len) .def("__getitem__", balance_pair_getitem) - .add_property("price", - make_getter(&balance_pair_t::price, - return_value_policy())) .add_property("cost", make_getter(&balance_pair_t::cost, return_value_policy())) diff --git a/balance.h b/balance.h index 766837c9..563f620a 100644 --- a/balance.h +++ b/balance.h @@ -411,6 +411,9 @@ class balance_t amount_t amount(const commodity_t& commodity) const; balance_t value(const std::time_t moment) const; balance_t price() const; + balance_t reduce(const bool keep_price = false, + const bool keep_date = false, + const bool keep_tag = false) const; void write(std::ostream& out, const int first_width, const int latter_width = -1) const; @@ -446,56 +449,42 @@ class balance_pair_t { public: balance_t quantity; - balance_t * price; balance_t * cost; // constructors - balance_pair_t() : price(NULL), cost(NULL) {} + balance_pair_t() : cost(NULL) {} balance_pair_t(const balance_pair_t& bal_pair) - : quantity(bal_pair.quantity), price(NULL), cost(NULL) { - if (bal_pair.price) - price = new balance_t(*bal_pair.price); + : quantity(bal_pair.quantity), cost(NULL) { if (bal_pair.cost) cost = new balance_t(*bal_pair.cost); } balance_pair_t(const balance_t& _quantity) - : quantity(_quantity), price(NULL), cost(NULL) {} + : quantity(_quantity), cost(NULL) {} balance_pair_t(const amount_t& _quantity) - : quantity(_quantity), price(NULL), cost(NULL) {} + : quantity(_quantity), cost(NULL) {} template - balance_pair_t(T value) : quantity(value), price(NULL), cost(NULL) {} + balance_pair_t(T value) : quantity(value), cost(NULL) {} // destructor ~balance_pair_t() { - if (price) delete price; - if (cost) delete cost; + if (cost) delete cost; } // assignment operator balance_pair_t& operator=(const balance_pair_t& bal_pair) { if (this != &bal_pair) { - if (price) { - delete price; - price = NULL; - } if (cost) { delete cost; cost = NULL; } quantity = bal_pair.quantity; - if (bal_pair.price) - price = new balance_t(*bal_pair.price); if (bal_pair.cost) cost = new balance_t(*bal_pair.cost); } return *this; } balance_pair_t& operator=(const balance_t& bal) { - if (price) { - delete price; - price = NULL; - } if (cost) { delete cost; cost = NULL; @@ -504,10 +493,6 @@ class balance_pair_t return *this; } balance_pair_t& operator=(const amount_t& amt) { - if (price) { - delete price; - price = NULL; - } if (cost) { delete cost; cost = NULL; @@ -517,10 +502,6 @@ class balance_pair_t } template balance_pair_t& operator=(T value) { - if (price) { - delete price; - price = NULL; - } if (cost) { delete cost; cost = NULL; @@ -536,13 +517,6 @@ class balance_pair_t quantity += bal_pair.quantity; if (cost) *cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; - - if (bal_pair.price) { - if (! price) - price = new balance_t(*bal_pair.price); - else - *price += *bal_pair.price; - } return *this; } balance_pair_t& operator+=(const balance_t& bal) { @@ -568,15 +542,6 @@ class balance_pair_t quantity -= bal_pair.quantity; if (cost) *cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; - - if (bal_pair.price) { - if (! price) { - price = new balance_t(*bal_pair.price); - price->negate(); - } else { - *price -= *bal_pair.price; - } - } return *this; } balance_pair_t& operator-=(const balance_t& bal) { @@ -648,15 +613,6 @@ class balance_pair_t quantity *= bal_pair.quantity; if (cost) *cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity; - - if (bal_pair.price && *bal_pair.price) { - if (price) - *price *= *bal_pair.price; - } - else if (price) { - delete price; - price = NULL; - } return *this; } balance_pair_t& operator*=(const balance_t& bal) { @@ -826,8 +782,7 @@ class balance_pair_t // unary negation void negate() { quantity.negate(); - if (price) price->negate(); - if (cost) cost->negate(); + if (cost) cost->negate(); } balance_pair_t negated() const { balance_pair_t temp = *this; @@ -851,8 +806,7 @@ class balance_pair_t void abs() { quantity.abs(); - if (price) price->abs(); - if (cost) cost->abs(); + if (cost) cost->abs(); } amount_t amount(const commodity_t& commodity) const { @@ -867,12 +821,10 @@ class balance_pair_t } balance_pair_t& add(const amount_t& amount, - const amount_t * a_price = NULL, - const amount_t * a_cost = NULL); + const amount_t * a_cost = NULL); bool valid() { - return (quantity.valid() && - (! price || price->valid()) && (! cost || cost->valid())); + return quantity.valid() && (! cost || cost->valid()); } void round() { diff --git a/config.cc b/config.cc index 54600369..bc67a7ef 100644 --- a/config.cc +++ b/config.cc @@ -780,9 +780,21 @@ OPT_BEGIN(actual, "L") { } OPT_END(actual); OPT_BEGIN(lots, "") { - show_lots = true; + keep_price = keep_date = keep_tag = true; } OPT_END(lots); +OPT_BEGIN(lot_prices, "") { + keep_price = true; +} OPT_END(lots_prices); + +OPT_BEGIN(lot_dates, "") { + keep_date = true; +} OPT_END(lots_dates); + +OPT_BEGIN(lot_tags, "") { + keep_tag = true; +} OPT_END(lots_tags); + ////////////////////////////////////////////////////////////////////// // // Output customization @@ -1121,6 +1133,9 @@ option_t config_options[CONFIG_OPTIONS_SIZE] = { { "init-file", 'i', true, opt_init_file, false }, { "input-date-format", '\0', true, opt_input_date_format, false }, { "limit", 'l', true, opt_limit, false }, + { "lot-dates", '\0', false, opt_lot_dates, false }, + { "lot-prices", '\0', false, opt_lot_prices, false }, + { "lot-tags", '\0', false, opt_lot_tags, false }, { "lots", '\0', false, opt_lots, false }, { "market", 'V', false, opt_market, false }, { "monthly", 'M', false, opt_monthly, false }, diff --git a/config.h b/config.h index 99295189..a19dd2b6 100644 --- a/config.h +++ b/config.h @@ -99,7 +99,7 @@ class config_t std::list *>& ptrs); }; -#define CONFIG_OPTIONS_SIZE 78 +#define CONFIG_OPTIONS_SIZE 81 extern option_t config_options[CONFIG_OPTIONS_SIZE]; void option_help(std::ostream& out); diff --git a/valexpr.cc b/valexpr.cc index 61574d3f..c8495771 100644 --- a/valexpr.cc +++ b/valexpr.cc @@ -13,6 +13,10 @@ std::auto_ptr total_expr; std::auto_ptr global_scope; std::time_t terminus; +bool keep_price = false; +bool keep_date = false; +bool keep_tag = false; + details_t::details_t(const transaction_t& _xact) : entry(_xact.entry), xact(&_xact), account(xact_account(_xact)) { @@ -643,6 +647,9 @@ void value_expr_t::compute(value_t& result, const details_t& details, assert(0); break; } + + if (! keep_price || ! keep_date || ! keep_tag) + result = result.reduce(keep_price, keep_date, keep_tag); } static inline void unexpected(char c, char wanted = '\0') { diff --git a/valexpr.h b/valexpr.h index 58eb4c99..8e890586 100644 --- a/valexpr.h +++ b/valexpr.h @@ -249,6 +249,10 @@ extern std::auto_ptr global_scope; extern std::time_t terminus; extern bool initialized; +extern bool keep_price; +extern bool keep_date; +extern bool keep_tag; + void init_value_expr(); bool compute_amount(value_expr_t * expr, amount_t& amt, diff --git a/value.cc b/value.cc index 8edffe80..377a9631 100644 --- a/value.cc +++ b/value.cc @@ -728,16 +728,42 @@ value_t value_t::price() const switch (type) { case BOOLEAN: case INTEGER: - case AMOUNT: - case BALANCE: return *this; - case BALANCE_PAIR: - if (((balance_pair_t *) data)->price) - return *(((balance_pair_t *) data)->price); - else - return 0L; + case AMOUNT: + return ((amount_t *) data)->price(); + case BALANCE: + return ((balance_t *) data)->price(); + + case BALANCE_PAIR: + return ((balance_pair_t *) data)->quantity.price(); + + default: + assert(0); + break; + } + assert(0); + return value_t(); +} + +value_t value_t::reduce(const bool keep_price, const bool keep_date, + const bool keep_tag) const +{ + switch (type) { + case BOOLEAN: + case INTEGER: + return *this; + + case AMOUNT: + return ((amount_t *) data)->reduce_commodity(keep_price, keep_date, + keep_tag); + case BALANCE: + return ((balance_t *) data)->reduce(keep_price, keep_date, keep_tag); + + case BALANCE_PAIR: + return ((balance_pair_t *) data)->quantity.reduce(keep_price, keep_date, + keep_tag); default: assert(0); break; @@ -770,22 +796,21 @@ value_t value_t::cost() const return value_t(); } -value_t& value_t::add(const amount_t& amount, - const amount_t * price, const amount_t * cost) +value_t& value_t::add(const amount_t& amount, const amount_t * cost) { switch (type) { case BOOLEAN: case INTEGER: case AMOUNT: - if (price || cost) { + if (cost) { cast(BALANCE_PAIR); - return add(amount, price, cost); + return add(amount, cost); } else if ((type == AMOUNT && ((amount_t *) data)->commodity() != amount.commodity()) || (type != AMOUNT && amount.commodity())) { cast(BALANCE); - return add(amount, price, cost); + return add(amount, cost); } else if (type != AMOUNT) { cast(AMOUNT); @@ -794,15 +819,15 @@ value_t& value_t::add(const amount_t& amount, break; case BALANCE: - if (price || cost) { + if (cost) { cast(BALANCE_PAIR); - return add(amount, price, cost); + return add(amount, cost); } *((balance_t *) data) += amount; break; case BALANCE_PAIR: - ((balance_pair_t *) data)->add(amount, price, cost); + ((balance_pair_t *) data)->add(amount, cost); break; default: diff --git a/value.h b/value.h index 05bea81f..bcc71d03 100644 --- a/value.h +++ b/value.h @@ -145,7 +145,7 @@ class value_t } value_t& operator=(const balance_pair_t& value) { if ((balance_pair_t *) data != &value) { - if (! value.price && ! value.cost) { + if (! value.cost) { return *this = value.quantity; } else { destroy(); @@ -267,9 +267,10 @@ class value_t void cast(type_t cast_type); value_t cost() const; value_t price() const; - value_t& add(const amount_t& amount, - const amount_t * price = NULL, - const amount_t * cost = NULL); + value_t reduce(const bool keep_price = false, + const bool keep_date = false, + const bool keep_tag = false) const; + value_t& add(const amount_t& amount, const amount_t * cost = NULL); value_t value(const std::time_t moment) const { switch (type) { diff --git a/walk.cc b/walk.cc index 4bb6a38a..300988a1 100644 --- a/walk.cc +++ b/walk.cc @@ -7,8 +7,6 @@ namespace ledger { -bool show_lots = false; - template <> bool compare_items::operator()(const transaction_t * left, const transaction_t * right) @@ -44,7 +42,7 @@ void add_transaction_to(const transaction_t& xact, value_t& value) transaction_xdata_(xact).dflags & TRANSACTION_COMPOSITE) { value += transaction_xdata_(xact).composite_amount; } - else if (xact.cost || xact.amount.commodity().annotated || value) { + else if (xact.cost || value) { value.add(xact.amount, xact.cost); } else { diff --git a/walk.h b/walk.h index 974cd575..a9164ad0 100644 --- a/walk.h +++ b/walk.h @@ -120,8 +120,6 @@ inline const account_t * xact_account(const transaction_t& xact) { return xact_account(const_cast(xact)); } -extern bool show_lots; - ////////////////////////////////////////////////////////////////////// inline void walk_transactions(transactions_list::iterator begin,