diff options
author | John Wiegley <johnw@newartisans.com> | 2012-03-09 20:02:53 -0600 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2012-03-09 20:02:53 -0600 |
commit | 2df8edc71c1e805fd54c2208b2b66bdde0460c59 (patch) | |
tree | 8a5aefa71d8713c4fe7d91df02f8046d18a9fe8c | |
parent | cbc7bd337bf523e9424c789a87be1d4a360740b2 (diff) | |
download | fork-ledger-2df8edc71c1e805fd54c2208b2b66bdde0460c59.tar.gz fork-ledger-2df8edc71c1e805fd54c2208b2b66bdde0460c59.tar.bz2 fork-ledger-2df8edc71c1e805fd54c2208b2b66bdde0460c59.zip |
Improved the behavior of -X
-rw-r--r-- | src/system.hh.in | 2 | ||||
-rw-r--r-- | src/value.cc | 101 | ||||
-rwxr-xr-x | test/RegressTests.py | 2 | ||||
-rw-r--r-- | test/baseline/opt-exchange.test | 57 | ||||
-rw-r--r-- | test/regress/83B4A0E5.test | 43 |
5 files changed, 192 insertions, 13 deletions
diff --git a/src/system.hh.in b/src/system.hh.in index fcc8e2ce..a38deb1f 100644 --- a/src/system.hh.in +++ b/src/system.hh.in @@ -185,6 +185,8 @@ typedef std::ostream::pos_type ostream_pos_type; #include <boost/regex.hpp> #endif // HAVE_BOOST_REGEX_UNICODE +#include <boost/tokenizer.hpp> + #include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple_comparison.hpp> diff --git a/src/value.cc b/src/value.cc index 6e1ed79d..87b31cd6 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1436,21 +1436,96 @@ value_t value_t::exchange_commodities(const std::string& commodities, const bool add_prices, const optional<datetime_t>& moment) { - scoped_array<char> buf(new char[commodities.length() + 1]); - - std::strcpy(buf.get(), commodities.c_str()); - - for (char * p = std::strtok(buf.get(), ","); - p; - p = std::strtok(NULL, ",")) { - if (commodity_t * commodity = - commodity_pool_t::current_pool->parse_price_expression(p, add_prices, - moment)) { - value_t result = value(moment, *commodity); - if (! result.is_null()) - return result; + if (type() == SEQUENCE) { + value_t temp; + foreach (value_t& value, as_sequence_lval()) + temp.push_back(value.exchange_commodities(commodities, add_prices, moment)); + return temp; + } + + // If we are repricing to just a single commodity, with no price + // expression, skip the expensive logic below. + if (commodities.find(',') == string::npos && + commodities.find('=') == string::npos) + return value(moment, *commodity_pool_t::current_pool->find_or_create(commodities)); + + std::vector<commodity_t *> comms; + std::vector<bool> force; + + typedef tokenizer<char_separator<char> > tokenizer; + tokenizer tokens(commodities, char_separator<char>(",")); + + foreach (const string& name, tokens) { + string::size_type name_len = name.length(); + + if (commodity_t * commodity = commodity_pool_t::current_pool + ->parse_price_expression(name[name_len - 1] == '!' ? + string(name, 0, name_len - 1) : + name, add_prices, moment)) { + DEBUG("commodity.exchange", "Pricing for commodity: " << commodity->symbol()); + comms.push_back(&commodity->referent()); + force.push_back(name[name_len - 1] == '!'); + } + } + + int index = 0; + foreach (commodity_t * comm, comms) { + switch (type()) { + case AMOUNT: + DEBUG("commodity.exchange", "We have an amount: " << as_amount_lval()); + if (! force[index] && + std::find(comms.begin(), comms.end(), + &as_amount_lval().commodity().referent()) != comms.end()) + break; + + DEBUG("commodity.exchange", "Referent doesn't match, pricing..."); + if (optional<amount_t> val = as_amount_lval().value(moment, *comm)) { + DEBUG("commodity.exchange", "Re-priced amount is: " << *val); + return *val; + } + DEBUG("commodity.exchange", "Was unable to find a price"); + break; + + case BALANCE: { + balance_t temp; + bool repriced = false; + + DEBUG("commodity.exchange", "We have a balance: " << as_balance_lval()); + foreach (const balance_t::amounts_map::value_type& pair, + as_balance_lval().amounts) { + DEBUG("commodity.exchange", "We have a balance amount of commodity: " + << pair.first->symbol() << " == " + << pair.second.commodity().symbol()); + if (! force[index] && + std::find(comms.begin(), comms.end(), + &pair.first->referent()) != comms.end()) { + temp += pair.second; + } else { + DEBUG("commodity.exchange", "Referent doesn't match, pricing..."); + if (optional<amount_t> val = pair.second.value(moment, *comm)) { + DEBUG("commodity.exchange", "Re-priced member amount is: " << *val); + temp += *val; + repriced = true; + } else { + DEBUG("commodity.exchange", "Was unable to find price"); + temp += pair.second; + } + } + } + + if (repriced) { + DEBUG("commodity.exchange", "Re-priced balance is: " << temp); + return temp; + } } + + default: + break; + } + + ++index; } + return *this; } diff --git a/test/RegressTests.py b/test/RegressTests.py index da5d92ca..a22e35bf 100755 --- a/test/RegressTests.py +++ b/test/RegressTests.py @@ -149,6 +149,8 @@ class RegressFile(object): harness.success() else: harness.failure(os.path.basename(self.filename)) + print "STDERR:" + print p.stderr.read() else: if success: print if test['exitcode']: diff --git a/test/baseline/opt-exchange.test b/test/baseline/opt-exchange.test index cfc48c3f..f5d73f78 100644 --- a/test/baseline/opt-exchange.test +++ b/test/baseline/opt-exchange.test @@ -53,6 +53,63 @@ test reg --exchange=' C, A ' Assets:Brokerage -75 A 75 A 09-Jan-01 January 1st, 2009 (3) Assets:Brokerage 100 A 175 A Assets:Brokerage -100 A 75 A +09-Jan-02 Commodities revalued <Revalued> 225 A + -1800 C 300 A + -1800 C +09-Jan-02 January 2nd, 2009 Assets:Brokerage 500 C 300 A + -1300 C + Assets:Brokerage -500 C 300 A + -1800 C +09-Jan-03 January 3rd, 2009 Assets:Brokerage 600 C 300 A + -1200 C + Assets:Brokerage -600 C 300 A + -1800 C +09-Jan-04 January 4th, 2009 Assets:Brokerage 300 A 600 A + -1800 C + Assets:Brokerage -2400 C 600 A + -4200 C +09-Jan-05 January 5th, 2009 Assets:Brokerage 1280 C 600 A + -2920 C + Assets:Brokerage -1280 C 600 A + -4200 C +09-Jan-06 Commodities revalued <Revalued> 2040 C 600 A + -2160 C +09-Jan-06 January 6th, 2009 Assets:Brokerage 155 A 755 A + -2160 C + Assets:Brokerage -186 C 755 A + -2346 C +09-Jan-07 Commodities revalued <Revalued> -86 C 755 A + -2432 C +09-Jan-07 January 7th, 2009 Assets:Brokerage 155 A 910 A + -2432 C + Assets:Brokerage -200 C 910 A + -2632 C +09-Jan-08 Commodities revalued <Revalued> -5613 C 910 A + -8245 C +09-Jan-08 January 8th, 2009 Assets:Brokerage 155 A 1065 A + -8245 C + Assets:Brokerage -200 C 1065 A + -8445 C +09-Jan-09 Commodities revalued <Revalued> -2800 C 1065 A + -11245 C +09-Jan-09 January 9th, 2009 Assets:Brokerage 200 C 1065 A + -11045 C + Assets:Brokerage -155 A 910 A + -11045 C +09-Jan-10 January 10th, 2009 Assets:Brokerage 200 C 910 A + -10845 C + Assets:Brokerage -155 A 755 A + -10845 C +end test + + +test reg --exchange=' C!, A ' +09-Jan-01 January 1st, 2009 (1) Assets:Brokerage 100 A 100 A + Assets:Brokerage -50 A 50 A +09-Jan-01 January 1st, 2009 (2) Assets:Brokerage 100 A 150 A + Assets:Brokerage -75 A 75 A +09-Jan-01 January 1st, 2009 (3) Assets:Brokerage 100 A 175 A + Assets:Brokerage -100 A 75 A 09-Jan-02 Commodities revalued <Revalued> 0 600 C 09-Jan-02 January 2nd, 2009 Assets:Brokerage 500 C 1100 C Assets:Brokerage -500 C 600 C diff --git a/test/regress/83B4A0E5.test b/test/regress/83B4A0E5.test new file mode 100644 index 00000000..f9402a2d --- /dev/null +++ b/test/regress/83B4A0E5.test @@ -0,0 +1,43 @@ +P 2012-03-01 EUR $2 +P 2012-03-01 GBP $2 + +2012-03-05 KFC + Expenses:Food 10 EUR + Assets:Cash + +2012-03-10 KFC + Expenses:Food 10 GBP + Assets:Cash + +test reg food +12-Mar-05 KFC Expenses:Food 10 EUR 10 EUR +12-Mar-10 KFC Expenses:Food 10 GBP 10 EUR + 10 GBP +end test + +test reg food -V +12-Mar-05 KFC Expenses:Food $20 $20 +12-Mar-10 KFC Expenses:Food $20 $40 +end test + +test reg food -X '$' +12-Mar-05 KFC Expenses:Food $20 $20 +12-Mar-10 KFC Expenses:Food $20 $40 +end test + +test reg food -X '$,GBP' +12-Mar-05 KFC Expenses:Food $20 $20 +12-Mar-10 KFC Expenses:Food 10 GBP $20 + 10 GBP +end test + +test reg food -X '$!,GBP' +12-Mar-05 KFC Expenses:Food $20 $20 +12-Mar-10 KFC Expenses:Food $20 $40 +end test + +test reg food -X '$,EUR' +12-Mar-05 KFC Expenses:Food 10 EUR 10 EUR +12-Mar-10 KFC Expenses:Food $20 $20 + 10 EUR +end test |