summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--account.cc2
-rw-r--r--amount.cc13
-rw-r--r--autoxact.h4
-rw-r--r--binary.cc2
-rw-r--r--format.cc22
-rw-r--r--format.h48
-rw-r--r--ledger.h67
-rw-r--r--main.cc37
-rw-r--r--valexpr.cc63
-rw-r--r--walk.cc163
-rw-r--r--walk.h116
12 files changed, 338 insertions, 201 deletions
diff --git a/Makefile b/Makefile
index 41e452d6..162a9e5b 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ CXX = g++
CFLAGS = -Wall -ansi -pedantic
#DFLAGS = -O3 -fomit-frame-pointer -DDEBUG_LEVEL=0
-DFLAGS = -g -DDEBUG_LEVEL=4
+DFLAGS = -g -DDEBUG_LEVEL=4 -DDO_CLEANUP
#DFLAGS = -g -DDEBUG_LEVEL=2 -pg
INCS = -I/sw/include \
diff --git a/account.cc b/account.cc
index f04eb55d..267d190a 100644
--- a/account.cc
+++ b/account.cc
@@ -8,6 +8,8 @@ namespace ledger {
account_t::~account_t()
{
DEBUG_PRINT("ledger.memory.ctors", "dtor account_t");
+ //assert(! data);
+
for (accounts_map::iterator i = accounts.begin();
i != accounts.end();
i++)
diff --git a/amount.cc b/amount.cc
index ed51f356..8a827d94 100644
--- a/amount.cc
+++ b/amount.cc
@@ -50,7 +50,7 @@ static struct init_amounts {
mpz_init(true_value);
mpz_set_ui(true_value, 1);
}
-#ifndef NO_CLEANUP
+#ifdef DO_CLEANUP
~init_amounts() {
mpz_clear(true_value);
mpz_clear(divisor);
@@ -593,8 +593,9 @@ amount_t amount_t::round(unsigned int prec) const
} else {
amount_t temp = *this;
temp._dup();
- mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), quantity->prec, prec);
- quantity->prec = prec;
+ mpz_round(MPZ(temp.quantity), MPZ(temp.quantity),
+ temp.quantity->prec, prec);
+ temp.quantity->prec = prec;
return temp;
}
}
@@ -929,7 +930,8 @@ commodities_map commodity_t::commodities;
commodity_t * commodity_t::null_commodity =
commodity_t::find_commodity("", true);
-#ifndef NO_CLEANUP
+#ifdef DO_CLEANUP
+
static struct cleanup_commodities
{
~cleanup_commodities() {
@@ -943,7 +945,8 @@ static struct cleanup_commodities
delete (*i).second;
}
} _cleanup;
-#endif
+
+#endif // DO_CLEANUP
commodity_t * commodity_t::find_commodity(const std::string& symbol,
bool auto_create)
diff --git a/autoxact.h b/autoxact.h
index 1a6ad3ea..9e25d967 100644
--- a/autoxact.h
+++ b/autoxact.h
@@ -42,6 +42,10 @@ typedef std::deque<automated_transaction_t *> automated_transactions_deque;
class automated_transactions_t
{
+#ifdef DEBUG_ENABLED
+ automated_transactions_t(const automated_transactions_t&);
+#endif
+
public:
automated_transactions_deque automated_transactions;
diff --git a/binary.cc b/binary.cc
index e336fc12..a1dbea98 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 = 0x00020011;
+static const unsigned long format_version = 0x00020012;
bool binary_parser_t::test(std::istream& in) const
{
diff --git a/format.cc b/format.cc
index 19c4f141..a26ce631 100644
--- a/format.cc
+++ b/format.cc
@@ -21,7 +21,7 @@ std::string partial_account_name(const account_t * account)
for (const account_t * acct = account;
acct && acct->parent;
acct = acct->parent) {
- if (acct->dflags & ACCOUNT_DISPLAYED)
+ if (acct->data && ACCT_DATA(acct)->dflags & ACCOUNT_DISPLAYED)
break;
if (name.empty())
@@ -35,12 +35,12 @@ std::string partial_account_name(const account_t * account)
std::string format_t::date_format = "%Y/%m/%d";
-#ifdef NO_CLEANUP
-value_expr_t * format_t::value_expr = NULL;
-value_expr_t * format_t::total_expr = NULL;
-#else
+#ifdef DO_CLEANUP
std::auto_ptr<value_expr_t> format_t::value_expr;
std::auto_ptr<value_expr_t> format_t::total_expr;
+#else
+value_expr_t * format_t::value_expr = NULL;
+value_expr_t * format_t::total_expr = NULL;
#endif
element_t * format_t::parse_elements(const std::string& fmt)
@@ -186,12 +186,12 @@ void format_t::format_elements(std::ostream& out,
case element_t::VALUE_EXPR: {
value_expr_t * expr = NULL;
switch (elem->type) {
-#ifdef NO_CLEANUP
- case element_t::VALUE: expr = value_expr; break;
- case element_t::TOTAL: expr = total_expr; break;
-#else
+#ifdef DO_CLEANUP
case element_t::VALUE: expr = value_expr.get(); break;
case element_t::TOTAL: expr = total_expr.get(); break;
+#else
+ case element_t::VALUE: expr = value_expr; break;
+ case element_t::TOTAL: expr = total_expr; break;
#endif
case element_t::VALUE_EXPR: expr = elem->val_expr; break;
@@ -336,7 +336,7 @@ void format_t::format_elements(std::ostream& out,
for (const account_t * acct = details.account;
acct;
acct = acct->parent)
- if (acct->dflags & ACCOUNT_DISPLAYED) {
+ if (acct->data && ACCT_DATA(acct)->dflags & ACCOUNT_DISPLAYED) {
if (elem->min_width > 0 || elem->max_width > 0)
out.width(elem->min_width > elem->max_width ?
elem->min_width : elem->max_width);
@@ -393,7 +393,7 @@ bool format_account::display_account(const account_t * account,
const item_predicate<account_t>& disp_pred)
{
// Never display an account that has already been displayed.
- if (account->dflags & ACCOUNT_DISPLAYED)
+ if (account->data && ACCT_DATA(account)->dflags & ACCOUNT_DISPLAYED)
return false;
// At this point, one of two possibilities exists: the account is a
diff --git a/format.h b/format.h
index 9996d378..4aaac3ea 100644
--- a/format.h
+++ b/format.h
@@ -54,12 +54,12 @@ struct format_t
static std::string date_format;
-#ifdef NO_CLEANUP
- static value_expr_t * value_expr;
- static value_expr_t * total_expr;
-#else
+#ifdef DO_CLEANUP
static std::auto_ptr<value_expr_t> value_expr;
static std::auto_ptr<value_expr_t> total_expr;
+#else
+ static value_expr_t * value_expr;
+ static value_expr_t * total_expr;
#endif
format_t(const std::string& _format) : elements(NULL) {
@@ -80,19 +80,19 @@ struct format_t
void format_elements(std::ostream& out, const details_t& details) const;
static void compute_value(value_t& result, const details_t& details) {
-#ifdef NO_CLEANUP
- if (value_expr)
-#else
+#ifdef DO_CLEANUP
if (value_expr.get())
+#else
+ if (value_expr)
#endif
value_expr->compute(result, details);
}
static void compute_total(value_t& result, const details_t& details) {
-#ifdef NO_CLEANUP
- if (total_expr)
-#else
+#ifdef DO_CLEANUP
if (total_expr.get())
+#else
+ if (total_expr)
#endif
total_expr->compute(result, details);
}
@@ -118,14 +118,17 @@ class format_transactions : public item_handler<transaction_t>
}
virtual void operator()(transaction_t * xact) {
- if (! (xact->dflags & TRANSACTION_DISPLAYED)) {
+ if (! xact->data ||
+ ! (XACT_DATA(xact)->dflags & TRANSACTION_DISPLAYED)) {
if (last_entry != xact->entry) {
first_line_format.format_elements(output_stream, details_t(xact));
last_entry = xact->entry;
} else {
next_lines_format.format_elements(output_stream, details_t(xact));
}
- xact->dflags |= TRANSACTION_DISPLAYED;
+ if (! xact->data)
+ xact->data = new transaction_data_t;
+ XACT_DATA(xact)->dflags |= TRANSACTION_DISPLAYED;
}
}
};
@@ -162,10 +165,14 @@ class format_account : public item_handler<account_t>
virtual void operator()(account_t * account) {
if (display_account(account, disp_pred)) {
if (! account->parent) {
- account->dflags |= ACCOUNT_TO_DISPLAY;
+ if (! account->data)
+ account->data = new account_data_t;
+ ACCT_DATA(account)->dflags |= ACCOUNT_TO_DISPLAY;
} else {
format.format_elements(output_stream, details_t(account));
- account->dflags |= ACCOUNT_DISPLAYED;
+ if (! account->data)
+ account->data = new account_data_t;
+ ACCT_DATA(account)->dflags |= ACCOUNT_DISPLAYED;
}
}
}
@@ -198,8 +205,10 @@ class format_equity : public item_handler<account_t>
virtual void flush() {
account_t summary(NULL, "Equity:Opening Balances");
- summary.value = total;
- summary.value.negate();
+ std::auto_ptr<account_data_t> acct_data(new account_data_t);
+ summary.data = acct_data.get();
+ ((account_data_t *) summary.data)->value = total;
+ ((account_data_t *) summary.data)->value.negate();
next_lines_format.format_elements(output_stream, details_t(&summary));
output_stream.flush();
}
@@ -207,8 +216,11 @@ class format_equity : public item_handler<account_t>
virtual void operator()(account_t * account) {
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;
+ if (! account->data)
+ account->data = new account_data_t;
+ else
+ total += ACCT_DATA(account)->value;
+ ACCT_DATA(account)->dflags |= ACCOUNT_DISPLAYED;
}
}
};
diff --git a/ledger.h b/ledger.h
index 169c2751..18ae3492 100644
--- a/ledger.h
+++ b/ledger.h
@@ -16,16 +16,8 @@
#include <ctime>
#include <iostream>
-#ifdef DEBUG_LEVEL
-#if DEBUG_LEVEL >= 2
#include "debug.h"
-#elif DEBUG_LEVEL == 0
-#define NO_CLEANUP 1
-#endif
-#endif
-
#include "amount.h"
-#include "value.h"
namespace ledger {
@@ -35,11 +27,6 @@ namespace ledger {
#define TRANSACTION_BALANCE 0x0002
#define TRANSACTION_AUTO 0x0004
-// These flags are only used during formatting, and are not saved
-#define TRANSACTION_HANDLED 0x0001
-#define TRANSACTION_DISPLAYED 0x0002
-#define TRANSACTION_NO_TOTAL 0x0004
-
class entry_t;
class account_t;
@@ -52,24 +39,23 @@ class transaction_t
amount_t * cost;
unsigned short flags;
std::string note;
-
- mutable value_t total;
- mutable unsigned int index;
- mutable unsigned short dflags;
+ mutable void * data;
transaction_t(account_t * _account)
: entry(NULL), account(_account), cost(NULL),
- flags(TRANSACTION_NORMAL), index(0), dflags(0) {}
+ flags(TRANSACTION_NORMAL), data(NULL) {
+ }
transaction_t(account_t * _account,
const amount_t& _amount,
unsigned int _flags = TRANSACTION_NORMAL,
const std::string& _note = "")
: entry(NULL), account(_account), amount(_amount),
- cost(NULL), flags(_flags), note(_note), index(0), dflags(0) {}
+ cost(NULL), flags(_flags), note(_note), data(NULL) {
+ }
~transaction_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_t");
+ //assert(! data);
if (cost)
delete cost;
}
@@ -91,12 +77,8 @@ class entry_t
std::string payee;
transactions_list transactions;
- entry_t() : date(-1), state(UNCLEARED) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t");
- }
-
+ entry_t() : date(-1), state(UNCLEARED) {}
~entry_t() {
- DEBUG_PRINT("ledger.memory.dtors", "dtor entry_t");
for (transactions_list::iterator i = transactions.begin();
i != transactions.end();
i++)
@@ -114,9 +96,6 @@ class entry_t
};
-#define ACCOUNT_DISPLAYED 0x1
-#define ACCOUNT_TO_DISPLAY 0x2
-
typedef std::map<const std::string, account_t *> accounts_map;
typedef std::pair<const std::string, account_t *> accounts_pair;
@@ -125,31 +104,21 @@ class account_t
public:
typedef unsigned long ident_t;
- account_t * parent;
- std::string name;
- std::string note;
- unsigned short depth;
- accounts_map accounts;
- transactions_list transactions;
-
- mutable value_t value;
- mutable value_t total;
- mutable unsigned int count; // transactions counted toward total
- mutable unsigned int subcount;
- mutable ident_t ident;
- mutable unsigned short dflags;
- mutable std::string _fullname;
-
- static ident_t next_ident;
+ account_t * parent;
+ std::string name;
+ std::string note;
+ unsigned short depth;
+ accounts_map accounts;
+ transactions_list transactions;
+ mutable void * data;
+ mutable ident_t ident;
+ mutable std::string _fullname;
account_t(account_t * _parent,
const std::string& _name = "",
const std::string& _note = "")
: parent(_parent), name(_name), note(_note),
- depth(parent ? parent->depth + 1 : 0),
- subcount(0), ident(0), dflags(0) {
- DEBUG_PRINT("ledger.memory.ctors", "ctor account_t");
- }
+ depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {}
~account_t();
@@ -198,10 +167,8 @@ class journal_t
mutable accounts_map accounts_cache;
journal_t() {
- DEBUG_PRINT("ledger.memory.ctors", "ctor journal_t");
master = new account_t(NULL, "");
}
-
~journal_t();
void add_account(account_t * acct) {
diff --git a/main.cc b/main.cc
index 3ccea275..ebab70d2 100644
--- a/main.cc
+++ b/main.cc
@@ -39,7 +39,7 @@ namespace {
TIMER_DEF(read_cache, "reading cache file");
}
-#ifdef NO_CLEANUP
+#ifndef DO_CLEANUP
#define auto_ptr bogus_auto_ptr
@@ -71,7 +71,7 @@ namespace std {
};
}
-#endif // NO_CLEANUP
+#endif // !DO_CLEANUP
static void
regexps_to_predicate(std::list<std::string>::const_iterator begin,
@@ -369,10 +369,10 @@ int main(int argc, char * argv[], char * envp[])
// Setup the values of %t and %T, used in format strings
try {
-#ifdef NO_CLEANUP
- format_t::value_expr = parse_value_expr(config->value_expr);
-#else
+#ifdef DO_CLEANUP
format_t::value_expr.reset(parse_value_expr(config->value_expr));
+#else
+ format_t::value_expr = parse_value_expr(config->value_expr);
#endif
}
catch (const value_expr_error& err) {
@@ -382,10 +382,10 @@ int main(int argc, char * argv[], char * envp[])
}
try {
-#ifdef NO_CLEANUP
- format_t::total_expr = parse_value_expr(config->total_expr);
-#else
+#ifdef DO_CLEANUP
format_t::total_expr.reset(parse_value_expr(config->total_expr));
+#else
+ format_t::total_expr = parse_value_expr(config->total_expr);
#endif
}
catch (const value_expr_error& err) {
@@ -589,12 +589,14 @@ int main(int argc, char * argv[], char * envp[])
walk_accounts(journal->master, acct_formatter, sort_order.get());
acct_formatter.flush();
- journal->master->value = journal->master->total;
+ if (journal->master->data) {
+ ACCT_DATA(journal->master)->value = ACCT_DATA(journal->master)->total;
- if (journal->master->dflags & ACCOUNT_TO_DISPLAY) {
- std::string end_format = "--------------------\n";
- format.reset(end_format + f);
- format.format_elements(OUT(), details_t(journal->master));
+ if (ACCT_DATA(journal->master)->dflags & ACCOUNT_TO_DISPLAY) {
+ std::string end_format = "--------------------\n";
+ format.reset(end_format + f);
+ format.format_elements(OUT(), details_t(journal->master));
+ }
}
}
else if (command == "E") {
@@ -605,13 +607,14 @@ int main(int argc, char * argv[], char * envp[])
acct_formatter.flush();
}
-#ifndef NO_CLEANUP
+#ifdef DO_CLEANUP
// The transaction display flags (dflags) are not recorded in the
// binary cache, and only need to be cleared if the transactions
// are to be displayed a second time.
- clear_display_flags cleanup;
- walk_entries(journal->entries, cleanup);
- cleanup.flush();
+ clear_transaction_data xact_cleanup;
+ walk_entries(journal->entries, xact_cleanup);
+ clear_account_data acct_cleanup;
+ walk_accounts(journal->master, acct_cleanup);
#endif
TIMER_STOP(report_gen);
diff --git a/valexpr.cc b/valexpr.cc
index a06d2f98..acc46378 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -1,4 +1,5 @@
#include "valexpr.h"
+#include "walk.h"
#include "format.h"
#include "error.h"
#include "datetime.h"
@@ -83,8 +84,8 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case AMOUNT:
if (details.xact)
result = details.xact->amount;
- else if (details.account)
- result = details.account->value;
+ else if (details.account && ACCT_DATA(details.account))
+ result = ACCT_DATA(details.account)->value;
break;
case COST:
@@ -94,37 +95,37 @@ void value_expr_t::compute(value_t& result, const details_t& details,
else
result = details.xact->amount;
}
- else if (details.account) {
- result = details.account->value.cost();
+ else if (details.account && ACCT_DATA(details.account)) {
+ result = ACCT_DATA(details.account)->value.cost();
}
break;
case TOTAL:
- if (details.xact)
- result = details.xact->total;
- else if (details.account)
- result = details.account->total;
+ if (details.xact && XACT_DATA(details.xact))
+ result = XACT_DATA(details.xact)->total;
+ else if (details.account && ACCT_DATA(details.account))
+ result = ACCT_DATA(details.account)->total;
break;
case COST_TOTAL:
- if (details.xact)
- result = details.xact->total.cost();
- else if (details.account)
- result = details.account->total.cost();
+ if (details.xact && XACT_DATA(details.xact))
+ result = XACT_DATA(details.xact)->total.cost();
+ else if (details.account && ACCT_DATA(details.account))
+ result = ACCT_DATA(details.account)->total.cost();
break;
case VALUE_EXPR:
-#ifdef NO_CLEANUP
- assert(format_t::value_expr);
-#else
+#ifdef DO_CLEANUP
assert(format_t::value_expr.get());
+#else
+ assert(format_t::value_expr);
#endif
format_t::value_expr->compute(result, details);
break;
case TOTAL_EXPR:
-#ifdef NO_CLEANUP
- assert(format_t::total_expr);
-#else
+#ifdef DO_CLEANUP
assert(format_t::total_expr.get());
+#else
+ assert(format_t::total_expr);
#endif
format_t::total_expr->compute(result, details);
break;
@@ -173,17 +174,17 @@ void value_expr_t::compute(value_t& result, const details_t& details,
break;
case INDEX:
- if (details.xact)
- result = details.xact->index + 1;
- else if (details.account)
- result = details.account->subcount;
+ if (details.xact && XACT_DATA(details.xact))
+ result = XACT_DATA(details.xact)->index + 1;
+ else if (details.account && ACCT_DATA(details.account))
+ result = ACCT_DATA(details.account)->subcount;
break;
case COUNT:
- if (details.xact)
- result = details.xact->index + 1;
- else if (details.account)
- result = details.account->count;
+ if (details.xact && XACT_DATA(details.xact))
+ result = XACT_DATA(details.xact)->index + 1;
+ else if (details.account && ACCT_DATA(details.account))
+ result = ACCT_DATA(details.account)->count;
break;
case DEPTH:
@@ -194,15 +195,17 @@ void value_expr_t::compute(value_t& result, const details_t& details,
break;
case F_ARITH_MEAN:
- if (details.xact) {
+ if (details.xact && XACT_DATA(details.xact)) {
assert(left);
left->compute(result, details);
- result /= amount_t(details.xact->index + 1);
+ result /= amount_t(XACT_DATA(details.xact)->index + 1);
}
- else if (details.account && details.account->count) {
+ else if (details.account &&
+ ACCT_DATA(details.account) &&
+ ACCT_DATA(details.account)->count) {
assert(left);
left->compute(result, details);
- result /= amount_t(details.account->count);
+ result /= amount_t(ACCT_DATA(details.account)->count);
}
break;
diff --git a/walk.cc b/walk.cc
index fff19645..87680a79 100644
--- a/walk.cc
+++ b/walk.cc
@@ -20,11 +20,14 @@ void sort_transactions::flush()
void calc_transactions::operator()(transaction_t * xact)
{
- if (last_xact) {
- xact->total += last_xact->total;
- xact->index = last_xact->index + 1;
+ if (! xact->data)
+ xact->data = new transaction_data_t;
+
+ if (last_xact && last_xact->data) {
+ XACT_DATA(xact)->total += XACT_DATA(last_xact)->total;
+ XACT_DATA(xact)->index = XACT_DATA(last_xact)->index + 1;
} else {
- xact->index = 0;
+ XACT_DATA(xact)->index = 0;
}
if (inverted) {
@@ -33,8 +36,8 @@ void calc_transactions::operator()(transaction_t * xact)
xact->cost->negate();
}
- if (! (xact->dflags & TRANSACTION_NO_TOTAL))
- xact->total += *xact;
+ if (! (XACT_DATA(xact)->dflags & TRANSACTION_NO_TOTAL))
+ XACT_DATA(xact)->total += *xact;
(*handler)(xact);
@@ -47,6 +50,80 @@ void calc_transactions::operator()(transaction_t * xact)
last_xact = xact;
}
+
+static void handle_value(const value_t& value, account_t * account,
+ entry_t * entry, unsigned int flags,
+ transactions_deque& temps,
+ item_handler<transaction_t> * handler)
+{
+ balance_t * bal = NULL;
+
+ switch (value.type) {
+ case value_t::BOOLEAN:
+ case value_t::INTEGER:
+ case value_t::AMOUNT: {
+ transaction_t * xact = new transaction_t(account);
+ temps.push_back(xact);
+
+ xact->entry = entry;
+ switch (value.type) {
+ case value_t::BOOLEAN:
+ xact->amount = *((bool *) value.data);
+ break;
+ case value_t::INTEGER:
+ xact->amount = *((unsigned int *) value.data);
+ break;
+ case value_t::AMOUNT:
+ xact->amount = *((amount_t *) value.data);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (flags) {
+ if (! xact->data)
+ xact->data = new transaction_data_t;
+ XACT_DATA(xact)->dflags |= flags;
+ }
+
+ (*handler)(xact);
+ break;
+ }
+
+ case value_t::BALANCE_PAIR:
+ bal = &((balance_pair_t *) value.data)->quantity;
+ // fall through...
+
+ case value_t::BALANCE:
+ if (! bal)
+ bal = (balance_t *) value.data;
+
+ for (amounts_map::const_iterator i = bal->amounts.begin();
+ i != bal->amounts.end();
+ i++) {
+ transaction_t * xact = new transaction_t(account);
+ temps.push_back(xact);
+
+ xact->entry = entry;
+ xact->amount = (*i).second;
+
+ if (flags) {
+ if (! xact->data)
+ xact->data = new transaction_data_t;
+ XACT_DATA(xact)->dflags |= flags;
+ }
+
+ (*handler)(xact);
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
void collapse_transactions::report_cumulative_subtotal()
{
if (count == 1) {
@@ -54,23 +131,12 @@ void collapse_transactions::report_cumulative_subtotal()
} else {
assert(count > 1);
- totals_account->total = subtotal;
+ if (! totals_account->data)
+ totals_account->data = new account_data_t;
+ ACCT_DATA(totals_account)->total = subtotal;
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++) {
- transaction_t * total_xact = new transaction_t(totals_account);
- xact_temps.push_back(total_xact);
-
- total_xact->entry = last_entry;
- total_xact->amount = (*i).second;
-
- (*handler)(total_xact);
- }
-#endif
+ handle_value(result, totals_account, last_entry, 0, xact_temps, handler);
}
subtotal = 0;
@@ -99,26 +165,17 @@ void changed_value_transactions::operator()(transaction_t * xact)
entry->payee = "Commodities revalued";
entry->date = current;
-#if 0
- for (amounts_map::const_iterator i = diff.amounts.begin();
- i != diff.amounts.end();
- i++) {
- transaction_t * temp_xact = new transaction_t(NULL);
- xact_temps.push_back(temp_xact);
-
- temp_xact->entry = entry;
- temp_xact->amount = (*i).second;
- temp_xact->dflags |= TRANSACTION_NO_TOTAL;
-
- (*handler)(temp_xact);
- }
-#endif
+ handle_value(cur_bal, NULL, entry, TRANSACTION_NO_TOTAL, xact_temps,
+ handler);
}
}
if (xact) {
- if (changed_values_only)
- xact->dflags |= TRANSACTION_DISPLAYED;
+ if (changed_values_only) {
+ if (! xact->data)
+ xact->data = new transaction_data_t;
+ XACT_DATA(xact)->dflags |= TRANSACTION_DISPLAYED;
+ }
(*handler)(xact);
}
@@ -151,27 +208,23 @@ void subtotal_transactions::flush(const char * spec_fmt)
for (balances_map::iterator i = balances.begin();
i != balances.end();
i++) {
- entry->date = finish;
- transaction_t temp((*i).first);
- temp.entry = entry;
- temp.total = (*i).second;
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++) {
- transaction_t * xact = new transaction_t((*i).first);
- xact_temps.push_back(xact);
-
- xact->entry = entry;
- xact->amount = (*j).second;
- (*handler)(xact);
+ entry->date = finish;
+ {
+ transaction_t temp((*i).first);
+ temp.entry = entry;
+ {
+ std::auto_ptr<transaction_data_t> xact_data(new transaction_data_t);
+ temp.data = xact_data.get();
+ ((transaction_data_t *) temp.data)->total = (*i).second;
+ format_t::compute_total(result, details_t(&temp));
+ }
+ temp.data = NULL;
}
-#endif
+ entry->date = start;
+
+ handle_value(result, (*i).first, entry, 0, xact_temps, handler);
}
balances.clear();
diff --git a/walk.h b/walk.h
index 07632e9f..a456bd82 100644
--- a/walk.h
+++ b/walk.h
@@ -104,17 +104,67 @@ inline void walk_entries(entries_list& list,
//////////////////////////////////////////////////////////////////////
+#define TRANSACTION_HANDLED 0x0001
+#define TRANSACTION_DISPLAYED 0x0002
+#define TRANSACTION_NO_TOTAL 0x0004
+
+struct transaction_data_t
+{
+ value_t total;
+ unsigned int index;
+ unsigned short dflags;
+
+ transaction_data_t() : index(0), dflags(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_data_t");
+ }
+#ifdef DEBUG_ENABLED
+ ~transaction_data_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_data_t");
+ }
+#endif
+};
+
+#define XACT_DATA(xact) ((transaction_data_t *) ((xact)->data))
+
+#define ACCOUNT_DISPLAYED 0x1
+#define ACCOUNT_TO_DISPLAY 0x2
+
+struct account_data_t
+{
+ value_t value;
+ value_t total;
+ unsigned int count; // transactions counted toward total
+ unsigned int subcount;
+ unsigned short dflags;
+
+ account_data_t() : count(0), subcount(0), dflags(0) {
+ DEBUG_PRINT("ledger.memory.ctors", "ctor account_data_t");
+ }
+#ifdef DEBUG_ENABLED
+ ~account_data_t() {
+ DEBUG_PRINT("ledger.memory.dtors", "dtor account_data_t");
+ }
+#endif
+};
+
+#define ACCT_DATA(acct) ((account_data_t *) ((acct)->data))
+
+//////////////////////////////////////////////////////////////////////
+
class ignore_transactions : public item_handler<transaction_t>
{
public:
virtual void operator()(transaction_t * xact) {}
};
-class clear_display_flags : public item_handler<transaction_t>
+class clear_transaction_data : public item_handler<transaction_t>
{
public:
virtual void operator()(transaction_t * xact) {
- xact->dflags = 0;
+ if (xact->data) {
+ delete (transaction_data_t *) xact->data;
+ xact->data = NULL;
+ }
}
};
@@ -125,8 +175,11 @@ class set_account_value : public item_handler<transaction_t>
: item_handler<transaction_t>(handler) {}
virtual void operator()(transaction_t * xact) {
- xact->account->value += *xact;
- xact->account->subcount++;
+ if (! ACCT_DATA(xact->account))
+ xact->account->data = new account_data_t;
+
+ ACCT_DATA(xact->account)->value += *xact;
+ ACCT_DATA(xact->account)->subcount++;
if (handler)
(*handler)(xact);
@@ -196,11 +249,20 @@ class collapse_transactions : public item_handler<transaction_t>
}
virtual ~collapse_transactions() {
+ if (totals_account->data) {
+ delete (account_data_t *) totals_account->data;
+ totals_account->data = NULL;
+ }
delete totals_account;
for (transactions_deque::iterator i = xact_temps.begin();
i != xact_temps.end();
- i++)
+ i++) {
+ if ((*i)->data) {
+ delete (transaction_data_t *) (*i)->data;
+ (*i)->data = NULL;
+ }
delete *i;
+ }
}
virtual void flush() {
@@ -250,8 +312,13 @@ class changed_value_transactions : public item_handler<transaction_t>
for (transactions_deque::iterator i = xact_temps.begin();
i != xact_temps.end();
- i++)
+ i++) {
+ if ((*i)->data) {
+ delete (transaction_data_t *) (*i)->data;
+ (*i)->data = NULL;
+ }
delete *i;
+ }
}
virtual void flush() {
@@ -286,8 +353,13 @@ class subtotal_transactions : public item_handler<transaction_t>
for (transactions_deque::iterator i = xact_temps.begin();
i != xact_temps.end();
- i++)
+ i++) {
+ if ((*i)->data) {
+ delete (transaction_data_t *) (*i)->data;
+ (*i)->data = NULL;
+ }
delete *i;
+ }
}
void flush(const char * spec_fmt);
@@ -348,10 +420,13 @@ class related_transactions : public item_handler<transaction_t>
for (transactions_list::iterator i = xact->entry->transactions.begin();
i != xact->entry->transactions.end();
i++)
- if (! ((*i)->dflags & TRANSACTION_HANDLED) &&
+ if ((! (*i)->data ||
+ ! (XACT_DATA(*i)->dflags & TRANSACTION_HANDLED)) &&
(*i == xact ? also_matching :
! ((*i)->flags & TRANSACTION_AUTO))) {
- (*i)->dflags |= TRANSACTION_HANDLED;
+ if (! (*i)->data)
+ (*i)->data = new transaction_data_t;
+ XACT_DATA(*i)->dflags |= TRANSACTION_HANDLED;
(*handler)(*i);
}
}
@@ -363,16 +438,31 @@ class related_transactions : public item_handler<transaction_t>
// Account walking functions
//
+class clear_account_data : public item_handler<account_t>
+{
+ public:
+ virtual void operator()(account_t * account) {
+ if (account->data) {
+ delete (account_data_t *) account->data;
+ account->data = NULL;
+ }
+ }
+};
+
inline void sum_accounts(account_t * account) {
+ if (! account->data)
+ account->data = new account_data_t;
+
for (accounts_map::iterator i = account->accounts.begin();
i != account->accounts.end();
i++) {
sum_accounts((*i).second);
- account->total += (*i).second->total;
- account->count += (*i).second->count + (*i).second->subcount;
+ ACCT_DATA(account)->total += ACCT_DATA((*i).second)->total;
+ ACCT_DATA(account)->count += (ACCT_DATA((*i).second)->count +
+ ACCT_DATA((*i).second)->subcount);
}
- account->total += account->value;
- account->count += account->subcount;
+ ACCT_DATA(account)->total += ACCT_DATA(account)->value;
+ ACCT_DATA(account)->count += ACCT_DATA(account)->subcount;
}
typedef std::deque<account_t *> accounts_deque;