diff options
-rw-r--r-- | autoxact.cc | 25 | ||||
-rw-r--r-- | autoxact.h | 11 | ||||
-rw-r--r-- | journal.cc | 44 | ||||
-rw-r--r-- | journal.h | 37 | ||||
-rw-r--r-- | python.cc | 2 | ||||
-rw-r--r-- | textual.cc | 17 |
6 files changed, 72 insertions, 64 deletions
diff --git a/autoxact.cc b/autoxact.cc index 4de8122d..bed69e2e 100644 --- a/autoxact.cc +++ b/autoxact.cc @@ -27,29 +27,4 @@ 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 - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> -#include <Python.h> - -using namespace boost::python; -using namespace ledger; - -void export_autoxact() { - def("handle_auto_xacts", handle_auto_xacts); -} - -#endif // USE_BOOST_PYTHON @@ -88,9 +88,14 @@ public: } }; -extern automated_transactions_t * current_auto_xacts; - -bool handle_auto_xacts(entry_t& entry); +struct autoxact_finalizer_t : public entry_finalizer_t { + automated_transactions_t auto_xacts; + virtual bool operator()(entry_t& entry) { + if (! auto_xacts.automated_transactions.empty()) + auto_xacts.extend_entry(entry); + return true; + } +}; } // namespace ledger @@ -360,6 +360,7 @@ journal_t::~journal_t() { DEBUG_PRINT("ledger.memory.dtors", "dtor journal_t"); + delete default_finalizer; delete master; // Don't bother unhooking each entry's transactions from the @@ -574,27 +575,42 @@ account_t * py_find_account_2(journal_t& journal, const std::string& name, return journal.find_account(name, auto_create); } -#if 0 +struct py_entry_finalizer_t : public entry_finalizer_t { + object pyobj; + py_entry_finalizer_t() {} + py_entry_finalizer_t(object obj) : pyobj(obj) {} + py_entry_finalizer_t(const py_entry_finalizer_t& other) + : pyobj(other.pyobj) {} + virtual bool operator()(entry_t& entry) { + return call<bool>(pyobj.ptr(), entry); + } +}; + +std::list<py_entry_finalizer_t> py_finalizers; -void py_add_entry_finalize_hook(journal_t& journal, object x) +void py_add_entry_finalizer(journal_t& journal, object x) { - add_hook(journal.entry_finalize_hooks, - extract<journal_t::entry_finalize_hook_t>(x)); + py_finalizers.push_back(py_entry_finalizer_t(x)); + add_hook<entry_finalizer_t *>(journal.entry_finalize_hooks, + &py_finalizers.back()); } -void py_remove_entry_finalize_hook(journal_t& journal, object x) +void py_remove_entry_finalizer(journal_t& journal, object x) { - remove_hook(journal.entry_finalize_hooks, - extract<journal_t::entry_finalize_hook_t>(x)); + for (std::list<py_entry_finalizer_t>::iterator i = py_finalizers.begin(); + i != py_finalizers.end(); + i++) + if ((*i).pyobj == x) { + remove_hook<entry_finalizer_t *>(journal.entry_finalize_hooks, &(*i)); + return; + } } -void py_run_entry_finalize_hooks(journal_t& journal, entry_t& entry) +void py_run_entry_finalizers(journal_t& journal, entry_t& entry) { run_hooks(journal.entry_finalize_hooks, entry); } -#endif - #define EXC_TRANSLATOR(type) \ void exc_translate_ ## type(const type& err) { \ PyErr_SetString(PyExc_RuntimeError, err.what()); \ @@ -682,11 +698,9 @@ void export_journal() .def("add_entry", &journal_t::add_entry) .def("remove_entry", &journal_t::remove_entry) -#if 0 - .def("add_entry_finalize_hook", py_add_entry_finalize_hook) - .def("remove_entry_finalize_hook", py_remove_entry_finalize_hook) - .def("run_entry_finalize_hooks", py_run_entry_finalize_hooks) -#endif + .def("add_entry_finalizer", py_add_entry_finalizer) + .def("remove_entry_finalizer", py_remove_entry_finalizer) + .def("run_entry_finalizers", py_run_entry_finalizers) .def("valid", &journal_t::valid) ; @@ -174,25 +174,40 @@ class account_t std::ostream& operator<<(std::ostream& out, const account_t& account); +struct entry_finalizer_t { + virtual ~entry_finalizer_t() {} + virtual bool operator()(entry_t& entry) = 0; +}; + +struct func_finalizer_t : public entry_finalizer_t { + typedef bool (*func_t)(entry_t& entry); + func_t func; + func_finalizer_t(func_t _func) : func(_func) {} + func_finalizer_t(const func_finalizer_t& other) : func(other.func) {} + virtual bool operator()(entry_t& entry) { + return func(entry); + } +}; + template <typename T> -void add_hook(std::list<T>& list, T func, const bool prepend = false) { +void add_hook(std::list<T>& list, T obj, const bool prepend = false) { if (prepend) - list.push_front(func); + list.push_front(obj); else - list.push_back(func); + list.push_back(obj); } template <typename T> -void remove_hook(std::list<T>& list, T func) { - list.remove(func); +void remove_hook(std::list<T>& list, T obj) { + list.remove(obj); } template <typename T, typename Data> -bool run_hooks(std::list<T>& list, Data& entry) { +bool run_hooks(std::list<T>& list, Data& item) { for (typename std::list<T>::const_iterator i = list.begin(); i != list.end(); i++) - if (! (*i)(entry)) + if (! (*(*i))(item)) return false; return true; } @@ -212,14 +227,14 @@ class journal_t mutable accounts_map accounts_cache; - typedef bool (*entry_finalize_hook_t)(entry_t& entry); - - std::list<entry_finalize_hook_t> entry_finalize_hooks; + std::list<entry_finalizer_t *> entry_finalize_hooks; + entry_finalizer_t * default_finalizer; journal_t() { master = new account_t(NULL, ""); item_pool = item_pool_end = NULL; - add_hook(entry_finalize_hooks, finalize_entry); + default_finalizer = new func_finalizer_t(finalize_entry); + add_hook(entry_finalize_hooks, default_finalizer); } ~journal_t(); @@ -28,7 +28,6 @@ void export_walk(); void export_format(); void export_valexpr(); void export_datetime(); -void export_autoxact(); void export_derive(); void initialize_ledger_for_python() @@ -50,7 +49,6 @@ void initialize_ledger_for_python() export_format(); export_valexpr(); export_datetime(); - export_autoxact(); export_derive(); module_initialized = true; @@ -230,10 +230,8 @@ unsigned int textual_parser_t::parse(std::istream& in, unsigned int errors = 0; commodity_t * time_commodity = NULL; - std::deque<account_t *> account_stack; - automated_transactions_t auto_xacts; - - current_auto_xacts = &auto_xacts; + std::deque<account_t *> account_stack; + autoxact_finalizer_t autoxact_finalizer; if (! master) master = journal->master; @@ -433,10 +431,12 @@ unsigned int textual_parser_t::parse(std::istream& in, case '=': // automated transactions if (! added_autoxact_hook) { - add_hook(journal->entry_finalize_hooks, handle_auto_xacts); + add_hook<entry_finalizer_t *>(journal->entry_finalize_hooks, + &autoxact_finalizer); added_autoxact_hook = true; } - parse_automated_transactions(in, account_stack.front(), auto_xacts); + parse_automated_transactions(in, account_stack.front(), + autoxact_finalizer.auto_xacts); break; case '!': { // directive @@ -449,8 +449,6 @@ unsigned int textual_parser_t::parse(std::istream& in, push_var<unsigned int> save_linenum(linenum); push_var<std::string> save_path(path); - push_var<automated_transactions_t *> - save_current_auto_xacts(current_auto_xacts); count += parse_journal_file(skip_ws(line), journal, account_stack.front()); @@ -496,6 +494,9 @@ unsigned int textual_parser_t::parse(std::istream& in, } done: + if (added_autoxact_hook) + remove_hook<entry_finalizer_t *>(journal->entry_finalize_hooks, + &autoxact_finalizer); if (time_commodity) { time_commodity->precision = 2; time_commodity->flags |= COMMODITY_STYLE_NOMARKET; |