More work to use boost/operators.hpp.
This commit is contained in:
parent
230e03166f
commit
76b2066b8b
16 changed files with 319 additions and 523 deletions
|
|
@ -410,58 +410,6 @@ amount_t& amount_t::operator=(const amount_t& amt)
|
|||
return *this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
amount_t& amount_t::operator=(const long val)
|
||||
{
|
||||
if (val == 0) {
|
||||
if (quantity)
|
||||
_clear();
|
||||
} else {
|
||||
commodity_ = NULL;
|
||||
_init();
|
||||
mpz_set_si(MPZ(quantity), val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
amount_t& amount_t::operator=(const unsigned long val)
|
||||
{
|
||||
if (val == 0) {
|
||||
if (quantity)
|
||||
_clear();
|
||||
} else {
|
||||
commodity_ = NULL;
|
||||
_init();
|
||||
mpz_set_ui(MPZ(quantity), val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
amount_t& amount_t::operator=(const double val)
|
||||
{
|
||||
commodity_ = NULL;
|
||||
_init();
|
||||
quantity->prec = convert_double(MPZ(quantity), val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
amount_t& amount_t::operator=(const string& val)
|
||||
{
|
||||
std::istringstream str(val);
|
||||
parse(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
amount_t& amount_t::operator=(const char * val)
|
||||
{
|
||||
string valstr(val);
|
||||
std::istringstream str(valstr);
|
||||
parse(str);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
amount_t& amount_t::operator+=(const amount_t& amt)
|
||||
{
|
||||
if (commodity() != amt.commodity())
|
||||
|
|
@ -702,45 +650,6 @@ bool amount_t::zero() const
|
|||
return realzero();
|
||||
}
|
||||
|
||||
#if 0
|
||||
amount_t::operator long() const
|
||||
{
|
||||
if (! quantity)
|
||||
return 0;
|
||||
|
||||
mpz_set(temp, MPZ(quantity));
|
||||
mpz_ui_pow_ui(divisor, 10, quantity->prec);
|
||||
mpz_tdiv_q(temp, temp, divisor);
|
||||
return mpz_get_si(temp);
|
||||
}
|
||||
|
||||
amount_t::operator double() const
|
||||
{
|
||||
if (! quantity)
|
||||
return 0.0;
|
||||
|
||||
mpz_t remainder;
|
||||
mpz_init(remainder);
|
||||
|
||||
mpz_set(temp, MPZ(quantity));
|
||||
mpz_ui_pow_ui(divisor, 10, quantity->prec);
|
||||
mpz_tdiv_qr(temp, remainder, temp, divisor);
|
||||
|
||||
char * quotient_s = mpz_get_str(NULL, 10, temp);
|
||||
char * remainder_s = mpz_get_str(NULL, 10, remainder);
|
||||
|
||||
std::ostringstream num;
|
||||
num << quotient_s << '.' << remainder_s;
|
||||
|
||||
std::free(quotient_s);
|
||||
std::free(remainder_s);
|
||||
|
||||
mpz_clear(remainder);
|
||||
|
||||
return std::atof(num.str().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
amount_t amount_t::value(const moment_t& moment) const
|
||||
{
|
||||
if (quantity) {
|
||||
|
|
|
|||
62
src/amount.h
62
src/amount.h
|
|
@ -69,9 +69,13 @@ DECLARE_EXCEPTION(amount_error);
|
|||
* uncommoditized numbers, no display truncation is ever done.
|
||||
* Internally, precision is always kept to an excessive degree.
|
||||
*/
|
||||
class amount_t : public ordered_field_operators<amount_t>
|
||||
class amount_t
|
||||
: public ordered_field_operators<amount_t,
|
||||
ordered_field_operators<amount_t, long,
|
||||
ordered_field_operators<amount_t, unsigned long,
|
||||
ordered_field_operators<amount_t, double > > > >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
class bigint_t;
|
||||
|
||||
static void initialize();
|
||||
|
|
@ -83,7 +87,7 @@ class amount_t : public ordered_field_operators<amount_t>
|
|||
static bool keep_base;
|
||||
static bool full_strings;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void _init();
|
||||
void _copy(const amount_t& amt);
|
||||
void _release();
|
||||
|
|
@ -94,7 +98,7 @@ class amount_t : public ordered_field_operators<amount_t>
|
|||
bigint_t * quantity;
|
||||
commodity_t * commodity_;
|
||||
|
||||
public:
|
||||
public:
|
||||
// constructors
|
||||
amount_t() : quantity(NULL), commodity_(NULL) {
|
||||
TRACE_CTOR(amount_t, "");
|
||||
|
|
@ -125,15 +129,10 @@ class amount_t : public ordered_field_operators<amount_t>
|
|||
_release();
|
||||
}
|
||||
|
||||
static amount_t exact(const string& value);
|
||||
|
||||
// assignment operator
|
||||
amount_t& operator=(const amount_t& amt);
|
||||
#if 0
|
||||
amount_t& operator=(const double val);
|
||||
amount_t& operator=(const unsigned long val);
|
||||
amount_t& operator=(const long val);
|
||||
amount_t& operator=(const string& val);
|
||||
amount_t& operator=(const char * val);
|
||||
#endif
|
||||
|
||||
// comparisons between amounts
|
||||
int compare(const amount_t& amt) const;
|
||||
|
|
@ -149,28 +148,33 @@ class amount_t : public ordered_field_operators<amount_t>
|
|||
amount_t& operator/=(const amount_t& amt);
|
||||
|
||||
// unary negation
|
||||
void in_place_negate();
|
||||
amount_t operator-() const {
|
||||
return negate();
|
||||
}
|
||||
amount_t negate() const {
|
||||
amount_t temp = *this;
|
||||
temp.in_place_negate();
|
||||
return temp;
|
||||
}
|
||||
amount_t operator-() const {
|
||||
return negate();
|
||||
void in_place_negate();
|
||||
|
||||
// test for truth, zero and non-zero
|
||||
operator bool() const {
|
||||
return ! zero();
|
||||
}
|
||||
|
||||
// test for zero and non-zero
|
||||
int sign() const;
|
||||
bool zero() const;
|
||||
bool realzero() const {
|
||||
return sign() == 0;
|
||||
}
|
||||
operator bool() const {
|
||||
return ! zero();
|
||||
}
|
||||
|
||||
// Methods relating to this amount's commodity
|
||||
// conversion methods
|
||||
string to_string() const;
|
||||
string to_fullstring() const;
|
||||
string quantity_string() const;
|
||||
|
||||
// methods relating to the commodity
|
||||
bool is_null() const {
|
||||
return ! quantity && ! has_commodity();
|
||||
}
|
||||
|
|
@ -205,40 +209,26 @@ class amount_t : public ordered_field_operators<amount_t>
|
|||
optional<moment_t> date() const;
|
||||
optional<string> tag() const;
|
||||
|
||||
#if 0
|
||||
// string and numeric conversions
|
||||
operator string() const {
|
||||
return to_string();
|
||||
}
|
||||
operator long() const;
|
||||
operator double() const;
|
||||
#endif
|
||||
|
||||
string to_string() const;
|
||||
string to_fullstring() const;
|
||||
string quantity_string() const;
|
||||
|
||||
// general methods
|
||||
amount_t round(unsigned int prec) const;
|
||||
amount_t round() const;
|
||||
amount_t unround() const;
|
||||
amount_t value(const moment_t& moment) const;
|
||||
|
||||
amount_t abs() const {
|
||||
if (sign() < 0)
|
||||
return negate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
amount_t reduce() const {
|
||||
amount_t temp(*this);
|
||||
temp.in_place_reduce();
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool valid() const;
|
||||
|
||||
void in_place_reduce();
|
||||
|
||||
static amount_t exact(const string& value);
|
||||
bool valid() const;
|
||||
|
||||
// This function is special, and exists only to support a custom
|
||||
// optimization in binary.cc (which offers a significant enough gain
|
||||
|
|
|
|||
262
src/balance.cc
262
src/balance.cc
|
|
@ -2,6 +2,137 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
balance_t& balance_t::operator*=(const balance_t& bal)
|
||||
{
|
||||
if (realzero() || bal.realzero()) {
|
||||
return *this = amount_t();
|
||||
}
|
||||
else if (bal.amounts.size() == 1) {
|
||||
return *this *= (*bal.amounts.begin()).second;
|
||||
}
|
||||
else if (amounts.size() == 1) {
|
||||
return *this = bal * *this;
|
||||
}
|
||||
else {
|
||||
// Since we would fail with an error at this point otherwise, try
|
||||
// stripping annotations to see if we can come up with a
|
||||
// reasonable result. The user will not notice any annotations
|
||||
// missing (since they are viewing a stripped report anyway), only
|
||||
// that some of their value expression may not see any pricing or
|
||||
// date data because of this operation.
|
||||
|
||||
balance_t temp(bal.strip_annotations());
|
||||
if (temp.amounts.size() == 1)
|
||||
return *this *= temp;
|
||||
temp = strip_annotations();
|
||||
if (temp.amounts.size() == 1)
|
||||
return *this = bal * temp;
|
||||
|
||||
throw_(amount_error, "Cannot multiply two balances: " << temp << " * " << bal);
|
||||
}
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator*=(const amount_t& amt)
|
||||
{
|
||||
if (realzero() || amt.realzero()) {
|
||||
return *this = amount_t();
|
||||
}
|
||||
else if (! amt.commodity()) {
|
||||
// Multiplying by the null commodity causes all amounts to be
|
||||
// increased by the same factor.
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second *= amt;
|
||||
}
|
||||
else if (amounts.size() == 1) {
|
||||
*this = (*amounts.begin()).second * amt;
|
||||
}
|
||||
else {
|
||||
amounts_map::iterator i = amounts.find(&amt.commodity());
|
||||
if (i != amounts.end()) {
|
||||
(*i).second *= amt;
|
||||
} else {
|
||||
// Try stripping annotations before giving an error.
|
||||
balance_t temp(strip_annotations());
|
||||
if (temp.amounts.size() == 1) {
|
||||
return *this = (*temp.amounts.begin()).second * amt;
|
||||
} else {
|
||||
i = temp.amounts.find(&amt.commodity());
|
||||
if (i != temp.amounts.end())
|
||||
return *this = temp * amt;
|
||||
}
|
||||
|
||||
throw_(amount_error, "Attempt to multiply balance by a commodity" <<
|
||||
" not found in that balance: " << temp << " * " << amt);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator/=(const balance_t& bal)
|
||||
{
|
||||
if (bal.realzero()) {
|
||||
throw_(amount_error, "Divide by zero: " << *this << " / " << bal);
|
||||
}
|
||||
else if (realzero()) {
|
||||
return *this = amount_t();
|
||||
}
|
||||
else if (bal.amounts.size() == 1) {
|
||||
return *this /= (*bal.amounts.begin()).second;
|
||||
}
|
||||
else if (*this == bal) {
|
||||
return *this = amount_t(1L);
|
||||
}
|
||||
else {
|
||||
// Try stripping annotations before giving an error.
|
||||
balance_t temp(bal.strip_annotations());
|
||||
if (temp.amounts.size() == 1)
|
||||
return *this /= temp;
|
||||
|
||||
throw_(amount_error,
|
||||
"Cannot divide two balances: " << temp << " / " << bal);
|
||||
}
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator/=(const amount_t& amt)
|
||||
{
|
||||
if (amt.realzero()) {
|
||||
throw_(amount_error, "Divide by zero: " << *this << " / " << amt);
|
||||
}
|
||||
else if (realzero()) {
|
||||
return *this = amount_t();
|
||||
}
|
||||
else if (! amt.commodity()) {
|
||||
// Dividing by the null commodity causes all amounts to be
|
||||
// decreased by the same factor.
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second /= amt;
|
||||
}
|
||||
else if (amounts.size() == 1 &&
|
||||
(*amounts.begin()).first == &amt.commodity()) {
|
||||
(*amounts.begin()).second /= amt;
|
||||
}
|
||||
else {
|
||||
amounts_map::iterator i = amounts.find(&amt.commodity());
|
||||
if (i != amounts.end()) {
|
||||
(*i).second /= amt;
|
||||
} else {
|
||||
// Try stripping annotations before giving an error.
|
||||
balance_t temp(strip_annotations());
|
||||
if (temp.amounts.size() == 1 &&
|
||||
(*temp.amounts.begin()).first == &amt.commodity())
|
||||
return *this = temp / amt;
|
||||
|
||||
throw_(amount_error, "Attempt to divide balance by a commodity" <<
|
||||
" not found in that balance: " << temp << " * " << amt);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
amount_t balance_t::amount(const commodity_t& commodity) const
|
||||
{
|
||||
if (! commodity) {
|
||||
|
|
@ -167,137 +298,6 @@ void balance_t::write(std::ostream& out,
|
|||
}
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator*=(const balance_t& bal)
|
||||
{
|
||||
if (realzero() || bal.realzero()) {
|
||||
return *this = 0L;
|
||||
}
|
||||
else if (bal.amounts.size() == 1) {
|
||||
return *this *= (*bal.amounts.begin()).second;
|
||||
}
|
||||
else if (amounts.size() == 1) {
|
||||
return *this = bal * *this;
|
||||
}
|
||||
else {
|
||||
// Since we would fail with an error at this point otherwise, try
|
||||
// stripping annotations to see if we can come up with a
|
||||
// reasonable result. The user will not notice any annotations
|
||||
// missing (since they are viewing a stripped report anyway), only
|
||||
// that some of their value expression may not see any pricing or
|
||||
// date data because of this operation.
|
||||
|
||||
balance_t temp(bal.strip_annotations());
|
||||
if (temp.amounts.size() == 1)
|
||||
return *this *= temp;
|
||||
temp = strip_annotations();
|
||||
if (temp.amounts.size() == 1)
|
||||
return *this = bal * temp;
|
||||
|
||||
throw_(amount_error, "Cannot multiply two balances: " << temp << " * " << bal);
|
||||
}
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator*=(const amount_t& amt)
|
||||
{
|
||||
if (realzero() || amt.realzero()) {
|
||||
return *this = 0L;
|
||||
}
|
||||
else if (! amt.commodity()) {
|
||||
// Multiplying by the null commodity causes all amounts to be
|
||||
// increased by the same factor.
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second *= amt;
|
||||
}
|
||||
else if (amounts.size() == 1) {
|
||||
*this = (*amounts.begin()).second * amt;
|
||||
}
|
||||
else {
|
||||
amounts_map::iterator i = amounts.find(&amt.commodity());
|
||||
if (i != amounts.end()) {
|
||||
(*i).second *= amt;
|
||||
} else {
|
||||
// Try stripping annotations before giving an error.
|
||||
balance_t temp(strip_annotations());
|
||||
if (temp.amounts.size() == 1) {
|
||||
return *this = (*temp.amounts.begin()).second * amt;
|
||||
} else {
|
||||
i = temp.amounts.find(&amt.commodity());
|
||||
if (i != temp.amounts.end())
|
||||
return *this = temp * amt;
|
||||
}
|
||||
|
||||
throw_(amount_error, "Attempt to multiply balance by a commodity" <<
|
||||
" not found in that balance: " << temp << " * " << amt);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator/=(const balance_t& bal)
|
||||
{
|
||||
if (bal.realzero()) {
|
||||
throw_(amount_error, "Divide by zero: " << *this << " / " << bal);
|
||||
}
|
||||
else if (realzero()) {
|
||||
return *this = 0L;
|
||||
}
|
||||
else if (bal.amounts.size() == 1) {
|
||||
return *this /= (*bal.amounts.begin()).second;
|
||||
}
|
||||
else if (*this == bal) {
|
||||
return *this = 1L;
|
||||
}
|
||||
else {
|
||||
// Try stripping annotations before giving an error.
|
||||
balance_t temp(bal.strip_annotations());
|
||||
if (temp.amounts.size() == 1)
|
||||
return *this /= temp;
|
||||
|
||||
throw_(amount_error,
|
||||
"Cannot divide two balances: " << temp << " / " << bal);
|
||||
}
|
||||
}
|
||||
|
||||
balance_t& balance_t::operator/=(const amount_t& amt)
|
||||
{
|
||||
if (amt.realzero()) {
|
||||
throw_(amount_error, "Divide by zero: " << *this << " / " << amt);
|
||||
}
|
||||
else if (realzero()) {
|
||||
return *this = 0L;
|
||||
}
|
||||
else if (! amt.commodity()) {
|
||||
// Dividing by the null commodity causes all amounts to be
|
||||
// decreased by the same factor.
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second /= amt;
|
||||
}
|
||||
else if (amounts.size() == 1 &&
|
||||
(*amounts.begin()).first == &amt.commodity()) {
|
||||
(*amounts.begin()).second /= amt;
|
||||
}
|
||||
else {
|
||||
amounts_map::iterator i = amounts.find(&amt.commodity());
|
||||
if (i != amounts.end()) {
|
||||
(*i).second /= amt;
|
||||
} else {
|
||||
// Try stripping annotations before giving an error.
|
||||
balance_t temp(strip_annotations());
|
||||
if (temp.amounts.size() == 1 &&
|
||||
(*temp.amounts.begin()).first == &amt.commodity())
|
||||
return *this = temp / amt;
|
||||
|
||||
throw_(amount_error, "Attempt to divide balance by a commodity" <<
|
||||
" not found in that balance: " << temp << " * " << amt);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
balance_t::operator amount_t() const
|
||||
{
|
||||
|
|
|
|||
193
src/balance.h
193
src/balance.h
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
// jww (2007-05-01): What really should be the operational semantics
|
||||
// of a balance?
|
||||
|
||||
class balance_t
|
||||
: public totally_ordered<balance_t,
|
||||
totally_ordered<balance_t, amount_t,
|
||||
integer_arithmetic<balance_t,
|
||||
integer_arithmetic<balance_t, amount_t
|
||||
> > > >
|
||||
: public ordered_field_operators<balance_t,
|
||||
ordered_field_operators<balance_t, amount_t> >
|
||||
{
|
||||
public:
|
||||
typedef std::map<const commodity_t *, amount_t> amounts_map;
|
||||
|
|
@ -54,10 +54,19 @@ public:
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
balance_t& operator=(const amount_t& amt) {
|
||||
amounts.clear();
|
||||
*this += amt;
|
||||
return *this;
|
||||
|
||||
int compare(const balance_t& bal) const;
|
||||
|
||||
bool operator==(const balance_t& bal) const {
|
||||
amounts_map::const_iterator i, j;
|
||||
for (i = amounts.begin(), j = bal.amounts.begin();
|
||||
i != amounts.end() && j != bal.amounts.end();
|
||||
i++, j++) {
|
||||
if (! ((*i).first == (*j).first &&
|
||||
(*i).second == (*j).second))
|
||||
return false;
|
||||
}
|
||||
return i == amounts.end() && j == bal.amounts.end();
|
||||
}
|
||||
|
||||
// in-place arithmetic
|
||||
|
|
@ -68,15 +77,6 @@ public:
|
|||
*this += (*i).second;
|
||||
return *this;
|
||||
}
|
||||
balance_t& operator+=(const amount_t& amt) {
|
||||
amounts_map::iterator i = amounts.find(&amt.commodity());
|
||||
if (i != amounts.end())
|
||||
(*i).second += amt;
|
||||
else if (! amt.realzero())
|
||||
amounts.insert(amounts_pair(&amt.commodity(), amt));
|
||||
return *this;
|
||||
}
|
||||
|
||||
balance_t& operator-=(const balance_t& bal) {
|
||||
for (amounts_map::const_iterator i = bal.amounts.begin();
|
||||
i != bal.amounts.end();
|
||||
|
|
@ -84,25 +84,10 @@ public:
|
|||
*this -= (*i).second;
|
||||
return *this;
|
||||
}
|
||||
balance_t& operator-=(const amount_t& amt) {
|
||||
amounts_map::iterator i = amounts.find(&amt.commodity());
|
||||
if (i != amounts.end()) {
|
||||
(*i).second -= amt;
|
||||
if ((*i).second.realzero())
|
||||
amounts.erase(i);
|
||||
}
|
||||
else if (! amt.realzero()) {
|
||||
amounts.insert(amounts_pair(&amt.commodity(), - amt));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// multiplication and divide
|
||||
balance_t& operator*=(const balance_t& bal);
|
||||
balance_t& operator*=(const amount_t& amt);
|
||||
|
||||
balance_t& operator*=(const amount_t& amt); // special
|
||||
balance_t& operator/=(const balance_t& bal);
|
||||
balance_t& operator/=(const amount_t& amt);
|
||||
balance_t& operator/=(const amount_t& amt); // special
|
||||
|
||||
// comparison
|
||||
bool operator<(const balance_t& bal) const {
|
||||
|
|
@ -123,42 +108,6 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
bool operator<(const amount_t& amt) const {
|
||||
if (amt.commodity())
|
||||
return amount(amt.commodity()) < amt;
|
||||
|
||||
for (amounts_map::const_iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
if ((*i).second < amt)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int compare(const balance_t& bal) const;
|
||||
|
||||
bool operator==(const balance_t& bal) const {
|
||||
amounts_map::const_iterator i, j;
|
||||
for (i = amounts.begin(), j = bal.amounts.begin();
|
||||
i != amounts.end() && j != bal.amounts.end();
|
||||
i++, j++) {
|
||||
if (! ((*i).first == (*j).first &&
|
||||
(*i).second == (*j).second))
|
||||
return false;
|
||||
}
|
||||
return i == amounts.end() && j == bal.amounts.end();
|
||||
}
|
||||
bool operator==(const amount_t& amt) const {
|
||||
if (amt.commodity())
|
||||
return amounts.size() == 1 && (*amounts.begin()).second == amt;
|
||||
|
||||
for (amounts_map::const_iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
if ((*i).second == amt)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// unary negation
|
||||
void in_place_negate() {
|
||||
|
|
@ -177,9 +126,6 @@ public:
|
|||
}
|
||||
|
||||
// conversion operators
|
||||
#if 0
|
||||
operator amount_t() const;
|
||||
#endif
|
||||
operator bool() const {
|
||||
for (amounts_map::const_iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
|
|
@ -275,13 +221,9 @@ inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
|
|||
}
|
||||
|
||||
class balance_pair_t
|
||||
: public totally_ordered<balance_pair_t,
|
||||
totally_ordered<balance_pair_t, balance_t,
|
||||
totally_ordered<balance_pair_t, amount_t,
|
||||
integer_arithmetic<balance_pair_t,
|
||||
integer_arithmetic<balance_pair_t, balance_t,
|
||||
integer_arithmetic<balance_pair_t, amount_t
|
||||
> > > > > >
|
||||
: public ordered_field_operators<balance_pair_t,
|
||||
ordered_field_operators<balance_pair_t, balance_t,
|
||||
ordered_field_operators<balance_pair_t, amount_t> > >
|
||||
{
|
||||
balance_t quantity;
|
||||
optional<balance_t> cost;
|
||||
|
|
@ -318,16 +260,6 @@ public:
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator=(const balance_t& bal) {
|
||||
quantity = bal;
|
||||
cost = optional<balance_t>();
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator=(const amount_t& amt) {
|
||||
quantity = amt;
|
||||
cost = optional<balance_t>();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// in-place arithmetic
|
||||
balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
|
||||
|
|
@ -338,19 +270,6 @@ public:
|
|||
*cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator+=(const balance_t& bal) {
|
||||
quantity += bal;
|
||||
if (cost)
|
||||
*cost += bal;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator+=(const amount_t& amt) {
|
||||
quantity += amt;
|
||||
if (cost)
|
||||
*cost += amt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = quantity;
|
||||
|
|
@ -359,20 +278,6 @@ public:
|
|||
*cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator-=(const balance_t& bal) {
|
||||
quantity -= bal;
|
||||
if (cost)
|
||||
*cost -= bal;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator-=(const amount_t& amt) {
|
||||
quantity -= amt;
|
||||
if (cost)
|
||||
*cost -= amt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// multiplication and division
|
||||
balance_pair_t& operator*=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = quantity;
|
||||
|
|
@ -381,19 +286,6 @@ public:
|
|||
*cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator*=(const balance_t& bal) {
|
||||
quantity *= bal;
|
||||
if (cost)
|
||||
*cost *= bal;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator*=(const amount_t& amt) {
|
||||
quantity *= amt;
|
||||
if (cost)
|
||||
*cost *= amt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = quantity;
|
||||
|
|
@ -402,40 +294,13 @@ public:
|
|||
*cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator/=(const balance_t& bal) {
|
||||
quantity /= bal;
|
||||
if (cost)
|
||||
*cost /= bal;
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator/=(const amount_t& amt) {
|
||||
quantity /= amt;
|
||||
if (cost)
|
||||
*cost /= amt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// comparison
|
||||
bool operator<(const balance_pair_t& bal_pair) const {
|
||||
return quantity < bal_pair.quantity;
|
||||
}
|
||||
bool operator<(const balance_t& bal) const {
|
||||
return quantity < bal;
|
||||
}
|
||||
bool operator<(const amount_t& amt) const {
|
||||
return quantity < amt;
|
||||
}
|
||||
|
||||
int compare(const balance_pair_t& bal) const;
|
||||
|
||||
bool operator==(const balance_pair_t& bal_pair) const {
|
||||
return quantity == bal_pair.quantity;
|
||||
}
|
||||
bool operator==(const balance_t& bal) const {
|
||||
return quantity == bal;
|
||||
}
|
||||
bool operator==(const amount_t& amt) const {
|
||||
return quantity == amt;
|
||||
bool operator<(const balance_pair_t& bal_pair) const {
|
||||
return quantity < bal_pair.quantity;
|
||||
}
|
||||
|
||||
// unary negation
|
||||
|
|
@ -454,14 +319,6 @@ public:
|
|||
}
|
||||
|
||||
// test for non-zero (use ! for zero)
|
||||
#if 0
|
||||
operator balance_t() const {
|
||||
return quantity;
|
||||
}
|
||||
operator amount_t() const {
|
||||
return quantity;
|
||||
}
|
||||
#endif
|
||||
operator bool() const {
|
||||
return quantity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ inline void read_binary_transaction(char *& data, transaction_t * xact)
|
|||
repitem_t::wrap(xact, static_cast<repitem_t *>(xact->entry->data));
|
||||
xact->data = item;
|
||||
|
||||
xact->amount = valexpr_t(xact->amount_expr).calc(item).to_amount();
|
||||
xact->amount = valexpr_t(xact->amount_expr).calc(item).amount();
|
||||
}
|
||||
|
||||
if (read_binary_bool(data)) {
|
||||
|
|
|
|||
|
|
@ -145,15 +145,15 @@ bool entry_base_t::finalize()
|
|||
// the balance. This is done for the last eligible commodity.
|
||||
|
||||
if (! saw_null && balance && balance.type == value_t::BALANCE &&
|
||||
((balance_t *) balance.data)->amounts.size() == 2) {
|
||||
balance.balance().amounts.size() == 2) {
|
||||
transactions_list::const_iterator x = transactions.begin();
|
||||
assert((*x)->amount);
|
||||
commodity_t& this_comm = (*x)->amount->commodity();
|
||||
|
||||
balance_t::amounts_map::const_iterator this_bal =
|
||||
((balance_t *) balance.data)->amounts.find(&this_comm);
|
||||
balance.balance().amounts.find(&this_comm);
|
||||
balance_t::amounts_map::const_iterator other_bal =
|
||||
((balance_t *) balance.data)->amounts.begin();
|
||||
balance.balance().amounts.begin();
|
||||
if (this_bal == other_bal)
|
||||
other_bal++;
|
||||
|
||||
|
|
@ -196,7 +196,8 @@ bool entry_base_t::finalize()
|
|||
continue;
|
||||
|
||||
if (! empty_allowed)
|
||||
throw_(std::logic_error, "Only one transaction with null amount allowed per entry");
|
||||
throw_(std::logic_error,
|
||||
"Only one transaction with null amount allowed per entry");
|
||||
empty_allowed = false;
|
||||
|
||||
// If one transaction gives no value at all, its value will become
|
||||
|
|
@ -207,12 +208,12 @@ bool entry_base_t::finalize()
|
|||
balance_t * bal = NULL;
|
||||
switch (balance.type) {
|
||||
case value_t::BALANCE_PAIR:
|
||||
bal = &((balance_pair_t *) balance.data)->quantity;
|
||||
bal = &balance.balance_pair().quantity;
|
||||
// fall through...
|
||||
|
||||
case value_t::BALANCE:
|
||||
if (! bal)
|
||||
bal = (balance_t *) balance.data;
|
||||
bal = &balance.balance();
|
||||
|
||||
if (bal->amounts.size() < 2) {
|
||||
balance.cast(value_t::AMOUNT);
|
||||
|
|
@ -241,7 +242,7 @@ bool entry_base_t::finalize()
|
|||
// fall through...
|
||||
|
||||
case value_t::AMOUNT:
|
||||
(*x)->amount = ((amount_t *) balance.data)->negate();
|
||||
(*x)->amount = balance.amount().negate();
|
||||
(*x)->flags |= TRANSACTION_CALCULATED;
|
||||
|
||||
balance += *(*x)->amount;
|
||||
|
|
|
|||
|
|
@ -87,12 +87,10 @@ void export_amount()
|
|||
.def(self += double())
|
||||
|
||||
.def(self + self)
|
||||
#if 0
|
||||
.def(self + long())
|
||||
.def(long() + self)
|
||||
.def(self + double())
|
||||
.def(double() + self)
|
||||
#endif
|
||||
|
||||
.def(self -= self)
|
||||
.def(self -= long())
|
||||
|
|
|
|||
|
|
@ -117,11 +117,11 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
|
|||
result = static_cast<const value_t&>(extract<value_t>(func.ptr()));
|
||||
} else {
|
||||
assert(locals->args.type == value_t::SEQUENCE);
|
||||
if (locals->args.to_sequence()->size() > 0) {
|
||||
if (locals->args.sequence()->size() > 0) {
|
||||
list arglist;
|
||||
for (value_t::sequence_t::iterator
|
||||
i = locals->args.to_sequence()->begin();
|
||||
i != locals->args.to_sequence()->end();
|
||||
i = locals->args.sequence()->begin();
|
||||
i != locals->args.sequence()->end();
|
||||
i++)
|
||||
arglist.append(*i);
|
||||
|
||||
|
|
@ -155,10 +155,10 @@ void python_interpreter_t::lambda_t::operator()(value_t& result,
|
|||
{
|
||||
try {
|
||||
assert(locals->args.type == value_t::SEQUENCE);
|
||||
assert(locals->args.to_sequence()->size() == 1);
|
||||
assert(locals->args.sequence()->size() == 1);
|
||||
value_t item = locals->args[0];
|
||||
assert(item.type == value_t::POINTER);
|
||||
result = call<value_t>(func.ptr(), (xml::node_t *)*(void **)item.data);
|
||||
result = call<value_t>(func.ptr(), item.xml_node());
|
||||
}
|
||||
catch (const error_already_set&) {
|
||||
PyErr_Print();
|
||||
|
|
|
|||
|
|
@ -20,16 +20,16 @@ void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
|
|||
if (locals->args.size() < 2)
|
||||
throw_(std::logic_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
|
||||
|
||||
string str = locals->args[0].to_string();
|
||||
string str = locals->args[0].string_value();
|
||||
long wid = locals->args[1];
|
||||
|
||||
elision_style_t style = session->elision_style;
|
||||
if (locals->args.size() == 3)
|
||||
style = (elision_style_t)locals->args[2].to_integer();
|
||||
style = (elision_style_t)locals->args[2].integer();
|
||||
|
||||
long abbrev_len = session->abbrev_length;
|
||||
if (locals->args.size() == 4)
|
||||
abbrev_len = locals->args[3].to_integer();
|
||||
abbrev_len = locals->args[3].integer();
|
||||
|
||||
result.set_string(abbreviate(str, wid, style, true, (int)abbrev_len));
|
||||
}
|
||||
|
|
@ -39,11 +39,11 @@ void report_t::ftime(value_t&, xml::xpath_t::scope_t * locals)
|
|||
if (locals->args.size() < 1)
|
||||
throw_(std::logic_error, "usage: ftime(DATE [, DATE_FORMAT])");
|
||||
|
||||
moment_t date = locals->args[0].to_datetime();
|
||||
moment_t date = locals->args[0].datetime();
|
||||
|
||||
string date_format;
|
||||
if (locals->args.size() == 2)
|
||||
date_format = locals->args[1].to_string();
|
||||
date_format = locals->args[1].string_value();
|
||||
#if 0
|
||||
// jww (2007-04-18): Need to setup an output facet here
|
||||
else
|
||||
|
|
|
|||
|
|
@ -60,18 +60,18 @@ class report_t : public xml::xpath_t::scope_t
|
|||
xml::xpath_t(expr).compile((xml::document_t *)NULL, this);
|
||||
}
|
||||
void option_eval(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
eval(locals->args[0].to_string());
|
||||
eval(locals->args[0].string_value());
|
||||
}
|
||||
|
||||
void option_amount(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
eval(string("t=") + locals->args[0].to_string());
|
||||
eval(string("t=") + locals->args[0].string_value());
|
||||
}
|
||||
void option_total(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
eval(string("T()=") + locals->args[0].to_string());
|
||||
eval(string("T()=") + locals->args[0].string_value());
|
||||
}
|
||||
|
||||
void option_format(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
format_string = locals->args[0].to_string();
|
||||
format_string = locals->args[0].string_value();
|
||||
}
|
||||
|
||||
void option_raw(value_t&) {
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ class session_t : public xml::xpath_t::scope_t
|
|||
//
|
||||
|
||||
void option_file(value_t&, xml::xpath_t::scope_t * locals) {
|
||||
data_file = locals->args.to_string();
|
||||
data_file = locals->args.string_value();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ parse_amount_expr(std::istream& in, journal_t *,
|
|||
}
|
||||
#endif
|
||||
|
||||
amount = xpath.calc(static_cast<xml::transaction_node_t *>(xact.data)).to_amount();
|
||||
amount = xpath.calc(static_cast<xml::transaction_node_t *>(xact.data)).amount();
|
||||
|
||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"The transaction amount is " << amount);
|
||||
|
|
|
|||
92
src/value.cc
92
src/value.cc
|
|
@ -3,84 +3,93 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
bool value_t::to_boolean() const
|
||||
bool& value_t::boolean()
|
||||
{
|
||||
if (type == BOOLEAN) {
|
||||
return *(bool *) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not a boolean");
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(BOOLEAN);
|
||||
return *(bool *) temp.data;
|
||||
}
|
||||
}
|
||||
|
||||
long value_t::to_integer() const
|
||||
long& value_t::integer()
|
||||
{
|
||||
if (type == INTEGER) {
|
||||
return *(long *) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not an integer");
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(INTEGER);
|
||||
return *(long *) temp.data;
|
||||
}
|
||||
}
|
||||
|
||||
moment_t value_t::to_datetime() const
|
||||
moment_t& value_t::datetime()
|
||||
{
|
||||
if (type == DATETIME) {
|
||||
return *(moment_t *) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not a date/time");
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(DATETIME);
|
||||
return *(moment_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
||||
amount_t value_t::to_amount() const
|
||||
amount_t& value_t::amount()
|
||||
{
|
||||
if (type == AMOUNT) {
|
||||
return *(amount_t *) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not an amount");
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(AMOUNT);
|
||||
return *(amount_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
||||
balance_t value_t::to_balance() const
|
||||
balance_t& value_t::balance()
|
||||
{
|
||||
if (type == BALANCE) {
|
||||
return *(balance_t *) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not a balance");
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(BALANCE);
|
||||
return *(balance_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
||||
balance_pair_t value_t::to_balance_pair() const
|
||||
balance_pair_t& value_t::balance_pair()
|
||||
{
|
||||
if (type == BALANCE_PAIR) {
|
||||
return *(balance_pair_t *) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not a balance pair");
|
||||
value_t temp(*this);
|
||||
temp.in_place_cast(BALANCE_PAIR);
|
||||
return *(balance_pair_t *) temp.data;
|
||||
}
|
||||
}
|
||||
|
||||
string value_t::to_string() const
|
||||
string& value_t::string_value()
|
||||
{
|
||||
if (type == STRING) {
|
||||
return **(string **) data;
|
||||
} else {
|
||||
throw_(value_error, "Value is not a string");
|
||||
#if 0
|
||||
std::ostringstream out;
|
||||
out << *this;
|
||||
return out.str();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
xml::node_t * value_t::to_xml_node() const
|
||||
xml::node_t *& value_t::xml_node()
|
||||
{
|
||||
if (type == XML_NODE)
|
||||
return *(xml::node_t **) data;
|
||||
|
|
@ -88,7 +97,7 @@ xml::node_t * value_t::to_xml_node() const
|
|||
throw_(value_error, "Value is not an XML node");
|
||||
}
|
||||
|
||||
void * value_t::to_pointer() const
|
||||
void *& value_t::pointer()
|
||||
{
|
||||
if (type == POINTER)
|
||||
return *(void **) data;
|
||||
|
|
@ -96,7 +105,7 @@ void * value_t::to_pointer() const
|
|||
throw_(value_error, "Value is not a pointer");
|
||||
}
|
||||
|
||||
value_t::sequence_t * value_t::to_sequence() const
|
||||
value_t::sequence_t *& value_t::sequence()
|
||||
{
|
||||
if (type == SEQUENCE)
|
||||
return *(sequence_t **) data;
|
||||
|
|
@ -352,7 +361,7 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
case BALANCE:
|
||||
switch (val.type) {
|
||||
case INTEGER:
|
||||
*((balance_t *) data) += *((long *) val.data);
|
||||
*((balance_t *) data) += amount_t(*((long *) val.data));
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((balance_t *) data) += *((amount_t *) val.data);
|
||||
|
|
@ -375,7 +384,7 @@ value_t& value_t::operator+=(const value_t& val)
|
|||
case BALANCE_PAIR:
|
||||
switch (val.type) {
|
||||
case INTEGER:
|
||||
*((balance_pair_t *) data) += *((long *) val.data);
|
||||
*((balance_pair_t *) data) += amount_t(*((long *) val.data));
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((balance_pair_t *) data) += *((amount_t *) val.data);
|
||||
|
|
@ -536,7 +545,7 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
case BALANCE:
|
||||
switch (val.type) {
|
||||
case INTEGER:
|
||||
*((balance_t *) data) -= *((long *) val.data);
|
||||
*((balance_t *) data) -= amount_t(*((long *) val.data));
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((balance_t *) data) -= *((amount_t *) val.data);
|
||||
|
|
@ -557,7 +566,7 @@ value_t& value_t::operator-=(const value_t& val)
|
|||
case BALANCE_PAIR:
|
||||
switch (val.type) {
|
||||
case INTEGER:
|
||||
*((balance_pair_t *) data) -= *((long *) val.data);
|
||||
*((balance_pair_t *) data) -= amount_t(*((long *) val.data));
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((balance_pair_t *) data) -= *((amount_t *) val.data);
|
||||
|
|
@ -686,7 +695,7 @@ value_t& value_t::operator*=(const value_t& val)
|
|||
case BALANCE_PAIR:
|
||||
switch (val.type) {
|
||||
case INTEGER:
|
||||
*((balance_pair_t *) data) *= *((long *) val.data);
|
||||
*((balance_pair_t *) data) *= amount_t(*((long *) val.data));
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((balance_pair_t *) data) *= *((amount_t *) val.data);
|
||||
|
|
@ -833,7 +842,7 @@ value_t& value_t::operator/=(const value_t& val)
|
|||
case BALANCE_PAIR:
|
||||
switch (val.type) {
|
||||
case INTEGER:
|
||||
*((balance_pair_t *) data) /= *((long *) val.data);
|
||||
*((balance_pair_t *) data) /= amount_t(*((long *) val.data));
|
||||
break;
|
||||
case AMOUNT:
|
||||
*((balance_pair_t *) data) /= *((amount_t *) val.data);
|
||||
|
|
@ -884,7 +893,7 @@ value_t::operator bool() const
|
|||
case STRING:
|
||||
return ! (**((string **) data)).empty();
|
||||
case XML_NODE:
|
||||
return (*(xml::node_t **) data)->to_value().to_boolean();
|
||||
return (*(xml::node_t **) data)->to_value().boolean();
|
||||
case POINTER:
|
||||
return *(void **) data != NULL;
|
||||
case SEQUENCE:
|
||||
|
|
@ -1032,10 +1041,18 @@ value_t::operator string() const
|
|||
}
|
||||
#endif
|
||||
|
||||
inline int compare_bool(const bool left, const bool right) {
|
||||
template <typename T>
|
||||
inline int compare_bool(const T& left, const T& right) {
|
||||
return (! left && right ? -1 : (left && ! right ? 1 : 0));
|
||||
}
|
||||
|
||||
// jww (2007-05-01): This is going to be slow as hell for two
|
||||
// balance_t objects
|
||||
template <typename T>
|
||||
inline int compare_equality(const T& left, const T& right) {
|
||||
return (left < right ? -1 : (left > right ? 1 : 0));
|
||||
}
|
||||
|
||||
int value_t::compare(const value_t& val) const
|
||||
{
|
||||
if (val.type == XML_NODE)
|
||||
|
|
@ -1090,10 +1107,12 @@ int value_t::compare(const value_t& val) const
|
|||
return amount_t(*((long *) data)).compare(*((amount_t *) val.data));
|
||||
|
||||
case BALANCE:
|
||||
return balance_t(*((long *) data)).compare(*((balance_t *) val.data));
|
||||
return compare_equality(balance_t(*((long *) data)),
|
||||
*((balance_t *) val.data));
|
||||
|
||||
case BALANCE_PAIR:
|
||||
return balance_pair_t(*((long *) data)).compare(*((balance_pair_t *) val.data));
|
||||
return compare_equality(balance_pair_t(*((long *) data)),
|
||||
*((balance_pair_t *) val.data));
|
||||
|
||||
case STRING:
|
||||
throw_(value_error, "Cannot compare an integer to a string");
|
||||
|
|
@ -1116,8 +1135,7 @@ int value_t::compare(const value_t& val) const
|
|||
throw_(value_error, "Cannot compare a date/time to an integer");
|
||||
|
||||
case DATETIME:
|
||||
return (*((moment_t *) data) < *((moment_t *) val.data) ? -1 :
|
||||
(*((moment_t *) data) > *((moment_t *) val.data) ? 1 : 0));
|
||||
return compare_equality(*((moment_t *) data), *((moment_t *) val.data));
|
||||
|
||||
case AMOUNT:
|
||||
throw_(value_error, "Cannot compare a date/time to an amount");
|
||||
|
|
@ -1153,10 +1171,12 @@ int value_t::compare(const value_t& val) const
|
|||
return ((amount_t *) data)->compare(*((amount_t *) val.data));
|
||||
|
||||
case BALANCE:
|
||||
return balance_t(*((amount_t *) data)).compare(*((balance_t *) val.data));
|
||||
return compare_equality(balance_t(*((amount_t *) data)),
|
||||
*((balance_t *) val.data));
|
||||
|
||||
case BALANCE_PAIR:
|
||||
return balance_pair_t(*((amount_t *) data)).compare(*((balance_pair_t *) val.data));
|
||||
return compare_equality(balance_pair_t(*((amount_t *) data)),
|
||||
*((balance_pair_t *) val.data));
|
||||
|
||||
case STRING:
|
||||
throw_(value_error, "Cannot compare an amount to a string");
|
||||
|
|
@ -1177,20 +1197,22 @@ int value_t::compare(const value_t& val) const
|
|||
throw_(value_error, "Cannot compare a balance to a boolean");
|
||||
|
||||
case INTEGER:
|
||||
return ((balance_t *) data)->compare(amount_t(*((long *) val.data)));
|
||||
return compare_equality(*(balance_t *) data,
|
||||
balance_t(*((long *) val.data)));
|
||||
|
||||
case DATETIME:
|
||||
throw_(value_error, "Cannot compare a balance to a date/time");
|
||||
|
||||
case AMOUNT:
|
||||
return ((balance_t *) data)->compare(*((amount_t *) val.data));
|
||||
return compare_equality(*(balance_t *) data,
|
||||
balance_t(*((amount_t *) val.data)));
|
||||
|
||||
case BALANCE:
|
||||
return ((balance_t *) data)->compare(*((balance_t *) val.data));
|
||||
return compare_equality(*(balance_t *) data, *((balance_t *) val.data));
|
||||
|
||||
case BALANCE_PAIR:
|
||||
return balance_pair_t(*((balance_t *) data)).
|
||||
compare(((balance_pair_t *) val.data)->quantity);
|
||||
return compare_equality(balance_pair_t(*((balance_t *) data)),
|
||||
*(balance_pair_t *) val.data);
|
||||
|
||||
case STRING:
|
||||
throw_(value_error, "Cannot compare a balance to a string");
|
||||
|
|
@ -1211,19 +1233,23 @@ int value_t::compare(const value_t& val) const
|
|||
throw_(value_error, "Cannot compare a balance pair to a boolean");
|
||||
|
||||
case INTEGER:
|
||||
return ((balance_pair_t *) data)->compare(amount_t(*((long *) val.data)));
|
||||
return compare_equality(*(balance_pair_t *) data,
|
||||
balance_pair_t(amount_t(*((long *) val.data))));
|
||||
|
||||
case DATETIME:
|
||||
throw_(value_error, "Cannot compare a balance pair to a date/time");
|
||||
|
||||
case AMOUNT:
|
||||
return ((balance_pair_t *) data)->compare(*((amount_t *) val.data));
|
||||
return compare_equality(*(balance_pair_t *) data,
|
||||
balance_pair_t(*((amount_t *) val.data)));
|
||||
|
||||
case BALANCE:
|
||||
return ((balance_pair_t *) data)->compare(*((balance_t *) val.data));
|
||||
return compare_equality(*(balance_pair_t *) data,
|
||||
balance_pair_t(*((balance_t *) val.data)));
|
||||
|
||||
case BALANCE_PAIR:
|
||||
return ((balance_pair_t *) data)->compare(*((balance_pair_t *) val.data));
|
||||
return compare_equality(*(balance_pair_t *) data,
|
||||
*((balance_pair_t *) val.data));
|
||||
|
||||
case STRING:
|
||||
throw_(value_error, "Cannot compare a balance pair to a string");
|
||||
|
|
|
|||
55
src/value.h
55
src/value.h
|
|
@ -19,13 +19,20 @@ namespace xml {
|
|||
// fact that logic chains only need boolean values to continue, no
|
||||
// memory allocations need to take place at all.
|
||||
|
||||
class value_t : public ordered_field_operators<value_t>
|
||||
class value_t
|
||||
: public ordered_field_operators<value_t,
|
||||
ordered_field_operators<value_t, balance_pair_t,
|
||||
ordered_field_operators<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> > > > > > >
|
||||
{
|
||||
char data[sizeof(balance_pair_t)];
|
||||
|
||||
public:
|
||||
typedef std::vector<value_t> sequence_t;
|
||||
|
||||
char data[sizeof(balance_pair_t)];
|
||||
|
||||
enum type_t {
|
||||
BOOLEAN,
|
||||
INTEGER,
|
||||
|
|
@ -124,6 +131,7 @@ class value_t : public ordered_field_operators<value_t>
|
|||
void simplify();
|
||||
|
||||
value_t& operator=(const value_t& val);
|
||||
#if 0
|
||||
value_t& operator=(const bool val) {
|
||||
if ((bool *) data != &val) {
|
||||
destroy();
|
||||
|
|
@ -258,6 +266,7 @@ class value_t : public ordered_field_operators<value_t>
|
|||
return *this;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
value_t& set_string(const string& str = "") {
|
||||
if (type != STRING) {
|
||||
|
|
@ -270,31 +279,31 @@ class value_t : public ordered_field_operators<value_t>
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool to_boolean() const;
|
||||
long to_integer() const;
|
||||
moment_t to_datetime() const;
|
||||
amount_t to_amount() const;
|
||||
balance_t to_balance() const;
|
||||
balance_pair_t to_balance_pair() const;
|
||||
string to_string() const;
|
||||
xml::node_t * to_xml_node() const;
|
||||
void * to_pointer() const;
|
||||
sequence_t * to_sequence() const;
|
||||
bool& boolean();
|
||||
long& integer();
|
||||
moment_t& datetime();
|
||||
amount_t& amount();
|
||||
balance_t& balance();
|
||||
balance_pair_t& balance_pair();
|
||||
string& string_value();
|
||||
xml::node_t *& xml_node();
|
||||
void *& pointer();
|
||||
sequence_t *& sequence();
|
||||
|
||||
value_t& operator[](const int index) {
|
||||
sequence_t * seq = to_sequence();
|
||||
sequence_t * seq = sequence();
|
||||
assert(seq);
|
||||
return (*seq)[index];
|
||||
}
|
||||
|
||||
void push_back(const value_t& val) {
|
||||
sequence_t * seq = to_sequence();
|
||||
sequence_t * seq = sequence();
|
||||
assert(seq);
|
||||
return seq->push_back(val);
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
sequence_t * seq = to_sequence();
|
||||
sequence_t * seq = const_cast<value_t&>(*this).sequence();
|
||||
assert(seq);
|
||||
return seq->size();
|
||||
}
|
||||
|
|
@ -309,18 +318,22 @@ class value_t : public ordered_field_operators<value_t>
|
|||
bool operator==(const value_t& val) const {
|
||||
return compare(val) == 0;
|
||||
}
|
||||
#if 0
|
||||
template <typename T>
|
||||
bool operator==(const T& val) const {
|
||||
return *this == value_t(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator<(const value_t& val) const {
|
||||
return compare(val) < 0;
|
||||
}
|
||||
#if 0
|
||||
template <typename T>
|
||||
bool operator<(const T& val) const {
|
||||
return *this < value_t(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
operator bool() const;
|
||||
|
||||
|
|
@ -336,15 +349,15 @@ class value_t : public ordered_field_operators<value_t>
|
|||
operator balance_pair_t() const;
|
||||
#endif
|
||||
|
||||
void in_place_negate();
|
||||
value_t operator-() const {
|
||||
return negate();
|
||||
}
|
||||
value_t negate() const {
|
||||
value_t temp = *this;
|
||||
temp.in_place_negate();
|
||||
return temp;
|
||||
}
|
||||
value_t operator-() const {
|
||||
return negate();
|
||||
}
|
||||
void in_place_negate();
|
||||
|
||||
bool realzero() const;
|
||||
value_t abs() const;
|
||||
|
|
@ -380,6 +393,8 @@ class value_t : public ordered_field_operators<value_t>
|
|||
|
||||
void write(std::ostream& out, const int first_width,
|
||||
const int latter_width = -1) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const value_t& val);
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
34
src/xpath.cc
34
src/xpath.cc
|
|
@ -534,7 +534,7 @@ bool xpath_t::function_scope_t::resolve(const string& name,
|
|||
case 't':
|
||||
if (name == "text") {
|
||||
if (value->type == value_t::XML_NODE)
|
||||
result.set_string(value->to_xml_node()->text());
|
||||
result.set_string(value->xml_node()->text());
|
||||
else
|
||||
throw_(calc_error, "Attempt to call text() on a non-node value");
|
||||
return true;
|
||||
|
|
@ -650,7 +650,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
|
|||
#endif /* USE_BOOST_PYTHON */
|
||||
#endif
|
||||
|
||||
string ident = tok.value.to_string();
|
||||
string ident = tok.value.string_value();
|
||||
int id = -1;
|
||||
if (std::isdigit(ident[0])) {
|
||||
node.reset(new op_t(op_t::ARG_INDEX));
|
||||
|
|
@ -692,7 +692,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
|
|||
throw_(parse_error, "@ symbol must be followed by attribute name");
|
||||
|
||||
node.reset(new op_t(op_t::ATTR_NAME));
|
||||
node->name = new string(tok.value.to_string());
|
||||
node->name = new string(tok.value.string_value());
|
||||
break;
|
||||
|
||||
#if 0
|
||||
|
|
@ -1184,7 +1184,7 @@ void xpath_t::op_t::find_values(value_t * context, scope_t * scope,
|
|||
|
||||
if (recursive) {
|
||||
if (context->type == value_t::XML_NODE) {
|
||||
node_t * ptr = context->to_xml_node();
|
||||
node_t * ptr = context->xml_node();
|
||||
if (ptr->flags & XML_NODE_IS_PARENT) {
|
||||
parent_node_t * parent = static_cast<parent_node_t *>(ptr);
|
||||
for (node_t * node = parent->children();
|
||||
|
|
@ -1211,10 +1211,10 @@ bool xpath_t::op_t::test_value(value_t * context, scope_t * scope,
|
|||
switch (expr->valuep->type) {
|
||||
case value_t::INTEGER:
|
||||
case value_t::AMOUNT:
|
||||
return *expr->valuep == (long)index + 1;
|
||||
return *expr->valuep == value_t((long)index + 1);
|
||||
|
||||
default:
|
||||
return expr->valuep->to_boolean();
|
||||
return expr->valuep->boolean();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1246,7 +1246,7 @@ xpath_t::op_t * xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
|
|||
if ((*i).type != value_t::POINTER)
|
||||
*opp = wrap_value(*i)->acquire();
|
||||
else
|
||||
*opp = static_cast<op_t *>((*i).to_pointer());
|
||||
*opp = static_cast<op_t *>((*i).pointer());
|
||||
}
|
||||
|
||||
return lit_seq.release();
|
||||
|
|
@ -1256,7 +1256,7 @@ void xpath_t::op_t::append_value(value_t& val,
|
|||
value_t::sequence_t& result_seq)
|
||||
{
|
||||
if (val.type == value_t::SEQUENCE) {
|
||||
value_t::sequence_t * subseq = val.to_sequence();
|
||||
value_t::sequence_t * subseq = val.sequence();
|
||||
for (value_t::sequence_t::iterator i = subseq->begin();
|
||||
i != subseq->end();
|
||||
i++)
|
||||
|
|
@ -1284,8 +1284,8 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
case document_t::PARENT:
|
||||
if (context->type != value_t::XML_NODE)
|
||||
throw_(compile_error, "Referencing parent node from a non-node value");
|
||||
else if (context->to_xml_node()->parent)
|
||||
return wrap_value(context->to_xml_node()->parent)->acquire();
|
||||
else if (context->xml_node()->parent)
|
||||
return wrap_value(context->xml_node()->parent)->acquire();
|
||||
else
|
||||
throw_(compile_error, "Referencing parent node from the root node");
|
||||
|
||||
|
|
@ -1293,13 +1293,13 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
if (context->type != value_t::XML_NODE)
|
||||
throw_(compile_error, "Referencing root node from a non-node value");
|
||||
else
|
||||
return wrap_value(context->to_xml_node()->document->top)->acquire();
|
||||
return wrap_value(context->xml_node()->document->top)->acquire();
|
||||
|
||||
case document_t::ALL: {
|
||||
if (context->type != value_t::XML_NODE)
|
||||
throw_(compile_error, "Referencing child nodes from a non-node value");
|
||||
|
||||
node_t * ptr = context->to_xml_node();
|
||||
node_t * ptr = context->xml_node();
|
||||
if (! (ptr->flags & XML_NODE_IS_PARENT))
|
||||
throw_(compile_error, "Request for child nodes of a leaf node");
|
||||
|
||||
|
|
@ -1319,7 +1319,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
|
||||
case NODE_NAME:
|
||||
if (context->type == value_t::XML_NODE) {
|
||||
node_t * ptr = context->to_xml_node();
|
||||
node_t * ptr = context->xml_node();
|
||||
if (resolve) {
|
||||
// First, look up the symbol as a node name within the current
|
||||
// context. If any exist, then return the set of names.
|
||||
|
|
@ -1352,7 +1352,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
|
||||
case ATTR_NAME: {
|
||||
// jww (2006-09-29): Attrs should map strings to values, not strings
|
||||
const char * value = context->to_xml_node()->get_attr(name->c_str());
|
||||
const char * value = context->xml_node()->get_attr(name->c_str());
|
||||
return wrap_value(value)->acquire();
|
||||
}
|
||||
|
||||
|
|
@ -1372,8 +1372,8 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
case ARG_INDEX:
|
||||
if (scope && scope->kind == scope_t::ARGUMENT) {
|
||||
assert(scope->args.type == value_t::SEQUENCE);
|
||||
if (arg_index < scope->args.to_sequence()->size())
|
||||
return wrap_value((*scope->args.to_sequence())[arg_index])->acquire();
|
||||
if (arg_index < scope->args.sequence()->size())
|
||||
return wrap_value((*scope->args.sequence())[arg_index])->acquire();
|
||||
else
|
||||
throw_(compile_error, "Reference to non-existing argument");
|
||||
} else {
|
||||
|
|
@ -1815,7 +1815,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
|||
}
|
||||
|
||||
case value_t::SEQUENCE: {
|
||||
value_t::sequence_t * seq = lexpr->valuep->to_sequence();
|
||||
value_t::sequence_t * seq = lexpr->valuep->sequence();
|
||||
|
||||
int index = 0;
|
||||
for (value_t::sequence_t::iterator i = seq->begin();
|
||||
|
|
|
|||
|
|
@ -760,7 +760,7 @@ inline std::ostream& operator<<(std::ostream& out, const xpath_t::op_t& op) {
|
|||
template <typename T>
|
||||
inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
||||
assert(locals->args.size() > idx);
|
||||
T * ptr = static_cast<T *>(locals->args[idx].to_pointer());
|
||||
T * ptr = static_cast<T *>(locals->args[idx].pointer());
|
||||
assert(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue