summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--account.cc3
-rw-r--r--amount.cc43
-rw-r--r--amount.h16
-rw-r--r--autoxact.h8
-rw-r--r--balance.cc2
-rw-r--r--balance.h68
-rw-r--r--binary.cc40
-rw-r--r--datetime.h9
-rw-r--r--format.cc11
-rw-r--r--format.h11
-rw-r--r--ledger.cc2
-rw-r--r--ledger.h22
-rw-r--r--option.cc2
-rw-r--r--qif.cc2
-rw-r--r--textual.cc25
-rw-r--r--valexpr.cc43
-rw-r--r--valexpr.h40
-rw-r--r--value.cc1026
-rw-r--r--value.h35
-rw-r--r--walk.cc17
-rw-r--r--walk.h9
21 files changed, 606 insertions, 828 deletions
diff --git a/account.cc b/account.cc
index 14d6f037..f04eb55d 100644
--- a/account.cc
+++ b/account.cc
@@ -5,10 +5,9 @@
namespace ledger {
-account_t::ident_t account_t::next_ident;
-
account_t::~account_t()
{
+ DEBUG_PRINT("ledger.memory.ctors", "dtor account_t");
for (accounts_map::iterator i = accounts.begin();
i != accounts.end();
i++)
diff --git a/amount.cc b/amount.cc
index 3417986c..ed51f356 100644
--- a/amount.cc
+++ b/amount.cc
@@ -10,21 +10,6 @@
namespace ledger {
-#ifdef DEBUG_ENABLED
-int bigint_ctors = 0;
-int bigint_dtors = 0;
-#endif
-
-#ifdef DEBUG_ENABLED
-static struct ctor_dtor_info {
- ~ctor_dtor_info() {
- DEBUG_CLASS("ledger.amount.bigint");
- DEBUG_PRINT_("bigint_t ctor count = " << bigint_ctors);
- DEBUG_PRINT_("bigint_t dtor count = " << bigint_dtors);
- }
-} __info;
-#endif
-
class amount_t::bigint_t {
public:
mpz_t val;
@@ -33,37 +18,21 @@ class amount_t::bigint_t {
unsigned int index;
bigint_t() : prec(0), ref(1), index(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t");
mpz_init(val);
-#ifdef DEBUG_ENABLED
- DEBUG_PRINT("ledger.amount.bigint-show",
- "ctor " << this << " " << bigint_ctors);
- bigint_ctors++;
-#endif
}
bigint_t(mpz_t _val) : prec(0), ref(1), index(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t");
mpz_init_set(val, _val);
-#ifdef DEBUG_ENABLED
- DEBUG_PRINT("ledger.amount.bigint-show",
- "ctor " << this << " " << bigint_ctors);
- bigint_ctors++;
-#endif
}
bigint_t(const bigint_t& other)
: prec(other.prec), ref(1), index(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t");
mpz_init_set(val, other.val);
-#ifdef DEBUG_ENABLED
- DEBUG_PRINT("ledger.amount.bigint-show",
- "ctor " << this << " " << bigint_ctors);
- bigint_ctors++;
-#endif
}
~bigint_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor amount_t::bigint_t");
assert(ref == 0);
-#ifdef DEBUG_ENABLED
- DEBUG_PRINT("ledger.amount.bigint-show",
- "dtor " << this << " " << bigint_dtors);
- bigint_dtors++;
-#endif
mpz_clear(val);
}
};
@@ -150,6 +119,7 @@ static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec)
amount_t::amount_t(const bool value)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
if (value) {
quantity = new bigint_t(true_value);
commodity = commodity_t::null_commodity;
@@ -161,6 +131,7 @@ amount_t::amount_t(const bool value)
amount_t::amount_t(const int value)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
if (value != 0) {
quantity = new bigint_t;
mpz_set_si(MPZ(quantity), value);
@@ -173,6 +144,7 @@ amount_t::amount_t(const int value)
amount_t::amount_t(const unsigned int value)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
if (value != 0) {
quantity = new bigint_t;
mpz_set_ui(MPZ(quantity), value);
@@ -185,6 +157,7 @@ amount_t::amount_t(const unsigned int value)
amount_t::amount_t(const double value)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
if (value != 0.0) {
quantity = new bigint_t;
mpz_set_d(MPZ(quantity), value);
diff --git a/amount.h b/amount.h
index aa38c2e4..3462679c 100644
--- a/amount.h
+++ b/amount.h
@@ -7,6 +7,8 @@
#include <iostream>
#include <sstream>
+#include "debug.h"
+
namespace ledger {
class commodity_t;
@@ -41,18 +43,23 @@ class amount_t
// constructors
amount_t(commodity_t * _commodity = NULL)
- : quantity(NULL), commodity(_commodity) {}
+ : quantity(NULL), commodity(_commodity) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
+ }
amount_t(const amount_t& amt) : quantity(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
if (amt.quantity)
_copy(amt);
else
commodity = NULL;
}
amount_t(const std::string& value) : quantity(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
parse(value);
}
amount_t(const char * value) : quantity(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t");
parse(value);
}
amount_t(const bool value);
@@ -62,6 +69,7 @@ class amount_t
// destructor
~amount_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor amount_t");
if (quantity)
_release();
}
@@ -253,8 +261,14 @@ class commodity_t
unsigned int _flags = COMMODITY_STYLE_DEFAULTS)
: symbol(_symbol), quote(false), precision(_precision),
flags(_flags), last_lookup(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor commodity_t");
check_symbol();
}
+#ifdef DEBUG_ENABLED
+ ~commodity_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor commodity_t");
+ }
+#endif
void check_symbol() {
for (const char * p = symbol.c_str(); *p; p++)
diff --git a/autoxact.h b/autoxact.h
index 76c67c3f..1a6ad3ea 100644
--- a/autoxact.h
+++ b/autoxact.h
@@ -19,6 +19,7 @@ public:
automated_transaction_t(const std::string& _predicate,
transactions_deque& _transactions)
: predicate(_predicate) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor automated_transaction_t");
transactions.insert(transactions.begin(),
_transactions.begin(), _transactions.end());
// Take over ownership of the pointers
@@ -26,6 +27,7 @@ public:
}
~automated_transaction_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor automated_transaction_t");
for (transactions_deque::iterator i = transactions.begin();
i != transactions.end();
i++)
@@ -43,7 +45,13 @@ class automated_transactions_t
public:
automated_transactions_deque automated_transactions;
+#ifdef DEBUG_ENABLED
+ automated_transactions_t() {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor automated_transactions_t");
+ }
+#endif
~automated_transactions_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor automated_transactions_t");
for (automated_transactions_deque::iterator i
= automated_transactions.begin();
i != automated_transactions.end();
diff --git a/balance.cc b/balance.cc
index 3b69904f..7e64124f 100644
--- a/balance.cc
+++ b/balance.cc
@@ -1,3 +1,4 @@
+#include "balance.h"
#include "ledger.h"
#include <deque>
@@ -87,6 +88,7 @@ void balance_t::write(std::ostream& out,
balance_pair_t::balance_pair_t(const transaction_t& xact)
: quantity(xact.amount), cost(NULL)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
if (xact.cost)
cost = new balance_t(*xact.cost);
}
diff --git a/balance.h b/balance.h
index 360bf129..550ecb28 100644
--- a/balance.h
+++ b/balance.h
@@ -27,28 +27,39 @@ class balance_t
}
// constructors
- balance_t() {}
+ balance_t() {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
+ }
balance_t(const balance_t& bal) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end();
i++)
*this += (*i).second;
}
balance_t(const amount_t& amt) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
*this += amt;
}
balance_t(const int value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
*this += amount_t(value);
}
balance_t(const unsigned int value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
*this += amount_t(value);
}
balance_t(const double value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t");
*this += amount_t(value);
}
// destructor
- ~balance_t() {}
+#ifdef DEBUG_ENABLED
+ ~balance_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor balance_t");
+ }
+#endif
// assignment operator
balance_t& operator=(const balance_t& bal) {
@@ -394,34 +405,40 @@ class balance_pair_t
}
// constructors
- balance_pair_t() : cost(NULL) {}
+ balance_pair_t() : cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
+ }
balance_pair_t(const balance_pair_t& bal_pair)
: quantity(bal_pair.quantity), cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
if (bal_pair.cost)
cost = new balance_t(*bal_pair.cost);
}
-#if 0
- balance_pair_t(const balance_t& _quantity, const balance_t& _cost)
- : quantity(_quantity), cost(_cost) {}
-#endif
balance_pair_t(const balance_t& _quantity)
- : quantity(_quantity), cost(NULL) {}
-#if 0
- balance_pair_t(const amount_t& _quantity, const amount_t& _cost)
- : quantity(_quantity), cost(_cost) {}
-#endif
+ : quantity(_quantity), cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
+ }
balance_pair_t(const amount_t& _quantity)
- : quantity(_quantity), cost(NULL) {}
+ : quantity(_quantity), cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
+ }
balance_pair_t(const int value)
- : quantity(value), cost(NULL) {}
+ : quantity(value), cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
+ }
balance_pair_t(const unsigned int value)
- : quantity(value), cost(NULL) {}
+ : quantity(value), cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
+ }
balance_pair_t(const double value)
- : quantity(value), cost(NULL) {}
+ : quantity(value), cost(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t");
+ }
balance_pair_t(const transaction_t& xact);
// destructor
~balance_pair_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor balance_pair_t");
if (cost)
delete cost;
}
@@ -723,15 +740,24 @@ class balance_pair_t
operator bool() const {
return quantity;
}
+ operator balance_t() const {
+ return quantity;
+ }
+ operator amount_t() const {
+ assert(0);
+ return quantity.amount();
+ }
+
+ void abs() {
+ quantity.abs();
+ if (cost)
+ cost->abs();
+ }
};
inline balance_pair_t abs(const balance_pair_t& bal_pair) {
balance_pair_t temp;
- temp.quantity = abs(bal_pair.quantity);
- if (bal_pair.cost) {
- temp.cost = new balance_t;
- *temp.cost = abs(*bal_pair.cost);
- }
+ temp.abs();
return temp;
}
diff --git a/binary.cc b/binary.cc
index 4fb557a5..e336fc12 100644
--- a/binary.cc
+++ b/binary.cc
@@ -9,7 +9,7 @@
namespace ledger {
const unsigned long binary_magic_number = 0xFFEED765;
-static const unsigned long format_version = 0x00020010;
+static const unsigned long format_version = 0x00020011;
bool binary_parser_t::test(std::istream& in) const
{
@@ -21,9 +21,9 @@ bool binary_parser_t::test(std::istream& in) const
}
static std::deque<account_t *> accounts;
-static account_t::ident_t ident;
+static unsigned int account_index;
static std::deque<commodity_t *> commodities;
-static commodity_t::ident_t c_ident;
+static unsigned int commodity_index;
std::deque<amount_t::bigint_t *> bigints;
#if DEBUG_LEVEL >= ALPHA
@@ -84,12 +84,12 @@ inline std::string read_binary_string(std::istream& in)
void read_binary_amount(std::istream& in, amount_t& amt)
{
- commodity_t::ident_t id;
- read_binary_number(in, id);
- if (id == 0xffffffff)
+ commodity_t::ident_t ident;
+ read_binary_number(in, ident);
+ if (ident == 0xffffffff)
amt.commodity = NULL;
else
- amt.commodity = commodities[id];
+ amt.commodity = commodities[ident - 1];
amt.read_quantity(in);
}
@@ -98,7 +98,7 @@ transaction_t * read_binary_transaction(std::istream& in, entry_t * entry)
{
transaction_t * xact = new transaction_t(NULL);
- xact->account = accounts[read_binary_number<account_t::ident_t>(in)];
+ xact->account = accounts[read_binary_number<account_t::ident_t>(in) - 1];
xact->account->add_transaction(xact);
read_binary_amount(in, xact->amount);
@@ -137,7 +137,7 @@ commodity_t * read_binary_commodity(std::istream& in)
commodities.push_back(commodity);
commodity->ident = read_binary_number<commodity_t::ident_t>(in);
- assert(commodity->ident == commodities.size() - 1);
+ assert(commodity->ident == commodities.size());
read_binary_string(in, commodity->symbol);
read_binary_string(in, commodity->name);
@@ -154,8 +154,8 @@ commodity_t * read_binary_commodity(std::istream& in)
read_binary_amount(in, amt);
commodity->history.insert(history_pair(when, amt));
}
- read_binary_number(in, commodity->last_lookup);
+ read_binary_number(in, commodity->last_lookup);
read_binary_amount(in, commodity->conversion);
return commodity;
@@ -167,14 +167,14 @@ account_t * read_binary_account(std::istream& in, account_t * master = NULL)
accounts.push_back(acct);
acct->ident = read_binary_number<account_t::ident_t>(in);
- assert(acct->ident == accounts.size() - 1);
+ assert(acct->ident == accounts.size());
account_t::ident_t id;
read_binary_number(in, id); // parent id
if (id == 0xffffffff)
acct->parent = NULL;
else
- acct->parent = accounts[id];
+ acct->parent = accounts[id - 1];
read_binary_string(in, acct->name);
read_binary_string(in, acct->note);
@@ -206,8 +206,8 @@ unsigned int read_binary_journal(std::istream& in,
journal_t * journal,
account_t * master)
{
- ident = 0;
- c_ident = 0;
+ account_index =
+ commodity_index = 0;
if (read_binary_number<unsigned long>(in) != binary_magic_number ||
read_binary_number<unsigned long>(in) != format_version)
@@ -343,10 +343,9 @@ void write_binary_entry(std::ostream& out, entry_t * entry)
void write_binary_commodity(std::ostream& out, commodity_t * commodity)
{
- write_binary_number(out, c_ident);
- commodity->ident = c_ident;
- ++c_ident;
+ commodity->ident = ++commodity_index;
+ write_binary_number(out, commodity->ident);
write_binary_string(out, commodity->symbol);
write_binary_string(out, commodity->name);
write_binary_string(out, commodity->note);
@@ -360,17 +359,16 @@ void write_binary_commodity(std::ostream& out, commodity_t * commodity)
write_binary_number(out, (*i).first);
write_binary_amount(out, (*i).second);
}
- write_binary_number(out, commodity->last_lookup);
+ write_binary_number(out, commodity->last_lookup);
write_binary_amount(out, commodity->conversion);
}
void write_binary_account(std::ostream& out, account_t * account)
{
- write_binary_number(out, ident);
- account->ident = ident;
- ++ident;
+ account->ident = ++account_index;
+ write_binary_number(out, account->ident);
if (account->parent)
write_binary_number(out, account->parent->ident);
else
diff --git a/datetime.h b/datetime.h
index e9f2cd8a..a3b0651a 100644
--- a/datetime.h
+++ b/datetime.h
@@ -14,7 +14,14 @@ struct interval_t
int seconds;
interval_t(int _seconds = 0, int _months = 0, int _years = 0)
- : years(_years), months(_months), seconds(_seconds) {}
+ : years(_years), months(_months), seconds(_seconds) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor interval_t");
+ }
+#ifdef DEBUG_ENABLED
+ ~interval_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor interval_t");
+ }
+#endif
operator bool() const {
return seconds > 0 || months > 0 || years > 0;
diff --git a/format.cc b/format.cc
index 4bbce62b..19c4f141 100644
--- a/format.cc
+++ b/format.cc
@@ -216,6 +216,11 @@ void format_t::format_elements(std::ostream& out,
(elem->max_width > 0 ?
elem->max_width : elem->min_width));
break;
+ case value_t::BALANCE_PAIR:
+ ((balance_pair_t *) value.data)->quantity.write(out, elem->min_width,
+ (elem->max_width > 0 ?
+ elem->max_width : elem->min_width));
+ break;
default:
assert(0);
break;
@@ -353,9 +358,9 @@ bool format_account::disp_subaccounts_p(const account_t * account,
{
bool display = false;
unsigned int counted = 0;
- bool computed = false;
bool matches = disp_pred(account);
- balance_t acct_total;
+ value_t acct_total;
+ bool computed = false;
to_show = NULL;
@@ -365,7 +370,7 @@ bool format_account::disp_subaccounts_p(const account_t * account,
if (! disp_pred((*i).second))
continue;
- balance_t result;
+ value_t result;
format_t::compute_total(result, details_t((*i).second));
if (! computed) {
diff --git a/format.h b/format.h
index 0f34b36a..9996d378 100644
--- a/format.h
+++ b/format.h
@@ -79,7 +79,7 @@ struct format_t
void format_elements(std::ostream& out, const details_t& details) const;
- static void compute_value(balance_t& result, const details_t& details) {
+ static void compute_value(value_t& result, const details_t& details) {
#ifdef NO_CLEANUP
if (value_expr)
#else
@@ -88,7 +88,7 @@ struct format_t
value_expr->compute(result, details);
}
- static void compute_total(balance_t& result, const details_t& details) {
+ static void compute_total(value_t& result, const details_t& details) {
#ifdef NO_CLEANUP
if (total_expr)
#else
@@ -179,7 +179,7 @@ class format_equity : public item_handler<account_t>
item_predicate<account_t> disp_pred;
- mutable balance_t total;
+ mutable value_t total;
public:
format_equity(std::ostream& _output_stream,
@@ -198,7 +198,8 @@ class format_equity : public item_handler<account_t>
virtual void flush() {
account_t summary(NULL, "Equity:Opening Balances");
- summary.value = - total;
+ summary.value = total;
+ summary.value.negate();
next_lines_format.format_elements(output_stream, details_t(&summary));
output_stream.flush();
}
@@ -207,7 +208,7 @@ class format_equity : public item_handler<account_t>
if (format_account::display_account(account, disp_pred)) {
next_lines_format.format_elements(output_stream, details_t(account));
account->dflags |= ACCOUNT_DISPLAYED;
- total += account->value.quantity;
+ total += account->value;
}
}
};
diff --git a/ledger.cc b/ledger.cc
index 5ecf6f61..de53b7b2 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -10,6 +10,8 @@ const std::string version = "2.0b";
journal_t::~journal_t()
{
+ DEBUG_PRINT("ledger.memory.dtors", "dtor journal_t");
+
delete master;
// Don't bother unhooking each entry's transactions from the
diff --git a/ledger.h b/ledger.h
index de51cc83..169c2751 100644
--- a/ledger.h
+++ b/ledger.h
@@ -25,7 +25,7 @@
#endif
#include "amount.h"
-#include "balance.h"
+#include "value.h"
namespace ledger {
@@ -53,7 +53,7 @@ class transaction_t
unsigned short flags;
std::string note;
- mutable balance_pair_t total;
+ mutable value_t total;
mutable unsigned int index;
mutable unsigned short dflags;
@@ -69,6 +69,7 @@ class transaction_t
cost(NULL), flags(_flags), note(_note), index(0), dflags(0) {}
~transaction_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_t");
if (cost)
delete cost;
}
@@ -90,9 +91,12 @@ class entry_t
std::string payee;
transactions_list transactions;
- entry_t() : date(-1), state(UNCLEARED) {}
+ entry_t() : date(-1), state(UNCLEARED) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t");
+ }
~entry_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor entry_t");
for (transactions_list::iterator i = transactions.begin();
i != transactions.end();
i++)
@@ -128,8 +132,8 @@ class account_t
accounts_map accounts;
transactions_list transactions;
- mutable balance_pair_t value;
- mutable balance_pair_t total;
+ mutable value_t value;
+ mutable value_t total;
mutable unsigned int count; // transactions counted toward total
mutable unsigned int subcount;
mutable ident_t ident;
@@ -143,14 +147,15 @@ class account_t
const std::string& _note = "")
: parent(_parent), name(_name), note(_note),
depth(parent ? parent->depth + 1 : 0),
- count(0), subcount(0), dflags(0) {}
+ subcount(0), ident(0), dflags(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor account_t");
+ }
~account_t();
std::string fullname() const;
void add_account(account_t * acct) {
- acct->ident = next_ident++;
accounts.insert(accounts_pair(acct->name, acct));
}
bool remove_account(account_t * acct) {
@@ -193,9 +198,8 @@ class journal_t
mutable accounts_map accounts_cache;
journal_t() {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor journal_t");
master = new account_t(NULL, "");
- master->ident = 0;
- account_t::next_ident = 1;
}
~journal_t();
diff --git a/option.cc b/option.cc
index 1010981f..82128318 100644
--- a/option.cc
+++ b/option.cc
@@ -9,6 +9,8 @@ option_handler::option_handler(const std::string& label,
const std::string& opt_chars)
: handled(false)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor option_handler");
+
option_t opt;
static char buf[128];
diff --git a/qif.cc b/qif.cc
index 5c1f6fac..dac4b3fa 100644
--- a/qif.cc
+++ b/qif.cc
@@ -43,7 +43,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
std::auto_ptr<entry_t> entry;
std::auto_ptr<amount_t> amount;
transaction_t * xact;
- unsigned int count;
+ unsigned int count = 0;
account_t * misc = NULL;
commodity_t * def_commodity = NULL;
diff --git a/textual.cc b/textual.cc
index c4d92e32..df45d2ce 100644
--- a/textual.cc
+++ b/textual.cc
@@ -146,7 +146,7 @@ bool finalize_entry(entry_t * entry)
// is used for auto-calculating the value of entries with no cost,
// and the per-unit price of unpriced commodities.
- balance_t balance;
+ value_t balance;
for (transactions_list::const_iterator x = entry->transactions.begin();
x != entry->transactions.end();
@@ -155,7 +155,9 @@ bool finalize_entry(entry_t * entry)
((*x)->flags & TRANSACTION_BALANCE)) {
DEBUG_PRINT("ledger.textual.finalize",
"item cost is " << ((*x)->cost ? *(*x)->cost : (*x)->amount));
- balance += (*x)->cost ? *(*x)->cost : (*x)->amount;
+ amount_t * p = (*x)->cost ? (*x)->cost : &(*x)->amount;
+ if (*p)
+ balance += *p;
}
// If one transaction of a two-line transaction is of a different
@@ -163,15 +165,17 @@ bool finalize_entry(entry_t * entry)
// determine its price by dividing the unit count into the value of
// the balance. This is done for the last eligible commodity.
- if (balance.amounts.size() == 2)
+ if (balance.type == value_t::BALANCE &&
+ ((balance_t *) balance.data)->amounts.size() == 2)
for (transactions_list::const_iterator x = entry->transactions.begin();
x != entry->transactions.end();
x++) {
if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL))
continue;
- for (amounts_map::const_iterator i = balance.amounts.begin();
- i != balance.amounts.end();
+ for (amounts_map::const_iterator i
+ = ((balance_t *) balance.data)->amounts.begin();
+ i != ((balance_t *) balance.data)->amounts.end();
i++)
if ((*i).second.commodity != (*x)->amount.commodity) {
assert((*x)->amount);
@@ -196,8 +200,7 @@ bool finalize_entry(entry_t * entry)
if ((*x)->amount || ((*x)->flags & TRANSACTION_VIRTUAL))
continue;
- if (! empty_allowed || balance.amounts.empty() ||
- balance.amounts.size() != 1)
+ if (! empty_allowed || ! balance || balance.type != value_t::AMOUNT)
return false;
empty_allowed = false;
@@ -206,13 +209,15 @@ bool finalize_entry(entry_t * entry)
// rest are of the same commodity -- then its value is the
// inverse of the computed value of the others.
- amounts_map::const_iterator i = balance.amounts.begin();
- (*x)->amount = - balance.amount((*i).first);
+ (*x)->amount = *((amount_t *) balance.data);
+ (*x)->amount.negate();
- balance = 0;
+ balance = 0U;
}
+#if 0
DEBUG_PRINT("ledger.textual.finalize", "balance is " << balance);
+#endif
return ! balance;
}
diff --git a/valexpr.cc b/valexpr.cc
index 73ffd738..a06d2f98 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -13,6 +13,8 @@ namespace ledger {
mask_t::mask_t(const std::string& pat) : exclude(false)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor mask_t");
+
const char * p = pat.c_str();
if (*p == '-') {
exclude = true;
@@ -40,6 +42,8 @@ mask_t::mask_t(const std::string& pat) : exclude(false)
mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern)
{
+ DEBUG_PRINT("ledger.memory.ctors", "ctor mask_t");
+
const char *error;
int erroffset;
regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS,
@@ -47,6 +51,11 @@ mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern)
assert(regexp);
}
+mask_t::~mask_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor mask_t");
+ pcre_free((pcre *)regexp);
+}
+
bool mask_t::match(const std::string& str) const
{
static int ovec[30];
@@ -55,10 +64,6 @@ bool mask_t::match(const std::string& str) const
return result >= 0 && ! exclude;
}
-mask_t::~mask_t() {
- pcre_free((pcre *)regexp);
-}
-
void value_expr_t::compute(value_t& result, const details_t& details,
value_t::type_t type) const
@@ -79,7 +84,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
if (details.xact)
result = details.xact->amount;
else if (details.account)
- result = details.account->value.quantity;
+ result = details.account->value;
break;
case COST:
@@ -90,32 +95,21 @@ void value_expr_t::compute(value_t& result, const details_t& details,
result = details.xact->amount;
}
else if (details.account) {
- if (details.account->value.cost)
- result = *details.account->value.cost;
- else
- result = details.account->value.quantity;
+ result = details.account->value.cost();
}
break;
case TOTAL:
if (details.xact)
- result = details.xact->total.quantity;
+ result = details.xact->total;
else if (details.account)
- result = details.account->total.quantity;
+ result = details.account->total;
break;
case COST_TOTAL:
- if (details.xact) {
- if (details.xact->total.cost)
- result = *details.xact->total.cost;
- else
- result = details.xact->total.quantity;
- }
- else if (details.account) {
- if (details.account->total.cost)
- result = *details.account->total.cost;
- else
- result = details.account->total.quantity;
- }
+ if (details.xact)
+ result = details.xact->total.cost();
+ else if (details.account)
+ result = details.account->total.cost();
break;
case VALUE_EXPR:
@@ -227,7 +221,8 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case F_STRIP: {
assert(left);
left->compute(result, details);
- if (result.type == value_t::BALANCE) {
+ if (result.type == value_t::BALANCE ||
+ result.type == value_t::BALANCE_PAIR) {
// jww (2004-08-17): do something smarter here?
result.cast(value_t::AMOUNT);
}
diff --git a/valexpr.h b/valexpr.h
index b1be9a6c..4c7f503e 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -16,12 +16,12 @@ class mask_t
explicit mask_t(const std::string& pattern);
mask_t(const mask_t&);
-
~mask_t();
bool match(const std::string& str) const;
};
+//////////////////////////////////////////////////////////////////////
struct details_t
{
@@ -30,13 +30,22 @@ struct details_t
const account_t * account;
details_t(const entry_t * _entry)
- : entry(_entry), xact(NULL), account(NULL) {}
-
+ : entry(_entry), xact(NULL), account(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
+ }
details_t(const transaction_t * _xact)
- : entry(_xact->entry), xact(_xact), account(_xact->account) {}
-
+ : entry(_xact->entry), xact(_xact), account(_xact->account) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
+ }
details_t(const account_t * _account)
- : entry(NULL), xact(NULL), account(_account) {}
+ : entry(NULL), xact(NULL), account(_account) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
+ }
+#ifdef DEBUG_ENABLED
+ ~details_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor details_t");
+ }
+#endif
};
struct value_expr_t
@@ -106,9 +115,12 @@ struct value_expr_t
mask_t * mask;
value_expr_t(const kind_t _kind)
- : kind(_kind), left(NULL), right(NULL), mask(NULL) {}
+ : kind(_kind), left(NULL), right(NULL), mask(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t");
+ }
~value_expr_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr_t");
if (mask) delete mask;
if (left) delete left;
if (right) delete right;
@@ -116,12 +128,6 @@ struct value_expr_t
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);
@@ -139,6 +145,8 @@ inline value_expr_t * parse_value_expr(const std::string& str) {
void dump_value_expr(std::ostream& out, const value_expr_t * node);
#endif
+//////////////////////////////////////////////////////////////////////
+
template <typename T>
class item_predicate
{
@@ -146,6 +154,7 @@ class item_predicate
public:
item_predicate(const std::string& _predicate) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
predicate = NULL;
if (! _predicate.empty()) {
try {
@@ -172,9 +181,12 @@ class item_predicate
}
}
item_predicate(const value_expr_t * _predicate)
- : predicate(_predicate) {}
+ : predicate(_predicate) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>");
+ }
~item_predicate() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor item_predicate<T>");
if (predicate)
delete predicate;
}
diff --git a/value.cc b/value.cc
index e5a89cda..bf235257 100644
--- a/value.cc
+++ b/value.cc
@@ -1,4 +1,5 @@
#include "value.h"
+#include "ledger.h"
namespace ledger {
@@ -11,733 +12,333 @@ void value_t::destroy()
case BALANCE:
((balance_t *)data)->~balance_t();
break;
- default:
+ case BALANCE_PAIR:
+ ((balance_pair_t *)data)->~balance_pair_t();
break;
- }
-}
-
-value_t& 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& value_t::operator-=(const value_t& value)
+value_t& value_t::operator=(const value_t& value)
{
+ destroy();
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;
- }
+ *((bool *) data) = *((bool *) value.data);
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& 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;
- }
+ *((unsigned int *) data) = *((unsigned int *) value.data);
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;
- }
+ new((amount_t *)data) amount_t(*((amount_t *) value.data));
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& 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;
- }
+ new((balance_t *)data) balance_t(*((balance_t *) value.data));
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;
- }
+ case BALANCE_PAIR:
+ new((balance_pair_t *)data) balance_pair_t(*((balance_pair_t *) value.data));
break;
default:
assert(0);
break;
}
- return *this;
-}
-
-bool value_t::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;
+ type = value.type;
- default:
- assert(0);
- break;
- }
return *this;
}
-bool value_t::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;
+#define DEF_VALUE_OP(OP) \
+value_t& value_t::operator OP(const value_t& value) \
+{ \
+ switch (value.type) { \
+ case BOOLEAN: \
+ case INTEGER: \
+ switch (type) { \
+ case BOOLEAN: \
+ cast(INTEGER); \
+ \
+ case INTEGER: \
+ *((unsigned int *) data) OP *((unsigned int *) value.data); \
+ break; \
+ \
+ case AMOUNT: \
+ *((amount_t *) data) OP *((unsigned int *) value.data); \
+ break; \
+ \
+ case BALANCE: \
+ *((balance_t *) data) OP amount_t(*((unsigned int *) value.data)); \
+ break; \
+ \
+ case BALANCE_PAIR: \
+ *((balance_pair_t *) data) OP amount_t(*((unsigned int *) value.data)); \
+ break; \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ case AMOUNT: \
+ switch (type) { \
+ case BOOLEAN: \
+ case INTEGER: \
+ cast(AMOUNT); \
+ \
+ case AMOUNT: \
+ if (((amount_t *) data)->commodity && \
+ ((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: \
+ *((balance_t *) data) OP *((amount_t *) value.data); \
+ break; \
+ \
+ case BALANCE_PAIR: \
+ *((balance_pair_t *) data) OP *((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) OP *((balance_t *) value.data); \
+ break; \
+ \
+ case BALANCE_PAIR: \
+ *((balance_pair_t *) data) OP *((balance_t *) value.data); \
+ break; \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ case BALANCE_PAIR: \
+ switch (type) { \
+ case BOOLEAN: \
+ case INTEGER: \
+ case AMOUNT: \
+ case BALANCE: \
+ cast(BALANCE_PAIR); \
+ \
+ 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; \
}
-bool value_t::operator<=(const value_t& value)
+DEF_VALUE_OP(+=)
+DEF_VALUE_OP(-=)
+DEF_VALUE_OP(*=)
+DEF_VALUE_OP(/=)
+
+value_t& value_t::operator +=(const transaction_t& xact)
{
- switch (value.type) {
+ switch (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;
+ cast(AMOUNT);
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 value_t::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;
+ if (xact.cost) {
+ cast(BALANCE_PAIR);
+ return *this += xact;
}
- 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;
+ else if (((amount_t *) data)->commodity &&
+ ((amount_t *) data)->commodity != xact.amount.commodity) {
+ cast(BALANCE);
+ return *this += xact;
}
+ *((amount_t *) data) += xact.amount;
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;
+ case BALANCE:
+ if (xact.cost) {
+ cast(BALANCE_PAIR);
+ return *this += xact;
}
+ *((balance_t *) data) += xact.amount;
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;
- }
+ case BALANCE_PAIR:
+ *((balance_pair_t *) data) += xact;
break;
default:
assert(0);
break;
}
+
return *this;
}
-bool value_t::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;
+#define DEF_VALUE_CMP_OP(OP) \
+bool value_t::operator OP(const value_t& value) \
+{ \
+ switch (value.type) { \
+ case BOOLEAN: \
+ switch (type) { \
+ case BOOLEAN: \
+ return *((bool *) data) OP *((bool *) value.data); \
+ \
+ case INTEGER: \
+ return bool(*((unsigned int *) data)) OP *((bool *) value.data); \
+ \
+ case AMOUNT: \
+ return bool(*((amount_t *) data)) OP *((bool *) value.data); \
+ \
+ case BALANCE: \
+ return bool(*((balance_t *) data)) OP *((bool *) value.data); \
+ \
+ case BALANCE_PAIR: \
+ return bool(*((balance_pair_t *) data)) OP *((bool *) value.data); \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ case INTEGER: \
+ switch (type) { \
+ case BOOLEAN: \
+ return ((unsigned int) *((bool *) data)) OP *((unsigned int *) value.data); \
+ \
+ case INTEGER: \
+ return *((unsigned int *) data) OP *((unsigned int *) value.data); \
+ \
+ case AMOUNT: \
+ return ((unsigned int) *((amount_t *) data)) OP *((unsigned int *) value.data); \
+ \
+ case BALANCE: \
+ return ((unsigned int) *((balance_t *) data)) OP *((unsigned int *) value.data); \
+ \
+ case BALANCE_PAIR: \
+ return ((unsigned int) *((balance_pair_t *) data)) OP *((unsigned int *) value.data); \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ case AMOUNT: \
+ switch (type) { \
+ case BOOLEAN: \
+ return amount_t(*((bool *) data)) OP *((amount_t *) value.data); \
+ \
+ case INTEGER: \
+ return amount_t(*((unsigned int *) data)) OP *((amount_t *) value.data); \
+ \
+ case AMOUNT: \
+ return *((amount_t *) data) OP *((amount_t *) value.data); \
+ \
+ case BALANCE: \
+ return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) OP *((amount_t *) value.data); \
+ \
+ case BALANCE_PAIR: \
+ return ((balance_pair_t *) data)->quantity.amount(((amount_t *) value.data)->commodity) OP *((amount_t *) value.data); \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ case BALANCE: \
+ switch (type) { \
+ case BOOLEAN: \
+ return balance_t(*((bool *) data)) OP *((balance_t *) value.data); \
+ \
+ case INTEGER: \
+ return balance_t(*((unsigned int *) data)) OP *((balance_t *) value.data); \
+ \
+ case AMOUNT: \
+ return balance_t(*((amount_t *) data)) OP *((balance_t *) value.data); \
+ \
+ case BALANCE: \
+ return *((balance_t *) data) OP *((balance_t *) value.data); \
+ \
+ case BALANCE_PAIR: \
+ return *((balance_pair_t *) data) OP *((balance_t *) value.data); \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ case BALANCE_PAIR: \
+ switch (type) { \
+ case BOOLEAN: \
+ return balance_pair_t(*((bool *) data)) OP *((balance_pair_t *) value.data); \
+ \
+ case INTEGER: \
+ return balance_pair_t(*((unsigned int *) data)) OP *((balance_pair_t *) value.data); \
+ \
+ case AMOUNT: \
+ return balance_pair_t(*((amount_t *) data)) OP *((balance_pair_t *) value.data); \
+ \
+ case BALANCE: \
+ return balance_pair_t(*((balance_t *) data)) OP *((balance_pair_t *) value.data); \
+ \
+ case BALANCE_PAIR: \
+ return *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ break; \
+ \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ return *this; \
}
+DEF_VALUE_CMP_OP(==)
+DEF_VALUE_CMP_OP(<)
+DEF_VALUE_CMP_OP(<=)
+DEF_VALUE_CMP_OP(>)
+DEF_VALUE_CMP_OP(>=)
+
void value_t::cast(type_t cast_type)
{
switch (type) {
@@ -754,6 +355,9 @@ void value_t::cast(type_t cast_type)
case BALANCE:
new((balance_t *)data) balance_t(*((bool *) data));
break;
+ case BALANCE_PAIR:
+ new((balance_pair_t *)data) balance_pair_t(*((bool *) data));
+ break;
default:
assert(0);
@@ -774,6 +378,9 @@ void value_t::cast(type_t cast_type)
case BALANCE:
new((balance_t *)data) balance_t(*((unsigned int *) data));
break;
+ case BALANCE_PAIR:
+ new((balance_pair_t *)data) balance_pair_t(*((unsigned int *) data));
+ break;
default:
assert(0);
@@ -803,6 +410,12 @@ void value_t::cast(type_t cast_type)
new((balance_t *)data) balance_t(temp);
break;
}
+ case BALANCE_PAIR: {
+ amount_t temp = *((amount_t *) data);
+ destroy();
+ new((balance_pair_t *)data) balance_pair_t(temp);
+ break;
+ }
default:
assert(0);
@@ -832,6 +445,47 @@ void value_t::cast(type_t cast_type)
}
case BALANCE:
break;
+ case BALANCE_PAIR: {
+ balance_t temp = *((balance_t *) data);
+ destroy();
+ new((balance_pair_t *)data) balance_pair_t(temp);
+ break;
+ }
+
+ default:
+ assert(0);
+ break;
+ }
+ break;
+
+ case BALANCE_PAIR:
+ switch (cast_type) {
+ case BOOLEAN: {
+ bool temp = *((balance_pair_t *) data);
+ destroy();
+ *((bool *)data) = temp;
+ break;
+ }
+ case INTEGER: {
+ unsigned int temp = ((balance_pair_t *) data)->quantity.amount();
+ destroy();
+ *((unsigned int *)data) = temp;
+ break;
+ }
+ case AMOUNT: {
+ amount_t temp = ((balance_pair_t *) data)->quantity.amount();
+ destroy();
+ new((amount_t *)data) amount_t(temp);
+ break;
+ }
+ case BALANCE: {
+ balance_t temp = ((balance_pair_t *) data)->quantity;
+ destroy();
+ new((balance_t *)data) balance_t(temp);
+ break;
+ }
+ case BALANCE_PAIR:
+ break;
default:
assert(0);
@@ -861,6 +515,9 @@ void value_t::negate()
case BALANCE:
((balance_t *) data)->negate();
break;
+ case BALANCE_PAIR:
+ ((balance_pair_t *) data)->negate();
+ break;
default:
assert(0);
@@ -883,11 +540,38 @@ void value_t::abs()
case BALANCE:
((balance_t *) data)->abs();
break;
+ case BALANCE_PAIR:
+ ((balance_pair_t *) data)->abs();
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+value_t value_t::cost() const
+{
+ switch (type) {
+ case BOOLEAN:
+ case INTEGER:
+ case AMOUNT:
+ case BALANCE:
+ return *this;
+
+ case BALANCE_PAIR:
+ assert(((balance_pair_t *) data)->cost);
+ if (((balance_pair_t *) data)->cost)
+ return *(((balance_pair_t *) data)->cost);
+ else
+ return ((balance_pair_t *) data)->quantity;
default:
assert(0);
break;
}
+ assert(0);
+ return value_t();
}
} // namespace ledger
diff --git a/value.h b/value.h
index d553eb9e..11ac2481 100644
--- a/value.h
+++ b/value.h
@@ -16,49 +16,66 @@ namespace ledger {
// fact that logic chains only need boolean values to continue, no
// memory allocations need to take place at all.
+class transaction_t;
+
class value_t
{
- value_t(const value_t& copy);
-
public:
- char data[sizeof(balance_t)];
+ char data[sizeof(balance_pair_t)];
enum type_t {
BOOLEAN,
INTEGER,
AMOUNT,
BALANCE,
+ BALANCE_PAIR,
ANY
} type;
value_t() {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
*((unsigned int *) data) = 0;
type = INTEGER;
}
+ value_t(const value_t& value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
+ *this = value;
+ }
value_t(const bool value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
*((bool *) data) = value;
type = BOOLEAN;
}
value_t(const unsigned int value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
*((unsigned int *) data) = value;
type = INTEGER;
}
value_t(const amount_t& value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
new((amount_t *)data) amount_t(value);
type = AMOUNT;
}
value_t(const balance_t& value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
new((balance_t *)data) balance_t(value);
type = BALANCE;
}
+ value_t(const balance_pair_t& value) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor value_t");
+ new((balance_pair_t *)data) balance_pair_t(value);
+ type = BALANCE_PAIR;
+ }
~value_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor value_t");
destroy();
}
void destroy();
+ value_t& operator=(const value_t& value);
value_t& operator=(const bool value) {
destroy();
*((bool *) data) = value;
@@ -83,12 +100,20 @@ class value_t
type = BALANCE;
return *this;
}
+ value_t& operator=(const balance_pair_t& value) {
+ destroy();
+ new((balance_pair_t *)data) balance_pair_t(value);
+ type = BALANCE_PAIR;
+ return *this;
+ }
value_t& operator+=(const value_t& value);
value_t& operator-=(const value_t& value);
value_t& operator*=(const value_t& value);
value_t& operator/=(const value_t& value);
+ value_t& operator+=(const transaction_t& xact);
+
bool operator==(const value_t& value);
bool operator!=(const value_t& value) {
return ! (*this == value);
@@ -105,6 +130,8 @@ class value_t
void cast(type_t cast_type);
void negate();
void abs();
+
+ value_t cost() const;
};
template <typename T>
@@ -119,6 +146,8 @@ value_t::operator T() const
return *((amount_t *) data);
case BALANCE:
return *((balance_t *) data);
+ case BALANCE_PAIR:
+ return *((balance_pair_t *) data);
default:
assert(0);
diff --git a/walk.cc b/walk.cc
index 00e4213f..fff19645 100644
--- a/walk.cc
+++ b/walk.cc
@@ -55,9 +55,10 @@ void collapse_transactions::report_cumulative_subtotal()
assert(count > 1);
totals_account->total = subtotal;
- balance_t result;
+ value_t result;
format_t::compute_total(result, details_t(totals_account));
+#if 0
for (amounts_map::const_iterator i = result.amounts.begin();
i != result.amounts.end();
i++) {
@@ -69,6 +70,7 @@ void collapse_transactions::report_cumulative_subtotal()
(*handler)(total_xact);
}
+#endif
}
subtotal = 0;
@@ -78,8 +80,8 @@ void collapse_transactions::report_cumulative_subtotal()
void changed_value_transactions::operator()(transaction_t * xact)
{
if (last_xact) {
- balance_t prev_bal;
- balance_t cur_bal;
+ value_t prev_bal;
+ value_t cur_bal;
std::time_t current = xact ? xact->entry->date : std::time(NULL);
std::time_t prev_date = last_xact->entry->date;
@@ -89,13 +91,15 @@ void changed_value_transactions::operator()(transaction_t * xact)
format_t::compute_total(cur_bal, details_t(last_xact));
last_xact->entry->date = prev_date;
- if (balance_t diff = cur_bal - prev_bal) {
+ cur_bal -= prev_bal;
+ if (cur_bal) {
entry_t * entry = new entry_t;
entry_temps.push_back(entry);
entry->payee = "Commodities revalued";
entry->date = current;
+#if 0
for (amounts_map::const_iterator i = diff.amounts.begin();
i != diff.amounts.end();
i++) {
@@ -108,6 +112,7 @@ void changed_value_transactions::operator()(transaction_t * xact)
(*handler)(temp_xact);
}
+#endif
}
}
@@ -150,10 +155,11 @@ void subtotal_transactions::flush(const char * spec_fmt)
transaction_t temp((*i).first);
temp.entry = entry;
temp.total = (*i).second;
- balance_t result;
+ value_t result;
format_t::compute_total(result, details_t(&temp));
entry->date = start;
+#if 0
for (amounts_map::const_iterator j = result.amounts.begin();
j != result.amounts.end();
j++) {
@@ -165,6 +171,7 @@ void subtotal_transactions::flush(const char * spec_fmt)
(*handler)(xact);
}
+#endif
}
balances.clear();
diff --git a/walk.h b/walk.h
index 6cac857f..07632e9f 100644
--- a/walk.h
+++ b/walk.h
@@ -16,10 +16,15 @@ struct item_handler {
item_handler * handler;
public:
- item_handler() : handler(NULL) {}
- item_handler(item_handler * _handler) : handler(_handler) {}
+ item_handler() : handler(NULL) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>");
+ }
+ item_handler(item_handler * _handler) : handler(_handler) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>");
+ }
virtual ~item_handler() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor item_handler<T>");
if (handler)
delete handler;
}