diff options
-rw-r--r-- | account.cc | 3 | ||||
-rw-r--r-- | amount.cc | 43 | ||||
-rw-r--r-- | amount.h | 16 | ||||
-rw-r--r-- | autoxact.h | 8 | ||||
-rw-r--r-- | balance.cc | 2 | ||||
-rw-r--r-- | balance.h | 68 | ||||
-rw-r--r-- | binary.cc | 40 | ||||
-rw-r--r-- | datetime.h | 9 | ||||
-rw-r--r-- | format.cc | 11 | ||||
-rw-r--r-- | format.h | 11 | ||||
-rw-r--r-- | ledger.cc | 2 | ||||
-rw-r--r-- | ledger.h | 22 | ||||
-rw-r--r-- | option.cc | 2 | ||||
-rw-r--r-- | qif.cc | 2 | ||||
-rw-r--r-- | textual.cc | 25 | ||||
-rw-r--r-- | valexpr.cc | 43 | ||||
-rw-r--r-- | valexpr.h | 40 | ||||
-rw-r--r-- | value.cc | 1026 | ||||
-rw-r--r-- | value.h | 35 | ||||
-rw-r--r-- | walk.cc | 17 | ||||
-rw-r--r-- | walk.h | 9 |
21 files changed, 606 insertions, 828 deletions
@@ -5,10 +5,9 @@ namespace ledger { -account_t::ident_t account_t::next_ident; - account_t::~account_t() { + DEBUG_PRINT("ledger.memory.ctors", "dtor account_t"); for (accounts_map::iterator i = accounts.begin(); i != accounts.end(); i++) @@ -10,21 +10,6 @@ namespace ledger { -#ifdef DEBUG_ENABLED -int bigint_ctors = 0; -int bigint_dtors = 0; -#endif - -#ifdef DEBUG_ENABLED -static struct ctor_dtor_info { - ~ctor_dtor_info() { - DEBUG_CLASS("ledger.amount.bigint"); - DEBUG_PRINT_("bigint_t ctor count = " << bigint_ctors); - DEBUG_PRINT_("bigint_t dtor count = " << bigint_dtors); - } -} __info; -#endif - class amount_t::bigint_t { public: mpz_t val; @@ -33,37 +18,21 @@ class amount_t::bigint_t { unsigned int index; bigint_t() : prec(0), ref(1), index(0) { + DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init(val); -#ifdef DEBUG_ENABLED - DEBUG_PRINT("ledger.amount.bigint-show", - "ctor " << this << " " << bigint_ctors); - bigint_ctors++; -#endif } bigint_t(mpz_t _val) : prec(0), ref(1), index(0) { + DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init_set(val, _val); -#ifdef DEBUG_ENABLED - DEBUG_PRINT("ledger.amount.bigint-show", - "ctor " << this << " " << bigint_ctors); - bigint_ctors++; -#endif } bigint_t(const bigint_t& other) : prec(other.prec), ref(1), index(0) { + DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init_set(val, other.val); -#ifdef DEBUG_ENABLED - DEBUG_PRINT("ledger.amount.bigint-show", - "ctor " << this << " " << bigint_ctors); - bigint_ctors++; -#endif } ~bigint_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor amount_t::bigint_t"); assert(ref == 0); -#ifdef DEBUG_ENABLED - DEBUG_PRINT("ledger.amount.bigint-show", - "dtor " << this << " " << bigint_dtors); - bigint_dtors++; -#endif mpz_clear(val); } }; @@ -150,6 +119,7 @@ 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 = new bigint_t(true_value); commodity = commodity_t::null_commodity; @@ -161,6 +131,7 @@ amount_t::amount_t(const bool value) 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); @@ -173,6 +144,7 @@ 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); @@ -185,6 +157,7 @@ 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); @@ -7,6 +7,8 @@ #include <iostream> #include <sstream> +#include "debug.h" + namespace ledger { class commodity_t; @@ -41,18 +43,23 @@ class amount_t // constructors amount_t(commodity_t * _commodity = NULL) - : quantity(NULL), commodity(_commodity) {} + : quantity(NULL), commodity(_commodity) { + DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t"); + } 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); @@ -62,6 +69,7 @@ class amount_t // destructor ~amount_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor amount_t"); if (quantity) _release(); } @@ -253,8 +261,14 @@ 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 void check_symbol() { for (const char * p = symbol.c_str(); *p; p++) @@ -19,6 +19,7 @@ public: automated_transaction_t(const std::string& _predicate, transactions_deque& _transactions) : predicate(_predicate) { + DEBUG_PRINT("ledger.memory.ctors", "ctor automated_transaction_t"); transactions.insert(transactions.begin(), _transactions.begin(), _transactions.end()); // Take over ownership of the pointers @@ -26,6 +27,7 @@ public: } ~automated_transaction_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor automated_transaction_t"); for (transactions_deque::iterator i = transactions.begin(); i != transactions.end(); i++) @@ -43,7 +45,13 @@ class automated_transactions_t public: automated_transactions_deque automated_transactions; +#ifdef DEBUG_ENABLED + automated_transactions_t() { + DEBUG_PRINT("ledger.memory.ctors", "ctor automated_transactions_t"); + } +#endif ~automated_transactions_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor automated_transactions_t"); for (automated_transactions_deque::iterator i = automated_transactions.begin(); i != automated_transactions.end(); @@ -1,3 +1,4 @@ +#include "balance.h" #include "ledger.h" #include <deque> @@ -87,6 +88,7 @@ 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); } @@ -27,28 +27,39 @@ class balance_t } // constructors - balance_t() {} + balance_t() { + DEBUG_PRINT("ledger.memory.ctors", "ctor 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"); *this += amt; } balance_t(const int value) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); *this += amount_t(value); } balance_t(const unsigned int value) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); *this += amount_t(value); } balance_t(const double value) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_t"); *this += amount_t(value); } // destructor - ~balance_t() {} +#ifdef DEBUG_ENABLED + ~balance_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor balance_t"); + } +#endif // assignment operator balance_t& operator=(const balance_t& bal) { @@ -394,34 +405,40 @@ class balance_pair_t } // constructors - balance_pair_t() : cost(NULL) {} + balance_pair_t() : cost(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); + } 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); } -#if 0 - balance_pair_t(const balance_t& _quantity, const balance_t& _cost) - : quantity(_quantity), cost(_cost) {} -#endif balance_pair_t(const balance_t& _quantity) - : quantity(_quantity), cost(NULL) {} -#if 0 - balance_pair_t(const amount_t& _quantity, const amount_t& _cost) - : quantity(_quantity), cost(_cost) {} -#endif + : quantity(_quantity), cost(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); + } balance_pair_t(const amount_t& _quantity) - : quantity(_quantity), cost(NULL) {} + : quantity(_quantity), cost(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); + } balance_pair_t(const int value) - : quantity(value), cost(NULL) {} + : quantity(value), cost(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); + } balance_pair_t(const unsigned int value) - : quantity(value), cost(NULL) {} + : quantity(value), cost(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); + } balance_pair_t(const double value) - : quantity(value), cost(NULL) {} + : quantity(value), cost(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor balance_pair_t"); + } balance_pair_t(const transaction_t& xact); // destructor ~balance_pair_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor balance_pair_t"); if (cost) delete cost; } @@ -723,15 +740,24 @@ class balance_pair_t operator bool() const { return quantity; } + operator balance_t() const { + return quantity; + } + operator amount_t() const { + assert(0); + return quantity.amount(); + } + + void abs() { + quantity.abs(); + if (cost) + cost->abs(); + } }; inline balance_pair_t abs(const balance_pair_t& bal_pair) { balance_pair_t temp; - temp.quantity = abs(bal_pair.quantity); - if (bal_pair.cost) { - temp.cost = new balance_t; - *temp.cost = abs(*bal_pair.cost); - } + temp.abs(); return temp; } @@ -9,7 +9,7 @@ namespace ledger { const unsigned long binary_magic_number = 0xFFEED765; -static const unsigned long format_version = 0x00020010; +static const unsigned long format_version = 0x00020011; bool binary_parser_t::test(std::istream& in) const { @@ -21,9 +21,9 @@ bool binary_parser_t::test(std::istream& in) const } static std::deque<account_t *> accounts; -static account_t::ident_t ident; +static unsigned int account_index; static std::deque<commodity_t *> commodities; -static commodity_t::ident_t c_ident; +static unsigned int commodity_index; std::deque<amount_t::bigint_t *> bigints; #if DEBUG_LEVEL >= ALPHA @@ -84,12 +84,12 @@ inline std::string read_binary_string(std::istream& in) void read_binary_amount(std::istream& in, amount_t& amt) { - commodity_t::ident_t id; - read_binary_number(in, id); - if (id == 0xffffffff) + commodity_t::ident_t ident; + read_binary_number(in, ident); + if (ident == 0xffffffff) amt.commodity = NULL; else - amt.commodity = commodities[id]; + amt.commodity = commodities[ident - 1]; amt.read_quantity(in); } @@ -98,7 +98,7 @@ transaction_t * read_binary_transaction(std::istream& in, entry_t * entry) { transaction_t * xact = new transaction_t(NULL); - xact->account = accounts[read_binary_number<account_t::ident_t>(in)]; + xact->account = accounts[read_binary_number<account_t::ident_t>(in) - 1]; xact->account->add_transaction(xact); read_binary_amount(in, xact->amount); @@ -137,7 +137,7 @@ commodity_t * read_binary_commodity(std::istream& in) commodities.push_back(commodity); commodity->ident = read_binary_number<commodity_t::ident_t>(in); - assert(commodity->ident == commodities.size() - 1); + assert(commodity->ident == commodities.size()); read_binary_string(in, commodity->symbol); read_binary_string(in, commodity->name); @@ -154,8 +154,8 @@ commodity_t * read_binary_commodity(std::istream& in) read_binary_amount(in, amt); commodity->history.insert(history_pair(when, amt)); } - read_binary_number(in, commodity->last_lookup); + read_binary_number(in, commodity->last_lookup); read_binary_amount(in, commodity->conversion); return commodity; @@ -167,14 +167,14 @@ account_t * read_binary_account(std::istream& in, account_t * master = NULL) accounts.push_back(acct); acct->ident = read_binary_number<account_t::ident_t>(in); - assert(acct->ident == accounts.size() - 1); + assert(acct->ident == accounts.size()); account_t::ident_t id; read_binary_number(in, id); // parent id if (id == 0xffffffff) acct->parent = NULL; else - acct->parent = accounts[id]; + acct->parent = accounts[id - 1]; read_binary_string(in, acct->name); read_binary_string(in, acct->note); @@ -206,8 +206,8 @@ unsigned int read_binary_journal(std::istream& in, journal_t * journal, account_t * master) { - ident = 0; - c_ident = 0; + account_index = + commodity_index = 0; if (read_binary_number<unsigned long>(in) != binary_magic_number || read_binary_number<unsigned long>(in) != format_version) @@ -343,10 +343,9 @@ void write_binary_entry(std::ostream& out, entry_t * entry) void write_binary_commodity(std::ostream& out, commodity_t * commodity) { - write_binary_number(out, c_ident); - commodity->ident = c_ident; - ++c_ident; + commodity->ident = ++commodity_index; + write_binary_number(out, commodity->ident); write_binary_string(out, commodity->symbol); write_binary_string(out, commodity->name); write_binary_string(out, commodity->note); @@ -360,17 +359,16 @@ void write_binary_commodity(std::ostream& out, commodity_t * commodity) write_binary_number(out, (*i).first); write_binary_amount(out, (*i).second); } - write_binary_number(out, commodity->last_lookup); + write_binary_number(out, commodity->last_lookup); write_binary_amount(out, commodity->conversion); } void write_binary_account(std::ostream& out, account_t * account) { - write_binary_number(out, ident); - account->ident = ident; - ++ident; + account->ident = ++account_index; + write_binary_number(out, account->ident); if (account->parent) write_binary_number(out, account->parent->ident); else @@ -14,7 +14,14 @@ struct interval_t int seconds; interval_t(int _seconds = 0, int _months = 0, int _years = 0) - : years(_years), months(_months), seconds(_seconds) {} + : years(_years), months(_months), seconds(_seconds) { + DEBUG_PRINT("ledger.memory.ctors", "ctor interval_t"); + } +#ifdef DEBUG_ENABLED + ~interval_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor interval_t"); + } +#endif operator bool() const { return seconds > 0 || months > 0 || years > 0; @@ -216,6 +216,11 @@ void format_t::format_elements(std::ostream& out, (elem->max_width > 0 ? elem->max_width : elem->min_width)); break; + case value_t::BALANCE_PAIR: + ((balance_pair_t *) value.data)->quantity.write(out, elem->min_width, + (elem->max_width > 0 ? + elem->max_width : elem->min_width)); + break; default: assert(0); break; @@ -353,9 +358,9 @@ bool format_account::disp_subaccounts_p(const account_t * account, { bool display = false; unsigned int counted = 0; - bool computed = false; bool matches = disp_pred(account); - balance_t acct_total; + value_t acct_total; + bool computed = false; to_show = NULL; @@ -365,7 +370,7 @@ bool format_account::disp_subaccounts_p(const account_t * account, if (! disp_pred((*i).second)) continue; - balance_t result; + value_t result; format_t::compute_total(result, details_t((*i).second)); if (! computed) { @@ -79,7 +79,7 @@ struct format_t void format_elements(std::ostream& out, const details_t& details) const; - static void compute_value(balance_t& result, const details_t& details) { + static void compute_value(value_t& result, const details_t& details) { #ifdef NO_CLEANUP if (value_expr) #else @@ -88,7 +88,7 @@ struct format_t value_expr->compute(result, details); } - static void compute_total(balance_t& result, const details_t& details) { + static void compute_total(value_t& result, const details_t& details) { #ifdef NO_CLEANUP if (total_expr) #else @@ -179,7 +179,7 @@ class format_equity : public item_handler<account_t> item_predicate<account_t> disp_pred; - mutable balance_t total; + mutable value_t total; public: format_equity(std::ostream& _output_stream, @@ -198,7 +198,8 @@ class format_equity : public item_handler<account_t> virtual void flush() { account_t summary(NULL, "Equity:Opening Balances"); - summary.value = - total; + summary.value = total; + summary.value.negate(); next_lines_format.format_elements(output_stream, details_t(&summary)); output_stream.flush(); } @@ -207,7 +208,7 @@ class format_equity : public item_handler<account_t> if (format_account::display_account(account, disp_pred)) { next_lines_format.format_elements(output_stream, details_t(account)); account->dflags |= ACCOUNT_DISPLAYED; - total += account->value.quantity; + total += account->value; } } }; @@ -10,6 +10,8 @@ const std::string version = "2.0b"; journal_t::~journal_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor journal_t"); + delete master; // Don't bother unhooking each entry's transactions from the @@ -25,7 +25,7 @@ #endif #include "amount.h" -#include "balance.h" +#include "value.h" namespace ledger { @@ -53,7 +53,7 @@ class transaction_t unsigned short flags; std::string note; - mutable balance_pair_t total; + mutable value_t total; mutable unsigned int index; mutable unsigned short dflags; @@ -69,6 +69,7 @@ class transaction_t cost(NULL), flags(_flags), note(_note), index(0), dflags(0) {} ~transaction_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor transaction_t"); if (cost) delete cost; } @@ -90,9 +91,12 @@ class entry_t std::string payee; transactions_list transactions; - entry_t() : date(-1), state(UNCLEARED) {} + entry_t() : date(-1), state(UNCLEARED) { + DEBUG_PRINT("ledger.memory.ctors", "ctor entry_t"); + } ~entry_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor entry_t"); for (transactions_list::iterator i = transactions.begin(); i != transactions.end(); i++) @@ -128,8 +132,8 @@ class account_t accounts_map accounts; transactions_list transactions; - mutable balance_pair_t value; - mutable balance_pair_t total; + mutable value_t value; + mutable value_t total; mutable unsigned int count; // transactions counted toward total mutable unsigned int subcount; mutable ident_t ident; @@ -143,14 +147,15 @@ class account_t const std::string& _note = "") : parent(_parent), name(_name), note(_note), depth(parent ? parent->depth + 1 : 0), - count(0), subcount(0), dflags(0) {} + subcount(0), ident(0), dflags(0) { + DEBUG_PRINT("ledger.memory.ctors", "ctor account_t"); + } ~account_t(); std::string fullname() const; void add_account(account_t * acct) { - acct->ident = next_ident++; accounts.insert(accounts_pair(acct->name, acct)); } bool remove_account(account_t * acct) { @@ -193,9 +198,8 @@ class journal_t mutable accounts_map accounts_cache; journal_t() { + DEBUG_PRINT("ledger.memory.ctors", "ctor journal_t"); master = new account_t(NULL, ""); - master->ident = 0; - account_t::next_ident = 1; } ~journal_t(); @@ -9,6 +9,8 @@ option_handler::option_handler(const std::string& label, const std::string& opt_chars) : handled(false) { + DEBUG_PRINT("ledger.memory.ctors", "ctor option_handler"); + option_t opt; static char buf[128]; @@ -43,7 +43,7 @@ unsigned int qif_parser_t::parse(std::istream& in, std::auto_ptr<entry_t> entry; std::auto_ptr<amount_t> amount; transaction_t * xact; - unsigned int count; + unsigned int count = 0; account_t * misc = NULL; commodity_t * def_commodity = NULL; @@ -146,7 +146,7 @@ bool finalize_entry(entry_t * entry) // is used for auto-calculating the value of entries with no cost, // and the per-unit price of unpriced commodities. - balance_t balance; + value_t balance; for (transactions_list::const_iterator x = entry->transactions.begin(); x != entry->transactions.end(); @@ -155,7 +155,9 @@ bool finalize_entry(entry_t * entry) ((*x)->flags & TRANSACTION_BALANCE)) { DEBUG_PRINT("ledger.textual.finalize", "item cost is " << ((*x)->cost ? *(*x)->cost : (*x)->amount)); - balance += (*x)->cost ? *(*x)->cost : (*x)->amount; + amount_t * p = (*x)->cost ? (*x)->cost : &(*x)->amount; + if (*p) + balance += *p; } // If one transaction of a two-line transaction is of a different @@ -163,15 +165,17 @@ bool finalize_entry(entry_t * entry) // determine its price by dividing the unit count into the value of // the balance. This is done for the last eligible commodity. - if (balance.amounts.size() == 2) + if (balance.type == value_t::BALANCE && + ((balance_t *) balance.data)->amounts.size() == 2) for (transactions_list::const_iterator x = entry->transactions.begin(); x != entry->transactions.end(); x++) { if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL)) continue; - for (amounts_map::const_iterator i = balance.amounts.begin(); - i != balance.amounts.end(); + for (amounts_map::const_iterator i + = ((balance_t *) balance.data)->amounts.begin(); + i != ((balance_t *) balance.data)->amounts.end(); i++) if ((*i).second.commodity != (*x)->amount.commodity) { assert((*x)->amount); @@ -196,8 +200,7 @@ bool finalize_entry(entry_t * entry) if ((*x)->amount || ((*x)->flags & TRANSACTION_VIRTUAL)) continue; - if (! empty_allowed || balance.amounts.empty() || - balance.amounts.size() != 1) + if (! empty_allowed || ! balance || balance.type != value_t::AMOUNT) return false; empty_allowed = false; @@ -206,13 +209,15 @@ bool finalize_entry(entry_t * entry) // rest are of the same commodity -- then its value is the // inverse of the computed value of the others. - amounts_map::const_iterator i = balance.amounts.begin(); - (*x)->amount = - balance.amount((*i).first); + (*x)->amount = *((amount_t *) balance.data); + (*x)->amount.negate(); - balance = 0; + balance = 0U; } +#if 0 DEBUG_PRINT("ledger.textual.finalize", "balance is " << balance); +#endif return ! balance; } @@ -13,6 +13,8 @@ namespace ledger { mask_t::mask_t(const std::string& pat) : exclude(false) { + DEBUG_PRINT("ledger.memory.ctors", "ctor mask_t"); + const char * p = pat.c_str(); if (*p == '-') { exclude = true; @@ -40,6 +42,8 @@ mask_t::mask_t(const std::string& pat) : exclude(false) mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern) { + DEBUG_PRINT("ledger.memory.ctors", "ctor mask_t"); + const char *error; int erroffset; regexp = pcre_compile(pattern.c_str(), PCRE_CASELESS, @@ -47,6 +51,11 @@ mask_t::mask_t(const mask_t& m) : exclude(m.exclude), pattern(m.pattern) assert(regexp); } +mask_t::~mask_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor mask_t"); + pcre_free((pcre *)regexp); +} + bool mask_t::match(const std::string& str) const { static int ovec[30]; @@ -55,10 +64,6 @@ bool mask_t::match(const std::string& str) const return result >= 0 && ! exclude; } -mask_t::~mask_t() { - pcre_free((pcre *)regexp); -} - void value_expr_t::compute(value_t& result, const details_t& details, value_t::type_t type) const @@ -79,7 +84,7 @@ void value_expr_t::compute(value_t& result, const details_t& details, if (details.xact) result = details.xact->amount; else if (details.account) - result = details.account->value.quantity; + result = details.account->value; break; case COST: @@ -90,32 +95,21 @@ void value_expr_t::compute(value_t& result, const details_t& details, result = details.xact->amount; } else if (details.account) { - if (details.account->value.cost) - result = *details.account->value.cost; - else - result = details.account->value.quantity; + result = details.account->value.cost(); } break; case TOTAL: if (details.xact) - result = details.xact->total.quantity; + result = details.xact->total; else if (details.account) - result = details.account->total.quantity; + result = details.account->total; break; case COST_TOTAL: - if (details.xact) { - if (details.xact->total.cost) - result = *details.xact->total.cost; - else - result = details.xact->total.quantity; - } - else if (details.account) { - if (details.account->total.cost) - result = *details.account->total.cost; - else - result = details.account->total.quantity; - } + if (details.xact) + result = details.xact->total.cost(); + else if (details.account) + result = details.account->total.cost(); break; case VALUE_EXPR: @@ -227,7 +221,8 @@ void value_expr_t::compute(value_t& result, const details_t& details, case F_STRIP: { assert(left); left->compute(result, details); - if (result.type == value_t::BALANCE) { + if (result.type == value_t::BALANCE || + result.type == value_t::BALANCE_PAIR) { // jww (2004-08-17): do something smarter here? result.cast(value_t::AMOUNT); } @@ -16,12 +16,12 @@ class mask_t explicit mask_t(const std::string& pattern); mask_t(const mask_t&); - ~mask_t(); bool match(const std::string& str) const; }; +////////////////////////////////////////////////////////////////////// struct details_t { @@ -30,13 +30,22 @@ struct details_t const account_t * account; details_t(const entry_t * _entry) - : entry(_entry), xact(NULL), account(NULL) {} - + : 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) {} - + : 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) {} + : 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 }; struct value_expr_t @@ -106,9 +115,12 @@ struct value_expr_t mask_t * mask; value_expr_t(const kind_t _kind) - : kind(_kind), left(NULL), right(NULL), mask(NULL) {} + : kind(_kind), left(NULL), right(NULL), mask(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor value_expr_t"); + } ~value_expr_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor value_expr_t"); if (mask) delete mask; if (left) delete left; if (right) delete right; @@ -116,12 +128,6 @@ struct value_expr_t void compute(value_t& result, const details_t& details, value_t::type_t type = value_t::ANY) const; - - void compute(balance_t& result, const details_t& details) const { - value_t value; - compute(value, details, value_t::BALANCE); - result = value.operator balance_t(); - } }; value_expr_t * parse_value_expr(std::istream& in); @@ -139,6 +145,8 @@ inline value_expr_t * parse_value_expr(const std::string& str) { void dump_value_expr(std::ostream& out, const value_expr_t * node); #endif +////////////////////////////////////////////////////////////////////// + template <typename T> class item_predicate { @@ -146,6 +154,7 @@ class item_predicate public: item_predicate(const std::string& _predicate) { + DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>"); predicate = NULL; if (! _predicate.empty()) { try { @@ -172,9 +181,12 @@ class item_predicate } } item_predicate(const value_expr_t * _predicate) - : predicate(_predicate) {} + : predicate(_predicate) { + DEBUG_PRINT("ledger.memory.ctors", "ctor item_predicate<T>"); + } ~item_predicate() { + DEBUG_PRINT("ledger.memory.dtors", "dtor item_predicate<T>"); if (predicate) delete predicate; } @@ -1,4 +1,5 @@ #include "value.h" +#include "ledger.h" namespace ledger { @@ -11,733 +12,333 @@ void value_t::destroy() case BALANCE: ((balance_t *)data)->~balance_t(); break; - default: + case BALANCE_PAIR: + ((balance_pair_t *)data)->~balance_pair_t(); break; - } -} - -value_t& value_t::operator+=(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: - case INTEGER: - switch (type) { - case BOOLEAN: - cast(INTEGER); - case INTEGER: - *((unsigned int *) data) += *((unsigned int *) value.data); - break; - - case AMOUNT: - *((amount_t *) data) += *((unsigned int *) value.data); - break; - - case BALANCE: - *((balance_t *) data) += amount_t(*((unsigned int *) value.data)); - break; - - default: - assert(0); - break; - } - break; - - case AMOUNT: - switch (type) { - case BOOLEAN: - case INTEGER: - cast(AMOUNT); - case AMOUNT: - *((amount_t *) data) += *((amount_t *) value.data); - break; - - case BALANCE: - *((balance_t *) data) += *((amount_t *) value.data); - break; - - default: - assert(0); - break; - } - break; - - case BALANCE: - switch (type) { - case BOOLEAN: - case INTEGER: - case AMOUNT: - cast(BALANCE); - case BALANCE: - *((balance_t *) data) += *((balance_t *) value.data); - break; - - default: - assert(0); - break; - } - break; - default: - assert(0); break; } - return *this; } -value_t& value_t::operator-=(const value_t& value) +value_t& value_t::operator=(const value_t& value) { + destroy(); switch (value.type) { case BOOLEAN: - case INTEGER: - switch (type) { - case BOOLEAN: - cast(INTEGER); - case INTEGER: - *((unsigned int *) data) -= *((unsigned int *) value.data); - break; - - case AMOUNT: - *((amount_t *) data) -= *((unsigned int *) value.data); - break; - - case BALANCE: - *((balance_t *) data) -= amount_t(*((unsigned int *) value.data)); - break; - - default: - assert(0); - break; - } + *((bool *) data) = *((bool *) value.data); break; - case AMOUNT: - switch (type) { - case BOOLEAN: - case INTEGER: - cast(AMOUNT); - case AMOUNT: - *((amount_t *) data) -= *((amount_t *) value.data); - break; - - case BALANCE: - *((balance_t *) data) -= *((amount_t *) value.data); - break; - - default: - assert(0); - break; - } - break; - - case BALANCE: - switch (type) { - case BOOLEAN: - case INTEGER: - case AMOUNT: - cast(BALANCE); - case BALANCE: - *((balance_t *) data) -= *((balance_t *) value.data); - break; - - default: - assert(0); - break; - } - break; - - default: - assert(0); - break; - } - return *this; -} - -value_t& value_t::operator*=(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: case INTEGER: - switch (type) { - case BOOLEAN: - cast(INTEGER); - case INTEGER: - *((unsigned int *) data) *= *((unsigned int *) value.data); - break; - - case AMOUNT: - *((amount_t *) data) *= *((unsigned int *) value.data); - break; - - case BALANCE: - *((balance_t *) data) *= amount_t(*((unsigned int *) value.data)); - break; - - default: - assert(0); - break; - } + *((unsigned int *) data) = *((unsigned int *) value.data); break; case AMOUNT: - switch (type) { - case BOOLEAN: - case INTEGER: - cast(AMOUNT); - case AMOUNT: - *((amount_t *) data) *= *((amount_t *) value.data); - break; - - case BALANCE: - *((balance_t *) data) *= *((amount_t *) value.data); - break; - - default: - assert(0); - break; - } + new((amount_t *)data) amount_t(*((amount_t *) value.data)); break; case BALANCE: - switch (type) { - case BOOLEAN: - case INTEGER: - case AMOUNT: - cast(BALANCE); - case BALANCE: - *((balance_t *) data) *= *((balance_t *) value.data); - break; - - default: - assert(0); - break; - } - break; - - default: - assert(0); - break; - } - return *this; -} - -value_t& value_t::operator/=(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: - case INTEGER: - switch (type) { - case BOOLEAN: - cast(INTEGER); - case INTEGER: - *((unsigned int *) data) /= *((unsigned int *) value.data); - break; - - case AMOUNT: - *((amount_t *) data) /= *((unsigned int *) value.data); - break; - - case BALANCE: - *((balance_t *) data) /= amount_t(*((unsigned int *) value.data)); - break; - - default: - assert(0); - break; - } - break; - - case AMOUNT: - switch (type) { - case BOOLEAN: - case INTEGER: - cast(AMOUNT); - case AMOUNT: - *((amount_t *) data) /= *((amount_t *) value.data); - break; - - case BALANCE: - *((balance_t *) data) /= *((amount_t *) value.data); - break; - - default: - assert(0); - break; - } + new((balance_t *)data) balance_t(*((balance_t *) value.data)); break; - case BALANCE: - switch (type) { - case BOOLEAN: - case INTEGER: - case AMOUNT: - cast(BALANCE); - case BALANCE: - *((balance_t *) data) /= *((balance_t *) value.data); - break; - - default: - assert(0); - break; - } + case BALANCE_PAIR: + new((balance_pair_t *)data) balance_pair_t(*((balance_pair_t *) value.data)); break; default: assert(0); break; } - return *this; -} - -bool value_t::operator==(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: - switch (type) { - case BOOLEAN: - return *((bool *) data) == *((bool *) value.data); - - case INTEGER: - return bool(*((unsigned int *) data)) == *((bool *) value.data); - - case AMOUNT: - return bool(*((amount_t *) data)) == *((bool *) value.data); - - case BALANCE: - return bool(*((balance_t *) data)) == *((bool *) value.data); - - default: - assert(0); - break; - } - break; - - case INTEGER: - switch (type) { - case BOOLEAN: - return ((unsigned int) *((bool *) data)) == *((unsigned int *) value.data); - - case INTEGER: - return *((unsigned int *) data) == *((unsigned int *) value.data); - - case AMOUNT: - return ((unsigned int) *((amount_t *) data)) == *((unsigned int *) value.data); - - case BALANCE: - return ((unsigned int) *((balance_t *) data)) == *((unsigned int *) value.data); - - default: - assert(0); - break; - } - break; - - case AMOUNT: - switch (type) { - case BOOLEAN: - return amount_t(*((bool *) data)) == *((amount_t *) value.data); - - case INTEGER: - return amount_t(*((unsigned int *) data)) == *((amount_t *) value.data); - - case AMOUNT: - return *((amount_t *) data) == *((amount_t *) value.data); - - case BALANCE: - return ((balance_t *) data)->amount() == *((amount_t *) value.data); - - default: - assert(0); - break; - } - break; - - case BALANCE: - switch (type) { - case BOOLEAN: - return balance_t(*((bool *) data)) == *((balance_t *) value.data); - - case INTEGER: - return balance_t(*((unsigned int *) data)) == *((balance_t *) value.data); - - case AMOUNT: - return balance_t(*((amount_t *) data)) == *((balance_t *) value.data); - - case BALANCE: - return *((balance_t *) data) == *((balance_t *) value.data); - default: - assert(0); - break; - } - break; + type = value.type; - default: - assert(0); - break; - } return *this; } -bool value_t::operator<(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: - switch (type) { - case BOOLEAN: - return *((bool *) data) < *((bool *) value.data); - - case INTEGER: - return bool(*((unsigned int *) data)) < *((bool *) value.data); - - case AMOUNT: - return bool(*((amount_t *) data)) < *((bool *) value.data); - - case BALANCE: - return bool(*((balance_t *) data)) < *((bool *) value.data); - - default: - assert(0); - break; - } - break; - - case INTEGER: - switch (type) { - case BOOLEAN: - return ((unsigned int) *((bool *) data)) < *((unsigned int *) value.data); - - case INTEGER: - return *((unsigned int *) data) < *((unsigned int *) value.data); - - case AMOUNT: - return *((amount_t *) data) < *((unsigned int *) value.data); - - case BALANCE: - return *((balance_t *) data) < *((unsigned int *) value.data); - - default: - assert(0); - break; - } - break; - - case AMOUNT: - switch (type) { - case BOOLEAN: - return amount_t(*((bool *) data)) < *((amount_t *) value.data); - - case INTEGER: - return amount_t(*((unsigned int *) data)) < *((amount_t *) value.data); - - case AMOUNT: - return *((amount_t *) data) < *((amount_t *) value.data); - - case BALANCE: - return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) < *((amount_t *) value.data); - - default: - assert(0); - break; - } - break; - - case BALANCE: - switch (type) { - case BOOLEAN: - return balance_t(*((bool *) data)) < *((balance_t *) value.data); - - case INTEGER: - return balance_t(*((unsigned int *) data)) < *((balance_t *) value.data); - - case AMOUNT: - return balance_t(*((amount_t *) data)) < *((balance_t *) value.data); - - case BALANCE: - return *((balance_t *) data) < *((balance_t *) value.data); - - default: - assert(0); - break; - } - break; - - default: - assert(0); - break; - } - return *this; +#define DEF_VALUE_OP(OP) \ +value_t& value_t::operator OP(const value_t& value) \ +{ \ + switch (value.type) { \ + case BOOLEAN: \ + case INTEGER: \ + switch (type) { \ + case BOOLEAN: \ + cast(INTEGER); \ + \ + case INTEGER: \ + *((unsigned int *) data) OP *((unsigned int *) value.data); \ + break; \ + \ + case AMOUNT: \ + *((amount_t *) data) OP *((unsigned int *) value.data); \ + break; \ + \ + case BALANCE: \ + *((balance_t *) data) OP amount_t(*((unsigned int *) value.data)); \ + break; \ + \ + case BALANCE_PAIR: \ + *((balance_pair_t *) data) OP amount_t(*((unsigned int *) value.data)); \ + break; \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case AMOUNT: \ + switch (type) { \ + case BOOLEAN: \ + case INTEGER: \ + cast(AMOUNT); \ + \ + case AMOUNT: \ + if (((amount_t *) data)->commodity && \ + ((amount_t *) data)->commodity != \ + ((amount_t *) value.data)->commodity) { \ + cast(BALANCE); \ + return *this OP value; \ + } \ + *((amount_t *) data) OP *((amount_t *) value.data); \ + break; \ + \ + case BALANCE: \ + *((balance_t *) data) OP *((amount_t *) value.data); \ + break; \ + \ + case BALANCE_PAIR: \ + *((balance_pair_t *) data) OP *((amount_t *) value.data); \ + break; \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case BALANCE: \ + switch (type) { \ + case BOOLEAN: \ + case INTEGER: \ + case AMOUNT: \ + cast(BALANCE); \ + \ + case BALANCE: \ + *((balance_t *) data) OP *((balance_t *) value.data); \ + break; \ + \ + case BALANCE_PAIR: \ + *((balance_pair_t *) data) OP *((balance_t *) value.data); \ + break; \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case BALANCE_PAIR: \ + switch (type) { \ + case BOOLEAN: \ + case INTEGER: \ + case AMOUNT: \ + case BALANCE: \ + cast(BALANCE_PAIR); \ + \ + case BALANCE_PAIR: \ + *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ + break; \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + default: \ + assert(0); \ + break; \ + } \ + return *this; \ } -bool value_t::operator<=(const value_t& value) +DEF_VALUE_OP(+=) +DEF_VALUE_OP(-=) +DEF_VALUE_OP(*=) +DEF_VALUE_OP(/=) + +value_t& value_t::operator +=(const transaction_t& xact) { - switch (value.type) { + switch (type) { case BOOLEAN: - switch (type) { - case BOOLEAN: - return *((bool *) data) <= *((bool *) value.data); - - case INTEGER: - return bool(*((unsigned int *) data)) <= *((bool *) value.data); - - case AMOUNT: - return bool(*((amount_t *) data)) <= *((bool *) value.data); - - case BALANCE: - return bool(*((balance_t *) data)) <= *((bool *) value.data); - - default: - assert(0); - break; - } - break; - case INTEGER: - switch (type) { - case BOOLEAN: - return ((unsigned int) *((bool *) data)) <= *((unsigned int *) value.data); - - case INTEGER: - return *((unsigned int *) data) <= *((unsigned int *) value.data); - - case AMOUNT: - return ((unsigned int) *((amount_t *) data)) <= *((unsigned int *) value.data); - - case BALANCE: - return ((unsigned int) *((balance_t *) data)) <= *((unsigned int *) value.data); - - default: - assert(0); - break; - } - break; + cast(AMOUNT); case AMOUNT: - switch (type) { - case BOOLEAN: - return amount_t(*((bool *) data)) <= *((amount_t *) value.data); - - case INTEGER: - return amount_t(*((unsigned int *) data)) <= *((amount_t *) value.data); - - case AMOUNT: - return *((amount_t *) data) <= *((amount_t *) value.data); - - case BALANCE: - return ((balance_t *) data)->amount() <= *((amount_t *) value.data); - - default: - assert(0); - break; - } - break; - - case BALANCE: - switch (type) { - case BOOLEAN: - return balance_t(*((bool *) data)) <= *((balance_t *) value.data); - - case INTEGER: - return balance_t(*((unsigned int *) data)) <= *((balance_t *) value.data); - - case AMOUNT: - return balance_t(*((amount_t *) data)) <= *((balance_t *) value.data); - - case BALANCE: - return *((balance_t *) data) <= *((balance_t *) value.data); - - default: - assert(0); - break; - } - break; - - default: - assert(0); - break; - } - return *this; -} - -bool value_t::operator>(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: - switch (type) { - case BOOLEAN: - return *((bool *) data) > *((bool *) value.data); - - case INTEGER: - return bool(*((unsigned int *) data)) > *((bool *) value.data); - - case AMOUNT: - return bool(*((amount_t *) data)) > *((bool *) value.data); - - case BALANCE: - return bool(*((balance_t *) data)) > *((bool *) value.data); - - default: - assert(0); - break; + if (xact.cost) { + cast(BALANCE_PAIR); + return *this += xact; } - break; - - case INTEGER: - switch (type) { - case BOOLEAN: - return ((unsigned int) *((bool *) data)) > *((unsigned int *) value.data); - - case INTEGER: - return *((unsigned int *) data) > *((unsigned int *) value.data); - - case AMOUNT: - return ((unsigned int) *((amount_t *) data)) > *((unsigned int *) value.data); - - case BALANCE: - return ((unsigned int) *((balance_t *) data)) > *((unsigned int *) value.data); - - default: - assert(0); - break; + else if (((amount_t *) data)->commodity && + ((amount_t *) data)->commodity != xact.amount.commodity) { + cast(BALANCE); + return *this += xact; } + *((amount_t *) data) += xact.amount; break; - case AMOUNT: - switch (type) { - case BOOLEAN: - return amount_t(*((bool *) data)) > *((amount_t *) value.data); - - case INTEGER: - return amount_t(*((unsigned int *) data)) > *((amount_t *) value.data); - - case AMOUNT: - return *((amount_t *) data) > *((amount_t *) value.data); - - case BALANCE: - return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) > *((amount_t *) value.data); - - default: - assert(0); - break; + case BALANCE: + if (xact.cost) { + cast(BALANCE_PAIR); + return *this += xact; } + *((balance_t *) data) += xact.amount; break; - case BALANCE: - switch (type) { - case BOOLEAN: - return balance_t(*((bool *) data)) > *((balance_t *) value.data); - - case INTEGER: - return balance_t(*((unsigned int *) data)) > *((balance_t *) value.data); - - case AMOUNT: - return balance_t(*((amount_t *) data)) > *((balance_t *) value.data); - - case BALANCE: - return *((balance_t *) data) > *((balance_t *) value.data); - - default: - assert(0); - break; - } + case BALANCE_PAIR: + *((balance_pair_t *) data) += xact; break; default: assert(0); break; } + return *this; } -bool value_t::operator>=(const value_t& value) -{ - switch (value.type) { - case BOOLEAN: - switch (type) { - case BOOLEAN: - return *((bool *) data) >= *((bool *) value.data); - - case INTEGER: - return bool(*((unsigned int *) data)) >= *((bool *) value.data); - - case AMOUNT: - return bool(*((amount_t *) data)) >= *((bool *) value.data); - - case BALANCE: - return bool(*((balance_t *) data)) >= *((bool *) value.data); - - default: - assert(0); - break; - } - break; - - case INTEGER: - switch (type) { - case BOOLEAN: - return ((unsigned int) *((bool *) data)) >= *((unsigned int *) value.data); - - case INTEGER: - return *((unsigned int *) data) >= *((unsigned int *) value.data); - - case AMOUNT: - return ((unsigned int) *((amount_t *) data)) >= *((unsigned int *) value.data); - - case BALANCE: - return ((unsigned int) *((balance_t *) data)) >= *((unsigned int *) value.data); - - default: - assert(0); - break; - } - break; - - case AMOUNT: - switch (type) { - case BOOLEAN: - return amount_t(*((bool *) data)) >= *((amount_t *) value.data); - - case INTEGER: - return amount_t(*((unsigned int *) data)) >= *((amount_t *) value.data); - - case AMOUNT: - return *((amount_t *) data) >= *((amount_t *) value.data); - - case BALANCE: - return ((balance_t *) data)->amount() >= *((amount_t *) value.data); - - default: - assert(0); - break; - } - break; - - case BALANCE: - switch (type) { - case BOOLEAN: - return balance_t(*((bool *) data)) >= *((balance_t *) value.data); - - case INTEGER: - return balance_t(*((unsigned int *) data)) >= *((balance_t *) value.data); - - case AMOUNT: - return balance_t(*((amount_t *) data)) >= *((balance_t *) value.data); - - case BALANCE: - return *((balance_t *) data) >= *((balance_t *) value.data); - - default: - assert(0); - break; - } - break; - - default: - assert(0); - break; - } - return *this; +#define DEF_VALUE_CMP_OP(OP) \ +bool value_t::operator OP(const value_t& value) \ +{ \ + switch (value.type) { \ + case BOOLEAN: \ + switch (type) { \ + case BOOLEAN: \ + return *((bool *) data) OP *((bool *) value.data); \ + \ + case INTEGER: \ + return bool(*((unsigned int *) data)) OP *((bool *) value.data); \ + \ + case AMOUNT: \ + return bool(*((amount_t *) data)) OP *((bool *) value.data); \ + \ + case BALANCE: \ + return bool(*((balance_t *) data)) OP *((bool *) value.data); \ + \ + case BALANCE_PAIR: \ + return bool(*((balance_pair_t *) data)) OP *((bool *) value.data); \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case INTEGER: \ + switch (type) { \ + case BOOLEAN: \ + return ((unsigned int) *((bool *) data)) OP *((unsigned int *) value.data); \ + \ + case INTEGER: \ + return *((unsigned int *) data) OP *((unsigned int *) value.data); \ + \ + case AMOUNT: \ + return ((unsigned int) *((amount_t *) data)) OP *((unsigned int *) value.data); \ + \ + case BALANCE: \ + return ((unsigned int) *((balance_t *) data)) OP *((unsigned int *) value.data); \ + \ + case BALANCE_PAIR: \ + return ((unsigned int) *((balance_pair_t *) data)) OP *((unsigned int *) value.data); \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case AMOUNT: \ + switch (type) { \ + case BOOLEAN: \ + return amount_t(*((bool *) data)) OP *((amount_t *) value.data); \ + \ + case INTEGER: \ + return amount_t(*((unsigned int *) data)) OP *((amount_t *) value.data); \ + \ + case AMOUNT: \ + return *((amount_t *) data) OP *((amount_t *) value.data); \ + \ + case BALANCE: \ + return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) OP *((amount_t *) value.data); \ + \ + case BALANCE_PAIR: \ + return ((balance_pair_t *) data)->quantity.amount(((amount_t *) value.data)->commodity) OP *((amount_t *) value.data); \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case BALANCE: \ + switch (type) { \ + case BOOLEAN: \ + return balance_t(*((bool *) data)) OP *((balance_t *) value.data); \ + \ + case INTEGER: \ + return balance_t(*((unsigned int *) data)) OP *((balance_t *) value.data); \ + \ + case AMOUNT: \ + return balance_t(*((amount_t *) data)) OP *((balance_t *) value.data); \ + \ + case BALANCE: \ + return *((balance_t *) data) OP *((balance_t *) value.data); \ + \ + case BALANCE_PAIR: \ + return *((balance_pair_t *) data) OP *((balance_t *) value.data); \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + case BALANCE_PAIR: \ + switch (type) { \ + case BOOLEAN: \ + return balance_pair_t(*((bool *) data)) OP *((balance_pair_t *) value.data); \ + \ + case INTEGER: \ + return balance_pair_t(*((unsigned int *) data)) OP *((balance_pair_t *) value.data); \ + \ + case AMOUNT: \ + return balance_pair_t(*((amount_t *) data)) OP *((balance_pair_t *) value.data); \ + \ + case BALANCE: \ + return balance_pair_t(*((balance_t *) data)) OP *((balance_pair_t *) value.data); \ + \ + case BALANCE_PAIR: \ + return *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ + \ + default: \ + assert(0); \ + break; \ + } \ + break; \ + \ + default: \ + assert(0); \ + break; \ + } \ + return *this; \ } +DEF_VALUE_CMP_OP(==) +DEF_VALUE_CMP_OP(<) +DEF_VALUE_CMP_OP(<=) +DEF_VALUE_CMP_OP(>) +DEF_VALUE_CMP_OP(>=) + void value_t::cast(type_t cast_type) { switch (type) { @@ -754,6 +355,9 @@ void value_t::cast(type_t cast_type) case BALANCE: new((balance_t *)data) balance_t(*((bool *) data)); break; + case BALANCE_PAIR: + new((balance_pair_t *)data) balance_pair_t(*((bool *) data)); + break; default: assert(0); @@ -774,6 +378,9 @@ void value_t::cast(type_t cast_type) case BALANCE: new((balance_t *)data) balance_t(*((unsigned int *) data)); break; + case BALANCE_PAIR: + new((balance_pair_t *)data) balance_pair_t(*((unsigned int *) data)); + break; default: assert(0); @@ -803,6 +410,12 @@ void value_t::cast(type_t cast_type) new((balance_t *)data) balance_t(temp); break; } + case BALANCE_PAIR: { + amount_t temp = *((amount_t *) data); + destroy(); + new((balance_pair_t *)data) balance_pair_t(temp); + break; + } default: assert(0); @@ -832,6 +445,47 @@ void value_t::cast(type_t cast_type) } case BALANCE: break; + case BALANCE_PAIR: { + balance_t temp = *((balance_t *) data); + destroy(); + new((balance_pair_t *)data) balance_pair_t(temp); + break; + } + + default: + assert(0); + break; + } + break; + + case BALANCE_PAIR: + switch (cast_type) { + case BOOLEAN: { + bool temp = *((balance_pair_t *) data); + destroy(); + *((bool *)data) = temp; + break; + } + case INTEGER: { + unsigned int temp = ((balance_pair_t *) data)->quantity.amount(); + destroy(); + *((unsigned int *)data) = temp; + break; + } + case AMOUNT: { + amount_t temp = ((balance_pair_t *) data)->quantity.amount(); + destroy(); + new((amount_t *)data) amount_t(temp); + break; + } + case BALANCE: { + balance_t temp = ((balance_pair_t *) data)->quantity; + destroy(); + new((balance_t *)data) balance_t(temp); + break; + } + case BALANCE_PAIR: + break; default: assert(0); @@ -861,6 +515,9 @@ void value_t::negate() case BALANCE: ((balance_t *) data)->negate(); break; + case BALANCE_PAIR: + ((balance_pair_t *) data)->negate(); + break; default: assert(0); @@ -883,11 +540,38 @@ void value_t::abs() case BALANCE: ((balance_t *) data)->abs(); break; + case BALANCE_PAIR: + ((balance_pair_t *) data)->abs(); + break; + + default: + assert(0); + break; + } +} + +value_t value_t::cost() const +{ + switch (type) { + case BOOLEAN: + case INTEGER: + case AMOUNT: + case BALANCE: + return *this; + + case BALANCE_PAIR: + assert(((balance_pair_t *) data)->cost); + if (((balance_pair_t *) data)->cost) + return *(((balance_pair_t *) data)->cost); + else + return ((balance_pair_t *) data)->quantity; default: assert(0); break; } + assert(0); + return value_t(); } } // namespace ledger @@ -16,49 +16,66 @@ 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 { - value_t(const value_t& copy); - public: - char data[sizeof(balance_t)]; + char data[sizeof(balance_pair_t)]; enum type_t { BOOLEAN, INTEGER, AMOUNT, BALANCE, + BALANCE_PAIR, ANY } type; value_t() { + DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); *((unsigned int *) data) = 0; type = INTEGER; } + value_t(const value_t& value) { + 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) { + DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); new((amount_t *)data) amount_t(value); type = AMOUNT; } value_t(const balance_t& value) { + DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); new((balance_t *)data) balance_t(value); type = BALANCE; } + value_t(const balance_pair_t& value) { + DEBUG_PRINT("ledger.memory.ctors", "ctor value_t"); + new((balance_pair_t *)data) balance_pair_t(value); + type = BALANCE_PAIR; + } ~value_t() { + DEBUG_PRINT("ledger.memory.dtors", "dtor value_t"); destroy(); } void destroy(); + value_t& operator=(const value_t& value); value_t& operator=(const bool value) { destroy(); *((bool *) data) = value; @@ -83,12 +100,20 @@ class value_t type = BALANCE; return *this; } + value_t& operator=(const balance_pair_t& value) { + destroy(); + new((balance_pair_t *)data) balance_pair_t(value); + type = BALANCE_PAIR; + return *this; + } value_t& operator+=(const value_t& value); value_t& operator-=(const value_t& value); 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); @@ -105,6 +130,8 @@ class value_t void cast(type_t cast_type); void negate(); void abs(); + + value_t cost() const; }; template <typename T> @@ -119,6 +146,8 @@ value_t::operator T() const return *((amount_t *) data); case BALANCE: return *((balance_t *) data); + case BALANCE_PAIR: + return *((balance_pair_t *) data); default: assert(0); @@ -55,9 +55,10 @@ void collapse_transactions::report_cumulative_subtotal() assert(count > 1); totals_account->total = subtotal; - balance_t result; + value_t result; format_t::compute_total(result, details_t(totals_account)); +#if 0 for (amounts_map::const_iterator i = result.amounts.begin(); i != result.amounts.end(); i++) { @@ -69,6 +70,7 @@ void collapse_transactions::report_cumulative_subtotal() (*handler)(total_xact); } +#endif } subtotal = 0; @@ -78,8 +80,8 @@ void collapse_transactions::report_cumulative_subtotal() void changed_value_transactions::operator()(transaction_t * xact) { if (last_xact) { - balance_t prev_bal; - balance_t cur_bal; + 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; @@ -89,13 +91,15 @@ void changed_value_transactions::operator()(transaction_t * xact) format_t::compute_total(cur_bal, details_t(last_xact)); last_xact->entry->date = prev_date; - if (balance_t diff = cur_bal - prev_bal) { + 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; +#if 0 for (amounts_map::const_iterator i = diff.amounts.begin(); i != diff.amounts.end(); i++) { @@ -108,6 +112,7 @@ void changed_value_transactions::operator()(transaction_t * xact) (*handler)(temp_xact); } +#endif } } @@ -150,10 +155,11 @@ void subtotal_transactions::flush(const char * spec_fmt) transaction_t temp((*i).first); temp.entry = entry; temp.total = (*i).second; - balance_t result; + value_t result; format_t::compute_total(result, details_t(&temp)); entry->date = start; +#if 0 for (amounts_map::const_iterator j = result.amounts.begin(); j != result.amounts.end(); j++) { @@ -165,6 +171,7 @@ void subtotal_transactions::flush(const char * spec_fmt) (*handler)(xact); } +#endif } balances.clear(); @@ -16,10 +16,15 @@ struct item_handler { item_handler * handler; public: - item_handler() : handler(NULL) {} - item_handler(item_handler * _handler) : handler(_handler) {} + item_handler() : handler(NULL) { + DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>"); + } + item_handler(item_handler * _handler) : handler(_handler) { + DEBUG_PRINT("ledger.memory.ctors", "ctor item_handler<T>"); + } virtual ~item_handler() { + DEBUG_PRINT("ledger.memory.dtors", "dtor item_handler<T>"); if (handler) delete handler; } |