diff options
-rw-r--r-- | src/balance.cc | 102 | ||||
-rw-r--r-- | src/balance.h | 8 | ||||
-rw-r--r-- | src/filters.cc | 56 | ||||
-rw-r--r-- | test/baseline/opt-equity.test | 4 |
4 files changed, 121 insertions, 49 deletions
diff --git a/src/balance.cc b/src/balance.cc index 5c57cd99..cd25eede 100644 --- a/src/balance.cc +++ b/src/balance.cc @@ -240,17 +240,8 @@ balance_t::strip_annotations(const keep_details_t& what_to_keep) const return temp; } -void balance_t::print(std::ostream& out, - const int first_width, - const int latter_width, - const uint_least8_t flags) const +void balance_t::map_sorted_amounts(function<void(const amount_t&)> fn) const { - bool first = true; - int lwidth = latter_width; - - if (lwidth == -1) - lwidth = first_width; - typedef std::vector<const amount_t *> amounts_array; amounts_array sorted; @@ -261,30 +252,79 @@ void balance_t::print(std::ostream& out, std::stable_sort(sorted.begin(), sorted.end(), commodity_t::compare_by_commodity()); - foreach (const amount_t * amount, sorted) { - int width; - if (! first) { - out << std::endl; - width = lwidth; - } else { - first = false; - width = first_width; + foreach (const amount_t * amount, sorted) + fn(*amount); +} + +namespace { + struct print_amount_from_balance + { + std::ostream& out; + bool& first; + int fwidth; + int lwidth; + uint_least8_t flags; + + explicit print_amount_from_balance(std::ostream& _out, + bool& _first, + int _fwidth, int _lwidth, + uint_least8_t _flags) + : out(_out), first(_first), fwidth(_fwidth), lwidth(_lwidth), + flags(_flags) { + TRACE_CTOR(print_amount_from_balance, + "ostream&, int, int, uint_least8_t"); + } + print_amount_from_balance(const print_amount_from_balance& other) + : out(other.out), first(other.first), fwidth(other.fwidth), + lwidth(other.lwidth), flags(other.flags) { + TRACE_CTOR(print_amount_from_balance, "copy"); + } + ~print_amount_from_balance() throw() { + TRACE_DTOR(print_amount_from_balance); } - std::ostringstream buf; - amount->print(buf, flags); - justify(out, buf.str(), width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY, - flags & AMOUNT_PRINT_COLORIZE && amount->sign() < 0); - } + void operator()(const amount_t& amount) { + int width; + if (! first) { + out << std::endl; + width = lwidth; + } else { + first = false; + width = fwidth; + } + + std::ostringstream buf; + amount.print(buf, flags); + + justify(out, buf.str(), width, + flags & AMOUNT_PRINT_RIGHT_JUSTIFY, + flags & AMOUNT_PRINT_COLORIZE && amount.sign() < 0); + } - if (first) { - out.width(first_width); - if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY) - out << std::right; - else - out << std::left; - out << 0; - } + void close() { + out.width(fwidth); + if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY) + out << std::right; + else + out << std::left; + out << 0; + } + }; +} + +void balance_t::print(std::ostream& out, + const int first_width, + const int latter_width, + const uint_least8_t flags) const +{ + bool first = true; + print_amount_from_balance + amount_printer(out, first, first_width, + latter_width == 1 ? first_width : latter_width, flags); + map_sorted_amounts(amount_printer); + + if (first) + amount_printer.close(); } void to_xml(std::ostream& out, const balance_t& bal) diff --git a/src/balance.h b/src/balance.h index 11c370bb..704b4072 100644 --- a/src/balance.h +++ b/src/balance.h @@ -507,6 +507,14 @@ public: balance_t strip_annotations(const keep_details_t& what_to_keep) const; /** + * Iteration primitives. `map_sorted_amounts' allows one to visit + * each amount in balance in the proper order for displaying to the + * user. Mostly used by `print' and other routinse where the sort + * order of the amounts' commodities is significant. + */ + void map_sorted_amounts(function<void(const amount_t&)> fn) const; + + /** * Printing methods. A balance may be output to a stream using the * `print' method. There is also a global operator<< defined which * simply calls print for a balance on the given stream. There is diff --git a/src/filters.cc b/src/filters.cc index 32b3ec3a..a665f9e6 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -1030,6 +1030,40 @@ void interval_posts::flush() subtotal_posts::flush(); } +namespace { + struct create_post_from_amount + { + post_handler_ptr handler; + xact_t& xact; + account_t& balance_account; + temporaries_t& temps; + + explicit create_post_from_amount(post_handler_ptr _handler, + xact_t& _xact, + account_t& _balance_account, + temporaries_t& _temps) + : handler(_handler), xact(_xact), + balance_account(_balance_account), temps(_temps) { + TRACE_CTOR(create_post_from_amount, + "post_handler_ptr, xact_t&, account_t&, temporaries_t&"); + } + create_post_from_amount(const create_post_from_amount& other) + : handler(other.handler), xact(other.xact), + balance_account(other.balance_account), temps(other.temps) { + TRACE_CTOR(create_post_from_amount, "copy"); + } + ~create_post_from_amount() throw() { + TRACE_DTOR(create_post_from_amount); + } + + void operator()(const amount_t& amount) { + post_t& balance_post = temps.create_post(xact, &balance_account); + balance_post.amount = - amount; + (*handler)(balance_post); + } + }; +} + void posts_as_equity::report_subtotal() { date_t finish; @@ -1076,28 +1110,18 @@ void posts_as_equity::report_subtotal() } values.clear(); -#if 1 // This last part isn't really needed, since an Equity:Opening // Balances posting with a null amount will automatically balance with // all the other postings generated. But it does make the full // balancing amount clearer to the user. if (! total.is_zero()) { - if (total.is_balance()) { - foreach (const balance_t::amounts_map::value_type& pair, - total.as_balance().amounts) { - if (! pair.second.is_zero()) { - post_t& balance_post = temps.create_post(xact, balance_account); - balance_post.amount = - pair.second; - (*handler)(balance_post); - } - } - } else { - post_t& balance_post = temps.create_post(xact, balance_account); - balance_post.amount = - total.to_amount(); - (*handler)(balance_post); - } + create_post_from_amount post_creator(handler, xact, + *balance_account, temps); + if (total.is_balance()) + total.as_balance_lval().map_sorted_amounts(post_creator); + else + post_creator(total.to_amount()); } -#endif } void by_payee_posts::flush() diff --git a/test/baseline/opt-equity.test b/test/baseline/opt-equity.test index 511333cc..35ea6b1e 100644 --- a/test/baseline/opt-equity.test +++ b/test/baseline/opt-equity.test @@ -41,9 +41,9 @@ test equity --lot-prices Assets:Bank -3.80 GBP Assets:Broker 2 AAA {0.90 GBP} Assets:Broker 2 AAA {1.00 GBP} - Equity:Opening Balances 3.80 GBP Equity:Opening Balances -2 AAA {0.90 GBP} Equity:Opening Balances -2 AAA {1.00 GBP} + Equity:Opening Balances 3.80 GBP end test test equity --lots @@ -51,8 +51,8 @@ test equity --lots Assets:Bank -3.80 GBP Assets:Broker 2 AAA {0.90 GBP} [2011/03/04] Assets:Broker 2 AAA {1.00 GBP} [2011/03/05] - Equity:Opening Balances 3.80 GBP Equity:Opening Balances -2 AAA {0.90 GBP} [2011/03/04] Equity:Opening Balances -2 AAA {1.00 GBP} [2011/03/05] + Equity:Opening Balances 3.80 GBP end test |