Moved xact_xdata_t into xact_t itself, as a set of "extended data" that might
be gathered during reporting. Removed the references to accounts and such from the mask logic, which means that the value expression "acount =~ /foo/" is needed in place of just "/foo/".
This commit is contained in:
parent
7b3c8c03c5
commit
5a90fe7357
19 changed files with 386 additions and 386 deletions
7
csv.cc
7
csv.cc
|
|
@ -19,9 +19,8 @@ namespace {
|
|||
|
||||
void format_csv_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
if (! xact_has_xdata(xact) ||
|
||||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
|
||||
|
||||
if (! xact.has_xdata() ||
|
||||
! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) {
|
||||
{
|
||||
format_t fmt("%D");
|
||||
std::ostringstream str;
|
||||
|
|
@ -111,7 +110,7 @@ void format_csv_xacts::operator()(xact_t& xact)
|
|||
}
|
||||
out << '\n';
|
||||
|
||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
||||
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
8
emacs.cc
8
emacs.cc
|
|
@ -33,8 +33,8 @@ void format_emacs_xacts::write_entry(entry_t& entry)
|
|||
|
||||
void format_emacs_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
if (! xact_has_xdata(xact) ||
|
||||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
|
||||
if (! xact.has_xdata() ||
|
||||
! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) {
|
||||
if (! last_entry) {
|
||||
out << "((";
|
||||
write_entry(*xact.entry);
|
||||
|
|
@ -48,7 +48,7 @@ void format_emacs_xacts::operator()(xact_t& xact)
|
|||
}
|
||||
|
||||
out << " (" << (static_cast<unsigned long>(xact.beg_line) + 1) << " ";
|
||||
out << "\"" << xact_account(xact)->fullname() << "\" \""
|
||||
out << "\"" << xact.reported_account()->fullname() << "\" \""
|
||||
<< xact.amount << "\"";
|
||||
|
||||
switch (xact.state) {
|
||||
|
|
@ -71,7 +71,7 @@ void format_emacs_xacts::operator()(xact_t& xact)
|
|||
|
||||
last_entry = xact.entry;
|
||||
|
||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
||||
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
6
entry.h
6
entry.h
|
|
@ -39,8 +39,6 @@ namespace ledger {
|
|||
|
||||
class journal_t;
|
||||
|
||||
typedef std::list<xact_t *> xacts_list;
|
||||
|
||||
class entry_base_t : public supports_flags<>
|
||||
{
|
||||
public:
|
||||
|
|
@ -232,6 +230,10 @@ inline bool auto_entry_finalizer_t::operator()(entry_t& entry, bool post) {
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef std::list<entry_t *> entries_list;
|
||||
typedef std::list<auto_entry_t *> auto_entries_list;
|
||||
typedef std::list<period_entry_t *> period_entries_list;
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _ENTRY_H
|
||||
|
|
|
|||
|
|
@ -43,10 +43,6 @@ typedef std::list<path> paths_list;
|
|||
class session_t;
|
||||
class account_t;
|
||||
|
||||
typedef std::list<entry_t *> entries_list;
|
||||
typedef std::list<auto_entry_t *> auto_entries_list;
|
||||
typedef std::list<period_entry_t *> period_entries_list;
|
||||
|
||||
class journal_t : public noncopyable
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
12
mask.h
12
mask.h
|
|
@ -36,25 +36,17 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
class mask_t : public supports_flags<>
|
||||
class mask_t
|
||||
{
|
||||
mask_t();
|
||||
|
||||
public:
|
||||
#define MASK_SHORT_ACCOUNT 0x01
|
||||
#define MASK_CODE 0x02
|
||||
#define MASK_COMMODITY 0x04
|
||||
#define MASK_PAYEE 0x08
|
||||
#define MASK_NOTE 0x10
|
||||
#define MASK_ACCOUNT 0x20
|
||||
|
||||
bool exclude;
|
||||
boost::regex expr;
|
||||
|
||||
explicit mask_t(const string& pattern);
|
||||
|
||||
mask_t(const mask_t& m)
|
||||
: supports_flags<>(), exclude(m.exclude), expr(m.expr) {
|
||||
mask_t(const mask_t& m) : exclude(m.exclude), expr(m.expr) {
|
||||
TRACE_CTOR(mask_t, "copy");
|
||||
}
|
||||
~mask_t() throw() {
|
||||
|
|
|
|||
28
op.cc
28
op.cc
|
|
@ -647,34 +647,6 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope)
|
|||
}
|
||||
return this;
|
||||
|
||||
case MASK: {
|
||||
ptr_op_t match = new op_t(op_t::O_MATCH);
|
||||
match->set_right(this);
|
||||
|
||||
// jww (2008-08-02): Coupling!
|
||||
ptr_op_t ident = new op_t(op_t::IDENT);
|
||||
switch (as_mask().flags()) {
|
||||
case MASK_SHORT_ACCOUNT:
|
||||
ident->set_ident("account_base");
|
||||
break;
|
||||
case MASK_CODE:
|
||||
ident->set_ident("code");
|
||||
break;
|
||||
case MASK_PAYEE:
|
||||
ident->set_ident("payee");
|
||||
break;
|
||||
case MASK_NOTE:
|
||||
ident->set_ident("note");
|
||||
break;
|
||||
case MASK_ACCOUNT:
|
||||
ident->set_ident("account");
|
||||
break;
|
||||
}
|
||||
match->set_left(ident->compile(scope));
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
|||
case token_t::MASK:
|
||||
node = new op_t(op_t::MASK);
|
||||
node->set_mask(tok.value.as_string());
|
||||
node->as_mask_lval().add_flags(tok.flags());
|
||||
break;
|
||||
|
||||
case token_t::IDENT: {
|
||||
|
|
|
|||
10
parser.h
10
parser.h
|
|
@ -46,10 +46,14 @@ class expr_t::parser_t : public noncopyable
|
|||
#define EXPR_PARSE_NO_ASSIGN 0x08
|
||||
#define EXPR_PARSE_NO_DATES 0x10
|
||||
|
||||
public:
|
||||
typedef uint_least8_t flags_t;
|
||||
|
||||
private:
|
||||
mutable token_t lookahead;
|
||||
mutable bool use_lookahead;
|
||||
|
||||
token_t& next_token(std::istream& in, token_t::flags_t tflags) const
|
||||
token_t& next_token(std::istream& in, flags_t tflags) const
|
||||
{
|
||||
if (use_lookahead)
|
||||
use_lookahead = false;
|
||||
|
|
@ -69,10 +73,6 @@ class expr_t::parser_t : public noncopyable
|
|||
use_lookahead = true;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef uint_least8_t flags_t;
|
||||
|
||||
private:
|
||||
ptr_op_t parse_value_term(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_unary_expr(std::istream& in, const flags_t flags) const;
|
||||
ptr_op_t parse_mul_expr(std::istream& in, const flags_t flags) const;
|
||||
|
|
|
|||
18
qif.cc
18
qif.cc
|
|
@ -34,21 +34,21 @@ bool qif_parser_t::test(std::istream& in) const
|
|||
}
|
||||
|
||||
unsigned int qif_parser_t::parse(std::istream& in,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
session_t& session,
|
||||
journal_t& journal,
|
||||
account_t * master,
|
||||
const path * original_file)
|
||||
{
|
||||
std::auto_ptr<entry_t> entry;
|
||||
std::auto_ptr<amount_t> amount;
|
||||
|
||||
xact_t * xact;
|
||||
unsigned int count = 0;
|
||||
account_t * misc = NULL;
|
||||
commodity_t * def_commodity = NULL;
|
||||
bool saw_splits = false;
|
||||
bool saw_category = false;
|
||||
xact_t * total = NULL;
|
||||
xact_t * xact;
|
||||
unsigned int count = 0;
|
||||
account_t * misc = NULL;
|
||||
commodity_t * def_commodity = NULL;
|
||||
bool saw_splits = false;
|
||||
bool saw_category = false;
|
||||
xact_t * total = NULL;
|
||||
|
||||
entry.reset(new entry_t);
|
||||
xact = new xact_t(master);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
#define xact_next(x) reinterpret_cast<xact_t *>(xact_xdata(*x).ptr)
|
||||
#define xact_next_ptr(x) reinterpret_cast<xact_t **>(&xact_xdata(*x).ptr)
|
||||
#define xact_next(x) reinterpret_cast<xact_t *>(x->xdata().ptr)
|
||||
#define xact_next_ptr(x) reinterpret_cast<xact_t **>(&x->xdata().ptr)
|
||||
|
||||
static bool search_for_balance(amount_t& amount,
|
||||
xact_t ** prev, xact_t * next)
|
||||
|
|
|
|||
|
|
@ -476,8 +476,8 @@ format_xacts::format_xacts(std::ostream& _output_stream,
|
|||
|
||||
void format_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
if (! xact_has_xdata(xact) ||
|
||||
! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) {
|
||||
if (! xact.has_xdata() ||
|
||||
! xact.xdata().has_flags(XACT_EXT_DISPLAYED)) {
|
||||
if (last_entry != xact.entry) {
|
||||
first_line_format.format(output_stream, xact);
|
||||
last_entry = xact.entry;
|
||||
|
|
@ -489,7 +489,7 @@ void format_xacts::operator()(xact_t& xact)
|
|||
next_lines_format.format(output_stream, xact);
|
||||
}
|
||||
|
||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
||||
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||
last_xact = &xact;
|
||||
}
|
||||
}
|
||||
|
|
@ -515,7 +515,7 @@ void format_entries::format_last_entry()
|
|||
|
||||
void format_entries::operator()(xact_t& xact)
|
||||
{
|
||||
xact_xdata(xact).dflags |= XACT_TO_DISPLAY;
|
||||
xact.xdata().add_flags(XACT_EXT_TO_DISPLAY);
|
||||
|
||||
if (last_entry && xact.entry != last_entry)
|
||||
format_last_entry();
|
||||
|
|
|
|||
|
|
@ -1079,7 +1079,7 @@ void write_textual_journal(journal_t& journal,
|
|||
if (base) {
|
||||
foreach (xact_t * xact, base->xacts) {
|
||||
if (! xact->has_flags(XACT_AUTO)) {
|
||||
xact_xdata(*xact).dflags |= XACT_TO_DISPLAY;
|
||||
xact->xdata().add_flags(XACT_EXT_TO_DISPLAY);
|
||||
(*formatter)(*xact);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
17
token.cc
17
token.cc
|
|
@ -53,8 +53,6 @@ void expr_t::token_t::parse_ident(std::istream& in)
|
|||
kind = IDENT;
|
||||
length = 0;
|
||||
|
||||
clear_flags();
|
||||
|
||||
char buf[256];
|
||||
READ_INTO_(in, buf, 255, c, length,
|
||||
std::isalnum(c) || c == '_' || c == '.' || c == '-');
|
||||
|
|
@ -122,7 +120,7 @@ void expr_t::token_t::parse_ident(std::istream& in)
|
|||
value.set_string(buf);
|
||||
}
|
||||
|
||||
void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
|
||||
void expr_t::token_t::next(std::istream& in, const uint_least8_t pflags)
|
||||
{
|
||||
if (in.eof()) {
|
||||
kind = TOK_EOF;
|
||||
|
|
@ -284,19 +282,6 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
|
|||
in.get(c);
|
||||
length++;
|
||||
|
||||
if (short_account_mask)
|
||||
set_flags(MASK_SHORT_ACCOUNT);
|
||||
else if (code_mask)
|
||||
set_flags(MASK_CODE);
|
||||
else if (commodity_mask)
|
||||
set_flags(MASK_COMMODITY);
|
||||
else if (payee_mask)
|
||||
set_flags(MASK_PAYEE);
|
||||
else if (note_mask)
|
||||
set_flags(MASK_NOTE);
|
||||
else
|
||||
set_flags(MASK_ACCOUNT);
|
||||
|
||||
kind = MASK;
|
||||
value.set_string(buf);
|
||||
break;
|
||||
|
|
|
|||
6
token.h
6
token.h
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
struct expr_t::token_t : public noncopyable, public supports_flags<>
|
||||
struct expr_t::token_t : public noncopyable
|
||||
{
|
||||
enum kind_t {
|
||||
VALUE, // any kind of literal value
|
||||
|
|
@ -79,7 +79,7 @@ struct expr_t::token_t : public noncopyable, public supports_flags<>
|
|||
value_t value;
|
||||
std::size_t length;
|
||||
|
||||
explicit token_t() : supports_flags<>(), kind(UNKNOWN), length(0) {
|
||||
explicit token_t() : kind(UNKNOWN), length(0) {
|
||||
TRACE_CTOR(token_t, "");
|
||||
}
|
||||
~token_t() throw() {
|
||||
|
|
@ -104,7 +104,7 @@ struct expr_t::token_t : public noncopyable, public supports_flags<>
|
|||
}
|
||||
|
||||
void parse_ident(std::istream& in);
|
||||
void next(std::istream& in, unsigned int flags);
|
||||
void next(std::istream& in, const uint_least8_t flags);
|
||||
void rewind(std::istream& in);
|
||||
void unexpected();
|
||||
|
||||
|
|
|
|||
165
walk.cc
165
walk.cc
|
|
@ -8,24 +8,23 @@
|
|||
namespace ledger {
|
||||
|
||||
template <>
|
||||
bool compare_items<xact_t>::operator()(const xact_t * left,
|
||||
const xact_t * right)
|
||||
bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right)
|
||||
{
|
||||
assert(left);
|
||||
assert(right);
|
||||
|
||||
xact_xdata_t& lxdata(xact_xdata(*left));
|
||||
if (! (lxdata.dflags & XACT_SORT_CALC)) {
|
||||
lxdata.sort_value = sort_order.calc(const_cast<xact_t&>(*left));
|
||||
xact_t::xdata_t& lxdata(left->xdata());
|
||||
if (! lxdata.has_flags(XACT_EXT_SORT_CALC)) {
|
||||
lxdata.sort_value = sort_order.calc(*left);
|
||||
lxdata.sort_value.reduce();
|
||||
lxdata.dflags |= XACT_SORT_CALC;
|
||||
lxdata.add_flags(XACT_EXT_SORT_CALC);
|
||||
}
|
||||
|
||||
xact_xdata_t& rxdata(xact_xdata(*right));
|
||||
if (! (rxdata.dflags & XACT_SORT_CALC)) {
|
||||
rxdata.sort_value = sort_order.calc(const_cast<xact_t&>(*right));
|
||||
xact_t::xdata_t& rxdata(right->xdata());
|
||||
if (! rxdata.has_flags(XACT_EXT_SORT_CALC)) {
|
||||
rxdata.sort_value = sort_order.calc(*right);
|
||||
rxdata.sort_value.reduce();
|
||||
rxdata.dflags |= XACT_SORT_CALC;
|
||||
rxdata.add_flags(XACT_EXT_SORT_CALC);
|
||||
}
|
||||
|
||||
DEBUG("ledger.walk.compare_items_xact",
|
||||
|
|
@ -36,27 +35,6 @@ bool compare_items<xact_t>::operator()(const xact_t * left,
|
|||
return lxdata.sort_value < rxdata.sort_value;
|
||||
}
|
||||
|
||||
xact_xdata_t& xact_xdata(const xact_t& xact)
|
||||
{
|
||||
if (! xact.data)
|
||||
xact.data = new xact_xdata_t();
|
||||
return *static_cast<xact_xdata_t *>(xact.data);
|
||||
}
|
||||
|
||||
void add_xact_to(const xact_t& xact, value_t& value)
|
||||
{
|
||||
if (xact_has_xdata(xact) &&
|
||||
xact_xdata_(xact).dflags & XACT_COMPOUND) {
|
||||
value += xact_xdata_(xact).value;
|
||||
}
|
||||
else if (xact.cost || (! value.is_null() && ! value.is_realzero())) {
|
||||
value.add(xact.amount, xact.cost);
|
||||
}
|
||||
else {
|
||||
value = xact.amount;
|
||||
}
|
||||
}
|
||||
|
||||
void entries_iterator::reset(session_t& session)
|
||||
{
|
||||
journals_i = session.journals.begin();
|
||||
|
|
@ -157,11 +135,11 @@ void truncate_entries::flush()
|
|||
|
||||
void set_account_value::operator()(xact_t& xact)
|
||||
{
|
||||
account_t * acct = xact_account(xact);
|
||||
account_t * acct = xact.reported_account();
|
||||
assert(acct);
|
||||
|
||||
account_xdata_t& xdata = account_xdata(*acct);
|
||||
add_xact_to(xact, xdata.value);
|
||||
xact.add_to_value(xdata.value);
|
||||
|
||||
xdata.count++;
|
||||
if (xact.has_flags(XACT_VIRTUAL))
|
||||
|
|
@ -176,7 +154,7 @@ void sort_xacts::post_accumulated_xacts()
|
|||
compare_items<xact_t>(sort_order));
|
||||
|
||||
foreach (xact_t * xact, xacts) {
|
||||
xact_xdata(*xact).dflags &= ~XACT_SORT_CALC;
|
||||
xact->xdata().drop_flags(XACT_EXT_SORT_CALC);
|
||||
item_handler<xact_t>::operator()(*xact);
|
||||
}
|
||||
|
||||
|
|
@ -186,26 +164,24 @@ void sort_xacts::post_accumulated_xacts()
|
|||
void calc_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
try {
|
||||
xact_t::xdata_t& xdata(xact.xdata());
|
||||
|
||||
xact_xdata_t& xdata(xact_xdata(xact));
|
||||
if (last_xact && last_xact->has_xdata()) {
|
||||
if (xdata.total.is_null())
|
||||
xdata.total = last_xact->xdata().total;
|
||||
else
|
||||
xdata.total += last_xact->xdata().total;
|
||||
xdata.index = last_xact->xdata().index + 1;
|
||||
} else {
|
||||
xdata.index = 0;
|
||||
}
|
||||
|
||||
if (last_xact && xact_has_xdata(*last_xact)) {
|
||||
if (xdata.total.is_null())
|
||||
xdata.total = xact_xdata_(*last_xact).total;
|
||||
else
|
||||
xdata.total += xact_xdata_(*last_xact).total;
|
||||
xdata.index = xact_xdata_(*last_xact).index + 1;
|
||||
} else {
|
||||
xdata.index = 0;
|
||||
}
|
||||
if (! xdata.has_flags(XACT_EXT_NO_TOTAL))
|
||||
xact.add_to_value(xdata.total);
|
||||
|
||||
if (! (xdata.dflags & XACT_NO_TOTAL))
|
||||
add_xact_to(xact, xdata.total);
|
||||
|
||||
item_handler<xact_t>::operator()(xact);
|
||||
|
||||
last_xact = &xact;
|
||||
item_handler<xact_t>::operator()(xact);
|
||||
|
||||
last_xact = &xact;
|
||||
}
|
||||
catch (const std::exception& err) {
|
||||
add_error_context("Calculating transaction at");
|
||||
|
|
@ -218,9 +194,9 @@ void calc_xacts::operator()(xact_t& xact)
|
|||
|
||||
void invert_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
if (xact_has_xdata(xact) &&
|
||||
xact_xdata_(xact).dflags & XACT_COMPOUND) {
|
||||
xact_xdata_(xact).value.negate();
|
||||
if (xact.has_xdata() &&
|
||||
xact.xdata().has_flags(XACT_EXT_COMPOUND)) {
|
||||
xact.xdata().value.negate();
|
||||
} else {
|
||||
xact.amount.negate();
|
||||
if (xact.cost)
|
||||
|
|
@ -251,7 +227,7 @@ void handle_value(const value_t& value,
|
|||
// temporary, do so now.
|
||||
|
||||
if (component_xacts)
|
||||
xact_xdata(xact).copy_component_xacts(*component_xacts);
|
||||
xact.xdata().copy_component_xacts(*component_xacts);
|
||||
|
||||
// If the account for this xact is all virtual, then report
|
||||
// the xact as such. This allows subtotal reports to show
|
||||
|
|
@ -264,7 +240,7 @@ void handle_value(const value_t& value,
|
|||
xact.add_flags(XACT_BALANCE);
|
||||
}
|
||||
|
||||
xact_xdata_t& xdata(xact_xdata(xact));
|
||||
xact_t::xdata_t& xdata(xact.xdata());
|
||||
|
||||
if (is_valid(date))
|
||||
xdata.date = date;
|
||||
|
|
@ -286,7 +262,7 @@ void handle_value(const value_t& value,
|
|||
case value_t::BALANCE:
|
||||
case value_t::BALANCE_PAIR:
|
||||
xdata.value = temp;
|
||||
flags |= XACT_COMPOUND;
|
||||
flags |= XACT_EXT_COMPOUND;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -295,7 +271,7 @@ void handle_value(const value_t& value,
|
|||
}
|
||||
|
||||
if (flags)
|
||||
xdata.dflags |= flags;
|
||||
xdata.add_flags(flags);
|
||||
|
||||
handler(xact);
|
||||
}
|
||||
|
|
@ -330,7 +306,7 @@ void collapse_xacts::operator()(xact_t& xact)
|
|||
if (last_entry && last_entry != xact.entry && count > 0)
|
||||
report_subtotal();
|
||||
|
||||
add_xact_to(xact, subtotal);
|
||||
xact.add_to_value(subtotal);
|
||||
count++;
|
||||
|
||||
last_entry = xact.entry;
|
||||
|
|
@ -343,12 +319,12 @@ void related_xacts::flush()
|
|||
foreach (xact_t * xact, xacts) {
|
||||
if (xact->entry) {
|
||||
foreach (xact_t * r_xact, xact->entry->xacts) {
|
||||
xact_xdata_t& xdata = xact_xdata(*r_xact);
|
||||
if (! (xdata.dflags & XACT_HANDLED) &&
|
||||
(! (xdata.dflags & XACT_RECEIVED) ?
|
||||
xact_t::xdata_t& xdata(r_xact->xdata());
|
||||
if (! xdata.has_flags(XACT_EXT_HANDLED) &&
|
||||
(! xdata.has_flags(XACT_EXT_RECEIVED) ?
|
||||
! r_xact->has_flags(XACT_AUTO | XACT_VIRTUAL) :
|
||||
also_matching)) {
|
||||
xdata.dflags |= XACT_HANDLED;
|
||||
xdata.add_flags(XACT_EXT_HANDLED);
|
||||
item_handler<xact_t>::operator()(*r_xact);
|
||||
}
|
||||
}
|
||||
|
|
@ -356,10 +332,10 @@ void related_xacts::flush()
|
|||
// This code should only be reachable from the "output"
|
||||
// command, since that is the only command which attempts to
|
||||
// output auto or period entries.
|
||||
xact_xdata_t& xdata = xact_xdata(*xact);
|
||||
if (! (xdata.dflags & XACT_HANDLED) &&
|
||||
xact_t::xdata_t& xdata(xact->xdata());
|
||||
if (! xdata.has_flags(XACT_EXT_HANDLED) &&
|
||||
! xact->has_flags(XACT_AUTO)) {
|
||||
xdata.dflags |= XACT_HANDLED;
|
||||
xdata.add_flags(XACT_EXT_HANDLED);
|
||||
item_handler<xact_t>::operator()(*xact);
|
||||
}
|
||||
}
|
||||
|
|
@ -373,7 +349,7 @@ void changed_value_xacts::output_diff(const date_t& date)
|
|||
{
|
||||
value_t cur_bal;
|
||||
|
||||
xact_xdata(*last_xact).date = date;
|
||||
last_xact->xdata().date = date;
|
||||
#if 0
|
||||
compute_total(cur_bal, details_t(*last_xact));
|
||||
#endif
|
||||
|
|
@ -381,7 +357,7 @@ void changed_value_xacts::output_diff(const date_t& date)
|
|||
|
||||
#if 0
|
||||
// jww (2008-04-24): What does this do?
|
||||
xact_xdata(*last_xact).date = 0;
|
||||
last_xact->xdata().date = 0;
|
||||
#endif
|
||||
|
||||
if (value_t diff = cur_bal - last_balance) {
|
||||
|
|
@ -390,24 +366,18 @@ void changed_value_xacts::output_diff(const date_t& date)
|
|||
entry.payee = "Commodities revalued";
|
||||
entry._date = date;
|
||||
|
||||
handle_value(diff, NULL, &entry, XACT_NO_TOTAL, xact_temps,
|
||||
handle_value(diff, NULL, &entry, XACT_EXT_NO_TOTAL, xact_temps,
|
||||
*handler);
|
||||
}
|
||||
}
|
||||
|
||||
void changed_value_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
if (last_xact) {
|
||||
date_t date;
|
||||
if (xact_has_xdata(*last_xact))
|
||||
date = xact_xdata_(*last_xact).date;
|
||||
else
|
||||
date = xact.date();
|
||||
output_diff(date);
|
||||
}
|
||||
if (last_xact)
|
||||
output_diff(last_xact->reported_date());
|
||||
|
||||
if (changed_values_only)
|
||||
xact_xdata(xact).dflags |= XACT_DISPLAYED;
|
||||
xact.xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||
|
||||
item_handler<xact_t>::operator()(xact);
|
||||
|
||||
|
|
@ -422,9 +392,13 @@ void changed_value_xacts::operator()(xact_t& xact)
|
|||
void component_xacts::operator()(xact_t& xact)
|
||||
{
|
||||
if (handler && pred(xact)) {
|
||||
if (xact_has_xdata(xact) &&
|
||||
xact_xdata_(xact).have_component_xacts())
|
||||
xact_xdata_(xact).walk_component_xacts(*handler);
|
||||
if (xact.has_xdata() &&
|
||||
xact.xdata().has_component_xacts())
|
||||
#if 0
|
||||
xact.xdata().walk_component_xacts(*handler);
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
else
|
||||
(*handler)(xact);
|
||||
}
|
||||
|
|
@ -460,13 +434,13 @@ void subtotal_xacts::operator()(xact_t& xact)
|
|||
if (! is_valid(finish) || xact.date() > finish)
|
||||
finish = xact.date();
|
||||
|
||||
account_t * acct = xact_account(xact);
|
||||
account_t * acct = xact.reported_account();
|
||||
assert(acct);
|
||||
|
||||
values_map::iterator i = values.find(acct->fullname());
|
||||
if (i == values.end()) {
|
||||
value_t temp;
|
||||
add_xact_to(xact, temp);
|
||||
xact.add_to_value(temp);
|
||||
std::pair<values_map::iterator, bool> result
|
||||
= values.insert(values_pair(acct->fullname(), acct_value_t(acct, temp)));
|
||||
assert(result.second);
|
||||
|
|
@ -474,7 +448,7 @@ void subtotal_xacts::operator()(xact_t& xact)
|
|||
if (remember_components)
|
||||
(*result.first).second.components.push_back(&xact);
|
||||
} else {
|
||||
add_xact_to(xact, (*i).second.value);
|
||||
xact.add_to_value((*i).second.value);
|
||||
|
||||
if (remember_components)
|
||||
(*i).second.components.push_back(&xact);
|
||||
|
|
@ -485,9 +459,9 @@ void subtotal_xacts::operator()(xact_t& xact)
|
|||
// that contain only virtual xacts.
|
||||
|
||||
if (! xact.has_flags(XACT_VIRTUAL))
|
||||
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
|
||||
account_xdata(*xact.reported_account()).dflags |= ACCOUNT_HAS_NON_VIRTUALS;
|
||||
else if (! xact.has_flags(XACT_BALANCE))
|
||||
account_xdata(*xact_account(xact)).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
|
||||
account_xdata(*xact.reported_account()).dflags |= ACCOUNT_HAS_UNB_VIRTUALS;
|
||||
}
|
||||
|
||||
void interval_xacts::report_subtotal(const date_t& date)
|
||||
|
|
@ -675,7 +649,7 @@ void budget_xacts::report_budget_items(const date_t& date)
|
|||
xact_t& xact = *pair.second;
|
||||
|
||||
DEBUG("ledger.walk.budget", "Reporting budget for "
|
||||
<< xact_account(xact)->fullname());
|
||||
<< xact.reported_account()->fullname());
|
||||
|
||||
entry_temps.push_back(entry_t());
|
||||
entry_t& entry = entry_temps.back();
|
||||
|
|
@ -704,15 +678,15 @@ void budget_xacts::operator()(xact_t& xact)
|
|||
bool xact_in_budget = false;
|
||||
|
||||
foreach (pending_xacts_list::value_type& pair, pending_xacts)
|
||||
for (account_t * acct = xact_account(xact);
|
||||
for (account_t * acct = xact.reported_account();
|
||||
acct;
|
||||
acct = acct->parent) {
|
||||
if (acct == xact_account(*pair.second)) {
|
||||
if (acct == (*pair.second).reported_account()) {
|
||||
xact_in_budget = true;
|
||||
// Report the xact as if it had occurred in the parent
|
||||
// account.
|
||||
if (xact_account(xact) != acct)
|
||||
xact_xdata(xact).account = acct;
|
||||
if (xact.reported_account() != acct)
|
||||
xact.xdata().account = acct;
|
||||
goto handle;
|
||||
}
|
||||
}
|
||||
|
|
@ -782,8 +756,8 @@ void forecast_xacts::flush()
|
|||
|
||||
item_handler<xact_t>::operator()(temp);
|
||||
|
||||
if (xact_has_xdata(temp) &&
|
||||
xact_xdata_(temp).dflags & XACT_MATCHES) {
|
||||
if (temp.has_xdata() &&
|
||||
temp.xdata().has_flags(XACT_EXT_MATCHES)) {
|
||||
if (! pred(temp))
|
||||
break;
|
||||
last = temp.date();
|
||||
|
|
@ -808,21 +782,20 @@ void forecast_xacts::flush()
|
|||
}
|
||||
|
||||
template <>
|
||||
bool compare_items<account_t>::operator()(const account_t * left,
|
||||
const account_t * right)
|
||||
bool compare_items<account_t>::operator()(account_t * left, account_t * right)
|
||||
{
|
||||
assert(left);
|
||||
assert(right);
|
||||
|
||||
account_xdata_t& lxdata(account_xdata(*left));
|
||||
if (! (lxdata.dflags & ACCOUNT_SORT_CALC)) {
|
||||
lxdata.sort_value = sort_order.calc(const_cast<account_t&>(*left));
|
||||
lxdata.sort_value = sort_order.calc(*left);
|
||||
lxdata.dflags |= ACCOUNT_SORT_CALC;
|
||||
}
|
||||
|
||||
account_xdata_t& rxdata(account_xdata(*right));
|
||||
if (! (rxdata.dflags & ACCOUNT_SORT_CALC)) {
|
||||
rxdata.sort_value = sort_order.calc(const_cast<account_t&>(*right));
|
||||
rxdata.sort_value = sort_order.calc(*right);
|
||||
rxdata.dflags |= ACCOUNT_SORT_CALC;
|
||||
}
|
||||
|
||||
|
|
|
|||
223
walk.h
223
walk.h
|
|
@ -2,6 +2,7 @@
|
|||
#define _WALK_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "entry.h"
|
||||
#include "account.h"
|
||||
|
||||
namespace ledger {
|
||||
|
|
@ -34,123 +35,6 @@ public:
|
|||
|
||||
typedef shared_ptr<item_handler<xact_t> > xact_handler_ptr;
|
||||
|
||||
template <typename T>
|
||||
class compare_items
|
||||
{
|
||||
expr_t sort_order;
|
||||
|
||||
compare_items();
|
||||
|
||||
public:
|
||||
compare_items(const compare_items& other) : sort_order(other.sort_order) {
|
||||
TRACE_CTOR(compare_items, "copy");
|
||||
}
|
||||
compare_items(const expr_t& _sort_order) : sort_order(_sort_order) {
|
||||
TRACE_CTOR(compare_items, "const value_expr&");
|
||||
}
|
||||
~compare_items() throw() {
|
||||
TRACE_DTOR(compare_items);
|
||||
}
|
||||
bool operator()(const T * left, const T * right);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool compare_items<T>::operator()(const T * left, const T * right)
|
||||
{
|
||||
assert(left);
|
||||
assert(right);
|
||||
return sort_order.calc(*left) < sort_order.calc(*right);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool compare_items<xact_t>::operator()(const xact_t * left,
|
||||
const xact_t * right);
|
||||
template <>
|
||||
bool compare_items<account_t>::operator()(const account_t * left,
|
||||
const account_t * right);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Xact handlers
|
||||
//
|
||||
|
||||
#define XACT_RECEIVED 0x0001
|
||||
#define XACT_HANDLED 0x0002
|
||||
#define XACT_TO_DISPLAY 0x0004
|
||||
#define XACT_DISPLAYED 0x0008
|
||||
#define XACT_NO_TOTAL 0x0010
|
||||
#define XACT_SORT_CALC 0x0020
|
||||
#define XACT_COMPOUND 0x0040
|
||||
#define XACT_MATCHES 0x0080
|
||||
|
||||
struct xact_xdata_t : public noncopyable
|
||||
{
|
||||
value_t total;
|
||||
value_t sort_value;
|
||||
value_t value;
|
||||
unsigned int index;
|
||||
unsigned short dflags;
|
||||
date_t date;
|
||||
account_t * account;
|
||||
void * ptr;
|
||||
xacts_list * component_xacts;
|
||||
|
||||
xact_xdata_t()
|
||||
: index(0), dflags(0),
|
||||
account(NULL), ptr(NULL), component_xacts(NULL) {
|
||||
TRACE_CTOR(xact_xdata_t, "");
|
||||
}
|
||||
~xact_xdata_t() {
|
||||
TRACE_DTOR(xact_xdata_t);
|
||||
if (component_xacts)
|
||||
checked_delete(component_xacts);
|
||||
}
|
||||
|
||||
void remember_xact(xact_t& xact) {
|
||||
if (! component_xacts)
|
||||
component_xacts = new xacts_list;
|
||||
component_xacts->push_back(&xact);
|
||||
}
|
||||
|
||||
bool have_component_xacts() const {
|
||||
return component_xacts != NULL && ! component_xacts->empty();
|
||||
}
|
||||
|
||||
void copy_component_xacts(xacts_list& xacts) {
|
||||
foreach (xact_t * xact, xacts)
|
||||
remember_xact(*xact);
|
||||
}
|
||||
|
||||
void walk_component_xacts(item_handler<xact_t>& handler) const {
|
||||
foreach (xact_t * xact, *component_xacts)
|
||||
handler(*xact);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool xact_has_xdata(const xact_t& xact) {
|
||||
return xact.data != NULL;
|
||||
}
|
||||
|
||||
inline xact_xdata_t& xact_xdata_(const xact_t& xact) {
|
||||
return *static_cast<xact_xdata_t *>(xact.data);
|
||||
}
|
||||
|
||||
xact_xdata_t& xact_xdata(const xact_t& xact);
|
||||
void add_xact_to(const xact_t& xact, value_t& value);
|
||||
|
||||
inline account_t * xact_account(xact_t& xact) {
|
||||
if (xact.data) {
|
||||
account_t * account = xact_xdata(xact).account;
|
||||
if (account)
|
||||
return account;
|
||||
}
|
||||
return xact.account;
|
||||
}
|
||||
|
||||
inline const account_t * xact_account(const xact_t& xact) {
|
||||
return xact_account(const_cast<xact_t&>(xact));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class entries_iterator : public noncopyable
|
||||
|
|
@ -226,7 +110,7 @@ public:
|
|||
|
||||
class session_xacts_iterator : public xacts_iterator
|
||||
{
|
||||
entries_iterator entries;
|
||||
entries_iterator entries;
|
||||
entry_xacts_iterator xacts;
|
||||
|
||||
public:
|
||||
|
|
@ -258,10 +142,7 @@ class clear_xact_xdata : public item_handler<xact_t>
|
|||
{
|
||||
public:
|
||||
virtual void operator()(xact_t& xact) {
|
||||
if (xact.data) {
|
||||
checked_delete(static_cast<xact_xdata_t *>(xact.data));
|
||||
xact.data = NULL;
|
||||
}
|
||||
xact.clear_xdata();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -270,11 +151,11 @@ class pass_down_xacts : public item_handler<xact_t>
|
|||
pass_down_xacts();
|
||||
|
||||
public:
|
||||
pass_down_xacts(xact_handler_ptr handler,
|
||||
xacts_iterator& iter)
|
||||
: item_handler<xact_t>(handler) {
|
||||
TRACE_CTOR(pass_down_xacts,
|
||||
"xact_handler_ptr, xacts_iterator");
|
||||
pass_down_xacts(xact_handler_ptr handler, xacts_iterator& iter)
|
||||
: item_handler<xact_t>(handler)
|
||||
{
|
||||
TRACE_CTOR(pass_down_xacts, "xact_handler_ptr, xacts_iterator");
|
||||
|
||||
for (xact_t * xact = iter(); xact; xact = iter())
|
||||
item_handler<xact_t>::operator()(*xact);
|
||||
}
|
||||
|
|
@ -284,6 +165,25 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class push_to_xacts_list : public item_handler<xact_t>
|
||||
{
|
||||
push_to_xacts_list();
|
||||
|
||||
public:
|
||||
xacts_list& xacts;
|
||||
|
||||
push_to_xacts_list(xacts_list& _xacts) : xacts(_xacts) {
|
||||
TRACE_CTOR(push_to_xacts_list, "xacts_list&");
|
||||
}
|
||||
virtual ~push_to_xacts_list() {
|
||||
TRACE_DTOR(push_to_xacts_list);
|
||||
}
|
||||
|
||||
virtual void operator()(xact_t& xact) {
|
||||
xacts.push_back(&xact);
|
||||
}
|
||||
};
|
||||
|
||||
class truncate_entries : public item_handler<xact_t>
|
||||
{
|
||||
int head_count;
|
||||
|
|
@ -306,6 +206,9 @@ public:
|
|||
|
||||
virtual void flush();
|
||||
virtual void operator()(xact_t& xact) {
|
||||
if (tail_count == 0 && head_count > 0 &&
|
||||
xacts.size() >= static_cast<unsigned int>(head_count))
|
||||
return;
|
||||
xacts.push_back(&xact);
|
||||
}
|
||||
};
|
||||
|
|
@ -319,26 +222,6 @@ public:
|
|||
virtual void operator()(xact_t& xact);
|
||||
};
|
||||
|
||||
class push_to_xacts_list : public item_handler<xact_t>
|
||||
{
|
||||
push_to_xacts_list();
|
||||
|
||||
public:
|
||||
xacts_list& xact_list;
|
||||
|
||||
push_to_xacts_list(xacts_list& _xact_list)
|
||||
: xact_list(_xact_list) {
|
||||
TRACE_CTOR(push_to_xacts_list, "xacts_list&");
|
||||
}
|
||||
virtual ~push_to_xacts_list() {
|
||||
TRACE_DTOR(push_to_xacts_list);
|
||||
}
|
||||
|
||||
virtual void operator()(xact_t& xact) {
|
||||
xact_list.push_back(&xact);
|
||||
}
|
||||
};
|
||||
|
||||
class sort_xacts : public item_handler<xact_t>
|
||||
{
|
||||
typedef std::deque<xact_t *> xacts_deque;
|
||||
|
|
@ -444,7 +327,7 @@ public:
|
|||
|
||||
virtual void operator()(xact_t& xact) {
|
||||
if (pred(xact)) {
|
||||
xact_xdata(xact).dflags |= XACT_MATCHES;
|
||||
xact.xdata().add_flags(XACT_EXT_MATCHES);
|
||||
(*handler)(xact);
|
||||
}
|
||||
}
|
||||
|
|
@ -567,7 +450,7 @@ public:
|
|||
|
||||
virtual void flush();
|
||||
virtual void operator()(xact_t& xact) {
|
||||
xact_xdata(xact).dflags |= XACT_RECEIVED;
|
||||
xact.xdata().add_flags(XACT_EXT_RECEIVED);
|
||||
xacts.push_back(&xact);
|
||||
}
|
||||
};
|
||||
|
|
@ -577,12 +460,12 @@ class changed_value_xacts : public item_handler<xact_t>
|
|||
// This filter requires that calc_xacts be used at some point
|
||||
// later in the chain.
|
||||
|
||||
bool changed_values_only;
|
||||
bool changed_values_only;
|
||||
xact_t * last_xact;
|
||||
value_t last_balance;
|
||||
value_t last_balance;
|
||||
|
||||
std::list<entry_t> entry_temps;
|
||||
std::list<xact_t> xact_temps;
|
||||
std::list<entry_t> entry_temps;
|
||||
std::list<xact_t> xact_temps;
|
||||
|
||||
changed_value_xacts();
|
||||
|
||||
|
|
@ -1045,6 +928,40 @@ public:
|
|||
virtual journal_t * operator()();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class compare_items
|
||||
{
|
||||
expr_t sort_order;
|
||||
|
||||
compare_items();
|
||||
|
||||
public:
|
||||
compare_items(const compare_items& other) : sort_order(other.sort_order) {
|
||||
TRACE_CTOR(compare_items, "copy");
|
||||
}
|
||||
compare_items(const expr_t& _sort_order) : sort_order(_sort_order) {
|
||||
TRACE_CTOR(compare_items, "const value_expr&");
|
||||
}
|
||||
~compare_items() throw() {
|
||||
TRACE_DTOR(compare_items);
|
||||
}
|
||||
bool operator()(T * left, T * right);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool compare_items<T>::operator()(T * left, T * right)
|
||||
{
|
||||
assert(left);
|
||||
assert(right);
|
||||
return sort_order.calc(*left) < sort_order.calc(*right);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool compare_items<xact_t>::operator()(xact_t * left, xact_t * right);
|
||||
template <>
|
||||
bool compare_items<account_t>::operator()(account_t * left,
|
||||
account_t * right);
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _WALK_H
|
||||
|
|
|
|||
98
xact.cc
98
xact.cc
|
|
@ -58,18 +58,39 @@ date_t xact_t::effective_date() const
|
|||
}
|
||||
|
||||
namespace {
|
||||
value_t get_amount(xact_t& xact)
|
||||
{
|
||||
return xact.amount;
|
||||
value_t get_state(xact_t& xact) {
|
||||
return long(xact.state);
|
||||
}
|
||||
|
||||
value_t get_date(xact_t& xact)
|
||||
{
|
||||
value_t state_uncleared(call_scope_t&) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
value_t state_cleared(call_scope_t&) {
|
||||
return 1L;
|
||||
}
|
||||
|
||||
value_t state_pending(call_scope_t&) {
|
||||
return 2L;
|
||||
}
|
||||
|
||||
value_t get_date(xact_t& xact) {
|
||||
return xact.date();
|
||||
}
|
||||
|
||||
value_t get_account(call_scope_t& scope)
|
||||
{
|
||||
value_t get_amount(xact_t& xact) {
|
||||
return xact.amount;
|
||||
}
|
||||
|
||||
value_t get_cost(xact_t& xact) {
|
||||
return xact.cost ? *xact.cost : xact.amount;
|
||||
}
|
||||
|
||||
value_t get_note(xact_t& xact) {
|
||||
return string_value(xact.note ? *xact.note : ":NOTELESS:");
|
||||
}
|
||||
|
||||
value_t get_account(call_scope_t& scope) {
|
||||
xact_t& xact(downcast<xact_t>(*scope.parent));
|
||||
|
||||
long width = 0;
|
||||
|
|
@ -78,7 +99,7 @@ namespace {
|
|||
|
||||
// jww (2008-08-02): Accept a width here so that we can abbreviate the
|
||||
// string.
|
||||
string name = xact.account->fullname();
|
||||
string name = xact.reported_account()->fullname();
|
||||
|
||||
if (width > 2)
|
||||
name = format_t::truncate(name, width - 2, true);
|
||||
|
|
@ -92,10 +113,33 @@ namespace {
|
|||
return string_value(name);
|
||||
}
|
||||
|
||||
value_t get_account_base(xact_t& xact)
|
||||
{
|
||||
assert(false);
|
||||
return NULL_VALUE;
|
||||
value_t get_account_base(xact_t& xact) {
|
||||
return string_value(xact.reported_account()->name);
|
||||
}
|
||||
|
||||
value_t get_beg_pos(xact_t& xact) {
|
||||
return long(xact.beg_pos);
|
||||
}
|
||||
|
||||
value_t get_beg_line(xact_t& xact) {
|
||||
return long(xact.beg_line);
|
||||
}
|
||||
|
||||
value_t get_end_pos(xact_t& xact) {
|
||||
return long(xact.end_pos);
|
||||
}
|
||||
|
||||
value_t get_end_line(xact_t& xact) {
|
||||
return long(xact.end_line);
|
||||
}
|
||||
|
||||
// xdata_t members...
|
||||
|
||||
value_t get_total(xact_t& xact) {
|
||||
if (xact.xdata_)
|
||||
return xact.xdata_->total;
|
||||
else
|
||||
return xact.amount;
|
||||
}
|
||||
|
||||
template <value_t (*Func)(xact_t&)>
|
||||
|
|
@ -115,16 +159,33 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
|
|||
else if (name == "account_base")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_account_base>);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (name == "cleared")
|
||||
return expr_t::op_t::wrap_value(0L);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (name[1] == '\0' || name == "date")
|
||||
return WRAP_FUNCTOR(get_wrapper<&get_date>);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (name.find("fmt_") == 0) {
|
||||
if (name == "fmt_A")
|
||||
return WRAP_FUNCTOR(get_account);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (name == "pending")
|
||||
return expr_t::op_t::wrap_value(2L);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (name == "uncleared")
|
||||
return expr_t::op_t::wrap_value(1L);
|
||||
break;
|
||||
}
|
||||
return entry->lookup(name);
|
||||
}
|
||||
|
|
@ -187,4 +248,17 @@ xact_context::xact_context(const xact_t& _xact, const string& desc) throw()
|
|||
}
|
||||
#endif
|
||||
|
||||
void xact_t::add_to_value(value_t& value)
|
||||
{
|
||||
if (xdata_ && xdata_->has_flags(XACT_EXT_COMPOUND)) {
|
||||
value += xdata_->value;
|
||||
}
|
||||
else if (cost || (! value.is_null() && ! value.is_realzero())) {
|
||||
value.add(amount, cost);
|
||||
}
|
||||
else {
|
||||
value = amount;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
140
xact.h
140
xact.h
|
|
@ -37,7 +37,15 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
// These flags persist with the object
|
||||
class entry_t;
|
||||
class account_t;
|
||||
|
||||
class xact_t;
|
||||
typedef std::list<xact_t *> xacts_list;
|
||||
|
||||
class xact_t : public supports_flags<>, public scope_t
|
||||
{
|
||||
public:
|
||||
#define XACT_NORMAL 0x0000 // no flags at all, a basic transaction
|
||||
#define XACT_VIRTUAL 0x0001 // the account was specified with (parens)
|
||||
#define XACT_BALANCE 0x0002 // the account was specified with [brackets]
|
||||
|
|
@ -47,47 +55,42 @@ namespace ledger {
|
|||
#define XACT_GENERATED 0x0020 // transaction was not found in a journal
|
||||
#define XACT_TEMP 0x0040 // transaction is a temporary object
|
||||
|
||||
class entry_t;
|
||||
class account_t;
|
||||
|
||||
class xact_t : public supports_flags<>, public scope_t
|
||||
{
|
||||
public:
|
||||
enum state_t { UNCLEARED, CLEARED, PENDING };
|
||||
|
||||
entry_t * entry;
|
||||
state_t state;
|
||||
account_t * account;
|
||||
state_t state;
|
||||
|
||||
optional<date_t> _date;
|
||||
optional<date_t> _date_eff;
|
||||
optional<string> note;
|
||||
|
||||
amount_t amount;
|
||||
optional<expr_t> amount_expr;
|
||||
optional<amount_t> cost;
|
||||
optional<expr_t> cost_expr;
|
||||
optional<string> note;
|
||||
|
||||
istream_pos_type beg_pos;
|
||||
unsigned long beg_line;
|
||||
istream_pos_type end_pos;
|
||||
unsigned long end_line;
|
||||
|
||||
mutable void * data;
|
||||
static bool use_effective_date;
|
||||
static bool use_effective_date;
|
||||
|
||||
xact_t(account_t * _account = NULL,
|
||||
flags_t _flags = XACT_NORMAL)
|
||||
: supports_flags<>(_flags), entry(NULL),
|
||||
state(UNCLEARED), account(_account),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
|
||||
flags_t _flags = XACT_NORMAL)
|
||||
: supports_flags<>(_flags), entry(NULL), account(_account),
|
||||
state(UNCLEARED), beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
||||
{
|
||||
TRACE_CTOR(xact_t, "account_t *, flags_t");
|
||||
}
|
||||
xact_t(account_t * _account,
|
||||
const amount_t& _amount,
|
||||
flags_t _flags = XACT_NORMAL,
|
||||
const optional<string>& _note = none)
|
||||
: supports_flags<>(_flags), entry(NULL), state(UNCLEARED),
|
||||
account(_account), amount(_amount), note(_note),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL)
|
||||
const amount_t& _amount,
|
||||
flags_t _flags = XACT_NORMAL,
|
||||
const optional<string>& _note = none)
|
||||
: supports_flags<>(_flags), entry(NULL), account(_account),
|
||||
state(UNCLEARED), note(_note), amount(_amount),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0)
|
||||
{
|
||||
TRACE_CTOR(xact_t,
|
||||
"account_t *, const amount_t&, flags_t, const string&");
|
||||
|
|
@ -96,18 +99,18 @@ class xact_t : public supports_flags<>, public scope_t
|
|||
: supports_flags<>(xact),
|
||||
scope_t(),
|
||||
entry(xact.entry),
|
||||
state(xact.state),
|
||||
account(xact.account),
|
||||
state(xact.state),
|
||||
_date(xact._date),
|
||||
_date_eff(xact._date_eff),
|
||||
note(xact.note),
|
||||
amount(xact.amount),
|
||||
cost(xact.cost),
|
||||
note(xact.note),
|
||||
beg_pos(xact.beg_pos),
|
||||
beg_line(xact.beg_line),
|
||||
end_pos(xact.end_pos),
|
||||
end_line(xact.end_line),
|
||||
data(xact.data) // jww (2008-07-19): What are the copy semantics?
|
||||
xdata_(xact.xdata_) // jww (2008-07-19): What are the copy semantics?
|
||||
{
|
||||
TRACE_CTOR(xact_t, "copy");
|
||||
}
|
||||
|
|
@ -129,6 +132,95 @@ class xact_t : public supports_flags<>, public scope_t
|
|||
virtual expr_t::ptr_op_t lookup(const string& name);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
struct xdata_t : public supports_flags<>
|
||||
{
|
||||
#define XACT_EXT_RECEIVED 0x01
|
||||
#define XACT_EXT_HANDLED 0x02
|
||||
#define XACT_EXT_TO_DISPLAY 0x04
|
||||
#define XACT_EXT_DISPLAYED 0x08
|
||||
#define XACT_EXT_NO_TOTAL 0x10
|
||||
#define XACT_EXT_SORT_CALC 0x20
|
||||
#define XACT_EXT_COMPOUND 0x40
|
||||
#define XACT_EXT_MATCHES 0x80
|
||||
|
||||
value_t total;
|
||||
value_t sort_value;
|
||||
value_t value;
|
||||
unsigned int index;
|
||||
date_t date;
|
||||
account_t * account;
|
||||
void * ptr;
|
||||
|
||||
optional<xacts_list> component_xacts;
|
||||
|
||||
xdata_t() : supports_flags<>(), index(0), account(NULL), ptr(NULL) {
|
||||
TRACE_CTOR(xdata_t, "");
|
||||
}
|
||||
~xdata_t() throw() {
|
||||
TRACE_DTOR(xdata_t);
|
||||
}
|
||||
|
||||
void remember_xact(xact_t& xact) {
|
||||
if (! component_xacts)
|
||||
component_xacts = xacts_list();
|
||||
component_xacts->push_back(&xact);
|
||||
}
|
||||
|
||||
bool has_component_xacts() const {
|
||||
return component_xacts && ! component_xacts->empty();
|
||||
}
|
||||
|
||||
void copy_component_xacts(xacts_list& xacts) {
|
||||
foreach (xact_t * xact, xacts)
|
||||
remember_xact(*xact);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void walk_component_xacts(item_handler<xact_t>& handler) const {
|
||||
foreach (xact_t * xact, *component_xacts)
|
||||
handler(*xact);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// This variable holds a pointer to "extended data" which is usually
|
||||
// produced only during reporting, and only for the transaction set being
|
||||
// reported. It's a memory-saving measure to delay allocation until the
|
||||
// last possible moment.
|
||||
mutable optional<xdata_t> xdata_;
|
||||
|
||||
bool has_xdata() const {
|
||||
return xdata_;
|
||||
}
|
||||
void clear_xdata() {
|
||||
xdata_ = none;
|
||||
}
|
||||
xdata_t& xdata() {
|
||||
if (! xdata_)
|
||||
xdata_ = xdata_t();
|
||||
return *xdata_;
|
||||
}
|
||||
|
||||
void add_to_value(value_t& value);
|
||||
|
||||
date_t reported_date() const {
|
||||
if (xdata_ && is_valid(xdata_->date))
|
||||
return xdata_->date;
|
||||
return
|
||||
date();
|
||||
}
|
||||
|
||||
account_t * reported_account() {
|
||||
if (xdata_)
|
||||
if (account_t * acct = xdata_->account)
|
||||
return acct;
|
||||
return account;
|
||||
}
|
||||
|
||||
const account_t * reported_account() const {
|
||||
return const_cast<xact_t *>(this)->reported_account();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
15
xml.cc
15
xml.cc
|
|
@ -381,9 +381,9 @@ void format_xml_entries::format_last_entry()
|
|||
}
|
||||
|
||||
bool first = true;
|
||||
foreach (const xact_t * xact, last_entry->xacts) {
|
||||
if (xact_has_xdata(*xact) &&
|
||||
xact_xdata_(*xact).dflags & XACT_TO_DISPLAY) {
|
||||
foreach (xact_t * xact, last_entry->xacts) {
|
||||
if (xact->has_xdata() &&
|
||||
xact->xdata().has_flags(XACT_EXT_TO_DISPLAY)) {
|
||||
if (first) {
|
||||
output_stream << " <en:xacts>\n";
|
||||
first = false;
|
||||
|
|
@ -427,9 +427,8 @@ void format_xml_entries::format_last_entry()
|
|||
}
|
||||
|
||||
output_stream << " <tr:amount>\n";
|
||||
if (xact_xdata_(*xact).dflags & XACT_COMPOUND)
|
||||
xml_write_value(output_stream,
|
||||
xact_xdata_(*xact).value, 10);
|
||||
if (xact->xdata().has_flags(XACT_EXT_COMPOUND))
|
||||
xml_write_value(output_stream, xact->xdata().value, 10);
|
||||
else
|
||||
xml_write_value(output_stream, value_t(xact->amount), 10);
|
||||
output_stream << " </tr:amount>\n";
|
||||
|
|
@ -448,13 +447,13 @@ void format_xml_entries::format_last_entry()
|
|||
|
||||
if (show_totals) {
|
||||
output_stream << " <total>\n";
|
||||
xml_write_value(output_stream, xact_xdata_(*xact).total, 10);
|
||||
xml_write_value(output_stream, xact->xdata().total, 10);
|
||||
output_stream << " </total>\n";
|
||||
}
|
||||
|
||||
output_stream << " </xact>\n";
|
||||
|
||||
xact_xdata_(*xact).dflags |= XACT_DISPLAYED;
|
||||
xact->xdata().add_flags(XACT_EXT_DISPLAYED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue