speed improvements; my "bal" script is cut to a third
This commit is contained in:
parent
18ec7d0539
commit
55d58940ce
6 changed files with 1206 additions and 83 deletions
92
amount.cc
92
amount.cc
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
25
amount.h
25
amount.h
|
|
@ -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);
|
||||
|
|
|
|||
37
balance.h
37
balance.h
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
110
valexpr.cc
110
valexpr.cc
|
|
@ -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];
|
||||
if (c == '{') {
|
||||
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];
|
||||
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;
|
||||
|
|
|
|||
30
valexpr.h
30
valexpr.h
|
|
@ -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 {
|
||||
|
|
|
|||
995
value.h
Normal file
995
value.h
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Reference in a new issue