summaryrefslogtreecommitdiff
path: root/src/commodity.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/commodity.cc')
-rw-r--r--src/commodity.cc102
1 files changed, 66 insertions, 36 deletions
diff --git a/src/commodity.cc b/src/commodity.cc
index 29bb2f56..44dab58f 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -45,62 +45,92 @@ namespace ledger {
void commodity_t::add_price(const datetime_t& date, const amount_t& price)
{
- if (! base->history)
- base->history = history_t();
-
- history_map::iterator i = base->history->prices.find(date);
- if (i != base->history->prices.end()) {
+ if (! base->varied_history)
+ base->varied_history = varied_history_t();
+
+ optional<history_t&> hist = history(price.commodity());
+ if (! hist) {
+ std::pair<history_by_commodity_map::iterator, bool> result
+ = base->varied_history->insert(history_by_commodity_map::value_type
+ (&price.commodity(), history_t()));
+ assert(result.second);
+ hist = (*result.first).second;
+ }
+ assert(hist);
+
+ history_map::iterator i = hist->prices.find(date);
+ if (i != hist->prices.end()) {
(*i).second = price;
} else {
std::pair<history_map::iterator, bool> result
- = base->history->prices.insert(history_map::value_type(date, price));
+ = hist->prices.insert(history_map::value_type(date, price));
assert(result.second);
}
}
-bool commodity_t::remove_price(const datetime_t& date)
+bool commodity_t::remove_price(const datetime_t& date, const commodity_t& comm)
{
- if (base->history) {
- history_map::size_type n = base->history->prices.erase(date);
- if (n > 0) {
- if (base->history->prices.empty())
- base->history.reset();
- return true;
+ if (base->varied_history) {
+ optional<history_t&> hist = history(comm);
+ if (hist) {
+ history_map::size_type n = hist->prices.erase(date);
+ if (n > 0) {
+ if (hist->prices.empty())
+ hist.reset();
+ return true;
+ }
}
}
return false;
}
-optional<amount_t> commodity_t::value(const optional<datetime_t>& moment)
+optional<amount_t>
+commodity_t::value(const optional<datetime_t>& moment,
+ const optional<std::vector<const commodity_t *> >& commodities)
{
optional<datetime_t> age;
- optional<amount_t> price;
+ optional<amount_t> price;
+ optional<history_t&> 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();
+ } else {
+ if (base->varied_history->size() > 1)
+ throw_(commodity_error,
+ "Cannot find commodity value: multiple possibilities exist");
+ comm = (*base->varied_history->begin()).first;
+ }
- if (base->history) {
- assert(base->history->prices.size() > 0);
+ hist = history(*comm);
+ if (hist) {
+ assert(hist->prices.size() > 0);
- if (! moment) {
- history_map::reverse_iterator r = base->history->prices.rbegin();
- age = (*r).first;
- price = (*r).second;
- } else {
- history_map::iterator i = base->history->prices.lower_bound(*moment);
- if (i == base->history->prices.end()) {
- history_map::reverse_iterator r = base->history->prices.rbegin();
+ if (! moment) {
+ history_map::reverse_iterator r = hist->prices.rbegin();
age = (*r).first;
price = (*r).second;
} else {
- age = (*i).first;
- if (*moment != *age) {
- if (i != base->history->prices.begin()) {
- --i;
- age = (*i).first;
- price = (*i).second;
+ 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;
+ } else {
+ age = (*i).first;
+ if (*moment != *age) {
+ if (i != hist->prices.begin()) {
+ --i;
+ age = (*i).first;
+ price = (*i).second;
+ } else {
+ age = none;
+ }
} else {
- age = none;
+ price = (*i).second;
}
- } else {
- price = (*i).second;
}
}
}
@@ -109,8 +139,8 @@ optional<amount_t> commodity_t::value(const optional<datetime_t>& moment)
if (! has_flags(COMMODITY_STYLE_NOMARKET) && parent().get_quote) {
if (optional<amount_t> quote = parent().get_quote
(*this, age, moment,
- (base->history && base->history->prices.size() > 0 ?
- (*base->history->prices.rbegin()).first : optional<datetime_t>())))
+ (hist && hist->prices.size() > 0 ?
+ (*hist->prices.rbegin()).first : optional<datetime_t>())))
return *quote;
}
return price;