diff options
Diffstat (limited to 'src/commodity.h')
-rw-r--r-- | src/commodity.h | 393 |
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 |