summaryrefslogtreecommitdiff
path: root/value.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-08-05 13:17:04 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-08-05 18:05:49 -0400
commitf6f4a46cf5b14f9a2170cd6475958efbf320caec (patch)
tree05bc1defcdebc201de3dd10477483d906a842821 /value.cc
parentb7970b29855563e4c67f85af8b31233eda80c22a (diff)
downloadfork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.gz
fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.bz2
fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.zip
Moved around most of the files so that source code is in src/, documentation
is in doc/, etc.
Diffstat (limited to 'value.cc')
-rw-r--r--value.cc1773
1 files changed, 0 insertions, 1773 deletions
diff --git a/value.cc b/value.cc
deleted file mode 100644
index ea52af1f..00000000
--- a/value.cc
+++ /dev/null
@@ -1,1773 +0,0 @@
-/*
- * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of New Artisans LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "value.h"
-#include "binary.h"
-
-namespace ledger {
-
-intrusive_ptr<value_t::storage_t> value_t::true_value;
-intrusive_ptr<value_t::storage_t> value_t::false_value;
-
-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 BALANCE_PAIR:
- *reinterpret_cast<balance_pair_t **>(data) =
- new balance_pair_t(**reinterpret_cast<balance_pair_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 SEQUENCE:
- *reinterpret_cast<sequence_t **>(data) =
- new sequence_t(**reinterpret_cast<sequence_t **>
- (const_cast<char *>(rhs.data)));
- break;
-
- default:
- // The rest are fundamental types, which can be copied using
- // std::memcpy
- std::memcpy(data, rhs.data, sizeof(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 BALANCE_PAIR:
- checked_delete(*reinterpret_cast<balance_pair_t **>(data));
- break;
- case STRING:
- reinterpret_cast<string *>(data)->~string();
- 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()
-{
- LOGGER("value.initialize");
-
- true_value = new storage_t;
- true_value->type = BOOLEAN;
- *reinterpret_cast<bool *>(true_value->data) = true;
-
- false_value = new storage_t;
- false_value->type = BOOLEAN;
- *reinterpret_cast<bool *>(false_value->data) = false;
-
-#if 0
- 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(balance_pair_t *));
- BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(string));
- BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(sequence_t *));
- BOOST_STATIC_ASSERT(sizeof(amount_t) >= sizeof(boost::any));
-#endif
-
- 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(balance_pair_t *)
- << " sizeof(balance_pair_t *)");
- DEBUG_(std::setw(3) << std::right << sizeof(string)
- << " sizeof(string)");
- DEBUG_(std::setw(3) << std::right << sizeof(sequence_t *)
- << " sizeof(sequence_t *)");
- DEBUG_(std::setw(3) << std::right << sizeof(boost::any)
- << " sizeof(boost::any)");
-}
-
-void value_t::shutdown()
-{
- true_value = intrusive_ptr<storage_t>();
- 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()) {
- case BOOLEAN:
- return as_boolean();
- case DATETIME:
- return is_valid(as_datetime());
- case DATE:
- return is_valid(as_date());
- case INTEGER:
- return as_long();
- case AMOUNT:
- return as_amount();
- case BALANCE:
- return as_balance();
- case BALANCE_PAIR:
- return as_balance_pair();
- case STRING:
- return ! as_string().empty();
- case SEQUENCE:
- return ! as_sequence().empty();
- case POINTER:
- return ! as_any_pointer().empty();
- default:
- assert(false);
- break;
- }
- assert(false);
- return 0;
-}
-
-bool value_t::to_boolean() const
-{
- if (is_boolean()) {
- return as_boolean();
- } else {
- value_t temp(*this);
- temp.in_place_cast(BOOLEAN);
- return temp.as_boolean();
- }
-}
-
-datetime_t value_t::to_datetime() const
-{
- if (is_datetime()) {
- return as_datetime();
- } else {
- value_t temp(*this);
- temp.in_place_cast(DATETIME);
- return temp.as_datetime();
- }
-}
-
-date_t value_t::to_date() const
-{
- if (is_date()) {
- return as_date();
- } else {
- value_t temp(*this);
- temp.in_place_cast(DATE);
- return temp.as_date();
- }
-}
-
-long value_t::to_long() const
-{
- if (is_long()) {
- return as_long();
- } else {
- value_t temp(*this);
- temp.in_place_cast(INTEGER);
- return temp.as_long();
- }
-}
-
-amount_t value_t::to_amount() const
-{
- if (is_amount()) {
- return as_amount();
- } else {
- value_t temp(*this);
- temp.in_place_cast(AMOUNT);
- return temp.as_amount();
- }
-}
-
-balance_t value_t::to_balance() const
-{
- if (is_balance()) {
- return as_balance();
- } else {
- value_t temp(*this);
- temp.in_place_cast(BALANCE);
- return temp.as_balance();
- }
-}
-
-balance_pair_t value_t::to_balance_pair() const
-{
- if (is_balance_pair()) {
- return as_balance_pair();
- } else {
- value_t temp(*this);
- temp.in_place_cast(BALANCE_PAIR);
- return temp.as_balance_pair();
- }
-}
-
-string value_t::to_string() const
-{
- if (is_string()) {
- return as_string();
- } else {
- value_t temp(*this);
- temp.in_place_cast(STRING);
- return temp.as_string();
- }
-}
-
-value_t::sequence_t value_t::to_sequence() const
-{
- if (is_sequence()) {
- return as_sequence();
- } else {
- value_t temp(*this);
- temp.in_place_cast(SEQUENCE);
- return temp.as_sequence();
- }
-}
-
-
-void value_t::in_place_simplify()
-{
- LOGGER("amounts.values.simplify");
-
- if (is_realzero()) {
- DEBUG_("Zeroing type " << static_cast<int>(type()));
- set_long(0L);
- return;
- }
-
- if (is_balance_pair() &&
- (! as_balance_pair().cost || as_balance_pair().cost->is_realzero())) {
- DEBUG_("Reducing balance pair to balance");
- in_place_cast(BALANCE);
- }
-
- if (is_balance() && as_balance().amounts.size() == 1) {
- DEBUG_("Reducing balance to amount");
- DEBUG("ledger.value.reduce", "as a balance it looks like: " << *this);
- in_place_cast(AMOUNT);
- DEBUG("ledger.value.reduce", "as an amount it looks like: " << *this);
- }
-
-#if 0
- if (is_amount() && ! as_amount().has_commodity() &&
- as_amount().fits_in_long()) {
- DEBUG_("Reducing amount to integer");
- in_place_cast(INTEGER);
- }
-#endif
-}
-
-value_t& value_t::operator+=(const value_t& val)
-{
- if (is_string()) {
- if (val.is_string())
- as_string_lval() += val.as_string();
- else
- as_string_lval() += val.to_string();
- return *this;
- }
- else if (is_sequence()) {
- if (val.is_sequence()) {
- sequence_t& seq(as_sequence_lval());
- seq.insert(seq.end(), val.as_sequence().begin(),
- val.as_sequence().end());
- } else {
- as_sequence_lval().push_back(val);
- }
- return *this;
- }
-
- switch (type()) {
- case DATETIME:
- switch (val.type()) {
- case INTEGER:
- as_datetime_lval() += date_duration(val.as_long());
- return *this;
- case AMOUNT:
- as_datetime_lval() += date_duration(val.as_amount().to_long());
- return *this;
- default:
- break;
- }
- break;
-
- case DATE:
- switch (val.type()) {
- case INTEGER:
- as_date_lval() += date_duration_t(val.as_long());
- return *this;
- case AMOUNT:
- as_date_lval() += date_duration_t(val.as_amount().to_long());
- return *this;
- default:
- break;
- }
- break;
-
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- as_long_lval() += val.as_long();
- return *this;
- case AMOUNT:
- in_place_cast(AMOUNT);
- as_amount_lval() += val.as_amount();
- return *this;
- case BALANCE:
- in_place_cast(BALANCE);
- as_balance_lval() += val.as_balance();
- return *this;
- case BALANCE_PAIR:
- in_place_cast(BALANCE_PAIR);
- as_balance_pair_lval() += val.as_balance_pair();
- return *this;
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- if (as_amount().has_commodity()) {
- in_place_cast(BALANCE);
- return *this += val;
- } else {
- as_amount_lval() += val.as_long();
- return *this;
- }
- break;
-
- case AMOUNT:
- if (as_amount().commodity() != val.as_amount().commodity()) {
- in_place_cast(BALANCE);
- return *this += val;
- } else {
- as_amount_lval() += val.as_amount();
- return *this;
- }
- break;
-
- case BALANCE:
- in_place_cast(BALANCE);
- as_balance_lval() += val.as_balance();
- return *this;
-
- case BALANCE_PAIR:
- in_place_cast(BALANCE_PAIR);
- as_balance_pair_lval() += val.as_balance_pair();
- return *this;
- default:
- break;
- }
- break;
-
- case BALANCE:
- switch (val.type()) {
- case INTEGER:
- as_balance_lval() += val.to_amount();
- return *this;
- case AMOUNT:
- as_balance_lval() += val.as_amount();
- return *this;
- case BALANCE:
- as_balance_lval() += val.as_balance();
- return *this;
- case BALANCE_PAIR:
- in_place_cast(BALANCE_PAIR);
- as_balance_pair_lval() += val.as_balance_pair();
- return *this;
- default:
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (val.type()) {
- case INTEGER:
- as_balance_pair_lval() += val.to_amount();
- return *this;
- case AMOUNT:
- as_balance_pair_lval() += val.as_amount();
- return *this;
- case BALANCE:
- as_balance_pair_lval() += val.as_balance();
- return *this;
- case BALANCE_PAIR:
- as_balance_pair_lval() += val.as_balance_pair();
- return *this;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot add " << val.label() << " to " << label());
- return *this;
-}
-
-value_t& value_t::operator-=(const value_t& val)
-{
- if (is_sequence()) {
- sequence_t& seq(as_sequence_lval());
-
- if (val.is_sequence()) {
- foreach (const value_t& v, val.as_sequence()) {
- sequence_t::iterator j = std::find(seq.begin(), seq.end(), v);
- if (j != seq.end())
- seq.erase(j);
- }
- } else {
- sequence_t::iterator i = std::find(seq.begin(), seq.end(), val);
- if (i != seq.end())
- seq.erase(i);
- }
- return *this;
- }
-
- switch (type()) {
- case DATETIME:
- switch (val.type()) {
- case INTEGER:
- as_datetime_lval() -= date_duration(val.as_long());
- return *this;
- case AMOUNT:
- as_datetime_lval() -= date_duration(val.as_amount().to_long());
- return *this;
- default:
- break;
- }
- break;
-
- case DATE:
- switch (val.type()) {
- case INTEGER:
- as_date_lval() -= date_duration_t(val.as_long());
- return *this;
- case AMOUNT:
- as_date_lval() -= date_duration_t(val.as_amount().to_long());
- return *this;
- default:
- break;
- }
- break;
-
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- as_long_lval() -= val.as_long();
- return *this;
- case AMOUNT:
- in_place_cast(AMOUNT);
- as_amount_lval() -= val.as_amount();
- in_place_simplify();
- return *this;
- case BALANCE:
- in_place_cast(BALANCE);
- as_balance_lval() -= val.as_balance();
- in_place_simplify();
- return *this;
- case BALANCE_PAIR:
- in_place_cast(BALANCE_PAIR);
- as_balance_pair_lval() -= val.as_balance_pair();
- in_place_simplify();
- return *this;
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- if (as_amount().has_commodity()) {
- in_place_cast(BALANCE);
- *this -= val;
- in_place_simplify();
- return *this;
- } else {
- as_amount_lval() -= val.as_long();
- in_place_simplify();
- return *this;
- }
- break;
-
- case AMOUNT:
- if (as_amount().commodity() != val.as_amount().commodity()) {
- in_place_cast(BALANCE);
- *this -= val;
- in_place_simplify();
- return *this;
- } else {
- as_amount_lval() -= val.as_amount();
- in_place_simplify();
- return *this;
- }
- break;
-
- case BALANCE:
- in_place_cast(BALANCE);
- as_balance_lval() -= val.as_balance();
- in_place_simplify();
- return *this;
-
- case BALANCE_PAIR:
- in_place_cast(BALANCE_PAIR);
- as_balance_pair_lval() -= val.as_balance_pair();
- in_place_simplify();
- return *this;
- default:
- break;
- }
- break;
-
- case BALANCE:
- switch (val.type()) {
- case INTEGER:
- as_balance_lval() -= val.to_amount();
- in_place_simplify();
- return *this;
- case AMOUNT:
- as_balance_lval() -= val.as_amount();
- in_place_simplify();
- return *this;
- case BALANCE:
- as_balance_lval() -= val.as_balance();
- in_place_simplify();
- return *this;
- case BALANCE_PAIR:
- in_place_cast(BALANCE_PAIR);
- as_balance_pair_lval() -= val.as_balance_pair();
- in_place_simplify();
- return *this;
- default:
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (val.type()) {
- case INTEGER:
- as_balance_pair_lval() -= val.to_amount();
- in_place_simplify();
- return *this;
- case AMOUNT:
- as_balance_pair_lval() -= val.as_amount();
- in_place_simplify();
- return *this;
- case BALANCE:
- as_balance_pair_lval() -= val.as_balance();
- in_place_simplify();
- return *this;
- case BALANCE_PAIR:
- as_balance_pair_lval() -= val.as_balance_pair();
- in_place_simplify();
- return *this;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot subtract " << val.label() << " from " << label());
-
- return *this;
-}
-
-value_t& value_t::operator*=(const value_t& val)
-{
- if (is_string()) {
- string temp;
- long count = val.to_long();
- for (long i = 0; i < count; i++)
- temp += as_string();
- set_string(temp);
- return *this;
- }
- else if (is_sequence()) {
- value_t temp;
- long count = val.to_long();
- for (long i = 0; i < count; i++)
- temp += as_sequence();
- return *this = temp;
- }
-
- switch (type()) {
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- as_long_lval() *= val.as_long();
- return *this;
- case AMOUNT:
- set_amount(val.as_amount() * as_long());
- return *this;
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- as_amount_lval() *= val.as_long();
- return *this;
- case AMOUNT:
- if (as_amount().commodity() == val.as_amount().commodity() ||
- ! val.as_amount().has_commodity()) {
- as_amount_lval() *= val.as_amount();
- return *this;
- }
- break;
- default:
- break;
- }
- break;
-
- case BALANCE:
- switch (val.type()) {
- case INTEGER:
- as_balance_lval() *= val.as_long();
- return *this;
- case AMOUNT:
- if (! val.as_amount().has_commodity()) {
- as_balance_lval() *= val.as_amount();
- return *this;
- }
- break;
- default:
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (val.type()) {
- case INTEGER:
- as_balance_pair_lval() *= val.as_long();
- return *this;
- case AMOUNT:
- if (! val.as_amount().has_commodity()) {
- as_balance_pair_lval() *= val.as_amount();
- return *this;
- }
- break;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot multiply " << label() << " with " << val.label());
-
- return *this;
-}
-
-value_t& value_t::operator/=(const value_t& val)
-{
- switch (type()) {
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- as_long_lval() /= val.as_long();
- return *this;
- case AMOUNT:
- set_amount(val.as_amount() / as_long());
- return *this;
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- as_amount_lval() /= val.as_long();
- return *this;
-
- case AMOUNT:
- if (as_amount().commodity() == val.as_amount().commodity() ||
- ! val.as_amount().has_commodity()) {
- as_amount_lval() /= val.as_amount();
- return *this;
- }
- break;
- default:
- break;
- }
- break;
-
- case BALANCE:
- switch (val.type()) {
- case INTEGER:
- as_balance_lval() /= val.as_long();
- return *this;
- case AMOUNT:
- if (! val.as_amount().has_commodity()) {
- as_balance_lval() /= val.as_amount();
- return *this;
- }
- break;
- default:
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (val.type()) {
- case INTEGER:
- as_balance_pair_lval() /= val.as_long();
- return *this;
- case AMOUNT:
- if (! val.as_amount().has_commodity()) {
- as_balance_pair_lval() /= val.as_amount();
- return *this;
- }
- break;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot divide " << label() << " by " << val.label());
-
- return *this;
-}
-
-
-bool value_t::operator==(const value_t& val) const
-{
- switch (type()) {
- case VOID:
- return val.type() == VOID;
-
- case BOOLEAN:
- if (val.is_boolean())
- return as_boolean() == val.as_boolean();
- break;
-
- case DATETIME:
- if (val.is_datetime())
- return as_datetime() == val.as_datetime();
- break;
-
- case DATE:
- if (val.is_date())
- return as_date() == val.as_date();
- break;
-
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- return as_long() == val.as_long();
- case AMOUNT:
- return val.as_amount() == to_amount();
- case BALANCE:
- return val.as_balance() == to_amount();
- case BALANCE_PAIR:
- return val.as_balance_pair() == to_amount();
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- return as_amount() == val.as_long();
- case AMOUNT:
- return as_amount() == val.as_amount();
- case BALANCE:
- return val.as_balance() == as_amount();
- case BALANCE_PAIR:
- return val.as_balance_pair() == as_amount();
- default:
- break;
- }
- break;
-
- case BALANCE:
- switch (val.type()) {
- case INTEGER:
- return as_balance() == val.to_amount();
- case AMOUNT:
- return as_balance() == val.as_amount();
- case BALANCE:
- return as_balance() == val.as_balance();
- case BALANCE_PAIR:
- return val.as_balance_pair() == as_balance();
- default:
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (val.type()) {
- case INTEGER:
- return as_balance_pair() == val.to_amount();
- case AMOUNT:
- return as_balance_pair() == val.as_amount();
- case BALANCE:
- return as_balance_pair() == val.as_balance();
- case BALANCE_PAIR:
- return as_balance_pair() == val.as_balance_pair();
- default:
- break;
- }
- break;
-
- case STRING:
- if (val.is_string())
- return as_string() == val.as_string();
- break;
-
- case SEQUENCE:
- if (val.is_sequence())
- return as_sequence() == val.as_sequence();
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot compare " << label() << " to " << val.label());
-
- return *this;
-}
-
-bool value_t::operator<(const value_t& val) const
-{
- switch (type()) {
- case DATETIME:
- if (val.is_datetime())
- return as_datetime() < val.as_datetime();
- break;
-
- case DATE:
- if (val.is_date())
- return as_date() < val.as_date();
- break;
-
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- return as_long() < val.as_long();
- case AMOUNT:
- return val.as_amount() < as_long();
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- return as_amount() < val.as_long();
- case AMOUNT:
- return as_amount() < val.as_amount();
- default:
- break;
- }
- break;
-
- case STRING:
- if (val.is_string())
- return as_string() < val.as_string();
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot compare " << label() << " to " << val.label());
-
- return *this;
-}
-
-#if 0
-bool value_t::operator>(const value_t& val) const
-{
- switch (type()) {
- case DATETIME:
- if (val.is_datetime())
- return as_datetime() > val.as_datetime();
- break;
-
- case DATE:
- if (val.is_date())
- return as_date() > val.as_date();
- break;
-
- case INTEGER:
- switch (val.type()) {
- case INTEGER:
- return as_long() > val.as_long();
- case AMOUNT:
- return val.as_amount() > as_long();
- default:
- break;
- }
- break;
-
- case AMOUNT:
- switch (val.type()) {
- case INTEGER:
- return as_amount() > val.as_long();
- case AMOUNT:
- return as_amount() > val.as_amount();
- default:
- break;
- }
- break;
-
- case STRING:
- if (val.is_string())
- return as_string() > val.as_string();
- break;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot compare " << label() << " to " << val.label());
-
- return *this;
-}
-#endif
-
-void value_t::in_place_cast(type_t cast_type)
-{
- if (type() == cast_type)
- return;
-
- if (cast_type == BOOLEAN) {
- set_boolean(bool(*this));
- return;
- }
- else if (cast_type == SEQUENCE) {
- sequence_t temp;
- if (! is_null())
- temp.push_back(*this);
- set_sequence(temp);
- return;
- }
-
- switch (type()) {
- case BOOLEAN:
- switch (cast_type) {
- case STRING:
- set_string(as_boolean() ? "true" : "false");
- return;
- default:
- break;
- }
- break;
-
- case INTEGER:
- switch (cast_type) {
- case AMOUNT:
- set_amount(as_long());
- return;
- case BALANCE:
- set_balance(to_amount());
- return;
- case BALANCE_PAIR:
- set_balance_pair(to_amount());
- return;
- case STRING:
- set_string(lexical_cast<string>(as_long()));
- return;
- default:
- break;
- }
- break;
-
- case AMOUNT: {
- const amount_t& amt(as_amount());
- switch (cast_type) {
- case INTEGER:
- if (amt.is_null())
- set_long(0L);
- else
- set_long(as_amount().to_long());
- return;
- case BALANCE:
- if (amt.is_null())
- set_balance(balance_t());
- else
- set_balance(as_amount()); // creates temporary
- return;
- case BALANCE_PAIR:
- if (amt.is_null())
- set_balance_pair(balance_pair_t());
- else
- set_balance_pair(as_amount()); // creates temporary
- return;
- case STRING:
- if (amt.is_null())
- set_string("");
- else
- set_string(as_amount().to_string());
- return;
- default:
- break;
- }
- break;
- }
-
- case BALANCE:
- switch (cast_type) {
- case AMOUNT: {
- const balance_t& temp(as_balance());
- if (temp.amounts.size() == 1) {
- // Because we are changing the current balance value to an amount
- // value, and because set_amount takes a reference (and that memory is
- // about to be repurposed), we must pass in a copy.
- set_amount(amount_t((*temp.amounts.begin()).second));
- return;
- }
- else if (temp.amounts.size() == 0) {
- set_amount(0L);
- return;
- }
- else {
- throw_(value_error, "Cannot convert " << label() <<
- " with multiple commodities to " << label(cast_type));
- }
- break;
- }
- case BALANCE_PAIR:
- set_balance_pair(as_balance());
- return;
- default:
- break;
- }
- break;
-
- case BALANCE_PAIR:
- switch (cast_type) {
- case AMOUNT: {
- const balance_t& temp(as_balance_pair().quantity());
- if (temp.amounts.size() == 1) {
- set_amount(amount_t((*temp.amounts.begin()).second));
- return;
- }
- else if (temp.amounts.size() == 0) {
- set_amount(0L);
- return;
- }
- else {
- throw_(value_error, "Cannot convert " << label() <<
- " with multiple commodities to " << label(cast_type));
- }
- break;
- }
- case BALANCE:
- // A temporary is required, becaues set_balance is going to wipe us out
- // before assigned the value passed in.
- set_balance(balance_t(as_balance_pair().quantity()));
- return;
- default:
- break;
- }
- break;
-
- case STRING:
- switch (cast_type) {
- case INTEGER: {
- if (all(as_string(), is_digit())) {
- set_long(lexical_cast<long>(as_string()));
- return;
- } else {
- throw_(value_error,
- "Cannot convert string '" << *this << "' to an integer");
- }
- break;
- }
- case AMOUNT:
- set_amount(amount_t(as_string()));
- return;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- throw_(value_error,
- "Cannot convert " << label() << " to " << label(cast_type));
-}
-
-void value_t::in_place_negate()
-{
- switch (type()) {
- case BOOLEAN:
- set_boolean(! as_boolean());
- return;
- case INTEGER:
- case DATETIME:
- set_long(- as_long());
- return;
- case DATE:
- set_long(- as_long());
- return;
- case AMOUNT:
- as_amount_lval().in_place_negate();
- return;
- case BALANCE:
- as_balance_lval().in_place_negate();
- return;
- case BALANCE_PAIR:
- as_balance_pair_lval().in_place_negate();
- return;
- default:
- break;
- }
-
- throw_(value_error, "Cannot negate " << label());
-}
-
-bool value_t::is_realzero() const
-{
- switch (type()) {
- case BOOLEAN:
- return ! as_boolean();
- case INTEGER:
- return as_long() == 0;
- case DATETIME:
- return ! is_valid(as_datetime());
- case DATE:
- return ! is_valid(as_date());
- case AMOUNT:
- return as_amount().is_realzero();
- case BALANCE:
- return as_balance().is_realzero();
- case BALANCE_PAIR:
- return as_balance_pair().is_realzero();
- case STRING:
- return as_string().empty();
- case SEQUENCE:
- return as_sequence().empty();
-
- case POINTER:
- return as_any_pointer().empty();
-
- default:
- assert(false);
- break;
- }
- assert(false);
- return true;
-}
-
-bool value_t::is_zero() const
-{
- switch (type()) {
- case BOOLEAN:
- return ! as_boolean();
- case INTEGER:
- return as_long() == 0;
- case DATETIME:
- return ! is_valid(as_datetime());
- case DATE:
- return ! is_valid(as_date());
- case AMOUNT:
- return as_amount().is_zero();
- case BALANCE:
- return as_balance().is_zero();
- case BALANCE_PAIR:
- return as_balance_pair().is_zero();
- case STRING:
- return as_string().empty();
- case SEQUENCE:
- return as_sequence().empty();
-
- case POINTER:
- return as_any_pointer().empty();
-
- default:
- assert(false);
- break;
- }
- assert(false);
- return true;
-}
-
-value_t value_t::value(const optional<datetime_t>& moment) const
-{
- switch (type()) {
- case INTEGER:
- return *this;
-
- case AMOUNT: {
- if (optional<amount_t> val = as_amount().value(moment))
- return *val;
- return false;
- }
- case BALANCE: {
- if (optional<balance_t> bal = as_balance().value(moment))
- return *bal;
- return false;
- }
- case BALANCE_PAIR: {
- if (optional<balance_t> bal_pair =
- as_balance_pair().quantity().value(moment))
- return *bal_pair;
- return false;
- }
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot find the value of " << label());
- return NULL_VALUE;
-}
-
-void value_t::in_place_reduce()
-{
- switch (type()) {
- case INTEGER:
- return;
- case AMOUNT:
- as_amount_lval().in_place_reduce();
- return;
- case BALANCE:
- as_balance_lval().in_place_reduce();
- return;
- case BALANCE_PAIR:
- as_balance_pair_lval().in_place_reduce();
- return;
- default:
- break;
- }
-
- throw_(value_error, "Cannot reduce " << label());
-}
-
-value_t value_t::abs() const
-{
- switch (type()) {
- case INTEGER: {
- long val = as_long();
- if (val < 0)
- return - val;
- return val;
- }
- case AMOUNT:
- return as_amount().abs();
- case BALANCE:
- return as_balance().abs();
- case BALANCE_PAIR:
- return as_balance_pair().abs();
- default:
- break;
- }
-
- throw_(value_error, "Cannot abs " << label());
- return NULL_VALUE;
-}
-
-value_t value_t::round() const
-{
- switch (type()) {
- case INTEGER:
- return *this;
- case AMOUNT:
- return as_amount().round();
- case BALANCE:
- return as_balance().round();
- case BALANCE_PAIR:
- return as_balance_pair().round();
- default:
- break;
- }
-
- throw_(value_error, "Cannot round " << label());
- return NULL_VALUE;
-}
-
-value_t value_t::unround() const
-{
- switch (type()) {
- case INTEGER:
- return *this;
- case AMOUNT:
- return as_amount().unround();
- default:
- break;
- }
-
- throw_(value_error, "Cannot unround " << label());
- return NULL_VALUE;
-}
-
-#if 0
-value_t value_t::annotated_price() const
-{
- 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;
-}
-
-value_t value_t::annotated_date() 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;
-}
-
-value_t value_t::annotated_tag() const
-{
- switch (type()) {
- case AMOUNT: {
- optional<string> temp = as_amount().annotation_details().tag;
- if (! temp)
- return false;
- return string_value(*temp);
- }
-
- 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 bool keep_price,
- const bool keep_date,
- const bool keep_tag) const
-{
- switch (type()) {
- case VOID:
- case BOOLEAN:
- case INTEGER:
- case DATETIME:
- case DATE:
- case STRING:
- case POINTER:
- return *this;
-
- case SEQUENCE: {
- sequence_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(value.strip_annotations(keep_price, keep_date, keep_tag));
- return temp;
- }
-
- case AMOUNT:
- return as_amount().strip_annotations(keep_price, keep_date, keep_tag);
- case BALANCE:
- return as_balance().strip_annotations(keep_price, keep_date, keep_tag);
- case BALANCE_PAIR:
- return as_balance_pair().quantity().strip_annotations(keep_price, keep_date,
- keep_tag);
-
- default:
- assert(false);
- break;
- }
- assert(false);
- return NULL_VALUE;
-}
-
-value_t value_t::cost() const
-{
- switch (type()) {
- case INTEGER:
- case AMOUNT:
- case BALANCE:
- return *this;
-
- case BALANCE_PAIR:
- assert(as_balance_pair().cost);
- if (as_balance_pair().cost)
- return *(as_balance_pair().cost);
- else
- return as_balance_pair().quantity();
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot find the cost of " << label());
- return NULL_VALUE;
-}
-
-value_t& value_t::add(const amount_t& amount, const optional<amount_t>& tcost)
-{
- switch (type()) {
- case INTEGER:
- case AMOUNT:
- if (tcost) {
- in_place_cast(BALANCE_PAIR);
- return add(amount, tcost);
- }
- else if ((is_amount() &&
- as_amount().commodity() != amount.commodity()) ||
- (! is_amount() && amount.commodity())) {
- in_place_cast(BALANCE);
- return add(amount, tcost);
- }
- else if (! is_amount()) {
- in_place_cast(AMOUNT);
- }
- return *this += amount;
-
- case BALANCE:
- if (tcost) {
- in_place_cast(BALANCE_PAIR);
- return add(amount, tcost);
- }
- return *this += amount;
-
- case BALANCE_PAIR:
- as_balance_pair_lval().add(amount, tcost);
- return *this;
-
- default:
- break;
- }
-
- throw_(value_error, "Cannot add an amount to " << label());
- return *this;
-}
-
-void value_t::dump(std::ostream& out, const int first_width,
- const int latter_width) const
-{
- switch (type()) {
- case VOID:
- out << "VOID";
- break;
-
- case BOOLEAN:
- out << as_boolean();
- break;
-
- case DATETIME:
- out << format_datetime(as_datetime());
- break;
-
- case DATE:
- out << format_date(as_date());
- break;
-
- case INTEGER:
- out << as_long();
- break;
-
- case AMOUNT:
- out << as_amount();
- break;
-
- case STRING:
- out << as_string();
- break;
-
- case POINTER:
- out << boost::unsafe_any_cast<const void *>(&as_any_pointer());
- break;
-
- case SEQUENCE: {
- out << '(';
- bool first = true;
- foreach (const value_t& value, as_sequence()) {
- if (first)
- first = false;
- else
- out << ", ";
-
- value.dump(out, first_width, latter_width);
- }
- out << ')';
- break;
- }
-
- case BALANCE:
- as_balance().print(out, first_width, latter_width);
- break;
- case BALANCE_PAIR:
- as_balance_pair().print(out, first_width, latter_width);
- break;
- default:
- assert(false);
- break;
- }
-}
-
-void value_t::print(std::ostream& out, const bool relaxed) const
-{
- switch (type()) {
- case VOID:
- out << "";
- break;
-
- case BOOLEAN:
- if (as_boolean())
- out << "true";
- else
- out << "false";
- break;
-
- case INTEGER:
- out << as_long();
- break;
-
- case AMOUNT:
- if (! relaxed)
- out << '{';
- out << as_amount();
- if (! relaxed)
- out << '}';
- break;
-
- case BALANCE:
- case BALANCE_PAIR:
- assert(false);
- break;
-
- case DATETIME:
- assert(false);
- break;
- case DATE:
- out << '[' << format_date(as_date()) << ']';
- break;
-
- case STRING:
- out << '"' << as_string() << '"';
- break;
-
- case POINTER:
- assert(false);
- break;
-
- case SEQUENCE: {
- out << '(';
- bool first = true;
- foreach (const value_t& value, as_sequence()) {
- if (first)
- first = false;
- else
- out << ", ";
-
- value.print(out, relaxed);
- }
- out << ')';
- break;
- }
- }
-}
-
-void value_t::read(const char *& data)
-{
- switch (static_cast<value_t::type_t>(binary::read_long<int>(data))) {
- case BOOLEAN:
- set_boolean(binary::read_bool(data));
- break;
- case INTEGER:
- set_long(binary::read_long<unsigned long>(data));
- break;
- case DATETIME:
-#if 0
- // jww (2008-04-22): I need to record and read a datetime_t directly
- set_datetime(read_long<unsigned long>(data));
-#endif
- break;
- case DATE:
-#if 0
- // jww (2008-04-22): I need to record and read a date_t directly
- set_date(read_long<unsigned long>(data));
-#endif
- break;
- case AMOUNT: {
- amount_t temp;
- temp.read(data);
- set_amount(temp);
- break;
- }
- default:
- break;
- }
-
- throw_(value_error, "Cannot read " << label() << " from a stream");
-}
-
-void value_t::write(std::ostream& out) const
-{
- binary::write_long(out, static_cast<int>(type()));
-
- switch (type()) {
- case BOOLEAN:
- binary::write_bool(out, as_boolean());
- break;
- case INTEGER:
- binary::write_long(out, as_long());
- break;
- case DATETIME:
-#if 0
- binary::write_number(out, as_datetime());
-#endif
- break;
- case DATE:
-#if 0
- binary::write_number(out, as_date());
-#endif
- break;
- case AMOUNT:
- as_amount().write(out);
- break;
- default:
- break;
- }
-
- throw_(value_error, "Cannot read " << label() << " to a stream");
-}
-
-bool value_t::valid() const
-{
- switch (type()) {
- case AMOUNT:
- return as_amount().valid();
- case BALANCE:
- return as_balance().valid();
- case BALANCE_PAIR:
- return as_balance_pair().valid();
- default:
- break;
- }
- return true;
-}
-
-} // namespace ledger