summaryrefslogtreecommitdiff
path: root/src/commodity.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/commodity.h')
-rw-r--r--src/commodity.h393
1 files changed, 241 insertions, 152 deletions
diff --git a/src/commodity.h b/src/commodity.h
index def41778..29534729 100644
--- a/src/commodity.h
+++ b/src/commodity.h
@@ -53,232 +53,229 @@ namespace ledger {
#define COMMODITY_STYLE_NOMARKET 0x0010
#define COMMODITY_STYLE_BUILTIN 0x0020
-typedef std::map<const moment_t, amount_t> history_map;
-typedef std::pair<const moment_t, amount_t> history_pair;
-
-class commodity_base_t;
-
-typedef std::map<const string, commodity_base_t *> base_commodities_map;
-typedef std::pair<const string, commodity_base_t *> base_commodities_pair;
-
class commodity_base_t : public noncopyable
{
-public:
+private:
+ friend class commodity_pool_t;
friend class commodity_t;
friend class annotated_commodity_t;
- friend void amount_t::initialize();
- friend void amount_t::shutdown();
+ typedef std::map<const moment_t, amount_t> history_map;
+ typedef std::pair<const moment_t, amount_t> history_pair;
- friend void checked_delete<commodity_base_t>(commodity_base_t *);
+ struct history_t {
+ history_map prices;
+ ptime last_lookup;
+ };
- typedef uint_least32_t ident_t;
+ typedef uint_least8_t flags_t;
- ident_t ident;
- string name;
- string note;
+ flags_t flags;
+ string symbol;
amount_t::precision_t precision;
- unsigned char flags;
+ optional<string> name;
+ optional<string> note;
+ optional<history_t> history;
optional<amount_t> smaller;
optional<amount_t> larger;
- commodity_base_t() : precision(0), flags(COMMODITY_STYLE_DEFAULTS) {
+public:
+ explicit commodity_base_t()
+ : flags(COMMODITY_STYLE_DEFAULTS), precision(0) {
TRACE_CTOR(commodity_base_t, "");
}
-
- commodity_base_t(const commodity_base_t&) {
- TRACE_CTOR(commodity_base_t, "copy");
- assert(0);
- }
-
- commodity_base_t(const string& _symbol,
- unsigned int _precision = 0,
- unsigned int _flags = COMMODITY_STYLE_DEFAULTS)
- : precision(_precision), flags(_flags), symbol(_symbol) {
- TRACE_CTOR(commodity_base_t, "const string&, unsigned int, unsigned int");
+ explicit commodity_base_t
+ (const string& _symbol,
+ amount_t::precision_t _precision = 0,
+ unsigned int _flags = COMMODITY_STYLE_DEFAULTS)
+ : flags(_flags), symbol(_symbol), precision(_precision) {
+ TRACE_CTOR(commodity_base_t,
+ "const string&, amount_t::precision_t, unsigned int");
}
-
~commodity_base_t() {
TRACE_DTOR(commodity_base_t);
}
-
- static base_commodities_map commodities;
-
- static commodity_base_t * create(const string& symbol);
-
- string symbol;
-
- struct history_t {
- history_map prices;
- ptime last_lookup;
- history_t() : last_lookup() {}
- };
- optional<history_t> history;
-
- void add_price(const moment_t& date, const amount_t& price);
- bool remove_price(const moment_t& date);
- amount_t value(const moment_t& moment = now);
-
-public:
- class updater_t {
- public:
- virtual ~updater_t() {}
- virtual void operator()(commodity_base_t& commodity,
- const moment_t& moment,
- const moment_t& date,
- const moment_t& last,
- amount_t& price) = 0;
- };
- friend class updater_t;
-
- static updater_t * updater;
};
-typedef std::map<const string, commodity_t *> commodities_map;
-typedef std::pair<const string, commodity_t *> commodities_pair;
-
-typedef std::vector<commodity_t *> commodities_array;
+class annotated_commodity_t;
class commodity_t
- : public equality_comparable<commodity_t, noncopyable>
+ : public equality_comparable1<commodity_t, noncopyable>
{
- friend class annotated_commodity_t;
-
public:
- // This map remembers all commodities that have been defined.
-
- static commodities_map commodities;
- static commodities_array * commodities_by_ident;
- static bool commodities_sorted;
- static commodity_t * null_commodity;
- static commodity_t * default_commodity;
-
- static commodity_t * create(const string& symbol);
- static commodity_t * find(const string& name);
- static commodity_t * find_or_create(const string& symbol);
+ static bool symbol_needs_quotes(const string& symbol);
- static bool needs_quotes(const string& symbol);
+ typedef commodity_base_t::flags_t flags_t;
+ typedef commodity_base_t::history_t history_t;
+ typedef commodity_base_t::history_map history_map;
+ typedef commodity_base_t::history_pair history_pair;
+ typedef uint_least32_t ident_t;
- static void make_alias(const string& symbol,
- commodity_t * commodity);
-
- // These are specific to each commodity reference
-
- typedef unsigned long ident_t;
+ shared_ptr<commodity_base_t> base;
+ commodity_pool_t * parent_;
ident_t ident;
- commodity_base_t * base;
- string qualified_symbol;
+ optional<string> qualified_symbol;
+ optional<string> mapping_key_;
bool annotated;
public:
- explicit commodity_t() : base(NULL), annotated(false) {
+ explicit commodity_t(commodity_pool_t * _parent,
+ const shared_ptr<commodity_base_t>& _base)
+ : base(_base), parent_(_parent), annotated(false) {
TRACE_CTOR(commodity_t, "");
}
- commodity_t(const commodity_t& o)
- : ident(o.ident), base(o.base),
- qualified_symbol(o.qualified_symbol), annotated(o.annotated) {
- TRACE_CTOR(commodity_t, "copy");
- }
virtual ~commodity_t() {
TRACE_DTOR(commodity_t);
}
- operator bool() const {
- return this != null_commodity;
- }
+ operator bool() const;
+
virtual bool operator==(const commodity_t& comm) const {
if (comm.annotated)
return comm == *this;
- return base == comm.base;
+ return base.get() == comm.base.get();
}
+ commodity_pool_t& parent() const {
+ return *parent_;
+ }
+
+ annotated_commodity_t& as_annotated();
+ const annotated_commodity_t& as_annotated() const;
+
string base_symbol() const {
return base->symbol;
}
string symbol() const {
- return qualified_symbol;
+ return qualified_symbol ? *qualified_symbol : base_symbol();
}
- void write(std::ostream& out) const {
- out << symbol();
+ string mapping_key() const {
+ if (mapping_key_)
+ return *mapping_key_;
+ else
+ return base_symbol();
}
- string name() const {
+ optional<string> name() const {
return base->name;
}
- void set_name(const string& arg) {
+ void set_name(const optional<string>& arg = optional<string>()) {
base->name = arg;
}
- string note() const {
+ optional<string> note() const {
return base->note;
}
- void set_note(const string& arg) {
+ void set_note(const optional<string>& arg = optional<string>()) {
base->note = arg;
}
- unsigned char precision() const {
+ amount_t::precision_t precision() const {
return base->precision;
}
- void set_precision(unsigned char arg) {
+ void set_precision(amount_t::precision_t arg) {
base->precision = arg;
}
- unsigned char flags() const {
+ flags_t flags() const {
return base->flags;
}
- void set_flags(unsigned char arg) {
+ void set_flags(flags_t arg) {
base->flags = arg;
}
- void add_flags(unsigned char arg) {
+ void add_flags(flags_t arg) {
base->flags |= arg;
}
- void drop_flags(unsigned char arg) {
+ void drop_flags(flags_t arg) {
base->flags &= ~arg;
}
optional<amount_t> smaller() const {
return base->smaller;
}
- void set_smaller(const amount_t& arg) {
+ void set_smaller(const optional<amount_t>& arg = optional<amount_t>()) {
base->smaller = arg;
}
optional<amount_t> larger() const {
return base->larger;
}
- void set_larger(const amount_t& arg) {
+ void set_larger(const optional<amount_t>& arg = optional<amount_t>()) {
base->larger = arg;
}
- optional<commodity_base_t::history_t> history() const {
+ optional<history_t> history() const {
return base->history;
}
- void add_price(const moment_t& date, const amount_t& price) {
- return base->add_price(date, price);
- }
- bool remove_price(const moment_t& date) {
- return base->remove_price(date);
- }
- amount_t value(const moment_t& moment = now) const {
- return base->value(moment);
+ void add_price(const moment_t& date, const amount_t& price);
+ bool remove_price(const moment_t& date);
+
+ optional<amount_t> value(const optional<moment_t>& moment =
+ optional<moment_t>());
+
+ void write(std::ostream& out) const {
+ out << symbol();
}
bool valid() const;
};
-class annotated_commodity_t : public commodity_t
+inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
+ comm.write(out);
+ return out;
+}
+
+struct annotation_t : public equality_comparable<annotation_t>
{
- public:
- const commodity_t * ptr;
+ optional<amount_t> price;
+ optional<moment_t> date;
+ optional<string> tag;
- optional<amount_t> price;
- optional<moment_t> date;
- optional<string> tag;
+ explicit annotation_t(const optional<amount_t>& _price = optional<amount_t>(),
+ const optional<moment_t>& _date = optional<moment_t>(),
+ const optional<string>& _tag = optional<string>())
+ : price(_price), date(_date), tag(_tag) {}
- explicit annotated_commodity_t() {
+ operator bool() const {
+ return price || date || tag;
+ }
+
+ bool operator==(const annotation_t& rhs) const {
+ return (price == rhs.price &&
+ date == rhs.date &&
+ tag == rhs.tag);
+ }
+
+ void write(std::ostream& out) const {
+ out << "price " << (price ? price->to_string() : "NONE") << " "
+ << "date " << (date ? *date : moment_t()) << " "
+ << "tag " << (tag ? *tag : "NONE");
+ }
+
+ bool valid() const {
+ assert(*this);
+ }
+};
+
+inline std::ostream& operator<<(std::ostream& out, const annotation_t& details) {
+ details.write(out);
+ return out;
+}
+
+class annotated_commodity_t
+ : public commodity_t,
+ equality_comparable1<annotated_commodity_t, noncopyable>
+{
+public:
+ commodity_t * ptr;
+ annotation_t details;
+
+ explicit annotated_commodity_t(commodity_t * _ptr,
+ const annotation_t& _details)
+ : commodity_t(_ptr->parent_, _ptr->base), ptr(_ptr), details(_details) {
TRACE_CTOR(annotated_commodity_t, "");
annotated = true;
}
@@ -288,37 +285,129 @@ class annotated_commodity_t : public commodity_t
virtual bool operator==(const commodity_t& comm) const;
+ commodity_t& referent() {
+ return *ptr;
+ }
+ const commodity_t& referent() const {
+ return *ptr;
+ }
+
void write_annotations(std::ostream& out) const {
- annotated_commodity_t::write_annotations(out, price, date, tag);
+ annotated_commodity_t::write_annotations(out, details);
+ }
+
+ static void write_annotations(std::ostream& out,
+ const annotation_t& info);
+};
+
+struct compare_amount_commodities {
+ bool operator()(const amount_t * left, const amount_t * right) const;
+};
+
+class commodity_pool_t : public noncopyable
+{
+public:
+ /**
+ * The commodities collection in commodity_pool_t maintains pointers
+ * to all the commodities which have ever been created by the user,
+ * whether explicitly by calling the create methods of
+ * commodity_pool_t, or implicitly by parsing a commoditized amount.
+ *
+ * The `commodities' member variable represents a collection which
+ * is indexed by two vertices: first, and ordered sequence of unique
+ * integer which identify commodities by a numerical identifier; and
+ * second, by a hashed set of symbolic names which reflect how the
+ * commodity was referred to by the user.
+ */
+ typedef multi_index_container<
+ commodity_t *,
+ multi_index::indexed_by<
+ multi_index::ordered_unique<
+ multi_index::member<commodity_t,
+ commodity_t::ident_t, &commodity_t::ident> >,
+ multi_index::hashed_unique<
+ multi_index::const_mem_fun<commodity_t,
+ string, &commodity_t::mapping_key> >
+ >
+ > commodities_t;
+
+ commodities_t commodities;
+ commodity_t * null_commodity;
+ commodity_t * default_commodity;
+
+private:
+ template<typename T>
+ struct first_initialized
+ {
+ typedef T result_type;
+
+ template<typename InputIterator>
+ T operator()(InputIterator first, InputIterator last) const
+ {
+ for (; first != last; first++)
+ if (*first)
+ return *first;
+ return T();
+ }
+ };
+
+public:
+ boost::signal<optional<amount_t>
+ (commodity_t& commodity,
+ const optional<moment_t>& date,
+ const optional<moment_t>& moment,
+ const optional<moment_t>& last),
+ first_initialized<optional<amount_t> > > get_quote;
+
+ explicit commodity_pool_t();
+
+ ~commodity_pool_t() {
+ typedef commodity_pool_t::commodities_t::nth_index<0>::type
+ commodities_by_ident;
+
+ commodities_by_ident& ident_index = commodities.get<0>();
+ for (commodities_by_ident::iterator i = ident_index.begin();
+ i != ident_index.end();
+ i++)
+ checked_delete(*i);
}
- static void write_annotations(std::ostream& out,
- const optional<amount_t>& price,
- const optional<moment_t>& date,
- const optional<string>& tag);
+ commodity_t * create(const string& symbol);
+ commodity_t * find(const string& name);
+ commodity_t * find(const commodity_t::ident_t ident);
+ commodity_t * find_or_create(const string& symbol);
- private:
- static commodity_t * create(const commodity_t& comm,
- const optional<amount_t>& price,
- const optional<moment_t>& date,
- const optional<string>& tag,
- const string& mapping_key);
+ commodity_t * create(const string& symbol, const annotation_t& details);
+ commodity_t * find(const string& symbol, const annotation_t& details);
+ commodity_t * find_or_create(const string& symbol,
+ const annotation_t& details);
- static commodity_t * find_or_create(const commodity_t& comm,
- const optional<amount_t>& price,
- const optional<moment_t>& date,
- const optional<string>& tag);
+ commodity_t * create(commodity_t& comm,
+ const annotation_t& details,
+ const string& mapping_key);
- friend class amount_t;
-};
+ commodity_t * find_or_create(commodity_t& comm,
+ const annotation_t& details);
-inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
- out << comm.symbol();
- return out;
-}
+ void parse_amount(amount_t& amount, std::istream& in,
+ amount_t::flags_t flags = 0) {
+ amount.parse(*this, in, flags);
+ }
+ void parse_amount(amount_t& amount, const string& str,
+ amount_t::flags_t flags = 0) {
+ amount.parse(*this, str, flags);
+ }
-struct compare_amount_commodities {
- bool operator()(const amount_t * left, const amount_t * right) const;
+ amount_t parse_amount(std::istream& in, amount_t::flags_t flags = 0) {
+ amount_t temp;
+ parse_amount(temp, in, flags);
+ return temp;
+ }
+ amount_t parse_amount(const string& str, amount_t::flags_t flags = 0) {
+ amount_t temp;
+ parse_amount(temp, str, flags);
+ return temp;
+ }
};
} // namespace ledger