--exchange option now accepts multiple commodities
They must be separated by a comma, and all whitespace is ignored.
This commit is contained in:
parent
f2e4f4c6d1
commit
ea75613760
8 changed files with 42 additions and 90 deletions
|
|
@ -352,29 +352,6 @@ optional<price_point_t>
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<price_point_t>
|
|
||||||
commodity_t::base_t::varied_history_t::
|
|
||||||
find_price(const commodity_t& source,
|
|
||||||
const std::vector<commodity_t *>& commodities,
|
|
||||||
const optional<datetime_t>& moment,
|
|
||||||
const optional<datetime_t>& oldest
|
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
, const int indent
|
|
||||||
#endif
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
foreach (commodity_t * commodity, commodities) {
|
|
||||||
if (optional<price_point_t> point = find_price(source, *commodity,
|
|
||||||
moment, oldest
|
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
, indent
|
|
||||||
#endif
|
|
||||||
))
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<commodity_t::base_t::history_t&>
|
optional<commodity_t::base_t::history_t&>
|
||||||
commodity_t::base_t::varied_history_t::
|
commodity_t::base_t::varied_history_t::
|
||||||
history(const optional<commodity_t&>& commodity)
|
history(const optional<commodity_t&>& commodity)
|
||||||
|
|
@ -400,22 +377,6 @@ optional<commodity_t::base_t::history_t&>
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<commodity_t::history_t&>
|
|
||||||
commodity_t::base_t::varied_history_t::history
|
|
||||||
(const std::vector<commodity_t *>& commodities)
|
|
||||||
{
|
|
||||||
// This function differs from the single commodity case avoid in that
|
|
||||||
// 'commodities' represents a list of preferred valuation commodities.
|
|
||||||
// If no price can be located in terms of the first commodity, then
|
|
||||||
// the second is chosen, etc.
|
|
||||||
|
|
||||||
foreach (commodity_t * commodity, commodities) {
|
|
||||||
if (optional<history_t&> hist = history(*commodity))
|
|
||||||
return hist;
|
|
||||||
}
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
|
|
||||||
void commodity_t::exchange(commodity_t& commodity,
|
void commodity_t::exchange(commodity_t& commodity,
|
||||||
const amount_t& per_unit_cost,
|
const amount_t& per_unit_cost,
|
||||||
const datetime_t& moment)
|
const datetime_t& moment)
|
||||||
|
|
|
||||||
|
|
@ -124,22 +124,11 @@ public:
|
||||||
const optional<datetime_t>& oldest = none
|
const optional<datetime_t>& oldest = none
|
||||||
#if defined(DEBUG_ON)
|
#if defined(DEBUG_ON)
|
||||||
, const int indent = 0
|
, const int indent = 0
|
||||||
#endif
|
|
||||||
) const;
|
|
||||||
optional<price_point_t>
|
|
||||||
find_price(const commodity_t& source,
|
|
||||||
const std::vector<commodity_t *>& commodities,
|
|
||||||
const optional<datetime_t>& moment = none,
|
|
||||||
const optional<datetime_t>& oldest = none
|
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
, const int indent = 0
|
|
||||||
#endif
|
#endif
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
optional<history_t&>
|
optional<history_t&>
|
||||||
history(const optional<commodity_t&>& commodity = none);
|
history(const optional<commodity_t&>& commodity = none);
|
||||||
optional<history_t&>
|
|
||||||
history(const std::vector<commodity_t *>& commodities);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define COMMODITY_STYLE_DEFAULTS 0x000
|
#define COMMODITY_STYLE_DEFAULTS 0x000
|
||||||
|
|
@ -283,7 +272,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<history_t&> history(const optional<commodity_t&>& commodity);
|
optional<history_t&> history(const optional<commodity_t&>& commodity);
|
||||||
optional<history_t&> history(const std::vector<commodity_t *>& commodities);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// These methods provide a transparent pass-through to the underlying
|
// These methods provide a transparent pass-through to the underlying
|
||||||
|
|
@ -324,23 +312,6 @@ public:
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<price_point_t>
|
|
||||||
find_price(const std::vector<commodity_t *>& commodities,
|
|
||||||
const optional<datetime_t>& moment = none,
|
|
||||||
const optional<datetime_t>& oldest = none
|
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
, const int indent = 0
|
|
||||||
#endif
|
|
||||||
) const {
|
|
||||||
if (base->varied_history)
|
|
||||||
return base->varied_history->find_price(*this, commodities, moment, oldest
|
|
||||||
#if defined(DEBUG_ON)
|
|
||||||
, indent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
return none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods to exchange one commodity for another, while recording the
|
// Methods to exchange one commodity for another, while recording the
|
||||||
// factored price.
|
// factored price.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ public:
|
||||||
void verify_arguments() const;
|
void verify_arguments() const;
|
||||||
|
|
||||||
bool has(std::size_t index) const {
|
bool has(std::size_t index) const {
|
||||||
if (index < args.size())
|
if (index < args.size() && ! args[index].is_null())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ public:
|
||||||
if (handled)
|
if (handled)
|
||||||
return value;
|
return value;
|
||||||
else
|
else
|
||||||
return false;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return handled;
|
return handled;
|
||||||
|
|
|
||||||
|
|
@ -124,22 +124,34 @@ value_t report_t::fn_market_value(call_scope_t& scope)
|
||||||
{
|
{
|
||||||
interactive_t args(scope, "a&ts");
|
interactive_t args(scope, "a&ts");
|
||||||
|
|
||||||
commodity_t * commodity = NULL;
|
if (args.has(2)) {
|
||||||
if (args.has(2))
|
scoped_array<char> buf(new char[args.get<string>(2).length() + 1]);
|
||||||
commodity = amount_t::current_pool->find_or_create(args.get<string>(2));
|
std::strcpy(buf.get(), args.get<string>(2).c_str());
|
||||||
|
|
||||||
DEBUG("report.market", "getting market value of: " << args.value_at(0));
|
bool primary_only = false;
|
||||||
|
for (char * p = std::strtok(buf.get(), ",");
|
||||||
value_t result =
|
p;
|
||||||
args.value_at(0).value(! args.has(2),
|
p = std::strtok(NULL, ",")) {
|
||||||
args.has(1) ?
|
if (commodity_t * commodity = amount_t::current_pool->find(trim_ws(p))) {
|
||||||
args.get<datetime_t>(1) : optional<datetime_t>(),
|
value_t result =
|
||||||
commodity ?
|
args.value_at(0).value(primary_only, args.has(1) ?
|
||||||
optional<commodity_t&>(*commodity) :
|
args.get<datetime_t>(1) :
|
||||||
optional<commodity_t&>());
|
optional<datetime_t>(), *commodity);
|
||||||
|
if (! result.is_null())
|
||||||
DEBUG("report.market", "result is: " << result);
|
return result;
|
||||||
return result;
|
}
|
||||||
|
// For subsequent, secondary commodities, don't convert primaries
|
||||||
|
primary_only = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value_t result =
|
||||||
|
args.value_at(0).value(! args.has(2), args.has(1) ?
|
||||||
|
args.get<datetime_t>(1) :
|
||||||
|
optional<datetime_t>());
|
||||||
|
if (! result.is_null())
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return args.value_at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t report_t::fn_strip(call_scope_t& args)
|
value_t report_t::fn_strip(call_scope_t& args)
|
||||||
|
|
|
||||||
|
|
@ -411,9 +411,9 @@ public:
|
||||||
OPTION_(report_t, market, DO() { // -V
|
OPTION_(report_t, market, DO() { // -V
|
||||||
parent->HANDLER(revalued).on_only();
|
parent->HANDLER(revalued).on_only();
|
||||||
parent->HANDLER(display_amount_)
|
parent->HANDLER(display_amount_)
|
||||||
.set_expr("exchange ? market(amount_expr, now, exchange) : market(amount_expr)");
|
.set_expr("market(amount_expr, now, exchange)");
|
||||||
parent->HANDLER(display_total_)
|
parent->HANDLER(display_total_)
|
||||||
.set_expr("exchange ? market(total_expr, now, exchange) : market(total_expr)");
|
.set_expr("market(total_expr, now, exchange)");
|
||||||
});
|
});
|
||||||
|
|
||||||
OPTION_(report_t, monthly, DO() { // -M
|
OPTION_(report_t, monthly, DO() { // -M
|
||||||
|
|
|
||||||
|
|
@ -522,6 +522,14 @@ inline char * skip_ws(char * ptr) {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline char * trim_ws(char * ptr) {
|
||||||
|
std::size_t len = std::strlen(ptr);
|
||||||
|
int i = int(len) - 1;
|
||||||
|
while (i >= 0 && ptr[i] == ' ' || ptr[i] == '\t' || ptr[i] == '\n')
|
||||||
|
ptr[i--] = '\0';
|
||||||
|
return skip_ws(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
inline char * next_element(char * buf, bool variable = false) {
|
inline char * next_element(char * buf, bool variable = false) {
|
||||||
for (char * p = buf; *p; p++) {
|
for (char * p = buf; *p; p++) {
|
||||||
if (! (*p == ' ' || *p == '\t'))
|
if (! (*p == ' ' || *p == '\t'))
|
||||||
|
|
|
||||||
|
|
@ -1143,19 +1143,19 @@ value_t value_t::value(const bool primary_only,
|
||||||
{
|
{
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
return *this;
|
return NULL_VALUE;
|
||||||
|
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
if (optional<amount_t> val =
|
if (optional<amount_t> val =
|
||||||
as_amount().value(primary_only, moment, in_terms_of))
|
as_amount().value(primary_only, moment, in_terms_of))
|
||||||
return *val;
|
return *val;
|
||||||
return *this;
|
return NULL_VALUE;
|
||||||
|
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
if (optional<balance_t> bal =
|
if (optional<balance_t> bal =
|
||||||
as_balance().value(primary_only, moment, in_terms_of))
|
as_balance().value(primary_only, moment, in_terms_of))
|
||||||
return *bal;
|
return *bal;
|
||||||
return *this;
|
return NULL_VALUE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue