--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;
|
||||
}
|
||||
|
||||
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&>
|
||||
commodity_t::base_t::varied_history_t::
|
||||
history(const optional<commodity_t&>& commodity)
|
||||
|
|
@ -400,22 +377,6 @@ optional<commodity_t::base_t::history_t&>
|
|||
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,
|
||||
const amount_t& per_unit_cost,
|
||||
const datetime_t& moment)
|
||||
|
|
|
|||
|
|
@ -124,22 +124,11 @@ public:
|
|||
const optional<datetime_t>& oldest = none
|
||||
#if defined(DEBUG_ON)
|
||||
, 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
|
||||
) const;
|
||||
|
||||
optional<history_t&>
|
||||
history(const optional<commodity_t&>& commodity = none);
|
||||
optional<history_t&>
|
||||
history(const std::vector<commodity_t *>& commodities);
|
||||
};
|
||||
|
||||
#define COMMODITY_STYLE_DEFAULTS 0x000
|
||||
|
|
@ -283,7 +272,6 @@ public:
|
|||
}
|
||||
|
||||
optional<history_t&> history(const optional<commodity_t&>& commodity);
|
||||
optional<history_t&> history(const std::vector<commodity_t *>& commodities);
|
||||
|
||||
public:
|
||||
// These methods provide a transparent pass-through to the underlying
|
||||
|
|
@ -324,23 +312,6 @@ public:
|
|||
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
|
||||
// factored price.
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public:
|
|||
void verify_arguments() const;
|
||||
|
||||
bool has(std::size_t index) const {
|
||||
if (index < args.size())
|
||||
if (index < args.size() && ! args[index].is_null())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ public:
|
|||
if (handled)
|
||||
return value;
|
||||
else
|
||||
return false;
|
||||
return NULL_VALUE;
|
||||
}
|
||||
else {
|
||||
return handled;
|
||||
|
|
|
|||
|
|
@ -124,22 +124,34 @@ value_t report_t::fn_market_value(call_scope_t& scope)
|
|||
{
|
||||
interactive_t args(scope, "a&ts");
|
||||
|
||||
commodity_t * commodity = NULL;
|
||||
if (args.has(2))
|
||||
commodity = amount_t::current_pool->find_or_create(args.get<string>(2));
|
||||
if (args.has(2)) {
|
||||
scoped_array<char> buf(new char[args.get<string>(2).length() + 1]);
|
||||
std::strcpy(buf.get(), args.get<string>(2).c_str());
|
||||
|
||||
DEBUG("report.market", "getting market value of: " << args.value_at(0));
|
||||
|
||||
value_t result =
|
||||
args.value_at(0).value(! args.has(2),
|
||||
args.has(1) ?
|
||||
args.get<datetime_t>(1) : optional<datetime_t>(),
|
||||
commodity ?
|
||||
optional<commodity_t&>(*commodity) :
|
||||
optional<commodity_t&>());
|
||||
|
||||
DEBUG("report.market", "result is: " << result);
|
||||
return result;
|
||||
bool primary_only = false;
|
||||
for (char * p = std::strtok(buf.get(), ",");
|
||||
p;
|
||||
p = std::strtok(NULL, ",")) {
|
||||
if (commodity_t * commodity = amount_t::current_pool->find(trim_ws(p))) {
|
||||
value_t result =
|
||||
args.value_at(0).value(primary_only, args.has(1) ?
|
||||
args.get<datetime_t>(1) :
|
||||
optional<datetime_t>(), *commodity);
|
||||
if (! result.is_null())
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -411,9 +411,9 @@ public:
|
|||
OPTION_(report_t, market, DO() { // -V
|
||||
parent->HANDLER(revalued).on_only();
|
||||
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_)
|
||||
.set_expr("exchange ? market(total_expr, now, exchange) : market(total_expr)");
|
||||
.set_expr("market(total_expr, now, exchange)");
|
||||
});
|
||||
|
||||
OPTION_(report_t, monthly, DO() { // -M
|
||||
|
|
|
|||
|
|
@ -522,6 +522,14 @@ inline char * skip_ws(char * 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) {
|
||||
for (char * p = buf; *p; p++) {
|
||||
if (! (*p == ' ' || *p == '\t'))
|
||||
|
|
|
|||
|
|
@ -1143,19 +1143,19 @@ value_t value_t::value(const bool primary_only,
|
|||
{
|
||||
switch (type()) {
|
||||
case INTEGER:
|
||||
return *this;
|
||||
return NULL_VALUE;
|
||||
|
||||
case AMOUNT:
|
||||
if (optional<amount_t> val =
|
||||
as_amount().value(primary_only, moment, in_terms_of))
|
||||
return *val;
|
||||
return *this;
|
||||
return NULL_VALUE;
|
||||
|
||||
case BALANCE:
|
||||
if (optional<balance_t> bal =
|
||||
as_balance().value(primary_only, moment, in_terms_of))
|
||||
return *bal;
|
||||
return *this;
|
||||
return NULL_VALUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue