*** no comment ***

This commit is contained in:
John Wiegley 2006-03-04 14:17:26 +00:00
parent 2034d6640c
commit 6375730fc9
6 changed files with 545 additions and 258 deletions

2
acprep
View file

@ -17,7 +17,7 @@ fi
autoconf
INCDIRS="-I/sw/include -I/usr/local/include/boost-1_33 -I/usr/include/httpd/xml"
INCDIRS="$INCDIRS -I/sw/include/libofx"
#INCDIRS="$INCDIRS -I/sw/include/libofx"
INCDIRS="$INCDIRS -Wno-long-double"
LIBDIRS="-L/sw/lib -L/usr/local/lib"

View file

@ -94,8 +94,7 @@ balance_t& balance_t::operator*=(const balance_t& bal)
return *this *= (*bal.amounts.begin()).second;
}
else {
std::string msg;
std::ostringstream errmsg(msg);
std::ostringstream errmsg;
errmsg << "It makes no sense to multiply two balances: "
<< *this << " * " << bal;
throw amount_error(errmsg.str());
@ -108,8 +107,7 @@ balance_t& balance_t::operator/=(const balance_t& bal)
return (*this = 0L);
}
else if (! bal) {
std::string msg;
std::ostringstream errmsg(msg);
std::ostringstream errmsg;
errmsg << "Attempt to divide by zero: " << *this << " / " << bal;
throw amount_error(errmsg.str());
}
@ -120,8 +118,7 @@ balance_t& balance_t::operator/=(const balance_t& bal)
return (*this = 1L);
}
else {
std::string msg;
std::ostringstream errmsg(msg);
std::ostringstream errmsg;
errmsg << "It makes no sense to divide two balances: "
<< *this << " / " << bal;
throw amount_error(errmsg.str());
@ -137,8 +134,7 @@ balance_t::operator amount_t() const
return amount_t();
}
else {
std::string msg;
std::ostringstream errmsg(msg);
std::ostringstream errmsg;
errmsg << "Cannot convert a balance with "
<< "multiple commodities to an amount: " << *this;
throw amount_error(errmsg.str());

View file

@ -97,10 +97,14 @@ class balance_t
}
balance_t& operator-=(const amount_t& amt) {
amounts_map::iterator i = amounts.find(&amt.commodity());
if (i != amounts.end())
if (i != amounts.end()) {
(*i).second -= amt;
else if (amt)
if (! (*i).second)
amounts.erase(&amt.commodity());
}
else if (amt) {
amounts.insert(amounts_pair(&amt.commodity(), - amt));
}
return *this;
}
template <typename T>
@ -147,7 +151,10 @@ class balance_t
balance_t& operator*=(const amount_t& amt) {
// Multiplying by the null commodity causes all amounts to be
// increased by the same factor.
if (amt.commodity().symbol.empty()) {
if (! amt) {
amounts.clear();
}
else if (! amt.commodity()) {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)
@ -172,7 +179,7 @@ class balance_t
balance_t& operator/=(const amount_t& amt) {
// Dividing by the null commodity causes all amounts to be
// increased by the same factor.
if (amt.commodity().symbol.empty()) {
if (! amt.commodity()) {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)

View file

@ -2,6 +2,7 @@
#include "datetime.h"
#include "error.h"
#include "mask.h"
#include "walk.h"
#include <memory>
@ -47,10 +48,31 @@ entry_t * derive_new_entry(journal_t& journal,
i++;
}
if (i == end)
if (i == end) {
added->add_transaction(new transaction_t(acct));
else
added->add_transaction(new transaction_t(acct, amount_t(*i++)));
} else {
transaction_t * xact = new transaction_t(acct, amount_t(*i++));
added->add_transaction(xact);
if (! xact->amount.commodity()) {
// If the amount has no commodity, we can determine it given
// the account by creating a final for the account and then
// checking if it contains only a single commodity. An
// account to which only dollars are applied would imply that
// dollars are wanted now too.
std::auto_ptr<item_handler<transaction_t> > formatter;
formatter.reset(new set_account_value);
walk_entries(journal.entries, *formatter.get());
formatter->flush();
sum_accounts(*journal.master);
value_t total = account_xdata(*acct).total;
if (total.type == value_t::AMOUNT)
xact->amount.set_commodity(((amount_t *) total.data)->commodity());
}
}
if (journal.basket)
acct = journal.basket;

745
value.cc
View file

@ -19,6 +19,27 @@ void value_t::destroy()
}
}
void value_t::simplify()
{
if (! *this) {
*this = 0L;
return;
}
if (type == BALANCE_PAIR &&
(! ((balance_pair_t *) data)->cost ||
! *((balance_pair_t *) data)->cost))
cast(BALANCE);
if (type == BALANCE &&
((balance_t *) data)->amounts.size() == 1)
cast(AMOUNT);
if (type == AMOUNT &&
! ((amount_t *) data)->commodity())
cast(INTEGER);
}
value_t& value_t::operator=(const value_t& value)
{
if (this == &value)
@ -57,253 +78,493 @@ value_t& value_t::operator=(const value_t& value)
return *this;
}
#define DEF_VALUE_ADDSUB_OP(OP) \
value_t& value_t::operator OP(const value_t& value) \
{ \
switch (type) { \
case BOOLEAN: \
case INTEGER: \
cast(INTEGER); \
switch (value.type) { \
case BOOLEAN: \
*((long *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((long *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
cast(AMOUNT); \
*((amount_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
cast(BALANCE); \
*((balance_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
cast(BALANCE_PAIR); \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
case AMOUNT: \
switch (value.type) { \
case BOOLEAN: \
if (*((bool *) value.data) && \
((amount_t *) data)->commodity()) { \
cast(BALANCE); \
return *this OP value; \
} \
*((amount_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
\
case INTEGER: \
if (*((long *) value.data) && \
((amount_t *) data)->commodity()) { \
cast(BALANCE); \
return *this OP value; \
} \
*((amount_t *) data) OP *((long *) value.data); \
break; \
\
case AMOUNT: \
if (((amount_t *) data)->commodity() != \
((amount_t *) value.data)->commodity()) { \
cast(BALANCE); \
return *this OP value; \
} \
*((amount_t *) data) OP *((amount_t *) value.data); \
break; \
\
case BALANCE: \
cast(BALANCE); \
*((balance_t *) data) OP *((balance_t *) value.data); \
break; \
\
case BALANCE_PAIR: \
cast(BALANCE_PAIR); \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
\
default: \
assert(0); \
break; \
} \
break; \
\
case BALANCE: \
switch (value.type) { \
case BOOLEAN: \
*((balance_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((balance_t *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
*((balance_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
*((balance_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
cast(BALANCE_PAIR); \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
case BALANCE_PAIR: \
switch (value.type) { \
case BOOLEAN: \
*((balance_pair_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((balance_pair_t *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
*((balance_pair_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
*((balance_pair_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
default: \
assert(0); \
break; \
} \
return *this; \
value_t& value_t::operator+=(const value_t& value)
{
switch (type) {
case BOOLEAN:
case INTEGER:
cast(INTEGER);
switch (value.type) {
case BOOLEAN:
*((long *) data) += (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((long *) data) += *((long *) value.data);
break;
case AMOUNT:
cast(AMOUNT);
*((amount_t *) data) += *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) += *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) += *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (value.type) {
case BOOLEAN:
if (*((bool *) value.data) &&
((amount_t *) data)->commodity()) {
cast(BALANCE);
return *this += value;
}
*((amount_t *) data) += (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
if (*((long *) value.data) &&
((amount_t *) data)->commodity()) {
cast(BALANCE);
return *this += value;
}
*((amount_t *) data) += *((long *) value.data);
break;
case AMOUNT:
if (((amount_t *) data)->commodity() !=
((amount_t *) value.data)->commodity()) {
cast(BALANCE);
return *this += value;
}
*((amount_t *) data) += *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) += *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) += *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (value.type) {
case BOOLEAN:
*((balance_t *) data) += (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_t *) data) += *((long *) value.data);
break;
case AMOUNT:
*((balance_t *) data) += *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) += *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) += *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE_PAIR:
switch (value.type) {
case BOOLEAN:
*((balance_pair_t *) data) += (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_pair_t *) data) += *((long *) value.data);
break;
case AMOUNT:
*((balance_pair_t *) data) += *((amount_t *) value.data);
break;
case BALANCE:
*((balance_pair_t *) data) += *((balance_t *) value.data);
break;
case BALANCE_PAIR:
*((balance_pair_t *) data) += *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
DEF_VALUE_ADDSUB_OP(+=)
DEF_VALUE_ADDSUB_OP(-=)
value_t& value_t::operator-=(const value_t& value)
{
switch (type) {
case BOOLEAN:
case INTEGER:
cast(INTEGER);
switch (value.type) {
case BOOLEAN:
*((long *) data) -= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((long *) data) -= *((long *) value.data);
break;
case AMOUNT:
cast(AMOUNT);
*((amount_t *) data) -= *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) -= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
#define DEF_VALUE_MULDIV_OP(OP) \
value_t& value_t::operator OP(const value_t& value) \
{ \
switch (type) { \
case BOOLEAN: \
case INTEGER: \
cast(INTEGER); \
switch (value.type) { \
case BOOLEAN: \
*((long *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((long *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
cast(AMOUNT); \
*((amount_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
cast(BALANCE); \
*((balance_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
cast(BALANCE_PAIR); \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
case AMOUNT: \
switch (value.type) { \
case BOOLEAN: \
*((amount_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((amount_t *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
*((amount_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
cast(BALANCE); \
*((balance_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
cast(BALANCE_PAIR); \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
case BALANCE: \
switch (value.type) { \
case BOOLEAN: \
*((balance_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((balance_t *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
*((balance_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
*((balance_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
cast(BALANCE_PAIR); \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
case BALANCE_PAIR: \
switch (value.type) { \
case BOOLEAN: \
*((balance_pair_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \
break; \
case INTEGER: \
*((balance_pair_t *) data) OP *((long *) value.data); \
break; \
case AMOUNT: \
*((balance_pair_t *) data) OP *((amount_t *) value.data); \
break; \
case BALANCE: \
*((balance_pair_t *) data) OP *((balance_t *) value.data); \
break; \
case BALANCE_PAIR: \
*((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
break; \
default: \
assert(0); \
break; \
} \
break; \
\
default: \
assert(0); \
break; \
} \
return *this; \
case AMOUNT:
switch (value.type) {
case BOOLEAN:
if (*((bool *) value.data) &&
((amount_t *) data)->commodity()) {
cast(BALANCE);
return *this -= value;
}
*((amount_t *) data) -= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
if (*((long *) value.data) &&
((amount_t *) data)->commodity()) {
cast(BALANCE);
return *this -= value;
}
*((amount_t *) data) -= *((long *) value.data);
break;
case AMOUNT:
if (((amount_t *) data)->commodity() !=
((amount_t *) value.data)->commodity()) {
cast(BALANCE);
return *this -= value;
}
*((amount_t *) data) -= *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) -= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (value.type) {
case BOOLEAN:
*((balance_t *) data) -= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_t *) data) -= *((long *) value.data);
break;
case AMOUNT:
*((balance_t *) data) -= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) -= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE_PAIR:
switch (value.type) {
case BOOLEAN:
*((balance_pair_t *) data) -= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_pair_t *) data) -= *((long *) value.data);
break;
case AMOUNT:
*((balance_pair_t *) data) -= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_pair_t *) data) -= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
*((balance_pair_t *) data) -= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
simplify();
return *this;
}
DEF_VALUE_MULDIV_OP(*=)
DEF_VALUE_MULDIV_OP(/=)
value_t& value_t::operator*=(const value_t& value)
{
if (! value) {
*this = 0L;
return *this;
}
switch (type) {
case BOOLEAN:
case INTEGER:
cast(INTEGER);
switch (value.type) {
case BOOLEAN:
*((long *) data) *= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((long *) data) *= *((long *) value.data);
break;
case AMOUNT:
cast(AMOUNT);
*((amount_t *) data) *= *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) *= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (value.type) {
case BOOLEAN:
*((amount_t *) data) *= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((amount_t *) data) *= *((long *) value.data);
break;
case AMOUNT:
*((amount_t *) data) *= *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) *= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (value.type) {
case BOOLEAN:
*((balance_t *) data) *= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_t *) data) *= *((long *) value.data);
break;
case AMOUNT:
*((balance_t *) data) *= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) *= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE_PAIR:
switch (value.type) {
case BOOLEAN:
*((balance_pair_t *) data) *= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_pair_t *) data) *= *((long *) value.data);
break;
case AMOUNT:
*((balance_pair_t *) data) *= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_pair_t *) data) *= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
*((balance_pair_t *) data) *= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
value_t& value_t::operator/=(const value_t& value)
{
switch (type) {
case BOOLEAN:
case INTEGER:
cast(INTEGER);
switch (value.type) {
case BOOLEAN:
*((long *) data) /= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((long *) data) /= *((long *) value.data);
break;
case AMOUNT:
cast(AMOUNT);
*((amount_t *) data) /= *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) /= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (value.type) {
case BOOLEAN:
*((amount_t *) data) /= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((amount_t *) data) /= *((long *) value.data);
break;
case AMOUNT:
*((amount_t *) data) /= *((amount_t *) value.data);
break;
case BALANCE:
cast(BALANCE);
*((balance_t *) data) /= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (value.type) {
case BOOLEAN:
*((balance_t *) data) /= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_t *) data) /= *((long *) value.data);
break;
case AMOUNT:
*((balance_t *) data) /= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) /= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
cast(BALANCE_PAIR);
*((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE_PAIR:
switch (value.type) {
case BOOLEAN:
*((balance_pair_t *) data) /= (*((bool *) value.data) ? 1L : 0L);
break;
case INTEGER:
*((balance_pair_t *) data) /= *((long *) value.data);
break;
case AMOUNT:
*((balance_pair_t *) data) /= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_pair_t *) data) /= *((balance_t *) value.data);
break;
case BALANCE_PAIR:
*((balance_pair_t *) data) /= *((balance_pair_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
#define DEF_VALUE_CMP_OP(OP) \
bool value_t::operator OP(const value_t& value) \

View file

@ -89,6 +89,7 @@ class value_t
}
void destroy();
void simplify();
value_t& operator=(const value_t& value);
value_t& operator=(const bool value) {