diff options
author | John Wiegley <johnw@newartisans.com> | 2004-08-17 22:18:38 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2004-08-17 22:18:38 -0400 |
commit | 55d58940ceb6a47e4032bbad83909d1ca82d2e03 (patch) | |
tree | 3cf5414137af9893924bedc3c6ad8c9f48a8084b | |
parent | 18ec7d05391d55a804042f47882c5af4e5765e86 (diff) | |
download | fork-ledger-55d58940ceb6a47e4032bbad83909d1ca82d2e03.tar.gz fork-ledger-55d58940ceb6a47e4032bbad83909d1ca82d2e03.tar.bz2 fork-ledger-55d58940ceb6a47e4032bbad83909d1ca82d2e03.zip |
speed improvements; my "bal" script is cut to a third
-rw-r--r-- | amount.cc | 92 | ||||
-rw-r--r-- | amount.h | 25 | ||||
-rw-r--r-- | balance.h | 37 | ||||
-rw-r--r-- | valexpr.cc | 110 | ||||
-rw-r--r-- | valexpr.h | 30 | ||||
-rw-r--r-- | value.h | 995 |
6 files changed, 1206 insertions, 83 deletions
@@ -254,16 +254,25 @@ amount_t& amount_t::negate() return *this; } -// comparisons to zero +// integer comparisons +template <typename T> +static inline void parse_num(amount_t& amt, T num) { + std::string str; + { std::ostringstream strstr(str); + strstr << num; + } + { std::istringstream strstr(str); + amt.parse(strstr); + } +} + bool amount_t::operator<(const int num) const { if (num == 0) { return quantity ? mpz_sgn(MPZ(quantity)) < 0 : false; } else { - std::string str; - std::ostringstream strstr(str); - strstr << num; - amount_t amt(strstr.str()); + amount_t amt; + parse_num(amt, num); return *this < amt; } } @@ -273,10 +282,8 @@ bool amount_t::operator<=(const int num) const if (num == 0) { return quantity ? mpz_sgn(MPZ(quantity)) <= 0 : true; } else { - std::string str; - std::ostringstream strstr(str); - strstr << num; - amount_t amt(strstr.str()); + amount_t amt; + parse_num(amt, num); return *this <= amt; } } @@ -286,10 +293,8 @@ bool amount_t::operator>(const int num) const if (num == 0) { return quantity ? mpz_sgn(MPZ(quantity)) > 0 : false; } else { - std::string str; - std::ostringstream strstr(str); - strstr << num; - amount_t amt(strstr.str()); + amount_t amt; + parse_num(amt, num); return *this > amt; } } @@ -299,14 +304,67 @@ bool amount_t::operator>=(const int num) const if (num == 0) { return quantity ? mpz_sgn(MPZ(quantity)) >= 0 : true; } else { - std::string str; - std::ostringstream strstr(str); - strstr << num; - amount_t amt(strstr.str()); + amount_t amt; + parse_num(amt, num); return *this >= amt; } } +bool amount_t::operator<(const unsigned int num) const +{ + if (num == 0) { + return quantity ? mpz_sgn(MPZ(quantity)) < 0 : false; + } else { + amount_t amt; + parse_num(amt, num); + return *this < amt; + } +} + +bool amount_t::operator<=(const unsigned int num) const +{ + if (num == 0) { + return quantity ? mpz_sgn(MPZ(quantity)) <= 0 : true; + } else { + amount_t amt; + parse_num(amt, num); + return *this <= amt; + } +} + +bool amount_t::operator>(const unsigned int num) const +{ + if (num == 0) { + return quantity ? mpz_sgn(MPZ(quantity)) > 0 : false; + } else { + amount_t amt; + parse_num(amt, num); + return *this > amt; + } +} + +bool amount_t::operator>=(const unsigned int num) const +{ + if (num == 0) { + return quantity ? mpz_sgn(MPZ(quantity)) >= 0 : true; + } else { + amount_t amt; + parse_num(amt, num); + return *this >= amt; + } +} + +bool amount_t::operator==(const unsigned int num) const +{ + if (num == 0) { + return quantity ? mpz_sgn(MPZ(quantity)) == 0 : true; + } else { + amount_t amt; + parse_num(amt, num); + return *this == amt; + } +} + // comparisons between amounts bool amount_t::operator<(const amount_t& amt) const { @@ -41,15 +41,10 @@ class amount_t commodity = amt.commodity; } amount_t(const std::string& value) { - _init(); - std::istringstream str(value); - str >> *this; + parse(value); } amount_t(const char * value) { - _init(); - std::string valstr(value); - std::istringstream str(valstr); - str >> *this; + parse(value); } amount_t(const bool value); amount_t(const int value); @@ -122,12 +117,21 @@ class amount_t // test for non-zero (use ! for zero) operator bool() const; - // comparisons to zero + // integer comparisons bool operator<(const int num) const; bool operator<=(const int num) const; bool operator>(const int num) const; bool operator>=(const int num) const; + bool operator<(const unsigned int num) const; + bool operator<=(const unsigned int num) const; + bool operator>(const unsigned int num) const; + bool operator>=(const unsigned int num) const; + bool operator==(const unsigned int num) const; + bool operator!=(const unsigned int num) const { + return ! (*this == num); + } + // comparisons between amounts bool operator<(const amount_t& amt) const; bool operator<=(const amount_t& amt) const; @@ -142,6 +146,11 @@ class amount_t amount_t value(const std::time_t moment) const; + void abs() { + if (*this < 0) + negate(); + } + operator std::string() const; void parse(std::istream& in); @@ -243,6 +243,12 @@ class balance_t bool operator<=(const amount_t& amt) const { return amount(amt.commodity) <= amt; } + bool operator<(const unsigned int val) const { + return amount() < val; + } + bool operator<=(const unsigned int val) const { + return amount() <= val; + } bool operator>(const balance_t& bal) const { for (amounts_map::const_iterator i = bal.amounts.begin(); @@ -283,6 +289,12 @@ class balance_t bool operator>=(const amount_t& amt) const { return amount(amt.commodity) >= amt; } + bool operator>(const unsigned int val) const { + return amount() > val; + } + bool operator>=(const unsigned int val) const { + return amount() >= val; + } bool operator==(const balance_t& bal) const { amounts_map::const_iterator i, j; @@ -298,12 +310,18 @@ class balance_t bool operator==(const amount_t& amt) const { return amounts.size() == 1 && (*amounts.begin()).second == amt; } + bool operator==(const unsigned int val) const { + return amount() == val; + } bool operator!=(const balance_t& bal) const { return ! (*this == bal); } bool operator!=(const amount_t& amt) const { return ! (*this == amt); } + bool operator!=(const unsigned int val) const { + return ! (*this == val); + } // unary negation balance_t& negate() { @@ -322,7 +340,10 @@ class balance_t return negated(); } - // test for non-zero (use ! for zero) + // conversion operators + operator amount_t() const { + return amount(); + } operator bool() const { for (amounts_map::const_iterator i = amounts.begin(); i != amounts.end(); @@ -338,14 +359,18 @@ class balance_t void write(std::ostream& out, const int first_width, const int latter_width = -1) const; + + void abs() { + for (amounts_map::iterator i = amounts.begin(); + i != amounts.end(); + i++) + (*i).second.abs(); + } }; inline balance_t abs(const balance_t& bal) { - balance_t temp; - for (amounts_map::const_iterator i = bal.amounts.begin(); - i != bal.amounts.end(); - i++) - temp += abs((*i).second); + balance_t temp = bal; + temp.abs(); return temp; } @@ -60,17 +60,21 @@ mask_t::~mask_t() { } -void value_expr_t::compute(balance_t& result, const details_t& details) const +void value_expr_t::compute(value_t& result, const details_t& details, + value_t::type_t type) const { - switch (type) { - case CONSTANT_A: - result = constant_a; + switch (kind) { + case CONSTANT_I: + result = constant_i; break; - case CONSTANT_T: result = (unsigned int) constant_t; break; + case CONSTANT_A: + result = constant_a; + break; + case AMOUNT: if (details.xact) result = details.xact->amount; @@ -183,11 +187,15 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const case INDEX: if (details.xact) result = details.xact->index + 1; + else + result = 0U; break; case DEPTH: if (details.account) - result = details.account->depth - 1; + result = (unsigned int) (details.account->depth - 1); + else + result = 0U; break; case F_ARITH_MEAN: @@ -212,15 +220,21 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const case F_ABS: assert(left); left->compute(result, details); - result = abs(result); + result.abs(); break; case F_STRIP: { assert(left); left->compute(result, details); - amount_t amt = result.amount(); - amt.commodity = commodity_t::null_commodity; - result = amt; + if (result.type == value_t::BALANCE) { + // jww (2004-08-17): do something smarter here + result.cast(value_t::AMOUNT); + } + if (result.type == value_t::AMOUNT) { + amount_t amt = result; + amt.commodity = commodity_t::null_commodity; + result = amt; + } break; } @@ -244,11 +258,11 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const case F_VALUE: { assert(left); - left->compute(result, details); + left->compute(result, details, value_t::BALANCE); std::time_t moment = now; if (right) { - switch (right->type) { + switch (right->kind) { case DATE: if (details.entry) moment = details.entry->date; @@ -262,20 +276,20 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const throw compute_error("Invalid date passed to P(value,date)"); } } - result = result.value(moment); + result = (*((balance_t *)result.data)).value(moment); break; } case O_NOT: - left->compute(result, details); - result = result ? false : true; + left->compute(result, details, value_t::BOOLEAN); + result.negate(); break; case O_QUES: assert(left); assert(right); - assert(right->type == O_COL); - left->compute(result, details); + assert(right->kind == O_COL); + left->compute(result, details, value_t::BOOLEAN); if (result) right->left->compute(result, details); else @@ -285,17 +299,17 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const case O_AND: assert(left); assert(right); - left->compute(result, details); + left->compute(result, details, value_t::BOOLEAN); if (result) - right->compute(result, details); + right->compute(result, details, value_t::BOOLEAN); break; case O_OR: assert(left); assert(right); - left->compute(result, details); + left->compute(result, details, value_t::BOOLEAN); if (! result) - right->compute(result, details); + right->compute(result, details, value_t::BOOLEAN); break; case O_EQ: @@ -305,10 +319,10 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const case O_GTE: { assert(left); assert(right); - balance_t temp; + value_t temp; left->compute(temp, details); right->compute(result, details); - switch (type) { + switch (kind) { case O_EQ: result = temp == result; break; case O_LT: result = temp < result; break; case O_LTE: result = temp <= result; break; @@ -325,10 +339,10 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const case O_DIV: { assert(left); assert(right); - balance_t temp; + value_t temp; right->compute(temp, details); left->compute(result, details); - switch (type) { + switch (kind) { case O_ADD: result += temp; break; case O_SUB: result -= temp; break; case O_MUL: result *= temp; break; @@ -343,6 +357,9 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const assert(0); break; } + + if (type < value_t::ANY && type != result.type) + result.cast(type); } value_expr_t * parse_value_term(std::istream& in); @@ -357,18 +374,22 @@ value_expr_t * parse_value_term(std::istream& in) value_expr_t * node = NULL; char c = peek_next_nonws(in); - if (std::isdigit(c) || c == '.' || c == '{') { + if (std::isdigit(c)) { + static char buf[2048]; + READ_INTO(in, buf, 2048, c, std::isdigit(c)); + + node = new value_expr_t(value_expr_t::CONSTANT_I); + node->constant_i = std::atol(buf); + return node; + } + else if (c == '{') { static char buf[2048]; - if (c == '{') { + in.get(c); + READ_INTO(in, buf, 2048, c, c != '}'); + if (c == '}') in.get(c); - READ_INTO(in, buf, 2048, c, c != '}'); - if (c == '}') - in.get(c); - else - throw value_expr_error("Missing '}'"); - } else { - READ_INTO(in, buf, 2048, c, std::isdigit(c) || c == '.'); - } + else + throw value_expr_error("Missing '}'"); node = new value_expr_t(value_expr_t::CONSTANT_A); node->constant_a.parse(buf); @@ -613,7 +634,7 @@ value_expr_t * parse_logic_expr(std::istream& in) node = new value_expr_t(value_expr_t::O_LT); if (peek_next_nonws(in) == '=') { in.get(c); - node->type = value_expr_t::O_LTE; + node->kind = value_expr_t::O_LTE; } node->left = prev; node->right = parse_add_expr(in); @@ -625,7 +646,7 @@ value_expr_t * parse_logic_expr(std::istream& in) node = new value_expr_t(value_expr_t::O_GT); if (peek_next_nonws(in) == '=') { in.get(c); - node->type = value_expr_t::O_GTE; + node->kind = value_expr_t::O_GTE; } node->left = prev; node->right = parse_add_expr(in); @@ -708,13 +729,16 @@ value_expr_t * parse_value_expr(std::istream& in) void dump_value_expr(std::ostream& out, const value_expr_t * node) { - switch (node->type) { - case value_expr_t::CONSTANT_A: - out << "CONST[" << node->constant_a << "]"; + switch (node->kind) { + case value_expr_t::CONSTANT_I: + out << "UINT[" << node->constant_i << "]"; break; case value_expr_t::CONSTANT_T: out << "DATE/TIME[" << node->constant_t << "]"; break; + case value_expr_t::CONSTANT_A: + out << "CONST[" << node->constant_a << "]"; + break; case value_expr_t::AMOUNT: out << "AMOUNT"; break; case value_expr_t::COST: out << "COST"; break; @@ -794,7 +818,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node) case value_expr_t::O_OR: out << "("; dump_value_expr(out, node->left); - switch (node->type) { + switch (node->kind) { case value_expr_t::O_AND: out << " & "; break; case value_expr_t::O_OR: out << " | "; break; default: assert(0); break; @@ -810,7 +834,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node) case value_expr_t::O_GTE: out << "("; dump_value_expr(out, node->left); - switch (node->type) { + switch (node->kind) { case value_expr_t::O_EQ: out << "="; break; case value_expr_t::O_LT: out << "<"; break; case value_expr_t::O_LTE: out << "<="; break; @@ -828,7 +852,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node) case value_expr_t::O_DIV: out << "("; dump_value_expr(out, node->left); - switch (node->type) { + switch (node->kind) { case value_expr_t::O_ADD: out << "+"; break; case value_expr_t::O_SUB: out << "-"; break; case value_expr_t::O_MUL: out << "*"; break; @@ -2,6 +2,7 @@ #define _EXPR_H #include "ledger.h" +#include "value.h" #include "error.h" namespace ledger { @@ -42,8 +43,9 @@ struct value_expr_t { enum kind_t { // Constants - CONSTANT_A, + CONSTANT_I, CONSTANT_T, + CONSTANT_A, // Item details AMOUNT, @@ -93,16 +95,19 @@ struct value_expr_t LAST }; - kind_t type; + kind_t kind; value_expr_t * left; value_expr_t * right; - amount_t constant_a; - std::time_t constant_t; - mask_t * mask; + union { + std::time_t constant_t; + unsigned int constant_i; + }; + amount_t constant_a; + mask_t * mask; - value_expr_t(const kind_t _type) - : type(_type), left(NULL), right(NULL), mask(NULL) {} + value_expr_t(const kind_t _kind) + : kind(_kind), left(NULL), right(NULL), mask(NULL) {} ~value_expr_t() { if (mask) delete mask; @@ -110,7 +115,14 @@ struct value_expr_t if (right) delete right; } - void compute(balance_t& result, const details_t& details) const; + void compute(value_t& result, const details_t& details, + value_t::type_t type = value_t::ANY) const; + + void compute(balance_t& result, const details_t& details) const { + value_t value; + compute(value, details, value_t::BALANCE); + result = value.operator balance_t(); + } }; value_expr_t * parse_value_expr(std::istream& in); @@ -170,7 +182,7 @@ class item_predicate bool operator()(const T * item) const { if (predicate) { - balance_t result; + value_t result; predicate->compute(result, details_t(item)); return result; } else { diff --git a/value.h b/value.h new file mode 100644 index 00000000..31158594 --- /dev/null +++ b/value.h @@ -0,0 +1,995 @@ +#ifndef _VALUE_H +#define _VALUE_H + +#include "amount.h" +#include "balance.h" + +namespace ledger { + +// The following type is a polymorphous value type used solely for +// performance reasons. The alternative is to compute value +// expressions (valexpr.cc) in terms of the largest data type, +// balance_t. This was found to be prohibitively expensive, especially +// when large logic chains were involved, since many temporary +// allocations would occur for every operator. With value_t, and the +// fact that logic chains only need boolean values to continue, no +// memory allocations need to take place at all. + +class value_t +{ + bool constructed; + + value_t(const value_t& copy); + + public: + char data[sizeof(balance_t)]; + + enum type_t { + BOOLEAN, + INTEGER, + AMOUNT, + BALANCE, + ANY + } type; + + value_t() : constructed(false) { + *this = 0U; + } + + value_t(const bool value) : constructed(false) { + *((bool *) data) = value; + type = BOOLEAN; + } + value_t(const unsigned int value) : constructed(false) { + *((unsigned int *) data) = value; + type = INTEGER; + } + value_t(const amount_t& value) : constructed(true) { + new((amount_t *)data) amount_t(value); + type = AMOUNT; + } + value_t(const balance_t& value) : constructed(true) { + new((balance_t *)data) balance_t(value); + type = BALANCE; + } + + ~value_t() { + destroy(); + } + + void destroy() { + if (constructed) { + switch (type) { + case AMOUNT: + ((amount_t *)data)->~amount_t(); + break; + case BALANCE: + ((balance_t *)data)->~balance_t(); + break; + default: + break; + } + constructed = false; + } + } + + value_t& operator=(const bool value) { + destroy(); + *((bool *) data) = value; + type = BOOLEAN; + return *this; + } + value_t& operator=(const unsigned int value) { + destroy(); + *((unsigned int *) data) = value; + type = INTEGER; + return *this; + } + value_t& operator=(const amount_t& value) { + destroy(); + new((amount_t *)data) amount_t(value); + type = AMOUNT; + return *this; + } + value_t& operator=(const balance_t& value) { + destroy(); + new((balance_t *)data) balance_t(value); + type = BALANCE; + return *this; + } + + value_t& operator+=(const value_t& value) { + switch (value.type) { + case BOOLEAN: + case INTEGER: + switch (type) { + case BOOLEAN: + cast(INTEGER); + case INTEGER: + *((unsigned int *) data) += *((unsigned int *) value.data); + break; + + case AMOUNT: + *((amount_t *) data) += *((unsigned int *) value.data); + break; + + case BALANCE: + *((balance_t *) data) += amount_t(*((unsigned int *) value.data)); + break; + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + case INTEGER: + cast(AMOUNT); + case AMOUNT: + *((amount_t *) data) += *((amount_t *) value.data); + break; + + case BALANCE: + *((balance_t *) data) += *((amount_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + case INTEGER: + case AMOUNT: + cast(BALANCE); + case BALANCE: + *((balance_t *) data) += *((balance_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + value_t& operator-=(const value_t& value) { + switch (value.type) { + case BOOLEAN: + case INTEGER: + switch (type) { + case BOOLEAN: + cast(INTEGER); + case INTEGER: + *((unsigned int *) data) -= *((unsigned int *) value.data); + break; + + case AMOUNT: + *((amount_t *) data) -= *((unsigned int *) value.data); + break; + + case BALANCE: + *((balance_t *) data) -= amount_t(*((unsigned int *) value.data)); + break; + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + case INTEGER: + cast(AMOUNT); + case AMOUNT: + *((amount_t *) data) -= *((amount_t *) value.data); + break; + + case BALANCE: + *((balance_t *) data) -= *((amount_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + case INTEGER: + case AMOUNT: + cast(BALANCE); + case BALANCE: + *((balance_t *) data) -= *((balance_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + value_t& operator*=(const value_t& value) { + switch (value.type) { + case BOOLEAN: + case INTEGER: + switch (type) { + case BOOLEAN: + cast(INTEGER); + case INTEGER: + *((unsigned int *) data) *= *((unsigned int *) value.data); + break; + + case AMOUNT: + *((amount_t *) data) *= *((unsigned int *) value.data); + break; + + case BALANCE: + *((balance_t *) data) *= amount_t(*((unsigned int *) value.data)); + break; + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + case INTEGER: + cast(AMOUNT); + case AMOUNT: + *((amount_t *) data) *= *((amount_t *) value.data); + break; + + case BALANCE: + *((balance_t *) data) *= *((amount_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + case INTEGER: + case AMOUNT: + cast(BALANCE); + case BALANCE: + *((balance_t *) data) *= *((balance_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + value_t& operator/=(const value_t& value) { + switch (value.type) { + case BOOLEAN: + case INTEGER: + switch (type) { + case BOOLEAN: + cast(INTEGER); + case INTEGER: + *((unsigned int *) data) /= *((unsigned int *) value.data); + break; + + case AMOUNT: + *((amount_t *) data) /= *((unsigned int *) value.data); + break; + + case BALANCE: + *((balance_t *) data) /= amount_t(*((unsigned int *) value.data)); + break; + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + case INTEGER: + cast(AMOUNT); + case AMOUNT: + *((amount_t *) data) /= *((amount_t *) value.data); + break; + + case BALANCE: + *((balance_t *) data) /= *((amount_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + case INTEGER: + case AMOUNT: + cast(BALANCE); + case BALANCE: + *((balance_t *) data) /= *((balance_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + bool operator==(const value_t& value) { + switch (value.type) { + case BOOLEAN: + switch (type) { + case BOOLEAN: + return *((bool *) data) == *((bool *) value.data); + + case INTEGER: + return bool(*((unsigned int *) data)) == *((bool *) value.data); + + case AMOUNT: + return bool(*((amount_t *) data)) == *((bool *) value.data); + + case BALANCE: + return bool(*((balance_t *) data)) == *((bool *) value.data); + + default: + assert(0); + break; + } + break; + + case INTEGER: + switch (type) { + case BOOLEAN: + return ((unsigned int) *((bool *) data)) == *((unsigned int *) value.data); + + case INTEGER: + return *((unsigned int *) data) == *((unsigned int *) value.data); + + case AMOUNT: + return ((unsigned int) *((amount_t *) data)) == *((unsigned int *) value.data); + + case BALANCE: + return ((unsigned int) *((balance_t *) data)) == *((unsigned int *) value.data); + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + return amount_t(*((bool *) data)) == *((amount_t *) value.data); + + case INTEGER: + return amount_t(*((unsigned int *) data)) == *((amount_t *) value.data); + + case AMOUNT: + return *((amount_t *) data) == *((amount_t *) value.data); + + case BALANCE: + return ((balance_t *) data)->amount() == *((amount_t *) value.data); + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + return balance_t(*((bool *) data)) == *((balance_t *) value.data); + + case INTEGER: + return balance_t(*((unsigned int *) data)) == *((balance_t *) value.data); + + case AMOUNT: + return balance_t(*((amount_t *) data)) == *((balance_t *) value.data); + + case BALANCE: + return *((balance_t *) data) == *((balance_t *) value.data); + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + bool operator!=(const value_t& value) { + return ! (*this == value); + } + + bool operator<(const value_t& value) { + switch (value.type) { + case BOOLEAN: + switch (type) { + case BOOLEAN: + return *((bool *) data) < *((bool *) value.data); + + case INTEGER: + return bool(*((unsigned int *) data)) < *((bool *) value.data); + + case AMOUNT: + return bool(*((amount_t *) data)) < *((bool *) value.data); + + case BALANCE: + return bool(*((balance_t *) data)) < *((bool *) value.data); + + default: + assert(0); + break; + } + break; + + case INTEGER: + switch (type) { + case BOOLEAN: + return ((unsigned int) *((bool *) data)) < *((unsigned int *) value.data); + + case INTEGER: + return *((unsigned int *) data) < *((unsigned int *) value.data); + + case AMOUNT: + return *((amount_t *) data) < *((unsigned int *) value.data); + + case BALANCE: + return *((balance_t *) data) < *((unsigned int *) value.data); + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + return amount_t(*((bool *) data)) < *((amount_t *) value.data); + + case INTEGER: + return amount_t(*((unsigned int *) data)) < *((amount_t *) value.data); + + case AMOUNT: + return *((amount_t *) data) < *((amount_t *) value.data); + + case BALANCE: + return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) < *((amount_t *) value.data); + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + return balance_t(*((bool *) data)) < *((balance_t *) value.data); + + case INTEGER: + return balance_t(*((unsigned int *) data)) < *((balance_t *) value.data); + + case AMOUNT: + return balance_t(*((amount_t *) data)) < *((balance_t *) value.data); + + case BALANCE: + return *((balance_t *) data) < *((balance_t *) value.data); + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + bool operator<=(const value_t& value) { + switch (value.type) { + case BOOLEAN: + switch (type) { + case BOOLEAN: + return *((bool *) data) <= *((bool *) value.data); + + case INTEGER: + return bool(*((unsigned int *) data)) <= *((bool *) value.data); + + case AMOUNT: + return bool(*((amount_t *) data)) <= *((bool *) value.data); + + case BALANCE: + return bool(*((balance_t *) data)) <= *((bool *) value.data); + + default: + assert(0); + break; + } + break; + + case INTEGER: + switch (type) { + case BOOLEAN: + return ((unsigned int) *((bool *) data)) <= *((unsigned int *) value.data); + + case INTEGER: + return *((unsigned int *) data) <= *((unsigned int *) value.data); + + case AMOUNT: + return ((unsigned int) *((amount_t *) data)) <= *((unsigned int *) value.data); + + case BALANCE: + return ((unsigned int) *((balance_t *) data)) <= *((unsigned int *) value.data); + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + return amount_t(*((bool *) data)) <= *((amount_t *) value.data); + + case INTEGER: + return amount_t(*((unsigned int *) data)) <= *((amount_t *) value.data); + + case AMOUNT: + return *((amount_t *) data) <= *((amount_t *) value.data); + + case BALANCE: + return ((balance_t *) data)->amount() <= *((amount_t *) value.data); + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + return balance_t(*((bool *) data)) <= *((balance_t *) value.data); + + case INTEGER: + return balance_t(*((unsigned int *) data)) <= *((balance_t *) value.data); + + case AMOUNT: + return balance_t(*((amount_t *) data)) <= *((balance_t *) value.data); + + case BALANCE: + return *((balance_t *) data) <= *((balance_t *) value.data); + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + bool operator>(const value_t& value) { + switch (value.type) { + case BOOLEAN: + switch (type) { + case BOOLEAN: + return *((bool *) data) > *((bool *) value.data); + + case INTEGER: + return bool(*((unsigned int *) data)) > *((bool *) value.data); + + case AMOUNT: + return bool(*((amount_t *) data)) > *((bool *) value.data); + + case BALANCE: + return bool(*((balance_t *) data)) > *((bool *) value.data); + + default: + assert(0); + break; + } + break; + + case INTEGER: + switch (type) { + case BOOLEAN: + return ((unsigned int) *((bool *) data)) > *((unsigned int *) value.data); + + case INTEGER: + return *((unsigned int *) data) > *((unsigned int *) value.data); + + case AMOUNT: + return ((unsigned int) *((amount_t *) data)) > *((unsigned int *) value.data); + + case BALANCE: + return ((unsigned int) *((balance_t *) data)) > *((unsigned int *) value.data); + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + return amount_t(*((bool *) data)) > *((amount_t *) value.data); + + case INTEGER: + return amount_t(*((unsigned int *) data)) > *((amount_t *) value.data); + + case AMOUNT: + return *((amount_t *) data) > *((amount_t *) value.data); + + case BALANCE: + return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) > *((amount_t *) value.data); + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + return balance_t(*((bool *) data)) > *((balance_t *) value.data); + + case INTEGER: + return balance_t(*((unsigned int *) data)) > *((balance_t *) value.data); + + case AMOUNT: + return balance_t(*((amount_t *) data)) > *((balance_t *) value.data); + + case BALANCE: + return *((balance_t *) data) > *((balance_t *) value.data); + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + bool operator>=(const value_t& value) { + switch (value.type) { + case BOOLEAN: + switch (type) { + case BOOLEAN: + return *((bool *) data) >= *((bool *) value.data); + + case INTEGER: + return bool(*((unsigned int *) data)) >= *((bool *) value.data); + + case AMOUNT: + return bool(*((amount_t *) data)) >= *((bool *) value.data); + + case BALANCE: + return bool(*((balance_t *) data)) >= *((bool *) value.data); + + default: + assert(0); + break; + } + break; + + case INTEGER: + switch (type) { + case BOOLEAN: + return ((unsigned int) *((bool *) data)) >= *((unsigned int *) value.data); + + case INTEGER: + return *((unsigned int *) data) >= *((unsigned int *) value.data); + + case AMOUNT: + return ((unsigned int) *((amount_t *) data)) >= *((unsigned int *) value.data); + + case BALANCE: + return ((unsigned int) *((balance_t *) data)) >= *((unsigned int *) value.data); + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (type) { + case BOOLEAN: + return amount_t(*((bool *) data)) >= *((amount_t *) value.data); + + case INTEGER: + return amount_t(*((unsigned int *) data)) >= *((amount_t *) value.data); + + case AMOUNT: + return *((amount_t *) data) >= *((amount_t *) value.data); + + case BALANCE: + return ((balance_t *) data)->amount() >= *((amount_t *) value.data); + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (type) { + case BOOLEAN: + return balance_t(*((bool *) data)) >= *((balance_t *) value.data); + + case INTEGER: + return balance_t(*((unsigned int *) data)) >= *((balance_t *) value.data); + + case AMOUNT: + return balance_t(*((amount_t *) data)) >= *((balance_t *) value.data); + + case BALANCE: + return *((balance_t *) data) >= *((balance_t *) value.data); + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; + } + + template <typename T> + operator T() const { + switch (type) { + case BOOLEAN: + return *((bool *) data); + case INTEGER: + return *((unsigned int *) data); + case AMOUNT: + return *((amount_t *) data); + case BALANCE: + return *((balance_t *) data); + + default: + assert(0); + break; + } + assert(0); + return 0; + } + + void cast(type_t cast_type) { + switch (type) { + case BOOLEAN: + switch (cast_type) { + case BOOLEAN: + break; + case INTEGER: + *((unsigned int *) data) = *((bool *) data); + break; + case AMOUNT: + new((amount_t *)data) amount_t(*((bool *) data)); + constructed = true; + break; + case BALANCE: + new((balance_t *)data) balance_t(*((bool *) data)); + constructed = true; + break; + + default: + assert(0); + break; + } + break; + + case INTEGER: + switch (cast_type) { + case BOOLEAN: + *((bool *) data) = *((unsigned int *) data); + break; + case INTEGER: + break; + case AMOUNT: + new((amount_t *)data) amount_t(*((unsigned int *) data)); + constructed = true; + break; + case BALANCE: + new((balance_t *)data) balance_t(*((unsigned int *) data)); + constructed = true; + break; + + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (cast_type) { + case BOOLEAN: { + bool temp = *((amount_t *) data); + destroy(); + *((bool *)data) = temp; + break; + } + case INTEGER: { + unsigned int temp = *((amount_t *) data); + destroy(); + *((unsigned int *)data) = temp; + break; + } + case AMOUNT: + break; + case BALANCE: { + amount_t temp = *((amount_t *) data); + destroy(); + new((balance_t *)data) balance_t(temp); + constructed = true; + break; + } + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (cast_type) { + case BOOLEAN: { + bool temp = *((balance_t *) data); + destroy(); + *((bool *)data) = temp; + break; + } + case INTEGER: { + unsigned int temp = ((balance_t *) data)->amount(); + destroy(); + *((unsigned int *)data) = temp; + break; + } + case AMOUNT: { + amount_t temp = ((balance_t *) data)->amount(); + destroy(); + new((amount_t *)data) amount_t(temp); + constructed = true; + break; + } + case BALANCE: + break; + + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + type = cast_type; + } + + void negate() { + switch (type) { + case BOOLEAN: + *((bool *) data) = ! *((bool *) data); + break; + case INTEGER: + *((unsigned int *) data) = - *((unsigned int *) data); + break; + case AMOUNT: + ((amount_t *) data)->negate(); + break; + case BALANCE: + ((balance_t *) data)->negate(); + break; + + default: + assert(0); + break; + } + } + + void abs() { + switch (type) { + case BOOLEAN: + break; + case INTEGER: + if (*((unsigned int *) data) < 0) + *((unsigned int *) data) = - *((unsigned int *) data); + break; + case AMOUNT: + ((amount_t *) data)->abs(); + break; + case BALANCE: + ((balance_t *) data)->abs(); + break; + + default: + assert(0); + break; + } + } +}; + +} // namespace ledger + +#endif // _VALUE_H |