summaryrefslogtreecommitdiff
path: root/amount.h
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2006-03-03 09:45:44 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 02:41:28 -0400
commit96d6d62ad94082ca777c2c88b88e0346a5d00e65 (patch)
treeb50a26a9c4c0cc0ab90b1772cc75368739501fa5 /amount.h
parent7d3e45958e805f8acaf399ef14d53757979240ab (diff)
downloadfork-ledger-96d6d62ad94082ca777c2c88b88e0346a5d00e65.tar.gz
fork-ledger-96d6d62ad94082ca777c2c88b88e0346a5d00e65.tar.bz2
fork-ledger-96d6d62ad94082ca777c2c88b88e0346a5d00e65.zip
Began support for improved commodity handling.
Diffstat (limited to 'amount.h')
-rw-r--r--amount.h325
1 files changed, 220 insertions, 105 deletions
diff --git a/amount.h b/amount.h
index d47aa575..b209adfc 100644
--- a/amount.h
+++ b/amount.h
@@ -10,6 +10,8 @@
#include <cassert>
#include <exception>
+#include "debug.h"
+
namespace ledger {
class commodity_t;
@@ -70,10 +72,15 @@ class amount_t
void set_commodity(commodity_t& comm) {
commodity_ = &comm;
}
+ void annotate_commodity(const amount_t& price,
+ const std::time_t date = 0,
+ const std::string& tag = "");
+ void reduce_commodity(const bool keep_price = false,
+ const bool keep_date = false,
+ const bool keep_tag = false);
void clear_commodity() {
commodity_ = NULL;
}
- amount_t base() const;
amount_t price() const;
bool null() const {
@@ -298,147 +305,264 @@ inline std::istream& operator>>(std::istream& in, amount_t& amt) {
typedef std::map<const std::time_t, amount_t> history_map;
typedef std::pair<const std::time_t, amount_t> history_pair;
-typedef std::map<const std::string, commodity_t *> commodities_map;
-typedef std::pair<const std::string, commodity_t *> commodities_pair;
+class commodity_base_t;
-class commodity_t
+typedef std::map<const std::string, commodity_base_t *> base_commodities_map;
+typedef std::pair<const std::string, commodity_base_t *> base_commodities_pair;
+
+class commodity_base_t
{
public:
+ friend class commodity_t;
+ friend class annotated_commodity_t;
+
+ typedef unsigned long ident_t;
+
+ ident_t ident;
+ std::string name;
+ std::string note;
+ unsigned short precision;
+ unsigned short flags;
+ amount_t * smaller;
+ amount_t * larger;
+
+ commodity_base_t() : precision(0), flags(COMMODITY_STYLE_DEFAULTS),
+ history(NULL), smaller(NULL), larger(NULL) {}
+
+ commodity_base_t(const std::string& _symbol,
+ unsigned int _precision = 0,
+ unsigned int _flags = COMMODITY_STYLE_DEFAULTS)
+ : precision(_precision), flags(_flags), history(NULL),
+ smaller(NULL), larger(NULL), symbol(_symbol) {}
+
+ ~commodity_base_t() {
+ if (history) delete history;
+ if (smaller) delete smaller;
+ if (larger) delete larger;
+ }
+
+ static base_commodities_map commodities;
+ static commodity_base_t * create(const std::string& symbol);
+
+ std::string symbol;
+
+ struct history_t {
+ history_map prices;
+ std::time_t last_lookup;
+ };
+ history_t * history;
+
+ void add_price(const std::time_t date, const amount_t& price);
+ bool remove_price(const std::time_t date) {
+ if (history) {
+ history_map::size_type n = history->prices.erase(date);
+ return n > 0;
+ }
+ return false;
+ }
+
+ amount_t value(const std::time_t moment = std::time(NULL));
+
class updater_t {
public:
virtual ~updater_t() {}
- virtual void operator()(commodity_t& commodity,
+ virtual void operator()(commodity_base_t& commodity,
const std::time_t moment,
const std::time_t date,
const std::time_t last,
amount_t& price) = 0;
};
+ friend class updater_t;
- typedef unsigned long ident_t;
+ static updater_t * updater;
+};
- struct history_t {
- history_map prices;
- std::time_t last_lookup;
- };
+typedef std::map<const std::string, commodity_t *> commodities_map;
+typedef std::pair<const std::string, commodity_t *> commodities_pair;
+
+class commodity_t
+{
+ friend class annotated_commodity_t;
- history_t * history_;
+ public:
+ // This map remembers all commodities that have been defined.
- history_t *& history() {
- return base ? base->history() : history_;
- }
+ static commodities_map commodities;
+ static commodity_t * null_commodity;
+ static commodity_t * default_commodity;
- const std::string symbol;
- bool quote;
- std::string name_;
- std::string note_;
- unsigned short precision_;
- unsigned short flags_;
- ident_t ident;
- amount_t * smaller_;
- amount_t * larger_;
- commodity_t * base; // base commodity for AAPL {$10} is AAPL
- amount_t * price; // its price is therefore $10.00
+ static commodity_t * create(const std::string& symbol);
+ static commodity_t * find(const std::string& name);
+ static commodity_t * find_or_create(const std::string& symbol);
- std::string& name() {
- return base ? base->name() : name_;
- }
- std::string& note() {
- return base ? base->note() : note_;
+ static bool needs_quotes(const std::string& symbol);
+
+ static void make_alias(const std::string& symbol,
+ commodity_t * commodity);
+
+ // These are specific to each commodity reference
+
+ typedef unsigned long ident_t;
+
+ ident_t ident;
+ commodity_base_t * ptr;
+ std::string qualified_symbol;
+ bool annotated;
+
+ public:
+ explicit commodity_t() : ptr(NULL), annotated(false) {}
+
+ operator bool() const {
+ return this != null_commodity;
}
- unsigned short& precision() {
- return base ? base->precision() : precision_;
+ bool operator==(const commodity_t& comm) const {
+ return ptr == comm.ptr;
}
- unsigned short& flags() {
- return base ? base->flags() : flags_;
+ bool operator!=(const commodity_t& comm) const {
+ return ptr != comm.ptr;
}
- amount_t *& smaller() {
- return base ? base->smaller() : smaller_;
+
+ std::string base_symbol() const {
+ return ptr->symbol;
}
- amount_t *& larger() {
- return base ? base->larger() : larger_;
+ std::string symbol() const {
+ return qualified_symbol;
}
- // If set, this global function pointer is called to determine
- // whether prices have been updated in the meanwhile.
-
- static updater_t * updater;
-
- // This map remembers all commodities that have been defined.
+ void write(std::ostream& out) const {
+ out << symbol();
+ }
- static commodities_map commodities;
- static commodity_t * null_commodity;
- static commodity_t * default_commodity;
+ std::string name() const {
+ return ptr->name;
+ }
+ void set_name(const std::string& arg) {
+ ptr->name = arg;
+ }
- static bool add_commodity(commodity_t * commodity,
- const std::string symbol = "") {
- // The argument "symbol" is useful for creating a symbol alias to
- // an underlying commodity type; it is used by the Gnucash parser
- // to link "USD" to "$".
- std::pair<commodities_map::iterator, bool> result
- = commodities.insert(commodities_pair((symbol.empty() ?
- commodity->symbol : symbol),
- commodity));
- return result.second;
+ std::string note() const {
+ return ptr->note;
}
- static bool remove_commodity(commodity_t * commodity) {
- commodities_map::size_type n = commodities.erase(commodity->symbol);
- return n > 0;
+ void set_note(const std::string& arg) {
+ ptr->note = arg;
}
- static commodity_t * find_commodity(const std::string& symbol,
- bool auto_create = false);
- // Now the per-object constructor and methods
+ unsigned short precision() const {
+ return ptr->precision;
+ }
+ void set_precision(unsigned short arg) {
+ ptr->precision = arg;
+ }
- commodity_t(const std::string& _symbol = "",
- unsigned int _precision = 0,
- unsigned int _flags = COMMODITY_STYLE_DEFAULTS)
- : precision_(_precision), flags_(_flags), history_(NULL),
- smaller_(NULL), larger_(NULL), base(NULL), price(NULL) {
- set_symbol(_symbol);
+ unsigned short flags() const {
+ return ptr->flags;
}
- ~commodity_t() {
- if (history_) delete history_;
- if (smaller_) delete smaller_;
- if (larger_) delete larger_;
- if (price) delete price;
+ void set_flags(unsigned short arg) {
+ ptr->flags = arg;
+ }
+ void add_flags(unsigned short arg) {
+ ptr->flags |= arg;
+ }
+ void drop_flags(unsigned short arg) {
+ ptr->flags &= ~arg;
}
- operator bool() const {
- return this != null_commodity;
+ amount_t * smaller() const {
+ return ptr->smaller;
}
- bool operator==(const commodity_t& comm) const {
- return this == &comm;
+ void set_smaller(const amount_t& arg) {
+ if (ptr->smaller)
+ delete ptr->smaller;
+ ptr->smaller = new amount_t(arg);
}
- bool operator!=(const commodity_t& comm) const {
- return this != &comm;
+
+ amount_t * larger() const {
+ return ptr->larger;
+ }
+ void set_larger(const amount_t& arg) {
+ if (ptr->larger)
+ delete ptr->larger;
+ ptr->larger = new amount_t(arg);
}
- void set_symbol(const std::string& sym);
+ commodity_base_t::history_t * history() const {
+ return ptr->history;
+ }
- void add_price(const std::time_t date, const amount_t& price);
+ void add_price(const std::time_t date, const amount_t& price) {
+ return ptr->add_price(date, price);
+ }
bool remove_price(const std::time_t date) {
- if (history_) {
- history_map::size_type n = history_->prices.erase(date);
- return n > 0;
- }
- return false;
+ return ptr->remove_price(date);
+ }
+ amount_t value(const std::time_t moment = std::time(NULL)) const {
+ return ptr->value(moment);
}
-
- amount_t value(const std::time_t moment = std::time(NULL));
bool valid() const {
- if (symbol.empty() && this != null_commodity)
+ if (symbol().empty() && this != null_commodity)
return false;
- if (precision_ > 16)
+ if (precision() > 16)
return false;
return true;
}
};
+class annotated_commodity_t : public commodity_t
+{
+ public:
+ const commodity_t * base;
+
+ amount_t price;
+ std::time_t date;
+ std::string tag;
+
+ static std::string date_format;
+
+ static void write_annotations(std::ostream& out,
+ const amount_t& price,
+ const std::time_t date,
+ const std::string& tag);
+ static
+ std::string make_qualified_name(const commodity_t& comm,
+ const amount_t& price,
+ const std::time_t date,
+ const std::string& tag);
+ static
+ annotated_commodity_t * create(const commodity_t& comm,
+ const amount_t& price,
+ const std::time_t date,
+ const std::string& tag,
+ const std::string& entry_name = "");
+ static
+ annotated_commodity_t * create(const std::string& symbol,
+ const amount_t& price,
+ const std::time_t date,
+ const std::string& tag);
+ static
+ annotated_commodity_t * create(const std::string& symbol,
+ const std::string& price,
+ const std::string& date,
+ const std::string& tag);
+ static
+ annotated_commodity_t * find_or_create(const commodity_t& comm,
+ const amount_t& price,
+ const std::time_t date,
+ const std::string& tag);
+
+ explicit annotated_commodity_t() {
+ annotated = true;
+ }
+
+ void write_annotations(std::ostream& out) const {
+ annotated_commodity_t::write_annotations(out, price, date, tag);
+ }
+};
+
inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {
- out << comm.symbol;
+ out << comm.symbol();
return out;
}
@@ -449,21 +573,12 @@ inline commodity_t& amount_t::commodity() const {
return *commodity_;
}
-inline amount_t amount_t::base() const {
- if (commodity_ && commodity_->price) {
- amount_t temp(*this);
- assert(commodity_->base);
- temp.set_commodity(*(commodity_->base));
- return temp;
- } else {
- return *this;
- }
-}
-
inline amount_t amount_t::price() const {
- if (commodity_ && commodity_->price) {
- amount_t temp(*commodity_->price);
+ if (commodity_ && commodity_->annotated) {
+ amount_t temp(((annotated_commodity_t *)commodity_)->price);
temp *= *this;
+ DEBUG_PRINT("amounts.commodities",
+ "Returning price of " << *this << " = " << temp);
return temp;
} else {
return 0L;