diff options
-rw-r--r-- | csv.cc | 7 | ||||
-rw-r--r-- | emacs.cc | 8 | ||||
-rw-r--r-- | entry.h | 6 | ||||
-rw-r--r-- | journal.h | 4 | ||||
-rw-r--r-- | mask.h | 12 | ||||
-rw-r--r-- | op.cc | 28 | ||||
-rw-r--r-- | parser.cc | 1 | ||||
-rw-r--r-- | parser.h | 10 | ||||
-rw-r--r-- | qif.cc | 18 | ||||
-rw-r--r-- | reconcile.cc | 4 | ||||
-rw-r--r-- | report.cc | 8 | ||||
-rw-r--r-- | textual.cc | 2 | ||||
-rw-r--r-- | token.cc | 17 | ||||
-rw-r--r-- | token.h | 6 | ||||
-rw-r--r-- | walk.cc | 167 | ||||
-rw-r--r-- | walk.h | 223 | ||||
-rw-r--r-- | xact.cc | 98 | ||||
-rw-r--r-- | xact.h | 140 | ||||
-rw-r--r-- | xml.cc | 15 |
19 files changed, 387 insertions, 387 deletions
@@ -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); } } @@ -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); } } @@ -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: @@ -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() { @@ -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: { @@ -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; @@ -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); diff --git a/reconcile.cc b/reconcile.cc index 12b66c8c..92068227 100644 --- a/reconcile.cc +++ b/reconcile.cc @@ -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); } } @@ -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; @@ -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(); @@ -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()); + + 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; + } - xact_xdata_t& xdata(xact_xdata(xact)); - - 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.dflags & XACT_NO_TOTAL)) - add_xact_to(xact, xdata.total); - - item_handler<xact_t>::operator()(xact); + if (! xdata.has_flags(XACT_EXT_NO_TOTAL)) + xact.add_to_value(xdata.total); - 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; } @@ -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 @@ -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 state_uncleared(call_scope_t&) { + return 0L; + } + + value_t state_cleared(call_scope_t&) { + return 1L; } - value_t get_date(xact_t& xact) - { + 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 @@ -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 @@ -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); } } |