summaryrefslogtreecommitdiff
path: root/src/value.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/value.h')
-rw-r--r--src/value.h233
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);