summaryrefslogtreecommitdiff
path: root/src/pool.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/pool.cc')
-rw-r--r--src/pool.cc267
1 files changed, 99 insertions, 168 deletions
diff --git a/src/pool.cc b/src/pool.cc
index 65edbd6a..61b5bef2 100644
--- a/src/pool.cc
+++ b/src/pool.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2010, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2012, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -35,6 +35,7 @@
#include "commodity.h"
#include "annotate.h"
#include "pool.h"
+#include "history.h"
#include "quotes.h"
namespace ledger {
@@ -46,16 +47,16 @@ commodity_pool_t::commodity_pool_t()
quote_leeway(86400), get_quotes(false),
get_commodity_quote(commodity_quote_from_script)
{
- TRACE_CTOR(commodity_pool_t, "");
null_commodity = create("");
null_commodity->add_flags(COMMODITY_BUILTIN | COMMODITY_NOMARKET);
+ TRACE_CTOR(commodity_pool_t, "");
}
commodity_t * commodity_pool_t::create(const string& symbol)
{
shared_ptr<commodity_t::base_t>
base_commodity(new commodity_t::base_t(symbol));
- std::auto_ptr<commodity_t> commodity(new commodity_t(this, base_commodity));
+ shared_ptr<commodity_t> commodity(new commodity_t(this, base_commodity));
DEBUG("pool.commodities", "Creating base commodity " << symbol);
@@ -66,25 +67,19 @@ commodity_t * commodity_pool_t::create(const string& symbol)
*commodity->qualified_symbol += "\"";
}
- DEBUG("pool.commodities",
- "Creating commodity '" << commodity->symbol() << "'");
+ DEBUG("pool.commodities", "Creating commodity '" << symbol << "'");
- std::pair<commodities_map::iterator, bool> result
- = commodities.insert(commodities_map::value_type(commodity->mapping_key(),
- commodity.get()));
+#if defined(DEBUG_ON)
+ std::pair<commodities_map::iterator, bool> result =
+#endif
+ commodities.insert(commodities_map::value_type(symbol, commodity));
+#if defined(DEBUG_ON)
assert(result.second);
+#endif
- return commodity.release();
-}
-
-commodity_t * commodity_pool_t::find_or_create(const string& symbol)
-{
- DEBUG("pool.commodities", "Find-or-create commodity " << symbol);
+ commodity_price_history.add_commodity(*commodity.get());
- commodity_t * commodity = find(symbol);
- if (commodity)
- return commodity;
- return create(symbol);
+ return commodity.get();
}
commodity_t * commodity_pool_t::find(const string& symbol)
@@ -93,91 +88,111 @@ commodity_t * commodity_pool_t::find(const string& symbol)
commodities_map::const_iterator i = commodities.find(symbol);
if (i != commodities.end())
- return (*i).second;
+ return (*i).second.get();
return NULL;
}
-commodity_t *
-commodity_pool_t::create(const string& symbol, const annotation_t& details)
+commodity_t * commodity_pool_t::find_or_create(const string& symbol)
{
- commodity_t * new_comm = create(symbol);
- if (! new_comm)
- return NULL;
-
- if (details)
- return find_or_create(*new_comm, details);
- else
- return new_comm;
+ DEBUG("pool.commodities", "Find-or-create commodity " << symbol);
+ if (commodity_t * commodity = find(symbol))
+ return commodity;
+ return create(symbol);
}
-string commodity_pool_t::make_qualified_name(const commodity_t& comm,
- const annotation_t& details)
+commodity_t * commodity_pool_t::alias(const string& name, commodity_t& referent)
{
- assert(details);
+ commodities_map::const_iterator i = commodities.find(referent.base_symbol());
+ assert(i != commodities.end());
- if (details.price && details.price->sign() < 0)
- throw_(amount_error, _("A commodity's price may not be negative"));
+ std::pair<commodities_map::iterator, bool> result
+ = commodities.insert(commodities_map::value_type(name, (*i).second));
+ assert(result.second);
- std::ostringstream name;
- comm.print(name);
- details.print(name, comm.pool().keep_base);
+ return (*result.first).second.get();
+}
-#if defined(DEBUG_ON)
- if (comm.qualified_symbol)
- DEBUG("pool.commodities", "make_qualified_name for "
- << *comm.qualified_symbol << std::endl << details);
-#endif
- DEBUG("pool.commodities", "qualified_name is " << name.str());
+commodity_t *
+commodity_pool_t::create(const string& symbol, const annotation_t& details)
+{
+ DEBUG("pool.commodities", "commodity_pool_t::create[ann] "
+ << "symbol " << symbol << std::endl << details);
- return name.str();
+ if (details)
+ return create(*find_or_create(symbol), details);
+ else
+ return create(symbol);
}
commodity_t *
commodity_pool_t::find(const string& symbol, const annotation_t& details)
{
- commodity_t * comm = find(symbol);
- if (! comm)
+ DEBUG("pool.commodities", "commodity_pool_t::find[ann] "
+ << "symbol " << symbol << std::endl << details);
+
+ annotated_commodities_map::const_iterator i =
+ annotated_commodities.find
+ (annotated_commodities_map::key_type(symbol, details));
+ if (i != annotated_commodities.end()) {
+ DEBUG("pool.commodities", "commodity_pool_t::find[ann] found "
+ << "symbol " << (*i).second->base_symbol() << std::endl
+ << as_annotated_commodity(*(*i).second.get()).details);
+ return (*i).second.get();
+ } else {
return NULL;
+ }
+}
- if (details) {
- string name = make_qualified_name(*comm, details);
+commodity_t *
+commodity_pool_t::find_or_create(const string& symbol,
+ const annotation_t& details)
+{
+ DEBUG("pool.commodities", "commodity_pool_t::find_or_create[ann] "
+ << "symbol " << symbol << std::endl << details);
- if (commodity_t * ann_comm = find(name)) {
+ if (details) {
+ if (commodity_t * ann_comm = find(symbol, details)) {
assert(ann_comm->annotated && as_annotated_commodity(*ann_comm).details);
return ann_comm;
+ } else {
+ return create(symbol, details);
}
- return NULL;
} else {
- return comm;
+ return find_or_create(symbol);
}
}
commodity_t *
-commodity_pool_t::find_or_create(const string& symbol,
- const annotation_t& details)
+commodity_pool_t::find_or_create(commodity_t& comm, const annotation_t& details)
{
- commodity_t * comm = find_or_create(symbol);
- if (! comm)
- return NULL;
+ DEBUG("pool.commodities", "commodity_pool_t::find_or_create[ann:comm] "
+ << "symbol " << comm.base_symbol() << std::endl << details);
- if (details)
- return find_or_create(*comm, details);
- else
- return comm;
+ if (details) {
+ if (commodity_t * ann_comm = find(comm.base_symbol(), details)) {
+ assert(ann_comm->annotated && as_annotated_commodity(*ann_comm).details);
+ return ann_comm;
+ } else {
+ return create(comm, details);
+ }
+ } else {
+ return &comm;
+ }
}
-commodity_t *
+annotated_commodity_t *
commodity_pool_t::create(commodity_t& comm,
- const annotation_t& details,
- const string& mapping_key)
+ const annotation_t& details)
{
+ DEBUG("pool.commodities", "commodity_pool_t::create[ann:comm] "
+ << "symbol " << comm.base_symbol() << std::endl << details);
+
assert(comm);
assert(! comm.has_annotation());
assert(details);
- assert(! mapping_key.empty());
- unique_ptr<commodity_t> commodity
- (new annotated_commodity_t(&comm, details));
+ shared_ptr<annotated_commodity_t>
+ commodity(new annotated_commodity_t(&comm, details));
comm.add_flags(COMMODITY_SAW_ANNOTATED);
if (details.price) {
@@ -187,39 +202,21 @@ commodity_pool_t::create(commodity_t& comm,
comm.add_flags(COMMODITY_SAW_ANN_PRICE_FLOAT);
}
- commodity->qualified_symbol = comm.symbol();
- assert(! commodity->qualified_symbol->empty());
-
DEBUG("pool.commodities", "Creating annotated commodity "
- << "symbol " << commodity->symbol()
- << " key " << mapping_key << std::endl << details);
+ << "symbol " << commodity->base_symbol()
+ << std::endl << details);
- // Add the fully annotated name to the map, so that this symbol may
- // quickly be found again.
- commodity->mapping_key_ = mapping_key;
-
- std::pair<commodities_map::iterator, bool> result
- = commodities.insert(commodities_map::value_type(mapping_key,
- commodity.get()));
+#if defined(DEBUG_ON)
+ std::pair<annotated_commodities_map::iterator, bool> result =
+#endif
+ annotated_commodities.insert(annotated_commodities_map::value_type
+ (annotated_commodities_map::key_type
+ (comm.base_symbol(), details), commodity));
+#if defined(DEBUG_ON)
assert(result.second);
+#endif
- return commodity.release();
-}
-
-commodity_t * commodity_pool_t::find_or_create(commodity_t& comm,
- const annotation_t& details)
-{
- assert(comm);
- assert(details);
-
- string name = make_qualified_name(comm, details);
- assert(! name.empty());
-
- if (commodity_t * ann_comm = find(name)) {
- assert(ann_comm->annotated && as_annotated_commodity(*ann_comm).details);
- return ann_comm;
- }
- return create(comm, details, name);
+ return commodity.get();
}
void commodity_pool_t::exchange(commodity_t& commodity,
@@ -240,6 +237,7 @@ cost_breakdown_t
commodity_pool_t::exchange(const amount_t& amount,
const amount_t& cost,
const bool is_per_unit,
+ const bool add_price,
const optional<datetime_t>& moment,
const optional<string>& tag)
{
@@ -261,6 +259,9 @@ commodity_pool_t::exchange(const amount_t& amount,
amount_t per_unit_cost =
(is_per_unit || amount.is_realzero()) ? cost.abs() : (cost / amount).abs();
+ if (! cost.has_commodity())
+ per_unit_cost.clear_commodity();
+
DEBUG("commodity.prices.add", "exchange: per-unit-cost = " << per_unit_cost);
// Do not record commodity exchanges where amount's commodity has a
@@ -269,8 +270,10 @@ commodity_pool_t::exchange(const amount_t& amount,
if (! per_unit_cost.is_realzero() &&
(current_annotation == NULL ||
! (current_annotation->price &&
- current_annotation->has_flags(ANNOTATION_PRICE_FIXATED))))
+ current_annotation->has_flags(ANNOTATION_PRICE_FIXATED))) &&
+ commodity.referent() != per_unit_cost.commodity().referent()) {
exchange(commodity, per_unit_cost, moment ? *moment : CURRENT_TIME());
+ }
cost_breakdown_t breakdown;
breakdown.final_cost = ! is_per_unit ? cost : cost * amount.abs();
@@ -382,76 +385,4 @@ commodity_pool_t::parse_price_expression(const std::string& str,
return NULL;
}
-void commodity_pool_t::print_pricemap(std::ostream& out,
- const keep_details_t& keep,
- const optional<datetime_t>& moment)
-{
- typedef std::map<commodity_t *, commodity_t *> comm_map_t;
-
- comm_map_t comm_map;
-
- foreach (const commodities_map::value_type& comm_pair, commodities) {
- commodity_t * comm(&comm_pair.second->strip_annotations(keep));
- comm_map.insert(comm_map_t::value_type(comm, NULL));
- }
-
- out << "digraph commodities {\n";
-
- foreach (const comm_map_t::value_type& comm_pair, comm_map) {
- commodity_t * comm(comm_pair.first);
- if (comm->has_flags(COMMODITY_BUILTIN))
- continue;
-
- out << " ";
- if (commodity_t::symbol_needs_quotes(comm->symbol()))
- out << comm->symbol() << ";\n";
- else
- out << "\"" << comm->symbol() << "\";\n";
-
- if (! comm->has_flags(COMMODITY_NOMARKET) &&
- (! commodity_pool_t::current_pool->default_commodity ||
- comm != commodity_pool_t::current_pool->default_commodity)) {
- if (optional<commodity_t::varied_history_t&> vhist =
- comm->varied_history()) {
- foreach (const commodity_t::history_by_commodity_map::value_type& pair,
- vhist->histories) {
- datetime_t most_recent;
- amount_t most_recent_amt;
- foreach (const commodity_t::history_map::value_type& inner_pair,
- pair.second.prices) {
- if ((most_recent.is_not_a_date_time() ||
- inner_pair.first > most_recent) &&
- (! moment || inner_pair.first <= moment)) {
- most_recent = inner_pair.first;
- most_recent_amt = inner_pair.second;
- }
- }
-
- if (! most_recent.is_not_a_date_time()) {
- out << " ";
- if (commodity_t::symbol_needs_quotes(comm->symbol()))
- out << comm->symbol();
- else
- out << "\"" << comm->symbol() << "\"";
-
- out << " -> ";
-
- if (commodity_t::symbol_needs_quotes(pair.first->symbol()))
- out << pair.first->symbol();
- else
- out << "\"" << pair.first->symbol() << "\"";
-
- out << " [label=\""
- << most_recent_amt.number() << "\\n"
- << format_date(most_recent.date(), FMT_WRITTEN)
- << "\" fontcolor=\"#008e28\"];\n";
- }
- }
- }
- }
- }
-
- out << "}\n";
-}
-
} // namespace ledger