diff options
Diffstat (limited to 'src/value.h')
-rw-r--r-- | src/value.h | 233 |
1 files changed, 115 insertions, 118 deletions
diff --git a/src/value.h b/src/value.h index 2e3998f3..6fe24da6 100644 --- a/src/value.h +++ b/src/value.h @@ -49,7 +49,7 @@ #ifndef _VALUE_H #define _VALUE_H -#include "balance.h" // includes amount.h +#include "balance.h" // includes amount.h #include "mask.h" namespace ledger { @@ -57,7 +57,6 @@ namespace ledger { DECLARE_EXCEPTION(value_error, std::runtime_error); class scope_t; -class expr_t; /** * @class value_t @@ -75,21 +74,21 @@ class expr_t; */ class value_t : public ordered_field_operators<value_t, - equality_comparable<value_t, balance_t, - additive<value_t, balance_t, - multiplicative<value_t, balance_t, - ordered_field_operators<value_t, amount_t, - ordered_field_operators<value_t, double, - ordered_field_operators<value_t, unsigned long, - ordered_field_operators<value_t, long> > > > > > > > + equality_comparable<value_t, balance_t, + additive<value_t, balance_t, + multiplicative<value_t, balance_t, + ordered_field_operators<value_t, amount_t, + ordered_field_operators<value_t, double, + ordered_field_operators<value_t, unsigned long, + ordered_field_operators<value_t, long> > > > > > > > { public: /** * The sequence_t member type abstracts the type used to represent a * resizable "array" of value_t objects. */ - typedef std::deque<value_t> sequence_t; - typedef sequence_t::iterator iterator; + typedef ptr_deque<value_t> sequence_t; + typedef sequence_t::iterator iterator; typedef sequence_t::const_iterator const_iterator; typedef sequence_t::difference_type difference_type; @@ -99,18 +98,18 @@ public: * type_t. */ enum type_t { - VOID, // a null value (i.e., uninitialized) - BOOLEAN, // a boolean - DATETIME, // a date and time (Boost posix_time) - DATE, // a date (Boost gregorian::date) - INTEGER, // a signed integer value - AMOUNT, // a ledger::amount_t - BALANCE, // a ledger::balance_t - STRING, // a string object - MASK, // a regular expression mask - SEQUENCE, // a vector of value_t objects - SCOPE, // a pointer to a scope - EXPR // a pointer to a value expression + VOID, // a null value (i.e., uninitialized) + BOOLEAN, // a boolean + DATETIME, // a date and time (Boost posix_time) + DATE, // a date (Boost gregorian::date) + INTEGER, // a signed integer value + AMOUNT, // a ledger::amount_t + BALANCE, // a ledger::balance_t + STRING, // a string object + MASK, // a regular expression mask + SEQUENCE, // a vector of value_t objects + SCOPE, // a pointer to a scope + ANY // a pointer to an arbitrary object }; private: @@ -128,18 +127,18 @@ private: * The `type' member holds the value_t::type_t value representing * the type of the object stored. */ - variant<bool, // BOOLEAN - datetime_t, // DATETIME - date_t, // DATE - long, // INTEGER - amount_t, // AMOUNT - balance_t *, // BALANCE - string, // STRING - mask_t, // MASK - sequence_t *, // SEQUENCE - scope_t *, // SCOPE - expr_t * // EXPR - > data; + variant<bool, // BOOLEAN + datetime_t, // DATETIME + date_t, // DATE + long, // INTEGER + amount_t, // AMOUNT + balance_t *, // BALANCE + string, // STRING + mask_t, // MASK + sequence_t *, // SEQUENCE + scope_t *, // SCOPE + boost::any // ANY + > data; type_t type; @@ -160,7 +159,7 @@ private: TRACE_CTOR(value_t::storage_t, ""); } - public: // so `checked_delete' can access it + public: // so `checked_delete' can access it /** * Destructor. Must only be called when the reference count has * reached zero. The `destroy' method is used to do the actual @@ -193,16 +192,16 @@ private: */ void acquire() const { DEBUG("value.storage.refcount", - "Acquiring " << this << ", refc now " << refc + 1); + "Acquiring " << this << ", refc now " << refc + 1); VERIFY(refc >= 0); refc++; } void release() const { DEBUG("value.storage.refcount", - "Releasing " << this << ", refc now " << refc - 1); + "Releasing " << this << ", refc now " << refc - 1); VERIFY(refc > 0); if (--refc == 0) - checked_delete(this); + checked_delete(this); } friend inline void intrusive_ptr_add_ref(value_t::storage_t * storage) { @@ -216,15 +215,15 @@ private: DEBUG("value.storage.refcount", "Destroying " << this); switch (type) { case VOID: - return; + return; case BALANCE: - checked_delete(boost::get<balance_t *>(data)); - break; + checked_delete(boost::get<balance_t *>(data)); + break; case SEQUENCE: - checked_delete(boost::get<sequence_t *>(data)); - break; + checked_delete(boost::get<sequence_t *>(data)); + break; default: - break; + break; } data = false; type = VOID; @@ -256,8 +255,7 @@ private: * subsequently be modified. */ void _dup() { - VERIFY(storage); - if (storage->refc > 1) + if (storage && storage->refc > 1) storage = new storage_t(*storage.get()); } @@ -354,10 +352,13 @@ public: TRACE_CTOR(value_t, "scope_t *"); set_scope(item); } - explicit value_t(const expr_t& item) { - TRACE_CTOR(value_t, "const expr_t&"); - set_expr(item); +#if 0 + template <typename T> + explicit value_t(T& item) { + TRACE_CTOR(value_t, "T&"); + set_any(item); } +#endif /** * Destructor. This does not do anything, because the intrusive_ptr @@ -424,8 +425,8 @@ public: temp.in_place_negate(); return temp; } - void in_place_negate(); // exists for efficiency's sake - void in_place_not(); // exists for efficiency's sake + void in_place_negate(); // exists for efficiency's sake + void in_place_not(); // exists for efficiency's sake value_t operator-() const { return negated(); @@ -466,25 +467,24 @@ public: temp.in_place_reduce(); return temp; } - void in_place_reduce(); // exists for efficiency's sake + void in_place_reduce(); // exists for efficiency's sake value_t unreduced() const { value_t temp(*this); temp.in_place_unreduce(); return temp; } - void in_place_unreduce(); // exists for efficiency's sake + void in_place_unreduce(); // exists for efficiency's sake // Return the "market value" of a given value at a specific time. - value_t value(const bool primary_only = false, - const optional<datetime_t>& moment = none, - const optional<commodity_t&>& in_terms_of = none) const; + value_t value(const optional<datetime_t>& moment = none, + const optional<commodity_t&>& in_terms_of = none) const; value_t price() const; - value_t exchange_commodities(const std::string& commodities, - const bool add_prices = false, - const optional<datetime_t>& moment = none); + value_t exchange_commodities(const std::string& commodities, + const bool add_prices = false, + const optional<datetime_t>& moment = none); /** * Truth tests. @@ -531,7 +531,7 @@ public: * is_string() * is_mask() * is_sequence() - * is_pointer() + * is_any() * * There are corresponding as_*() methods that represent a value as a * reference to its underlying type. For example, as_long() returns a @@ -730,29 +730,54 @@ public: } /** - * Dealing with expr pointers. + * Dealing with any type at all is bit involved because we actually + * deal with typed object. For example, if you call as_any it returns + * a boost::any object, but if you use as_any<type_t>, then it returns + * a type_t by value. */ - bool is_expr() const { - return is_type(EXPR); + bool is_any() const { + return is_type(ANY); + } + template <typename T> + bool is_any() const { + return (is_type(ANY) && + boost::get<boost::any>(storage->data).type() == typeid(T)); + } + boost::any& as_any_lval() { + VERIFY(is_any()); + _dup(); + return boost::get<boost::any>(storage->data); } - expr_t& as_expr_lval() const { - VERIFY(is_expr()); - return *boost::get<expr_t *>(storage->data); + template <typename T> + T& as_any_lval() { + return any_cast<T&>(as_any_lval()); } - const expr_t& as_expr() const { - VERIFY(is_expr()); - return *boost::get<expr_t *>(storage->data); + const boost::any& as_any() const { + VERIFY(is_any()); + return boost::get<boost::any>(storage->data); + } + template <typename T> + const T& as_any() const { + return any_cast<const T&>(as_any()); + } + void set_any(const boost::any& val) { + set_type(ANY); + storage->data = val; + } + template <typename T> + void set_any(T& val) { + set_type(ANY); + storage->data = boost::any(val); } - void set_expr(const expr_t& val); /** * Data conversion methods. These methods convert a value object to * its underlying type, where possible. If not possible, an * exception is thrown. */ - bool to_boolean() const; - int to_int() const; - long to_long() const; + bool to_boolean() const; + int to_int() const; + long to_long() const; datetime_t to_datetime() const; date_t to_date() const; amount_t to_amount() const; @@ -837,7 +862,7 @@ public: *this = sequence_t(); if (! is_sequence()) in_place_cast(SEQUENCE); - as_sequence_lval().push_front(val); + as_sequence_lval().push_front(new value_t(val)); } void push_back(const value_t& val) { @@ -845,7 +870,7 @@ public: *this = sequence_t(); if (! is_sequence()) in_place_cast(SEQUENCE); - as_sequence_lval().push_back(val); + as_sequence_lval().push_back(new value_t(val)); } void pop_back() { @@ -864,13 +889,13 @@ public: std::size_t new_size = seq.size(); if (new_size == 0) { #if BOOST_VERSION >= 103700 - storage.reset(); + storage.reset(); #else - storage = intrusive_ptr<storage_t>(); + storage = intrusive_ptr<storage_t>(); #endif } else if (new_size == 1) { - *this = seq.front(); + *this = seq.front(); } } } @@ -905,48 +930,16 @@ public: /** * Informational methods. */ - string label(optional<type_t> the_type = none) const { - switch (the_type ? *the_type : type()) { - case VOID: - return _("an uninitialized value"); - case BOOLEAN: - return _("a boolean"); - case DATETIME: - return _("a date/time"); - case DATE: - return _("a date"); - case INTEGER: - return _("an integer"); - case AMOUNT: - return _("an amount"); - case BALANCE: - return _("a balance"); - case STRING: - return _("a string"); - case MASK: - return _("a regexp"); - case SEQUENCE: - return _("a sequence"); - case SCOPE: - return _("a scope"); - case EXPR: - return _("a expr"); - default: - assert(false); - break; - } - assert(false); - return _("<invalid>"); - } + string label(optional<type_t> the_type = none) const; /** * Printing methods. */ - void print(std::ostream& out, - const int first_width = -1, - const int latter_width = -1, - const bool right_justify = false, - const bool colorize = false) const; + void print(std::ostream& out, + const int first_width = -1, + const int latter_width = -1, + const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const; + void dump(std::ostream& out, const bool relaxed = true) const; /** @@ -994,6 +987,10 @@ inline string value_context(const value_t& val) { return buf.str(); } +inline value_t scope_value(scope_t * val) { + return value_t(val); +} + template <typename T> inline value_t& add_or_set_value(value_t& lhs, const T& rhs) { if (lhs.is_null()) @@ -1012,7 +1009,7 @@ struct sort_value_t }; bool sort_value_is_less_than(const std::list<sort_value_t>& left_values, - const std::list<sort_value_t>& right_values); + const std::list<sort_value_t>& right_values); void to_xml(std::ostream& out, const value_t& value); |