fix to textual parsing, and a bit of reconstruction in main.cc

This commit is contained in:
John Wiegley 2004-08-19 02:30:56 -04:00
parent 41604e0ea6
commit f62a4906d1
10 changed files with 285 additions and 257 deletions

View file

@ -1,4 +1,5 @@
#include "ledger.h" #include "ledger.h"
#include "error.h"
#include "util.h" #include "util.h"
#include "gmp.h" #include "gmp.h"
@ -7,8 +8,6 @@
#define MPZ(x) ((MP_INT *)(x)) #define MPZ(x) ((MP_INT *)(x))
#define INIT() if (! quantity) _init()
namespace ledger { namespace ledger {
static mpz_t full_divisor; static mpz_t full_divisor;
@ -229,8 +228,14 @@ amount_t& amount_t::operator=(const double value)
amount_t& amount_t::operator+=(const amount_t& amt) amount_t& amount_t::operator+=(const amount_t& amt)
{ {
if (amt.quantity) { if (amt.quantity) {
assert(! commodity || commodity == amt.commodity); if (! quantity) {
INIT(); _init();
commodity = amt.commodity;
}
if (commodity != amt.commodity)
throw amount_error("Adding amounts with different commodities");
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
} }
return *this; return *this;
@ -239,8 +244,14 @@ amount_t& amount_t::operator+=(const amount_t& amt)
amount_t& amount_t::operator-=(const amount_t& amt) amount_t& amount_t::operator-=(const amount_t& amt)
{ {
if (amt.quantity) { if (amt.quantity) {
assert(commodity == amt.commodity); if (! quantity) {
INIT(); _init();
commodity = amt.commodity;
}
if (commodity != amt.commodity)
throw amount_error("Subtracting amounts with different commodities");
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
} }
return *this; return *this;
@ -372,7 +383,10 @@ bool amount_t::operator<(const amount_t& amt) const
return amt > 0; return amt > 0;
if (! amt.quantity) // equivalent to zero if (! amt.quantity) // equivalent to zero
return *this < 0; return *this < 0;
assert(commodity == amt.commodity);
if (commodity != amt.commodity)
throw amount_error("Comparing amounts with different commodities");
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) < 0; return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) < 0;
} }
@ -382,7 +396,10 @@ bool amount_t::operator<=(const amount_t& amt) const
return amt >= 0; return amt >= 0;
if (! amt.quantity) // equivalent to zero if (! amt.quantity) // equivalent to zero
return *this <= 0; return *this <= 0;
assert(commodity == amt.commodity);
if (commodity != amt.commodity)
throw amount_error("Comparing amounts with different commodities");
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) <= 0; return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) <= 0;
} }
@ -392,7 +409,10 @@ bool amount_t::operator>(const amount_t& amt) const
return amt < 0; return amt < 0;
if (! amt.quantity) // equivalent to zero if (! amt.quantity) // equivalent to zero
return *this > 0; return *this > 0;
assert(commodity == amt.commodity);
if (commodity != amt.commodity)
throw amount_error("Comparing amounts with different commodities");
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) > 0; return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) > 0;
} }
@ -402,16 +422,23 @@ bool amount_t::operator>=(const amount_t& amt) const
return amt <= 0; return amt <= 0;
if (! amt.quantity) // equivalent to zero if (! amt.quantity) // equivalent to zero
return *this >= 0; return *this >= 0;
assert(commodity == amt.commodity);
if (commodity != amt.commodity)
throw amount_error("Comparing amounts with different commodities");
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) >= 0; return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) >= 0;
} }
bool amount_t::operator==(const amount_t& amt) const bool amount_t::operator==(const amount_t& amt) const
{ {
if (commodity != amt.commodity) if (! quantity && ! amt.quantity)
return true;
else if (! quantity || ! amt.quantity)
return false; return false;
assert(amt.quantity);
assert(quantity); if (commodity != amt.commodity)
throw amount_error("Comparing amounts with different commodities");
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) == 0; return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) == 0;
} }
@ -448,7 +475,10 @@ amount_t& amount_t::operator*=(const amount_t& amt)
if (! amt.quantity) if (! amt.quantity)
return *this; return *this;
INIT(); if (! quantity) {
_init();
commodity = amt.commodity;
}
mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), full_divisor); mpz_tdiv_q(MPZ(quantity), MPZ(quantity), full_divisor);
@ -461,7 +491,10 @@ amount_t& amount_t::operator/=(const amount_t& amt)
if (! amt.quantity) if (! amt.quantity)
return *this; return *this;
INIT(); if (! quantity) {
_init();
commodity = amt.commodity;
}
mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor);
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
@ -474,7 +507,10 @@ amount_t& amount_t::operator%=(const amount_t& amt)
if (! amt.quantity) if (! amt.quantity)
return *this; return *this;
INIT(); if (! quantity) {
_init();
commodity = amt.commodity;
}
mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor); mpz_mul(MPZ(quantity), MPZ(quantity), full_divisor);
mpz_tdiv_r(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_tdiv_r(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
@ -650,7 +686,7 @@ void parse_commodity(std::istream& in, std::string& symbol)
if (c == '"') if (c == '"')
in.get(c); in.get(c);
else else
assert(0); throw amount_error("Quoted commodity symbol lacks closing quote");
} else { } else {
READ_INTO(in, buf, 256, c, ! std::isspace(c) && ! std::isdigit(c) && READ_INTO(in, buf, 256, c, ! std::isspace(c) && ! std::isdigit(c) &&
c != '-' && c != '.'); c != '-' && c != '.');
@ -670,7 +706,8 @@ void amount_t::parse(std::istream& in)
unsigned int flags = COMMODITY_STYLE_DEFAULTS;; unsigned int flags = COMMODITY_STYLE_DEFAULTS;;
unsigned int precision = MAX_PRECISION; unsigned int precision = MAX_PRECISION;
INIT(); if (! quantity)
_init();
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
if (std::isdigit(c) || c == '.' || c == '-') { if (std::isdigit(c) || c == '.' || c == '-') {
@ -794,7 +831,8 @@ void amount_t::read_quantity(std::istream& in)
in.read((char *)&len, sizeof(len)); in.read((char *)&len, sizeof(len));
if (len) { if (len) {
in.read(buf, len); in.read(buf, len);
INIT(); if (! quantity)
_init();
#ifdef WRITE_AMOUNTS_TEXTUALLY #ifdef WRITE_AMOUNTS_TEXTUALLY
buf[len] = '\0'; buf[len] = '\0';
mpz_set_str(MPZ(quantity), buf, 10); mpz_set_str(MPZ(quantity), buf, 10);

View file

@ -97,7 +97,8 @@ Commodity reporting:\n\
-A, --average report average transaction amount\n\ -A, --average report average transaction amount\n\
-D, --deviation report deviation from the average\n\ -D, --deviation report deviation from the average\n\
-X, --trend report average deviation from the average\n\ -X, --trend report average deviation from the average\n\
-Z, --weighted-trend same as trend, but older values less significant\n\n\ -Z, --weighted-trend same as trend, but older values are less significant\n\
(-D, -X and -Z make little sense in balance reports)\n\n\
Commands:\n\ Commands:\n\
balance [REGEXP]... show balance totals for matching accounts\n\ balance [REGEXP]... show balance totals for matching accounts\n\
register [REGEXP]... show register of matching transactions\n\ register [REGEXP]... show register of matching transactions\n\
@ -345,7 +346,7 @@ OPT_BEGIN(trend, "X") {
OPT_BEGIN(weighted_trend, "Z") { OPT_BEGIN(weighted_trend, "Z") {
config->value_expr = "a"; config->value_expr = "a";
config->total_expr config->total_expr
= "MD(MO/(1+(((t-d)/(30*86400))<0?0:((t-d)/(30*86400)))))"; = "MD(MO/(1+(((N-d)/(30*86400))<0?0:((N-d)/(30*86400)))))";
} OPT_END(weighted_trend); } OPT_END(weighted_trend);
} // namespace ledger } // namespace ledger

24
error.h
View file

@ -8,8 +8,7 @@
namespace ledger { namespace ledger {
class error : public std::exception class error : public std::exception {
{
std::string reason; std::string reason;
public: public:
error(const std::string& _reason) throw() : reason(_reason) {} error(const std::string& _reason) throw() : reason(_reason) {}
@ -20,36 +19,37 @@ class error : public std::exception
} }
}; };
class compute_error : public error class amount_error : public error {
{ public:
amount_error(const std::string& reason) throw() : error(reason) {}
virtual ~amount_error() throw() {}
};
class compute_error : public error {
public: public:
compute_error(const std::string& reason) throw() : error(reason) {} compute_error(const std::string& reason) throw() : error(reason) {}
virtual ~compute_error() throw() {} virtual ~compute_error() throw() {}
}; };
class value_expr_error : public error class value_expr_error : public error {
{
public: public:
value_expr_error(const std::string& reason) throw() : error(reason) {} value_expr_error(const std::string& reason) throw() : error(reason) {}
virtual ~value_expr_error() throw() {} virtual ~value_expr_error() throw() {}
}; };
class interval_expr_error : public error class interval_expr_error : public error {
{
public: public:
interval_expr_error(const std::string& reason) throw() : error(reason) {} interval_expr_error(const std::string& reason) throw() : error(reason) {}
virtual ~interval_expr_error() throw() {} virtual ~interval_expr_error() throw() {}
}; };
class format_error : public error class format_error : public error {
{
public: public:
format_error(const std::string& reason) throw() : error(reason) {} format_error(const std::string& reason) throw() : error(reason) {}
virtual ~format_error() throw() {} virtual ~format_error() throw() {}
}; };
class parse_error : public error class parse_error : public error {
{
unsigned int line; unsigned int line;
std::string file; std::string file;
public: public:

View file

@ -52,7 +52,11 @@ element_t * format_t::parse_elements(const std::string& fmt)
char * q = buf; char * q = buf;
for (const char * p = fmt.c_str(); *p; p++) { for (const char * p = fmt.c_str(); *p; p++) {
if (*p == '%') { if (*p != '%') {
*q++ = *p;
continue;
}
if (! result) { if (! result) {
current = result = new element_t; current = result = new element_t;
} else { } else {
@ -141,9 +145,6 @@ element_t * format_t::parse_elements(const std::string& fmt)
case 'T': current->type = element_t::TOTAL; break; case 'T': current->type = element_t::TOTAL; break;
case '_': current->type = element_t::SPACER; break; case '_': current->type = element_t::SPACER; break;
} }
} else {
*q++ = *p;
}
} }
if (q != buf) { if (q != buf) {

View file

@ -113,10 +113,6 @@ class format_transactions : public item_handler<transaction_t>
first_line_format(_first_line_format), first_line_format(_first_line_format),
next_lines_format(_next_lines_format), last_entry(NULL) {} next_lines_format(_next_lines_format), last_entry(NULL) {}
virtual ~format_transactions() {
flush();
}
virtual void flush() { virtual void flush() {
output_stream.flush(); output_stream.flush();
} }
@ -148,10 +144,6 @@ class format_account : public item_handler<account_t>
: output_stream(_output_stream), format(_format), : output_stream(_output_stream), format(_format),
disp_pred(display_predicate) {} disp_pred(display_predicate) {}
virtual ~format_account() {
flush();
}
static bool disp_subaccounts_p(const account_t * account, static bool disp_subaccounts_p(const account_t * account,
const item_predicate<account_t>& disp_pred, const item_predicate<account_t>& disp_pred,
const account_t *& to_show); const account_t *& to_show);
@ -201,10 +193,6 @@ class format_equity : public item_handler<account_t>
first_line_format.format_elements(output_stream, details_t(&header_entry)); first_line_format.format_elements(output_stream, details_t(&header_entry));
} }
virtual ~format_equity() {
flush();
}
virtual void flush() { virtual void flush() {
account_t summary(NULL, "Equity:Opening Balances"); account_t summary(NULL, "Equity:Opening Balances");
summary.value = - total; summary.value = - total;

153
main.cc
View file

@ -106,8 +106,10 @@ regexps_to_predicate(std::list<std::string>::const_iterator begin,
if (i != regexps.begin()) { if (i != regexps.begin()) {
config->predicate += "!"; config->predicate += "!";
} }
else if (add_account_short_masks && else if (add_account_short_masks) {
(*i).find(':') == std::string::npos) { if ((*i).find(':') != std::string::npos) {
config->show_subtotal = true;
} else {
if (! config->display_predicate.empty()) if (! config->display_predicate.empty())
config->display_predicate += "&"; config->display_predicate += "&";
else if (! config->show_empty) else if (! config->show_empty)
@ -117,6 +119,7 @@ regexps_to_predicate(std::list<std::string>::const_iterator begin,
config->display_predicate += *i; config->display_predicate += *i;
config->display_predicate += ")/"; config->display_predicate += ")/";
} }
}
if (! account_regexp) if (! account_regexp)
config->predicate += "/"; config->predicate += "/";
@ -257,7 +260,28 @@ int main(int argc, char * argv[], char * envp[])
return 1; return 1;
} }
// Process the remaining command-line arguments // Configure some other options depending on report type
bool show_all_related = false;
if (command == "p" || command == "e") {
config->show_related =
show_all_related =
config->show_subtotal = true;
}
else if (command == "E") {
config->show_subtotal = true;
}
else if (config->show_related) {
if (command == "r") {
config->show_inverted = true;
} else {
config->show_subtotal = true;
show_all_related = true;
}
}
// Process remaining command-line arguments
std::auto_ptr<entry_t> new_entry; std::auto_ptr<entry_t> new_entry;
if (command == "e") { if (command == "e") {
@ -278,7 +302,7 @@ int main(int argc, char * argv[], char * envp[])
regexps_to_predicate(i, args.end(), config); regexps_to_predicate(i, args.end(), config);
} }
// Compile the predicates // Setup default value for the display predicate
if (config->display_predicate.empty()) { if (config->display_predicate.empty()) {
if (command == "b") { if (command == "b") {
@ -295,7 +319,7 @@ int main(int argc, char * argv[], char * envp[])
} }
} }
// Compile the sorting criteria // Compile sorting criteria
std::auto_ptr<value_expr_t> sort_order; std::auto_ptr<value_expr_t> sort_order;
@ -319,7 +343,7 @@ int main(int argc, char * argv[], char * envp[])
} }
} }
// Setup the meaning of %t and %T, used in format strings // Setup the values of %t and %T, used in format strings
try { try {
#ifdef NO_CLEANUP #ifdef NO_CLEANUP
@ -347,27 +371,7 @@ int main(int argc, char * argv[], char * envp[])
return 1; return 1;
} }
// Configure some option depending on the report type // Setup local and global variables, depending on config settings.
bool show_all_related = false;
if (command == "p" || command == "e") {
config->show_related =
show_all_related =
config->show_subtotal = true;
}
else if (command == "E") {
config->show_subtotal = true;
}
else if (config->show_related) {
if (command == "r")
config->show_inverted = true;
else
show_all_related = true;
}
// Setup a few local and global variables, depending on the config
// settings.
std::auto_ptr<std::ostream> output_stream; std::auto_ptr<std::ostream> output_stream;
std::auto_ptr<interval_t> report_interval; std::auto_ptr<interval_t> report_interval;
@ -458,59 +462,23 @@ int main(int argc, char * argv[], char * envp[])
TIMER_START(report_gen); TIMER_START(report_gen);
if (command == "b") {
std::auto_ptr<item_handler<transaction_t> > formatter;
formatter.reset(new add_to_account_value);
if (config->show_related)
formatter.reset(new related_transactions(formatter.release(),
show_all_related));
formatter.reset(new filter_transactions(formatter.release(),
config->predicate));
walk_entries(journal->entries, *formatter);
formatter->flush();
format_account acct_formatter(OUT(), format, config->display_predicate);
sum_accounts(journal->master);
walk_accounts(journal->master, acct_formatter, sort_order.get());
acct_formatter.flush();
journal->master->value = journal->master->total;
if (format_account::display_account(journal->master,
item_predicate<account_t>("T"),
true)) {
std::string end_format = "--------------------\n";
format.reset(end_format + f);
format.format_elements(OUT(), details_t(journal->master));
}
}
else if (command == "E") {
std::auto_ptr<item_handler<transaction_t> > formatter;
formatter.reset(new add_to_account_value);
formatter.reset(new filter_transactions(formatter.release(),
config->predicate));
walk_entries(journal->entries, *formatter);
formatter->flush();
format_equity acct_formatter(OUT(), format, nformat,
config->display_predicate);
sum_accounts(journal->master);
walk_accounts(journal->master, acct_formatter, sort_order.get());
acct_formatter.flush();
}
else if (command == "e") {
format_transactions formatter(OUT(), format, nformat);
walk_transactions(new_entry->transactions, formatter);
formatter.flush();
}
else {
std::auto_ptr<item_handler<transaction_t> > formatter;
// Stack up all the formatter needed to fulfills the user's // Stack up all the formatter needed to fulfills the user's
// requests. Some of these are order dependent, in terms of // requests. Some of these are order dependent, in terms of
// whether calc_transactions occurs before or after them. // whether calc_transactions occurs before or after them.
std::auto_ptr<item_handler<transaction_t> > formatter;
// format_transactions write each transaction received to the // format_transactions write each transaction received to the
// output stream. // output stream.
if (command == "b" || command == "E") {
#ifdef DEBUG_ENABLED
if (DEBUG("ledger.balance.items")) {
formatter.reset(new format_transactions(OUT(), format, nformat));
formatter.reset(new set_account_value(formatter.release()));
} else
#endif
formatter.reset(new set_account_value);
} else {
formatter.reset(new format_transactions(OUT(), format, nformat)); formatter.reset(new format_transactions(OUT(), format, nformat));
// sort_transactions will sort all the transactions it sees, based // sort_transactions will sort all the transactions it sees, based
@ -562,6 +530,7 @@ int main(int argc, char * argv[], char * envp[])
interval_begin)); interval_begin));
else if (config->days_of_the_week) else if (config->days_of_the_week)
formatter.reset(new dow_transactions(formatter.release())); formatter.reset(new dow_transactions(formatter.release()));
}
// related_transactions will pass along all transactions related // related_transactions will pass along all transactions related
// to the transaction received. If `show_all_related' is true, // to the transaction received. If `show_all_related' is true,
@ -579,10 +548,43 @@ int main(int argc, char * argv[], char * envp[])
// Once the filters are chained, walk `journal's entries and start // Once the filters are chained, walk `journal's entries and start
// feeding each transaction that matches `predicate' to the chain. // feeding each transaction that matches `predicate' to the chain.
if (command == "e")
walk_transactions(new_entry->transactions, *formatter);
else
walk_entries(journal->entries, *formatter); walk_entries(journal->entries, *formatter);
formatter->flush(); formatter->flush();
#ifdef DEBUG_ENABLED // At this point all printing is finished if doing a register
// report; but if it's a balance or equity report, we've only
// finished calculating the totals and there is still reporting to
// be done.
if (command == "b") {
format_account acct_formatter(OUT(), format, config->display_predicate);
sum_accounts(journal->master);
walk_accounts(journal->master, acct_formatter, sort_order.get());
acct_formatter.flush();
journal->master->value = journal->master->total;
if (format_account::display_account(journal->master,
item_predicate<account_t>("T"),
true)) {
std::string end_format = "--------------------\n";
format.reset(end_format + f);
format.format_elements(OUT(), details_t(journal->master));
}
}
else if (command == "E") {
format_equity acct_formatter(OUT(), format, nformat,
config->display_predicate);
sum_accounts(journal->master);
walk_accounts(journal->master, acct_formatter, sort_order.get());
acct_formatter.flush();
}
#ifndef NO_CLEANUP
// The transaction display flags (dflags) are not recorded in the // The transaction display flags (dflags) are not recorded in the
// binary cache, and only need to be cleared if the transactions // binary cache, and only need to be cleared if the transactions
// are to be displayed a second time. // are to be displayed a second time.
@ -590,7 +592,6 @@ int main(int argc, char * argv[], char * envp[])
walk_entries(journal->entries, cleanup); walk_entries(journal->entries, cleanup);
cleanup.flush(); cleanup.flush();
#endif #endif
}
TIMER_STOP(report_gen); TIMER_STOP(report_gen);

View file

@ -9,3 +9,4 @@
2004/05/29 Restaurant 2004/05/29 Restaurant
Expenses:Food $50.00 Expenses:Food $50.00
Liabilities:MasterCard Liabilities:MasterCard

View file

@ -110,6 +110,10 @@ transaction_t * parse_transaction(std::istream& in, account_t * account,
in.getline(line, MAX_LINE); in.getline(line, MAX_LINE);
linenum++; linenum++;
// Skip a possible blank line
if (*skip_ws(line) == '\0')
return NULL;
return parse_transaction_text(line, account, entry); return parse_transaction_text(line, account, entry);
} }
@ -321,8 +325,7 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
if (peek_next_nonws(in) != '\n') { if (peek_next_nonws(in) != '\n') {
in.getline(line, MAX_LINE); in.getline(line, MAX_LINE);
linenum++; linenum++;
throw parse_error(path, linenum, throw parse_error(path, linenum, "Line begins with whitespace");
"Ignoring entry beginning with whitespace");
} }
// fall through... // fall through...

View file

@ -59,8 +59,8 @@ void collapse_transactions::report_cumulative_subtotal()
for (amounts_map::const_iterator i = result.amounts.begin(); for (amounts_map::const_iterator i = result.amounts.begin();
i != result.amounts.end(); i != result.amounts.end();
i++) { i++) {
transaction_t * total_xact = new transaction_t(last_entry, transaction_t * total_xact
totals_account); = new transaction_t(last_entry, totals_account);
xact_temps.push_back(total_xact); xact_temps.push_back(total_xact);
total_xact->amount = (*i).second; total_xact->amount = (*i).second;

33
walk.h
View file

@ -18,18 +18,19 @@ struct item_handler {
public: public:
item_handler() : handler(NULL) {} item_handler() : handler(NULL) {}
item_handler(item_handler * _handler) : handler(_handler) {} item_handler(item_handler * _handler) : handler(_handler) {}
virtual ~item_handler() {}
virtual void close() { virtual ~item_handler() {
if (handler) { if (handler)
delete handler; delete handler;
handler = NULL;
}
} }
virtual void flush() { virtual void flush() {
if (handler) if (handler)
handler->flush(); handler->flush();
} }
virtual void operator()(T * item) = 0; virtual void operator()(T * item) {
if (handler)
(*handler)(item);
}
}; };
template <typename T> template <typename T>
@ -112,12 +113,18 @@ class clear_display_flags : public item_handler<transaction_t>
} }
}; };
class add_to_account_value : public item_handler<transaction_t> class set_account_value : public item_handler<transaction_t>
{ {
public: public:
set_account_value(item_handler<transaction_t> * handler = NULL)
: item_handler<transaction_t>(handler) {}
virtual void operator()(transaction_t * xact) { virtual void operator()(transaction_t * xact) {
xact->account->value += *xact; xact->account->value += *xact;
xact->account->count++; xact->account->count++;
if (handler)
(*handler)(xact);
} }
}; };
@ -131,7 +138,6 @@ class sort_transactions : public item_handler<transaction_t>
const value_expr_t * _sort_order) const value_expr_t * _sort_order)
: item_handler<transaction_t>(handler), : item_handler<transaction_t>(handler),
sort_order(_sort_order) {} sort_order(_sort_order) {}
virtual ~sort_transactions() { close(); }
virtual void flush(); virtual void flush();
virtual void operator()(transaction_t * xact) { virtual void operator()(transaction_t * xact) {
@ -148,8 +154,6 @@ class filter_transactions : public item_handler<transaction_t>
const std::string& predicate) const std::string& predicate)
: item_handler<transaction_t>(handler), pred(predicate) {} : item_handler<transaction_t>(handler), pred(predicate) {}
virtual ~filter_transactions() { close(); }
virtual void operator()(transaction_t * xact) { virtual void operator()(transaction_t * xact) {
if (pred(xact)) if (pred(xact))
(*handler)(xact); (*handler)(xact);
@ -167,8 +171,6 @@ class calc_transactions : public item_handler<transaction_t>
: item_handler<transaction_t>(handler), : item_handler<transaction_t>(handler),
last_xact(NULL), inverted(_inverted) {} last_xact(NULL), inverted(_inverted) {}
virtual ~calc_transactions() { close(); }
virtual void operator()(transaction_t * xact); virtual void operator()(transaction_t * xact);
}; };
@ -189,7 +191,6 @@ class collapse_transactions : public item_handler<transaction_t>
} }
virtual ~collapse_transactions() { virtual ~collapse_transactions() {
close();
delete totals_account; delete totals_account;
for (transactions_deque::iterator i = xact_temps.begin(); for (transactions_deque::iterator i = xact_temps.begin();
i != xact_temps.end(); i != xact_temps.end();
@ -237,8 +238,6 @@ class changed_value_transactions : public item_handler<transaction_t>
changed_values_only(_changed_values_only), last_xact(NULL) {} changed_values_only(_changed_values_only), last_xact(NULL) {}
virtual ~changed_value_transactions() { virtual ~changed_value_transactions() {
close();
for (entries_deque::iterator i = entry_temps.begin(); for (entries_deque::iterator i = entry_temps.begin();
i != entry_temps.end(); i != entry_temps.end();
i++) i++)
@ -275,8 +274,6 @@ class subtotal_transactions : public item_handler<transaction_t>
: item_handler<transaction_t>(handler) {} : item_handler<transaction_t>(handler) {}
virtual ~subtotal_transactions() { virtual ~subtotal_transactions() {
close();
for (entries_deque::iterator i = entry_temps.begin(); for (entries_deque::iterator i = entry_temps.begin();
i != entry_temps.end(); i != entry_temps.end();
i++) i++)
@ -342,8 +339,6 @@ class related_transactions : public item_handler<transaction_t>
: item_handler<transaction_t>(handler), : item_handler<transaction_t>(handler),
also_matching(_also_matching) {} also_matching(_also_matching) {}
virtual ~related_transactions() { close(); }
virtual void operator()(transaction_t * xact) { virtual void operator()(transaction_t * xact) {
for (transactions_list::iterator i = xact->entry->transactions.begin(); for (transactions_list::iterator i = xact->entry->transactions.begin();
i != xact->entry->transactions.end(); i != xact->entry->transactions.end();