summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2004-08-27 23:38:39 -0400
committerJohn Wiegley <johnw@newartisans.com>2004-08-27 23:38:39 -0400
commit16841fbae3adcb0a143d709e2597ce543bff084e (patch)
tree9683e8e1b4442b99e2d7f2e26cf409c89c0f10a6
parentf0238fdd065ace9edbb65a45875f2f47a7a932d6 (diff)
downloadfork-ledger-16841fbae3adcb0a143d709e2597ce543bff084e.tar.gz
fork-ledger-16841fbae3adcb0a143d709e2597ce543bff084e.tar.bz2
fork-ledger-16841fbae3adcb0a143d709e2597ce543bff084e.zip
added (disabled) code for Boost.Python
-rw-r--r--Makefile.am6
-rw-r--r--account.cc115
-rwxr-xr-xacprep22
-rw-r--r--amount.cc115
-rw-r--r--amount.h22
-rw-r--r--balance.cc72
-rw-r--r--binary.cc20
-rw-r--r--gnucash.cc19
-rw-r--r--journal.cc (renamed from ledger.cc)260
-rw-r--r--ledger.h26
-rw-r--r--main.cc26
-rw-r--r--option.cc6
-rw-r--r--option.h8
-rw-r--r--parser.cc112
-rw-r--r--parser.h25
-rw-r--r--qif.cc19
-rw-r--r--textual.cc25
-rw-r--r--value.cc15
-rw-r--r--walk.cc6
-rw-r--r--walk.h49
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
diff --git a/acprep b/acprep
index f2652dfd..63fc2180 100755
--- a/acprep
+++ b/acprep
@@ -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
diff --git a/amount.cc b/amount.cc
index b168551b..0af00602 100644
--- a/amount.cc
+++ b/amount.cc
@@ -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
diff --git a/amount.h b/amount.h
index d18ff020..bd0acce9 100644
--- a/amount.h
+++ b/amount.h
@@ -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
diff --git a/balance.cc b/balance.cc
index 954dc8a1..b09f1425 100644
--- a/balance.cc
+++ b/balance.cc
@@ -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
diff --git a/binary.cc b/binary.cc
index d055406b..088a6bd8 100644
--- a/binary.cc
+++ b/binary.cc
@@ -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
diff --git a/gnucash.cc b/gnucash.cc
index f035536f..c5b4dcc3 100644
--- a/gnucash.cc
+++ b/gnucash.cc
@@ -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
diff --git a/ledger.cc b/journal.cc
index 3a6f1016..3d2f60bd 100644
--- a/ledger.cc
+++ b/journal.cc
@@ -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
diff --git a/ledger.h b/ledger.h
index 2e24201a..3503e35a 100644
--- a/ledger.h
+++ b/ledger.h
@@ -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
{
diff --git a/main.cc b/main.cc
index 95bf0e0d..3d069234 100644
--- a/main.cc
+++ b/main.cc
@@ -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;
diff --git a/option.cc b/option.cc
index d8ca441a..98b4a1b6 100644
--- a/option.cc
+++ b/option.cc
@@ -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) {
diff --git a/option.h b/option.h
index a0f1e418..b93f50ab 100644
--- a/option.h
+++ b/option.h
@@ -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) \
diff --git a/parser.cc b/parser.cc
index 6a97caa2..46c334d0 100644
--- a/parser.cc
+++ b/parser.cc
@@ -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
diff --git a/parser.h b/parser.h
index 19ceb35a..515bf09b 100644
--- a/parser.h
+++ b/parser.h
@@ -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
diff --git a/qif.cc b/qif.cc
index dac4b3fa..c5e007a7 100644
--- a/qif.cc
+++ b/qif.cc
@@ -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
diff --git a/textual.cc b/textual.cc
index fa7f28d0..074e1f00 100644
--- a/textual.cc
+++ b/textual.cc
@@ -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
diff --git a/value.cc b/value.cc
index 7de21813..8d28e506 100644
--- a/value.cc
+++ b/value.cc
@@ -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
diff --git a/walk.cc b/walk.cc
index 6f4656c5..ffcaede0 100644
--- a/walk.cc
+++ b/walk.cc
@@ -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);
diff --git a/walk.h b/walk.h
index 93a2a3b0..6fa86272 100644
--- a/walk.h
+++ b/walk.h
@@ -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);