diff options
author | John Wiegley <johnw@newartisans.com> | 2004-08-29 23:32:29 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2004-08-29 23:32:29 -0400 |
commit | 63367e3aac062a7b55a3ba5c36a6c7fffbb6e2cc (patch) | |
tree | 6af161c7d0a7ca78a26f8b1f1f57426acddf9be9 | |
parent | 2d62f7b633bdaa39c650bb67425514cf1e66a4dd (diff) | |
download | fork-ledger-63367e3aac062a7b55a3ba5c36a6c7fffbb6e2cc.tar.gz fork-ledger-63367e3aac062a7b55a3ba5c36a6c7fffbb6e2cc.tar.bz2 fork-ledger-63367e3aac062a7b55a3ba5c36a6c7fffbb6e2cc.zip |
the amount/balance/value logic is now a library, completely separate from ledger
-rw-r--r-- | Makefile.am | 42 | ||||
-rwxr-xr-x | acprep | 2 | ||||
-rw-r--r-- | amount.cc | 203 | ||||
-rw-r--r-- | amount.h | 69 | ||||
-rw-r--r-- | autoxact.cc | 2 | ||||
-rw-r--r-- | balance.cc | 105 | ||||
-rw-r--r-- | balance.h | 91 | ||||
-rw-r--r-- | binary.cc | 29 | ||||
-rw-r--r-- | binary.h | 5 | ||||
-rw-r--r-- | error.h | 6 | ||||
-rw-r--r-- | format.cc | 31 | ||||
-rw-r--r-- | format.h | 52 | ||||
-rw-r--r-- | journal.cc | 18 | ||||
-rw-r--r-- | ledger.h | 61 | ||||
-rw-r--r-- | main.cc | 27 | ||||
-rw-r--r-- | python.cc | 7 | ||||
-rwxr-xr-x | setup.py | 6 | ||||
-rw-r--r-- | valexpr.cc | 3 | ||||
-rw-r--r-- | valexpr.h | 25 | ||||
-rw-r--r-- | value.cc | 79 | ||||
-rw-r--r-- | value.h | 37 | ||||
-rw-r--r-- | walk.cc | 136 | ||||
-rw-r--r-- | walk.h | 113 |
23 files changed, 613 insertions, 536 deletions
diff --git a/Makefile.am b/Makefile.am index 4b3d0ab0..191017d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,11 @@ -lib_LTLIBRARIES = libledger.la -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 +lib_LTLIBRARIES = libamounts.la +libamounts_la_SOURCES = amount.cc balance.cc value.cc +libamounts_la_LDFLAGS = -version-info 2:0 + +lib_LTLIBRARIES += libledger.la +libledger_la_SOURCES = autoxact.cc binary.cc config.cc datetime.cc \ + format.cc journal.cc option.cc parser.cc qif.cc quotes.cc \ + textual.cc valexpr.cc walk.cc if READ_GNUCASH libledger_la_SOURCES += gnucash.cc endif @@ -18,12 +22,13 @@ if DEBUG ledger_CXXFLAGS = -DDEBUG_LEVEL=4 endif ledger_SOURCES = main.cc -ledger_LDADD = $(LIBOBJS) libledger.la +ledger_LDADD = $(LIBOBJS) libamounts.la libledger.la nobase_include_HEADERS = \ amount.h \ - autoxact.h \ balance.h \ + value.h \ + autoxact.h \ binary.h \ config.h \ datetime.h \ @@ -38,7 +43,6 @@ nobase_include_HEADERS = \ quotes.h \ textual.h \ valexpr.h \ - value.h \ walk.h info_TEXINFOS = ledger.texi @@ -47,10 +51,14 @@ info_TEXINFOS = ledger.texi if HAVE_PYTHON if HAVE_BOOST_PYTHON -noinst_LIBRARIES = libledger_bpy.a -libledger_bpy_a_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 +noinst_LIBRARIES = libamounts_bpy.a +libamounts_bpy_a_SOURCES = amount.cc balance.cc value.cc +libamounts_bpy_a_CXXFLAGS = -DUSE_BOOST_PYTHON=1 + +noinst_LIBRARIES += libledger_bpy.a +libledger_bpy_a_SOURCES = autoxact.cc binary.cc config.cc datetime.cc \ + format.cc journal.cc option.cc parser.cc qif.cc quotes.cc \ + textual.cc valexpr.cc walk.cc libledger_bpy_a_CXXFLAGS = -DUSE_BOOST_PYTHON=1 if READ_GNUCASH libledger_bpy_a_SOURCES += gnucash.cc @@ -60,13 +68,17 @@ libledger_bpy_a_CXXFLAGS += -DDEBUG_LEVEL=4 libledger_bpy_a_SOURCES += debug.cc endif -bin_PROGRAMS += ledger.so +bin_PROGRAMS += amounts.so ledger.so + +amounts.so: pyamounts.cc libamounts_bpy.a + CFLAGS="$(CPPFLAGS) -L." python setup_amounts.py build --build-lib=. -ledger.so: python.cc libledger_bpy.a - CFLAGS="$(CPPFLAGS) -L." python setup.py build --build-lib=. +ledger.so: pyledger.cc libamounts_bpy.a libledger_bpy.a + CFLAGS="$(CPPFLAGS) -L." python setup_ledger.py build --build-lib=. install-exec-hook: - CFLAGS="$(CPPFLAGS) -L." python setup.py install --prefix=$(DESTDIR) + CFLAGS="$(CPPFLAGS) -L." python setup_amounts.py install --prefix=$(DESTDIR) + CFLAGS="$(CPPFLAGS) -L." python setup_ledger.py install --prefix=$(DESTDIR) endif endif @@ -1,6 +1,6 @@ #!/bin/sh -libtoolize --automake -fc +libtoolize --automake -f -c aclocal autoheader touch AUTHORS ChangeLog @@ -1,10 +1,8 @@ #include "amount.h" -#include "binary.h" -#include "error.h" #include "util.h" #include <sstream> -#include <cstring> +#include <deque> #include "gmp.h" @@ -21,23 +19,17 @@ class amount_t::bigint_t { unsigned int index; bigint_t() : prec(0), flags(0), ref(1), index(0) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init(val); } bigint_t(mpz_t _val) : prec(0), flags(0), ref(1), index(0) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init_set(val, _val); } bigint_t(const bigint_t& other) : prec(other.prec), flags(0), ref(1), index(0) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init_set(val, other.val); } ~bigint_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor amount_t::bigint_t"); -#if DEBUG_LEVEL >= BETA assert(ref == 0); -#endif mpz_clear(val); } }; @@ -56,7 +48,12 @@ commodity_t::updater_t * commodity_t::updater = NULL; commodities_map commodity_t::commodities; commodity_t * commodity_t::null_commodity; -void initialize_amounts() +static struct _init_amounts { + _init_amounts(); + ~_init_amounts(); +} _init_obj; + +_init_amounts::_init_amounts() { mpz_init(temp); mpz_init(divisor); @@ -67,6 +64,26 @@ void initialize_amounts() commodity_t::null_commodity = commodity_t::find_commodity("", true); } +_init_amounts::~_init_amounts() +{ + mpz_clear(divisor); + mpz_clear(temp); + + if (commodity_t::updater) { + delete commodity_t::updater; + commodity_t::updater = NULL; + } + + for (commodities_map::iterator i = commodity_t::commodities.begin(); + i != commodity_t::commodities.end(); + i++) + delete (*i).second; + + commodity_t::commodities.clear(); + + true_value.ref--; +} + void clean_commodity_history(char * item_pool, char * item_pool_end) { for (commodities_map::iterator i = commodity_t::commodities.begin(); @@ -94,26 +111,6 @@ void clean_commodity_history(char * item_pool, char * item_pool_end) } } -void shutdown_amounts() -{ - mpz_clear(divisor); - mpz_clear(temp); - - if (commodity_t::updater) { - delete commodity_t::updater; - commodity_t::updater = NULL; - } - - for (commodities_map::iterator i = commodity_t::commodities.begin(); - i != commodity_t::commodities.end(); - i++) - delete (*i).second; - - commodity_t::commodities.clear(); - - true_value.ref--; -} - static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec) { // Round `value', with an encoding precision of `value_prec', to a @@ -162,21 +159,17 @@ static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec) amount_t::amount_t(const bool value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); - if (value) { - quantity = &true_value; + quantity = &true_value; quantity->ref++; } else { - quantity = NULL; + quantity = NULL; } commodity_ = NULL; } amount_t::amount_t(const int value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); - if (value != 0) { quantity = new bigint_t; mpz_set_si(MPZ(quantity), value); @@ -188,8 +181,6 @@ amount_t::amount_t(const int value) amount_t::amount_t(const unsigned int value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); - if (value != 0) { quantity = new bigint_t; mpz_set_ui(MPZ(quantity), value); @@ -201,8 +192,6 @@ amount_t::amount_t(const unsigned int value) amount_t::amount_t(const double value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); - if (value != 0.0) { quantity = new bigint_t; mpz_set_d(MPZ(quantity), value); @@ -668,7 +657,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt) std::free(p); } else { - strings_list strs; + std::deque<std::string> strs; char buf[4]; for (int powers = 0; true; powers += 3) { @@ -687,7 +676,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt) bool printed = false; - for (strings_list::reverse_iterator i = strs.rbegin(); + for (std::deque<std::string>::reverse_iterator i = strs.rbegin(); i != strs.rend(); i++) { if (printed) { @@ -858,8 +847,81 @@ void amount_t::parse(const std::string& str) } +char * bigints; +char * bigints_next; +unsigned int bigints_index; +unsigned int bigints_count; + +void amount_t::read_quantity(char *& data) +{ + char byte = *data++;; + + if (byte == 0) { + quantity = NULL; + } + else if (byte == 1) { + quantity = new((bigint_t *)bigints_next) bigint_t; + bigints_next += sizeof(bigint_t); + quantity->flags |= BIGINT_BULK_ALLOC; + + unsigned short len = *((unsigned short *) data); + data += sizeof(unsigned short); + mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short), + 0, 0, data); + data += len; + + char negative = *data++; + if (negative) + mpz_neg(MPZ(quantity), MPZ(quantity)); + + quantity->prec = *((unsigned short *) data); + data += sizeof(unsigned short); + } else { + unsigned int index = *((unsigned int *) data); + data += sizeof(unsigned int); + + quantity = (bigint_t *) (bigints + (index - 1) * sizeof(bigint_t)); + quantity->ref++; + } +} + static char buf[4096]; +void amount_t::read_quantity(std::istream& in) +{ + static std::deque<bigint_t *> _bigints; + + char byte; + in.read(&byte, sizeof(byte)); + + if (byte == 0) { + quantity = NULL; + } + else if (byte == 1) { + quantity = new bigint_t; + _bigints.push_back(quantity); + + unsigned short len; + in.read((char *)&len, sizeof(len)); + assert(len < 4096); + in.read(buf, len); + mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short), + 0, 0, buf); + + char negative; + in.read(&negative, sizeof(negative)); + if (negative) + mpz_neg(MPZ(quantity), MPZ(quantity)); + + in.read((char *)&quantity->prec, sizeof(quantity->prec)); + } else { + unsigned int index; + in.read((char *)&index, sizeof(index)); + quantity = _bigints[index - 1]; + quantity->ref++; + } +} + void amount_t::write_quantity(std::ostream& out) const { char byte; @@ -883,6 +945,7 @@ void amount_t::write_quantity(std::ostream& out) const out.write((char *)&len, sizeof(len)); if (len) { + assert(len < 4096); out.write(buf, len); byte = mpz_sgn(MPZ(quantity)) < 0 ? 1 : 0; @@ -901,38 +964,6 @@ void amount_t::write_quantity(std::ostream& out) const } } -void amount_t::read_quantity(char *& data) -{ - char byte = *data++;; - - if (byte == 0) { - quantity = NULL; - } - else if (byte == 1) { - quantity = new(bigints_next++) bigint_t; - quantity->flags |= BIGINT_BULK_ALLOC; - - unsigned short len = *((unsigned short *) data); - data += sizeof(unsigned short); - mpz_import(MPZ(quantity), len / sizeof(short), 1, sizeof(short), - 0, 0, data); - data += len; - - char negative = *data++; - if (negative) - mpz_neg(MPZ(quantity), MPZ(quantity)); - - quantity->prec = *((unsigned short *) data); - data += sizeof(unsigned short); - } else { - unsigned int index = *((unsigned int *) data); - data += sizeof(unsigned int); - - quantity = bigints + (index - 1); - quantity->ref++; - } -} - bool amount_t::valid() const { if (quantity) { @@ -1039,30 +1070,38 @@ void export_amount() .def("commodity", &amount_t::commodity, return_value_policy<reference_existing_object>()) .def("set_commodity", &amount_t::set_commodity) + .def("clear_commodity", &amount_t::clear_commodity) .def(self += self) + .def(self += int()) .def(self + self) + .def(self + int()) .def(self -= self) + .def(self -= int()) .def(self - self) + .def(self - int()) .def(self *= self) + .def(self *= int()) .def(self * self) + .def(self * int()) .def(self /= self) + .def(self /= int()) .def(self / self) - - .def(self < int()) - .def(self <= int()) - .def(self > int()) - .def(self >= int()) - .def(self == int()) - .def(self != int()) + .def(self / int()) + .def(- self) .def(self < self) + .def(self < int()) .def(self <= self) + .def(self <= int()) .def(self > self) + .def(self > int()) .def(self >= self) + .def(self >= int()) .def(self == self) + .def(self == int()) .def(self != self) - .def(- self) + .def(self != int()) .def(! self) .def(abs(self)) @@ -6,8 +6,8 @@ #include <ctime> #include <cctype> #include <iostream> - -#include "debug.h" +#include <cassert> +#include <exception> namespace ledger { @@ -41,22 +41,17 @@ class amount_t public: // constructors - amount_t() : quantity(NULL), commodity_(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); - } + amount_t() : quantity(NULL), commodity_(NULL) {} amount_t(const amount_t& amt) : quantity(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); if (amt.quantity) _copy(amt); else commodity_ = NULL; } amount_t(const std::string& value) : quantity(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); parse(value); } amount_t(const char * value) : quantity(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); parse(value); } amount_t(const bool value); @@ -66,7 +61,6 @@ class amount_t // destructor ~amount_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor amount_t"); if (quantity) _release(); } @@ -75,6 +69,9 @@ class amount_t void set_commodity(commodity_t& comm) { commodity_ = &comm; } + void clear_commodity() { + commodity_ = NULL; + } // assignment operator amount_t& operator=(const amount_t& amt); @@ -94,6 +91,19 @@ class amount_t amount_t& operator*=(const amount_t& amt); amount_t& operator/=(const amount_t& amt); + amount_t& operator+=(const int value) { + return *this += amount_t(value); + } + amount_t& operator-=(const int value) { + return *this -= amount_t(value); + } + amount_t& operator*=(const int value) { + return *this *= amount_t(value); + } + amount_t& operator/=(const int value) { + return *this /= amount_t(value); + } + // simple arithmetic amount_t operator+(const amount_t& amt) const { amount_t temp = *this; @@ -116,6 +126,27 @@ class amount_t return temp; } + amount_t operator+(const int value) const { + amount_t temp = *this; + temp += value; + return temp; + } + amount_t operator-(const int value) const { + amount_t temp = *this; + temp -= value; + return temp; + } + amount_t operator*(const int value) const { + amount_t temp = *this; + temp *= value; + return temp; + } + amount_t operator/(const int value) const { + amount_t temp = *this; + temp /= value; + return temp; + } + // unary negation void negate(); amount_t negated() const { @@ -172,6 +203,7 @@ class amount_t void parse(const std::string& str); void read_quantity(char *& data); + void read_quantity(std::istream& in); void write_quantity(std::ostream& out) const; bool valid() const; @@ -285,14 +317,8 @@ class commodity_t unsigned int _flags = COMMODITY_STYLE_DEFAULTS) : symbol(_symbol), quote(false), precision(_precision), flags(_flags), last_lookup(0) { - DEBUG_PRINT("ledger.memory.ctors", "ctor commodity_t"); check_symbol(); } -#ifdef DEBUG_ENABLED - ~commodity_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor commodity_t"); - } -#endif operator bool() const { return this != null_commodity; @@ -346,7 +372,18 @@ inline commodity_t& amount_t::commodity() const { return *commodity_t::null_commodity; else return *commodity_; - } +} + +class amount_error : public std::exception { + std::string reason; + public: + amount_error(const std::string& _reason) throw() : reason(_reason) {} + virtual ~amount_error() throw() {} + + virtual const char* what() const throw() { + return reason.c_str(); + } +}; } // namespace ledger diff --git a/autoxact.cc b/autoxact.cc index 165ebede..d358daf3 100644 --- a/autoxact.cc +++ b/autoxact.cc @@ -10,7 +10,7 @@ void automated_transaction_t::extend_entry(entry_t * entry) for (transactions_deque::iterator i = initial_xacts.begin(); i != initial_xacts.end(); i++) - if (predicate(*i)) + if (predicate(**i)) for (transactions_deque::iterator t = transactions.begin(); t != transactions.end(); t++) { @@ -1,5 +1,4 @@ #include "balance.h" -#include "ledger.h" #include <deque> @@ -84,40 +83,6 @@ void balance_t::write(std::ostream& out, } } -balance_pair_t::balance_pair_t(const transaction_t& xact) - : quantity(xact.amount), cost(NULL) -{ - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - if (xact.cost) - cost = new balance_t(*xact.cost); -} - -balance_pair_t& balance_pair_t::operator+=(const transaction_t& xact) -{ - if (xact.cost && ! cost) - cost = new balance_t(quantity); - - quantity += xact.amount; - - if (cost) - *cost += xact.cost ? *xact.cost : xact.amount; - - return *this; -} - -balance_pair_t& balance_pair_t::operator-=(const transaction_t& xact) -{ - if (xact.cost && ! cost) - cost = new balance_t(quantity); - - quantity -= xact.amount; - - if (cost) - *cost -= xact.cost ? *xact.cost : xact.amount; - - return *this; -} - } // namespace ledger #ifdef USE_BOOST_PYTHON @@ -169,10 +134,11 @@ void export_balance() .def(! self) .def(abs(self)) - //.def(str(self)) +#if 0 + .def(str(self)) +#endif - .def("negate", &balance_t::negate, - return_value_policy<reference_existing_object>()) + .def("negate", &balance_t::negate) .def("amount", &balance_t::amount) .def("value", &balance_t::value) .def("write", &balance_t::write) @@ -180,6 +146,69 @@ void export_balance() ; class_< balance_pair_t > ("BalancePair") + .def(init<balance_pair_t>()) + .def(init<balance_t>()) + .def(init<amount_t>()) + .def(init<int>()) + .def(init<unsigned int>()) + .def(init<double>()) + + .def(self += self) + .def(self += other<balance_t>()) + .def(self += other<amount_t>()) + .def(self + self) + .def(self + other<balance_t>()) + .def(self + other<amount_t>()) + .def(self -= self) + .def(self -= other<balance_t>()) + .def(self -= other<amount_t>()) + .def(self - self) + .def(self - other<balance_t>()) + .def(self - other<amount_t>()) + .def(self *= self) + .def(self *= other<balance_t>()) + .def(self *= other<amount_t>()) + .def(self * self) + .def(self * other<balance_t>()) + .def(self * other<amount_t>()) + .def(self /= self) + .def(self /= other<balance_t>()) + .def(self /= other<amount_t>()) + .def(self / self) + .def(self / other<balance_t>()) + .def(self / other<amount_t>()) + .def(- self) + + .def(self < self) + .def(self < other<balance_t>()) + .def(self < other<amount_t>()) + .def(self <= self) + .def(self <= other<balance_t>()) + .def(self <= other<amount_t>()) + .def(self > self) + .def(self > other<balance_t>()) + .def(self > other<amount_t>()) + .def(self >= self) + .def(self >= other<balance_t>()) + .def(self >= other<amount_t>()) + .def(self == self) + .def(self == other<balance_t>()) + .def(self == other<amount_t>()) + .def(self != self) + .def(self != other<balance_t>()) + .def(self != other<amount_t>()) + .def(! self) + + .def(abs(self)) +#if 0 + .def(str(self)) +#endif + + .def("negate", &balance_pair_t::negate) + .def("amount", &balance_pair_t::amount) + .def("value", &balance_pair_t::value) + .def("write", &balance_pair_t::write) + .def("valid", &balance_pair_t::valid) ; } @@ -1,13 +1,12 @@ #ifndef _BALANCE_H #define _BALANCE_H +#include "amount.h" + #include <map> #include <ctime> #include <iostream> -#include "amount.h" -#include "error.h" - namespace ledger { typedef std::map<const commodity_t *, amount_t> amounts_map; @@ -28,47 +27,33 @@ class balance_t } // constructors - balance_t() { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); - } + balance_t() {} balance_t(const balance_t& bal) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); for (amounts_map::const_iterator i = bal.amounts.begin(); i != bal.amounts.end(); i++) *this += (*i).second; } balance_t(const amount_t& amt) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); if (amt) amounts.insert(amounts_pair(&amt.commodity(), amt)); } balance_t(const int value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); amount_t amt(value); if (amt) amounts.insert(amounts_pair(&amt.commodity(), amt)); } balance_t(const unsigned int value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); amount_t amt(value); if (amt) amounts.insert(amounts_pair(&amt.commodity(), amt)); } balance_t(const double value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); amount_t amt(value); if (amt) amounts.insert(amounts_pair(&amt.commodity(), amt)); } - // destructor -#ifdef DEBUG_ENABLED - ~balance_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor balance_t"); - } -#endif - // assignment operator balance_t& operator=(const balance_t& bal) { if (this != &bal) { @@ -351,12 +336,11 @@ class balance_t #endif // unary negation - balance_t& negate() { + void negate() { for (amounts_map::iterator i = amounts.begin(); i != amounts.end(); i++) (*i).second.negate(); - return *this; } balance_t negated() const { balance_t temp = *this; @@ -372,7 +356,8 @@ class balance_t if (amounts.size() == 1) return (*amounts.begin()).second; else - throw error("Cannot convert a balance with multiple commodities to an amount"); + throw amount_error("Cannot convert a balance with " + "multiple commodities to an amount"); } operator bool() const { for (amounts_map::const_iterator i = amounts.begin(); @@ -404,60 +389,32 @@ inline balance_t abs(const balance_t& bal) { return temp; } -#ifdef DEBUG_ENABLED -inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) { - bal.write(out, 12); - return out; -} -#endif - -class transaction_t; - class balance_pair_t { public: balance_t quantity; balance_t * cost; - bool valid() const { - return quantity.valid() && (! cost || cost->valid()); - } - // constructors - balance_pair_t() : cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - } + balance_pair_t() : cost(NULL) {} balance_pair_t(const balance_pair_t& bal_pair) : quantity(bal_pair.quantity), cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); if (bal_pair.cost) cost = new balance_t(*bal_pair.cost); } balance_pair_t(const balance_t& _quantity) - : quantity(_quantity), cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - } + : quantity(_quantity), cost(NULL) {} balance_pair_t(const amount_t& _quantity) - : quantity(_quantity), cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - } + : quantity(_quantity), cost(NULL) {} balance_pair_t(const int value) - : quantity(value), cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - } + : quantity(value), cost(NULL) {} balance_pair_t(const unsigned int value) - : quantity(value), cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - } + : quantity(value), cost(NULL) {} balance_pair_t(const double value) - : quantity(value), cost(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); - } - balance_pair_t(const transaction_t& xact); + : quantity(value), cost(NULL) {} // destructor ~balance_pair_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor balance_pair_t"); if (cost) delete cost; } @@ -541,7 +498,6 @@ class balance_pair_t *cost += amt; return *this; } - balance_pair_t& operator+=(const transaction_t& xact); balance_pair_t& operator-=(const balance_pair_t& bal_pair) { if (bal_pair.cost && ! cost) @@ -566,7 +522,6 @@ class balance_pair_t *cost -= amt; return *this; } - balance_pair_t& operator-=(const transaction_t& xact); // simple arithmetic balance_pair_t operator+(const balance_pair_t& bal_pair) const { @@ -741,11 +696,10 @@ class balance_pair_t } // unary negation - balance_pair_t& negate() { + void negate() { quantity.negate(); if (cost) cost->negate(); - return *this; } balance_pair_t negated() const { balance_pair_t temp = *this; @@ -767,7 +721,8 @@ class balance_pair_t if (quantity.amounts.size() == 1) return (*quantity.amounts.begin()).second; else - throw error("Cannot convert a balance pair with multiple commodities to an amount"); + throw amount_error("Cannot convert a balance pair with " + "multiple commodities to an amount"); } void abs() { @@ -775,6 +730,22 @@ class balance_pair_t if (cost) cost->abs(); } + + amount_t amount(const commodity_t& commodity) const { + return quantity.amount(commodity); + } + balance_t value(const std::time_t moment) const { + return quantity.value(moment); + } + void write(std::ostream& out, + const int first_width, + const int latter_width = -1) const { + quantity.write(out, first_width, latter_width); + } + + bool valid() { + return quantity.valid() && (! cost || cost->valid()); + } }; inline balance_pair_t abs(const balance_pair_t& bal_pair) { @@ -8,21 +8,21 @@ namespace ledger { -const unsigned long binary_magic_number = 0xFFEED765; -static const unsigned long format_version = 0x0002001a; +static unsigned long binary_magic_number = 0xFFEED765; +static unsigned long format_version = 0x0002001a; -static account_t ** accounts; -static account_t ** accounts_next; -static unsigned int account_index; +static account_t ** accounts; +static account_t ** accounts_next; +static unsigned int account_index; -static commodity_t ** commodities; -static commodity_t ** commodities_next; -static unsigned int commodity_index; +static commodity_t ** commodities; +static commodity_t ** commodities_next; +static unsigned int commodity_index; -amount_t::bigint_t * bigints; -amount_t::bigint_t * bigints_next; -unsigned int bigints_index; -unsigned int bigints_count; +extern char * bigints; +extern char * bigints_next; +extern unsigned int bigints_index; +extern unsigned int bigints_count; #if DEBUG_LEVEL >= ALPHA #define read_binary_guard(in, id) { \ @@ -342,9 +342,8 @@ unsigned int read_binary_journal(std::istream& in, transaction_t * xact_pool = (transaction_t *) (item_pool + sizeof(entry_t) * count); bigints_index = 0; - bigints = bigints_next - = (amount_t::bigint_t *) (item_pool + sizeof(entry_t) * count + - sizeof(transaction_t) * xact_count); + bigints = bigints_next = (item_pool + sizeof(entry_t) * count + + sizeof(transaction_t) * xact_count); // Read in the commodities @@ -19,11 +19,6 @@ class binary_parser_t : public parser_t const std::string * original_file = NULL); }; -extern amount_t::bigint_t * bigints; -extern amount_t::bigint_t * bigints_next; -extern unsigned int bigints_index; -extern unsigned int bigints_count; - void write_binary_journal(std::ostream& out, journal_t * journal, strings_list * files = NULL); @@ -20,12 +20,6 @@ class error : public std::exception { } }; -class amount_error : public error { - public: - amount_error(const std::string& reason) throw() : error(reason) {} - virtual ~amount_error() throw() {} -}; - class compute_error : public error { public: compute_error(const std::string& reason) throw() : error(reason) {} @@ -33,18 +33,15 @@ std::string partial_account_name(const account_t * account) return name; } -std::string format_t::date_format; -value_expr_t * format_t::value_expr; -value_expr_t * format_t::total_expr; +std::string format_t::date_format = "%Y/%m/%d"; +value_expr_t * format_t::value_expr = NULL; +value_expr_t * format_t::total_expr = NULL; -void initialize_formats() -{ - format_t::date_format = "%Y/%m/%d"; - format_t::value_expr = NULL; - format_t::total_expr = NULL; -} +static struct _init_format { + ~_init_format(); +} _init_obj; -void shutdown_formats() +_init_format::~_init_format() { if (format_t::value_expr) delete format_t::value_expr; @@ -375,7 +372,7 @@ void format_t::format_elements(std::ostream& out, } } -bool format_account::disp_subaccounts_p(const account_t * account, +bool format_account::disp_subaccounts_p(const account_t& account, const item_predicate<account_t>& disp_pred, const account_t *& to_show) @@ -389,13 +386,13 @@ bool format_account::disp_subaccounts_p(const account_t * account, to_show = NULL; - for (accounts_map::const_iterator i = account->accounts.begin(); - i != account->accounts.end(); + for (accounts_map::const_iterator i = account.accounts.begin(); + i != account.accounts.end(); i++) { - if (! disp_pred((*i).second)) + if (! disp_pred(*(*i).second)) continue; - format_t::compute_total(result, details_t((*i).second)); + format_t::compute_total(result, details_t(*(*i).second)); if (! computed) { format_t::compute_total(acct_total, details_t(account)); computed = true; @@ -412,11 +409,11 @@ bool format_account::disp_subaccounts_p(const account_t * account, return display; } -bool format_account::display_account(const account_t * account, +bool format_account::display_account(const account_t& account, const item_predicate<account_t>& disp_pred) { // Never display an account that has already been displayed. - if (account->data && ACCT_DATA(account)->dflags & ACCOUNT_DISPLAYED) + if (account.data && ACCT_DATA_(account)->dflags & ACCOUNT_DISPLAYED) return false; // At this point, one of two possibilities exists: the account is a @@ -105,18 +105,18 @@ class format_transactions : public item_handler<transaction_t> output_stream.flush(); } - virtual void operator()(transaction_t * xact) { - if (! xact->data || - ! (XACT_DATA(xact)->dflags & TRANSACTION_DISPLAYED)) { - if (last_entry != xact->entry) { + virtual void operator()(transaction_t& xact) { + if (! xact.data || + ! (XACT_DATA_(xact)->dflags & TRANSACTION_DISPLAYED)) { + if (last_entry != xact.entry) { first_line_format.format_elements(output_stream, details_t(xact)); - last_entry = xact->entry; + last_entry = xact.entry; } else { next_lines_format.format_elements(output_stream, details_t(xact)); } - if (! xact->data) - xact->data = new transaction_data_t; - XACT_DATA(xact)->dflags |= TRANSACTION_DISPLAYED; + if (! xact.data) + xact.data = new transaction_data_t; + XACT_DATA_(xact)->dflags |= TRANSACTION_DISPLAYED; } } }; @@ -135,32 +135,32 @@ class format_account : public item_handler<account_t> : output_stream(_output_stream), format(_format), disp_pred(display_predicate) {} - static bool disp_subaccounts_p(const account_t * account, + static bool disp_subaccounts_p(const account_t& account, const item_predicate<account_t>& disp_pred, const account_t *& to_show); - static bool disp_subaccounts_p(const account_t * account) { + static bool disp_subaccounts_p(const account_t& account) { const account_t * temp; return disp_subaccounts_p(account, item_predicate<account_t>(NULL), temp); } - static bool display_account(const account_t * account, + static bool display_account(const account_t& account, const item_predicate<account_t>& disp_pred); virtual void flush() { output_stream.flush(); } - virtual void operator()(account_t * account) { + virtual void operator()(account_t& account) { if (display_account(account, disp_pred)) { - if (! account->parent) { - if (! account->data) - account->data = new account_data_t; - ACCT_DATA(account)->dflags |= ACCOUNT_TO_DISPLAY; + if (! account.parent) { + if (! account.data) + account.data = new account_data_t; + ACCT_DATA_(account)->dflags |= ACCOUNT_TO_DISPLAY; } else { format.format_elements(output_stream, details_t(account)); - if (! account->data) - account->data = new account_data_t; - ACCT_DATA(account)->dflags |= ACCOUNT_DISPLAYED; + if (! account.data) + account.data = new account_data_t; + ACCT_DATA_(account)->dflags |= ACCOUNT_DISPLAYED; } } } @@ -188,7 +188,7 @@ class format_equity : public item_handler<account_t> entry_t header_entry; header_entry.payee = "Opening Balances"; header_entry.date = std::time(NULL); - first_line_format.format_elements(output_stream, details_t(&header_entry)); + first_line_format.format_elements(output_stream, details_t(header_entry)); } virtual void flush() { @@ -197,18 +197,18 @@ class format_equity : public item_handler<account_t> summary.data = acct_data.get(); ((account_data_t *) summary.data)->value = total; ((account_data_t *) summary.data)->value.negate(); - next_lines_format.format_elements(output_stream, details_t(&summary)); + next_lines_format.format_elements(output_stream, details_t(summary)); output_stream.flush(); } - virtual void operator()(account_t * account) { + virtual void operator()(account_t& account) { if (format_account::display_account(account, disp_pred)) { next_lines_format.format_elements(output_stream, details_t(account)); - if (! account->data) - account->data = new account_data_t; + if (! account.data) + account.data = new account_data_t; else - total += ACCT_DATA(account)->value; - ACCT_DATA(account)->dflags |= ACCOUNT_DISPLAYED; + total += ACCT_DATA_(account)->value; + ACCT_DATA_(account)->dflags |= ACCOUNT_DISPLAYED; } } }; @@ -418,24 +418,6 @@ bool journal_t::valid() const return true; } -void initialize_amounts(); -void shutdown_amounts(); - -void initialize_formats(); -void shutdown_formats(); - -void initialize() -{ - initialize_amounts(); - initialize_formats(); -} - -void shutdown() -{ - shutdown_amounts(); - shutdown_formats(); -} - } // namespace ledger #ifdef USE_BOOST_PYTHON @@ -16,8 +16,9 @@ #include <ctime> #include <iostream> -#include "debug.h" #include "amount.h" +#include "value.h" +#include "debug.h" namespace ledger { @@ -64,6 +65,61 @@ class transaction_t bool valid() const; }; +inline +balance_pair_t& add_transaction_to(const transaction_t& xact, + balance_pair_t& bal_pair) +{ + if (xact.cost && ! bal_pair.cost) + bal_pair.cost = new balance_t(bal_pair.quantity); + + bal_pair.quantity += xact.amount; + + if (bal_pair.cost) + *bal_pair.cost += xact.cost ? *xact.cost : xact.amount; + + return bal_pair; +} + +inline +value_t& add_transaction_to(const transaction_t& xact, value_t& value) +{ + switch (value.type) { + case value_t::BOOLEAN: + case value_t::INTEGER: + value.cast(value_t::AMOUNT); + + case value_t::AMOUNT: + if (xact.cost) { + value.cast(value_t::BALANCE_PAIR); + return add_transaction_to(xact, value); + } + else if (((amount_t *) value.data)->commodity() != + xact.amount.commodity()) { + value.cast(value_t::BALANCE); + return add_transaction_to(xact, value); + } + *((amount_t *) value.data) += xact.amount; + break; + + case value_t::BALANCE: + if (xact.cost) { + value.cast(value_t::BALANCE_PAIR); + return add_transaction_to(xact, value); + } + *((balance_t *) value.data) += xact.amount; + break; + + case value_t::BALANCE_PAIR: + add_transaction_to(xact, *((balance_pair_t *) value.data)); + break; + + default: + assert(0); + break; + } + + return value; +} typedef std::deque<transaction_t *> transactions_list; @@ -211,9 +267,6 @@ class journal_t extern const std::string version; -void initialize(); -void shutdown(); - } // namespace ledger #endif // _LEDGER_H @@ -335,8 +335,8 @@ int parse_and_report(int argc, char * argv[], char * envp[]) 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_order.get()); + sum_accounts(*journal->master); + walk_accounts(*journal->master, acct_formatter, config.sort_order.get()); acct_formatter.flush(); if (journal->master->data) { @@ -344,15 +344,15 @@ int parse_and_report(int argc, char * argv[], char * envp[]) if (ACCT_DATA(journal->master)->dflags & ACCOUNT_TO_DISPLAY) { out << "--------------------\n"; - config.format.format_elements(out, details_t(journal->master)); + config.format.format_elements(out, details_t(*journal->master)); } } } else if (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_order.get()); + sum_accounts(*journal->master); + walk_accounts(*journal->master, acct_formatter, config.sort_order.get()); acct_formatter.flush(); } @@ -363,7 +363,7 @@ int parse_and_report(int argc, char * argv[], char * envp[]) walk_entries(journal->entries, xact_cleanup); clear_account_data acct_cleanup; - walk_accounts(journal->master, acct_cleanup); + walk_accounts(*journal->master, acct_cleanup); #endif TIMER_STOP(report_gen); @@ -384,25 +384,16 @@ int parse_and_report(int argc, char * argv[], char * envp[]) int main(int argc, char * argv[], char * envp[]) { - int status = 0; - - initialize(); - try { - status = parse_and_report(argc, argv, envp); + return parse_and_report(argc, argv, envp); } catch (error& err) { std::cerr << "Error: " << err.what() << std::endl; - status = 1; + return 1; } catch (int& val) { - status = val; + return val; // this acts like a std::setjmp } - -#if DEBUG_LEVEL >= BETA - shutdown(); -#endif - return status; } // main.cc ends here. @@ -5,12 +5,6 @@ using namespace boost::python; #include "ledger.h" #include "acconf.h" -static struct cleanup_ledger_t { - ~cleanup_ledger_t() { - ledger::shutdown(); - } -} _cleanup_ledger; - void export_amount(); void export_balance(); void export_value(); @@ -37,5 +31,4 @@ BOOST_PYTHON_MODULE(ledger) { export_gnucash(); #endif export_option(); - ledger::initialize(); } @@ -10,6 +10,6 @@ setup(name = "Ledger", url = "http://www.newartisans.com/johnw/", ext_modules = [ Extension("ledger", ["python.cc"], - define_macros = [('PYTHON_MODULE', None)], - libraries = ["ledger_bpy", "boost_python", "gmp", "pcre", - "xmlparse", "xmltok"])]) + define_macros = [('PYTHON_MODULE', None)], + libraries = ["ledger_bpy", "boost_python", "gmp", "pcre", + "xmlparse", "xmltok"])]) @@ -218,9 +218,8 @@ void value_expr_t::compute(value_t& result, const details_t& details) const // jww (2004-08-17): do something smarter here? result.cast(value_t::AMOUNT); } - // jww (2004-08-29): maybe this should be strip_commodity? if (result.type == value_t::AMOUNT) - ((amount_t *) result.data)->set_commodity(*commodity_t::null_commodity); + ((amount_t *) result.data)->clear_commodity(); break; } @@ -29,23 +29,12 @@ struct details_t const transaction_t * xact; const account_t * account; - details_t(const entry_t * _entry) - : entry(_entry), xact(NULL), account(NULL) { - DEBUG_PRINT("ledger.memory.ctors", "ctor details_t"); - } - details_t(const transaction_t * _xact) - : entry(_xact->entry), xact(_xact), account(_xact->account) { - DEBUG_PRINT("ledger.memory.ctors", "ctor details_t"); - } - details_t(const account_t * _account) - : entry(NULL), xact(NULL), account(_account) { - DEBUG_PRINT("ledger.memory.ctors", "ctor details_t"); - } -#ifdef DEBUG_ENABLED - ~details_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor details_t"); - } -#endif + details_t(const entry_t& _entry) + : entry(&_entry), xact(NULL), account(NULL) {} + details_t(const transaction_t& _xact) + : entry(_xact.entry), xact(&_xact), account(_xact.account) {} + details_t(const account_t& _account) + : entry(NULL), xact(NULL), account(&_account) {} }; struct value_expr_t @@ -190,7 +179,7 @@ class item_predicate delete predicate; } - bool operator()(const T * item) const { + bool operator()(const T& item) const { if (predicate) { value_t result; predicate->compute(result, details_t(item)); @@ -1,6 +1,4 @@ #include "value.h" -#include "ledger.h" -#include "error.h" namespace ledger { @@ -171,45 +169,6 @@ DEF_VALUE_OP(-=) DEF_VALUE_OP(*=) DEF_VALUE_OP(/=) -value_t& value_t::operator +=(const transaction_t& xact) -{ - switch (type) { - case BOOLEAN: - case INTEGER: - cast(AMOUNT); - - case AMOUNT: - if (xact.cost) { - cast(BALANCE_PAIR); - return *this += xact; - } - else if (((amount_t *) data)->commodity() != xact.amount.commodity()) { - cast(BALANCE); - return *this += xact; - } - *((amount_t *) data) += xact.amount; - break; - - case BALANCE: - if (xact.cost) { - cast(BALANCE_PAIR); - return *this += xact; - } - *((balance_t *) data) += xact.amount; - break; - - case BALANCE_PAIR: - *((balance_pair_t *) data) += xact; - break; - - default: - assert(0); - break; - } - - return *this; -} - #define DEF_VALUE_CMP_OP(OP) \ bool value_t::operator OP(const value_t& value) \ { \ @@ -435,7 +394,7 @@ void value_t::cast(type_t cast_type) break; } case INTEGER: - throw error("Cannot convert a balance to an integer"); + throw value_error("Cannot convert a balance to an integer"); case AMOUNT: { balance_t * temp = (balance_t *) data; if (temp->amounts.size() == 1) { @@ -443,7 +402,8 @@ void value_t::cast(type_t cast_type) destroy(); new((amount_t *)data) amount_t(amt); } else { - throw error("Cannot convert a balance with multiple commodities to an amount"); + throw value_error("Cannot convert a balance with " + "multiple commodities to an amount"); } break; } @@ -471,7 +431,7 @@ void value_t::cast(type_t cast_type) break; } case INTEGER: - throw error("Cannot convert a balance pair to an integer"); + throw value_error("Cannot convert a balance pair to an integer"); case AMOUNT: { balance_t * temp = &((balance_pair_t *) data)->quantity; @@ -480,7 +440,8 @@ void value_t::cast(type_t cast_type) destroy(); new((amount_t *)data) amount_t(amt); } else { - throw error("Cannot convert a balance pair with multiple commodities to an amount"); + throw value_error("Cannot convert a balance pair with " + "multiple commodities to an amount"); } break; } @@ -592,6 +553,34 @@ using namespace ledger; void export_value() { class_< value_t > ("Value") + .def(init<value_t>()) + .def(init<balance_pair_t>()) + .def(init<balance_t>()) + .def(init<amount_t>()) + .def(init<unsigned int>()) + .def(init<bool>()) + + .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 == self) + .def(self != self) + .def(! self) + +#if 0 + .def(abs(self)) + .def(str(self)) + + .def("cast", &value_t::cast) +#endif + .def("negate", &value_t::negate) + .def("cost", &value_t::cost) ; } @@ -3,7 +3,8 @@ #include "amount.h" #include "balance.h" -#include "debug.h" + +#include <exception> namespace ledger { @@ -16,8 +17,6 @@ namespace ledger { // fact that logic chains only need boolean values to continue, no // memory allocations need to take place at all. -class transaction_t; - class value_t { public: @@ -32,40 +31,32 @@ class value_t } type; value_t() { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *((unsigned int *) data) = 0; type = INTEGER; } value_t(const value_t& value) : type(INTEGER) { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *this = value; } value_t(const bool value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *((bool *) data) = value; type = BOOLEAN; } value_t(const unsigned int value) { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *((unsigned int *) data) = value; type = INTEGER; } value_t(const amount_t& value) : type(INTEGER) { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *this = value; } value_t(const balance_t& value) : type(INTEGER) { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *this = value; } value_t(const balance_pair_t& value) : type(INTEGER) { - DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *this = value; } ~value_t() { - DEBUG_PRINT("ledger.memory.dtors", "dtor value_t"); destroy(); } @@ -130,17 +121,14 @@ class value_t value_t& operator*=(const value_t& value); value_t& operator/=(const value_t& value); - value_t& operator+=(const transaction_t& xact); - - bool operator==(const value_t& value); - bool operator!=(const value_t& value) { - return ! (*this == value); - } - bool operator<(const value_t& value); bool operator<=(const value_t& value); bool operator>(const value_t& value); bool operator>=(const value_t& value); + bool operator==(const value_t& value); + bool operator!=(const value_t& value) { + return ! (*this == value); + } template <typename T> operator T() const; @@ -173,7 +161,18 @@ value_t::operator T() const } assert(0); return 0; - } +} + +class value_error : public std::exception { + std::string reason; + public: + value_error(const std::string& _reason) throw() : reason(_reason) {} + virtual ~value_error() throw() {} + + virtual const char* what() const throw() { + return reason.c_str(); + } +}; } // namespace ledger @@ -11,43 +11,43 @@ void sort_transactions::flush() for (std::deque<transaction_t *>::iterator i = transactions.begin(); i != transactions.end(); i++) - (*handler)(*i); + (*handler)(**i); transactions.clear(); item_handler<transaction_t>::flush(); } -void calc_transactions::operator()(transaction_t * xact) +void calc_transactions::operator()(transaction_t& xact) { - if (! xact->data) - xact->data = new transaction_data_t; + if (! xact.data) + xact.data = new transaction_data_t; if (last_xact && last_xact->data) { - XACT_DATA(xact)->total += XACT_DATA(last_xact)->total; - XACT_DATA(xact)->index = XACT_DATA(last_xact)->index + 1; + XACT_DATA_(xact)->total += XACT_DATA(last_xact)->total; + XACT_DATA_(xact)->index = XACT_DATA(last_xact)->index + 1; } else { - XACT_DATA(xact)->index = 0; + XACT_DATA_(xact)->index = 0; } if (inverted) { - xact->amount.negate(); - if (xact->cost) - xact->cost->negate(); + xact.amount.negate(); + if (xact.cost) + xact.cost->negate(); } - if (! (XACT_DATA(xact)->dflags & TRANSACTION_NO_TOTAL)) - XACT_DATA(xact)->total += *xact; + if (! (XACT_DATA_(xact)->dflags & TRANSACTION_NO_TOTAL)) + add_transaction_to(xact, XACT_DATA_(xact)->total); (*handler)(xact); if (inverted) { - xact->amount.negate(); - if (xact->cost) - xact->cost->negate(); + xact.amount.negate(); + if (xact.cost) + xact.cost->negate(); } - last_xact = xact; + last_xact = &xact; } @@ -65,7 +65,7 @@ static void handle_value(const value_t& value, account_t * account, transaction_t * xact = new transaction_t(account); temps.push_back(xact); - xact->entry = entry; + xact->entry = entry; switch (value.type) { case value_t::BOOLEAN: xact->amount = *((bool *) value.data); @@ -87,7 +87,7 @@ static void handle_value(const value_t& value, account_t * account, XACT_DATA(xact)->dflags |= flags; } - (*handler)(xact); + (*handler)(*xact); break; } @@ -114,7 +114,7 @@ static void handle_value(const value_t& value, account_t * account, XACT_DATA(xact)->dflags |= flags; } - (*handler)(xact); + (*handler)(*xact); } break; @@ -127,7 +127,7 @@ static void handle_value(const value_t& value, account_t * account, void collapse_transactions::report_cumulative_subtotal() { if (count == 1) { - (*handler)(last_xact); + (*handler)(*last_xact); } else { assert(count > 1); @@ -135,7 +135,7 @@ void collapse_transactions::report_cumulative_subtotal() totals_account->data = new account_data_t; ACCT_DATA(totals_account)->total = subtotal; value_t result; - format_t::compute_total(result, details_t(totals_account)); + format_t::compute_total(result, details_t(*totals_account)); handle_value(result, totals_account, last_entry, 0, xact_temps, handler); } @@ -143,44 +143,45 @@ void collapse_transactions::report_cumulative_subtotal() count = 0; } -void changed_value_transactions::operator()(transaction_t * xact) +void changed_value_transactions::output_diff(const std::time_t current) { - if (last_xact) { - value_t prev_bal; - value_t cur_bal; - std::time_t current = xact ? xact->entry->date : std::time(NULL); - std::time_t prev_date = last_xact->entry->date; + value_t prev_bal; + value_t cur_bal; + std::time_t prev_date = last_xact->entry->date; - format_t::compute_total(prev_bal, details_t(last_xact)); + format_t::compute_total(prev_bal, details_t(*last_xact)); - last_xact->entry->date = current; - format_t::compute_total(cur_bal, details_t(last_xact)); - last_xact->entry->date = prev_date; + last_xact->entry->date = current; + format_t::compute_total(cur_bal, details_t(*last_xact)); + last_xact->entry->date = prev_date; - cur_bal -= prev_bal; - if (cur_bal) { - entry_t * entry = new entry_t; - entry_temps.push_back(entry); + cur_bal -= prev_bal; + if (cur_bal) { + entry_t * entry = new entry_t; + entry_temps.push_back(entry); - entry->payee = "Commodities revalued"; - entry->date = current; + entry->payee = "Commodities revalued"; + entry->date = current; - handle_value(cur_bal, NULL, entry, TRANSACTION_NO_TOTAL, xact_temps, - handler); - } + handle_value(cur_bal, NULL, entry, TRANSACTION_NO_TOTAL, xact_temps, + handler); } +} - if (xact) { - if (changed_values_only) { - if (! xact->data) - xact->data = new transaction_data_t; - XACT_DATA(xact)->dflags |= TRANSACTION_DISPLAYED; - } +void changed_value_transactions::operator()(transaction_t& xact) +{ + if (last_xact) + output_diff(xact.entry->date); - (*handler)(xact); + if (changed_values_only) { + if (! xact.data) + xact.data = new transaction_data_t; + XACT_DATA_(xact)->dflags |= TRANSACTION_DISPLAYED; } - last_xact = xact; + (*handler)(xact); + + last_xact = &xact; } void subtotal_transactions::flush(const char * spec_fmt) @@ -218,7 +219,7 @@ void subtotal_transactions::flush(const char * spec_fmt) std::auto_ptr<transaction_data_t> xact_data(new transaction_data_t); temp.data = xact_data.get(); ((transaction_data_t *) temp.data)->total = (*i).second; - format_t::compute_total(result, details_t(&temp)); + format_t::compute_total(result, details_t(temp)); } temp.data = NULL; } @@ -232,28 +233,31 @@ void subtotal_transactions::flush(const char * spec_fmt) item_handler<transaction_t>::flush(); } -void subtotal_transactions::operator()(transaction_t * xact) +void subtotal_transactions::operator()(transaction_t& xact) { if (balances.size() == 0) { - start = finish = xact->entry->date; + start = finish = xact.entry->date; } else { - if (std::difftime(xact->entry->date, start) < 0) - start = xact->entry->date; - if (std::difftime(xact->entry->date, finish) > 0) - finish = xact->entry->date; + if (std::difftime(xact.entry->date, start) < 0) + start = xact.entry->date; + if (std::difftime(xact.entry->date, finish) > 0) + finish = xact.entry->date; } - balances_map::iterator i = balances.find(xact->account); - if (i == balances.end()) - balances.insert(balances_pair(xact->account, *xact)); - else - (*i).second += *xact; + balances_map::iterator i = balances.find(xact.account); + if (i == balances.end()) { + balance_pair_t temp; + add_transaction_to(xact, temp); + balances.insert(balances_pair(xact.account, temp)); + } else { + add_transaction_to(xact, (*i).second); + } } -void interval_transactions::operator()(transaction_t * xact) +void interval_transactions::operator()(transaction_t& xact) { std::time_t quant = interval.increment(begin); - if (std::difftime(xact->entry->date, quant) > 0) { + if (std::difftime(xact.entry->date, quant) > 0) { if (last_xact) { start = begin; finish = quant; @@ -261,7 +265,7 @@ void interval_transactions::operator()(transaction_t * xact) } if (! interval.seconds) { - struct std::tm * desc = std::localtime(&xact->entry->date); + struct std::tm * desc = std::localtime(&xact.entry->date); if (interval.years) desc->tm_mon = 0; desc->tm_mday = 1; @@ -272,7 +276,7 @@ void interval_transactions::operator()(transaction_t * xact) } std::time_t temp; - while (std::difftime(xact->entry->date, + while (std::difftime(xact.entry->date, temp = interval.increment(quant)) > 0) quant = temp; begin = quant; @@ -280,7 +284,7 @@ void interval_transactions::operator()(transaction_t * xact) subtotal_transactions::operator()(xact); - last_xact = xact; + last_xact = &xact; } void dow_transactions::flush() @@ -289,7 +293,7 @@ void dow_transactions::flush() for (std::deque<transaction_t *>::iterator d = days_of_the_week[i].begin(); d != days_of_the_week[i].end(); d++) - subtotal_transactions::operator()(*d); + subtotal_transactions::operator()(**d); subtotal_transactions::flush("%As"); days_of_the_week[i].clear(); } @@ -32,7 +32,7 @@ struct item_handler { if (handler) handler->flush(); } - virtual void operator()(T * item) { + virtual void operator()(T& item) { if (handler) (*handler)(item); } @@ -55,8 +55,8 @@ class compare_items { assert(left); assert(right); - sort_order->compute(left_result, details_t(left)); - sort_order->compute(right_result, details_t(right)); + sort_order->compute(left_result, details_t(*left)); + sort_order->compute(right_result, details_t(*right)); return left_result < right_result; } @@ -71,7 +71,7 @@ inline void walk_transactions(transactions_list::iterator begin, transactions_list::iterator end, item_handler<transaction_t>& handler) { for (transactions_list::iterator i = begin; i != end; i++) - handler(*i); + handler(**i); } inline void walk_transactions(transactions_list& deque, @@ -114,6 +114,7 @@ struct transaction_data_t }; #define XACT_DATA(xact) ((transaction_data_t *) ((xact)->data)) +#define XACT_DATA_(xact) ((transaction_data_t *) ((xact).data)) #define ACCOUNT_DISPLAYED 0x1 #define ACCOUNT_TO_DISPLAY 0x2 @@ -137,22 +138,23 @@ struct account_data_t }; #define ACCT_DATA(acct) ((account_data_t *) ((acct)->data)) +#define ACCT_DATA_(acct) ((account_data_t *) ((acct).data)) ////////////////////////////////////////////////////////////////////// class ignore_transactions : public item_handler<transaction_t> { public: - virtual void operator()(transaction_t * xact) {} + virtual void operator()(transaction_t& xact) {} }; class clear_transaction_data : public item_handler<transaction_t> { public: - virtual void operator()(transaction_t * xact) { - if (xact->data) { - delete (transaction_data_t *) xact->data; - xact->data = NULL; + virtual void operator()(transaction_t& xact) { + if (xact.data) { + delete (transaction_data_t *) xact.data; + xact.data = NULL; } } }; @@ -163,12 +165,12 @@ class set_account_value : public item_handler<transaction_t> set_account_value(item_handler<transaction_t> * handler = NULL) : item_handler<transaction_t>(handler) {} - virtual void operator()(transaction_t * xact) { - if (! ACCT_DATA(xact->account)) - xact->account->data = new account_data_t; + virtual void operator()(transaction_t& xact) { + if (! ACCT_DATA(xact.account)) + xact.account->data = new account_data_t; - ACCT_DATA(xact->account)->value += *xact; - ACCT_DATA(xact->account)->subcount++; + add_transaction_to(xact, ACCT_DATA(xact.account)->value); + ACCT_DATA(xact.account)->subcount++; if (handler) (*handler)(xact); @@ -187,8 +189,8 @@ class sort_transactions : public item_handler<transaction_t> sort_order(_sort_order) {} virtual void flush(); - virtual void operator()(transaction_t * xact) { - transactions.push_back(xact); + virtual void operator()(transaction_t& xact) { + transactions.push_back(&xact); } }; @@ -201,7 +203,7 @@ class filter_transactions : public item_handler<transaction_t> const std::string& predicate) : item_handler<transaction_t>(handler), pred(predicate) {} - virtual void operator()(transaction_t * xact) { + virtual void operator()(transaction_t& xact) { if (pred(xact)) (*handler)(xact); } @@ -218,7 +220,7 @@ class calc_transactions : public item_handler<transaction_t> : item_handler<transaction_t>(handler), last_xact(NULL), inverted(_inverted) {} - virtual void operator()(transaction_t * xact); + virtual void operator()(transaction_t& xact); }; class collapse_transactions : public item_handler<transaction_t> @@ -262,18 +264,18 @@ class collapse_transactions : public item_handler<transaction_t> void report_cumulative_subtotal(); - virtual void operator()(transaction_t * xact) { + virtual void operator()(transaction_t& xact) { // If we've reached a new entry, report on the subtotal // accumulated thus far. - if (last_entry && last_entry != xact->entry) + if (last_entry && last_entry != xact.entry) report_cumulative_subtotal(); - subtotal += *xact; + add_transaction_to(xact, subtotal); count++; - last_entry = xact->entry; - last_xact = xact; + last_entry = xact.entry; + last_xact = &xact; } }; @@ -311,11 +313,14 @@ class changed_value_transactions : public item_handler<transaction_t> } virtual void flush() { - (*this)(NULL); + output_diff(std::time(NULL)); + last_xact = NULL; item_handler<transaction_t>::flush(); } - virtual void operator()(transaction_t * xact); + void output_diff(const std::time_t current); + + virtual void operator()(transaction_t& xact); }; class subtotal_transactions : public item_handler<transaction_t> @@ -356,7 +361,7 @@ class subtotal_transactions : public item_handler<transaction_t> virtual void flush() { flush(NULL); } - virtual void operator()(transaction_t * xact); + virtual void operator()(transaction_t& xact); }; class interval_transactions : public subtotal_transactions @@ -377,7 +382,7 @@ class interval_transactions : public subtotal_transactions finish = interval.increment(begin); } - virtual void operator()(transaction_t * xact); + virtual void operator()(transaction_t& xact); }; class dow_transactions : public subtotal_transactions @@ -389,9 +394,9 @@ class dow_transactions : public subtotal_transactions : subtotal_transactions(handler) {} virtual void flush(); - virtual void operator()(transaction_t * xact) { - struct std::tm * desc = std::localtime(&xact->entry->date); - days_of_the_week[desc->tm_wday].push_back(xact); + virtual void operator()(transaction_t& xact) { + struct std::tm * desc = std::localtime(&xact.entry->date); + days_of_the_week[desc->tm_wday].push_back(&xact); } }; @@ -405,18 +410,18 @@ class related_transactions : public item_handler<transaction_t> : item_handler<transaction_t>(handler), also_matching(_also_matching) {} - virtual void operator()(transaction_t * xact) { - for (transactions_list::iterator i = xact->entry->transactions.begin(); - i != xact->entry->transactions.end(); + virtual void operator()(transaction_t& xact) { + for (transactions_list::iterator i = xact.entry->transactions.begin(); + i != xact.entry->transactions.end(); i++) if ((! (*i)->data || ! (XACT_DATA(*i)->dflags & TRANSACTION_HANDLED)) && - (*i == xact ? also_matching : + (*i == &xact ? also_matching : ! ((*i)->flags & TRANSACTION_AUTO))) { if (! (*i)->data) (*i)->data = new transaction_data_t; XACT_DATA(*i)->dflags |= TRANSACTION_HANDLED; - (*handler)(*i); + (*handler)(**i); } } }; @@ -438,29 +443,29 @@ class clear_account_data : public item_handler<account_t> } }; -inline void sum_accounts(account_t * account) { - if (! account->data) - account->data = new account_data_t; +inline void sum_accounts(account_t& account) { + if (! account.data) + account.data = new account_data_t; - for (accounts_map::iterator i = account->accounts.begin(); - i != account->accounts.end(); + for (accounts_map::iterator i = account.accounts.begin(); + i != account.accounts.end(); i++) { - sum_accounts((*i).second); - ACCT_DATA(account)->total += ACCT_DATA((*i).second)->total; - ACCT_DATA(account)->count += (ACCT_DATA((*i).second)->count + + sum_accounts(*(*i).second); + ACCT_DATA_(account)->total += ACCT_DATA((*i).second)->total; + ACCT_DATA_(account)->count += (ACCT_DATA((*i).second)->count + ACCT_DATA((*i).second)->subcount); } - ACCT_DATA(account)->total += ACCT_DATA(account)->value; - ACCT_DATA(account)->count += ACCT_DATA(account)->subcount; + ACCT_DATA_(account)->total += ACCT_DATA_(account)->value; + ACCT_DATA_(account)->count += ACCT_DATA_(account)->subcount; } typedef std::deque<account_t *> accounts_list; -inline void sort_accounts(account_t * account, +inline void sort_accounts(account_t& account, const value_expr_t * sort_order, - accounts_list& accounts) { - for (accounts_map::iterator i = account->accounts.begin(); - i != account->accounts.end(); + accounts_list& accounts) { + for (accounts_map::iterator i = account.accounts.begin(); + i != account.accounts.end(); i++) accounts.push_back((*i).second); @@ -468,7 +473,7 @@ inline void sort_accounts(account_t * account, compare_items<account_t>(sort_order)); } -inline void walk_accounts(account_t * account, +inline void walk_accounts(account_t& account, item_handler<account_t>& handler, const value_expr_t * sort_order = NULL) { handler(account); @@ -479,12 +484,12 @@ inline void walk_accounts(account_t * account, for (accounts_list::const_iterator i = accounts.begin(); i != accounts.end(); i++) - walk_accounts(*i, handler, sort_order); + walk_accounts(**i, handler, sort_order); } else { - for (accounts_map::const_iterator i = account->accounts.begin(); - i != account->accounts.end(); + for (accounts_map::const_iterator i = account.accounts.begin(); + i != account.accounts.end(); i++) - walk_accounts((*i).second, handler); + walk_accounts(*(*i).second, handler); } } |