diff --git a/src/amount.cc b/src/amount.cc index 8d433ad4..59671f98 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -650,7 +650,8 @@ amount_t& amount_t::in_place_unreduce() optional amount_t::value(const optional& moment) const { if (quantity) { - optional amt(commodity().value(moment)); + // jww (2008-09-21): 'none' is not the right argument here. + optional amt(commodity().value(none, moment)); if (amt) return (*amt * number()).round(); } else { diff --git a/src/commodity.cc b/src/commodity.cc index 44dab58f..11a53e96 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -43,6 +43,44 @@ namespace ledger { +optional +commodity_t::history(const optional& commodity) const +{ + if (base->varied_history) { + const commodity_t * comm = NULL; + if (! commodity) { + if (base->varied_history->size() > 1) + // jww (2008-09-20): Document which option switch to use here + throw_(commodity_error, "Cannot determine history for '" + << *this << "': prices known for multiple commodities (use -?)"); + comm = (*base->varied_history->begin()).first; + } else { + comm = &(*commodity); + } + + history_by_commodity_map::iterator i = base->varied_history->find(comm); + if (i != base->varied_history->end()) + return (*i).second; + } + return none; +} + +optional +commodity_t::history(const std::vector& commodities) const +{ + // This function differs from the single commodity case avoid in that + // 'commodities' represents a list of preferred valuation commodities. + // If no price can be located in terms of the first commodity, then + // the second is chosen, etc. + + foreach (const commodity_t * commodity, commodities) { + if (optional hist = + history(*commodity)) + return hist; + } + return none; +} + void commodity_t::add_price(const datetime_t& date, const amount_t& price) { if (! base->varied_history) @@ -85,57 +123,42 @@ bool commodity_t::remove_price(const datetime_t& date, const commodity_t& comm) } optional -commodity_t::value(const optional& moment, - const optional >& commodities) +commodity_t::value(const history_t& history, + const optional& moment) { optional age; optional price; - optional hist; - if (base->varied_history) { - const commodity_t * comm = NULL; - if (commodities) { - // Walk the list of commodities, finding the first one applicable - comm = commodities->back(); + if (history.prices.size() == 0) + return none; + + if (! moment) { + history_map::const_reverse_iterator r = history.prices.rbegin(); + age = (*r).first; + price = (*r).second; + } else { + history_map::const_iterator i = history.prices.lower_bound(*moment); + if (i == history.prices.end()) { + history_map::const_reverse_iterator r = history.prices.rbegin(); + age = (*r).first; + price = (*r).second; } else { - if (base->varied_history->size() > 1) - throw_(commodity_error, - "Cannot find commodity value: multiple possibilities exist"); - comm = (*base->varied_history->begin()).first; - } - - hist = history(*comm); - if (hist) { - assert(hist->prices.size() > 0); - - if (! moment) { - history_map::reverse_iterator r = hist->prices.rbegin(); - age = (*r).first; - price = (*r).second; - } else { - history_map::iterator i = hist->prices.lower_bound(*moment); - if (i == hist->prices.end()) { - history_map::reverse_iterator r = hist->prices.rbegin(); - age = (*r).first; - price = (*r).second; + age = (*i).first; + if (*moment != *age) { + if (i != history.prices.begin()) { + --i; + age = (*i).first; + price = (*i).second; } else { - age = (*i).first; - if (*moment != *age) { - if (i != hist->prices.begin()) { - --i; - age = (*i).first; - price = (*i).second; - } else { - age = none; - } - } else { - price = (*i).second; - } + age = none; } + } else { + price = (*i).second; } } } +#if 0 if (! has_flags(COMMODITY_STYLE_NOMARKET) && parent().get_quote) { if (optional quote = parent().get_quote (*this, age, moment, @@ -143,6 +166,8 @@ commodity_t::value(const optional& moment, (*hist->prices.rbegin()).first : optional()))) return *quote; } +#endif + return price; } diff --git a/src/commodity.h b/src/commodity.h index 06e64a7f..6b1001cd 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -201,21 +201,34 @@ public: return *base->varied_history; return none; } - optional history(const commodity_t& comm) const { - if (base->varied_history) { - history_by_commodity_map::iterator i = base->varied_history->find(&comm); - if (i != base->varied_history->end()) - return (*i).second; - } - return none; - } + + optional + history(const optional& commodity) const; + optional + history(const std::vector& commodities) const; void add_price(const datetime_t& date, const amount_t& price); bool remove_price(const datetime_t& date, const commodity_t& comm); optional - value(const optional& moment = none, - const optional >& commodities = none); + value(const history_t& history, + const optional& moment = none); + + optional + value(const optional& commodity = none, + const optional& moment = none) { + if (optional hist = history(commodity)) + return value(*hist, moment); + return none; + } + + optional + value(const std::vector& commodities, + const optional& moment = none) { + if (optional hist = history(commodities)) + return value(*hist, moment); + return none; + } static void exchange(commodity_t& commodity, const amount_t& per_unit_cost,