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;
|
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)
|
amount_t& amount_t::operator+=(const amount_t& amt)
|
||||||
{
|
{
|
||||||
if (commodity() != amt.commodity())
|
if (commodity() != amt.commodity())
|
||||||
|
|
@ -702,45 +650,6 @@ bool amount_t::zero() const
|
||||||
return realzero();
|
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
|
amount_t amount_t::value(const moment_t& moment) const
|
||||||
{
|
{
|
||||||
if (quantity) {
|
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.
|
* uncommoditized numbers, no display truncation is ever done.
|
||||||
* Internally, precision is always kept to an excessive degree.
|
* 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;
|
class bigint_t;
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
@ -83,7 +87,7 @@ class amount_t : public ordered_field_operators<amount_t>
|
||||||
static bool keep_base;
|
static bool keep_base;
|
||||||
static bool full_strings;
|
static bool full_strings;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _init();
|
void _init();
|
||||||
void _copy(const amount_t& amt);
|
void _copy(const amount_t& amt);
|
||||||
void _release();
|
void _release();
|
||||||
|
|
@ -94,7 +98,7 @@ class amount_t : public ordered_field_operators<amount_t>
|
||||||
bigint_t * quantity;
|
bigint_t * quantity;
|
||||||
commodity_t * commodity_;
|
commodity_t * commodity_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
amount_t() : quantity(NULL), commodity_(NULL) {
|
amount_t() : quantity(NULL), commodity_(NULL) {
|
||||||
TRACE_CTOR(amount_t, "");
|
TRACE_CTOR(amount_t, "");
|
||||||
|
|
@ -125,15 +129,10 @@ class amount_t : public ordered_field_operators<amount_t>
|
||||||
_release();
|
_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static amount_t exact(const string& value);
|
||||||
|
|
||||||
// assignment operator
|
// assignment operator
|
||||||
amount_t& operator=(const amount_t& amt);
|
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
|
// comparisons between amounts
|
||||||
int compare(const amount_t& amt) const;
|
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);
|
amount_t& operator/=(const amount_t& amt);
|
||||||
|
|
||||||
// unary negation
|
// unary negation
|
||||||
void in_place_negate();
|
amount_t operator-() const {
|
||||||
|
return negate();
|
||||||
|
}
|
||||||
amount_t negate() const {
|
amount_t negate() const {
|
||||||
amount_t temp = *this;
|
amount_t temp = *this;
|
||||||
temp.in_place_negate();
|
temp.in_place_negate();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
amount_t operator-() const {
|
void in_place_negate();
|
||||||
return negate();
|
|
||||||
|
// test for truth, zero and non-zero
|
||||||
|
operator bool() const {
|
||||||
|
return ! zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for zero and non-zero
|
|
||||||
int sign() const;
|
int sign() const;
|
||||||
bool zero() const;
|
bool zero() const;
|
||||||
bool realzero() const {
|
bool realzero() const {
|
||||||
return sign() == 0;
|
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 {
|
bool is_null() const {
|
||||||
return ! quantity && ! has_commodity();
|
return ! quantity && ! has_commodity();
|
||||||
}
|
}
|
||||||
|
|
@ -205,40 +209,26 @@ class amount_t : public ordered_field_operators<amount_t>
|
||||||
optional<moment_t> date() const;
|
optional<moment_t> date() const;
|
||||||
optional<string> tag() 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
|
// general methods
|
||||||
amount_t round(unsigned int prec) const;
|
amount_t round(unsigned int prec) const;
|
||||||
amount_t round() const;
|
amount_t round() const;
|
||||||
amount_t unround() const;
|
amount_t unround() const;
|
||||||
amount_t value(const moment_t& moment) const;
|
amount_t value(const moment_t& moment) const;
|
||||||
|
|
||||||
amount_t abs() const {
|
amount_t abs() const {
|
||||||
if (sign() < 0)
|
if (sign() < 0)
|
||||||
return negate();
|
return negate();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
amount_t reduce() const {
|
amount_t reduce() const {
|
||||||
amount_t temp(*this);
|
amount_t temp(*this);
|
||||||
temp.in_place_reduce();
|
temp.in_place_reduce();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid() const;
|
|
||||||
|
|
||||||
void in_place_reduce();
|
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
|
// This function is special, and exists only to support a custom
|
||||||
// optimization in binary.cc (which offers a significant enough gain
|
// optimization in binary.cc (which offers a significant enough gain
|
||||||
|
|
|
||||||
262
src/balance.cc
262
src/balance.cc
|
|
@ -2,6 +2,137 @@
|
||||||
|
|
||||||
namespace ledger {
|
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
|
amount_t balance_t::amount(const commodity_t& commodity) const
|
||||||
{
|
{
|
||||||
if (! commodity) {
|
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
|
#if 0
|
||||||
balance_t::operator amount_t() const
|
balance_t::operator amount_t() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
193
src/balance.h
193
src/balance.h
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
// jww (2007-05-01): What really should be the operational semantics
|
||||||
|
// of a balance?
|
||||||
|
|
||||||
class balance_t
|
class balance_t
|
||||||
: public totally_ordered<balance_t,
|
: public ordered_field_operators<balance_t,
|
||||||
totally_ordered<balance_t, amount_t,
|
ordered_field_operators<balance_t, amount_t> >
|
||||||
integer_arithmetic<balance_t,
|
|
||||||
integer_arithmetic<balance_t, amount_t
|
|
||||||
> > > >
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<const commodity_t *, amount_t> amounts_map;
|
typedef std::map<const commodity_t *, amount_t> amounts_map;
|
||||||
|
|
@ -54,10 +54,19 @@ public:
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
balance_t& operator=(const amount_t& amt) {
|
|
||||||
amounts.clear();
|
int compare(const balance_t& bal) const;
|
||||||
*this += amt;
|
|
||||||
return *this;
|
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
|
// in-place arithmetic
|
||||||
|
|
@ -68,15 +77,6 @@ public:
|
||||||
*this += (*i).second;
|
*this += (*i).second;
|
||||||
return *this;
|
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) {
|
balance_t& operator-=(const balance_t& bal) {
|
||||||
for (amounts_map::const_iterator i = bal.amounts.begin();
|
for (amounts_map::const_iterator i = bal.amounts.begin();
|
||||||
i != bal.amounts.end();
|
i != bal.amounts.end();
|
||||||
|
|
@ -84,25 +84,10 @@ public:
|
||||||
*this -= (*i).second;
|
*this -= (*i).second;
|
||||||
return *this;
|
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 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 balance_t& bal);
|
||||||
balance_t& operator/=(const amount_t& amt);
|
balance_t& operator/=(const amount_t& amt); // special
|
||||||
|
|
||||||
// comparison
|
// comparison
|
||||||
bool operator<(const balance_t& bal) const {
|
bool operator<(const balance_t& bal) const {
|
||||||
|
|
@ -123,42 +108,6 @@ public:
|
||||||
|
|
||||||
return true;
|
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
|
// unary negation
|
||||||
void in_place_negate() {
|
void in_place_negate() {
|
||||||
|
|
@ -177,9 +126,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// conversion operators
|
// conversion operators
|
||||||
#if 0
|
|
||||||
operator amount_t() const;
|
|
||||||
#endif
|
|
||||||
operator bool() const {
|
operator bool() const {
|
||||||
for (amounts_map::const_iterator i = amounts.begin();
|
for (amounts_map::const_iterator i = amounts.begin();
|
||||||
i != amounts.end();
|
i != amounts.end();
|
||||||
|
|
@ -275,13 +221,9 @@ inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class balance_pair_t
|
class balance_pair_t
|
||||||
: public totally_ordered<balance_pair_t,
|
: public ordered_field_operators<balance_pair_t,
|
||||||
totally_ordered<balance_pair_t, balance_t,
|
ordered_field_operators<balance_pair_t, balance_t,
|
||||||
totally_ordered<balance_pair_t, amount_t,
|
ordered_field_operators<balance_pair_t, amount_t> > >
|
||||||
integer_arithmetic<balance_pair_t,
|
|
||||||
integer_arithmetic<balance_pair_t, balance_t,
|
|
||||||
integer_arithmetic<balance_pair_t, amount_t
|
|
||||||
> > > > > >
|
|
||||||
{
|
{
|
||||||
balance_t quantity;
|
balance_t quantity;
|
||||||
optional<balance_t> cost;
|
optional<balance_t> cost;
|
||||||
|
|
@ -318,16 +260,6 @@ public:
|
||||||
}
|
}
|
||||||
return *this;
|
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
|
// in-place arithmetic
|
||||||
balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
|
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;
|
*cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||||
return *this;
|
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) {
|
balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
|
||||||
if (bal_pair.cost && ! cost)
|
if (bal_pair.cost && ! cost)
|
||||||
cost = quantity;
|
cost = quantity;
|
||||||
|
|
@ -359,20 +278,6 @@ public:
|
||||||
*cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
*cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||||
return *this;
|
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) {
|
balance_pair_t& operator*=(const balance_pair_t& bal_pair) {
|
||||||
if (bal_pair.cost && ! cost)
|
if (bal_pair.cost && ! cost)
|
||||||
cost = quantity;
|
cost = quantity;
|
||||||
|
|
@ -381,19 +286,6 @@ public:
|
||||||
*cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
*cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||||
return *this;
|
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) {
|
balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
|
||||||
if (bal_pair.cost && ! cost)
|
if (bal_pair.cost && ! cost)
|
||||||
cost = quantity;
|
cost = quantity;
|
||||||
|
|
@ -402,40 +294,13 @@ public:
|
||||||
*cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
*cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||||
return *this;
|
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
|
// 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 {
|
bool operator==(const balance_pair_t& bal_pair) const {
|
||||||
return quantity == bal_pair.quantity;
|
return quantity == bal_pair.quantity;
|
||||||
}
|
}
|
||||||
bool operator==(const balance_t& bal) const {
|
bool operator<(const balance_pair_t& bal_pair) const {
|
||||||
return quantity == bal;
|
return quantity < bal_pair.quantity;
|
||||||
}
|
|
||||||
bool operator==(const amount_t& amt) const {
|
|
||||||
return quantity == amt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unary negation
|
// unary negation
|
||||||
|
|
@ -454,14 +319,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for non-zero (use ! for zero)
|
// 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 {
|
operator bool() const {
|
||||||
return quantity;
|
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));
|
repitem_t::wrap(xact, static_cast<repitem_t *>(xact->entry->data));
|
||||||
xact->data = item;
|
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)) {
|
if (read_binary_bool(data)) {
|
||||||
|
|
|
||||||
|
|
@ -145,15 +145,15 @@ bool entry_base_t::finalize()
|
||||||
// the balance. This is done for the last eligible commodity.
|
// the balance. This is done for the last eligible commodity.
|
||||||
|
|
||||||
if (! saw_null && balance && balance.type == value_t::BALANCE &&
|
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();
|
transactions_list::const_iterator x = transactions.begin();
|
||||||
assert((*x)->amount);
|
assert((*x)->amount);
|
||||||
commodity_t& this_comm = (*x)->amount->commodity();
|
commodity_t& this_comm = (*x)->amount->commodity();
|
||||||
|
|
||||||
balance_t::amounts_map::const_iterator this_bal =
|
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::amounts_map::const_iterator other_bal =
|
||||||
((balance_t *) balance.data)->amounts.begin();
|
balance.balance().amounts.begin();
|
||||||
if (this_bal == other_bal)
|
if (this_bal == other_bal)
|
||||||
other_bal++;
|
other_bal++;
|
||||||
|
|
||||||
|
|
@ -196,7 +196,8 @@ bool entry_base_t::finalize()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (! empty_allowed)
|
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;
|
empty_allowed = false;
|
||||||
|
|
||||||
// If one transaction gives no value at all, its value will become
|
// 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;
|
balance_t * bal = NULL;
|
||||||
switch (balance.type) {
|
switch (balance.type) {
|
||||||
case value_t::BALANCE_PAIR:
|
case value_t::BALANCE_PAIR:
|
||||||
bal = &((balance_pair_t *) balance.data)->quantity;
|
bal = &balance.balance_pair().quantity;
|
||||||
// fall through...
|
// fall through...
|
||||||
|
|
||||||
case value_t::BALANCE:
|
case value_t::BALANCE:
|
||||||
if (! bal)
|
if (! bal)
|
||||||
bal = (balance_t *) balance.data;
|
bal = &balance.balance();
|
||||||
|
|
||||||
if (bal->amounts.size() < 2) {
|
if (bal->amounts.size() < 2) {
|
||||||
balance.cast(value_t::AMOUNT);
|
balance.cast(value_t::AMOUNT);
|
||||||
|
|
@ -241,7 +242,7 @@ bool entry_base_t::finalize()
|
||||||
// fall through...
|
// fall through...
|
||||||
|
|
||||||
case value_t::AMOUNT:
|
case value_t::AMOUNT:
|
||||||
(*x)->amount = ((amount_t *) balance.data)->negate();
|
(*x)->amount = balance.amount().negate();
|
||||||
(*x)->flags |= TRANSACTION_CALCULATED;
|
(*x)->flags |= TRANSACTION_CALCULATED;
|
||||||
|
|
||||||
balance += *(*x)->amount;
|
balance += *(*x)->amount;
|
||||||
|
|
|
||||||
|
|
@ -87,12 +87,10 @@ void export_amount()
|
||||||
.def(self += double())
|
.def(self += double())
|
||||||
|
|
||||||
.def(self + self)
|
.def(self + self)
|
||||||
#if 0
|
|
||||||
.def(self + long())
|
.def(self + long())
|
||||||
.def(long() + self)
|
.def(long() + self)
|
||||||
.def(self + double())
|
.def(self + double())
|
||||||
.def(double() + self)
|
.def(double() + self)
|
||||||
#endif
|
|
||||||
|
|
||||||
.def(self -= self)
|
.def(self -= self)
|
||||||
.def(self -= long())
|
.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()));
|
result = static_cast<const value_t&>(extract<value_t>(func.ptr()));
|
||||||
} else {
|
} else {
|
||||||
assert(locals->args.type == value_t::SEQUENCE);
|
assert(locals->args.type == value_t::SEQUENCE);
|
||||||
if (locals->args.to_sequence()->size() > 0) {
|
if (locals->args.sequence()->size() > 0) {
|
||||||
list arglist;
|
list arglist;
|
||||||
for (value_t::sequence_t::iterator
|
for (value_t::sequence_t::iterator
|
||||||
i = locals->args.to_sequence()->begin();
|
i = locals->args.sequence()->begin();
|
||||||
i != locals->args.to_sequence()->end();
|
i != locals->args.sequence()->end();
|
||||||
i++)
|
i++)
|
||||||
arglist.append(*i);
|
arglist.append(*i);
|
||||||
|
|
||||||
|
|
@ -155,10 +155,10 @@ void python_interpreter_t::lambda_t::operator()(value_t& result,
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
assert(locals->args.type == value_t::SEQUENCE);
|
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];
|
value_t item = locals->args[0];
|
||||||
assert(item.type == value_t::POINTER);
|
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&) {
|
catch (const error_already_set&) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,16 @@ void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
|
||||||
if (locals->args.size() < 2)
|
if (locals->args.size() < 2)
|
||||||
throw_(std::logic_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
|
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];
|
long wid = locals->args[1];
|
||||||
|
|
||||||
elision_style_t style = session->elision_style;
|
elision_style_t style = session->elision_style;
|
||||||
if (locals->args.size() == 3)
|
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;
|
long abbrev_len = session->abbrev_length;
|
||||||
if (locals->args.size() == 4)
|
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));
|
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)
|
if (locals->args.size() < 1)
|
||||||
throw_(std::logic_error, "usage: ftime(DATE [, DATE_FORMAT])");
|
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;
|
string date_format;
|
||||||
if (locals->args.size() == 2)
|
if (locals->args.size() == 2)
|
||||||
date_format = locals->args[1].to_string();
|
date_format = locals->args[1].string_value();
|
||||||
#if 0
|
#if 0
|
||||||
// jww (2007-04-18): Need to setup an output facet here
|
// jww (2007-04-18): Need to setup an output facet here
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -60,18 +60,18 @@ class report_t : public xml::xpath_t::scope_t
|
||||||
xml::xpath_t(expr).compile((xml::document_t *)NULL, this);
|
xml::xpath_t(expr).compile((xml::document_t *)NULL, this);
|
||||||
}
|
}
|
||||||
void option_eval(value_t&, xml::xpath_t::scope_t * locals) {
|
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) {
|
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) {
|
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) {
|
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&) {
|
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) {
|
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
|
#if 0
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ parse_amount_expr(std::istream& in, journal_t *,
|
||||||
}
|
}
|
||||||
#endif
|
#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 << ": " <<
|
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||||
"The transaction amount is " << amount);
|
"The transaction amount is " << amount);
|
||||||
|
|
|
||||||
92
src/value.cc
92
src/value.cc
|
|
@ -3,84 +3,93 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
bool value_t::to_boolean() const
|
bool& value_t::boolean()
|
||||||
{
|
{
|
||||||
if (type == BOOLEAN) {
|
if (type == BOOLEAN) {
|
||||||
return *(bool *) data;
|
return *(bool *) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not a boolean");
|
||||||
value_t temp(*this);
|
value_t temp(*this);
|
||||||
temp.in_place_cast(BOOLEAN);
|
temp.in_place_cast(BOOLEAN);
|
||||||
return *(bool *) temp.data;
|
return *(bool *) temp.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long value_t::to_integer() const
|
long& value_t::integer()
|
||||||
{
|
{
|
||||||
if (type == INTEGER) {
|
if (type == INTEGER) {
|
||||||
return *(long *) data;
|
return *(long *) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not an integer");
|
||||||
value_t temp(*this);
|
value_t temp(*this);
|
||||||
temp.in_place_cast(INTEGER);
|
temp.in_place_cast(INTEGER);
|
||||||
return *(long *) temp.data;
|
return *(long *) temp.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
moment_t value_t::to_datetime() const
|
moment_t& value_t::datetime()
|
||||||
{
|
{
|
||||||
if (type == DATETIME) {
|
if (type == DATETIME) {
|
||||||
return *(moment_t *) data;
|
return *(moment_t *) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not a date/time");
|
||||||
value_t temp(*this);
|
value_t temp(*this);
|
||||||
temp.in_place_cast(DATETIME);
|
temp.in_place_cast(DATETIME);
|
||||||
return *(moment_t *) temp.data;
|
return *(moment_t *) temp.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
amount_t value_t::to_amount() const
|
amount_t& value_t::amount()
|
||||||
{
|
{
|
||||||
if (type == AMOUNT) {
|
if (type == AMOUNT) {
|
||||||
return *(amount_t *) data;
|
return *(amount_t *) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not an amount");
|
||||||
value_t temp(*this);
|
value_t temp(*this);
|
||||||
temp.in_place_cast(AMOUNT);
|
temp.in_place_cast(AMOUNT);
|
||||||
return *(amount_t *) temp.data;
|
return *(amount_t *) temp.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
balance_t value_t::to_balance() const
|
balance_t& value_t::balance()
|
||||||
{
|
{
|
||||||
if (type == BALANCE) {
|
if (type == BALANCE) {
|
||||||
return *(balance_t *) data;
|
return *(balance_t *) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not a balance");
|
||||||
value_t temp(*this);
|
value_t temp(*this);
|
||||||
temp.in_place_cast(BALANCE);
|
temp.in_place_cast(BALANCE);
|
||||||
return *(balance_t *) temp.data;
|
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) {
|
if (type == BALANCE_PAIR) {
|
||||||
return *(balance_pair_t *) data;
|
return *(balance_pair_t *) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not a balance pair");
|
||||||
value_t temp(*this);
|
value_t temp(*this);
|
||||||
temp.in_place_cast(BALANCE_PAIR);
|
temp.in_place_cast(BALANCE_PAIR);
|
||||||
return *(balance_pair_t *) temp.data;
|
return *(balance_pair_t *) temp.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string value_t::to_string() const
|
string& value_t::string_value()
|
||||||
{
|
{
|
||||||
if (type == STRING) {
|
if (type == STRING) {
|
||||||
return **(string **) data;
|
return **(string **) data;
|
||||||
} else {
|
} else {
|
||||||
|
throw_(value_error, "Value is not a string");
|
||||||
|
#if 0
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << *this;
|
out << *this;
|
||||||
return out.str();
|
return out.str();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xml::node_t * value_t::to_xml_node() const
|
xml::node_t *& value_t::xml_node()
|
||||||
{
|
{
|
||||||
if (type == XML_NODE)
|
if (type == XML_NODE)
|
||||||
return *(xml::node_t **) data;
|
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");
|
throw_(value_error, "Value is not an XML node");
|
||||||
}
|
}
|
||||||
|
|
||||||
void * value_t::to_pointer() const
|
void *& value_t::pointer()
|
||||||
{
|
{
|
||||||
if (type == POINTER)
|
if (type == POINTER)
|
||||||
return *(void **) data;
|
return *(void **) data;
|
||||||
|
|
@ -96,7 +105,7 @@ void * value_t::to_pointer() const
|
||||||
throw_(value_error, "Value is not a pointer");
|
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)
|
if (type == SEQUENCE)
|
||||||
return *(sequence_t **) data;
|
return *(sequence_t **) data;
|
||||||
|
|
@ -352,7 +361,7 @@ value_t& value_t::operator+=(const value_t& val)
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
*((balance_t *) data) += *((long *) val.data);
|
*((balance_t *) data) += amount_t(*((long *) val.data));
|
||||||
break;
|
break;
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
*((balance_t *) data) += *((amount_t *) val.data);
|
*((balance_t *) data) += *((amount_t *) val.data);
|
||||||
|
|
@ -375,7 +384,7 @@ value_t& value_t::operator+=(const value_t& val)
|
||||||
case BALANCE_PAIR:
|
case BALANCE_PAIR:
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
*((balance_pair_t *) data) += *((long *) val.data);
|
*((balance_pair_t *) data) += amount_t(*((long *) val.data));
|
||||||
break;
|
break;
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
*((balance_pair_t *) data) += *((amount_t *) val.data);
|
*((balance_pair_t *) data) += *((amount_t *) val.data);
|
||||||
|
|
@ -536,7 +545,7 @@ value_t& value_t::operator-=(const value_t& val)
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
*((balance_t *) data) -= *((long *) val.data);
|
*((balance_t *) data) -= amount_t(*((long *) val.data));
|
||||||
break;
|
break;
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
*((balance_t *) data) -= *((amount_t *) val.data);
|
*((balance_t *) data) -= *((amount_t *) val.data);
|
||||||
|
|
@ -557,7 +566,7 @@ value_t& value_t::operator-=(const value_t& val)
|
||||||
case BALANCE_PAIR:
|
case BALANCE_PAIR:
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
*((balance_pair_t *) data) -= *((long *) val.data);
|
*((balance_pair_t *) data) -= amount_t(*((long *) val.data));
|
||||||
break;
|
break;
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
*((balance_pair_t *) data) -= *((amount_t *) val.data);
|
*((balance_pair_t *) data) -= *((amount_t *) val.data);
|
||||||
|
|
@ -686,7 +695,7 @@ value_t& value_t::operator*=(const value_t& val)
|
||||||
case BALANCE_PAIR:
|
case BALANCE_PAIR:
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
*((balance_pair_t *) data) *= *((long *) val.data);
|
*((balance_pair_t *) data) *= amount_t(*((long *) val.data));
|
||||||
break;
|
break;
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
*((balance_pair_t *) data) *= *((amount_t *) val.data);
|
*((balance_pair_t *) data) *= *((amount_t *) val.data);
|
||||||
|
|
@ -833,7 +842,7 @@ value_t& value_t::operator/=(const value_t& val)
|
||||||
case BALANCE_PAIR:
|
case BALANCE_PAIR:
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
*((balance_pair_t *) data) /= *((long *) val.data);
|
*((balance_pair_t *) data) /= amount_t(*((long *) val.data));
|
||||||
break;
|
break;
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
*((balance_pair_t *) data) /= *((amount_t *) val.data);
|
*((balance_pair_t *) data) /= *((amount_t *) val.data);
|
||||||
|
|
@ -884,7 +893,7 @@ value_t::operator bool() const
|
||||||
case STRING:
|
case STRING:
|
||||||
return ! (**((string **) data)).empty();
|
return ! (**((string **) data)).empty();
|
||||||
case XML_NODE:
|
case XML_NODE:
|
||||||
return (*(xml::node_t **) data)->to_value().to_boolean();
|
return (*(xml::node_t **) data)->to_value().boolean();
|
||||||
case POINTER:
|
case POINTER:
|
||||||
return *(void **) data != NULL;
|
return *(void **) data != NULL;
|
||||||
case SEQUENCE:
|
case SEQUENCE:
|
||||||
|
|
@ -1032,10 +1041,18 @@ value_t::operator string() const
|
||||||
}
|
}
|
||||||
#endif
|
#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));
|
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
|
int value_t::compare(const value_t& val) const
|
||||||
{
|
{
|
||||||
if (val.type == XML_NODE)
|
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));
|
return amount_t(*((long *) data)).compare(*((amount_t *) val.data));
|
||||||
|
|
||||||
case BALANCE:
|
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:
|
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:
|
case STRING:
|
||||||
throw_(value_error, "Cannot compare an integer to a 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");
|
throw_(value_error, "Cannot compare a date/time to an integer");
|
||||||
|
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
return (*((moment_t *) data) < *((moment_t *) val.data) ? -1 :
|
return compare_equality(*((moment_t *) data), *((moment_t *) val.data));
|
||||||
(*((moment_t *) data) > *((moment_t *) val.data) ? 1 : 0));
|
|
||||||
|
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
throw_(value_error, "Cannot compare a date/time to an 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));
|
return ((amount_t *) data)->compare(*((amount_t *) val.data));
|
||||||
|
|
||||||
case BALANCE:
|
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:
|
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:
|
case STRING:
|
||||||
throw_(value_error, "Cannot compare an amount to a 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");
|
throw_(value_error, "Cannot compare a balance to a boolean");
|
||||||
|
|
||||||
case INTEGER:
|
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:
|
case DATETIME:
|
||||||
throw_(value_error, "Cannot compare a balance to a date/time");
|
throw_(value_error, "Cannot compare a balance to a date/time");
|
||||||
|
|
||||||
case AMOUNT:
|
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:
|
case BALANCE:
|
||||||
return ((balance_t *) data)->compare(*((balance_t *) val.data));
|
return compare_equality(*(balance_t *) data, *((balance_t *) val.data));
|
||||||
|
|
||||||
case BALANCE_PAIR:
|
case BALANCE_PAIR:
|
||||||
return balance_pair_t(*((balance_t *) data)).
|
return compare_equality(balance_pair_t(*((balance_t *) data)),
|
||||||
compare(((balance_pair_t *) val.data)->quantity);
|
*(balance_pair_t *) val.data);
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
throw_(value_error, "Cannot compare a balance to a 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");
|
throw_(value_error, "Cannot compare a balance pair to a boolean");
|
||||||
|
|
||||||
case INTEGER:
|
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:
|
case DATETIME:
|
||||||
throw_(value_error, "Cannot compare a balance pair to a date/time");
|
throw_(value_error, "Cannot compare a balance pair to a date/time");
|
||||||
|
|
||||||
case AMOUNT:
|
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:
|
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:
|
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:
|
case STRING:
|
||||||
throw_(value_error, "Cannot compare a balance pair to a 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
|
// fact that logic chains only need boolean values to continue, no
|
||||||
// memory allocations need to take place at all.
|
// 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:
|
public:
|
||||||
typedef std::vector<value_t> sequence_t;
|
typedef std::vector<value_t> sequence_t;
|
||||||
|
|
||||||
char data[sizeof(balance_pair_t)];
|
|
||||||
|
|
||||||
enum type_t {
|
enum type_t {
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
INTEGER,
|
INTEGER,
|
||||||
|
|
@ -124,6 +131,7 @@ class value_t : public ordered_field_operators<value_t>
|
||||||
void simplify();
|
void simplify();
|
||||||
|
|
||||||
value_t& operator=(const value_t& val);
|
value_t& operator=(const value_t& val);
|
||||||
|
#if 0
|
||||||
value_t& operator=(const bool val) {
|
value_t& operator=(const bool val) {
|
||||||
if ((bool *) data != &val) {
|
if ((bool *) data != &val) {
|
||||||
destroy();
|
destroy();
|
||||||
|
|
@ -258,6 +266,7 @@ class value_t : public ordered_field_operators<value_t>
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
value_t& set_string(const string& str = "") {
|
value_t& set_string(const string& str = "") {
|
||||||
if (type != STRING) {
|
if (type != STRING) {
|
||||||
|
|
@ -270,31 +279,31 @@ class value_t : public ordered_field_operators<value_t>
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool to_boolean() const;
|
bool& boolean();
|
||||||
long to_integer() const;
|
long& integer();
|
||||||
moment_t to_datetime() const;
|
moment_t& datetime();
|
||||||
amount_t to_amount() const;
|
amount_t& amount();
|
||||||
balance_t to_balance() const;
|
balance_t& balance();
|
||||||
balance_pair_t to_balance_pair() const;
|
balance_pair_t& balance_pair();
|
||||||
string to_string() const;
|
string& string_value();
|
||||||
xml::node_t * to_xml_node() const;
|
xml::node_t *& xml_node();
|
||||||
void * to_pointer() const;
|
void *& pointer();
|
||||||
sequence_t * to_sequence() const;
|
sequence_t *& sequence();
|
||||||
|
|
||||||
value_t& operator[](const int index) {
|
value_t& operator[](const int index) {
|
||||||
sequence_t * seq = to_sequence();
|
sequence_t * seq = sequence();
|
||||||
assert(seq);
|
assert(seq);
|
||||||
return (*seq)[index];
|
return (*seq)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_back(const value_t& val) {
|
void push_back(const value_t& val) {
|
||||||
sequence_t * seq = to_sequence();
|
sequence_t * seq = sequence();
|
||||||
assert(seq);
|
assert(seq);
|
||||||
return seq->push_back(val);
|
return seq->push_back(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size() const {
|
std::size_t size() const {
|
||||||
sequence_t * seq = to_sequence();
|
sequence_t * seq = const_cast<value_t&>(*this).sequence();
|
||||||
assert(seq);
|
assert(seq);
|
||||||
return seq->size();
|
return seq->size();
|
||||||
}
|
}
|
||||||
|
|
@ -309,18 +318,22 @@ class value_t : public ordered_field_operators<value_t>
|
||||||
bool operator==(const value_t& val) const {
|
bool operator==(const value_t& val) const {
|
||||||
return compare(val) == 0;
|
return compare(val) == 0;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool operator==(const T& val) const {
|
bool operator==(const T& val) const {
|
||||||
return *this == value_t(val);
|
return *this == value_t(val);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool operator<(const value_t& val) const {
|
bool operator<(const value_t& val) const {
|
||||||
return compare(val) < 0;
|
return compare(val) < 0;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool operator<(const T& val) const {
|
bool operator<(const T& val) const {
|
||||||
return *this < value_t(val);
|
return *this < value_t(val);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
|
|
@ -336,15 +349,15 @@ class value_t : public ordered_field_operators<value_t>
|
||||||
operator balance_pair_t() const;
|
operator balance_pair_t() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void in_place_negate();
|
value_t operator-() const {
|
||||||
|
return negate();
|
||||||
|
}
|
||||||
value_t negate() const {
|
value_t negate() const {
|
||||||
value_t temp = *this;
|
value_t temp = *this;
|
||||||
temp.in_place_negate();
|
temp.in_place_negate();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
value_t operator-() const {
|
void in_place_negate();
|
||||||
return negate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool realzero() const;
|
bool realzero() const;
|
||||||
value_t abs() 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,
|
void write(std::ostream& out, const int first_width,
|
||||||
const int latter_width = -1) const;
|
const int latter_width = -1) const;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& out, const value_t& val);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#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':
|
case 't':
|
||||||
if (name == "text") {
|
if (name == "text") {
|
||||||
if (value->type == value_t::XML_NODE)
|
if (value->type == value_t::XML_NODE)
|
||||||
result.set_string(value->to_xml_node()->text());
|
result.set_string(value->xml_node()->text());
|
||||||
else
|
else
|
||||||
throw_(calc_error, "Attempt to call text() on a non-node value");
|
throw_(calc_error, "Attempt to call text() on a non-node value");
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -650,7 +650,7 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
|
||||||
#endif /* USE_BOOST_PYTHON */
|
#endif /* USE_BOOST_PYTHON */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
string ident = tok.value.to_string();
|
string ident = tok.value.string_value();
|
||||||
int id = -1;
|
int id = -1;
|
||||||
if (std::isdigit(ident[0])) {
|
if (std::isdigit(ident[0])) {
|
||||||
node.reset(new op_t(op_t::ARG_INDEX));
|
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");
|
throw_(parse_error, "@ symbol must be followed by attribute name");
|
||||||
|
|
||||||
node.reset(new op_t(op_t::ATTR_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;
|
break;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -1184,7 +1184,7 @@ void xpath_t::op_t::find_values(value_t * context, scope_t * scope,
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
if (context->type == value_t::XML_NODE) {
|
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) {
|
if (ptr->flags & XML_NODE_IS_PARENT) {
|
||||||
parent_node_t * parent = static_cast<parent_node_t *>(ptr);
|
parent_node_t * parent = static_cast<parent_node_t *>(ptr);
|
||||||
for (node_t * node = parent->children();
|
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) {
|
switch (expr->valuep->type) {
|
||||||
case value_t::INTEGER:
|
case value_t::INTEGER:
|
||||||
case value_t::AMOUNT:
|
case value_t::AMOUNT:
|
||||||
return *expr->valuep == (long)index + 1;
|
return *expr->valuep == value_t((long)index + 1);
|
||||||
|
|
||||||
default:
|
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)
|
if ((*i).type != value_t::POINTER)
|
||||||
*opp = wrap_value(*i)->acquire();
|
*opp = wrap_value(*i)->acquire();
|
||||||
else
|
else
|
||||||
*opp = static_cast<op_t *>((*i).to_pointer());
|
*opp = static_cast<op_t *>((*i).pointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
return lit_seq.release();
|
return lit_seq.release();
|
||||||
|
|
@ -1256,7 +1256,7 @@ void xpath_t::op_t::append_value(value_t& val,
|
||||||
value_t::sequence_t& result_seq)
|
value_t::sequence_t& result_seq)
|
||||||
{
|
{
|
||||||
if (val.type == value_t::SEQUENCE) {
|
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();
|
for (value_t::sequence_t::iterator i = subseq->begin();
|
||||||
i != subseq->end();
|
i != subseq->end();
|
||||||
i++)
|
i++)
|
||||||
|
|
@ -1284,8 +1284,8 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
||||||
case document_t::PARENT:
|
case document_t::PARENT:
|
||||||
if (context->type != value_t::XML_NODE)
|
if (context->type != value_t::XML_NODE)
|
||||||
throw_(compile_error, "Referencing parent node from a non-node value");
|
throw_(compile_error, "Referencing parent node from a non-node value");
|
||||||
else if (context->to_xml_node()->parent)
|
else if (context->xml_node()->parent)
|
||||||
return wrap_value(context->to_xml_node()->parent)->acquire();
|
return wrap_value(context->xml_node()->parent)->acquire();
|
||||||
else
|
else
|
||||||
throw_(compile_error, "Referencing parent node from the root node");
|
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)
|
if (context->type != value_t::XML_NODE)
|
||||||
throw_(compile_error, "Referencing root node from a non-node value");
|
throw_(compile_error, "Referencing root node from a non-node value");
|
||||||
else
|
else
|
||||||
return wrap_value(context->to_xml_node()->document->top)->acquire();
|
return wrap_value(context->xml_node()->document->top)->acquire();
|
||||||
|
|
||||||
case document_t::ALL: {
|
case document_t::ALL: {
|
||||||
if (context->type != value_t::XML_NODE)
|
if (context->type != value_t::XML_NODE)
|
||||||
throw_(compile_error, "Referencing child nodes from a non-node value");
|
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))
|
if (! (ptr->flags & XML_NODE_IS_PARENT))
|
||||||
throw_(compile_error, "Request for child nodes of a leaf node");
|
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:
|
case NODE_NAME:
|
||||||
if (context->type == value_t::XML_NODE) {
|
if (context->type == value_t::XML_NODE) {
|
||||||
node_t * ptr = context->to_xml_node();
|
node_t * ptr = context->xml_node();
|
||||||
if (resolve) {
|
if (resolve) {
|
||||||
// First, look up the symbol as a node name within the current
|
// First, look up the symbol as a node name within the current
|
||||||
// context. If any exist, then return the set of names.
|
// 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: {
|
case ATTR_NAME: {
|
||||||
// jww (2006-09-29): Attrs should map strings to values, not strings
|
// 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();
|
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:
|
case ARG_INDEX:
|
||||||
if (scope && scope->kind == scope_t::ARGUMENT) {
|
if (scope && scope->kind == scope_t::ARGUMENT) {
|
||||||
assert(scope->args.type == value_t::SEQUENCE);
|
assert(scope->args.type == value_t::SEQUENCE);
|
||||||
if (arg_index < scope->args.to_sequence()->size())
|
if (arg_index < scope->args.sequence()->size())
|
||||||
return wrap_value((*scope->args.to_sequence())[arg_index])->acquire();
|
return wrap_value((*scope->args.sequence())[arg_index])->acquire();
|
||||||
else
|
else
|
||||||
throw_(compile_error, "Reference to non-existing argument");
|
throw_(compile_error, "Reference to non-existing argument");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1815,7 +1815,7 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::SEQUENCE: {
|
case value_t::SEQUENCE: {
|
||||||
value_t::sequence_t * seq = lexpr->valuep->to_sequence();
|
value_t::sequence_t * seq = lexpr->valuep->sequence();
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (value_t::sequence_t::iterator i = seq->begin();
|
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>
|
template <typename T>
|
||||||
inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
||||||
assert(locals->args.size() > 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);
|
assert(ptr);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue