diff options
author | John Wiegley <johnw@newartisans.com> | 2009-02-10 04:24:06 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2009-02-10 04:24:06 -0400 |
commit | d726624e60caa77354c7d4ef03cb564064316916 (patch) | |
tree | 31beac5e1eb8348ca6cb24717debaf6d72a97694 /src | |
parent | 6d4c3ffde57ad710be8ecff3675a13ddb9c44379 (diff) | |
download | fork-ledger-d726624e60caa77354c7d4ef03cb564064316916.tar.gz fork-ledger-d726624e60caa77354c7d4ef03cb564064316916.tar.bz2 fork-ledger-d726624e60caa77354c7d4ef03cb564064316916.zip |
Changed value_t to use boost::any (more type-safe).
Diffstat (limited to 'src')
-rw-r--r-- | src/value.cc | 187 | ||||
-rw-r--r-- | src/value.h | 155 |
2 files changed, 103 insertions, 239 deletions
diff --git a/src/value.cc b/src/value.cc index d28883a4..482dca21 100644 --- a/src/value.cc +++ b/src/value.cc @@ -41,128 +41,30 @@ value_t::storage_t& value_t::storage_t::operator=(const value_t::storage_t& rhs) type = rhs.type; switch (type) { - case DATETIME: - new(reinterpret_cast<datetime_t *>(data)) - datetime_t(*reinterpret_cast<datetime_t *> - (const_cast<char *>(rhs.data))); - break; - - case DATE: - new(reinterpret_cast<date_t *>(data)) - date_t(*reinterpret_cast<date_t *>(const_cast<char *>(rhs.data))); - break; - - case AMOUNT: - new(reinterpret_cast<amount_t *>(data)) - amount_t(*reinterpret_cast<amount_t *> - (const_cast<char *>(rhs.data))); - break; - case BALANCE: - *reinterpret_cast<balance_t **>(data) = - new balance_t(**reinterpret_cast<balance_t **> - (const_cast<char *>(rhs.data))); - break; - - case STRING: - new(reinterpret_cast<string *>(data)) - string(*reinterpret_cast<string *>(const_cast<char *>(rhs.data))); - break; - - case MASK: - new(reinterpret_cast<mask_t *>(data)) - mask_t(*reinterpret_cast<mask_t *>(const_cast<char *>(rhs.data))); + data = new balance_t(*boost::get<balance_t *>(rhs.data)); break; - case SEQUENCE: - *reinterpret_cast<sequence_t **>(data) = - new sequence_t(**reinterpret_cast<sequence_t **> - (const_cast<char *>(rhs.data))); + data = new sequence_t(*boost::get<sequence_t *>(rhs.data)); break; default: - // The rest are fundamental types, which can be copied using - // std::memcpy - std::memcpy(data, rhs.data, sizeof(data)); + data = rhs.data; break; } return *this; } -void value_t::storage_t::destroy() -{ - switch (type) { - case AMOUNT: - reinterpret_cast<amount_t *>(data)->~amount_t(); - break; - case BALANCE: - checked_delete(*reinterpret_cast<balance_t **>(data)); - break; - case STRING: - reinterpret_cast<string *>(data)->~string(); - break; - case MASK: - reinterpret_cast<mask_t *>(data)->~mask_t(); - break; - case SEQUENCE: - checked_delete(*reinterpret_cast<sequence_t **>(data)); - break; - case POINTER: - reinterpret_cast<boost::any *>(data)->~any(); - break; - - default: - break; - } - type = VOID; -} - void value_t::initialize() { -#if defined(DEBUG_ON) - LOGGER("value.init"); -#endif - true_value = new storage_t; true_value->type = BOOLEAN; - *reinterpret_cast<bool *>(true_value->data) = true; + boost::get<bool>(true_value->data) = true; false_value = new storage_t; false_value->type = BOOLEAN; - *reinterpret_cast<bool *>(false_value->data) = false; - - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(bool)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(datetime_t)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(date_t)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(long)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(amount_t)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(balance_t *)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(string)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(mask_t)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(sequence_t *)); - BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(boost::any)); - - DEBUG_(std::setw(3) << std::right << sizeof(bool) - << " sizeof(bool)"); - DEBUG_(std::setw(3) << std::right << sizeof(datetime_t) - << " sizeof(datetime_t)"); - DEBUG_(std::setw(3) << std::right << sizeof(date_t) - << " sizeof(date_t)"); - DEBUG_(std::setw(3) << std::right << sizeof(long) - << " sizeof(long)"); - DEBUG_(std::setw(3) << std::right << sizeof(amount_t) - << " sizeof(amount_t)"); - DEBUG_(std::setw(3) << std::right << sizeof(balance_t *) - << " sizeof(balance_t *)"); - DEBUG_(std::setw(3) << std::right << sizeof(string) - << " sizeof(string)"); - DEBUG_(std::setw(3) << std::right << sizeof(mask_t) - << " sizeof(mask_t)"); - DEBUG_(std::setw(3) << std::right << sizeof(sequence_t *) - << " sizeof(sequence_t *)"); - DEBUG_(std::setw(3) << std::right << sizeof(boost::any) - << " sizeof(boost::any)"); + boost::get<bool>(true_value->data) = false; } void value_t::shutdown() @@ -171,13 +73,6 @@ void value_t::shutdown() false_value = intrusive_ptr<storage_t>(); } -void value_t::_dup() -{ - assert(storage); - if (storage->refc > 1) - storage = new storage_t(*storage.get()); -} - value_t::operator bool() const { switch (type()) { @@ -1263,69 +1158,33 @@ value_t value_t::unrounded() const return NULL_VALUE; } -#if 0 -value_t value_t::annotated_price() const +void value_t::annotate(const annotation_t& details) { - switch (type()) { - case AMOUNT: { - optional<amount_t> temp = as_amount().annotation_details().price; - if (! temp) - return false; - return *temp; - } - - default: - break; - } - - throw_(value_error, "Cannot find the annotated price of " << label()); - return NULL_VALUE; + if (is_amount()) + as_amount_lval().annotate(details); + else + throw_(value_error, "Cannot annotate " << label()); } -value_t value_t::annotated_date() const +bool value_t::is_annotated() const { - switch (type()) { - case DATETIME: - return *this; - case DATE: - return *this; - - case AMOUNT: { - optional<datetime_t> temp = as_amount().annotation_details().date; - if (! temp) - return false; - return *temp; - } - - default: - break; - } - - throw_(value_error, "Cannot find the annotated date of " << label()); - return NULL_VALUE; + if (is_amount()) + return as_amount().is_annotated(); + else + throw_(value_error, + "Cannot determine whether " << label() << " is annotated"); + return false; } -value_t value_t::annotated_tag() const +annotation_t& value_t::annotation() { - switch (type()) { - case AMOUNT: { - optional<string> temp = as_amount().annotation_details().tag; - if (! temp) - return false; - return string_value(*temp); + if (is_amount()) + return as_amount_lval().annotation(); + else { + throw_(value_error, "Cannot request annotation of " << label()); + return as_amount_lval().annotation(); // quiet g++ warning } - - case STRING: - return *this; - - default: - break; - } - - throw_(value_error, "Cannot find the annotated tag of " << label()); - return NULL_VALUE; } -#endif value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const { diff --git a/src/value.h b/src/value.h index b9f8fcae..c49846d6 100644 --- a/src/value.h +++ b/src/value.h @@ -125,7 +125,18 @@ private: * The `type' member holds the value_t::type_t value representing * the type of the object stored. */ - char data[sizeof(amount_t)]; + 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 + boost::any // POINTER + > data; + type_t type; /** @@ -157,10 +168,18 @@ private: TRACE_DTOR(value_t::storage_t); DEBUG("value.storage.refcount", "Destroying " << this); assert(refc == 0); - destroy(); - } - void destroy(); + switch (type) { + case BALANCE: + checked_delete(boost::get<balance_t *>(data)); + break; + case SEQUENCE: + checked_delete(boost::get<sequence_t *>(data)); + break; + default: + break; + } + } private: /** @@ -202,7 +221,7 @@ private: }; /** - * The actual data for each value_t is kept in the `storage' member. + * The actual data for each value_t is kept in reference counted storage. * Data is modified using a copy-on-write policy. */ intrusive_ptr<storage_t> storage; @@ -213,20 +232,19 @@ private: * * _clear() removes our pointer to the current value and initializes * a new storage bin for things to be stored in. - * - * _reset() makes the current object appear as if it were - * uninitialized. */ - void _dup(); + void _dup() { + assert(storage); + if (storage->refc > 1) + storage = new storage_t(*storage.get()); + } void _clear() { - if (! storage || storage->refc > 1) + if (! storage || storage->refc > 1) { storage = new storage_t; - else - storage->destroy(); - } - void _reset() { - if (storage) - storage = intrusive_ptr<storage_t>(); + } else { + storage->data = false; // destruct any other type + storage->type = VOID; + } } /** @@ -455,7 +473,7 @@ private: void set_type(type_t new_type) { assert(new_type >= VOID && new_type <= POINTER); if (new_type == VOID) { - _reset(); + storage.reset(); assert(is_null()); } else { _clear(); @@ -500,11 +518,11 @@ public: bool& as_boolean_lval() { assert(is_boolean()); _dup(); - return *reinterpret_cast<bool *>(storage->data); + return boost::get<bool>(storage->data); } const bool& as_boolean() const { assert(is_boolean()); - return *reinterpret_cast<bool *>(storage->data); + return boost::get<bool>(storage->data); } void set_boolean(const bool val) { set_type(BOOLEAN); @@ -517,15 +535,15 @@ public: datetime_t& as_datetime_lval() { assert(is_datetime()); _dup(); - return *reinterpret_cast<datetime_t *>(storage->data); + return boost::get<datetime_t>(storage->data); } const datetime_t& as_datetime() const { assert(is_datetime()); - return *reinterpret_cast<datetime_t *>(storage->data); + return boost::get<datetime_t>(storage->data); } void set_datetime(const datetime_t& val) { set_type(DATETIME); - new(reinterpret_cast<datetime_t *>(storage->data)) datetime_t(val); + storage->data = val; } bool is_date() const { @@ -534,15 +552,15 @@ public: date_t& as_date_lval() { assert(is_date()); _dup(); - return *reinterpret_cast<date_t *>(storage->data); + return boost::get<date_t>(storage->data); } const date_t& as_date() const { assert(is_date()); - return *reinterpret_cast<date_t *>(storage->data); + return boost::get<date_t>(storage->data); } void set_date(const date_t& val) { set_type(DATE); - new(reinterpret_cast<date_t *>(storage->data)) date_t(val); + storage->data = val; } bool is_long() const { @@ -551,15 +569,15 @@ public: long& as_long_lval() { assert(is_long()); _dup(); - return *reinterpret_cast<long *>(storage->data); + return boost::get<long>(storage->data); } const long& as_long() const { assert(is_long()); - return *reinterpret_cast<long *>(storage->data); + return boost::get<long>(storage->data); } void set_long(const long val) { set_type(INTEGER); - *reinterpret_cast<long *>(storage->data) = val; + storage->data = val; } bool is_amount() const { @@ -568,20 +586,16 @@ public: amount_t& as_amount_lval() { assert(is_amount()); _dup(); - amount_t& amt(*reinterpret_cast<amount_t *>(storage->data)); - assert(amt.valid()); - return amt; + return boost::get<amount_t>(storage->data); } const amount_t& as_amount() const { assert(is_amount()); - amount_t& amt(*reinterpret_cast<amount_t *>(storage->data)); - assert(amt.valid()); - return amt; + return boost::get<amount_t>(storage->data); } void set_amount(const amount_t& val) { assert(val.valid()); set_type(AMOUNT); - new(reinterpret_cast<amount_t *>(storage->data)) amount_t(val); + storage->data = val; } bool is_balance() const { @@ -590,20 +604,16 @@ public: balance_t& as_balance_lval() { assert(is_balance()); _dup(); - balance_t& bal(**reinterpret_cast<balance_t **>(storage->data)); - assert(bal.valid()); - return bal; + return *boost::get<balance_t *>(storage->data); } const balance_t& as_balance() const { assert(is_balance()); - balance_t& bal(**reinterpret_cast<balance_t **>(storage->data)); - assert(bal.valid()); - return bal; + return *boost::get<balance_t *>(storage->data); } void set_balance(const balance_t& val) { assert(val.valid()); set_type(BALANCE); - *reinterpret_cast<balance_t **>(storage->data) = new balance_t(val); + storage->data = new balance_t(val); } bool is_string() const { @@ -612,19 +622,19 @@ public: string& as_string_lval() { assert(is_string()); _dup(); - return *reinterpret_cast<string *>(storage->data); + return boost::get<string>(storage->data); } const string& as_string() const { assert(is_string()); - return *reinterpret_cast<string *>(storage->data); + return boost::get<string>(storage->data); } void set_string(const string& val = "") { set_type(STRING); - new(reinterpret_cast<string *>(storage->data)) string(val); + storage->data = val; } void set_string(const char * val = "") { set_type(STRING); - new(reinterpret_cast<string *>(storage->data)) string(val); + storage->data = string(val); } bool is_mask() const { @@ -633,19 +643,19 @@ public: mask_t& as_mask_lval() { assert(is_mask()); _dup(); - return *reinterpret_cast<mask_t *>(storage->data); + return boost::get<mask_t>(storage->data); } const mask_t& as_mask() const { assert(is_mask()); - return *reinterpret_cast<mask_t *>(storage->data); + return boost::get<mask_t>(storage->data); } void set_mask(const string& val) { set_type(MASK); - new(reinterpret_cast<mask_t *>(storage->data)) mask_t(val); + storage->data = mask_t(val); } void set_mask(const mask_t& val) { set_type(MASK); - new(reinterpret_cast<mask_t *>(storage->data)) mask_t(val); + storage->data = val; } bool is_sequence() const { @@ -654,15 +664,15 @@ public: sequence_t& as_sequence_lval() { assert(is_sequence()); _dup(); - return **reinterpret_cast<sequence_t **>(storage->data); + return *boost::get<sequence_t *>(storage->data); } const sequence_t& as_sequence() const { assert(is_sequence()); - return **reinterpret_cast<sequence_t **>(storage->data); + return *boost::get<sequence_t *>(storage->data); } void set_sequence(const sequence_t& val) { set_type(SEQUENCE); - *reinterpret_cast<sequence_t **>(storage->data) = new sequence_t(val); + storage->data = new sequence_t(val); } /** @@ -679,42 +689,36 @@ public: boost::any& as_any_pointer_lval() { assert(is_pointer()); _dup(); - return *reinterpret_cast<boost::any *>(storage->data); + return boost::get<boost::any>(storage->data); } template <typename T> T * as_pointer_lval() { - assert(is_pointer()); - _dup(); - return any_cast<T *>(*reinterpret_cast<boost::any *>(storage->data)); + return any_cast<T *>(as_any_pointer_lval()); } template <typename T> T& as_ref_lval() { - assert(is_pointer()); - _dup(); - return *any_cast<T *>(*reinterpret_cast<boost::any *>(storage->data)); + return *as_pointer_lval<T>(); } const boost::any& as_any_pointer() const { assert(is_pointer()); - return *reinterpret_cast<boost::any *>(storage->data); + return boost::get<boost::any>(storage->data); } template <typename T> T * as_pointer() const { - assert(is_pointer()); - return any_cast<T *>(*reinterpret_cast<boost::any *>(storage->data)); + return any_cast<T *>(as_any_pointer()); } template <typename T> T& as_ref() const { - assert(is_pointer()); - return *any_cast<T *>(*reinterpret_cast<boost::any *>(storage->data)); + return *as_pointer<T>(); } void set_any_pointer(const boost::any& val) { set_type(POINTER); - new(reinterpret_cast<boost::any *>(storage->data)) boost::any(val); + storage->data = val; } template <typename T> void set_pointer(T * val) { set_type(POINTER); - new(reinterpret_cast<boost::any *>(storage->data)) boost::any(val); + storage->data = boost::any(val); } /** @@ -765,12 +769,13 @@ public: /** * Annotated commodity methods. */ -#if 0 - // These helper methods only apply to AMOUNT values. - value_t annotated_price() const; - value_t annotated_date() const; - value_t annotated_tag() const; -#endif + void annotate(const annotation_t& details); + bool is_annotated() const; + + annotation_t& annotation(); + const annotation_t& annotation() const { + return const_cast<value_t&>(*this).annotation(); + } value_t strip_annotations(const keep_details_t& what_to_keep) const; @@ -821,14 +826,14 @@ public: assert(! is_null()); if (! is_sequence()) { - _reset(); + storage.reset(); } else { as_sequence_lval().pop_back(); const sequence_t& seq(as_sequence()); std::size_t new_size = seq.size(); if (new_size == 0) - _reset(); + storage.reset(); else if (new_size == 1) *this = seq.front(); } |