diff options
author | John Wiegley <johnw@newartisans.com> | 2004-08-27 23:38:39 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2004-08-27 23:38:39 -0400 |
commit | 16841fbae3adcb0a143d709e2597ce543bff084e (patch) | |
tree | 9683e8e1b4442b99e2d7f2e26cf409c89c0f10a6 | |
parent | f0238fdd065ace9edbb65a45875f2f47a7a932d6 (diff) | |
download | fork-ledger-16841fbae3adcb0a143d709e2597ce543bff084e.tar.gz fork-ledger-16841fbae3adcb0a143d709e2597ce543bff084e.tar.bz2 fork-ledger-16841fbae3adcb0a143d709e2597ce543bff084e.zip |
added (disabled) code for Boost.Python
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | account.cc | 115 | ||||
-rwxr-xr-x | acprep | 22 | ||||
-rw-r--r-- | amount.cc | 115 | ||||
-rw-r--r-- | amount.h | 22 | ||||
-rw-r--r-- | balance.cc | 72 | ||||
-rw-r--r-- | binary.cc | 20 | ||||
-rw-r--r-- | gnucash.cc | 19 | ||||
-rw-r--r-- | journal.cc (renamed from ledger.cc) | 260 | ||||
-rw-r--r-- | ledger.h | 26 | ||||
-rw-r--r-- | main.cc | 26 | ||||
-rw-r--r-- | option.cc | 6 | ||||
-rw-r--r-- | option.h | 8 | ||||
-rw-r--r-- | parser.cc | 112 | ||||
-rw-r--r-- | parser.h | 25 | ||||
-rw-r--r-- | qif.cc | 19 | ||||
-rw-r--r-- | textual.cc | 25 | ||||
-rw-r--r-- | value.cc | 15 | ||||
-rw-r--r-- | walk.cc | 6 | ||||
-rw-r--r-- | walk.h | 49 |
20 files changed, 730 insertions, 238 deletions
diff --git a/Makefile.am b/Makefile.am index c9f64685..d5ad48cd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ lib_LTLIBRARIES = libledger.la -libledger_la_SOURCES = account.cc amount.cc autoxact.cc balance.cc binary.cc \ - config.cc datetime.cc format.cc ledger.cc option.cc parser.cc qif.cc \ - quotes.cc textual.cc valexpr.cc value.cc walk.cc +libledger_la_SOURCES = amount.cc autoxact.cc balance.cc binary.cc config.cc \ + datetime.cc format.cc journal.cc option.cc parser.cc qif.cc quotes.cc \ + textual.cc valexpr.cc value.cc walk.cc if DEBUG libledger_la_CXXFLAGS = -DDEBUG_LEVEL=4 libledger_la_SOURCES += debug.cc diff --git a/account.cc b/account.cc deleted file mode 100644 index 0c795654..00000000 --- a/account.cc +++ /dev/null @@ -1,115 +0,0 @@ -#include "ledger.h" - -#include <sstream> -#include <deque> - -namespace ledger { - -account_t::~account_t() -{ - DEBUG_PRINT("ledger.memory.ctors", "dtor account_t"); - //assert(! data); - - for (accounts_map::iterator i = accounts.begin(); - i != accounts.end(); - i++) - delete (*i).second; -} - -account_t * account_t::find_account(const std::string& name, - const bool auto_create) -{ - accounts_map::const_iterator i = accounts.find(name); - if (i != accounts.end()) - return (*i).second; - - static char buf[256]; - - std::string::size_type sep = name.find(':'); - const char * first, * rest; - if (sep == std::string::npos) { - first = name.c_str(); - rest = NULL; - } else { - std::strncpy(buf, name.c_str(), sep); - buf[sep] = '\0'; - - first = buf; - rest = name.c_str() + sep + 1; - } - - account_t * account; - - i = accounts.find(first); - if (i == accounts.end()) { - if (! auto_create) - return NULL; - account = new account_t(this, first); - accounts.insert(accounts_pair(first, account)); - } else { - account = (*i).second; - } - - if (rest) - account = account->find_account(rest, auto_create); - - return account; -} - -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; -} - -std::string account_t::fullname() const -{ - if (! _fullname.empty()) { - return _fullname; - } else { - const account_t * first = this; - std::string fullname = name; - - while (first->parent) { - first = first->parent; - if (! first->name.empty()) - fullname = first->name + ":" + fullname; - } - - _fullname = fullname; - - return fullname; - } -} - -bool account_t::valid() const -{ - if (name.find('-') != std::string::npos) - return false; - - if (depth > 16) - return false; - - for (transactions_list::const_iterator i = transactions.begin(); - i != transactions.end(); - i++) - if ((*i)->account != this) - return false; - - for (accounts_map::const_iterator i = accounts.begin(); - i != accounts.end(); - i++) - if (! (*i).second->valid()) - return false; - - return true; -} - -} // namespace ledger @@ -13,16 +13,24 @@ fi autoconf -INCDIRS="-I/sw/include -I/usr/include/httpd/xml" +INCDIRS="-I/sw/include -I/usr/include/httpd/xml -I/sw/include/python2.3" +LIBFLAGS="-L/sw/lib" + +if [ "$1" = "--boost" ]; then + BOOST="-DUSE_BOOST_PYTHON=1 -Wno-long-double" + shift +fi + if [ "$1" = "--debug" ]; then - ./configure CPPFLAGS="$INCDIRS" LDFLAGS=-L/sw/lib \ - CXXFLAGS="-g" --enable-debug --disable-shared + ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBFLAGS" \ + CXXFLAGS="-g $BOOST" --enable-debug --disable-shared elif [ "$1" = "--opt" ]; then - ./configure CPPFLAGS="$INCDIRS" LDFLAGS=-L/sw/lib \ - CXXFLAGS="-fomit-frame-pointer -fastf -mcpu=7450 -fPIC" --enable-standalone + ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBFLAGS" \ + CXXFLAGS="-fomit-frame-pointer -fastf -mcpu=7450 -fPIC $BOOST" \ + --enable-standalone elif [ "$1" = "--perf" ]; then - ./configure CPPFLAGS="$INCDIRS" LDFLAGS=-L/sw/lib \ - CXXFLAGS="-g -pg" + ./configure CPPFLAGS="$INCDIRS" LDFLAGS="$LIBFLAGS" \ + CXXFLAGS="-g -pg $BOOST" fi rm AUTHORS ChangeLog @@ -469,13 +469,12 @@ amount_t& amount_t::operator/=(const amount_t& amt) } // unary negation -amount_t& amount_t::negate() +void amount_t::negate() { if (quantity) { _dup(); mpz_neg(MPZ(quantity), MPZ(quantity)); } - return *this; } // integer comparisons @@ -1035,3 +1034,115 @@ amount_t commodity_t::value(const std::time_t moment) } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> +#include <Python.h> + +using namespace boost::python; +using namespace ledger; + +void (amount_t::*parse_1)(std::istream& in) = &amount_t::parse; +void (amount_t::*parse_2)(const std::string& str) = &amount_t::parse; + +struct commodity_updater_wrap : commodity_t::updater_t +{ + PyObject * self; + commodity_updater_wrap(PyObject * self_) : self(self_) {} + + virtual void operator()(commodity_t * commodity, + const std::time_t moment, + const std::time_t date, + const std::time_t last, + amount_t& price) { + call_method<void>(self, "__call__", commodity, moment, date, last, price); + } +}; + +void export_amount() +{ + class_< amount_t > ("Amount") + .def(init<amount_t>()) + .def(init<std::string>()) + .def(init<char *>()) + .def(init<bool>()) + .def(init<int>()) + .def(init<unsigned int>()) + .def(init<double>()) + + .def_readonly("commodity", &amount_t::commodity) + + .def(self += self) + .def(self + self) + .def(self -= self) + .def(self - self) + .def(self *= self) + .def(self * self) + .def(self /= self) + .def(self / self) + + .def(self < int()) + .def(self <= int()) + .def(self > int()) + .def(self >= int()) + .def(self == int()) + .def(self != int()) + + .def(self < self) + .def(self <= self) + .def(self > self) + .def(self >= self) + .def(self == self) + .def(self != self) + .def(- self) + .def(! self) + + .def(abs(self)) +#if 0 + .def(str(self)) +#endif + + .def("negate", &amount_t::negate) + .def("parse", parse_1) + .def("parse", parse_2) + .def("valid", &amount_t::valid) + ; + + class_< commodity_t::updater_t, commodity_updater_wrap, boost::noncopyable > + ("Updater") + ; + + class_< commodity_t > ("Commodity") + .def(init<std::string, optional<unsigned int, unsigned int> >()) + + // make this a function which called check_symbol after being set + .def_readwrite("symbol", &commodity_t::symbol) + .def_readwrite("quote", &commodity_t::quote) + .def_readwrite("name", &commodity_t::name) + .def_readwrite("note", &commodity_t::name) + .def_readwrite("precision", &commodity_t::precision) + .def_readwrite("flags", &commodity_t::flags) + .def_readwrite("last_lookup", &commodity_t::last_lookup) + .def_readwrite("conversion", &commodity_t::conversion) + .def_readwrite("ident", &commodity_t::ident) + .def_readwrite("updater", &commodity_t::updater) + .def_readwrite("commodities", &commodity_t::commodities) + .def_readwrite("null_commodity", &commodity_t::null_commodity) + + .def("add_commodity", &commodity_t::add_commodity) + .def("remove_commodity", &commodity_t::remove_commodity) + .def("find_commodity", &commodity_t::find_commodity, + return_value_policy<reference_existing_object>()) + + .def("check_symbol", &commodity_t::check_symbol) + .def("add_price", &commodity_t::add_price) + .def("remove_price", &commodity_t::remove_price) + .def("set_conversion", &commodity_t::set_conversion) + .def("value", &commodity_t::value) + + .def("valid", &commodity_t::valid) + ; +} + +#endif // USE_BOOST_PYTHON @@ -88,29 +88,29 @@ class amount_t amount_t& operator/=(const amount_t& amt); // simple arithmetic - amount_t operator*(const amount_t& amt) const { + amount_t operator+(const amount_t& amt) const { amount_t temp = *this; - temp *= amt; + temp += amt; return temp; } - amount_t operator/(const amount_t& amt) const { + amount_t operator-(const amount_t& amt) const { amount_t temp = *this; - temp /= amt; + temp -= amt; return temp; } - amount_t operator+(const amount_t& amt) const { + amount_t operator*(const amount_t& amt) const { amount_t temp = *this; - temp += amt; + temp *= amt; return temp; } - amount_t operator-(const amount_t& amt) const { + amount_t operator/(const amount_t& amt) const { amount_t temp = *this; - temp -= amt; + temp /= amt; return temp; } // unary negation - amount_t& negate(); + void negate(); amount_t negated() const { amount_t temp = *this; temp.negate(); @@ -182,13 +182,13 @@ inline amount_t abs(const amount_t& amt) { return amt < 0 ? amt.negated() : amt; } +std::ostream& operator<<(std::ostream& out, const amount_t& amt); + inline std::istream& operator>>(std::istream& in, amount_t& amt) { amt.parse(in); return in; } -std::ostream& operator<<(std::ostream& out, const amount_t& amt); - #define COMMODITY_STYLE_DEFAULTS 0x0000 #define COMMODITY_STYLE_SUFFIXED 0x0001 @@ -120,3 +120,75 @@ balance_pair_t& balance_pair_t::operator-=(const transaction_t& xact) } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> + +using namespace boost::python; +using namespace ledger; + +void export_balance() +{ + class_< balance_t > ("Balance") + .def(init<balance_t>()) + .def(init<amount_t>()) + .def(init<int>()) + .def(init<unsigned int>()) + .def(init<double>()) + + .def(self < other<unsigned int>()) + .def(self <= other<unsigned int>()) + .def(self > other<unsigned int>()) + .def(self >= other<unsigned int>()) + .def(self == other<unsigned int>()) + .def(self != other<unsigned int>()) + + .def(self += self) + .def(self += other<amount_t>()) + .def(self + self) + .def(self + other<amount_t>()) + .def(self -= self) + .def(self -= other<amount_t>()) + .def(self - self) + .def(self - other<amount_t>()) + .def(self *= self) + .def(self *= other<amount_t>()) + .def(self * self) + .def(self * other<amount_t>()) + .def(self /= self) + .def(self /= other<amount_t>()) + .def(self / self) + .def(self / other<amount_t>()) + .def(- self) + + .def(self < self) + .def(self < other<amount_t>()) + .def(self <= self) + .def(self <= other<amount_t>()) + .def(self > self) + .def(self > other<amount_t>()) + .def(self >= self) + .def(self >= other<amount_t>()) + .def(self == self) + .def(self == other<amount_t>()) + .def(self != self) + .def(self != other<amount_t>()) + .def(! self) + + .def(abs(self)) + //.def(str(self)) + + .def("negate", &balance_t::negate, + return_value_policy<reference_existing_object>()) + .def("amount", &balance_t::amount) + .def("value", &balance_t::value) + .def("write", &balance_t::write) + .def("valid", &balance_t::valid) + ; + + class_< balance_pair_t > ("BalancePair") + ; +} + +#endif // USE_BOOST_PYTHON @@ -175,7 +175,6 @@ inline void read_binary_amount(char *& data, amount_t& amt) inline void read_binary_transaction(char *& data, transaction_t * xact) { xact->account = accounts[read_binary_number<account_t::ident_t>(data) - 1]; - xact->account->add_transaction(xact); read_binary_amount(data, xact->amount); @@ -601,3 +600,22 @@ void write_binary_journal(std::ostream& out, journal_t * journal, } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> + +using namespace boost::python; +using namespace ledger; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(binary_parse_overloads, + binary_parser_t::parse, 2, 4) + +void export_binary() { + class_< binary_parser_t, bases<parser_t> > ("BinaryParser") + .def("test", &binary_parser_t::test) + .def("parse", &binary_parser_t::parse, binary_parse_overloads()) + ; +} + +#endif // USE_BOOST_PYTHON @@ -317,3 +317,22 @@ unsigned int gnucash_parser_t::parse(std::istream& in, } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> + +using namespace boost::python; +using namespace ledger; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(gnucash_parse_overloads, + gnucash_parser_t::parse, 2, 4) + +void export_gnucash() { + class_< gnucash_parser_t, bases<parser_t> > ("GnucashParser") + .def("test", &gnucash_parser_t::test) + .def("parse", &gnucash_parser_t::parse, gnucash_parse_overloads()) + ; +} + +#endif // USE_BOOST_PYTHON @@ -51,6 +51,38 @@ bool transaction_t::valid() const return true; } +void entry_t::add_transaction(transaction_t * xact) +{ + xact->entry = this; + transactions.push_back(xact); + xact->account->add_transaction(xact); +} + +bool entry_t::remove_transaction(transaction_t * xact) +{ + bool found = false; + transactions_list::iterator i; + for (i = transactions.begin(); i != transactions.end(); i++) + if (*i == xact) { + found = true; + break; + } + if (! found) + return false; + + transactions.erase(i); + + for (i = xact->account->transactions.begin(); + i != xact->account->transactions.end(); + i++) + if (*i == xact) { + xact->account->transactions.erase(i); + return true; + } + + return false; +} + bool entry_t::valid() const { if (! date || date == -1) @@ -68,6 +100,113 @@ bool entry_t::valid() const return true; } +account_t::~account_t() +{ + DEBUG_PRINT("ledger.memory.ctors", "dtor account_t"); + //assert(! data); + + for (accounts_map::iterator i = accounts.begin(); + i != accounts.end(); + i++) + delete (*i).second; +} + +account_t * account_t::find_account(const std::string& name, + const bool auto_create) +{ + accounts_map::const_iterator i = accounts.find(name); + if (i != accounts.end()) + return (*i).second; + + static char buf[256]; + + std::string::size_type sep = name.find(':'); + const char * first, * rest; + if (sep == std::string::npos) { + first = name.c_str(); + rest = NULL; + } else { + std::strncpy(buf, name.c_str(), sep); + buf[sep] = '\0'; + + first = buf; + rest = name.c_str() + sep + 1; + } + + account_t * account; + + i = accounts.find(first); + if (i == accounts.end()) { + if (! auto_create) + return NULL; + account = new account_t(this, first); + accounts.insert(accounts_pair(first, account)); + } else { + account = (*i).second; + } + + if (rest) + account = account->find_account(rest, auto_create); + + return account; +} + +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; +} + +std::string account_t::fullname() const +{ + if (! _fullname.empty()) { + return _fullname; + } else { + const account_t * first = this; + std::string fullname = name; + + while (first->parent) { + first = first->parent; + if (! first->name.empty()) + fullname = first->name + ":" + fullname; + } + + _fullname = fullname; + + return fullname; + } +} + +bool account_t::valid() const +{ + if (name.find('-') != std::string::npos) + return false; + + if (depth > 16) + return false; + + for (transactions_list::const_iterator i = transactions.begin(); + i != transactions.end(); + i++) + if ((*i)->account != this) + return false; + + for (accounts_map::const_iterator i = accounts.begin(); + i != accounts.end(); + i++) + if (! (*i).second->valid()) + return false; + + return true; +} + void clean_commodity_history(char * item_pool, char * item_pool_end); journal_t::~journal_t() @@ -116,7 +255,17 @@ bool journal_t::add_entry(entry_t * entry) bool journal_t::remove_entry(entry_t * entry) { - entries.remove(entry); + bool found = false; + entries_list::iterator i; + for (i = entries.begin(); i != entries.end(); i++) + if (*i == entry) { + found = true; + break; + } + if (! found) + return false; + + entries.erase(i); for (transactions_list::const_iterator i = entry->transactions.begin(); @@ -286,3 +435,112 @@ void shutdown() } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> + +using namespace boost::python; +using namespace ledger; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(journal_find_account_overloads, + find_account, 1, 2) + +#if 0 +template <typename T> +struct ptr_to_ref +{ + ptr_to_ref(T *) {} +}; +#endif + +void export_journal() +{ + class_< transaction_t > ("Transaction") + .def(init<account_t *, amount_t, optional<unsigned int, std::string> >()) + + .def_readwrite("entry", &transaction_t::entry) + .def_readwrite("account", &transaction_t::account) + .def_readwrite("amount", &transaction_t::amount) + .def_readwrite("cost", &transaction_t::cost) + .def_readwrite("flags", &transaction_t::flags) + .def_readwrite("note", &transaction_t::note) + .def_readwrite("data", &transaction_t::data) + + .def("valid", &transaction_t::valid) + ; + + class_< transactions_list > ("TransactionsList") + .def(vector_indexing_suite< transactions_list >()) + ; + + class_< entry_t > ("Entry") + .def_readwrite("date", &entry_t::date) + .def_readwrite("state", &entry_t::state) + .def_readwrite("code", &entry_t::code) + .def_readwrite("payee", &entry_t::payee) + .def_readonly("transactions", &entry_t::transactions) + + .def("add_transaction", &entry_t::add_transaction) + .def("remove_transaction", &entry_t::remove_transaction) + + .def("valid", &entry_t::valid) + ; + + class_< account_t > + ("Account", init<optional<account_t *, std::string, std::string> >()) + .def_readwrite("parent", &account_t::parent) + .def_readwrite("name", &account_t::name) + .def_readwrite("note", &account_t::note) + .def_readonly("depth", &account_t::depth) + .def_readonly("transactions", &account_t::transactions) + .def_readwrite("data", &account_t::data) + .def_readonly("ident", &account_t::ident) + +#if 0 + .def(str(self)) +#endif + + .def("fullname", &account_t::fullname) + .def("add_account", &account_t::add_account) + .def("remove_account", &account_t::remove_account) + .def("find_account", &account_t::find_account, + return_value_policy<reference_existing_object>()) + .def("add_transaction", &account_t::add_transaction) + .def("remove_transaction", &account_t::remove_transaction) + + .def("valid", &account_t::valid) + ; + + class_< entries_list > ("EntriesList") + .def(vector_indexing_suite< entries_list >()) + ; + + class_< strings_list > ("StringsList") + .def(vector_indexing_suite< strings_list >()) + ; + + class_< journal_t > ("Journal") + .def_readwrite("master", &journal_t::master) + .def_readonly("entries", &journal_t::entries) + .def_readwrite("sources", &journal_t::sources) + + .def("add_account", &journal_t::add_account) + .def("remove_account", &journal_t::remove_account) +#if 0 + .def("find_account", &journal_t::find_account, + journal_find_account_overloads(args("name", "auto_create")) + [return_value_policy<reference_existing_object>()]) +#endif + + .def("add_entry", &journal_t::add_entry) + .def("remove_entry", &journal_t::remove_entry) + .def("derive_entry", &journal_t::derive_entry, + return_value_policy<reference_existing_object>()) + + .def("valid", &journal_t::valid) + ; +} + +#endif // USE_BOOST_PYTHON @@ -11,7 +11,7 @@ // #include <map> -#include <list> +#include <deque> #include <string> #include <ctime> #include <iostream> @@ -42,7 +42,7 @@ class transaction_t std::string note; mutable void * data; - transaction_t(account_t * _account) + transaction_t(account_t * _account = NULL) : entry(NULL), account(_account), cost(NULL), flags(TRANSACTION_NORMAL), data(NULL) { } @@ -65,7 +65,7 @@ class transaction_t }; -typedef std::list<transaction_t *> transactions_list; +typedef std::deque<transaction_t *> transactions_list; class entry_t { @@ -91,14 +91,8 @@ class entry_t (*i)->~transaction_t(); } - void add_transaction(transaction_t * xact) { - xact->entry = this; - transactions.push_back(xact); - } - bool remove_transaction(transaction_t * xact) { - transactions.remove(xact); - return true; - } + void add_transaction(transaction_t * xact); + bool remove_transaction(transaction_t * xact); bool valid() const; }; @@ -122,9 +116,9 @@ class account_t mutable ident_t ident; mutable std::string _fullname; - account_t(account_t * _parent, - const std::string& _name = "", - const std::string& _note = "") + account_t(account_t * _parent = NULL, + const std::string& _name = "", + const std::string& _note = "") : parent(_parent), name(_name), note(_note), depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {} @@ -164,8 +158,8 @@ inline std::ostream& operator<<(std::ostream& out, const account_t& acct) { } -typedef std::list<entry_t *> entries_list; -typedef std::list<std::string> strings_list; +typedef std::deque<entry_t *> entries_list; +typedef std::deque<std::string> strings_list; class journal_t { @@ -78,8 +78,8 @@ namespace std { #endif static void -regexps_to_predicate(std::list<std::string>::const_iterator begin, - std::list<std::string>::const_iterator end, +regexps_to_predicate(std::deque<std::string>::const_iterator begin, + std::deque<std::string>::const_iterator end, config_t * config, const bool account_regexp = false, const bool add_account_short_masks = false) @@ -89,7 +89,7 @@ regexps_to_predicate(std::list<std::string>::const_iterator begin, // Treat the remaining command-line arguments as regular // expressions, used for refining report results. - for (std::list<std::string>::const_iterator i = begin; + for (std::deque<std::string>::const_iterator i = begin; i != end; i++) if ((*i)[0] == '-') { @@ -154,7 +154,7 @@ int parse_and_report(int argc, char * argv[], char * envp[]) TIMER_START(process_args); - std::list<std::string> args; + std::deque<std::string> args; process_arguments(argc, argv, false, args); if (args.empty()) { @@ -198,18 +198,18 @@ int parse_and_report(int argc, char * argv[], char * envp[]) std::auto_ptr<qif_parser_t> qif_parser(new qif_parser_t); std::auto_ptr<textual_parser_t> text_parser(new textual_parser_t); - parser_t::parsers.push_back(bin_parser.get()); + register_parser(bin_parser.get()); #ifdef READ_GNUCASH - parser_t::parsers.push_back(gnucash_parser.get()); + register_parser(gnucash_parser.get()); #endif - parser_t::parsers.push_back(qif_parser.get()); - parser_t::parsers.push_back(text_parser.get()); + register_parser(qif_parser.get()); + register_parser(text_parser.get()); int entry_count = 0; try { if (! config->init_file.empty()) { - if (parser_t::parse_file(config->init_file, journal.get())) + if (parse_journal_file(config->init_file, journal.get())) throw error("Entries not allowed in initialization file"); journal->sources.pop_front(); // remove init file } @@ -237,12 +237,12 @@ int parse_and_report(int argc, char * argv[], char * envp[]) use_cache = false; entry_count += text_parser->parse(std::cin, journal.get(), account); } else { - entry_count += parser_t::parse_file(config->data_file, journal.get(), - account); + entry_count += parse_journal_file(config->data_file, journal.get(), + account); } if (! config->price_db.empty()) - if (parser_t::parse_file(config->price_db, journal.get())) + if (parse_journal_file(config->price_db, journal.get())) throw error("Entries not allowed in price history file"); } @@ -327,7 +327,7 @@ int parse_and_report(int argc, char * argv[], char * envp[]) // Treat the remaining command-line arguments as regular // expressions, used for refining report results. - std::list<std::string>::iterator i = args.begin(); + std::deque<std::string>::iterator i = args.begin(); for (; i != args.end(); i++) if (*i == "--") break; @@ -62,7 +62,7 @@ bool process_option(const std::string& opt, const char * arg) } void process_arguments(int argc, char ** argv, const bool anywhere, - std::list<std::string>& args) + std::deque<std::string>& args) { int index = 1; for (char ** i = argv + 1; index < argc; i++, index++) { @@ -83,7 +83,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere, if ((*i)[2] == '\0') break; - for (std::list<option_t>::iterator j = option_handler::options.begin(); + for (std::deque<option_t>::iterator j = option_handler::options.begin(); j != option_handler::options.end(); j++) if ((*j).wants_arg) { @@ -107,7 +107,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere, std::cerr << "Error: illegal option " << *i << std::endl; std::exit(1); } else { - for (std::list<option_t>::iterator j = option_handler::options.begin(); + for (std::deque<option_t>::iterator j = option_handler::options.begin(); j != option_handler::options.end(); j++) if ((*i)[1] == (*j).short_opt) { @@ -2,7 +2,7 @@ #define _OPTION_H #include <map> -#include <list> +#include <deque> #include <string> struct option_handler; @@ -22,7 +22,7 @@ typedef std::pair<const std::string, option_handler *> option_handler_pair; struct option_handler { bool handled; - static std::list<option_t> options; + static std::deque<option_t> options; static option_handler_map handlers; option_handler(const std::string& label, @@ -33,11 +33,11 @@ struct option_handler { bool process_option(const std::string& opt, const char * arg = NULL); void process_arguments(int argc, char ** argv, const bool anywhere, - std::list<std::string>& args); + std::deque<std::string>& args); void process_environment(char ** envp, const std::string& tag); #define DEF_OPT_HANDLERS() \ - std::list<option_t> option_handler::options; \ + std::deque<option_t> option_handler::options; \ option_handler_map option_handler::handlers #define OPT_BEGIN(tag, chars) \ @@ -1,35 +1,117 @@ #include "parser.h" +#include "ledger.h" #include <fstream> +#include <deque> namespace ledger { -parsers_list parser_t::parsers; +typedef std::deque<parser_t *> parsers_list; -unsigned int parser_t::parse_file(const std::string& path, - journal_t * journal, - account_t * master, - const std::string * original_file) +static parsers_list parsers; + +bool register_parser(parser_t * parser) { - journal->sources.push_back(path); + parsers_list::iterator i; + for (i = parsers.begin(); i != parsers.end(); i++) + if (*i == parser) + break; + if (i != parsers.end()) + return false; - if (access(path.c_str(), R_OK) == -1) - return 0; + parsers.push_back(parser); - std::ifstream stream(path.c_str()); + return true; +} + +bool unregister_parser(parser_t * parser) +{ + parsers_list::iterator i; + for (i = parsers.begin(); i != parsers.end(); i++) + if (*i == parser) + break; + if (i == parsers.end()) + return false; + parsers.erase(i); + + return true; +} + +unsigned int parse_journal(std::istream& in, + journal_t * journal, + account_t * master, + const std::string * original_file) +{ if (! master) master = journal->master; - if (! original_file) - original_file = &path; - for (parsers_list::iterator i = parser_t::parsers.begin(); - i != parser_t::parsers.end(); + for (parsers_list::iterator i = parsers.begin(); + i != parsers.end(); i++) - if ((*i)->test(stream)) - return (*i)->parse(stream, journal, master, original_file); + if ((*i)->test(in)) + return (*i)->parse(in, journal, master, original_file); return 0; } +unsigned int parse_journal_file(const std::string& path, + journal_t * journal, + account_t * master, + const std::string * original_file) +{ + journal->sources.push_back(path); + + if (access(path.c_str(), R_OK) == -1) + return 0; + + if (! original_file) + original_file = &path; + + std::ifstream stream(path.c_str()); + return parse_journal(stream, journal, master, original_file); +} + } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> +#include <Python.h> + +using namespace boost::python; +using namespace ledger; + +struct parser_wrap : public parser_t +{ + PyObject * self; + parser_wrap(PyObject * self_) : self(self_) {} + + virtual bool test(std::istream& in) const { + return call_method<bool>(self, "test", in); + } + + virtual unsigned int parse(std::istream& in, + journal_t * journal, + account_t * master = NULL, + const std::string * original_file = NULL) { + return call_method<unsigned int>(self, "__call__", in, journal, master, + original_file); + } +}; + +BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_overloads, parse_journal, 2, 4) +BOOST_PYTHON_FUNCTION_OVERLOADS(parse_journal_file_overloads, + parse_journal_file, 2, 4) + +void export_parser() { + class_< parser_t, parser_wrap, boost::noncopyable > ("Parser") + ; + + def("register_parser", register_parser); + def("unregister_parser", unregister_parser); + def("parse_journal", parse_journal, parse_journal_overloads()); + def("parse_journal_file", parse_journal_file, parse_journal_file_overloads()); +} + +#endif // USE_BOOST_PYTHON @@ -1,12 +1,13 @@ #ifndef _PARSER_H #define _PARSER_H -#include "ledger.h" +#include <iostream> +#include <string> namespace ledger { -class parser_t; -typedef std::list<parser_t *> parsers_list; +class account_t; +class journal_t; class parser_t { @@ -19,14 +20,20 @@ class parser_t journal_t * journal, account_t * master = NULL, const std::string * original_file = NULL) = 0; +}; - static parsers_list parsers; +bool register_parser(parser_t * parser); +bool unregister_parser(parser_t * parser); - static unsigned int parse_file(const std::string& path, - journal_t * journal, - account_t * master = NULL, - const std::string * original_file = NULL); -}; +unsigned int parse_journal(std::istream& in, + journal_t * journal, + account_t * master = NULL, + const std::string * original_file = NULL); + +unsigned int parse_journal_file(const std::string& path, + journal_t * journal, + account_t * master = NULL, + const std::string * original_file = NULL); } // namespace ledger @@ -180,3 +180,22 @@ unsigned int qif_parser_t::parse(std::istream& in, } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> + +using namespace boost::python; +using namespace ledger; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(qif_parse_overloads, + qif_parser_t::parse, 2, 4) + +void export_qif() { + class_< qif_parser_t, bases<parser_t> > ("QifParser") + .def("test", &qif_parser_t::test) + .def("parse", &qif_parser_t::parse, qif_parse_overloads()) + ; +} + +#endif // USE_BOOST_PYTHON @@ -319,7 +319,7 @@ unsigned int textual_parser_t::parse(std::istream& in, unsigned int errors = 0; commodity_t * time_commodity = NULL; - std::list<account_t *> account_stack; + std::deque<account_t *> account_stack; automated_transactions_t auto_xacts; if (! master) @@ -546,8 +546,8 @@ unsigned int textual_parser_t::parse(std::istream& in, push_var<unsigned int> save_linenum(linenum); push_var<std::string> save_path(path); - count += parser_t::parse_file(skip_ws(line), journal, - account_stack.front()); + count += parse_journal_file(skip_ws(line), journal, + account_stack.front()); } break; @@ -590,3 +590,22 @@ unsigned int textual_parser_t::parse(std::istream& in, } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> + +using namespace boost::python; +using namespace ledger; + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(textual_parse_overloads, + textual_parser_t::parse, 2, 4) + +void export_textual() { + class_< textual_parser_t, bases<parser_t> > ("TextualParser") + .def("test", &textual_parser_t::test) + .def("parse", &textual_parser_t::parse, textual_parse_overloads()) + ; +} + +#endif // USE_BOOST_PYTHON @@ -579,3 +579,18 @@ value_t value_t::cost() const } } // namespace ledger + +#ifdef USE_BOOST_PYTHON + +#include <boost/python.hpp> + +using namespace boost::python; +using namespace ledger; + +void export_value() +{ + class_< value_t > ("Value") + ; +} + +#endif // USE_BOOST_PYTHON @@ -8,7 +8,7 @@ void sort_transactions::flush() std::stable_sort(transactions.begin(), transactions.end(), compare_items<transaction_t>(sort_order)); - for (transactions_deque::iterator i = transactions.begin(); + for (transactions_list::iterator i = transactions.begin(); i != transactions.end(); i++) (*handler)(*i); @@ -53,7 +53,7 @@ void calc_transactions::operator()(transaction_t * xact) static void handle_value(const value_t& value, account_t * account, entry_t * entry, unsigned int flags, - transactions_deque& temps, + transactions_list& temps, item_handler<transaction_t> * handler) { balance_t * bal = NULL; @@ -286,7 +286,7 @@ void interval_transactions::operator()(transaction_t * xact) void dow_transactions::flush() { for (int i = 0; i < 7; i++) { - for (transactions_deque::iterator d = days_of_the_week[i].begin(); + for (transactions_list::iterator d = days_of_the_week[i].begin(); d != days_of_the_week[i].end(); d++) subtotal_transactions::operator()(*d); @@ -67,9 +67,6 @@ class compare_items { // Transaction handlers // -typedef std::deque<transaction_t *> transactions_deque; -typedef std::deque<entry_t *> entries_deque; - inline void walk_transactions(transactions_list::iterator begin, transactions_list::iterator end, item_handler<transaction_t>& handler) { @@ -77,19 +74,7 @@ inline void walk_transactions(transactions_list::iterator begin, handler(*i); } -inline void walk_transactions(transactions_list& list, - item_handler<transaction_t>& handler) { - walk_transactions(list.begin(), list.end(), handler); -} - -inline void walk_transactions(transactions_deque::iterator begin, - transactions_deque::iterator end, - item_handler<transaction_t>& handler) { - for (transactions_deque::iterator i = begin; i != end; i++) - handler(*i); -} - -inline void walk_transactions(transactions_deque& deque, +inline void walk_transactions(transactions_list& deque, item_handler<transaction_t>& handler) { walk_transactions(deque.begin(), deque.end(), handler); } @@ -192,7 +177,7 @@ class set_account_value : public item_handler<transaction_t> class sort_transactions : public item_handler<transaction_t> { - transactions_deque transactions; + transactions_list transactions; const value_expr_t * sort_order; public: @@ -243,7 +228,7 @@ class collapse_transactions : public item_handler<transaction_t> entry_t * last_entry; transaction_t * last_xact; account_t * totals_account; - transactions_deque xact_temps; + transactions_list xact_temps; public: collapse_transactions(item_handler<transaction_t> * handler) @@ -258,7 +243,7 @@ class collapse_transactions : public item_handler<transaction_t> totals_account->data = NULL; } delete totals_account; - for (transactions_deque::iterator i = xact_temps.begin(); + for (transactions_list::iterator i = xact_temps.begin(); i != xact_temps.end(); i++) { if ((*i)->data) { @@ -299,8 +284,8 @@ class changed_value_transactions : public item_handler<transaction_t> bool changed_values_only; transaction_t * last_xact; - entries_deque entry_temps; - transactions_deque xact_temps; + entries_list entry_temps; + transactions_list xact_temps; public: changed_value_transactions(item_handler<transaction_t> * handler, @@ -309,12 +294,12 @@ class changed_value_transactions : public item_handler<transaction_t> changed_values_only(_changed_values_only), last_xact(NULL) {} virtual ~changed_value_transactions() { - for (entries_deque::iterator i = entry_temps.begin(); + for (entries_list::iterator i = entry_temps.begin(); i != entry_temps.end(); i++) delete *i; - for (transactions_deque::iterator i = xact_temps.begin(); + for (transactions_list::iterator i = xact_temps.begin(); i != xact_temps.end(); i++) { if ((*i)->data) { @@ -342,20 +327,20 @@ class subtotal_transactions : public item_handler<transaction_t> std::time_t start; std::time_t finish; balances_map balances; - entries_deque entry_temps; - transactions_deque xact_temps; + entries_list entry_temps; + transactions_list xact_temps; public: subtotal_transactions(item_handler<transaction_t> * handler) : item_handler<transaction_t>(handler) {} virtual ~subtotal_transactions() { - for (entries_deque::iterator i = entry_temps.begin(); + for (entries_list::iterator i = entry_temps.begin(); i != entry_temps.end(); i++) delete *i; - for (transactions_deque::iterator i = xact_temps.begin(); + for (transactions_list::iterator i = xact_temps.begin(); i != xact_temps.end(); i++) { if ((*i)->data) { @@ -397,7 +382,7 @@ class interval_transactions : public subtotal_transactions class dow_transactions : public subtotal_transactions { - transactions_deque days_of_the_week[7]; + transactions_list days_of_the_week[7]; public: dow_transactions(item_handler<transaction_t> * handler) @@ -469,11 +454,11 @@ inline void sum_accounts(account_t * account) { ACCT_DATA(account)->count += ACCT_DATA(account)->subcount; } -typedef std::deque<account_t *> accounts_deque; +typedef std::deque<account_t *> accounts_list; inline void sort_accounts(account_t * account, const value_expr_t * sort_order, - accounts_deque& accounts) { + accounts_list& accounts) { for (accounts_map::iterator i = account->accounts.begin(); i != account->accounts.end(); i++) @@ -489,9 +474,9 @@ inline void walk_accounts(account_t * account, handler(account); if (sort_order) { - accounts_deque accounts; + accounts_list accounts; sort_accounts(account, sort_order, accounts); - for (accounts_deque::const_iterator i = accounts.begin(); + for (accounts_list::const_iterator i = accounts.begin(); i != accounts.end(); i++) walk_accounts(*i, handler, sort_order); |