From 5429792edc077d8c65d7bbf0f98c3d0e59837775 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 20 Sep 2004 03:25:28 -0400 Subject: the "bal" command mostly works now in main.py; added a finalize_entry hook --- acprep | 3 ++ autoxact.cc | 11 ++++++ autoxact.h | 4 ++ format.cc | 94 +++++++++++++++++++++++++++++++++++++++++--- format.h | 99 +++++++++++----------------------------------- journal.cc | 24 +++++++----- ledger.h | 5 +-- main.cc | 2 + main.py | 70 +++++++++++++++++++++++---------- textual.cc | 27 +++++++------ textual.h | 29 ++++++++++++++ valexpr.cc | 10 +++++ walk.cc | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- walk.h | 71 ++++++--------------------------- 14 files changed, 383 insertions(+), 193 deletions(-) diff --git a/acprep b/acprep index f479a924..17c9d2f3 100755 --- a/acprep +++ b/acprep @@ -23,6 +23,9 @@ if [ "$1" = "--debug" ]; then elif [ "$1" = "--opt" ]; then ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ CXXFLAGS="-fomit-frame-pointer -fastf -mcpu=7450 -fPIC" +elif [ "$1" = "--flat-opt" ]; then + ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" \ + CXXFLAGS="-fomit-frame-pointer -fastf -mcpu=7450" --disable-shared elif [ "$1" = "--perf" ]; then ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBDIRS" CXXFLAGS="-g -pg" fi diff --git a/autoxact.cc b/autoxact.cc index d358daf3..cc07ad2f 100644 --- a/autoxact.cc +++ b/autoxact.cc @@ -27,4 +27,15 @@ void automated_transaction_t::extend_entry(entry_t * entry) } } +automated_transactions_t * current_auto_xacts = NULL; + +bool handle_auto_xacts(entry_t * entry) +{ + if (current_auto_xacts && + ! current_auto_xacts->automated_transactions.empty()) + current_auto_xacts->extend_entry(entry); + + return true; +} + } // namespace ledger diff --git a/autoxact.h b/autoxact.h index 9e25d967..301a2b26 100644 --- a/autoxact.h +++ b/autoxact.h @@ -88,6 +88,10 @@ public: } }; +extern automated_transactions_t * current_auto_xacts; + +bool handle_auto_xacts(entry_t * entry); + } // namespace ledger #endif // _AUTOXACT_H diff --git a/format.cc b/format.cc index 33c465ca..cb5d3027 100644 --- a/format.cc +++ b/format.cc @@ -373,10 +373,37 @@ void format_t::format(std::ostream& out, const details_t& details) const } } -bool format_account::disp_subaccounts_p(const account_t& account, - const item_predicate& - disp_pred, - const account_t *& to_show) +format_transactions::format_transactions(std::ostream& _output_stream, + const std::string& format) + : output_stream(_output_stream), last_entry(NULL) +{ + const char * f = format.c_str(); + if (const char * p = std::strstr(f, "%/")) { + first_line_format.reset(std::string(f, 0, p - f)); + next_lines_format.reset(std::string(p + 2)); + } else { + first_line_format.reset(format); + next_lines_format.reset(format); + } +} + +void format_transactions::operator()(transaction_t& xact) +{ + if (! transaction_has_xdata(xact) || + ! (transaction_xdata(xact).dflags & TRANSACTION_DISPLAYED)) { + if (last_entry != xact.entry) { + first_line_format.format(output_stream, details_t(xact)); + last_entry = xact.entry; + } else { + next_lines_format.format(output_stream, details_t(xact)); + } + transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED; + } +} + +bool disp_subaccounts_p(const account_t& account, + const item_predicate& disp_pred, + const account_t *& to_show) { bool display = false; unsigned int counted = 0; @@ -410,8 +437,8 @@ bool format_account::disp_subaccounts_p(const account_t& account, return display; } -bool format_account::display_account(const account_t& account, - const item_predicate& disp_pred) +bool display_account(const account_t& account, + const item_predicate& disp_pred) { // Never display an account that has already been displayed. if (account_has_xdata(account) && @@ -432,6 +459,59 @@ bool format_account::display_account(const account_t& account, return ! account_to_show && disp_pred(account); } +void format_account::operator()(account_t& account) +{ + if (display_account(account, disp_pred)) { + if (! account.parent) { + account_xdata(account).dflags |= ACCOUNT_TO_DISPLAY; + } else { + format.format(output_stream, details_t(account)); + account_xdata(account).dflags |= ACCOUNT_DISPLAYED; + } + } +} + +format_equity::format_equity(std::ostream& _output_stream, + const std::string& _format, + const std::string& display_predicate) + : output_stream(_output_stream), disp_pred(display_predicate) +{ + const char * f = _format.c_str(); + if (const char * p = std::strstr(f, "%/")) { + first_line_format.reset(std::string(f, 0, p - f)); + next_lines_format.reset(std::string(p + 2)); + } else { + first_line_format.reset(_format); + next_lines_format.reset(_format); + } + + entry_t header_entry; + header_entry.payee = "Opening Balances"; + header_entry.date = std::time(NULL); + first_line_format.format(output_stream, details_t(header_entry)); +} + +void format_equity::flush() +{ + account_xdata_t xdata; + xdata.value = total; + xdata.value.negate(); + account_t summary(NULL, "Equity:Opening Balances"); + summary.data = &xdata; + next_lines_format.format(output_stream, details_t(summary)); + output_stream.flush(); +} + +void format_equity::operator()(account_t& account) +{ + if (display_account(account, disp_pred)) { + next_lines_format.format(output_stream, details_t(account)); + if (account_has_xdata(account)) + total += account_xdata(account).value; + account_xdata(account).dflags |= ACCOUNT_DISPLAYED; + } +} + } // namespace ledger #ifdef USE_BOOST_PYTHON @@ -471,6 +551,8 @@ void export_format() #if 0 def("partial_account_name", partial_account_name); #endif + + def("display_account", display_account); } #endif // USE_BOOST_PYTHON diff --git a/format.h b/format.h index b388d40e..945645f2 100644 --- a/format.h +++ b/format.h @@ -97,36 +97,27 @@ class format_transactions : public item_handler public: format_transactions(std::ostream& _output_stream, - const std::string& format) - : output_stream(_output_stream), last_entry(NULL) { - const char * f = format.c_str(); - if (const char * p = std::strstr(f, "%/")) { - first_line_format.reset(std::string(f, 0, p - f)); - next_lines_format.reset(std::string(p + 2)); - } else { - first_line_format.reset(format); - next_lines_format.reset(format); - } - } + const std::string& format); virtual void flush() { output_stream.flush(); } - virtual void operator()(transaction_t& xact) { - if (! transaction_has_xdata(xact) || - ! (transaction_xdata(xact).dflags & TRANSACTION_DISPLAYED)) { - if (last_entry != xact.entry) { - first_line_format.format(output_stream, details_t(xact)); - last_entry = xact.entry; - } else { - next_lines_format.format(output_stream, details_t(xact)); - } - transaction_xdata(xact).dflags |= TRANSACTION_DISPLAYED; - } - } + virtual void operator()(transaction_t& xact); }; +bool disp_subaccounts_p(const account_t& account, + const item_predicate& disp_pred, + const account_t *& to_show); + +inline bool disp_subaccounts_p(const account_t& account) { + const account_t * temp; + return disp_subaccounts_p(account, item_predicate(NULL), temp); + } + +bool display_account(const account_t& account, + const item_predicate& disp_pred); + class format_account : public item_handler { std::ostream& output_stream; @@ -142,38 +133,18 @@ class format_account : public item_handler : output_stream(_output_stream), format(_format), disp_pred(display_predicate) {} - static bool disp_subaccounts_p(const account_t& account, - const item_predicate& disp_pred, - const account_t *& to_show); - static bool disp_subaccounts_p(const account_t& account) { - const account_t * temp; - return disp_subaccounts_p(account, item_predicate(NULL), temp); - } - - static bool display_account(const account_t& account, - const item_predicate& disp_pred); - virtual void flush() { output_stream.flush(); } - virtual void operator()(account_t& account) { - if (display_account(account, disp_pred)) { - if (! account.parent) { - account_xdata(account).dflags |= ACCOUNT_TO_DISPLAY; - } else { - format.format(output_stream, details_t(account)); - account_xdata(account).dflags |= ACCOUNT_DISPLAYED; - } - } - } + virtual void operator()(account_t& account); }; class format_equity : public item_handler { - std::ostream& output_stream; - const format_t& first_line_format; - const format_t& next_lines_format; + std::ostream& output_stream; + format_t first_line_format; + format_t next_lines_format; item_predicate disp_pred; @@ -181,37 +152,11 @@ class format_equity : public item_handler public: format_equity(std::ostream& _output_stream, - const format_t& _first_line_format, - const format_t& _next_lines_format, - const std::string& display_predicate = NULL) - : output_stream(_output_stream), - first_line_format(_first_line_format), - next_lines_format(_next_lines_format), - disp_pred(display_predicate) { - entry_t header_entry; - header_entry.payee = "Opening Balances"; - header_entry.date = std::time(NULL); - first_line_format.format(output_stream, details_t(header_entry)); - } + const std::string& _format, + const std::string& display_predicate); - virtual void flush() { - account_xdata_t xdata; - xdata.value = total; - xdata.value.negate(); - account_t summary(NULL, "Equity:Opening Balances"); - summary.data = &xdata; - next_lines_format.format(output_stream, details_t(summary)); - output_stream.flush(); - } - - virtual void operator()(account_t& account) { - if (format_account::display_account(account, disp_pred)) { - next_lines_format.format(output_stream, details_t(account)); - if (account_has_xdata(account)) - total += account_xdata(account).value; - account_xdata(account).dflags |= ACCOUNT_DISPLAYED; - } - } + virtual void flush(); + virtual void operator()(account_t& account); }; } // namespace ledger diff --git a/journal.cc b/journal.cc index dde4a1d2..4fedc206 100644 --- a/journal.cc +++ b/journal.cc @@ -193,15 +193,8 @@ account_t * account_t::find_account(const std::string& name, bool account_t::remove_transaction(transaction_t * xact) { - for (transactions_list::iterator i = transactions.begin(); - i != transactions.end(); - i++) - if (*i == xact) { - transactions.erase(i); - return true; - } - - return false; + transactions.remove(xact); + return true; } std::string account_t::fullname() const @@ -224,6 +217,12 @@ std::string account_t::fullname() const } } +std::ostream& operator<<(std::ostream& out, const account_t& account) +{ + out << account.fullname(); + return out; +} + bool account_t::valid() const { if (name.find('-') != std::string::npos) @@ -599,7 +598,9 @@ void export_journal() .def(self == self) .def(self != self) - .def_readwrite("parent", &account_t::parent) + .add_property("parent", + make_getter(&account_t::parent, + return_internal_reference<1>())) .def_readwrite("name", &account_t::name) .def_readwrite("note", &account_t::note) .def_readonly("depth", &account_t::depth) @@ -624,6 +625,9 @@ void export_journal() .def(self == self) .def(self != self) + .add_property("master", + make_getter(&journal_t::master, + return_internal_reference<1>())) .def_readonly("sources", &journal_t::sources) .def("__len__", entries_len) diff --git a/ledger.h b/ledger.h index cc177f82..1aef2e3a 100644 --- a/ledger.h +++ b/ledger.h @@ -178,10 +178,7 @@ class account_t bool valid() const; }; -inline std::ostream& operator<<(std::ostream& out, const account_t& acct) { - out << acct.fullname(); - return out; -} +std::ostream& operator<<(std::ostream& out, const account_t& account); typedef std::list entries_list; diff --git a/main.cc b/main.cc index 145497d8..db1eacd4 100644 --- a/main.cc +++ b/main.cc @@ -1,6 +1,7 @@ #include "ledger.h" #include "parser.h" #include "textual.h" +#include "autoxact.h" #include "binary.h" #include "qif.h" #include "acconf.h" @@ -216,6 +217,7 @@ int parse_and_report(int argc, char * argv[], char * envp[]) #endif std::auto_ptr qif_parser(new qif_parser_t); std::auto_ptr text_parser(new textual_parser_t); + text_parser->add_finalize_hook(handle_auto_xacts); register_parser(bin_parser.get()); #ifdef READ_GNUCASH diff --git a/main.py b/main.py index 458470f0..3a5fe7bc 100755 --- a/main.py +++ b/main.py @@ -116,12 +116,44 @@ class FormatTransaction (TransactionHandler): self.output.flush () def __call__ (self, xact): - if self.nformatter is not None and self.last_entry is not None and \ - xact.entry == self.last_entry: - self.output.write(self.nformatter.format(xact)) + if not transaction_has_xdata (xact) or \ + not transaction_xdata (xact).dflags & TRANSACTION_DISPLAYED: + if self.nformatter is not None and \ + self.last_entry is not None and \ + xact.entry == self.last_entry: + self.output.write(self.nformatter.format(xact)) + else: + self.output.write(self.formatter.format(xact)) + self.last_entry = xact.entry + +class FormatAccount (AccountHandler): + output = None + + def __init__ (self, fmt, pred): + self.formatter = Format (fmt) + self.predicate = AccountPredicate (pred) + + if config.output_file: + self.output = open(config.output_file, "w") else: - self.output.write(self.formatter.format(xact)) - self.last_entry = xact.entry + self.output = sys.stdout + + AccountHandler.__init__ (self) + + def __del__ (self): + if config.output_file: + self.output.close () + + def flush (self): + self.output.flush () + + def __call__ (self, account): + if display_account (account, self.predicate): + if not account.parent: + account_xdata (account).dflags |= ACCOUNT_TO_DISPLAY + else: + self.output.write(self.formatter.format(account)) + account_xdata (account).dflags |= ACCOUNT_DISPLAYED if command == "b" or command == "E": handler = SetAccountValue() @@ -166,28 +198,24 @@ else: handler.flush () -#if command == "b": -# format_account acct_formatter(out, config.format, -# config.display_predicate); -# sum_accounts(*journal->master); -# walk_accounts(*journal->master, acct_formatter, config.sort_string); -# acct_formatter.flush(); -# -# if (journal->master->data) { -# ACCT_DATA(journal->master)->value = ACCT_DATA(journal->master)->total; -# -# if (ACCT_DATA(journal->master)->dflags & ACCOUNT_TO_DISPLAY) { -# out << "--------------------\n"; -# config.format.format(out, details_t(*journal->master)); -# } -# } +if command == "b": + acct_formatter = FormatAccount (format, config.display_predicate) + sum_accounts (journal.master) + walk_accounts (journal.master, acct_formatter, config.sort_string) + acct_formatter.flush () + #if account_has_xdata(journal.master): + # account_xdata(journal.master).value = account_xdata(journal.master).total; + # + # if account_xdata(journal.master).dflags & ACCOUNT_TO_DISPLAY: + # print "--------------------" + # config.format.format(out, details_t(*journal->master)); + #elif command == "E": # format_equity acct_formatter(out, config.format, config.nformat, # config.display_predicate); # sum_accounts(*journal->master); # walk_accounts(*journal->master, acct_formatter, config.sort_string); # acct_formatter.flush(); -# } if config.use_cache and config.cache_dirty and config.cache_file: write_binary_journal(config.cache_file, journal); diff --git a/textual.cc b/textual.cc index e95d0eff..4f60d898 100644 --- a/textual.cc +++ b/textual.cc @@ -121,7 +121,8 @@ transaction_t * parse_transaction(std::istream& in, account_t * account, return parse_transaction_text(line, account, entry); } -void parse_automated_transactions(std::istream& in, account_t * account, +void parse_automated_transactions(std::istream& in, + account_t * account, automated_transactions_t& auto_xacts) { static char line[MAX_LINE + 1]; @@ -238,7 +239,8 @@ namespace { TIMER_DEF(entry_date, "parsing entry date"); } -entry_t * parse_entry(std::istream& in, account_t * master) +entry_t * parse_entry(std::istream& in, account_t * master, + textual_parser_t& parser) { std::auto_ptr curr(new entry_t); @@ -296,8 +298,10 @@ entry_t * parse_entry(std::istream& in, account_t * master) TIMER_START(entry_finish); - if (curr->transactions.empty() || ! finalize_entry(curr.get())) + if (curr->transactions.empty() || + ! parser.run_finalize_hooks(curr.get())) { return NULL; // ~auto_ptr will delete curr + } TIMER_STOP(entry_finish); @@ -326,6 +330,8 @@ unsigned int textual_parser_t::parse(std::istream& in, std::deque account_stack; automated_transactions_t auto_xacts; + current_auto_xacts = &auto_xacts; + if (! master) master = journal->master; @@ -417,10 +423,10 @@ unsigned int textual_parser_t::parse(std::istream& in, = new transaction_t(last_account, amt, TRANSACTION_VIRTUAL); curr->add_transaction(xact); - if (! finalize_entry(curr.get()) || + if (! run_finalize_hooks(curr.get()) || ! journal->add_entry(curr.release())) - assert(0); - + throw parse_error(path, linenum, + "Failed to record 'out' timelog entry"); count++; } else { throw parse_error(path, linenum, "Cannot parse timelog entry date"); @@ -551,7 +557,9 @@ unsigned int textual_parser_t::parse(std::istream& in, linenum++; push_var save_linenum(linenum); - push_var save_path(path); + push_var save_path(path); + push_var + save_current_auto_xacts(current_auto_xacts); count += parse_journal_file(skip_ws(line), journal, account_stack.front()); } @@ -566,10 +574,7 @@ unsigned int textual_parser_t::parse(std::istream& in, default: { unsigned int first_line = linenum; - if (entry_t * entry = parse_entry(in, account_stack.front())) { - if (! auto_xacts.automated_transactions.empty()) - auto_xacts.extend_entry(entry); - + if (entry_t * entry = parse_entry(in, account_stack.front(), *this)) { if (journal->add_entry(entry)) count++; else diff --git a/textual.h b/textual.h index 5fe17dd8..a58153da 100644 --- a/textual.h +++ b/textual.h @@ -5,13 +5,42 @@ namespace ledger { +bool finalize_entry(entry_t * entry); + class textual_parser_t : public parser_t { public: + typedef bool (*finalize_hook_t)(entry_t * entry); + + std::list finalize_hooks; + + textual_parser_t() { + add_finalize_hook(finalize_entry); + } + virtual bool test(std::istream& in) const { return true; } + void add_finalize_hook(finalize_hook_t func, bool prepend = false) { + if (prepend) + finalize_hooks.push_front(func); + else + finalize_hooks.push_back(func); + } + void remove_finalize_hook(finalize_hook_t func) { + finalize_hooks.remove(func); + } + bool run_finalize_hooks(entry_t * entry) { + for (std::list::const_iterator i + = finalize_hooks.begin(); + i != finalize_hooks.end(); + i++) + if (! (*i)(entry)) + return false; + return true; + } + virtual unsigned int parse(std::istream& in, journal_t * journal, account_t * master = NULL, diff --git a/valexpr.cc b/valexpr.cc index 46c30e06..862f730d 100644 --- a/valexpr.cc +++ b/valexpr.cc @@ -945,6 +945,16 @@ void export_valexpr() def("parse_value_expr", py_parse_value_expr, return_value_policy()); + + class_< item_predicate > + ("TransactionPredicate", init()) + .def("__call__", &item_predicate::operator()) + ; + + class_< item_predicate > + ("AccountPredicate", init()) + .def("__call__", &item_predicate::operator()) + ; } #endif // USE_BOOST_PYTHON diff --git a/walk.cc b/walk.cc index ae4624eb..205d4d65 100644 --- a/walk.cc +++ b/walk.cc @@ -298,6 +298,76 @@ void dow_transactions::flush() } } +void sum_accounts(account_t& account) +{ + for (accounts_map::iterator i = account.accounts.begin(); + i != account.accounts.end(); + i++) { + sum_accounts(*(*i).second); + account_xdata(account).total += account_xdata(*(*i).second).total; + account_xdata(account).count += (account_xdata(*(*i).second).count + + account_xdata(*(*i).second).subcount); + } + account_xdata(account).total += account_xdata(account).value; + account_xdata(account).count += account_xdata(account).subcount; +} + +void sort_accounts(account_t& account, + const value_expr_t * sort_order, + accounts_deque& accounts) +{ + for (accounts_map::iterator i = account.accounts.begin(); + i != account.accounts.end(); + i++) + accounts.push_back((*i).second); + + std::stable_sort(accounts.begin(), accounts.end(), + compare_items(sort_order)); +} + +void walk_accounts(account_t& account, + item_handler& handler, + const value_expr_t * sort_order) +{ + handler(account); + + if (sort_order) { + accounts_deque accounts; + sort_accounts(account, sort_order, accounts); + for (accounts_deque::const_iterator i = accounts.begin(); + i != accounts.end(); + i++) + walk_accounts(**i, handler, sort_order); + } else { + for (accounts_map::const_iterator i = account.accounts.begin(); + i != account.accounts.end(); + i++) + walk_accounts(*(*i).second, handler, NULL); + } +} + +void walk_accounts(account_t& account, + item_handler& handler, + const std::string& sort_string) +{ + if (! sort_string.empty()) { + std::auto_ptr sort_order(parse_value_expr(sort_string)); + walk_accounts(account, handler, sort_order.get()); + } else { + walk_accounts(account, handler); + } +} + +void clear_accounts_xdata() +{ + accounts_xdata.clear(); + + for (std::list::iterator i = accounts_xdata_ptrs.begin(); + i != accounts_xdata_ptrs.end(); + i++) + **i = NULL; +} + } // namespace ledger #ifdef USE_BOOST_PYTHON @@ -324,7 +394,7 @@ struct item_handler_wrap : public item_handler } virtual void operator()(T& item) { - call_method(self, "__call__", item); + call_method(self, "__call__", ptr(&item)); } void default_call(T& item) { item_handler::operator()(item); @@ -344,6 +414,26 @@ void py_walk_transactions(entry_t& entry, item_handler& handler) walk_transactions(entry.transactions, handler); } +void py_walk_accounts_1(account_t& account, + item_handler& handler) +{ + walk_accounts(account, handler); +} + +void py_walk_accounts_2(account_t& account, + item_handler& handler, + const value_expr_t * sort_order) +{ + walk_accounts(account, handler, sort_order); +} + +void py_walk_accounts_3(account_t& account, + item_handler& handler, + const std::string& sort_string) +{ + walk_accounts(account, handler, sort_string); +} + void export_walk() { typedef item_handler xact_handler_t; @@ -377,9 +467,8 @@ void export_walk() .def("__call__", &ignore_transactions::operator()); ; - class_< set_account_value, bases > - ("SetAccountValue", init() - [with_custodian_and_ward<1, 2>()]) + class_< set_account_value, bases > ("SetAccountValue") + .def(init()[with_custodian_and_ward<1, 2>()]) .def("flush", &xact_handler_t::flush) .def("__call__", &set_account_value::operator()); ; @@ -455,6 +544,36 @@ void export_walk() def("walk_entries", py_walk_entries); def("walk_transactions", py_walk_transactions); + + typedef item_handler account_handler_t; + + scope().attr("ACCOUNT_DISPLAYED") = ACCOUNT_DISPLAYED; + scope().attr("ACCOUNT_TO_DISPLAY") = ACCOUNT_TO_DISPLAY; + + class_< account_xdata_t > ("AccountXData") + .def_readwrite("value", &account_xdata_t::value) + .def_readwrite("total", &account_xdata_t::total) + .def_readwrite("count", &account_xdata_t::count) + .def_readwrite("subcount", &account_xdata_t::subcount) + .def_readwrite("dflags", &account_xdata_t::dflags) + ; + + def("account_has_xdata", account_has_xdata); + def("account_xdata", account_xdata, return_internal_reference<1>()); + + class_< account_handler_t, item_handler_wrap > ("AccountHandler") + .def(init()) + + .def("flush", &account_handler_t::flush, + &item_handler_wrap::default_flush) + .def("__call__", &account_handler_t::operator(), + &item_handler_wrap::default_call) + ; + + def("sum_accounts", sum_accounts); + def("walk_accounts", py_walk_accounts_1); + def("walk_accounts", py_walk_accounts_2); + def("walk_accounts", py_walk_accounts_3); } #endif // USE_BOOST_PYTHON diff --git a/walk.h b/walk.h index 846ccfe1..147c900b 100644 --- a/walk.h +++ b/walk.h @@ -444,72 +444,23 @@ inline void set_account_value::operator()(transaction_t& xact) { ////////////////////////////////////////////////////////////////////// -inline void sum_accounts(account_t& account) { - for (accounts_map::iterator i = account.accounts.begin(); - i != account.accounts.end(); - i++) { - sum_accounts(*(*i).second); - account_xdata(account).total += account_xdata(*(*i).second).total; - account_xdata(account).count += (account_xdata(*(*i).second).count + - account_xdata(*(*i).second).subcount); - } - account_xdata(account).total += account_xdata(account).value; - account_xdata(account).count += account_xdata(account).subcount; -} +void sum_accounts(account_t& account); typedef std::deque accounts_deque; -inline void sort_accounts(account_t& account, - const value_expr_t * sort_order, - accounts_deque& accounts) { - for (accounts_map::iterator i = account.accounts.begin(); - i != account.accounts.end(); - i++) - accounts.push_back((*i).second); - - std::stable_sort(accounts.begin(), accounts.end(), - compare_items(sort_order)); -} - -inline void walk_accounts(account_t& account, - item_handler& handler, - const value_expr_t * sort_order = NULL) { - handler(account); - - if (sort_order) { - accounts_deque accounts; - sort_accounts(account, sort_order, accounts); - for (accounts_deque::const_iterator i = accounts.begin(); - i != accounts.end(); - i++) - walk_accounts(**i, handler, sort_order); - } else { - for (accounts_map::const_iterator i = account.accounts.begin(); - i != account.accounts.end(); - i++) - walk_accounts(*(*i).second, handler, NULL); - } -} +void sort_accounts(account_t& account, + const value_expr_t * sort_order, + accounts_deque& accounts); -inline void walk_accounts(account_t& account, - item_handler& handler, - const std::string& sort_string) { - if (! sort_string.empty()) { - std::auto_ptr sort_order(parse_value_expr(sort_string)); - walk_accounts(account, handler, sort_order.get()); - } else { - walk_accounts(account, handler); - } -} +void walk_accounts(account_t& account, + item_handler& handler, + const value_expr_t * sort_order = NULL); -inline void clear_accounts_xdata() { - accounts_xdata.clear(); +void walk_accounts(account_t& account, + item_handler& handler, + const std::string& sort_string); - for (std::list::iterator i = accounts_xdata_ptrs.begin(); - i != accounts_xdata_ptrs.end(); - i++) - **i = NULL; -} +void clear_accounts_xdata(); } // namespace ledger -- cgit v1.2.3