changed the management of "xdata" in walk.h
This commit is contained in:
parent
50a322adcf
commit
79b664f6f0
11 changed files with 396 additions and 456 deletions
63
config.cc
63
config.cc
|
|
@ -44,7 +44,6 @@ config_t::config_t()
|
||||||
|
|
||||||
use_cache = false;
|
use_cache = false;
|
||||||
cache_dirty = false;
|
cache_dirty = false;
|
||||||
sort_order = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -168,25 +167,6 @@ void config_t::process_options(const std::string& command,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the sort_string
|
|
||||||
|
|
||||||
if (! sort_order && ! sort_string.empty()) {
|
|
||||||
try {
|
|
||||||
std::istringstream stream(sort_string);
|
|
||||||
sort_order = parse_value_expr(stream);
|
|
||||||
if (stream.peek() != -1) {
|
|
||||||
throw value_expr_error(std::string("Unexpected character '") +
|
|
||||||
char(stream.peek()) + "'");
|
|
||||||
}
|
|
||||||
else if (! sort_order) {
|
|
||||||
throw error("Failed to parse sort criteria!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const value_expr_error& err) {
|
|
||||||
throw error(std::string("In sort criteria: ") + err.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the values of %t and %T, used in format strings
|
// Setup the values of %t and %T, used in format strings
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -218,35 +198,6 @@ void config_t::process_options(const std::string& command,
|
||||||
pricing_leeway,
|
pricing_leeway,
|
||||||
cache_dirty);
|
cache_dirty);
|
||||||
|
|
||||||
// Parse the interval specifier, if provided
|
|
||||||
|
|
||||||
if (! report_interval && ! interval_text.empty()) {
|
|
||||||
try {
|
|
||||||
std::istringstream stream(interval_text);
|
|
||||||
|
|
||||||
report_interval.parse(stream);
|
|
||||||
|
|
||||||
if (report_interval.begin) {
|
|
||||||
if (! predicate.empty())
|
|
||||||
predicate += "&";
|
|
||||||
char buf[32];
|
|
||||||
std::sprintf(buf, "d>=%lu", report_interval.begin);
|
|
||||||
predicate += buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (report_interval.end) {
|
|
||||||
if (! predicate.empty())
|
|
||||||
predicate += "&";
|
|
||||||
char buf[32];
|
|
||||||
std::sprintf(buf, "d<%lu", report_interval.end);
|
|
||||||
predicate += buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const interval_expr_error& err) {
|
|
||||||
throw error(std::string("In interval (-z) specifier: ") + err.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format_t::date_format.empty() && ! date_format.empty())
|
if (format_t::date_format.empty() && ! date_format.empty())
|
||||||
format_t::date_format = date_format;
|
format_t::date_format = date_format;
|
||||||
|
|
||||||
|
|
@ -557,11 +508,11 @@ OPT_BEGIN(related, "r") {
|
||||||
} OPT_END(related);
|
} OPT_END(related);
|
||||||
|
|
||||||
OPT_BEGIN(interval, "p:") {
|
OPT_BEGIN(interval, "p:") {
|
||||||
config.interval_text = optarg;
|
config.report_interval = optarg;
|
||||||
} OPT_END(interval);
|
} OPT_END(interval);
|
||||||
|
|
||||||
OPT_BEGIN(weekly, "W") {
|
OPT_BEGIN(weekly, "W") {
|
||||||
config.interval_text = "weekly";
|
config.report_interval = "weekly";
|
||||||
} OPT_END(weekly);
|
} OPT_END(weekly);
|
||||||
|
|
||||||
OPT_BEGIN(dow, "") {
|
OPT_BEGIN(dow, "") {
|
||||||
|
|
@ -569,11 +520,11 @@ OPT_BEGIN(dow, "") {
|
||||||
} OPT_END(dow);
|
} OPT_END(dow);
|
||||||
|
|
||||||
OPT_BEGIN(monthly, "M") {
|
OPT_BEGIN(monthly, "M") {
|
||||||
config.interval_text = "monthly";
|
config.report_interval = "monthly";
|
||||||
} OPT_END(monthly);
|
} OPT_END(monthly);
|
||||||
|
|
||||||
OPT_BEGIN(yearly, "Y") {
|
OPT_BEGIN(yearly, "Y") {
|
||||||
config.interval_text = "yearly";
|
config.report_interval = "yearly";
|
||||||
} OPT_END(yearly);
|
} OPT_END(yearly);
|
||||||
|
|
||||||
OPT_BEGIN(limit, "l:") {
|
OPT_BEGIN(limit, "l:") {
|
||||||
|
|
@ -721,7 +672,7 @@ void export_config()
|
||||||
.def_readwrite("account", &config_t::account)
|
.def_readwrite("account", &config_t::account)
|
||||||
.def_readwrite("predicate", &config_t::predicate)
|
.def_readwrite("predicate", &config_t::predicate)
|
||||||
.def_readwrite("display_predicate", &config_t::display_predicate)
|
.def_readwrite("display_predicate", &config_t::display_predicate)
|
||||||
.def_readwrite("interval_text", &config_t::interval_text)
|
.def_readwrite("report_interval", &config_t::report_interval)
|
||||||
.def_readwrite("format_string", &config_t::format_string)
|
.def_readwrite("format_string", &config_t::format_string)
|
||||||
.def_readwrite("date_format", &config_t::date_format)
|
.def_readwrite("date_format", &config_t::date_format)
|
||||||
.def_readwrite("sort_string", &config_t::sort_string)
|
.def_readwrite("sort_string", &config_t::sort_string)
|
||||||
|
|
@ -741,12 +692,8 @@ void export_config()
|
||||||
|
|
||||||
.def_readwrite("use_cache", &config_t::use_cache)
|
.def_readwrite("use_cache", &config_t::use_cache)
|
||||||
.def_readwrite("cache_dirty", &config_t::cache_dirty)
|
.def_readwrite("cache_dirty", &config_t::cache_dirty)
|
||||||
.def_readwrite("report_interval", &config_t::report_interval)
|
|
||||||
.def_readwrite("format", &config_t::format)
|
.def_readwrite("format", &config_t::format)
|
||||||
.def_readwrite("nformat", &config_t::nformat)
|
.def_readwrite("nformat", &config_t::nformat)
|
||||||
.add_property("sort_order",
|
|
||||||
make_getter(&config_t::sort_order,
|
|
||||||
return_value_policy<reference_existing_object>()))
|
|
||||||
|
|
||||||
.def("process_options", py_process_options)
|
.def("process_options", py_process_options)
|
||||||
;
|
;
|
||||||
|
|
|
||||||
10
config.h
10
config.h
|
|
@ -34,7 +34,7 @@ struct config_t
|
||||||
std::string account;
|
std::string account;
|
||||||
std::string predicate;
|
std::string predicate;
|
||||||
std::string display_predicate;
|
std::string display_predicate;
|
||||||
std::string interval_text;
|
std::string report_interval;
|
||||||
std::string format_string;
|
std::string format_string;
|
||||||
std::string date_format;
|
std::string date_format;
|
||||||
std::string sort_string;
|
std::string sort_string;
|
||||||
|
|
@ -56,22 +56,14 @@ struct config_t
|
||||||
|
|
||||||
bool use_cache;
|
bool use_cache;
|
||||||
bool cache_dirty;
|
bool cache_dirty;
|
||||||
interval_t report_interval;
|
|
||||||
format_t format;
|
format_t format;
|
||||||
format_t nformat;
|
format_t nformat;
|
||||||
|
|
||||||
value_expr_t * sort_order;
|
|
||||||
|
|
||||||
config_t();
|
config_t();
|
||||||
config_t(const config_t&) {
|
config_t(const config_t&) {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
~config_t() {
|
|
||||||
if (sort_order)
|
|
||||||
delete sort_order;
|
|
||||||
}
|
|
||||||
|
|
||||||
void process_options(const std::string& command,
|
void process_options(const std::string& command,
|
||||||
strings_list::iterator arg,
|
strings_list::iterator arg,
|
||||||
strings_list::iterator args_end);
|
strings_list::iterator args_end);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ std::string partial_account_name(const account_t& account)
|
||||||
for (const account_t * acct = &account;
|
for (const account_t * acct = &account;
|
||||||
acct && acct->parent;
|
acct && acct->parent;
|
||||||
acct = acct->parent) {
|
acct = acct->parent) {
|
||||||
if (acct->data && ACCT_DATA(acct)->dflags & ACCOUNT_DISPLAYED)
|
if (account_has_xdata(*acct) &&
|
||||||
|
account_xdata(*acct).dflags & ACCOUNT_DISPLAYED)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
|
|
@ -356,7 +357,8 @@ void format_t::format(std::ostream& out, const details_t& details) const
|
||||||
for (const account_t * acct = details.account;
|
for (const account_t * acct = details.account;
|
||||||
acct;
|
acct;
|
||||||
acct = acct->parent)
|
acct = acct->parent)
|
||||||
if (acct->data && ACCT_DATA(acct)->dflags & ACCOUNT_DISPLAYED) {
|
if (account_has_xdata(*acct) &&
|
||||||
|
account_xdata(*acct).dflags & ACCOUNT_DISPLAYED) {
|
||||||
if (elem->min_width > 0 || elem->max_width > 0)
|
if (elem->min_width > 0 || elem->max_width > 0)
|
||||||
out.width(elem->min_width > elem->max_width ?
|
out.width(elem->min_width > elem->max_width ?
|
||||||
elem->min_width : elem->max_width);
|
elem->min_width : elem->max_width);
|
||||||
|
|
@ -412,7 +414,8 @@ bool format_account::display_account(const account_t& account,
|
||||||
const item_predicate<account_t>& disp_pred)
|
const item_predicate<account_t>& disp_pred)
|
||||||
{
|
{
|
||||||
// Never display an account that has already been displayed.
|
// Never display an account that has already been displayed.
|
||||||
if (account.data && ACCT_DATA_(account)->dflags & ACCOUNT_DISPLAYED)
|
if (account_has_xdata(account) &&
|
||||||
|
account_xdata(account).dflags & ACCOUNT_DISPLAYED)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// At this point, one of two possibilities exists: the account is a
|
// At this point, one of two possibilities exists: the account is a
|
||||||
|
|
|
||||||
32
format.h
32
format.h
|
|
@ -108,17 +108,15 @@ class format_transactions : public item_handler<transaction_t>
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(transaction_t& xact) {
|
virtual void operator()(transaction_t& xact) {
|
||||||
if (! xact.data ||
|
if (! transaction_has_xdata(xact) ||
|
||||||
! (XACT_DATA_(xact)->dflags & TRANSACTION_DISPLAYED)) {
|
! (transaction_xdata(xact).dflags & TRANSACTION_DISPLAYED)) {
|
||||||
if (last_entry != xact.entry) {
|
if (last_entry != xact.entry) {
|
||||||
first_line_format.format(output_stream, details_t(xact));
|
first_line_format.format(output_stream, details_t(xact));
|
||||||
last_entry = xact.entry;
|
last_entry = xact.entry;
|
||||||
} else {
|
} else {
|
||||||
next_lines_format.format(output_stream, details_t(xact));
|
next_lines_format.format(output_stream, details_t(xact));
|
||||||
}
|
}
|
||||||
if (! xact.data)
|
transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
|
||||||
xact.data = new transaction_data_t;
|
|
||||||
XACT_DATA_(xact)->dflags |= TRANSACTION_DISPLAYED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -155,14 +153,10 @@ class format_account : public item_handler<account_t>
|
||||||
virtual void operator()(account_t& account) {
|
virtual void operator()(account_t& account) {
|
||||||
if (display_account(account, disp_pred)) {
|
if (display_account(account, disp_pred)) {
|
||||||
if (! account.parent) {
|
if (! account.parent) {
|
||||||
if (! account.data)
|
account_xdata(account).dflags |= ACCOUNT_TO_DISPLAY;
|
||||||
account.data = new account_data_t;
|
|
||||||
ACCT_DATA_(account)->dflags |= ACCOUNT_TO_DISPLAY;
|
|
||||||
} else {
|
} else {
|
||||||
format.format(output_stream, details_t(account));
|
format.format(output_stream, details_t(account));
|
||||||
if (! account.data)
|
account_xdata(account).dflags |= ACCOUNT_DISPLAYED;
|
||||||
account.data = new account_data_t;
|
|
||||||
ACCT_DATA_(account)->dflags |= ACCOUNT_DISPLAYED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -194,11 +188,11 @@ class format_equity : public item_handler<account_t>
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void flush() {
|
virtual void flush() {
|
||||||
|
account_xdata_t xdata;
|
||||||
|
xdata.value = total;
|
||||||
|
xdata.value.negate();
|
||||||
account_t summary(NULL, "Equity:Opening Balances");
|
account_t summary(NULL, "Equity:Opening Balances");
|
||||||
std::auto_ptr<account_data_t> acct_data(new account_data_t);
|
summary.data = &xdata;
|
||||||
summary.data = acct_data.get();
|
|
||||||
((account_data_t *) summary.data)->value = total;
|
|
||||||
((account_data_t *) summary.data)->value.negate();
|
|
||||||
next_lines_format.format(output_stream, details_t(summary));
|
next_lines_format.format(output_stream, details_t(summary));
|
||||||
output_stream.flush();
|
output_stream.flush();
|
||||||
}
|
}
|
||||||
|
|
@ -206,11 +200,9 @@ class format_equity : public item_handler<account_t>
|
||||||
virtual void operator()(account_t& account) {
|
virtual void operator()(account_t& account) {
|
||||||
if (format_account::display_account(account, disp_pred)) {
|
if (format_account::display_account(account, disp_pred)) {
|
||||||
next_lines_format.format(output_stream, details_t(account));
|
next_lines_format.format(output_stream, details_t(account));
|
||||||
if (! account.data)
|
if (account_has_xdata(account))
|
||||||
account.data = new account_data_t;
|
total += account_xdata(account).value;
|
||||||
else
|
account_xdata(account).dflags |= ACCOUNT_DISPLAYED;
|
||||||
total += ACCT_DATA_(account)->value;
|
|
||||||
ACCT_DATA_(account)->dflags |= ACCOUNT_DISPLAYED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
123
journal.cc
123
journal.cc
|
|
@ -51,6 +51,60 @@ bool transaction_t::valid() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
balance_pair_t& add_transaction_to(const transaction_t& xact,
|
||||||
|
balance_pair_t& bal_pair)
|
||||||
|
{
|
||||||
|
if (xact.cost && ! bal_pair.cost)
|
||||||
|
bal_pair.cost = new balance_t(bal_pair.quantity);
|
||||||
|
|
||||||
|
bal_pair.quantity += xact.amount;
|
||||||
|
|
||||||
|
if (bal_pair.cost)
|
||||||
|
*bal_pair.cost += xact.cost ? *xact.cost : xact.amount;
|
||||||
|
|
||||||
|
return bal_pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& add_transaction_to(const transaction_t& xact, value_t& value)
|
||||||
|
{
|
||||||
|
switch (value.type) {
|
||||||
|
case value_t::BOOLEAN:
|
||||||
|
case value_t::INTEGER:
|
||||||
|
value.cast(value_t::AMOUNT);
|
||||||
|
|
||||||
|
case value_t::AMOUNT:
|
||||||
|
if (xact.cost) {
|
||||||
|
value.cast(value_t::BALANCE_PAIR);
|
||||||
|
return add_transaction_to(xact, value);
|
||||||
|
}
|
||||||
|
else if (((amount_t *) value.data)->commodity() !=
|
||||||
|
xact.amount.commodity()) {
|
||||||
|
value.cast(value_t::BALANCE);
|
||||||
|
return add_transaction_to(xact, value);
|
||||||
|
}
|
||||||
|
*((amount_t *) value.data) += xact.amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case value_t::BALANCE:
|
||||||
|
if (xact.cost) {
|
||||||
|
value.cast(value_t::BALANCE_PAIR);
|
||||||
|
return add_transaction_to(xact, value);
|
||||||
|
}
|
||||||
|
*((balance_t *) value.data) += xact.amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case value_t::BALANCE_PAIR:
|
||||||
|
add_transaction_to(xact, *((balance_pair_t *) value.data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void entry_t::add_transaction(transaction_t * xact)
|
void entry_t::add_transaction(transaction_t * xact)
|
||||||
{
|
{
|
||||||
xact->entry = this;
|
xact->entry = this;
|
||||||
|
|
@ -394,9 +448,6 @@ bool journal_t::valid() const
|
||||||
using namespace boost::python;
|
using namespace boost::python;
|
||||||
using namespace ledger;
|
using namespace ledger;
|
||||||
|
|
||||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(journal_find_account_overloads,
|
|
||||||
find_account, 1, 2)
|
|
||||||
|
|
||||||
entry_t& transaction_entry(const transaction_t& xact)
|
entry_t& transaction_entry(const transaction_t& xact)
|
||||||
{
|
{
|
||||||
return *xact.entry;
|
return *xact.entry;
|
||||||
|
|
@ -504,8 +555,26 @@ account_t& accounts_getitem(account_t& account, int i)
|
||||||
return *(*elem).second;
|
return *(*elem).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
account_t * py_find_account_1(journal_t& journal, const std::string& name)
|
||||||
|
{
|
||||||
|
return journal.find_account(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
account_t * py_find_account_2(journal_t& journal, const std::string& name,
|
||||||
|
const bool auto_create)
|
||||||
|
{
|
||||||
|
return journal.find_account(name, auto_create);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void export_journal()
|
void export_journal()
|
||||||
{
|
{
|
||||||
|
scope().attr("TRANSACTION_NORMAL") = TRANSACTION_NORMAL;
|
||||||
|
scope().attr("TRANSACTION_VIRTUAL") = TRANSACTION_VIRTUAL;
|
||||||
|
scope().attr("TRANSACTION_BALANCE") = TRANSACTION_BALANCE;
|
||||||
|
scope().attr("TRANSACTION_AUTO") = TRANSACTION_AUTO;
|
||||||
|
scope().attr("TRANSACTION_BULK_ALLOC") = TRANSACTION_BULK_ALLOC;
|
||||||
|
|
||||||
class_< transaction_t > ("Transaction")
|
class_< transaction_t > ("Transaction")
|
||||||
.def(init<account_t *, amount_t, optional<unsigned int, std::string> >())
|
.def(init<account_t *, amount_t, optional<unsigned int, std::string> >())
|
||||||
|
|
||||||
|
|
@ -522,22 +591,6 @@ void export_journal()
|
||||||
.def("valid", &transaction_t::valid)
|
.def("valid", &transaction_t::valid)
|
||||||
;
|
;
|
||||||
|
|
||||||
class_< entry_t > ("Entry")
|
|
||||||
.def_readwrite("date", &entry_t::date)
|
|
||||||
.def_readwrite("state", &entry_t::state)
|
|
||||||
.def_readwrite("code", &entry_t::code)
|
|
||||||
.def_readwrite("payee", &entry_t::payee)
|
|
||||||
|
|
||||||
.def("__len__", transactions_len)
|
|
||||||
.def("__getitem__", transactions_getitem,
|
|
||||||
return_value_policy<reference_existing_object>())
|
|
||||||
|
|
||||||
.def("add_transaction", &entry_t::add_transaction)
|
|
||||||
.def("remove_transaction", &entry_t::remove_transaction)
|
|
||||||
|
|
||||||
.def("valid", &entry_t::valid)
|
|
||||||
;
|
|
||||||
|
|
||||||
class_< account_t >
|
class_< account_t >
|
||||||
("Account", init<optional<account_t *, std::string, std::string> >())
|
("Account", init<optional<account_t *, std::string, std::string> >())
|
||||||
.def_readwrite("parent", &account_t::parent)
|
.def_readwrite("parent", &account_t::parent)
|
||||||
|
|
@ -565,16 +618,12 @@ void export_journal()
|
||||||
.def_readonly("sources", &journal_t::sources)
|
.def_readonly("sources", &journal_t::sources)
|
||||||
|
|
||||||
.def("__len__", entries_len)
|
.def("__len__", entries_len)
|
||||||
.def("__getitem__", entries_getitem,
|
.def("__getitem__", entries_getitem, return_internal_reference<1>())
|
||||||
return_value_policy<reference_existing_object>())
|
|
||||||
|
|
||||||
.def("add_account", &journal_t::add_account)
|
.def("add_account", &journal_t::add_account)
|
||||||
.def("remove_account", &journal_t::remove_account)
|
.def("remove_account", &journal_t::remove_account)
|
||||||
#if 0
|
.def("find_account", py_find_account_1, return_internal_reference<1>())
|
||||||
.def("find_account", &journal_t::find_account,
|
.def("find_account", py_find_account_2, return_internal_reference<1>())
|
||||||
journal_find_account_overloads(args("name", "auto_create"))
|
|
||||||
[return_value_policy<reference_existing_object>()])
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.def("add_entry", &journal_t::add_entry)
|
.def("add_entry", &journal_t::add_entry)
|
||||||
.def("remove_entry", &journal_t::remove_entry)
|
.def("remove_entry", &journal_t::remove_entry)
|
||||||
|
|
@ -583,6 +632,28 @@ void export_journal()
|
||||||
|
|
||||||
.def("valid", &journal_t::valid)
|
.def("valid", &journal_t::valid)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
scope in_entry = class_< entry_t > ("Entry")
|
||||||
|
.def_readwrite("date", &entry_t::date)
|
||||||
|
.def_readwrite("state", &entry_t::state)
|
||||||
|
.def_readwrite("code", &entry_t::code)
|
||||||
|
.def_readwrite("payee", &entry_t::payee)
|
||||||
|
|
||||||
|
.def("__len__", transactions_len)
|
||||||
|
.def("__getitem__", transactions_getitem,
|
||||||
|
return_internal_reference<1>())
|
||||||
|
|
||||||
|
.def("add_transaction", &entry_t::add_transaction)
|
||||||
|
.def("remove_transaction", &entry_t::remove_transaction)
|
||||||
|
|
||||||
|
.def("valid", &entry_t::valid)
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_< entry_t::state_t > ("State")
|
||||||
|
.value("UNCLEARED", entry_t::UNCLEARED)
|
||||||
|
.value("CLEARED", entry_t::CLEARED)
|
||||||
|
.value("PENDING", entry_t::PENDING)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_BOOST_PYTHON
|
#endif // USE_BOOST_PYTHON
|
||||||
|
|
|
||||||
67
ledger.h
67
ledger.h
|
|
@ -65,75 +65,24 @@ class transaction_t
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
|
||||||
balance_pair_t& add_transaction_to(const transaction_t& xact,
|
balance_pair_t& add_transaction_to(const transaction_t& xact,
|
||||||
balance_pair_t& bal_pair)
|
balance_pair_t& bal_pair);
|
||||||
{
|
value_t& add_transaction_to(const transaction_t& xact, value_t& value);
|
||||||
if (xact.cost && ! bal_pair.cost)
|
|
||||||
bal_pair.cost = new balance_t(bal_pair.quantity);
|
|
||||||
|
|
||||||
bal_pair.quantity += xact.amount;
|
|
||||||
|
|
||||||
if (bal_pair.cost)
|
|
||||||
*bal_pair.cost += xact.cost ? *xact.cost : xact.amount;
|
|
||||||
|
|
||||||
return bal_pair;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
value_t& add_transaction_to(const transaction_t& xact, value_t& value)
|
|
||||||
{
|
|
||||||
switch (value.type) {
|
|
||||||
case value_t::BOOLEAN:
|
|
||||||
case value_t::INTEGER:
|
|
||||||
value.cast(value_t::AMOUNT);
|
|
||||||
|
|
||||||
case value_t::AMOUNT:
|
|
||||||
if (xact.cost) {
|
|
||||||
value.cast(value_t::BALANCE_PAIR);
|
|
||||||
return add_transaction_to(xact, value);
|
|
||||||
}
|
|
||||||
else if (((amount_t *) value.data)->commodity() !=
|
|
||||||
xact.amount.commodity()) {
|
|
||||||
value.cast(value_t::BALANCE);
|
|
||||||
return add_transaction_to(xact, value);
|
|
||||||
}
|
|
||||||
*((amount_t *) value.data) += xact.amount;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case value_t::BALANCE:
|
|
||||||
if (xact.cost) {
|
|
||||||
value.cast(value_t::BALANCE_PAIR);
|
|
||||||
return add_transaction_to(xact, value);
|
|
||||||
}
|
|
||||||
*((balance_t *) value.data) += xact.amount;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case value_t::BALANCE_PAIR:
|
|
||||||
add_transaction_to(xact, *((balance_pair_t *) value.data));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::list<transaction_t *> transactions_list;
|
typedef std::list<transaction_t *> transactions_list;
|
||||||
|
|
||||||
class entry_t
|
class entry_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum entry_state_t {
|
enum state_t {
|
||||||
UNCLEARED, CLEARED, PENDING
|
UNCLEARED, CLEARED, PENDING
|
||||||
};
|
};
|
||||||
|
|
||||||
std::time_t date;
|
std::time_t date;
|
||||||
entry_state_t state;
|
state_t state;
|
||||||
std::string code;
|
std::string code;
|
||||||
std::string payee;
|
std::string payee;
|
||||||
|
|
||||||
transactions_list transactions;
|
transactions_list transactions;
|
||||||
|
|
||||||
entry_t() : date(-1), state(UNCLEARED) {}
|
entry_t() : date(-1), state(UNCLEARED) {}
|
||||||
|
|
|
||||||
26
main.cc
26
main.cc
|
|
@ -97,9 +97,9 @@ chain_formatters(const std::string& command,
|
||||||
|
|
||||||
// sort_transactions will sort all the transactions it sees, based
|
// sort_transactions will sort all the transactions it sees, based
|
||||||
// on the `sort_order' value expression.
|
// on the `sort_order' value expression.
|
||||||
if (config.sort_order)
|
if (! config.sort_string.empty())
|
||||||
ptrs.push_back(formatter =
|
ptrs.push_back(formatter =
|
||||||
new sort_transactions(formatter, config.sort_order));
|
new sort_transactions(formatter, config.sort_string));
|
||||||
|
|
||||||
// changed_value_transactions adds virtual transactions to the
|
// changed_value_transactions adds virtual transactions to the
|
||||||
// list to account for changes in market value of commodities,
|
// list to account for changes in market value of commodities,
|
||||||
|
|
@ -128,7 +128,7 @@ chain_formatters(const std::string& command,
|
||||||
// of the week.
|
// of the week.
|
||||||
if (config.show_subtotal)
|
if (config.show_subtotal)
|
||||||
ptrs.push_back(formatter = new subtotal_transactions(formatter));
|
ptrs.push_back(formatter = new subtotal_transactions(formatter));
|
||||||
else if (config.report_interval)
|
else if (! config.report_interval.empty())
|
||||||
ptrs.push_back(formatter =
|
ptrs.push_back(formatter =
|
||||||
new interval_transactions(formatter,
|
new interval_transactions(formatter,
|
||||||
config.report_interval));
|
config.report_interval));
|
||||||
|
|
@ -271,13 +271,13 @@ int parse_and_report(int argc, char * argv[], char * envp[])
|
||||||
format_account acct_formatter(*out, config.format,
|
format_account acct_formatter(*out, config.format,
|
||||||
config.display_predicate);
|
config.display_predicate);
|
||||||
sum_accounts(*journal->master);
|
sum_accounts(*journal->master);
|
||||||
walk_accounts(*journal->master, acct_formatter, config.sort_order);
|
walk_accounts(*journal->master, acct_formatter, config.sort_string);
|
||||||
acct_formatter.flush();
|
acct_formatter.flush();
|
||||||
|
|
||||||
if (journal->master->data) {
|
if (account_has_xdata(*journal->master)) {
|
||||||
ACCT_DATA(journal->master)->value = ACCT_DATA(journal->master)->total;
|
account_xdata_t& xdata = account_xdata(*journal->master);
|
||||||
|
xdata.value = xdata.total;
|
||||||
if (ACCT_DATA(journal->master)->dflags & ACCOUNT_TO_DISPLAY) {
|
if (xdata.dflags & ACCOUNT_TO_DISPLAY) {
|
||||||
*out << "--------------------\n";
|
*out << "--------------------\n";
|
||||||
config.format.format(*out, details_t(*journal->master));
|
config.format.format(*out, details_t(*journal->master));
|
||||||
}
|
}
|
||||||
|
|
@ -287,7 +287,7 @@ int parse_and_report(int argc, char * argv[], char * envp[])
|
||||||
format_equity acct_formatter(*out, config.format, config.nformat,
|
format_equity acct_formatter(*out, config.format, config.nformat,
|
||||||
config.display_predicate);
|
config.display_predicate);
|
||||||
sum_accounts(*journal->master);
|
sum_accounts(*journal->master);
|
||||||
walk_accounts(*journal->master, acct_formatter, config.sort_order);
|
walk_accounts(*journal->master, acct_formatter, config.sort_string);
|
||||||
acct_formatter.flush();
|
acct_formatter.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,14 +300,6 @@ int parse_and_report(int argc, char * argv[], char * envp[])
|
||||||
i != formatter_ptrs.end();
|
i != formatter_ptrs.end();
|
||||||
i++)
|
i++)
|
||||||
delete *i;
|
delete *i;
|
||||||
|
|
||||||
// Cleanup the data handlers that might be present on some objects.
|
|
||||||
|
|
||||||
clear_transaction_data xact_cleanup;
|
|
||||||
walk_entries(journal->entries, xact_cleanup);
|
|
||||||
|
|
||||||
clear_account_data acct_cleanup;
|
|
||||||
walk_accounts(*journal->master, acct_cleanup);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TIMER_STOP(report_gen);
|
TIMER_STOP(report_gen);
|
||||||
|
|
|
||||||
14
main.py
14
main.py
|
|
@ -106,7 +106,7 @@ class FormatTransaction (TransactionHandler):
|
||||||
self.output.flush ()
|
self.output.flush ()
|
||||||
|
|
||||||
def __call__ (self, xact):
|
def __call__ (self, xact):
|
||||||
if self.nformatter and xact.entry is self.last_entry:
|
if self.nformatter is not None and xact.entry is self.last_entry:
|
||||||
self.output.write(self.nformatter.format(xact))
|
self.output.write(self.nformatter.format(xact))
|
||||||
else:
|
else:
|
||||||
self.output.write(self.formatter.format(xact))
|
self.output.write(self.formatter.format(xact))
|
||||||
|
|
@ -123,8 +123,8 @@ if not (command == "b" or command == "E"):
|
||||||
|
|
||||||
handler = CalcTransactions(handler, config.show_inverted)
|
handler = CalcTransactions(handler, config.show_inverted)
|
||||||
|
|
||||||
if config.sort_order:
|
if config.sort_string:
|
||||||
handler = SortTransactions(handler, config.sort_order)
|
handler = SortTransactions(handler, config.sort_string)
|
||||||
|
|
||||||
if config.show_revalued:
|
if config.show_revalued:
|
||||||
handler = ChangedValueTransactions(handler, config.show_revalued_only)
|
handler = ChangedValueTransactions(handler, config.show_revalued_only)
|
||||||
|
|
@ -145,12 +145,14 @@ if config.show_related:
|
||||||
if config.predicate:
|
if config.predicate:
|
||||||
handler = FilterTransactions(handler, config.predicate)
|
handler = FilterTransactions(handler, config.predicate)
|
||||||
|
|
||||||
if 1:
|
if 0:
|
||||||
walk_entries (journal, handler)
|
walk_entries (journal, handler)
|
||||||
else:
|
else:
|
||||||
# These for loops are equivalent to `walk_entries', but far slower
|
# These for loops are equivalent to `walk_entries', but far slower
|
||||||
for entry in journal:
|
for entry in journal:
|
||||||
|
#print "1:", entry
|
||||||
for xact in entry:
|
for xact in entry:
|
||||||
|
#print "2:", xact.entry
|
||||||
handler (xact)
|
handler (xact)
|
||||||
|
|
||||||
handler.flush ()
|
handler.flush ()
|
||||||
|
|
@ -159,7 +161,7 @@ handler.flush ()
|
||||||
# format_account acct_formatter(out, config.format,
|
# format_account acct_formatter(out, config.format,
|
||||||
# config.display_predicate);
|
# config.display_predicate);
|
||||||
# sum_accounts(*journal->master);
|
# sum_accounts(*journal->master);
|
||||||
# walk_accounts(*journal->master, acct_formatter, config.sort_order);
|
# walk_accounts(*journal->master, acct_formatter, config.sort_string);
|
||||||
# acct_formatter.flush();
|
# acct_formatter.flush();
|
||||||
#
|
#
|
||||||
# if (journal->master->data) {
|
# if (journal->master->data) {
|
||||||
|
|
@ -174,7 +176,7 @@ handler.flush ()
|
||||||
# format_equity acct_formatter(out, config.format, config.nformat,
|
# format_equity acct_formatter(out, config.format, config.nformat,
|
||||||
# config.display_predicate);
|
# config.display_predicate);
|
||||||
# sum_accounts(*journal->master);
|
# sum_accounts(*journal->master);
|
||||||
# walk_accounts(*journal->master, acct_formatter, config.sort_order);
|
# walk_accounts(*journal->master, acct_formatter, config.sort_string);
|
||||||
# acct_formatter.flush();
|
# acct_formatter.flush();
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
|
|
||||||
51
valexpr.cc
51
valexpr.cc
|
|
@ -84,8 +84,8 @@ void value_expr_t::compute(value_t& result, const details_t& details) const
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
if (details.xact)
|
if (details.xact)
|
||||||
result = details.xact->amount;
|
result = details.xact->amount;
|
||||||
else if (details.account && ACCT_DATA(details.account))
|
else if (details.account && account_has_xdata(*details.account))
|
||||||
result = ACCT_DATA(details.account)->value;
|
result = account_xdata(*details.account).value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COST:
|
case COST:
|
||||||
|
|
@ -95,22 +95,22 @@ void value_expr_t::compute(value_t& result, const details_t& details) const
|
||||||
else
|
else
|
||||||
result = details.xact->amount;
|
result = details.xact->amount;
|
||||||
}
|
}
|
||||||
else if (details.account && ACCT_DATA(details.account)) {
|
else if (details.account && account_has_xdata(*details.account)) {
|
||||||
result = ACCT_DATA(details.account)->value.cost();
|
result = account_xdata(*details.account).value.cost();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOTAL:
|
case TOTAL:
|
||||||
if (details.xact && XACT_DATA(details.xact))
|
if (details.xact && transaction_has_xdata(*details.xact))
|
||||||
result = XACT_DATA(details.xact)->total;
|
result = transaction_xdata(*details.xact).total;
|
||||||
else if (details.account && ACCT_DATA(details.account))
|
else if (details.account && account_has_xdata(*details.account))
|
||||||
result = ACCT_DATA(details.account)->total;
|
result = account_xdata(*details.account).total;
|
||||||
break;
|
break;
|
||||||
case COST_TOTAL:
|
case COST_TOTAL:
|
||||||
if (details.xact && XACT_DATA(details.xact))
|
if (details.xact && transaction_has_xdata(*details.xact))
|
||||||
result = XACT_DATA(details.xact)->total.cost();
|
result = transaction_xdata(*details.xact).total.cost();
|
||||||
else if (details.account && ACCT_DATA(details.account))
|
else if (details.account && account_has_xdata(*details.account))
|
||||||
result = ACCT_DATA(details.account)->total.cost();
|
result = account_xdata(*details.account).total.cost();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VALUE_EXPR:
|
case VALUE_EXPR:
|
||||||
|
|
@ -166,17 +166,17 @@ void value_expr_t::compute(value_t& result, const details_t& details) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX:
|
case INDEX:
|
||||||
if (details.xact && XACT_DATA(details.xact))
|
if (details.xact && transaction_has_xdata(*details.xact))
|
||||||
result = XACT_DATA(details.xact)->index + 1;
|
result = transaction_xdata(*details.xact).index + 1;
|
||||||
else if (details.account && ACCT_DATA(details.account))
|
else if (details.account && account_has_xdata(*details.account))
|
||||||
result = ACCT_DATA(details.account)->subcount;
|
result = account_xdata(*details.account).subcount;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COUNT:
|
case COUNT:
|
||||||
if (details.xact && XACT_DATA(details.xact))
|
if (details.xact && transaction_has_xdata(*details.xact))
|
||||||
result = XACT_DATA(details.xact)->index + 1;
|
result = transaction_xdata(*details.xact).index + 1;
|
||||||
else if (details.account && ACCT_DATA(details.account))
|
else if (details.account && account_has_xdata(*details.account))
|
||||||
result = ACCT_DATA(details.account)->count;
|
result = account_xdata(*details.account).count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEPTH:
|
case DEPTH:
|
||||||
|
|
@ -187,17 +187,16 @@ void value_expr_t::compute(value_t& result, const details_t& details) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F_ARITH_MEAN:
|
case F_ARITH_MEAN:
|
||||||
if (details.xact && XACT_DATA(details.xact)) {
|
if (details.xact && transaction_has_xdata(*details.xact)) {
|
||||||
assert(left);
|
assert(left);
|
||||||
left->compute(result, details);
|
left->compute(result, details);
|
||||||
result /= amount_t(XACT_DATA(details.xact)->index + 1);
|
result /= amount_t(transaction_xdata(*details.xact).index + 1);
|
||||||
}
|
}
|
||||||
else if (details.account &&
|
else if (details.account && account_has_xdata(*details.account) &&
|
||||||
ACCT_DATA(details.account) &&
|
account_xdata(*details.account).count) {
|
||||||
ACCT_DATA(details.account)->count) {
|
|
||||||
assert(left);
|
assert(left);
|
||||||
left->compute(result, details);
|
left->compute(result, details);
|
||||||
result /= amount_t(ACCT_DATA(details.account)->count);
|
result /= amount_t(account_xdata(*details.account).count);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
147
walk.cc
147
walk.cc
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
std::list<transaction_xdata_t> transactions_xdata;
|
||||||
|
std::list<account_xdata_t> accounts_xdata;
|
||||||
|
|
||||||
void sort_transactions::flush()
|
void sort_transactions::flush()
|
||||||
{
|
{
|
||||||
std::stable_sort(transactions.begin(), transactions.end(),
|
std::stable_sort(transactions.begin(), transactions.end(),
|
||||||
|
|
@ -20,14 +23,11 @@ void sort_transactions::flush()
|
||||||
|
|
||||||
void calc_transactions::operator()(transaction_t& xact)
|
void calc_transactions::operator()(transaction_t& xact)
|
||||||
{
|
{
|
||||||
if (! xact.data)
|
if (last_xact && transaction_has_xdata(*last_xact)) {
|
||||||
xact.data = new transaction_data_t;
|
transaction_xdata(xact).total += transaction_xdata(*last_xact).total;
|
||||||
|
transaction_xdata(xact).index = transaction_xdata(*last_xact).index + 1;
|
||||||
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 {
|
} else {
|
||||||
XACT_DATA_(xact)->index = 0;
|
transaction_xdata(xact).index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
|
|
@ -36,8 +36,8 @@ void calc_transactions::operator()(transaction_t& xact)
|
||||||
xact.cost->negate();
|
xact.cost->negate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (XACT_DATA_(xact)->dflags & TRANSACTION_NO_TOTAL))
|
if (! (transaction_xdata(xact).dflags & TRANSACTION_NO_TOTAL))
|
||||||
add_transaction_to(xact, XACT_DATA_(xact)->total);
|
add_transaction_to(xact, transaction_xdata(xact).total);
|
||||||
|
|
||||||
(*handler)(xact);
|
(*handler)(xact);
|
||||||
|
|
||||||
|
|
@ -51,9 +51,11 @@ void calc_transactions::operator()(transaction_t& xact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void handle_value(const value_t& value, account_t * account,
|
static void handle_value(const value_t& value,
|
||||||
entry_t * entry, unsigned int flags,
|
account_t * account,
|
||||||
transactions_list& temps,
|
entry_t * entry,
|
||||||
|
unsigned int flags,
|
||||||
|
std::list<transaction_t>& temps,
|
||||||
item_handler<transaction_t> * handler)
|
item_handler<transaction_t> * handler)
|
||||||
{
|
{
|
||||||
balance_t * bal = NULL;
|
balance_t * bal = NULL;
|
||||||
|
|
@ -62,32 +64,29 @@ static void handle_value(const value_t& value, account_t * account,
|
||||||
case value_t::BOOLEAN:
|
case value_t::BOOLEAN:
|
||||||
case value_t::INTEGER:
|
case value_t::INTEGER:
|
||||||
case value_t::AMOUNT: {
|
case value_t::AMOUNT: {
|
||||||
transaction_t * xact = new transaction_t(account);
|
temps.push_back(transaction_t(account));
|
||||||
temps.push_back(xact);
|
transaction_t& xact = temps.back();
|
||||||
|
|
||||||
xact->entry = entry;
|
xact.entry = entry;
|
||||||
switch (value.type) {
|
switch (value.type) {
|
||||||
case value_t::BOOLEAN:
|
case value_t::BOOLEAN:
|
||||||
xact->amount = *((bool *) value.data);
|
xact.amount = *((bool *) value.data);
|
||||||
break;
|
break;
|
||||||
case value_t::INTEGER:
|
case value_t::INTEGER:
|
||||||
xact->amount = *((unsigned int *) value.data);
|
xact.amount = *((unsigned int *) value.data);
|
||||||
break;
|
break;
|
||||||
case value_t::AMOUNT:
|
case value_t::AMOUNT:
|
||||||
xact->amount = *((amount_t *) value.data);
|
xact.amount = *((amount_t *) value.data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags) {
|
if (flags)
|
||||||
if (! xact->data)
|
transaction_xdata(xact).dflags |= flags;
|
||||||
xact->data = new transaction_data_t;
|
|
||||||
XACT_DATA(xact)->dflags |= flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*handler)(*xact);
|
(*handler)(xact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,19 +101,16 @@ static void handle_value(const value_t& value, account_t * account,
|
||||||
for (amounts_map::const_iterator i = bal->amounts.begin();
|
for (amounts_map::const_iterator i = bal->amounts.begin();
|
||||||
i != bal->amounts.end();
|
i != bal->amounts.end();
|
||||||
i++) {
|
i++) {
|
||||||
transaction_t * xact = new transaction_t(account);
|
temps.push_back(transaction_t(account));
|
||||||
temps.push_back(xact);
|
transaction_t& xact = temps.back();
|
||||||
|
|
||||||
xact->entry = entry;
|
xact.entry = entry;
|
||||||
xact->amount = (*i).second;
|
xact.amount = (*i).second;
|
||||||
|
|
||||||
if (flags) {
|
if (flags)
|
||||||
if (! xact->data)
|
transaction_xdata(xact).dflags |= flags;
|
||||||
xact->data = new transaction_data_t;
|
|
||||||
XACT_DATA(xact)->dflags |= flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*handler)(*xact);
|
(*handler)(xact);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -131,12 +127,12 @@ void collapse_transactions::report_cumulative_subtotal()
|
||||||
} else {
|
} else {
|
||||||
assert(count > 1);
|
assert(count > 1);
|
||||||
|
|
||||||
if (! totals_account->data)
|
account_xdata_t xdata;
|
||||||
totals_account->data = new account_data_t;
|
xdata.total = subtotal;
|
||||||
ACCT_DATA(totals_account)->total = subtotal;
|
|
||||||
value_t result;
|
value_t result;
|
||||||
format_t::compute_total(result, details_t(*totals_account));
|
totals_account.data = &xdata;
|
||||||
handle_value(result, totals_account, last_entry, 0, xact_temps, handler);
|
format_t::compute_total(result, details_t(totals_account));
|
||||||
|
handle_value(result, &totals_account, last_entry, 0, xact_temps, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
subtotal = 0;
|
subtotal = 0;
|
||||||
|
|
@ -157,13 +153,13 @@ void changed_value_transactions::output_diff(const std::time_t current)
|
||||||
|
|
||||||
cur_bal -= prev_bal;
|
cur_bal -= prev_bal;
|
||||||
if (cur_bal) {
|
if (cur_bal) {
|
||||||
entry_t * entry = new entry_t;
|
entry_temps.push_back(entry_t());
|
||||||
entry_temps.push_back(entry);
|
entry_t& entry = entry_temps.back();
|
||||||
|
|
||||||
entry->payee = "Commodities revalued";
|
entry.payee = "Commodities revalued";
|
||||||
entry->date = current;
|
entry.date = current;
|
||||||
|
|
||||||
handle_value(cur_bal, NULL, entry, TRANSACTION_NO_TOTAL, xact_temps,
|
handle_value(cur_bal, NULL, &entry, TRANSACTION_NO_TOTAL, xact_temps,
|
||||||
handler);
|
handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,11 +169,8 @@ void changed_value_transactions::operator()(transaction_t& xact)
|
||||||
if (last_xact)
|
if (last_xact)
|
||||||
output_diff(xact.entry->date);
|
output_diff(xact.entry->date);
|
||||||
|
|
||||||
if (changed_values_only) {
|
if (changed_values_only)
|
||||||
if (! xact.data)
|
transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED;
|
||||||
xact.data = new transaction_data_t;
|
|
||||||
XACT_DATA_(xact)->dflags |= TRANSACTION_DISPLAYED;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*handler)(xact);
|
(*handler)(xact);
|
||||||
|
|
||||||
|
|
@ -201,31 +194,28 @@ void subtotal_transactions::flush(const char * spec_fmt)
|
||||||
std::strftime(buf, 255, spec_fmt, std::localtime(&finish));
|
std::strftime(buf, 255, spec_fmt, std::localtime(&finish));
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_t * entry = new entry_t;
|
entry_temps.push_back(entry_t());
|
||||||
entry_temps.push_back(entry);
|
entry_t& entry = entry_temps.back();
|
||||||
|
|
||||||
entry->payee = buf;
|
entry.payee = buf;
|
||||||
|
|
||||||
value_t result;
|
value_t result;
|
||||||
|
|
||||||
for (balances_map::iterator i = balances.begin();
|
for (balances_map::iterator i = balances.begin();
|
||||||
i != balances.end();
|
i != balances.end();
|
||||||
i++) {
|
i++) {
|
||||||
entry->date = finish;
|
entry.date = finish;
|
||||||
{
|
{
|
||||||
|
transaction_xdata_t xact_data;
|
||||||
|
xact_data.total = (*i).second;
|
||||||
transaction_t temp((*i).first);
|
transaction_t temp((*i).first);
|
||||||
temp.entry = entry;
|
temp.entry = &entry;
|
||||||
{
|
temp.data = &xact_data;
|
||||||
std::auto_ptr<transaction_data_t> xact_data(new transaction_data_t);
|
format_t::compute_total(result, details_t(temp));
|
||||||
temp.data = xact_data.get();
|
|
||||||
((transaction_data_t *) temp.data)->total = (*i).second;
|
|
||||||
format_t::compute_total(result, details_t(temp));
|
|
||||||
}
|
|
||||||
temp.data = NULL;
|
|
||||||
}
|
}
|
||||||
entry->date = start;
|
entry.date = start;
|
||||||
|
|
||||||
handle_value(result, (*i).first, entry, 0, xact_temps, handler);
|
handle_value(result, (*i).first, &entry, 0, xact_temps, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
balances.clear();
|
balances.clear();
|
||||||
|
|
@ -256,6 +246,12 @@ void subtotal_transactions::operator()(transaction_t& xact)
|
||||||
|
|
||||||
void interval_transactions::operator()(transaction_t& xact)
|
void interval_transactions::operator()(transaction_t& xact)
|
||||||
{
|
{
|
||||||
|
if ((interval.begin &&
|
||||||
|
std::difftime(xact.entry->date, interval.begin) < 0) ||
|
||||||
|
(interval.end &&
|
||||||
|
std::difftime(xact.entry->date, interval.end) >= 0))
|
||||||
|
return;
|
||||||
|
|
||||||
std::time_t quant = interval.increment(interval.begin);
|
std::time_t quant = interval.increment(interval.begin);
|
||||||
if (std::difftime(xact.entry->date, quant) > 0) {
|
if (std::difftime(xact.entry->date, quant) > 0) {
|
||||||
if (last_xact) {
|
if (last_xact) {
|
||||||
|
|
@ -349,6 +345,19 @@ void export_walk()
|
||||||
{
|
{
|
||||||
typedef item_handler<transaction_t> xact_handler_t;
|
typedef item_handler<transaction_t> xact_handler_t;
|
||||||
|
|
||||||
|
scope().attr("TRANSACTION_HANDLED") = TRANSACTION_HANDLED;
|
||||||
|
scope().attr("TRANSACTION_DISPLAYED") = TRANSACTION_DISPLAYED;
|
||||||
|
scope().attr("TRANSACTION_NO_TOTAL") = TRANSACTION_NO_TOTAL;
|
||||||
|
|
||||||
|
class_< transaction_xdata_t > ("TransactionXData")
|
||||||
|
.def_readwrite("total", &transaction_xdata_t::total)
|
||||||
|
.def_readwrite("index", &transaction_xdata_t::index)
|
||||||
|
.def_readwrite("dflags", &transaction_xdata_t::dflags)
|
||||||
|
;
|
||||||
|
|
||||||
|
def("transaction_has_xdata", transaction_has_xdata);
|
||||||
|
def("transaction_xdata", transaction_xdata, return_internal_reference<1>());
|
||||||
|
|
||||||
class_< xact_handler_t, item_handler_wrap<transaction_t> >
|
class_< xact_handler_t, item_handler_wrap<transaction_t> >
|
||||||
("TransactionHandler")
|
("TransactionHandler")
|
||||||
.def(init<xact_handler_t *>())
|
.def(init<xact_handler_t *>())
|
||||||
|
|
@ -365,12 +374,6 @@ void export_walk()
|
||||||
.def("__call__", &ignore_transactions::operator());
|
.def("__call__", &ignore_transactions::operator());
|
||||||
;
|
;
|
||||||
|
|
||||||
class_< clear_transaction_data, bases<xact_handler_t> >
|
|
||||||
("ClearTransactionData")
|
|
||||||
.def("flush", &xact_handler_t::flush)
|
|
||||||
.def("__call__", &clear_transaction_data::operator());
|
|
||||||
;
|
|
||||||
|
|
||||||
class_< set_account_value, bases<xact_handler_t> >
|
class_< set_account_value, bases<xact_handler_t> >
|
||||||
("SetAccountValue", init<xact_handler_t *>()
|
("SetAccountValue", init<xact_handler_t *>()
|
||||||
[with_custodian_and_ward<1, 2>()])
|
[with_custodian_and_ward<1, 2>()])
|
||||||
|
|
@ -381,6 +384,8 @@ void export_walk()
|
||||||
class_< sort_transactions, bases<xact_handler_t> >
|
class_< sort_transactions, bases<xact_handler_t> >
|
||||||
("SortTransactions", init<xact_handler_t *, const value_expr_t *>()
|
("SortTransactions", init<xact_handler_t *, const value_expr_t *>()
|
||||||
[with_custodian_and_ward<1, 2>()])
|
[with_custodian_and_ward<1, 2>()])
|
||||||
|
.def(init<xact_handler_t *, const std::string&>()
|
||||||
|
[with_custodian_and_ward<1, 2>()])
|
||||||
.def("flush", &sort_transactions::flush)
|
.def("flush", &sort_transactions::flush)
|
||||||
.def("__call__", &sort_transactions::operator());
|
.def("__call__", &sort_transactions::operator());
|
||||||
;
|
;
|
||||||
|
|
@ -388,6 +393,8 @@ void export_walk()
|
||||||
class_< filter_transactions, bases<xact_handler_t> >
|
class_< filter_transactions, bases<xact_handler_t> >
|
||||||
("FilterTransactions", init<xact_handler_t *, std::string>()
|
("FilterTransactions", init<xact_handler_t *, std::string>()
|
||||||
[with_custodian_and_ward<1, 2>()])
|
[with_custodian_and_ward<1, 2>()])
|
||||||
|
.def(init<xact_handler_t *, const std::string&>()
|
||||||
|
[with_custodian_and_ward<1, 2>()])
|
||||||
.def("flush", &xact_handler_t::flush)
|
.def("flush", &xact_handler_t::flush)
|
||||||
.def("__call__", &filter_transactions::operator());
|
.def("__call__", &filter_transactions::operator());
|
||||||
;
|
;
|
||||||
|
|
@ -423,6 +430,8 @@ void export_walk()
|
||||||
class_< interval_transactions, bases<xact_handler_t> >
|
class_< interval_transactions, bases<xact_handler_t> >
|
||||||
("IntervalTransactions", init<xact_handler_t *, interval_t>()
|
("IntervalTransactions", init<xact_handler_t *, interval_t>()
|
||||||
[with_custodian_and_ward<1, 2>()])
|
[with_custodian_and_ward<1, 2>()])
|
||||||
|
.def(init<xact_handler_t *, const std::string&>()
|
||||||
|
[with_custodian_and_ward<1, 2>()])
|
||||||
.def("flush", &xact_handler_t::flush)
|
.def("flush", &xact_handler_t::flush)
|
||||||
.def("__call__", &interval_transactions::operator());
|
.def("__call__", &interval_transactions::operator());
|
||||||
;
|
;
|
||||||
|
|
|
||||||
310
walk.h
310
walk.h
|
|
@ -65,6 +65,42 @@ class compare_items {
|
||||||
// Transaction handlers
|
// Transaction handlers
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#define TRANSACTION_HANDLED 0x0001
|
||||||
|
#define TRANSACTION_DISPLAYED 0x0002
|
||||||
|
#define TRANSACTION_NO_TOTAL 0x0004
|
||||||
|
|
||||||
|
struct transaction_xdata_t
|
||||||
|
{
|
||||||
|
value_t total;
|
||||||
|
unsigned int index;
|
||||||
|
unsigned short dflags;
|
||||||
|
|
||||||
|
transaction_xdata_t() : index(0), dflags(0) {
|
||||||
|
DEBUG_PRINT("ledger.memory.ctors", "ctor transaction_xdata_t");
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
~transaction_xdata_t() {
|
||||||
|
DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_xdata_t");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool transaction_has_xdata(const transaction_t& xact) {
|
||||||
|
return xact.data != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern std::list<transaction_xdata_t> transactions_xdata;
|
||||||
|
|
||||||
|
inline transaction_xdata_t& transaction_xdata(const transaction_t& xact) {
|
||||||
|
if (! xact.data) {
|
||||||
|
transactions_xdata.push_back(transaction_xdata_t());
|
||||||
|
xact.data = &transactions_xdata.back();
|
||||||
|
}
|
||||||
|
return *((transaction_xdata_t *) xact.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef std::deque<transaction_t *> transactions_deque;
|
typedef std::deque<transaction_t *> transactions_deque;
|
||||||
typedef std::deque<entry_t *> entries_deque;
|
typedef std::deque<entry_t *> entries_deque;
|
||||||
|
|
||||||
|
|
@ -73,6 +109,7 @@ inline void walk_transactions(transactions_list::iterator begin,
|
||||||
item_handler<transaction_t>& handler) {
|
item_handler<transaction_t>& handler) {
|
||||||
for (transactions_list::iterator i = begin; i != end; i++)
|
for (transactions_list::iterator i = begin; i != end; i++)
|
||||||
handler(**i);
|
handler(**i);
|
||||||
|
transactions_xdata.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void walk_transactions(transactions_list& list,
|
inline void walk_transactions(transactions_list& list,
|
||||||
|
|
@ -85,6 +122,7 @@ inline void walk_transactions(transactions_deque::iterator begin,
|
||||||
item_handler<transaction_t>& handler) {
|
item_handler<transaction_t>& handler) {
|
||||||
for (transactions_deque::iterator i = begin; i != end; i++)
|
for (transactions_deque::iterator i = begin; i != end; i++)
|
||||||
handler(**i);
|
handler(**i);
|
||||||
|
transactions_xdata.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void walk_transactions(transactions_deque& deque,
|
inline void walk_transactions(transactions_deque& deque,
|
||||||
|
|
@ -106,100 +144,43 @@ 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 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))
|
|
||||||
#define ACCT_DATA_(acct) ((account_data_t *) ((acct).data))
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class ignore_transactions : public item_handler<transaction_t>
|
class ignore_transactions : public item_handler<transaction_t>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void operator()(transaction_t& xact) {}
|
virtual void operator()(transaction_t& xact) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class clear_transaction_data : public item_handler<transaction_t>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void operator()(transaction_t& xact) {
|
|
||||||
if (xact.data) {
|
|
||||||
delete (transaction_data_t *) xact.data;
|
|
||||||
xact.data = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class set_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)
|
set_account_value(item_handler<transaction_t> * handler = NULL)
|
||||||
: item_handler<transaction_t>(handler) {}
|
: item_handler<transaction_t>(handler) {}
|
||||||
|
|
||||||
virtual void operator()(transaction_t& xact) {
|
virtual void operator()(transaction_t& xact);
|
||||||
if (! ACCT_DATA(xact.account))
|
|
||||||
xact.account->data = new account_data_t;
|
|
||||||
|
|
||||||
add_transaction_to(xact, ACCT_DATA(xact.account)->value);
|
|
||||||
ACCT_DATA(xact.account)->subcount++;
|
|
||||||
|
|
||||||
if (handler)
|
|
||||||
(*handler)(xact);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class sort_transactions : public item_handler<transaction_t>
|
class sort_transactions : public item_handler<transaction_t>
|
||||||
{
|
{
|
||||||
transactions_deque transactions;
|
transactions_deque transactions;
|
||||||
const value_expr_t * sort_order;
|
const value_expr_t * sort_order;
|
||||||
|
bool allocated;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sort_transactions(item_handler<transaction_t> * handler,
|
sort_transactions(item_handler<transaction_t> * handler,
|
||||||
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), allocated(false) {}
|
||||||
|
|
||||||
|
sort_transactions(item_handler<transaction_t> * handler,
|
||||||
|
const std::string& _sort_order)
|
||||||
|
: item_handler<transaction_t>(handler),
|
||||||
|
sort_order(parse_value_expr(_sort_order)), allocated(true) {}
|
||||||
|
|
||||||
|
virtual ~sort_transactions() {
|
||||||
|
assert(sort_order);
|
||||||
|
if (allocated)
|
||||||
|
delete sort_order;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
virtual void operator()(transaction_t& xact) {
|
virtual void operator()(transaction_t& xact) {
|
||||||
|
|
@ -209,15 +190,28 @@ class sort_transactions : public item_handler<transaction_t>
|
||||||
|
|
||||||
class filter_transactions : public item_handler<transaction_t>
|
class filter_transactions : public item_handler<transaction_t>
|
||||||
{
|
{
|
||||||
item_predicate<transaction_t> pred;
|
const item_predicate<transaction_t> * pred;
|
||||||
|
bool allocated;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
filter_transactions(item_handler<transaction_t> * handler,
|
||||||
|
const item_predicate<transaction_t> * predicate)
|
||||||
|
: item_handler<transaction_t>(handler),
|
||||||
|
pred(predicate), allocated(false) {}
|
||||||
|
|
||||||
filter_transactions(item_handler<transaction_t> * handler,
|
filter_transactions(item_handler<transaction_t> * handler,
|
||||||
const std::string& predicate)
|
const std::string& predicate)
|
||||||
: item_handler<transaction_t>(handler), pred(predicate) {}
|
: item_handler<transaction_t>(handler),
|
||||||
|
pred(new item_predicate<transaction_t>(predicate)),
|
||||||
|
allocated(true) {}
|
||||||
|
|
||||||
|
virtual ~filter_transactions() {
|
||||||
|
if (allocated)
|
||||||
|
delete pred;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void operator()(transaction_t& xact) {
|
virtual void operator()(transaction_t& xact) {
|
||||||
if (pred(xact))
|
if ((*pred)(xact))
|
||||||
(*handler)(xact);
|
(*handler)(xact);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -238,36 +232,18 @@ class calc_transactions : public item_handler<transaction_t>
|
||||||
|
|
||||||
class collapse_transactions : public item_handler<transaction_t>
|
class collapse_transactions : public item_handler<transaction_t>
|
||||||
{
|
{
|
||||||
balance_pair_t subtotal;
|
balance_pair_t subtotal;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
entry_t * last_entry;
|
entry_t * last_entry;
|
||||||
transaction_t * last_xact;
|
transaction_t * last_xact;
|
||||||
account_t * totals_account;
|
account_t totals_account;
|
||||||
transactions_list xact_temps;
|
|
||||||
|
std::list<transaction_t> xact_temps;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
collapse_transactions(item_handler<transaction_t> * handler)
|
collapse_transactions(item_handler<transaction_t> * handler)
|
||||||
: item_handler<transaction_t>(handler), count(0),
|
: item_handler<transaction_t>(handler), count(0),
|
||||||
last_entry(NULL), last_xact(NULL) {
|
last_entry(NULL), last_xact(NULL), totals_account(NULL, "<Total>") {}
|
||||||
totals_account = new account_t(NULL, "<Total>");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~collapse_transactions() {
|
|
||||||
if (totals_account->data) {
|
|
||||||
delete (account_data_t *) totals_account->data;
|
|
||||||
totals_account->data = NULL;
|
|
||||||
}
|
|
||||||
delete totals_account;
|
|
||||||
for (transactions_list::iterator i = xact_temps.begin();
|
|
||||||
i != xact_temps.end();
|
|
||||||
i++) {
|
|
||||||
if ((*i)->data) {
|
|
||||||
delete (transaction_data_t *) (*i)->data;
|
|
||||||
(*i)->data = NULL;
|
|
||||||
}
|
|
||||||
delete *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void flush() {
|
virtual void flush() {
|
||||||
if (subtotal)
|
if (subtotal)
|
||||||
|
|
@ -297,10 +273,10 @@ class changed_value_transactions : public item_handler<transaction_t>
|
||||||
// This filter requires that calc_transactions be used at some point
|
// This filter requires that calc_transactions be used at some point
|
||||||
// later in the chain.
|
// later in the chain.
|
||||||
|
|
||||||
bool changed_values_only;
|
bool changed_values_only;
|
||||||
transaction_t * last_xact;
|
transaction_t * last_xact;
|
||||||
entries_list entry_temps;
|
std::list<entry_t> entry_temps;
|
||||||
transactions_list xact_temps;
|
std::list<transaction_t> xact_temps;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
changed_value_transactions(item_handler<transaction_t> * handler,
|
changed_value_transactions(item_handler<transaction_t> * handler,
|
||||||
|
|
@ -308,23 +284,6 @@ class changed_value_transactions : public item_handler<transaction_t>
|
||||||
: item_handler<transaction_t>(handler),
|
: item_handler<transaction_t>(handler),
|
||||||
changed_values_only(_changed_values_only), last_xact(NULL) {}
|
changed_values_only(_changed_values_only), last_xact(NULL) {}
|
||||||
|
|
||||||
virtual ~changed_value_transactions() {
|
|
||||||
for (entries_list::iterator i = entry_temps.begin();
|
|
||||||
i != entry_temps.end();
|
|
||||||
i++)
|
|
||||||
delete *i;
|
|
||||||
|
|
||||||
for (transactions_list::iterator i = xact_temps.begin();
|
|
||||||
i != xact_temps.end();
|
|
||||||
i++) {
|
|
||||||
if ((*i)->data) {
|
|
||||||
delete (transaction_data_t *) (*i)->data;
|
|
||||||
(*i)->data = NULL;
|
|
||||||
}
|
|
||||||
delete *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void flush() {
|
virtual void flush() {
|
||||||
output_diff(std::time(NULL));
|
output_diff(std::time(NULL));
|
||||||
last_xact = NULL;
|
last_xact = NULL;
|
||||||
|
|
@ -342,33 +301,16 @@ class subtotal_transactions : public item_handler<transaction_t>
|
||||||
typedef std::pair<account_t *, balance_pair_t> balances_pair;
|
typedef std::pair<account_t *, balance_pair_t> balances_pair;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::time_t start;
|
std::time_t start;
|
||||||
std::time_t finish;
|
std::time_t finish;
|
||||||
balances_map balances;
|
balances_map balances;
|
||||||
entries_list entry_temps;
|
std::list<entry_t> entry_temps;
|
||||||
transactions_list xact_temps;
|
std::list<transaction_t> xact_temps;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
subtotal_transactions(item_handler<transaction_t> * handler)
|
subtotal_transactions(item_handler<transaction_t> * handler)
|
||||||
: item_handler<transaction_t>(handler) {}
|
: item_handler<transaction_t>(handler) {}
|
||||||
|
|
||||||
virtual ~subtotal_transactions() {
|
|
||||||
for (entries_list::iterator i = entry_temps.begin();
|
|
||||||
i != entry_temps.end();
|
|
||||||
i++)
|
|
||||||
delete *i;
|
|
||||||
|
|
||||||
for (transactions_list::iterator i = xact_temps.begin();
|
|
||||||
i != xact_temps.end();
|
|
||||||
i++) {
|
|
||||||
if ((*i)->data) {
|
|
||||||
delete (transaction_data_t *) (*i)->data;
|
|
||||||
(*i)->data = NULL;
|
|
||||||
}
|
|
||||||
delete *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush(const char * spec_fmt);
|
void flush(const char * spec_fmt);
|
||||||
|
|
||||||
virtual void flush() {
|
virtual void flush() {
|
||||||
|
|
@ -388,6 +330,11 @@ class interval_transactions : public subtotal_transactions
|
||||||
: subtotal_transactions(handler), interval(_interval),
|
: subtotal_transactions(handler), interval(_interval),
|
||||||
last_xact(NULL) {}
|
last_xact(NULL) {}
|
||||||
|
|
||||||
|
interval_transactions(item_handler<transaction_t> * handler,
|
||||||
|
const std::string& _interval)
|
||||||
|
: subtotal_transactions(handler), interval(_interval),
|
||||||
|
last_xact(NULL) {}
|
||||||
|
|
||||||
virtual ~interval_transactions() {
|
virtual ~interval_transactions() {
|
||||||
start = interval.begin;
|
start = interval.begin;
|
||||||
finish = interval.increment(interval.begin);
|
finish = interval.increment(interval.begin);
|
||||||
|
|
@ -425,13 +372,11 @@ class related_transactions : public item_handler<transaction_t>
|
||||||
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();
|
||||||
i++)
|
i++)
|
||||||
if ((! (*i)->data ||
|
if ((! transaction_has_xdata(**i) ||
|
||||||
! (XACT_DATA(*i)->dflags & TRANSACTION_HANDLED)) &&
|
! (transaction_xdata(**i).dflags & TRANSACTION_HANDLED)) &&
|
||||||
(*i == &xact ? also_matching :
|
(*i == &xact ? also_matching :
|
||||||
! ((*i)->flags & TRANSACTION_AUTO))) {
|
! ((*i)->flags & TRANSACTION_AUTO))) {
|
||||||
if (! (*i)->data)
|
transaction_xdata(**i).dflags |= TRANSACTION_HANDLED;
|
||||||
(*i)->data = new transaction_data_t;
|
|
||||||
XACT_DATA(*i)->dflags |= TRANSACTION_HANDLED;
|
|
||||||
(*handler)(**i);
|
(*handler)(**i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -443,31 +388,62 @@ class related_transactions : public item_handler<transaction_t>
|
||||||
// Account walking functions
|
// Account walking functions
|
||||||
//
|
//
|
||||||
|
|
||||||
class clear_account_data : public item_handler<account_t>
|
#define ACCOUNT_DISPLAYED 0x1
|
||||||
|
#define ACCOUNT_TO_DISPLAY 0x2
|
||||||
|
|
||||||
|
struct account_xdata_t
|
||||||
{
|
{
|
||||||
public:
|
value_t value;
|
||||||
virtual void operator()(account_t * account) {
|
value_t total;
|
||||||
if (account->data) {
|
unsigned int count; // transactions counted toward total
|
||||||
delete (account_data_t *) account->data;
|
unsigned int subcount;
|
||||||
account->data = NULL;
|
unsigned short dflags;
|
||||||
}
|
|
||||||
|
account_xdata_t() : count(0), subcount(0), dflags(0) {
|
||||||
|
DEBUG_PRINT("ledger.memory.ctors", "ctor account_xdata_t");
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
~account_xdata_t() {
|
||||||
|
DEBUG_PRINT("ledger.memory.dtors", "dtor account_xdata_t");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void sum_accounts(account_t& account) {
|
inline bool account_has_xdata(const account_t& account) {
|
||||||
if (! account.data)
|
return account.data != NULL;
|
||||||
account.data = new account_data_t;
|
}
|
||||||
|
|
||||||
|
extern std::list<account_xdata_t> accounts_xdata;
|
||||||
|
|
||||||
|
inline account_xdata_t& account_xdata(const account_t& account) {
|
||||||
|
if (! account.data) {
|
||||||
|
accounts_xdata.push_back(account_xdata_t());
|
||||||
|
account.data = &accounts_xdata.back();
|
||||||
|
}
|
||||||
|
return *((account_xdata_t *) account.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_account_value::operator()(transaction_t& xact) {
|
||||||
|
add_transaction_to(xact, account_xdata(*xact.account).value);
|
||||||
|
account_xdata(*xact.account).subcount++;
|
||||||
|
|
||||||
|
if (handler)
|
||||||
|
(*handler)(xact);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void sum_accounts(account_t& account) {
|
||||||
for (accounts_map::iterator i = account.accounts.begin();
|
for (accounts_map::iterator i = account.accounts.begin();
|
||||||
i != account.accounts.end();
|
i != account.accounts.end();
|
||||||
i++) {
|
i++) {
|
||||||
sum_accounts(*(*i).second);
|
sum_accounts(*(*i).second);
|
||||||
ACCT_DATA_(account)->total += ACCT_DATA((*i).second)->total;
|
account_xdata(account).total += account_xdata(*(*i).second).total;
|
||||||
ACCT_DATA_(account)->count += (ACCT_DATA((*i).second)->count +
|
account_xdata(account).count += (account_xdata(*(*i).second).count +
|
||||||
ACCT_DATA((*i).second)->subcount);
|
account_xdata(*(*i).second).subcount);
|
||||||
}
|
}
|
||||||
ACCT_DATA_(account)->total += ACCT_DATA_(account)->value;
|
account_xdata(account).total += account_xdata(account).value;
|
||||||
ACCT_DATA_(account)->count += ACCT_DATA_(account)->subcount;
|
account_xdata(account).count += account_xdata(account).subcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::deque<account_t *> accounts_deque;
|
typedef std::deque<account_t *> accounts_deque;
|
||||||
|
|
@ -502,6 +478,14 @@ inline void walk_accounts(account_t& account,
|
||||||
i++)
|
i++)
|
||||||
walk_accounts(*(*i).second, handler);
|
walk_accounts(*(*i).second, handler);
|
||||||
}
|
}
|
||||||
|
accounts_xdata.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void walk_accounts(account_t& account,
|
||||||
|
item_handler<account_t>& handler,
|
||||||
|
const std::string& sort_string) {
|
||||||
|
std::auto_ptr<value_expr_t> sort_order(parse_value_expr(sort_string));
|
||||||
|
walk_accounts(account, handler, sort_order.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue