*** empty log message ***

This commit is contained in:
John Wiegley 2006-03-16 11:58:44 +00:00
parent 2964dd15b2
commit b1a04923fe
8 changed files with 196 additions and 218 deletions

267
amount.cc
View file

@ -378,8 +378,11 @@ amount_t& amount_t::operator+=(const amount_t& amt)
_dup(); _dup();
if (commodity_ != amt.commodity_) if (commodity() != amt.commodity())
throw new amount_error("Adding amounts with different commodities"); throw new amount_error
(std::string("Adding amounts with different commodities: ") +
commodity_->qualified_symbol + " != " +
amt.commodity_->qualified_symbol);
if (quantity->prec == amt.quantity->prec) { if (quantity->prec == amt.quantity->prec) {
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
@ -411,8 +414,11 @@ amount_t& amount_t::operator-=(const amount_t& amt)
_dup(); _dup();
if (commodity_ != amt.commodity_) if (commodity() != amt.commodity())
throw new amount_error("Subtracting amounts with different commodities"); throw new amount_error
(std::string("Subtracting amounts with different commodities: ") +
commodity_->qualified_symbol + " != " +
amt.commodity_->qualified_symbol);
if (quantity->prec == amt.quantity->prec) { if (quantity->prec == amt.quantity->prec) {
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
@ -533,10 +539,10 @@ amount_t::operator bool() const
return mpz_sgn(MPZ(quantity)) != 0; return mpz_sgn(MPZ(quantity)) != 0;
} else { } else {
mpz_set(temp, MPZ(quantity)); mpz_set(temp, MPZ(quantity));
if (commodity_) if (quantity->flags & BIGINT_KEEP_PREC)
mpz_ui_pow_ui(divisor, 10, quantity->prec - commodity().precision());
else
mpz_ui_pow_ui(divisor, 10, quantity->prec); mpz_ui_pow_ui(divisor, 10, quantity->prec);
else
mpz_ui_pow_ui(divisor, 10, quantity->prec - commodity().precision());
mpz_tdiv_q(temp, temp, divisor); mpz_tdiv_q(temp, temp, divisor);
bool zero = mpz_sgn(temp) == 0; bool zero = mpz_sgn(temp) == 0;
return ! zero; return ! zero;
@ -600,22 +606,37 @@ amount_t amount_t::value(const std::time_t moment) const
amount_t amount_t::round(unsigned int prec) const amount_t amount_t::round(unsigned int prec) const
{ {
if (! quantity || quantity->prec <= prec)
return *this;
amount_t temp = *this; amount_t temp = *this;
if (! quantity || quantity->prec <= prec) {
if (quantity->flags & BIGINT_KEEP_PREC) {
temp._dup();
temp.quantity->flags &= ~BIGINT_KEEP_PREC;
}
return temp;
}
temp._dup(); temp._dup();
mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), temp.quantity->prec, prec); mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), temp.quantity->prec, prec);
temp.quantity->prec = prec; temp.quantity->prec = prec;
temp.quantity->flags &= ~BIGINT_KEEP_PREC;
return temp; return temp;
} }
amount_t amount_t::unround() const amount_t amount_t::unround() const
{ {
if (! quantity || quantity->flags & BIGINT_KEEP_PREC) if (! quantity) {
amount_t temp(0L);
assert(temp.quantity);
temp.quantity->flags |= BIGINT_KEEP_PREC;
return temp;
}
else if (quantity->flags & BIGINT_KEEP_PREC) {
return *this; return *this;
}
amount_t temp = *this; amount_t temp = *this;
temp._dup(); temp._dup();
@ -731,7 +752,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
last.commodity_ = last.commodity().larger()->commodity_; last.commodity_ = last.commodity().larger()->commodity_;
if (ledger::abs(last) < 1) if (ledger::abs(last) < 1)
break; break;
base = last; base = last.round();
} }
} }
@ -849,8 +870,6 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
} }
if (precision) { if (precision) {
out << ((comm.flags() & COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
std::ostringstream final; std::ostringstream final;
final.width(precision); final.width(precision);
final.fill('0'); final.fill('0');
@ -865,12 +884,18 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
if (q[i - 1] != '0') if (q[i - 1] != '0')
break; break;
std::string ender;
if (i == len) if (i == len)
out << str; ender = str;
else if (i < comm.precision()) else if (i < comm.precision())
out << std::string(str, 0, comm.precision()); ender = std::string(str, 0, comm.precision());
else else
out << std::string(str, 0, i); ender = std::string(str, 0, i);
if (! ender.empty()) {
out << ((comm.flags() & COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
out << ender;
}
} }
if (comm.flags() & COMMODITY_STYLE_SUFFIXED) { if (comm.flags() & COMMODITY_STYLE_SUFFIXED) {
@ -889,6 +914,7 @@ std::ostream& operator<<(std::ostream& _out, const amount_t& amt)
if (comm.annotated) { if (comm.annotated) {
annotated_commodity_t& ann(static_cast<annotated_commodity_t&>(comm)); annotated_commodity_t& ann(static_cast<annotated_commodity_t&>(comm));
assert(&ann.price != &amt);
ann.write_annotations(out); ann.write_annotations(out);
} }
@ -928,18 +954,14 @@ void parse_commodity(std::istream& in, std::string& symbol)
symbol = buf; symbol = buf;
} }
void parse_annotations(std::istream& in, const std::string& symbol, void parse_annotations(std::istream& in, amount_t& price,
std::string& name, std::string& price, std::time_t& date, std::string& tag)
std::string& date, std::string& tag)
{ {
char buf[256];
bool added_name = false;
bool handled = false;
do { do {
char buf[256];
char c = peek_next_nonws(in); char c = peek_next_nonws(in);
if (c == '{') { if (c == '{') {
if (! price.empty()) if (price)
throw new amount_error("Commodity specifies more than one price"); throw new amount_error("Commodity specifies more than one price");
in.get(c); in.get(c);
@ -948,21 +970,12 @@ void parse_annotations(std::istream& in, const std::string& symbol,
in.get(c); in.get(c);
else else
throw new amount_error("Commodity price lacks closing brace"); throw new amount_error("Commodity price lacks closing brace");
price = buf;
if (! added_name) { price.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
added_name = true; price.reduce();
if (commodity_t::needs_quotes(symbol)) {
name = "\"";
name += symbol;
name += "\"";
}
}
name += " {";
name += price;
name += "}";
} }
else if (c == '[') { else if (c == '[') {
if (! date.empty()) if (date)
throw new amount_error("Commodity specifies more than one date"); throw new amount_error("Commodity specifies more than one date");
in.get(c); in.get(c);
@ -971,18 +984,8 @@ void parse_annotations(std::istream& in, const std::string& symbol,
in.get(c); in.get(c);
else else
throw new amount_error("Commodity date lacks closing bracket"); throw new amount_error("Commodity date lacks closing bracket");
date = buf;
if (! added_name) { parse_date(buf, &date);
added_name = true;
if (commodity_t::needs_quotes(symbol)) {
name = "\"";
name += symbol;
name += "\"";
}
}
name += " [";
name += date;
name += "]";
} }
else if (c == '(') { else if (c == '(') {
if (! tag.empty()) if (! tag.empty())
@ -994,27 +997,16 @@ void parse_annotations(std::istream& in, const std::string& symbol,
in.get(c); in.get(c);
else else
throw new amount_error("Commodity tag lacks closing parenthesis"); throw new amount_error("Commodity tag lacks closing parenthesis");
tag = buf; tag = buf;
if (! added_name) {
added_name = true;
if (commodity_t::needs_quotes(symbol)) {
name = "\"";
name += symbol;
name += "\"";
}
}
name += " (";
name += tag;
name += ")";
} }
else { else {
break; break;
} }
} while (true); } while (true);
DEBUG_PRINT("amounts.commodities", "Parsed commodity annotations: " DEBUG_PRINT("amounts.commodities",
<< "name " << name << " " "Parsed commodity annotations: "
<< "symbol " << symbol << std::endl
<< " price " << price << " " << " price " << price << " "
<< " date " << date << " " << " date " << date << " "
<< " tag " << tag); << " tag " << tag);
@ -1027,11 +1019,10 @@ void amount_t::parse(std::istream& in, unsigned char flags)
// [-]NUM[ ]SYM [@ AMOUNT] // [-]NUM[ ]SYM [@ AMOUNT]
// SYM[ ][-]NUM [@ AMOUNT] // SYM[ ][-]NUM [@ AMOUNT]
std::string name;
std::string symbol; std::string symbol;
std::string quant; std::string quant;
std::string price; amount_t price;
std::string date; std::time_t date = 0;
std::string tag; std::string tag;
unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS; unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS;
bool negative = false; bool negative = false;
@ -1052,17 +1043,15 @@ void amount_t::parse(std::istream& in, unsigned char flags)
comm_flags |= COMMODITY_STYLE_SEPARATED; comm_flags |= COMMODITY_STYLE_SEPARATED;
parse_commodity(in, symbol); parse_commodity(in, symbol);
name = symbol;
if (! symbol.empty()) if (! symbol.empty())
comm_flags |= COMMODITY_STYLE_SUFFIXED; comm_flags |= COMMODITY_STYLE_SUFFIXED;
if (! in.eof() && ((n = in.peek()) != '\n')) if (! in.eof() && ((n = in.peek()) != '\n'))
parse_annotations(in, symbol, name, price, date, tag); parse_annotations(in, price, date, tag);
} }
} else { } else {
parse_commodity(in, symbol); parse_commodity(in, symbol);
name = symbol;
if (! in.eof() && ((n = in.peek()) != '\n')) { if (! in.eof() && ((n = in.peek()) != '\n')) {
if (std::isspace(in.peek())) if (std::isspace(in.peek()))
@ -1071,7 +1060,7 @@ void amount_t::parse(std::istream& in, unsigned char flags)
parse_quantity(in, quant); parse_quantity(in, quant);
if (! in.eof() && ((n = in.peek()) != '\n')) if (! in.eof() && ((n = in.peek()) != '\n'))
parse_annotations(in, symbol, name, price, date, tag); parse_annotations(in, price, date, tag);
} }
} }
@ -1085,23 +1074,19 @@ void amount_t::parse(std::istream& in, unsigned char flags)
bool newly_created = false; bool newly_created = false;
commodity_ = commodity_t::find(name); if (symbol.empty()) {
if (! commodity_) { commodity_ = commodity_t::null_commodity;
newly_created = true; } else {
commodity_ = commodity_t::find(symbol);
if (! price.empty() || ! date.empty() || ! tag.empty()) { if (! commodity_) {
commodity_ = annotated_commodity_t::create(symbol, price, date, tag);
} else {
assert(name == symbol);
commodity_ = commodity_t::create(symbol); commodity_ = commodity_t::create(symbol);
newly_created = true;
} }
#ifdef DEBUG_ENABLED assert(commodity_);
if (! commodity_)
std::cerr << "Failed to find commodity for name " if (price || date || ! tag.empty())
<< name << " symbol " << symbol << std::endl; commodity_ =
#endif annotated_commodity_t::find_or_create(*commodity_, price, date, tag);
if (! commodity_)
commodity_ = commodity_t::null_commodity;
} }
// Determine the precision of the amount, based on the usage of // Determine the precision of the amount, based on the usage of
@ -1327,10 +1312,13 @@ void amount_t::write_quantity(std::ostream& out) const
bool amount_t::valid() const bool amount_t::valid() const
{ {
if (quantity) { if (quantity) {
if (quantity->ref == 0) if (quantity->ref == 0) {
DEBUG_PRINT("ledger.validate", "amount_t: quantity->ref == 0");
return false; return false;
}
} }
else if (commodity_) { else if (commodity_) {
DEBUG_PRINT("ledger.validate", "amount_t: commodity_ != NULL");
return false; return false;
} }
return true; return true;
@ -1448,16 +1436,21 @@ bool commodity_t::needs_quotes(const std::string& symbol)
bool commodity_t::valid() const bool commodity_t::valid() const
{ {
if (symbol().empty() && this != null_commodity) if (symbol().empty() && this != null_commodity) {
DEBUG_PRINT("ledger.validate",
"commodity_t: symbol().empty() && this != null_commodity");
return false; return false;
}
#if 0 if (annotated && ! base) {
if (annotated && ! base) DEBUG_PRINT("ledger.validate", "commodity_t: annotated && ! base");
return false; return false;
#endif }
if (precision() > 16) if (precision() > 16) {
DEBUG_PRINT("ledger.validate", "commodity_t: precision() > 16");
return false; return false;
}
return true; return true;
} }
@ -1572,34 +1565,12 @@ annotated_commodity_t::write_annotations(std::ostream& out,
out << " (" << tag << ')'; out << " (" << tag << ')';
} }
std::string
annotated_commodity_t::make_qualified_name(const commodity_t& comm,
const amount_t& price,
const std::time_t date,
const std::string& tag)
{
std::ostringstream name;
comm.write(name);
write_annotations(name, price, date, tag);
DEBUG_PRINT("amounts.commodities", "make_qualified_name for "
<< comm.qualified_symbol << std::endl
<< " price " << price << " "
<< " date " << date << " "
<< " tag " << tag);
DEBUG_PRINT("amounts.commodities", "qualified_name is " << name.str());
return name.str();
}
commodity_t * commodity_t *
annotated_commodity_t::create(const commodity_t& comm, annotated_commodity_t::create(const commodity_t& comm,
const amount_t& price, const amount_t& price,
const std::time_t date, const std::time_t date,
const std::string& tag, const std::string& tag,
const std::string& entry_name) const std::string& mapping_key)
{ {
std::auto_ptr<annotated_commodity_t> commodity(new annotated_commodity_t); std::auto_ptr<annotated_commodity_t> commodity(new annotated_commodity_t);
@ -1615,12 +1586,6 @@ annotated_commodity_t::create(const commodity_t& comm,
commodity->qualified_symbol = comm.symbol(); commodity->qualified_symbol = comm.symbol();
std::string mapping_key;
if (entry_name.empty())
mapping_key = make_qualified_name(comm, price, date, tag);
else
mapping_key = entry_name;
DEBUG_PRINT("amounts.commodities", "Creating annotated commodity " DEBUG_PRINT("amounts.commodities", "Creating annotated commodity "
<< "symbol " << commodity->symbol() << "symbol " << commodity->symbol()
<< " key " << mapping_key << std::endl << " key " << mapping_key << std::endl
@ -1638,39 +1603,27 @@ annotated_commodity_t::create(const commodity_t& comm,
return commodity.release(); return commodity.release();
} }
commodity_t * namespace {
annotated_commodity_t::create(const std::string& symbol, std::string make_qualified_name(const commodity_t& comm,
const amount_t& price, const amount_t& price,
const std::time_t date, const std::time_t date,
const std::string& tag) const std::string& tag)
{ {
commodity_t * comm = commodity_t::find_or_create(symbol); std::ostringstream name;
assert(comm);
if (! price && ! date && tag.empty()) comm.write(name);
return comm; annotated_commodity_t::write_annotations(name, price, date, tag);
return create(*comm, price, date, tag); DEBUG_PRINT("amounts.commodities", "make_qualified_name for "
} << comm.qualified_symbol << std::endl
<< " price " << price << " "
<< " date " << date << " "
<< " tag " << tag);
commodity_t * DEBUG_PRINT("amounts.commodities", "qualified_name is " << name.str());
annotated_commodity_t::create(const std::string& symbol,
const std::string& price,
const std::string& date,
const std::string& tag)
{
commodity_t * comm = commodity_t::find_or_create(symbol);
assert(comm);
amount_t real_price; return name.str();
if (! price.empty()) }
real_price.parse(price, AMOUNT_PARSE_NO_MIGRATE);
std::time_t real_date = 0;
if (! date.empty())
parse_date(date.c_str(), &real_date);
return create(*comm, real_price, real_date, tag);
} }
commodity_t * commodity_t *
@ -1681,14 +1634,12 @@ annotated_commodity_t::find_or_create(const commodity_t& comm,
{ {
std::string name = make_qualified_name(comm, price, date, tag); std::string name = make_qualified_name(comm, price, date, tag);
commodity_t * base = commodity_t::find(name); commodity_t * ann_comm = commodity_t::find(name);
if (base) if (ann_comm) {
return base; assert(ann_comm->annotated);
return ann_comm;
base = commodity_t::find_or_create(comm.base_symbol()); }
assert(base); return create(comm, price, date, tag, name);
return create(*base, price, date, tag, name);
} }
} // namespace ledger } // namespace ledger

View file

@ -551,33 +551,6 @@ class annotated_commodity_t : public commodity_t
std::time_t date; std::time_t date;
std::string tag; std::string tag;
static void write_annotations(std::ostream& out,
const amount_t& price,
const std::time_t date,
const std::string& tag);
static
std::string make_qualified_name(const commodity_t& comm,
const amount_t& price,
const std::time_t date,
const std::string& tag);
static commodity_t * create(const commodity_t& comm,
const amount_t& price,
const std::time_t date,
const std::string& tag,
const std::string& entry_name = "");
static commodity_t * create(const std::string& symbol,
const amount_t& price,
const std::time_t date,
const std::string& tag);
static commodity_t * create(const std::string& symbol,
const std::string& price,
const std::string& date,
const std::string& tag);
static commodity_t * find_or_create(const commodity_t& comm,
const amount_t& price,
const std::time_t date,
const std::string& tag);
explicit annotated_commodity_t() { explicit annotated_commodity_t() {
annotated = true; annotated = true;
} }
@ -585,6 +558,25 @@ class annotated_commodity_t : public commodity_t
void write_annotations(std::ostream& out) const { void write_annotations(std::ostream& out) const {
annotated_commodity_t::write_annotations(out, price, date, tag); annotated_commodity_t::write_annotations(out, price, date, tag);
} }
static void write_annotations(std::ostream& out,
const amount_t& price,
const std::time_t date,
const std::string& tag);
private:
static commodity_t * create(const commodity_t& comm,
const amount_t& price,
const std::time_t date,
const std::string& tag,
const std::string& mapping_key);
static commodity_t * find_or_create(const commodity_t& comm,
const amount_t& price,
const std::time_t date,
const std::string& tag);
friend class amount_t;
}; };
inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) { inline std::ostream& operator<<(std::ostream& out, const commodity_t& comm) {

View file

@ -101,7 +101,7 @@ class balance_t
if (i != amounts.end()) { if (i != amounts.end()) {
(*i).second -= amt; (*i).second -= amt;
if ((*i).second.realzero()) if ((*i).second.realzero())
amounts.erase(&amt.commodity()); amounts.erase(i);
} }
else if (! amt.realzero()) { else if (! amt.realzero()) {
amounts.insert(amounts_pair(&amt.commodity(), - amt)); amounts.insert(amounts_pair(&amt.commodity(), - amt));

View file

@ -36,11 +36,15 @@ std::time_t transaction_t::effective_date() const
bool transaction_t::valid() const bool transaction_t::valid() const
{ {
if (! entry) if (! entry) {
DEBUG_PRINT("ledger.validate", "transaction_t: ! entry");
return false; return false;
}
if (state != UNCLEARED && state != CLEARED && state != PENDING) if (state != UNCLEARED && state != CLEARED && state != PENDING) {
DEBUG_PRINT("ledger.validate", "transaction_t: state is bad");
return false; return false;
}
bool found = false; bool found = false;
for (transactions_list::const_iterator i = entry->transactions.begin(); for (transactions_list::const_iterator i = entry->transactions.begin();
@ -50,20 +54,30 @@ bool transaction_t::valid() const
found = true; found = true;
break; break;
} }
if (! found) if (! found) {
DEBUG_PRINT("ledger.validate", "transaction_t: ! found");
return false; return false;
}
if (! account) if (! account) {
DEBUG_PRINT("ledger.validate", "transaction_t: ! account");
return false; return false;
}
if (! amount.valid()) if (! amount.valid()) {
DEBUG_PRINT("ledger.validate", "transaction_t: ! amount.valid()");
return false; return false;
}
if (cost && ! cost->valid()) if (cost && ! cost->valid()) {
DEBUG_PRINT("ledger.validate", "transaction_t: cost && ! cost->valid()");
return false; return false;
}
if (flags & ~0x001f) if (flags & ~0x001f) {
DEBUG_PRINT("ledger.validate", "transaction_t: flags are bad");
return false; return false;
}
return true; return true;
} }
@ -158,7 +172,8 @@ bool entry_base_t::finalize()
entry_t * entry = dynamic_cast<entry_t *>(this); entry_t * entry = dynamic_cast<entry_t *>(this);
if (! (*x)->amount.commodity().annotated) if ((*x)->amount.commodity() &&
! (*x)->amount.commodity().annotated)
(*x)->amount.annotate_commodity(abs(per_unit_cost), (*x)->amount.annotate_commodity(abs(per_unit_cost),
entry ? entry->actual_date() : 0, entry ? entry->actual_date() : 0,
entry ? entry->code : ""); entry ? entry->code : "");
@ -271,14 +286,18 @@ void entry_t::add_transaction(transaction_t * xact)
bool entry_t::valid() const bool entry_t::valid() const
{ {
if (! _date || ! journal) if (! _date || ! journal) {
DEBUG_PRINT("ledger.validate", "entry_t: ! _date || ! journal");
return false; return false;
}
for (transactions_list::const_iterator i = transactions.begin(); for (transactions_list::const_iterator i = transactions.begin();
i != transactions.end(); i != transactions.end();
i++) i++)
if ((*i)->entry != this || ! (*i)->valid()) if ((*i)->entry != this || ! (*i)->valid()) {
DEBUG_PRINT("ledger.validate", "entry_t: transaction not valid");
return false; return false;
}
return true; return true;
} }
@ -434,14 +453,18 @@ std::ostream& operator<<(std::ostream& out, const account_t& account)
bool account_t::valid() const bool account_t::valid() const
{ {
if (depth > 256 || ! journal) if (depth > 256 || ! journal) {
DEBUG_PRINT("ledger.validate", "account_t: depth > 256 || ! journal");
return false; return false;
}
for (accounts_map::const_iterator i = accounts.begin(); for (accounts_map::const_iterator i = accounts.begin();
i != accounts.end(); i != accounts.end();
i++) i++)
if (! (*i).second->valid()) if (! (*i).second->valid()) {
DEBUG_PRINT("ledger.validate", "account_t: child not valid");
return false; return false;
}
return true; return true;
} }
@ -528,20 +551,26 @@ bool journal_t::remove_entry(entry_t * entry)
bool journal_t::valid() const bool journal_t::valid() const
{ {
if (! master->valid()) if (! master->valid()) {
DEBUG_PRINT("ledger.validate", "journal_t: master not valid");
return false; return false;
}
for (entries_list::const_iterator i = entries.begin(); for (entries_list::const_iterator i = entries.begin();
i != entries.end(); i != entries.end();
i++) i++)
if (! (*i)->valid()) if (! (*i)->valid()) {
DEBUG_PRINT("ledger.validate", "journal_t: entry not valid");
return false; return false;
}
for (commodities_map::const_iterator i = commodity_t::commodities.begin(); for (commodities_map::const_iterator i = commodity_t::commodities.begin();
i != commodity_t::commodities.end(); i != commodity_t::commodities.end();
i++) i++)
if (! (*i).second->valid()) if (! (*i).second->valid()) {
DEBUG_PRINT("ledger.validate", "journal_t: commodity not valid");
return false; return false;
}
return true; return true;
} }

View file

@ -229,16 +229,19 @@ transaction_t * parse_transaction(char * line, account_t * account,
else else
per_unit_cost /= xact->amount; per_unit_cost /= xact->amount;
if (! xact->amount.commodity().annotated) { if (xact->amount.commodity()) {
xact->amount.annotate_commodity(per_unit_cost, if (! xact->amount.commodity().annotated) {
xact->entry->actual_date(), xact->amount.annotate_commodity(per_unit_cost,
xact->entry->code); xact->entry->actual_date(),
} else { xact->entry->code);
annotated_commodity_t& ann(static_cast<annotated_commodity_t&> } else {
(xact->amount.commodity())); annotated_commodity_t& ann(static_cast<annotated_commodity_t&>
xact->amount.annotate_commodity(! ann.price ? per_unit_cost : amount_t(), (xact->amount.commodity()));
! ann.date ? xact->entry->actual_date() : 0, xact->amount.annotate_commodity
ann.tag.empty() ? xact->entry->code : ""); (! ann.price ? per_unit_cost : amount_t(),
! ann.date ? xact->entry->actual_date() : 0,
ann.tag.empty() ? xact->entry->code : "");
}
} }
DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " << DEBUG_PRINT("ledger.textual.parse", "line " << linenum << ": " <<

View file

@ -629,7 +629,10 @@ void value_expr_t::compute(value_t& result, const details_t& details,
case O_NOT: case O_NOT:
left->compute(result, details, context); left->compute(result, details, context);
result.negate(); if (result.strip_annotations())
result = false;
else
result = true;
break; break;
case O_QUES: { case O_QUES: {
@ -637,7 +640,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
assert(right); assert(right);
assert(right->kind == O_COL); assert(right->kind == O_COL);
left->compute(result, details, context); left->compute(result, details, context);
if (result) if (result.strip_annotations())
right->left->compute(result, details, context); right->left->compute(result, details, context);
else else
right->right->compute(result, details, context); right->right->compute(result, details, context);
@ -648,6 +651,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
assert(left); assert(left);
assert(right); assert(right);
left->compute(result, details, context); left->compute(result, details, context);
result = result.strip_annotations();
if (result) if (result)
right->compute(result, details, context); right->compute(result, details, context);
break; break;
@ -656,7 +660,7 @@ void value_expr_t::compute(value_t& result, const details_t& details,
assert(left); assert(left);
assert(right); assert(right);
left->compute(result, details, context); left->compute(result, details, context);
if (! result) if (! result.strip_annotations())
right->compute(result, details, context); right->compute(result, details, context);
break; break;

View file

@ -491,7 +491,8 @@ class item_predicate
} }
bool operator()(const T& item) const { bool operator()(const T& item) const {
return ! predicate || predicate->compute(details_t(item)); return (! predicate ||
predicate->compute(details_t(item)).strip_annotations());
} }
}; };

View file

@ -1233,11 +1233,9 @@ value_t value_t::strip_annotations(const bool keep_price,
{ {
switch (type) { switch (type) {
case BOOLEAN: case BOOLEAN:
throw new value_error("Cannot strip commodity annotations from a boolean");
case INTEGER: case INTEGER:
return *this;
case DATETIME: case DATETIME:
throw new value_error("Cannot strip commodity annotations from a date/time"); return *this;
case AMOUNT: case AMOUNT:
return ((amount_t *) data)->strip_annotations return ((amount_t *) data)->strip_annotations