Started using boost::optional<T>.
This commit is contained in:
parent
50a9caf302
commit
e92bcf411d
37 changed files with 655 additions and 694 deletions
220
src/amount.cc
220
src/amount.cc
|
|
@ -147,24 +147,24 @@ void amount_t::shutdown()
|
|||
mpz_clear(divisor);
|
||||
|
||||
if (commodity_base_t::updater) {
|
||||
delete commodity_base_t::updater;
|
||||
checked_delete(commodity_base_t::updater);
|
||||
commodity_base_t::updater = NULL;
|
||||
}
|
||||
|
||||
for (base_commodities_map::iterator i = commodity_base_t::commodities.begin();
|
||||
i != commodity_base_t::commodities.end();
|
||||
i++)
|
||||
delete (*i).second;
|
||||
checked_delete((*i).second);
|
||||
|
||||
for (commodities_map::iterator i = commodity_t::commodities.begin();
|
||||
i != commodity_t::commodities.end();
|
||||
i++)
|
||||
delete (*i).second;
|
||||
checked_delete((*i).second);
|
||||
|
||||
commodity_base_t::commodities.clear();
|
||||
commodity_t::commodities.clear();
|
||||
|
||||
delete commodity_t::commodities_by_ident;
|
||||
checked_delete(commodity_t::commodities_by_ident);
|
||||
commodity_t::commodities_by_ident = NULL;
|
||||
|
||||
commodity_t::null_commodity = NULL;
|
||||
|
|
@ -172,7 +172,7 @@ void amount_t::shutdown()
|
|||
|
||||
true_value->ref--;
|
||||
assert(true_value->ref == 0);
|
||||
delete true_value;
|
||||
checked_delete(true_value);
|
||||
true_value = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -318,13 +318,13 @@ namespace {
|
|||
newbuf[0] = '-';
|
||||
std::strcpy(&newbuf[1], result ? result : buf);
|
||||
mpz_set_str(dest, newbuf, 10);
|
||||
delete[] newbuf;
|
||||
checked_array_delete(newbuf);
|
||||
} else {
|
||||
mpz_set_str(dest, result ? result : buf, 10);
|
||||
}
|
||||
|
||||
if (result)
|
||||
delete[] result;
|
||||
checked_array_delete(result);
|
||||
freedtoa(buf);
|
||||
|
||||
return decpt;
|
||||
|
|
@ -346,7 +346,7 @@ void amount_t::_release()
|
|||
|
||||
if (--quantity->ref == 0) {
|
||||
if (! (quantity->flags & BIGINT_BULK_ALLOC))
|
||||
delete quantity;
|
||||
checked_delete(quantity);
|
||||
else
|
||||
quantity->~bigint_t();
|
||||
}
|
||||
|
|
@ -1073,7 +1073,7 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
|
|||
|
||||
if (! omit_commodity && comm.annotated) {
|
||||
annotated_commodity_t& ann(static_cast<annotated_commodity_t&>(comm));
|
||||
assert(&ann.price != this);
|
||||
assert(&*ann.price != this);
|
||||
ann.write_annotations(out);
|
||||
}
|
||||
|
||||
|
|
@ -1144,11 +1144,11 @@ static void parse_commodity(std::istream& in, string& symbol)
|
|||
symbol = buf;
|
||||
}
|
||||
|
||||
bool parse_annotations(std::istream& in, amount_t& price,
|
||||
moment_t& date, string& tag)
|
||||
void parse_annotations(std::istream& in,
|
||||
optional<amount_t>& price,
|
||||
optional<moment_t>& date,
|
||||
optional<string>& tag)
|
||||
{
|
||||
bool has_date = false;
|
||||
|
||||
do {
|
||||
char buf[256];
|
||||
char c = peek_next_nonws(in);
|
||||
|
|
@ -1163,19 +1163,22 @@ bool parse_annotations(std::istream& in, amount_t& price,
|
|||
else
|
||||
throw_(amount_error, "Commodity price lacks closing brace");
|
||||
|
||||
price.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
|
||||
price.in_place_reduce();
|
||||
amount_t temp;
|
||||
temp.parse(buf, AMOUNT_PARSE_NO_MIGRATE);
|
||||
temp.in_place_reduce();
|
||||
|
||||
// Since this price will maintain its own precision, make sure
|
||||
// it is at least as large as the base commodity, since the user
|
||||
// may have only specified {$1} or something similar.
|
||||
|
||||
if (price.has_commodity() &&
|
||||
price.quantity->prec < price.commodity().precision())
|
||||
price = price.round(); // no need to retain individual precision
|
||||
if (temp.has_commodity() &&
|
||||
temp.quantity->prec < temp.commodity().precision())
|
||||
temp = temp.round(); // no need to retain individual precision
|
||||
|
||||
price = temp;
|
||||
}
|
||||
else if (c == '[') {
|
||||
if (is_valid_moment(date))
|
||||
if (date)
|
||||
throw_(amount_error, "Commodity specifies more than one date");
|
||||
|
||||
in.get(c);
|
||||
|
|
@ -1186,10 +1189,9 @@ bool parse_annotations(std::istream& in, amount_t& price,
|
|||
throw_(amount_error, "Commodity date lacks closing bracket");
|
||||
|
||||
date = parse_datetime(buf);
|
||||
has_date = true;
|
||||
}
|
||||
else if (c == '(') {
|
||||
if (! tag.empty())
|
||||
if (tag)
|
||||
throw_(amount_error, "Commodity specifies more than one tag");
|
||||
|
||||
in.get(c);
|
||||
|
|
@ -1207,12 +1209,10 @@ bool parse_annotations(std::istream& in, amount_t& price,
|
|||
} while (true);
|
||||
|
||||
DEBUG("amounts.commodities",
|
||||
"Parsed commodity annotations: "
|
||||
<< " price " << price << " "
|
||||
<< " date " << date << " "
|
||||
<< " tag " << tag);
|
||||
|
||||
return has_date;
|
||||
"Parsed commodity annotations: "
|
||||
<< " price " << (price ? price->to_string() : "NONE") << " "
|
||||
<< " date " << (date ? *date : moment_t()) << " "
|
||||
<< " tag " << (tag ? *tag : "NONE"));
|
||||
}
|
||||
|
||||
void amount_t::parse(std::istream& in, uint8_t flags)
|
||||
|
|
@ -1222,14 +1222,13 @@ void amount_t::parse(std::istream& in, uint8_t flags)
|
|||
// [-]NUM[ ]SYM [@ AMOUNT]
|
||||
// SYM[ ][-]NUM [@ AMOUNT]
|
||||
|
||||
string symbol;
|
||||
string quant;
|
||||
amount_t tprice;
|
||||
moment_t tdate;
|
||||
bool had_date = false;
|
||||
string tag;
|
||||
unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS;
|
||||
bool negative = false;
|
||||
string symbol;
|
||||
string quant;
|
||||
optional<amount_t> tprice;
|
||||
optional<moment_t> tdate;
|
||||
optional<string> ttag;
|
||||
unsigned int comm_flags = COMMODITY_STYLE_DEFAULTS;
|
||||
bool negative = false;
|
||||
|
||||
char c = peek_next_nonws(in);
|
||||
if (c == '-') {
|
||||
|
|
@ -1252,7 +1251,7 @@ void amount_t::parse(std::istream& in, uint8_t flags)
|
|||
comm_flags |= COMMODITY_STYLE_SUFFIXED;
|
||||
|
||||
if (! in.eof() && ((n = in.peek()) != '\n'))
|
||||
had_date = parse_annotations(in, tprice, tdate, tag);
|
||||
parse_annotations(in, tprice, tdate, ttag);
|
||||
}
|
||||
} else {
|
||||
parse_commodity(in, symbol);
|
||||
|
|
@ -1264,7 +1263,7 @@ void amount_t::parse(std::istream& in, uint8_t flags)
|
|||
parse_quantity(in, quant);
|
||||
|
||||
if (! quant.empty() && ! in.eof() && ((n = in.peek()) != '\n'))
|
||||
had_date = parse_annotations(in, tprice, tdate, tag);
|
||||
parse_annotations(in, tprice, tdate, ttag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1288,9 +1287,9 @@ void amount_t::parse(std::istream& in, uint8_t flags)
|
|||
}
|
||||
assert(commodity_);
|
||||
|
||||
if (! tprice.realzero() || had_date || ! tag.empty())
|
||||
commodity_ =
|
||||
annotated_commodity_t::find_or_create(*commodity_, tprice, tdate, tag);
|
||||
if (tprice || tdate || ttag)
|
||||
commodity_ = annotated_commodity_t::find_or_create
|
||||
(*commodity_, tprice, tdate, ttag);
|
||||
}
|
||||
|
||||
// Determine the precision of the amount, based on the usage of
|
||||
|
|
@ -1348,7 +1347,7 @@ void amount_t::parse(std::istream& in, uint8_t flags)
|
|||
*t = '\0';
|
||||
|
||||
mpz_set_str(MPZ(quantity), buf, 10);
|
||||
delete[] buf;
|
||||
checked_array_delete(buf);
|
||||
} else {
|
||||
mpz_set_str(MPZ(quantity), quant.c_str(), 10);
|
||||
}
|
||||
|
|
@ -1564,9 +1563,9 @@ bool amount_t::valid() const
|
|||
return true;
|
||||
}
|
||||
|
||||
void amount_t::annotate_commodity(const amount_t& tprice,
|
||||
const moment_t& tdate,
|
||||
const string& tag)
|
||||
void amount_t::annotate_commodity(const optional<amount_t>& tprice,
|
||||
const optional<moment_t>& tdate,
|
||||
const optional<string>& ttag)
|
||||
{
|
||||
const commodity_t * this_base;
|
||||
annotated_commodity_t * this_ann = NULL;
|
||||
|
|
@ -1580,17 +1579,17 @@ void amount_t::annotate_commodity(const amount_t& tprice,
|
|||
assert(this_base);
|
||||
|
||||
DEBUG("amounts.commodities", "Annotating commodity for amount "
|
||||
<< *this << std::endl
|
||||
<< " price " << tprice << " "
|
||||
<< " date " << tdate << " "
|
||||
<< " tag " << tag);
|
||||
<< *this << std::endl
|
||||
<< " price " << (tprice ? tprice->to_string() : "NONE") << " "
|
||||
<< " date " << (tdate ? *tdate : moment_t()) << " "
|
||||
<< " ttag " << (ttag ? *ttag : "NONE"));
|
||||
|
||||
commodity_t * ann_comm =
|
||||
annotated_commodity_t::find_or_create
|
||||
(*this_base, ! tprice && this_ann ? this_ann->price : tprice,
|
||||
! is_valid_moment(tdate) && this_ann ? this_ann->date : tdate,
|
||||
tag.empty() && this_ann ? this_ann->tag : tag);
|
||||
if (ann_comm)
|
||||
if (commodity_t * ann_comm =
|
||||
annotated_commodity_t::find_or_create
|
||||
(*this_base,
|
||||
! tprice && this_ann ? this_ann->price : tprice,
|
||||
! tdate && this_ann ? this_ann->date : tdate,
|
||||
! ttag && this_ann ? this_ann->tag : ttag))
|
||||
set_commodity(*ann_comm);
|
||||
|
||||
DEBUG("amounts.commodities", " Annotated amount is " << *this);
|
||||
|
|
@ -1607,8 +1606,8 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
|
|||
DEBUG("amounts.commodities", "Reducing commodity for amount "
|
||||
<< *this << std::endl
|
||||
<< " keep price " << _keep_price << " "
|
||||
<< " keep date " << _keep_date << " "
|
||||
<< " keep tag " << _keep_tag);
|
||||
<< " keep date " << _keep_date << " "
|
||||
<< " keep tag " << _keep_tag);
|
||||
|
||||
annotated_commodity_t&
|
||||
ann_comm(static_cast<annotated_commodity_t&>(commodity()));
|
||||
|
|
@ -1617,13 +1616,14 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
|
|||
commodity_t * new_comm;
|
||||
|
||||
if ((_keep_price && ann_comm.price) ||
|
||||
(_keep_date && is_valid_moment(ann_comm.date)) ||
|
||||
(_keep_tag && ! ann_comm.tag.empty()))
|
||||
(_keep_date && ann_comm.date) ||
|
||||
(_keep_tag && ann_comm.tag))
|
||||
{
|
||||
new_comm = annotated_commodity_t::find_or_create
|
||||
(*ann_comm.ptr, _keep_price ? ann_comm.price : amount_t(),
|
||||
_keep_date ? ann_comm.date : moment_t(),
|
||||
_keep_tag ? ann_comm.tag : "");
|
||||
(*ann_comm.ptr,
|
||||
_keep_price ? ann_comm.price : optional<amount_t>(),
|
||||
_keep_date ? ann_comm.date : optional<moment_t>(),
|
||||
_keep_tag ? ann_comm.tag : optional<string>());
|
||||
} else {
|
||||
new_comm = commodity_t::find_or_create(ann_comm.base_symbol());
|
||||
}
|
||||
|
|
@ -1638,8 +1638,9 @@ amount_t amount_t::strip_annotations(const bool _keep_price,
|
|||
|
||||
optional<amount_t> amount_t::price() const
|
||||
{
|
||||
if (commodity_ && commodity_->annotated) {
|
||||
amount_t t(((annotated_commodity_t *)commodity_)->price);
|
||||
if (commodity_ && commodity_->annotated &&
|
||||
((annotated_commodity_t *)commodity_)->price) {
|
||||
amount_t t(*((annotated_commodity_t *)commodity_)->price);
|
||||
t *= number();
|
||||
DEBUG("amounts.commodities",
|
||||
"Returning price of " << *this << " = " << t);
|
||||
|
|
@ -1800,7 +1801,7 @@ commodity_t * commodity_t::find(const string& symbol)
|
|||
amount_t commodity_base_t::value(const moment_t& moment)
|
||||
{
|
||||
moment_t age;
|
||||
amount_t price;
|
||||
amount_t price;
|
||||
|
||||
if (history) {
|
||||
assert(history->prices.size() > 0);
|
||||
|
|
@ -1851,12 +1852,12 @@ bool annotated_commodity_t::operator==(const commodity_t& comm) const
|
|||
price != static_cast<const annotated_commodity_t&>(comm).price))
|
||||
return false;
|
||||
|
||||
if (is_valid_moment(date) &&
|
||||
if (date &&
|
||||
(! comm.annotated ||
|
||||
date != static_cast<const annotated_commodity_t&>(comm).date))
|
||||
return false;
|
||||
|
||||
if (! tag.empty() &&
|
||||
if (tag &&
|
||||
(! comm.annotated ||
|
||||
tag != static_cast<const annotated_commodity_t&>(comm).tag))
|
||||
return false;
|
||||
|
|
@ -1865,27 +1866,27 @@ bool annotated_commodity_t::operator==(const commodity_t& comm) const
|
|||
}
|
||||
|
||||
void
|
||||
annotated_commodity_t::write_annotations(std::ostream& out,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag)
|
||||
annotated_commodity_t::write_annotations(std::ostream& out,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag)
|
||||
{
|
||||
if (price)
|
||||
out << " {" << price << '}';
|
||||
out << " {" << *price << '}';
|
||||
|
||||
if (is_valid_moment(date))
|
||||
out << " [" << date << ']';
|
||||
if (date)
|
||||
out << " [" << *date << ']';
|
||||
|
||||
if (! tag.empty())
|
||||
out << " (" << tag << ')';
|
||||
if (tag)
|
||||
out << " (" << *tag << ')';
|
||||
}
|
||||
|
||||
commodity_t *
|
||||
annotated_commodity_t::create(const commodity_t& comm,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag,
|
||||
const string& mapping_key)
|
||||
annotated_commodity_t::create(const commodity_t& comm,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag,
|
||||
const string& mapping_key)
|
||||
{
|
||||
std::auto_ptr<annotated_commodity_t> commodity(new annotated_commodity_t);
|
||||
|
||||
|
|
@ -1902,11 +1903,11 @@ annotated_commodity_t::create(const commodity_t& comm,
|
|||
commodity->qualified_symbol = comm.symbol();
|
||||
|
||||
DEBUG("amounts.commodities", "Creating annotated commodity "
|
||||
<< "symbol " << commodity->symbol()
|
||||
<< " key " << mapping_key << std::endl
|
||||
<< " price " << price << " "
|
||||
<< " date " << date << " "
|
||||
<< " tag " << tag);
|
||||
<< "symbol " << commodity->symbol()
|
||||
<< " key " << mapping_key << std::endl
|
||||
<< " price " << (price ? price->to_string() : "NONE") << " "
|
||||
<< " date " << (date ? *date : moment_t()) << " "
|
||||
<< " tag " << (tag ? *tag : "NONE"));
|
||||
|
||||
// Add the fully annotated name to the map, so that this symbol may
|
||||
// quickly be found again.
|
||||
|
|
@ -1922,12 +1923,12 @@ annotated_commodity_t::create(const commodity_t& comm,
|
|||
}
|
||||
|
||||
namespace {
|
||||
string make_qualified_name(const commodity_t& comm,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag)
|
||||
string make_qualified_name(const commodity_t& comm,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag)
|
||||
{
|
||||
if (price < 0)
|
||||
if (price && *price < 0)
|
||||
throw_(amount_error, "A commodity's price may not be negative");
|
||||
|
||||
std::ostringstream name;
|
||||
|
|
@ -1937,9 +1938,9 @@ namespace {
|
|||
|
||||
DEBUG("amounts.commodities", "make_qualified_name for "
|
||||
<< comm.qualified_symbol << std::endl
|
||||
<< " price " << price << " "
|
||||
<< " date " << date << " "
|
||||
<< " tag " << tag);
|
||||
<< " price " << (price ? price->to_string() : "NONE") << " "
|
||||
<< " date " << (date ? *date : moment_t()) << " "
|
||||
<< " tag " << (tag ? *tag : "NONE"));
|
||||
|
||||
DEBUG("amounts.commodities", "qualified_name is " << name.str());
|
||||
|
||||
|
|
@ -1948,10 +1949,10 @@ namespace {
|
|||
}
|
||||
|
||||
commodity_t *
|
||||
annotated_commodity_t::find_or_create(const commodity_t& comm,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag)
|
||||
annotated_commodity_t::find_or_create(const commodity_t& comm,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag)
|
||||
{
|
||||
string name = make_qualified_name(comm, price, date, tag);
|
||||
|
||||
|
|
@ -1991,9 +1992,9 @@ bool compare_amount_commodities::operator()(const amount_t * left,
|
|||
return false;
|
||||
|
||||
if (aleftcomm.price && arightcomm.price) {
|
||||
amount_t leftprice(aleftcomm.price);
|
||||
amount_t leftprice(*aleftcomm.price);
|
||||
leftprice.in_place_reduce();
|
||||
amount_t rightprice(arightcomm.price);
|
||||
amount_t rightprice(*arightcomm.price);
|
||||
rightprice.in_place_reduce();
|
||||
|
||||
if (leftprice.commodity() == rightprice.commodity()) {
|
||||
|
|
@ -2013,28 +2014,25 @@ bool compare_amount_commodities::operator()(const amount_t * left,
|
|||
}
|
||||
}
|
||||
|
||||
if (! is_valid_moment(aleftcomm.date) &&
|
||||
is_valid_moment(arightcomm.date))
|
||||
if (! aleftcomm.date && arightcomm.date)
|
||||
return true;
|
||||
if (is_valid_moment(aleftcomm.date) &&
|
||||
! is_valid_moment(arightcomm.date))
|
||||
if (aleftcomm.date && ! arightcomm.date)
|
||||
return false;
|
||||
|
||||
if (is_valid_moment(aleftcomm.date) &&
|
||||
is_valid_moment(arightcomm.date)) {
|
||||
duration_t diff = aleftcomm.date - arightcomm.date;
|
||||
if (aleftcomm.date && arightcomm.date) {
|
||||
duration_t diff = *aleftcomm.date - *arightcomm.date;
|
||||
return diff.is_negative();
|
||||
}
|
||||
|
||||
if (aleftcomm.tag.empty() && ! arightcomm.tag.empty())
|
||||
if (! aleftcomm.tag && arightcomm.tag)
|
||||
return true;
|
||||
if (! aleftcomm.tag.empty() && arightcomm.tag.empty())
|
||||
if (aleftcomm.tag && ! arightcomm.tag)
|
||||
return false;
|
||||
|
||||
if (! aleftcomm.tag.empty() && ! arightcomm.tag.empty())
|
||||
return aleftcomm.tag < arightcomm.tag;
|
||||
if (aleftcomm.tag && arightcomm.tag)
|
||||
return *aleftcomm.tag < *arightcomm.tag;
|
||||
|
||||
assert(0);
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
62
src/amount.h
62
src/amount.h
|
|
@ -142,9 +142,9 @@ class amount_t
|
|||
|
||||
commodity_t& commodity() const;
|
||||
|
||||
void annotate_commodity(const amount_t& price,
|
||||
const moment_t& date = moment_t(),
|
||||
const string& tag = "");
|
||||
void annotate_commodity(const optional<amount_t>& tprice,
|
||||
const optional<moment_t>& tdate = optional<moment_t>(),
|
||||
const optional<string>& ttag = optional<string>());
|
||||
|
||||
amount_t strip_annotations(const bool _keep_price = keep_price,
|
||||
const bool _keep_date = keep_date,
|
||||
|
|
@ -348,8 +348,10 @@ class amount_t
|
|||
friend void clean_commodity_history(char * item_pool,
|
||||
char * item_pool_end);
|
||||
|
||||
friend bool parse_annotations(std::istream& in, amount_t& price,
|
||||
moment_t& date, string& tag);
|
||||
friend void parse_annotations(std::istream& in,
|
||||
optional<amount_t>& price,
|
||||
optional<moment_t>& date,
|
||||
optional<string>& tag);
|
||||
|
||||
// Streaming interface
|
||||
|
||||
|
|
@ -513,9 +515,9 @@ class commodity_base_t
|
|||
|
||||
~commodity_base_t() {
|
||||
TRACE_DTOR(commodity_base_t);
|
||||
if (history) delete history;
|
||||
if (smaller) delete smaller;
|
||||
if (larger) delete larger;
|
||||
if (history) checked_delete(history);
|
||||
if (smaller) checked_delete(smaller);
|
||||
if (larger) checked_delete(larger);
|
||||
}
|
||||
|
||||
static base_commodities_map commodities;
|
||||
|
|
@ -538,10 +540,10 @@ class commodity_base_t
|
|||
public:
|
||||
virtual ~updater_t() {}
|
||||
virtual void operator()(commodity_base_t& commodity,
|
||||
const moment_t& moment,
|
||||
const moment_t& date,
|
||||
const moment_t& last,
|
||||
amount_t& price) = 0;
|
||||
const moment_t& moment,
|
||||
const moment_t& date,
|
||||
const moment_t& last,
|
||||
amount_t& price) = 0;
|
||||
};
|
||||
friend class updater_t;
|
||||
|
||||
|
|
@ -659,7 +661,7 @@ class commodity_t
|
|||
}
|
||||
void set_smaller(const amount_t& arg) {
|
||||
if (base->smaller)
|
||||
delete base->smaller;
|
||||
checked_delete(base->smaller);
|
||||
base->smaller = new amount_t(arg);
|
||||
}
|
||||
|
||||
|
|
@ -668,7 +670,7 @@ class commodity_t
|
|||
}
|
||||
void set_larger(const amount_t& arg) {
|
||||
if (base->larger)
|
||||
delete base->larger;
|
||||
checked_delete(base->larger);
|
||||
base->larger = new amount_t(arg);
|
||||
}
|
||||
|
||||
|
|
@ -694,9 +696,9 @@ class annotated_commodity_t : public commodity_t
|
|||
public:
|
||||
const commodity_t * ptr;
|
||||
|
||||
amount_t price;
|
||||
moment_t date;
|
||||
string tag;
|
||||
optional<amount_t> price;
|
||||
optional<moment_t> date;
|
||||
optional<string> tag;
|
||||
|
||||
explicit annotated_commodity_t() {
|
||||
TRACE_CTOR(annotated_commodity_t, "");
|
||||
|
|
@ -712,22 +714,22 @@ class annotated_commodity_t : public commodity_t
|
|||
annotated_commodity_t::write_annotations(out, price, date, tag);
|
||||
}
|
||||
|
||||
static void write_annotations(std::ostream& out,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag);
|
||||
static void write_annotations(std::ostream& out,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag);
|
||||
|
||||
private:
|
||||
static commodity_t * create(const commodity_t& comm,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag,
|
||||
const string& mapping_key);
|
||||
static commodity_t * create(const commodity_t& comm,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag,
|
||||
const string& mapping_key);
|
||||
|
||||
static commodity_t * find_or_create(const commodity_t& comm,
|
||||
const amount_t& price,
|
||||
const moment_t& date,
|
||||
const string& tag);
|
||||
static commodity_t * find_or_create(const commodity_t& comm,
|
||||
const optional<amount_t>& price,
|
||||
const optional<moment_t>& date,
|
||||
const optional<string>& tag);
|
||||
|
||||
friend class amount_t;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -448,15 +448,12 @@ class balance_t
|
|||
void write(std::ostream& out, const int first_width,
|
||||
const int latter_width = -1) const;
|
||||
|
||||
void in_place_abs() {
|
||||
for (amounts_map::iterator i = amounts.begin();
|
||||
i != amounts.end();
|
||||
i++)
|
||||
(*i).second = (*i).second.abs();
|
||||
}
|
||||
balance_t abs() const {
|
||||
balance_t temp = *this;
|
||||
temp.in_place_abs();
|
||||
for (amounts_map::iterator i = temp.amounts.begin();
|
||||
i != temp.amounts.end();
|
||||
i++)
|
||||
(*i).second = (*i).second.abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
|
@ -503,81 +500,64 @@ inline std::ostream& operator<<(std::ostream& out, const balance_t& bal) {
|
|||
class balance_pair_t
|
||||
{
|
||||
public:
|
||||
balance_t quantity;
|
||||
balance_t * cost;
|
||||
balance_t quantity;
|
||||
optional<balance_t> cost;
|
||||
|
||||
// constructors
|
||||
balance_pair_t() : cost(NULL) {
|
||||
balance_pair_t() {
|
||||
TRACE_CTOR(balance_pair_t, "");
|
||||
}
|
||||
balance_pair_t(const balance_pair_t& bal_pair)
|
||||
: quantity(bal_pair.quantity), cost(NULL) {
|
||||
: quantity(bal_pair.quantity), cost(bal_pair.cost) {
|
||||
TRACE_CTOR(balance_pair_t, "copy");
|
||||
if (bal_pair.cost)
|
||||
cost = new balance_t(*bal_pair.cost);
|
||||
}
|
||||
balance_pair_t(const balance_t& _quantity)
|
||||
: quantity(_quantity), cost(NULL) {
|
||||
: quantity(_quantity) {
|
||||
TRACE_CTOR(balance_pair_t, "const balance_t&");
|
||||
}
|
||||
balance_pair_t(const amount_t& _quantity)
|
||||
: quantity(_quantity), cost(NULL) {
|
||||
: quantity(_quantity) {
|
||||
TRACE_CTOR(balance_pair_t, "const amount_t&");
|
||||
}
|
||||
template <typename T>
|
||||
balance_pair_t(T val) : quantity(val), cost(NULL) {
|
||||
balance_pair_t(T val) : quantity(val) {
|
||||
TRACE_CTOR(balance_pair_t, "T");
|
||||
}
|
||||
|
||||
// destructor
|
||||
~balance_pair_t() {
|
||||
TRACE_DTOR(balance_pair_t);
|
||||
if (cost) delete cost;
|
||||
}
|
||||
|
||||
// assignment operator
|
||||
balance_pair_t& operator=(const balance_pair_t& bal_pair) {
|
||||
if (this != &bal_pair) {
|
||||
if (cost) {
|
||||
delete cost;
|
||||
cost = NULL;
|
||||
}
|
||||
quantity = bal_pair.quantity;
|
||||
if (bal_pair.cost)
|
||||
cost = new balance_t(*bal_pair.cost);
|
||||
cost = bal_pair.cost;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator=(const balance_t& bal) {
|
||||
if (cost) {
|
||||
delete cost;
|
||||
cost = NULL;
|
||||
}
|
||||
quantity = bal;
|
||||
cost = optional<balance_t>();
|
||||
return *this;
|
||||
}
|
||||
balance_pair_t& operator=(const amount_t& amt) {
|
||||
if (cost) {
|
||||
delete cost;
|
||||
cost = NULL;
|
||||
}
|
||||
quantity = amt;
|
||||
cost = optional<balance_t>();
|
||||
return *this;
|
||||
}
|
||||
template <typename T>
|
||||
balance_pair_t& operator=(T val) {
|
||||
if (cost) {
|
||||
delete cost;
|
||||
cost = NULL;
|
||||
}
|
||||
quantity = val;
|
||||
cost = optional<balance_t>();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// in-place arithmetic
|
||||
balance_pair_t& operator+=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = new balance_t(quantity);
|
||||
cost = quantity;
|
||||
quantity += bal_pair.quantity;
|
||||
if (cost)
|
||||
*cost += bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
|
|
@ -602,7 +582,7 @@ class balance_pair_t
|
|||
|
||||
balance_pair_t& operator-=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = new balance_t(quantity);
|
||||
cost = quantity;
|
||||
quantity -= bal_pair.quantity;
|
||||
if (cost)
|
||||
*cost -= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
|
|
@ -673,7 +653,7 @@ class balance_pair_t
|
|||
// multiplication and division
|
||||
balance_pair_t& operator*=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = new balance_t(quantity);
|
||||
cost = quantity;
|
||||
quantity *= bal_pair.quantity;
|
||||
if (cost)
|
||||
*cost *= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
|
|
@ -698,7 +678,7 @@ class balance_pair_t
|
|||
|
||||
balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
|
||||
if (bal_pair.cost && ! cost)
|
||||
cost = new balance_t(quantity);
|
||||
cost = quantity;
|
||||
quantity /= bal_pair.quantity;
|
||||
if (cost)
|
||||
*cost /= bal_pair.cost ? *bal_pair.cost : bal_pair.quantity;
|
||||
|
|
@ -852,9 +832,9 @@ class balance_pair_t
|
|||
|
||||
// unary negation
|
||||
void in_place_negate() {
|
||||
quantity = quantity.negate();
|
||||
quantity.in_place_negate();
|
||||
if (cost)
|
||||
*cost = cost->negate();
|
||||
cost->in_place_negate();
|
||||
}
|
||||
balance_pair_t negate() const {
|
||||
balance_pair_t temp = *this;
|
||||
|
|
@ -880,14 +860,11 @@ class balance_pair_t
|
|||
return ((! cost || cost->realzero()) && quantity.realzero());
|
||||
}
|
||||
|
||||
void in_place_abs() {
|
||||
quantity = quantity.abs();
|
||||
if (cost)
|
||||
*cost = cost->abs();
|
||||
}
|
||||
balance_pair_t abs() const {
|
||||
balance_pair_t temp = *this;
|
||||
temp.in_place_abs();
|
||||
temp.quantity = temp.quantity.abs();
|
||||
if (temp.cost)
|
||||
temp.cost = temp.cost->abs();
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
|
@ -922,9 +899,9 @@ class balance_pair_t
|
|||
}
|
||||
|
||||
balance_pair_t& add(const amount_t& amt,
|
||||
const amount_t * a_cost = NULL) {
|
||||
const optional<amount_t>& a_cost = optional<amount_t>()) {
|
||||
if (a_cost && ! cost)
|
||||
cost = new balance_t(quantity);
|
||||
cost = quantity;
|
||||
quantity += amt;
|
||||
if (cost)
|
||||
*cost += a_cost ? *a_cost : amt;
|
||||
|
|
@ -948,7 +925,7 @@ class balance_pair_t
|
|||
void in_place_round() {
|
||||
quantity = quantity.round();
|
||||
if (cost)
|
||||
*cost = cost->round();
|
||||
cost = cost->round();
|
||||
}
|
||||
balance_pair_t round() const {
|
||||
balance_pair_t temp(*this);
|
||||
|
|
@ -959,7 +936,7 @@ class balance_pair_t
|
|||
balance_pair_t unround() {
|
||||
balance_pair_t temp(quantity.unround());
|
||||
if (cost)
|
||||
temp.cost = new balance_t(cost->unround());
|
||||
temp.cost = cost->unround();
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void read_binary_string(std::istream& in, string& str)
|
|||
in.read(buf, slen);
|
||||
buf[slen] = '\0';
|
||||
str = buf;
|
||||
delete[] buf;
|
||||
checked_array_delete(buf);
|
||||
}
|
||||
else if (len) {
|
||||
char buf[256];
|
||||
|
|
@ -374,7 +374,7 @@ account_t * read_binary_account(char *& data, journal_t * journal,
|
|||
// journal's own master account.
|
||||
|
||||
if (master && acct != master) {
|
||||
delete acct;
|
||||
checked_delete(acct);
|
||||
acct = master;
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +441,7 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
accounts = accounts_next = new account_t *[a_count];
|
||||
|
||||
assert(journal->master);
|
||||
delete journal->master;
|
||||
checked_delete(journal->master);
|
||||
journal->master = read_binary_account(data, journal, master);
|
||||
|
||||
if (read_binary_bool(data))
|
||||
|
|
@ -501,14 +501,14 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
(*c).second->precision = commodity->precision;
|
||||
(*c).second->flags = commodity->flags;
|
||||
if ((*c).second->smaller)
|
||||
delete (*c).second->smaller;
|
||||
checked_delete((*c).second->smaller);
|
||||
(*c).second->smaller = commodity->smaller;
|
||||
if ((*c).second->larger)
|
||||
delete (*c).second->larger;
|
||||
checked_delete((*c).second->larger);
|
||||
(*c).second->larger = commodity->larger;
|
||||
|
||||
*(base_commodities_next - 1) = (*c).second;
|
||||
delete commodity;
|
||||
checked_delete(commodity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -538,7 +538,7 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
commodity->symbol());
|
||||
|
||||
*(commodities_next - 1) = (*c).second;
|
||||
delete commodity;
|
||||
checked_delete(commodity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -583,9 +583,9 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
|
||||
// Clean up and return the number of entries read
|
||||
|
||||
delete[] accounts;
|
||||
delete[] commodities;
|
||||
delete[] data_pool;
|
||||
checked_array_delete(accounts);
|
||||
checked_array_delete(commodities);
|
||||
checked_array_delete(data_pool);
|
||||
|
||||
VALIDATE(journal->valid());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _DERIVE_H
|
||||
#define _DERIVE_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "xpath.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ class format_t
|
|||
|
||||
switch (kind) {
|
||||
case TEXT:
|
||||
delete chars;
|
||||
checked_delete(chars);
|
||||
break;
|
||||
case XPATH:
|
||||
delete xpath;
|
||||
checked_delete(xpath);
|
||||
break;
|
||||
case GROUP:
|
||||
delete format;
|
||||
checked_delete(format);
|
||||
break;
|
||||
default:
|
||||
assert(! chars);
|
||||
|
|
@ -75,7 +75,7 @@ class format_t
|
|||
for (std::list<element_t *>::iterator i = elements.begin();
|
||||
i != elements.end();
|
||||
i++)
|
||||
delete *i;
|
||||
checked_delete(*i);
|
||||
elements.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ void endElement(void *userData, const char *name)
|
|||
if (! parser->curr_journal->add_entry(parser->curr_entry)) {
|
||||
print_entry(std::cerr, *parser->curr_entry);
|
||||
parser->have_error = "The above entry does not balance";
|
||||
delete parser->curr_entry;
|
||||
checked_delete(parser->curr_entry);
|
||||
} else {
|
||||
parser->curr_entry->src_idx = parser->src_idx;
|
||||
parser->curr_entry->beg_pos = parser->beg_pos;
|
||||
|
|
@ -122,7 +122,7 @@ void endElement(void *userData, const char *name)
|
|||
xact->state = parser->curr_state;
|
||||
xact->amount = value;
|
||||
if (value != parser->curr_value)
|
||||
xact->cost = new amount_t(parser->curr_value);
|
||||
xact->cost = amount_t(parser->curr_value);
|
||||
|
||||
xact->beg_pos = parser->beg_pos;
|
||||
xact->beg_line = parser->beg_line;
|
||||
|
|
@ -291,10 +291,10 @@ bool gnucash_parser_t::test(std::istream& in) const
|
|||
return std::strncmp(buf, "<?xml", 5) == 0;
|
||||
}
|
||||
|
||||
unsigned int gnucash_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string * original_file)
|
||||
unsigned int gnucash_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>& original_file)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ unsigned int gnucash_parser_t::parse(std::istream& in,
|
|||
curr_state = transaction_t::UNCLEARED;
|
||||
|
||||
instreamp = ∈
|
||||
path = original_file ? *original_file : "<gnucash>";
|
||||
pathname = original_file ? *original_file : "<gnucash>";
|
||||
src_idx = journal->sources.size() - 1;
|
||||
|
||||
// GnuCash uses the USD commodity without defining it, which really
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ struct gnucash_parser_t : public parser_t
|
|||
std::istream * instreamp;
|
||||
unsigned int offset;
|
||||
XML_Parser parser;
|
||||
string path;
|
||||
path pathname;
|
||||
unsigned int src_idx;
|
||||
unsigned long beg_pos;
|
||||
unsigned long beg_line;
|
||||
|
|
@ -62,10 +62,10 @@ struct gnucash_parser_t : public parser_t
|
|||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL);
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>());
|
||||
|
||||
amount_t convert_number(const string& number, int * precision = NULL);
|
||||
};
|
||||
|
|
|
|||
113
src/journal.cc
113
src/journal.cc
|
|
@ -1,4 +1,5 @@
|
|||
#include "journal.h"
|
||||
#include "xpath.h"
|
||||
#include "mask.h"
|
||||
#if 0
|
||||
#ifdef USE_BOOST_PYTHON
|
||||
|
|
@ -15,21 +16,20 @@ bool transaction_t::use_effective_date = false;
|
|||
transaction_t::~transaction_t()
|
||||
{
|
||||
TRACE_DTOR(transaction_t);
|
||||
if (cost) delete cost;
|
||||
}
|
||||
|
||||
moment_t transaction_t::actual_date() const
|
||||
{
|
||||
if (! is_valid_moment(_date) && entry)
|
||||
if (! _date && entry)
|
||||
return entry->actual_date();
|
||||
return _date;
|
||||
return *_date;
|
||||
}
|
||||
|
||||
moment_t transaction_t::effective_date() const
|
||||
{
|
||||
if (! is_valid_moment(_date_eff) && entry)
|
||||
if (! _date_eff && entry)
|
||||
return entry->effective_date();
|
||||
return _date_eff;
|
||||
return *_date_eff;
|
||||
}
|
||||
|
||||
bool transaction_t::valid() const
|
||||
|
|
@ -44,15 +44,10 @@ bool transaction_t::valid() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (transactions_list::const_iterator i = entry->transactions.begin();
|
||||
i != entry->transactions.end();
|
||||
i++)
|
||||
if (*i == this) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (! found) {
|
||||
transactions_list::const_iterator i =
|
||||
std::find(entry->transactions.begin(),
|
||||
entry->transactions.end(), this);
|
||||
if (i == entry->transactions.end()) {
|
||||
DEBUG("ledger.validate", "transaction_t: ! found");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -62,7 +57,7 @@ bool transaction_t::valid() const
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! amount.valid()) {
|
||||
if (amount && ! amount->valid()) {
|
||||
DEBUG("ledger.validate", "transaction_t: ! amount.valid()");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -98,16 +93,16 @@ bool entry_base_t::finalize()
|
|||
// and the per-unit price of unpriced commodities.
|
||||
|
||||
value_t balance;
|
||||
bool no_amounts = true;
|
||||
bool saw_null = false;
|
||||
|
||||
bool no_amounts = true;
|
||||
bool saw_null = false;
|
||||
for (transactions_list::const_iterator x = transactions.begin();
|
||||
x != transactions.end();
|
||||
x++)
|
||||
if (! ((*x)->flags & TRANSACTION_VIRTUAL) ||
|
||||
((*x)->flags & TRANSACTION_BALANCE)) {
|
||||
amount_t * p = (*x)->cost ? (*x)->cost : &(*x)->amount;
|
||||
if (*p) {
|
||||
optional<amount_t>& p((*x)->cost ? (*x)->cost : (*x)->amount);
|
||||
if (p) {
|
||||
if (no_amounts) {
|
||||
balance = *p;
|
||||
no_amounts = false;
|
||||
|
|
@ -115,12 +110,13 @@ bool entry_base_t::finalize()
|
|||
balance += *p;
|
||||
}
|
||||
|
||||
if ((*x)->cost && (*x)->amount.commodity().annotated) {
|
||||
assert((*x)->amount);
|
||||
if ((*x)->cost && (*x)->amount->commodity().annotated) {
|
||||
annotated_commodity_t&
|
||||
ann_comm(static_cast<annotated_commodity_t&>
|
||||
((*x)->amount.commodity()));
|
||||
((*x)->amount->commodity()));
|
||||
if (ann_comm.price)
|
||||
balance += ann_comm.price * (*x)->amount.number() - *((*x)->cost);
|
||||
balance += *ann_comm.price * (*x)->amount->number() - *((*x)->cost);
|
||||
}
|
||||
} else {
|
||||
saw_null = true;
|
||||
|
|
@ -151,7 +147,8 @@ bool entry_base_t::finalize()
|
|||
if (! saw_null && balance && balance.type == value_t::BALANCE &&
|
||||
((balance_t *) balance.data)->amounts.size() == 2) {
|
||||
transactions_list::const_iterator x = transactions.begin();
|
||||
commodity_t& this_comm = (*x)->amount.commodity();
|
||||
assert((*x)->amount);
|
||||
commodity_t& this_comm = (*x)->amount->commodity();
|
||||
|
||||
amounts_map::const_iterator this_bal =
|
||||
((balance_t *) balance.data)->amounts.find(&this_comm);
|
||||
|
|
@ -165,22 +162,22 @@ bool entry_base_t::finalize()
|
|||
|
||||
for (; x != transactions.end(); x++) {
|
||||
if ((*x)->cost || ((*x)->flags & TRANSACTION_VIRTUAL) ||
|
||||
! (*x)->amount || (*x)->amount.commodity() != this_comm)
|
||||
! (*x)->amount || (*x)->amount->commodity() != this_comm)
|
||||
continue;
|
||||
|
||||
assert((*x)->amount);
|
||||
balance -= (*x)->amount;
|
||||
balance -= *(*x)->amount;
|
||||
|
||||
entry_t * entry = dynamic_cast<entry_t *>(this);
|
||||
|
||||
if ((*x)->amount.commodity() &&
|
||||
! (*x)->amount.commodity().annotated)
|
||||
(*x)->amount.annotate_commodity
|
||||
if ((*x)->amount->commodity() &&
|
||||
! (*x)->amount->commodity().annotated)
|
||||
(*x)->amount->annotate_commodity
|
||||
(per_unit_cost.abs(),
|
||||
entry ? entry->actual_date() : moment_t(),
|
||||
entry ? entry->code : "");
|
||||
entry ? entry->actual_date() : optional<moment_t>(),
|
||||
entry ? entry->code : optional<string>());
|
||||
|
||||
(*x)->cost = new amount_t(- (per_unit_cost * (*x)->amount.number()));
|
||||
(*x)->cost = - (per_unit_cost * (*x)->amount->number());
|
||||
balance += *(*x)->cost;
|
||||
}
|
||||
}
|
||||
|
|
@ -193,7 +190,7 @@ bool entry_base_t::finalize()
|
|||
for (transactions_list::const_iterator x = transactions.begin();
|
||||
x != transactions.end();
|
||||
x++) {
|
||||
if (! (*x)->amount.null() ||
|
||||
if ((*x)->amount ||
|
||||
(((*x)->flags & TRANSACTION_VIRTUAL) &&
|
||||
! ((*x)->flags & TRANSACTION_BALANCE)))
|
||||
continue;
|
||||
|
|
@ -246,7 +243,7 @@ bool entry_base_t::finalize()
|
|||
(*x)->amount = ((amount_t *) balance.data)->negate();
|
||||
(*x)->flags |= TRANSACTION_CALCULATED;
|
||||
|
||||
balance += (*x)->amount;
|
||||
balance += *(*x)->amount;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -326,6 +323,21 @@ bool entry_t::valid() const
|
|||
return true;
|
||||
}
|
||||
|
||||
auto_entry_t::auto_entry_t()
|
||||
{
|
||||
TRACE_CTOR(auto_entry_t, "");
|
||||
}
|
||||
|
||||
auto_entry_t::auto_entry_t(const string& _predicate)
|
||||
: predicate(new xml::xpath_t(_predicate))
|
||||
{
|
||||
TRACE_CTOR(auto_entry_t, "const string&");
|
||||
}
|
||||
|
||||
auto_entry_t::~auto_entry_t() {
|
||||
TRACE_DTOR(auto_entry_t);
|
||||
}
|
||||
|
||||
void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
|
||||
{
|
||||
transactions_list initial_xacts(entry.transactions.begin(),
|
||||
|
|
@ -335,19 +347,21 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
|
|||
i != initial_xacts.end();
|
||||
i++) {
|
||||
// jww (2006-09-10): Create a scope here based on entry
|
||||
if (predicate.calc((xml::node_t *) NULL)) {
|
||||
if (predicate->calc((xml::node_t *) NULL)) {
|
||||
for (transactions_list::iterator t = transactions.begin();
|
||||
t != transactions.end();
|
||||
t++) {
|
||||
amount_t amt;
|
||||
if (! (*t)->amount.commodity()) {
|
||||
assert((*t)->amount);
|
||||
if (! (*t)->amount->commodity()) {
|
||||
if (! post)
|
||||
continue;
|
||||
amt = (*i)->amount * (*t)->amount;
|
||||
assert((*i)->amount);
|
||||
amt = *(*i)->amount * *(*t)->amount;
|
||||
} else {
|
||||
if (post)
|
||||
continue;
|
||||
amt = (*t)->amount;
|
||||
amt = *(*t)->amount;
|
||||
}
|
||||
|
||||
account_t * account = (*t)->account;
|
||||
|
|
@ -371,7 +385,7 @@ account_t::~account_t()
|
|||
for (accounts_map::iterator i = accounts.begin();
|
||||
i != accounts.end();
|
||||
i++)
|
||||
delete (*i).second;
|
||||
checked_delete((*i).second);
|
||||
}
|
||||
|
||||
account_t * account_t::find_account(const string& name,
|
||||
|
|
@ -496,10 +510,10 @@ journal_t::~journal_t()
|
|||
TRACE_DTOR(journal_t);
|
||||
|
||||
assert(master);
|
||||
delete master;
|
||||
checked_delete(master);
|
||||
|
||||
if (document)
|
||||
delete document;
|
||||
checked_delete(document);
|
||||
|
||||
// Don't bother unhooking each entry's transactions from the
|
||||
// accounts they refer to, because all accounts are about to
|
||||
|
|
@ -509,7 +523,7 @@ journal_t::~journal_t()
|
|||
i++)
|
||||
if (! item_pool ||
|
||||
((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
|
||||
delete *i;
|
||||
checked_delete(*i);
|
||||
else
|
||||
(*i)->~entry_t();
|
||||
|
||||
|
|
@ -518,7 +532,7 @@ journal_t::~journal_t()
|
|||
i++)
|
||||
if (! item_pool ||
|
||||
((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
|
||||
delete *i;
|
||||
checked_delete(*i);
|
||||
else
|
||||
(*i)->~auto_entry_t();
|
||||
|
||||
|
|
@ -527,12 +541,12 @@ journal_t::~journal_t()
|
|||
i++)
|
||||
if (! item_pool ||
|
||||
((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
|
||||
delete *i;
|
||||
checked_delete(*i);
|
||||
else
|
||||
(*i)->~period_entry_t();
|
||||
|
||||
if (item_pool)
|
||||
delete[] item_pool;
|
||||
checked_array_delete(item_pool);
|
||||
}
|
||||
|
||||
bool journal_t::add_entry(entry_t * entry)
|
||||
|
|
@ -551,9 +565,12 @@ bool journal_t::add_entry(entry_t * entry)
|
|||
for (transactions_list::const_iterator i = entry->transactions.begin();
|
||||
i != entry->transactions.end();
|
||||
i++)
|
||||
if ((*i)->cost && (*i)->amount)
|
||||
(*i)->amount.commodity().add_price(entry->date(),
|
||||
*(*i)->cost / (*i)->amount.number());
|
||||
if ((*i)->cost) {
|
||||
assert((*i)->amount);
|
||||
assert(*(*i)->amount);
|
||||
(*i)->amount->commodity().add_price(entry->date(),
|
||||
*(*i)->cost / (*i)->amount->number());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -614,7 +631,7 @@ void print_entry(std::ostream& out, const entry_base_t& entry_base,
|
|||
}
|
||||
else if (const auto_entry_t * entry =
|
||||
dynamic_cast<const auto_entry_t *>(&entry_base)) {
|
||||
out << "= " << entry->predicate.expr << '\n';
|
||||
out << "= " << entry->predicate->expr << '\n';
|
||||
print_format = prefix + " %-34A %12o\n";
|
||||
}
|
||||
else if (const period_entry_t * entry =
|
||||
|
|
|
|||
185
src/journal.h
185
src/journal.h
|
|
@ -1,10 +1,20 @@
|
|||
#ifndef _JOURNAL_H
|
||||
#define _JOURNAL_H
|
||||
|
||||
#include "xpath.h"
|
||||
#include "amount.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
namespace xml {
|
||||
class document_t;
|
||||
class xpath_t;
|
||||
|
||||
class transaction_node_t;
|
||||
class entry_node_t;
|
||||
class account_node_t;
|
||||
class journal_node_t;
|
||||
};
|
||||
|
||||
// These flags persist with the object
|
||||
#define TRANSACTION_NORMAL 0x0000
|
||||
#define TRANSACTION_VIRTUAL 0x0001
|
||||
|
|
@ -21,47 +31,48 @@ class transaction_t
|
|||
public:
|
||||
enum state_t { UNCLEARED, CLEARED, PENDING };
|
||||
|
||||
entry_t * entry;
|
||||
moment_t _date;
|
||||
moment_t _date_eff;
|
||||
account_t * account;
|
||||
amount_t amount;
|
||||
string amount_expr;
|
||||
amount_t * cost;
|
||||
string cost_expr;
|
||||
state_t state;
|
||||
unsigned short flags;
|
||||
string note;
|
||||
unsigned long beg_pos;
|
||||
unsigned long beg_line;
|
||||
unsigned long end_pos;
|
||||
unsigned long end_line;
|
||||
entry_t * entry;
|
||||
optional<moment_t> _date;
|
||||
optional<moment_t> _date_eff;
|
||||
account_t * account;
|
||||
optional<amount_t> amount;
|
||||
optional<string> amount_expr;
|
||||
optional<amount_t> cost;
|
||||
optional<string> cost_expr;
|
||||
state_t state;
|
||||
unsigned short flags;
|
||||
optional<string> note;
|
||||
unsigned long beg_pos;
|
||||
unsigned long beg_line;
|
||||
unsigned long end_pos;
|
||||
unsigned long end_line;
|
||||
|
||||
mutable void * data;
|
||||
typedef xml::transaction_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
static bool use_effective_date;
|
||||
|
||||
transaction_t(account_t * _account = NULL)
|
||||
: entry(NULL), account(_account), cost(NULL),
|
||||
state(UNCLEARED), flags(TRANSACTION_NORMAL),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
|
||||
explicit transaction_t(account_t * _account = NULL)
|
||||
: entry(NULL), account(_account), state(UNCLEARED),
|
||||
flags(TRANSACTION_NORMAL), beg_pos(0), beg_line(0),
|
||||
end_pos(0), end_line(0), data(NULL) {
|
||||
TRACE_CTOR(transaction_t, "account_t *");
|
||||
}
|
||||
transaction_t(account_t * _account,
|
||||
const amount_t& _amount,
|
||||
unsigned int _flags = TRANSACTION_NORMAL,
|
||||
const string& _note = "")
|
||||
: entry(NULL), account(_account), amount(_amount), cost(NULL),
|
||||
state(UNCLEARED), flags(_flags),
|
||||
note(_note), beg_pos(0), beg_line(0), end_pos(0), end_line(0),
|
||||
data(NULL) {
|
||||
TRACE_CTOR(transaction_t, "account_t *, const amount_t&, unsigned int, const string&");
|
||||
}
|
||||
transaction_t(const transaction_t& xact)
|
||||
: entry(xact.entry), account(xact.account), amount(xact.amount),
|
||||
cost(xact.cost ? new amount_t(*xact.cost) : NULL),
|
||||
state(xact.state), flags(xact.flags), note(xact.note),
|
||||
explicit transaction_t(account_t * _account,
|
||||
const amount_t& _amount,
|
||||
unsigned int _flags = TRANSACTION_NORMAL,
|
||||
const optional<string> _note = optional<string>())
|
||||
: entry(NULL), account(_account), amount(_amount),
|
||||
state(UNCLEARED), flags(_flags), note(_note),
|
||||
beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
|
||||
TRACE_CTOR(transaction_t,
|
||||
"account_t *, const amount_t&, unsigned int, const string&");
|
||||
}
|
||||
explicit transaction_t(const transaction_t& xact)
|
||||
: entry(xact.entry), account(xact.account), amount(xact.amount),
|
||||
cost(xact.cost), state(xact.state), flags(xact.flags), note(xact.note),
|
||||
beg_pos(xact.beg_pos), beg_line(xact.beg_line),
|
||||
end_pos(xact.end_pos), end_line(xact.end_line), data(NULL) {
|
||||
TRACE_CTOR(transaction_t, "copy");
|
||||
}
|
||||
~transaction_t();
|
||||
|
|
@ -75,13 +86,6 @@ class transaction_t
|
|||
return actual_date();
|
||||
}
|
||||
|
||||
bool operator==(const transaction_t& xact) {
|
||||
return this == &xact;
|
||||
}
|
||||
bool operator!=(const transaction_t& xact) {
|
||||
return ! (*this == xact);
|
||||
}
|
||||
|
||||
bool valid() const;
|
||||
};
|
||||
|
||||
|
|
@ -130,7 +134,7 @@ class entry_base_t
|
|||
i != transactions.end();
|
||||
i++)
|
||||
if (! ((*i)->flags & TRANSACTION_BULK_ALLOC))
|
||||
delete *i;
|
||||
checked_delete(*i);
|
||||
else
|
||||
(*i)->~transaction_t();
|
||||
}
|
||||
|
|
@ -152,12 +156,13 @@ class entry_base_t
|
|||
class entry_t : public entry_base_t
|
||||
{
|
||||
public:
|
||||
moment_t _date;
|
||||
moment_t _date_eff;
|
||||
string code;
|
||||
string payee;
|
||||
moment_t _date;
|
||||
optional<moment_t> _date_eff;
|
||||
optional<string> code;
|
||||
string payee;
|
||||
|
||||
mutable void * data;
|
||||
typedef xml::entry_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
entry_t() : data(NULL) {
|
||||
TRACE_CTOR(entry_t, "");
|
||||
|
|
@ -172,9 +177,7 @@ class entry_t : public entry_base_t
|
|||
return _date;
|
||||
}
|
||||
moment_t effective_date() const {
|
||||
if (! is_valid_moment(_date_eff))
|
||||
return _date;
|
||||
return _date_eff;
|
||||
return _date_eff ? *_date_eff : _date;
|
||||
}
|
||||
moment_t date() const {
|
||||
if (transaction_t::use_effective_date)
|
||||
|
|
@ -184,7 +187,6 @@ class entry_t : public entry_base_t
|
|||
}
|
||||
|
||||
virtual void add_transaction(transaction_t * xact);
|
||||
|
||||
virtual bool valid() const;
|
||||
|
||||
bool get_state(transaction_t::state_t * state) const;
|
||||
|
|
@ -218,19 +220,11 @@ DECLARE_EXCEPTION(balance_error);
|
|||
class auto_entry_t : public entry_base_t
|
||||
{
|
||||
public:
|
||||
xml::xpath_t predicate;
|
||||
scoped_ptr<xml::xpath_t> predicate;
|
||||
|
||||
auto_entry_t() {
|
||||
TRACE_CTOR(auto_entry_t, "");
|
||||
}
|
||||
auto_entry_t(const string& _predicate)
|
||||
: predicate(_predicate) {
|
||||
TRACE_CTOR(auto_entry_t, "const string&");
|
||||
}
|
||||
|
||||
virtual ~auto_entry_t() {
|
||||
TRACE_DTOR(auto_entry_t);
|
||||
}
|
||||
auto_entry_t();
|
||||
auto_entry_t(const string& _predicate);
|
||||
virtual ~auto_entry_t();
|
||||
|
||||
virtual void extend_entry(entry_base_t& entry, bool post);
|
||||
virtual bool valid() const {
|
||||
|
|
@ -248,8 +242,8 @@ struct auto_entry_finalizer_t : public entry_finalizer_t {
|
|||
class period_entry_t : public entry_base_t
|
||||
{
|
||||
public:
|
||||
interval_t period;
|
||||
string period_string;
|
||||
interval_t period;
|
||||
string period_string;
|
||||
|
||||
period_entry_t() {
|
||||
TRACE_CTOR(period_entry_t, "");
|
||||
|
|
@ -281,33 +275,31 @@ class account_t
|
|||
public:
|
||||
typedef unsigned long ident_t;
|
||||
|
||||
journal_t * journal;
|
||||
account_t * parent;
|
||||
string name;
|
||||
string note;
|
||||
unsigned short depth;
|
||||
accounts_map accounts;
|
||||
journal_t * journal;
|
||||
account_t * parent;
|
||||
string name;
|
||||
optional<string> note;
|
||||
unsigned short depth;
|
||||
accounts_map accounts;
|
||||
|
||||
typedef xml::account_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
mutable void * data;
|
||||
mutable ident_t ident;
|
||||
mutable string _fullname;
|
||||
|
||||
account_t(account_t * _parent = NULL,
|
||||
const string& _name = "",
|
||||
const string& _note = "")
|
||||
const optional<string> _note = optional<string>())
|
||||
: parent(_parent), name(_name), note(_note),
|
||||
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
|
||||
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
|
||||
}
|
||||
~account_t();
|
||||
|
||||
bool operator==(const account_t& account) {
|
||||
return this == &account;
|
||||
operator string() const {
|
||||
return fullname();
|
||||
}
|
||||
bool operator!=(const account_t& account) {
|
||||
return ! (*this == account);
|
||||
}
|
||||
|
||||
string fullname() const;
|
||||
|
||||
void add_account(account_t * acct) {
|
||||
|
|
@ -322,10 +314,6 @@ class account_t
|
|||
|
||||
account_t * find_account(const string& name, bool auto_create = true);
|
||||
|
||||
operator string() const {
|
||||
return fullname();
|
||||
}
|
||||
|
||||
bool valid() const;
|
||||
|
||||
friend class journal_t;
|
||||
|
|
@ -372,6 +360,7 @@ bool run_hooks(std::list<T>& list, Data& item, bool post) {
|
|||
typedef std::list<entry_t *> entries_list;
|
||||
typedef std::list<auto_entry_t *> auto_entries_list;
|
||||
typedef std::list<period_entry_t *> period_entries_list;
|
||||
typedef std::list<path> path_list;
|
||||
typedef std::list<string> strings_list;
|
||||
|
||||
class session_t;
|
||||
|
|
@ -379,21 +368,24 @@ class session_t;
|
|||
class journal_t
|
||||
{
|
||||
public:
|
||||
session_t * session;
|
||||
account_t * master;
|
||||
account_t * basket;
|
||||
entries_list entries;
|
||||
strings_list sources;
|
||||
string price_db;
|
||||
char * item_pool;
|
||||
char * item_pool_end;
|
||||
session_t * session;
|
||||
account_t * master;
|
||||
account_t * basket;
|
||||
entries_list entries;
|
||||
path_list sources;
|
||||
optional<path> price_db;
|
||||
char * item_pool;
|
||||
char * item_pool_end;
|
||||
|
||||
// This is used for dynamically representing the journal data as an
|
||||
// XML tree, to facilitate transformations without modifying any of
|
||||
// the underlying structures (the transformers modify the XML tree
|
||||
// -- perhaps even adding, changing or deleting nodes -- but they do
|
||||
// not affect the basic data parsed from the journal file).
|
||||
xml::document_t * document;
|
||||
mutable xml::document_t * document;
|
||||
|
||||
typedef xml::journal_node_t node_type;
|
||||
mutable node_type * data;
|
||||
|
||||
auto_entries_list auto_entries;
|
||||
period_entries_list period_entries;
|
||||
|
|
@ -410,13 +402,6 @@ class journal_t
|
|||
}
|
||||
~journal_t();
|
||||
|
||||
bool operator==(const journal_t& journal) {
|
||||
return this == &journal;
|
||||
}
|
||||
bool operator!=(const journal_t& journal) {
|
||||
return ! (*this == journal);
|
||||
}
|
||||
|
||||
void add_account(account_t * acct) {
|
||||
master->add_account(acct);
|
||||
acct->journal = this;
|
||||
|
|
|
|||
74
src/main.cc
74
src/main.cc
|
|
@ -1,15 +1,15 @@
|
|||
#include "utils.h"
|
||||
#include "option.h"
|
||||
#include "gnucash.h"
|
||||
#include "qif.h"
|
||||
#include "ofx.h"
|
||||
|
||||
#if defined(USE_BOOST_PYTHON)
|
||||
#include <pyledger.h>
|
||||
#else
|
||||
#include <ledger.h>
|
||||
#endif
|
||||
|
||||
#include "acconf.h"
|
||||
#include "option.h"
|
||||
#include "gnucash.h"
|
||||
#include "qif.h"
|
||||
#include "ofx.h"
|
||||
|
||||
#ifdef HAVE_UNIX_PIPES
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -33,7 +33,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
|
||||
// Handle the command-line arguments
|
||||
|
||||
std::list<string> args;
|
||||
strings_list args;
|
||||
process_arguments(argc - 1, argv + 1, false, report, args);
|
||||
|
||||
if (args.empty()) {
|
||||
|
|
@ -44,10 +44,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
}
|
||||
strings_list::iterator arg = args.begin();
|
||||
|
||||
if (session.cache_file == "<none>")
|
||||
if (! session.cache_file)
|
||||
session.use_cache = false;
|
||||
else
|
||||
session.use_cache = session.data_file.empty() && session.price_db.empty();
|
||||
session.use_cache = ! session.data_file.empty() && session.price_db;
|
||||
|
||||
DEBUG("ledger.session.cache", "1. use_cache = " << session.use_cache);
|
||||
|
||||
|
|
@ -58,25 +58,25 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
TRACE_FINISH(environment, 1);
|
||||
|
||||
const char * p = std::getenv("HOME");
|
||||
string home = p ? p : "";
|
||||
path home = p ? p : "";
|
||||
|
||||
if (session.init_file.empty())
|
||||
session.init_file = home + "/.ledgerrc";
|
||||
if (session.price_db.empty())
|
||||
session.price_db = home + "/.pricedb";
|
||||
if (! session.init_file)
|
||||
session.init_file = home / ".ledgerrc";
|
||||
if (! session.price_db)
|
||||
session.price_db = home / ".pricedb";
|
||||
|
||||
if (session.cache_file.empty())
|
||||
session.cache_file = home + "/.ledger-cache";
|
||||
if (! session.cache_file)
|
||||
session.cache_file = home / ".ledger-cache";
|
||||
|
||||
if (session.data_file == session.cache_file)
|
||||
if (session.data_file == *session.cache_file)
|
||||
session.use_cache = false;
|
||||
|
||||
DEBUG("ledger.session.cache", "2. use_cache = " << session.use_cache);
|
||||
|
||||
INFO("Initialization file is " << session.init_file);
|
||||
INFO("Price database is " << session.price_db);
|
||||
INFO("Binary cache is " << session.cache_file);
|
||||
INFO("Journal file is " << session.data_file);
|
||||
INFO("Initialization file is " << session.init_file->string());
|
||||
INFO("Price database is " << session.price_db->string());
|
||||
INFO("Binary cache is " << session.cache_file->string());
|
||||
INFO("Journal file is " << session.data_file.string());
|
||||
|
||||
if (! session.use_cache)
|
||||
INFO("Binary cache mechanism will not be used");
|
||||
|
|
@ -197,11 +197,11 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
#endif
|
||||
std::ostream * out = &std::cout;
|
||||
|
||||
if (! report->output_file.empty()) {
|
||||
out = new std::ofstream(report->output_file.c_str());
|
||||
if (report->output_file) {
|
||||
out = new ofstream(*report->output_file);
|
||||
}
|
||||
#ifdef HAVE_UNIX_PIPES
|
||||
else if (! report->pager.empty()) {
|
||||
else if (report->pager) {
|
||||
status = pipe(pfd);
|
||||
if (status == -1)
|
||||
throw_(std::logic_error, "Failed to create pipe");
|
||||
|
|
@ -227,13 +227,8 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
// Find command name: its the substring starting right of the
|
||||
// rightmost '/' character in the pager pathname. See manpage
|
||||
// for strrchr.
|
||||
arg0 = std::strrchr(report->pager.c_str(), '/');
|
||||
if (arg0)
|
||||
arg0++;
|
||||
else
|
||||
arg0 = report->pager.c_str(); // No slashes in pager.
|
||||
|
||||
execlp(report->pager.c_str(), arg0, (char *)0);
|
||||
execlp(report->pager->native_file_string().c_str(),
|
||||
basename(*report->pager).c_str(), (char *)0);
|
||||
perror("execl");
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -352,11 +347,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
|
||||
// Write out the binary cache, if need be
|
||||
|
||||
if (session.use_cache && session.cache_dirty &&
|
||||
! session.cache_file.empty()) {
|
||||
if (session.use_cache && session.cache_dirty && session.cache_file) {
|
||||
TRACE_START(binary_cache, 1, "Wrote binary journal file");
|
||||
|
||||
std::ofstream stream(session.cache_file.c_str());
|
||||
ofstream stream(*session.cache_file);
|
||||
#if 0
|
||||
write_binary_journal(stream, journal);
|
||||
#endif
|
||||
|
|
@ -367,15 +361,15 @@ static int read_and_report(report_t * report, int argc, char * argv[],
|
|||
#if defined(FREE_MEMORY)
|
||||
// Cleanup memory -- if this is a beta or development build.
|
||||
|
||||
if (! report->output_file.empty())
|
||||
delete out;
|
||||
if (report->output_file)
|
||||
checked_delete(out);
|
||||
#endif
|
||||
|
||||
// If the user specified a pager, wait for it to exit now
|
||||
|
||||
#ifdef HAVE_UNIX_PIPES
|
||||
if (report->output_file.empty() && ! report->pager.empty()) {
|
||||
delete out;
|
||||
if (! report->output_file && report->pager) {
|
||||
checked_delete(out);
|
||||
close(pfd[1]);
|
||||
|
||||
// Wait for child to finish
|
||||
|
|
@ -457,7 +451,7 @@ int main(int argc, char * argv[], char * envp[])
|
|||
err->context.push_front(new error_context(""));
|
||||
err->reveal_context(std::cerr, "Error");
|
||||
std::cerr << err->what() << std::endl;
|
||||
delete err;
|
||||
checked_delete(err);
|
||||
}
|
||||
catch (fatal * err) {
|
||||
std::cout.flush();
|
||||
|
|
@ -467,7 +461,7 @@ int main(int argc, char * argv[], char * envp[])
|
|||
err->context.push_front(new error_context(""));
|
||||
err->reveal_context(std::cerr, "Fatal");
|
||||
std::cerr << err->what() << std::endl;
|
||||
delete err;
|
||||
checked_delete(err);
|
||||
}
|
||||
#endif
|
||||
catch (const std::exception& err) {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data,
|
|||
// jww (2005-02-09): uncomment
|
||||
have_error = "The above entry does not balance";
|
||||
#endif
|
||||
delete entry;
|
||||
checked_delete(entry);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
|
|||
}
|
||||
process_option(def, scope, value);
|
||||
|
||||
delete *o;
|
||||
checked_delete(*o);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ class parser_t
|
|||
|
||||
virtual bool test(std::istream& in) const = 0;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL) = 0;
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>()) = 0;
|
||||
};
|
||||
|
||||
DECLARE_EXCEPTION(parse_error);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct python_run
|
||||
{
|
||||
object result;
|
||||
|
|
|
|||
|
|
@ -12,14 +12,12 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
class python_interpreter_t : public xml::xpath_t::scope_t
|
||||
{
|
||||
handle<> mmodule;
|
||||
boost::python::handle<> mmodule;
|
||||
|
||||
public:
|
||||
dict nspace;
|
||||
boost::python::dict nspace;
|
||||
|
||||
python_interpreter_t(xml::xpath_t::scope_t * parent);
|
||||
|
||||
|
|
@ -27,7 +25,7 @@ class python_interpreter_t : public xml::xpath_t::scope_t
|
|||
Py_Finalize();
|
||||
}
|
||||
|
||||
object import(const string& name);
|
||||
boost::python::object import(const string& name);
|
||||
|
||||
enum py_eval_mode_t {
|
||||
PY_EVAL_EXPR,
|
||||
|
|
@ -35,18 +33,21 @@ class python_interpreter_t : public xml::xpath_t::scope_t
|
|||
PY_EVAL_MULTI
|
||||
};
|
||||
|
||||
object eval(std::istream& in, py_eval_mode_t mode = PY_EVAL_EXPR);
|
||||
object eval(const string& str, py_eval_mode_t mode = PY_EVAL_EXPR);
|
||||
object eval(const char * c_str, py_eval_mode_t mode = PY_EVAL_EXPR) {
|
||||
boost::python::object eval(std::istream& in,
|
||||
py_eval_mode_t mode = PY_EVAL_EXPR);
|
||||
boost::python::object eval(const string& str,
|
||||
py_eval_mode_t mode = PY_EVAL_EXPR);
|
||||
boost::python::object eval(const char * c_str,
|
||||
py_eval_mode_t mode = PY_EVAL_EXPR) {
|
||||
string str(c_str);
|
||||
return eval(str, mode);
|
||||
}
|
||||
|
||||
class functor_t : public xml::xpath_t::functor_t {
|
||||
protected:
|
||||
object func;
|
||||
public:
|
||||
functor_t(const string& name, object _func)
|
||||
protected:
|
||||
boost::python::object func;
|
||||
public:
|
||||
functor_t(const string& name, boost::python::object _func)
|
||||
: xml::xpath_t::functor_t(name), func(_func) {}
|
||||
|
||||
virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
|
||||
|
|
@ -58,7 +59,7 @@ class python_interpreter_t : public xml::xpath_t::scope_t
|
|||
}
|
||||
|
||||
virtual xml::xpath_t::op_t * lookup(const string& name) {
|
||||
object func = eval(name);
|
||||
boost::python::object func = eval(name);
|
||||
if (! func)
|
||||
return parent ? parent->lookup(name) : NULL;
|
||||
return xml::xpath_t::wrap_functor(new functor_t(name, func));
|
||||
|
|
@ -66,8 +67,7 @@ class python_interpreter_t : public xml::xpath_t::scope_t
|
|||
|
||||
class lambda_t : public functor_t {
|
||||
public:
|
||||
lambda_t(object code) : functor_t("<lambda>", code) {}
|
||||
|
||||
lambda_t(boost::python::object code) : functor_t("<lambda>", code) {}
|
||||
virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
16
src/qif.cc
16
src/qif.cc
|
|
@ -6,7 +6,7 @@ namespace ledger {
|
|||
#define MAX_LINE 1024
|
||||
|
||||
static char line[MAX_LINE + 1];
|
||||
static string pathname;
|
||||
static path pathname;
|
||||
static unsigned int src_idx;
|
||||
static unsigned int linenum;
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ bool qif_parser_t::test(std::istream& in) const
|
|||
unsigned int qif_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string *)
|
||||
const optional<path>&)
|
||||
{
|
||||
std::auto_ptr<entry_t> entry;
|
||||
std::auto_ptr<amount_t> amount;
|
||||
|
|
@ -104,16 +104,16 @@ unsigned int qif_parser_t::parse(std::istream& in,
|
|||
case '$': {
|
||||
SET_BEG_POS_AND_LINE();
|
||||
get_line(in);
|
||||
xact->amount.parse(line);
|
||||
xact->amount = amount_t(line);
|
||||
|
||||
unsigned char flags = xact->amount.commodity().flags();
|
||||
unsigned char prec = xact->amount.commodity().precision();
|
||||
unsigned char flags = xact->amount->commodity().flags();
|
||||
unsigned char prec = xact->amount->commodity().precision();
|
||||
|
||||
if (! def_commodity) {
|
||||
def_commodity = commodity_t::find_or_create("$");
|
||||
assert(def_commodity);
|
||||
}
|
||||
xact->amount.set_commodity(*def_commodity);
|
||||
xact->amount->set_commodity(*def_commodity);
|
||||
|
||||
def_commodity->add_flags(flags);
|
||||
if (prec > def_commodity->precision())
|
||||
|
|
@ -121,7 +121,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
|
|||
|
||||
if (c == '$') {
|
||||
saw_splits = true;
|
||||
xact->amount.in_place_negate();
|
||||
xact->amount->in_place_negate();
|
||||
} else {
|
||||
total = xact;
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
|
|||
|
||||
if (total && saw_category) {
|
||||
if (! saw_splits)
|
||||
total->amount.in_place_negate(); // negate, to show correct flow
|
||||
total->amount->in_place_negate(); // negate, to show correct flow
|
||||
else
|
||||
total->account = other;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ class qif_parser_t : public parser_t
|
|||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL);
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>());
|
||||
};
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -117,8 +117,10 @@ static void scan_for_transactions(std::ostream& out, const xml::node_t * node)
|
|||
<< std::setw(21) << std::left
|
||||
<< abbreviate(xact->account->fullname(), 21,
|
||||
ABBREVIATE, true) << ' '
|
||||
<< std::setw(12) << std::right
|
||||
<< xact->amount << '\n';
|
||||
<< std::setw(12) << std::right;
|
||||
if (xact->amount)
|
||||
out << *xact->amount;
|
||||
out << '\n';
|
||||
} else {
|
||||
scan_for_transactions(out, child);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,14 @@ namespace ledger {
|
|||
report_t::~report_t()
|
||||
{
|
||||
TRACE_DTOR(report_t);
|
||||
for (std::list<transform_t *>::const_iterator i = transforms.begin();
|
||||
i != transforms.end();
|
||||
i++)
|
||||
delete *i;
|
||||
}
|
||||
|
||||
void report_t::apply_transforms(xml::document_t * document)
|
||||
{
|
||||
for (std::list<transform_t *>::const_iterator i = transforms.begin();
|
||||
for (ptr_list<transform_t>::iterator i = transforms.begin();
|
||||
i != transforms.end();
|
||||
i++)
|
||||
(*i)->execute(document);
|
||||
i->execute(document);
|
||||
}
|
||||
|
||||
void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
|
||||
|
|
|
|||
14
src/report.h
14
src/report.h
|
|
@ -11,16 +11,16 @@ typedef std::list<string> strings_list;
|
|||
class report_t : public xml::xpath_t::scope_t
|
||||
{
|
||||
public:
|
||||
string output_file;
|
||||
string format_string;
|
||||
string amount_expr;
|
||||
string total_expr;
|
||||
string date_output_format;
|
||||
optional<path> output_file;
|
||||
string format_string;
|
||||
string amount_expr;
|
||||
string total_expr;
|
||||
string date_output_format;
|
||||
|
||||
unsigned long budget_flags;
|
||||
|
||||
string account;
|
||||
string pager;
|
||||
optional<path> pager;
|
||||
|
||||
bool show_totals;
|
||||
bool raw_mode;
|
||||
|
|
@ -28,7 +28,7 @@ class report_t : public xml::xpath_t::scope_t
|
|||
session_t * session;
|
||||
transform_t * last_transform;
|
||||
|
||||
std::list<transform_t *> transforms;
|
||||
ptr_list<transform_t> transforms;
|
||||
|
||||
report_t(session_t * _session)
|
||||
: xml::xpath_t::scope_t(_session),
|
||||
|
|
|
|||
|
|
@ -2,57 +2,58 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
unsigned int session_t::read_journal(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string * original_file)
|
||||
unsigned int session_t::read_journal(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>& original)
|
||||
{
|
||||
if (! master)
|
||||
master = journal->master;
|
||||
|
||||
for (std::list<parser_t *>::iterator i = parsers.begin();
|
||||
for (ptr_list<parser_t>::iterator i = parsers.begin();
|
||||
i != parsers.end();
|
||||
i++)
|
||||
if ((*i)->test(in))
|
||||
return (*i)->parse(in, journal, master, original_file);
|
||||
if (i->test(in))
|
||||
return i->parse(in, journal, master, original);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int session_t::read_journal(const string& pathname,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string * original_file)
|
||||
unsigned int session_t::read_journal(const path& pathname,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>& original)
|
||||
{
|
||||
journal->sources.push_back(pathname);
|
||||
|
||||
if (access(pathname.c_str(), R_OK) == -1)
|
||||
if (! exists(pathname))
|
||||
throw filesystem_error(BOOST_CURRENT_FUNCTION, pathname,
|
||||
"Cannot read file");
|
||||
|
||||
if (! original_file)
|
||||
original_file = &pathname;
|
||||
|
||||
std::ifstream stream(pathname.c_str());
|
||||
return read_journal(stream, journal, master, original_file);
|
||||
ifstream stream(pathname);
|
||||
return read_journal(stream, journal, master,
|
||||
original ? original : pathname);
|
||||
}
|
||||
|
||||
void session_t::read_init()
|
||||
{
|
||||
if (init_file.empty())
|
||||
if (! init_file)
|
||||
return;
|
||||
|
||||
if (access(init_file.c_str(), R_OK) == -1)
|
||||
throw filesystem_error(BOOST_CURRENT_FUNCTION, init_file,
|
||||
if (! exists(*init_file))
|
||||
throw filesystem_error(BOOST_CURRENT_FUNCTION, *init_file,
|
||||
"Cannot read init file");
|
||||
|
||||
std::ifstream init(init_file.c_str());
|
||||
ifstream init(*init_file);
|
||||
|
||||
// jww (2006-09-15): Read initialization options here!
|
||||
}
|
||||
|
||||
journal_t * session_t::read_data(const string& master_account)
|
||||
{
|
||||
if (data_file.empty())
|
||||
throw_(parse_error, "No journal file was specified (please use -f)");
|
||||
|
||||
TRACE_START(parser, 1, "Parsing journal file");
|
||||
|
||||
journal_t * journal = new_journal();
|
||||
|
|
@ -63,50 +64,55 @@ journal_t * session_t::read_data(const string& master_account)
|
|||
|
||||
DEBUG("ledger.cache", "3. use_cache = " << use_cache);
|
||||
|
||||
if (use_cache && ! cache_file.empty() &&
|
||||
! data_file.empty()) {
|
||||
DEBUG("ledger.cache", "using_cache " << cache_file);
|
||||
if (use_cache && cache_file) {
|
||||
DEBUG("ledger.cache", "using_cache " << cache_file->string());
|
||||
cache_dirty = true;
|
||||
if (access(cache_file.c_str(), R_OK) != -1) {
|
||||
std::ifstream stream(cache_file.c_str());
|
||||
if (exists(*cache_file)) {
|
||||
ifstream stream(*cache_file);
|
||||
|
||||
optional<path> price_db_orig = journal->price_db;
|
||||
try {
|
||||
journal->price_db = price_db;
|
||||
|
||||
entry_count += read_journal(stream, journal, NULL, data_file);
|
||||
if (entry_count > 0)
|
||||
cache_dirty = false;
|
||||
|
||||
string price_db_orig = journal->price_db;
|
||||
journal->price_db = price_db;
|
||||
entry_count += read_journal(stream, journal, NULL,
|
||||
&data_file);
|
||||
if (entry_count > 0)
|
||||
cache_dirty = false;
|
||||
else
|
||||
journal->price_db = price_db_orig;
|
||||
}
|
||||
catch (...) {
|
||||
journal->price_db = price_db_orig;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry_count == 0 && ! data_file.empty()) {
|
||||
if (entry_count == 0) {
|
||||
account_t * acct = NULL;
|
||||
if (! master_account.empty())
|
||||
acct = journal->find_account(master_account);
|
||||
|
||||
journal->price_db = price_db;
|
||||
if (! journal->price_db.empty() &&
|
||||
access(journal->price_db.c_str(), R_OK) != -1) {
|
||||
if (read_journal(journal->price_db, journal)) {
|
||||
if (journal->price_db && exists(*journal->price_db)) {
|
||||
if (read_journal(*journal->price_db, journal)) {
|
||||
throw_(parse_error, "Entries not allowed in price history file");
|
||||
} else {
|
||||
DEBUG("ledger.cache", "read price database " << journal->price_db);
|
||||
DEBUG("ledger.cache",
|
||||
"read price database " << journal->price_db->string());
|
||||
journal->sources.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("ledger.cache", "rejected cache, parsing " << data_file);
|
||||
DEBUG("ledger.cache", "rejected cache, parsing " << data_file.string());
|
||||
if (data_file == "-") {
|
||||
use_cache = false;
|
||||
journal->sources.push_back("<stdin>");
|
||||
entry_count += read_journal(std::cin, journal, acct);
|
||||
}
|
||||
else if (access(data_file.c_str(), R_OK) != -1) {
|
||||
else if (exists(data_file)) {
|
||||
entry_count += read_journal(data_file, journal, acct);
|
||||
if (! journal->price_db.empty())
|
||||
journal->sources.push_back(journal->price_db);
|
||||
if (journal->price_db)
|
||||
journal->sources.push_back(*journal->price_db);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ namespace ledger {
|
|||
class session_t : public xml::xpath_t::scope_t
|
||||
{
|
||||
public:
|
||||
string init_file;
|
||||
string data_file;
|
||||
string cache_file;
|
||||
string price_db;
|
||||
path data_file;
|
||||
optional<path> init_file;
|
||||
optional<path> cache_file;
|
||||
optional<path> price_db;
|
||||
|
||||
string register_format;
|
||||
string wide_register_format;
|
||||
|
|
@ -42,8 +42,8 @@ class session_t : public xml::xpath_t::scope_t
|
|||
bool ansi_codes;
|
||||
bool ansi_invert;
|
||||
|
||||
std::list<journal_t *> journals;
|
||||
std::list<parser_t *> parsers;
|
||||
ptr_list<journal_t> journals;
|
||||
ptr_list<parser_t> parsers;
|
||||
|
||||
session_t(xml::xpath_t::scope_t * _parent = NULL) :
|
||||
xml::xpath_t::scope_t(_parent),
|
||||
|
|
@ -96,16 +96,6 @@ class session_t : public xml::xpath_t::scope_t
|
|||
|
||||
virtual ~session_t() {
|
||||
TRACE_DTOR(session_t);
|
||||
|
||||
for (std::list<journal_t *>::iterator i = journals.begin();
|
||||
i != journals.end();
|
||||
i++)
|
||||
delete *i;
|
||||
|
||||
for (std::list<parser_t *>::iterator i = parsers.begin();
|
||||
i != parsers.end();
|
||||
i++)
|
||||
delete *i;
|
||||
}
|
||||
|
||||
journal_t * new_journal() {
|
||||
|
|
@ -114,19 +104,26 @@ class session_t : public xml::xpath_t::scope_t
|
|||
return journal;
|
||||
}
|
||||
void close_journal(journal_t * journal) {
|
||||
journals.remove(journal);
|
||||
delete journal;
|
||||
for (ptr_list<journal_t>::iterator i = journals.begin();
|
||||
i != journals.end();
|
||||
i++)
|
||||
if (&*i == journal) {
|
||||
journals.erase(i);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
checked_delete(journal);
|
||||
}
|
||||
|
||||
unsigned int read_journal(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL);
|
||||
unsigned int read_journal(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>());
|
||||
|
||||
unsigned int read_journal(const string& path,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL);
|
||||
unsigned int read_journal(const path& path,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>());
|
||||
|
||||
void read_init();
|
||||
|
||||
|
|
@ -135,17 +132,16 @@ class session_t : public xml::xpath_t::scope_t
|
|||
void register_parser(parser_t * parser) {
|
||||
parsers.push_back(parser);
|
||||
}
|
||||
bool unregister_parser(parser_t * parser) {
|
||||
std::list<parser_t *>::iterator i;
|
||||
for (i = parsers.begin(); i != parsers.end(); i++)
|
||||
if (*i == parser)
|
||||
break;
|
||||
if (i == parsers.end())
|
||||
return false;
|
||||
|
||||
parsers.erase(i);
|
||||
|
||||
return true;
|
||||
void unregister_parser(parser_t * parser) {
|
||||
for (ptr_list<parser_t>::iterator i = parsers.begin();
|
||||
i != parsers.end();
|
||||
i++)
|
||||
if (&*i == parser) {
|
||||
parsers.erase(i);
|
||||
return;
|
||||
}
|
||||
assert(false);
|
||||
checked_delete(parser);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -101,8 +101,10 @@ extern "C" {
|
|||
#include <boost/any.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
#include <boost/filesystem/exception.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/ptr_container/ptr_list.hpp>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ namespace ledger {
|
|||
|
||||
#define MAX_LINE 1024
|
||||
|
||||
static string pathname;
|
||||
static path pathname;
|
||||
static unsigned int linenum;
|
||||
static unsigned int src_idx;
|
||||
static accounts_map account_aliases;
|
||||
|
||||
static std::list<std::pair<string, int> > include_stack;
|
||||
static std::list<std::pair<path, int> > include_stack;
|
||||
|
||||
#ifdef TIMELOG_SUPPORT
|
||||
struct time_entry_t {
|
||||
|
|
@ -173,7 +173,9 @@ transaction_t * parse_transaction(char * line,
|
|||
|
||||
unsigned long beg = (long)in.tellg();
|
||||
|
||||
xact->amount.parse(in, AMOUNT_PARSE_NO_REDUCE);
|
||||
amount_t temp;
|
||||
temp.parse(in, AMOUNT_PARSE_NO_REDUCE);
|
||||
xact->amount = temp;
|
||||
|
||||
char c;
|
||||
if (! in.eof() && (c = peek_next_nonws(in)) != '@' &&
|
||||
|
|
@ -192,11 +194,12 @@ transaction_t * parse_transaction(char * line,
|
|||
xact->entry->data);
|
||||
}
|
||||
|
||||
parse_amount_expr(in, journal, *xact, xact->amount,
|
||||
assert(xact->amount);
|
||||
parse_amount_expr(in, journal, *xact, *xact->amount,
|
||||
XPATH_PARSE_NO_REDUCE);
|
||||
|
||||
if (xact->entry) {
|
||||
delete static_cast<xml::transaction_node_t *>(xact->data);
|
||||
checked_delete(xact->data);
|
||||
xact->data = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -226,13 +229,13 @@ transaction_t * parse_transaction(char * line,
|
|||
}
|
||||
|
||||
if (in.good() && ! in.eof()) {
|
||||
xact->cost = new amount_t;
|
||||
|
||||
PUSH_CONTEXT();
|
||||
|
||||
unsigned long beg = (long)in.tellg();
|
||||
|
||||
xact->cost->parse(in);
|
||||
amount_t temp;
|
||||
temp.parse(in);
|
||||
xact->cost = temp;
|
||||
|
||||
unsigned long end = (long)in.tellg();
|
||||
|
||||
|
|
@ -248,15 +251,17 @@ transaction_t * parse_transaction(char * line,
|
|||
if (*xact->cost < 0)
|
||||
throw_(parse_error, "A transaction's cost may not be negative");
|
||||
|
||||
assert(xact->amount);
|
||||
|
||||
amount_t per_unit_cost(*xact->cost);
|
||||
if (per_unit)
|
||||
*xact->cost *= xact->amount.number();
|
||||
*xact->cost *= xact->amount->number();
|
||||
else
|
||||
per_unit_cost /= xact->amount.number();
|
||||
per_unit_cost /= xact->amount->number();
|
||||
|
||||
if (xact->amount.commodity() &&
|
||||
! xact->amount.commodity().annotated)
|
||||
xact->amount.annotate_commodity(per_unit_cost,
|
||||
if (xact->amount->commodity() &&
|
||||
! xact->amount->commodity().annotated)
|
||||
xact->amount->annotate_commodity(per_unit_cost,
|
||||
xact->entry->actual_date(),
|
||||
xact->entry->code);
|
||||
|
||||
|
|
@ -265,17 +270,19 @@ transaction_t * parse_transaction(char * line,
|
|||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Per-unit cost is " << per_unit_cost);
|
||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Annotated amount is " << xact->amount);
|
||||
"Annotated amount is " << *xact->amount);
|
||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Bare amount is " << xact->amount.number());
|
||||
"Bare amount is " << xact->amount->number());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xact->amount.in_place_reduce();
|
||||
if (xact->amount) {
|
||||
xact->amount->in_place_reduce();
|
||||
|
||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Reduced amount is " << xact->amount);
|
||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Reduced amount is " << *xact->amount);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the optional note
|
||||
|
|
@ -283,10 +290,10 @@ transaction_t * parse_transaction(char * line,
|
|||
if (note) {
|
||||
xact->note = note;
|
||||
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
|
||||
"Parsed a note '" << xact->note << "'");
|
||||
"Parsed a note '" << *xact->note << "'");
|
||||
|
||||
if (char * b = std::strchr(xact->note.c_str(), '['))
|
||||
if (char * e = std::strchr(xact->note.c_str(), ']')) {
|
||||
if (char * b = std::strchr(xact->note->c_str(), '['))
|
||||
if (char * e = std::strchr(xact->note->c_str(), ']')) {
|
||||
char buf[256];
|
||||
std::strncpy(buf, b + 1, e - b - 1);
|
||||
buf[e - b - 1] = '\0';
|
||||
|
|
@ -490,7 +497,7 @@ entry_t * parse_entry(std::istream& in, char * line, journal_t * journal,
|
|||
}
|
||||
|
||||
if (curr->data) {
|
||||
delete static_cast<xml::entry_node_t *>(curr->data);
|
||||
checked_delete(curr->data);
|
||||
curr->data = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -612,10 +619,10 @@ static void clock_out_from_timelog(const moment_t& when,
|
|||
curr.release();
|
||||
}
|
||||
|
||||
unsigned int textual_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string * original_file)
|
||||
unsigned int textual_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>& original)
|
||||
{
|
||||
static bool added_auto_entry_hook = false;
|
||||
static char line[MAX_LINE + 1];
|
||||
|
|
@ -632,11 +639,12 @@ unsigned int textual_parser_t::parse(std::istream& in,
|
|||
|
||||
account_stack.push_front(master);
|
||||
|
||||
pathname = journal ? journal->sources.back() : *original_file;
|
||||
pathname = (journal ? journal->sources.back() :
|
||||
(assert(original), *original));
|
||||
src_idx = journal ? journal->sources.size() - 1 : 0;
|
||||
linenum = 1;
|
||||
|
||||
INFO("Parsing file '" << pathname << "'");
|
||||
INFO("Parsing file '" << pathname.string() << "'");
|
||||
|
||||
unsigned long beg_pos = in.tellg();
|
||||
unsigned long end_pos;
|
||||
|
|
@ -825,31 +833,29 @@ unsigned int textual_parser_t::parse(std::istream& in,
|
|||
char * p = next_element(line);
|
||||
string word(line + 1);
|
||||
if (word == "include") {
|
||||
push_var<string> save_path(pathname);
|
||||
push_var<path> save_path(pathname);
|
||||
push_var<unsigned int> save_src_idx(src_idx);
|
||||
push_var<unsigned long> save_beg_pos(beg_pos);
|
||||
push_var<unsigned long> save_end_pos(end_pos);
|
||||
push_var<unsigned int> save_linenum(linenum);
|
||||
|
||||
pathname = p;
|
||||
if (pathname[0] != '/' && pathname[0] != '\\' &&
|
||||
pathname[0] != '~') {
|
||||
string::size_type pos = save_path.prev.rfind('/');
|
||||
if (pos == string::npos)
|
||||
pos = save_path.prev.rfind('\\');
|
||||
if (pos != string::npos)
|
||||
pathname = string(save_path.prev, 0, pos + 1) + pathname;
|
||||
}
|
||||
pathname = resolve_path(pathname);
|
||||
|
||||
DEBUG("ledger.textual.include", "line " << linenum << ": " <<
|
||||
"Including path '" << pathname << "'");
|
||||
"Including path '" << pathname.string() << "'");
|
||||
|
||||
include_stack.push_back(std::pair<string, int>
|
||||
(journal->sources.back(), linenum - 1));
|
||||
count += journal->session->read_journal(pathname, journal,
|
||||
account_stack.front());
|
||||
include_stack.pop_back();
|
||||
include_stack.push_back
|
||||
(std::pair<path, int>(journal->sources.back(), linenum - 1));
|
||||
|
||||
try {
|
||||
count += journal->session->read_journal(pathname, journal,
|
||||
account_stack.front());
|
||||
include_stack.pop_back();
|
||||
}
|
||||
catch (...) {
|
||||
include_stack.pop_back();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else if (word == "account") {
|
||||
if (account_t * acct = account_stack.front()->find_account(p))
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ class textual_parser_t : public parser_t
|
|||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL);
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>());
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ void compact_transform::execute(xml::document_t * document)
|
|||
account_repitem_t * acct = static_cast<account_repitem_t *>(i);
|
||||
acct->parents_elided = p->parents_elided + 1;
|
||||
|
||||
delete p;
|
||||
checked_delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ void clean_transform::execute(xml::document_t * document)
|
|||
i->add_total(temp);
|
||||
if (! temp) {
|
||||
repitem_t * next = i->next;
|
||||
delete i;
|
||||
checked_delete(i);
|
||||
i = next;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -125,7 +125,7 @@ void clean_transform::execute(xml::document_t * document)
|
|||
else if (i->kind == repitem_t::ENTRY && ! i->contents) {
|
||||
assert(! i->children);
|
||||
repitem_t * next = i->next;
|
||||
delete i;
|
||||
checked_delete(i);
|
||||
i = next;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ void merge_transform::execute(xml::document_t * document)
|
|||
|
||||
j->contents = NULL;
|
||||
assert(! j->children);
|
||||
delete j;
|
||||
checked_delete(j);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -276,14 +276,14 @@ namespace {
|
|||
class delete_unmarked : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
if (item->parent && ! (item->flags & REPITEM_FLAGGED))
|
||||
delete item;
|
||||
checked_delete(item);
|
||||
}
|
||||
};
|
||||
|
||||
class delete_marked : public repitem_t::select_callback_t {
|
||||
virtual void operator()(xml::document_t * document) {
|
||||
if (item->flags & REPITEM_FLAGGED)
|
||||
delete item;
|
||||
checked_delete(item);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -113,10 +113,7 @@ class select_transform : public transform_t
|
|||
select_transform(const string& selection_path) {
|
||||
xpath.parse(selection_path);
|
||||
}
|
||||
virtual ~select_transform() {
|
||||
if (path)
|
||||
delete path;
|
||||
}
|
||||
virtual ~select_transform() {}
|
||||
|
||||
virtual void execute(xml::document_t * document);
|
||||
};
|
||||
|
|
|
|||
48
src/utils.cc
48
src/utils.cc
|
|
@ -87,14 +87,14 @@ void shutdown_memory_tracing()
|
|||
report_memory(std::cerr);
|
||||
}
|
||||
|
||||
delete live_memory; live_memory = NULL;
|
||||
delete live_memory_count; live_memory_count = NULL;
|
||||
delete total_memory_count; total_memory_count = NULL;
|
||||
checked_delete(live_memory); live_memory = NULL;
|
||||
checked_delete(live_memory_count); live_memory_count = NULL;
|
||||
checked_delete(total_memory_count); total_memory_count = NULL;
|
||||
|
||||
delete live_objects; live_objects = NULL;
|
||||
delete live_object_count; live_object_count = NULL;
|
||||
delete total_object_count; total_object_count = NULL;
|
||||
delete total_ctor_count; total_ctor_count = NULL;
|
||||
checked_delete(live_objects); live_objects = NULL;
|
||||
checked_delete(live_object_count); live_object_count = NULL;
|
||||
checked_delete(total_object_count); total_object_count = NULL;
|
||||
checked_delete(total_ctor_count); total_ctor_count = NULL;
|
||||
}
|
||||
|
||||
inline void add_to_count_map(object_count_map& the_map,
|
||||
|
|
@ -630,15 +630,20 @@ ptr_list<context> context_stack;
|
|||
|
||||
namespace ledger {
|
||||
|
||||
string expand_path(const string& path)
|
||||
path expand_path(const path& pathname)
|
||||
{
|
||||
if (path.length() == 0 || path[0] != '~')
|
||||
return path;
|
||||
if (pathname.empty())
|
||||
return pathname;
|
||||
|
||||
const char * pfx = NULL;
|
||||
string::size_type pos = path.find_first_of('/');
|
||||
#if 1
|
||||
return pathname;
|
||||
#else
|
||||
// jww (2007-04-30): I need to port this code to use
|
||||
// boost::filesystem::path
|
||||
const char * pfx = NULL;
|
||||
string::size_type pos = pathname.find_first_of('/');
|
||||
|
||||
if (path.length() == 1 || pos == 1) {
|
||||
if (pathname.length() == 1 || pos == 1) {
|
||||
pfx = std::getenv("HOME");
|
||||
#ifdef HAVE_GETPWUID
|
||||
if (! pfx) {
|
||||
|
|
@ -651,7 +656,7 @@ string expand_path(const string& path)
|
|||
}
|
||||
#ifdef HAVE_GETPWNAM
|
||||
else {
|
||||
string user(path, 1, pos == string::npos ?
|
||||
string user(pathname, 1, pos == string::npos ?
|
||||
string::npos : pos - 1);
|
||||
struct passwd * pw = getpwnam(user.c_str());
|
||||
if (pw)
|
||||
|
|
@ -662,7 +667,7 @@ string expand_path(const string& path)
|
|||
// if we failed to find an expansion, return the path unchanged.
|
||||
|
||||
if (! pfx)
|
||||
return path;
|
||||
return pathname;
|
||||
|
||||
string result(pfx);
|
||||
|
||||
|
|
@ -672,16 +677,19 @@ string expand_path(const string& path)
|
|||
if (result.length() == 0 || result[result.length() - 1] != '/')
|
||||
result += '/';
|
||||
|
||||
result += path.substr(pos + 1);
|
||||
result += pathname.substr(pos + 1);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
string resolve_path(const string& path)
|
||||
path resolve_path(const path& pathname)
|
||||
{
|
||||
if (path[0] == '~')
|
||||
return expand_path(path);
|
||||
return path;
|
||||
path temp = pathname;
|
||||
if (temp.string()[0] == '~')
|
||||
temp = expand_path(temp);
|
||||
temp.normalize();
|
||||
return temp;
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ inline void throw_unexpected_error(char c, char wanted) {
|
|||
|
||||
namespace ledger {
|
||||
|
||||
string resolve_path(const string& path);
|
||||
path resolve_path(const path& pathname);
|
||||
|
||||
#ifdef HAVE_REALPATH
|
||||
extern "C" char * realpath(const char *, char resolved_path[]);
|
||||
|
|
|
|||
45
src/value.cc
45
src/value.cc
|
|
@ -117,10 +117,10 @@ void value_t::destroy()
|
|||
((balance_pair_t *)data)->~balance_pair_t();
|
||||
break;
|
||||
case STRING:
|
||||
delete *(string **) data;
|
||||
checked_delete(*(string **) data);
|
||||
break;
|
||||
case SEQUENCE:
|
||||
delete *(sequence_t **) data;
|
||||
checked_delete(*(sequence_t **) data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1820,43 +1820,6 @@ void value_t::in_place_negate()
|
|||
}
|
||||
}
|
||||
|
||||
void value_t::in_place_abs()
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
break;
|
||||
case INTEGER:
|
||||
if (*((long *) data) < 0)
|
||||
*((long *) data) = - *((long *) data);
|
||||
break;
|
||||
case DATETIME:
|
||||
break;
|
||||
case AMOUNT:
|
||||
((amount_t *) data)->abs();
|
||||
break;
|
||||
case BALANCE:
|
||||
((balance_t *) data)->abs();
|
||||
break;
|
||||
case BALANCE_PAIR:
|
||||
((balance_pair_t *) data)->abs();
|
||||
break;
|
||||
case STRING:
|
||||
throw_(value_error, "Cannot take the absolute value of a string");
|
||||
case XML_NODE:
|
||||
*this = (*(xml::node_t **) data)->to_value();
|
||||
in_place_abs();
|
||||
break;
|
||||
case POINTER:
|
||||
throw_(value_error, "Cannot take the absolute value of a pointer");
|
||||
case SEQUENCE:
|
||||
throw_(value_error, "Cannot take the absolute value of a sequence");
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value_t value_t::value(const moment_t& moment) const
|
||||
{
|
||||
switch (type) {
|
||||
|
|
@ -2188,7 +2151,7 @@ value_t value_t::cost() const
|
|||
return value_t();
|
||||
}
|
||||
|
||||
value_t& value_t::add(const amount_t& amount, const amount_t * tcost)
|
||||
value_t& value_t::add(const amount_t& amount, const optional<amount_t>& tcost)
|
||||
{
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
|
|
@ -2337,7 +2300,7 @@ value_context::value_context(const value_t& _bal,
|
|||
|
||||
value_context::~value_context() throw()
|
||||
{
|
||||
delete bal;
|
||||
checked_delete(bal);
|
||||
}
|
||||
|
||||
void value_context::describe(std::ostream& out) const throw()
|
||||
|
|
|
|||
|
|
@ -435,7 +435,6 @@ class value_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
void in_place_abs();
|
||||
value_t abs() const;
|
||||
void in_place_cast(type_t cast_type);
|
||||
value_t cost() const;
|
||||
|
|
@ -453,10 +452,11 @@ class value_t
|
|||
const bool keep_date = amount_t::keep_date,
|
||||
const bool keep_tag = amount_t::keep_tag) const;
|
||||
|
||||
value_t& add(const amount_t& amount, const amount_t * cost = NULL);
|
||||
value_t& add(const amount_t& amount,
|
||||
const optional<amount_t>& cost = optional<amount_t>());
|
||||
value_t value(const moment_t& moment) const;
|
||||
void in_place_reduce();
|
||||
|
||||
void in_place_reduce();
|
||||
value_t reduce() const {
|
||||
value_t temp(*this);
|
||||
temp.in_place_reduce();
|
||||
|
|
|
|||
20
src/xml.cc
20
src/xml.cc
|
|
@ -29,13 +29,13 @@ document_t::~document_t()
|
|||
{
|
||||
TRACE_DTOR(xml::document_t);
|
||||
if (top && top != &stub)
|
||||
delete top;
|
||||
checked_delete(top);
|
||||
}
|
||||
|
||||
void document_t::set_top(node_t * _top)
|
||||
{
|
||||
if (top && top != &stub)
|
||||
delete top;
|
||||
checked_delete(top);
|
||||
top = _top;
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ void parent_node_t::clear()
|
|||
node_t * child = _children;
|
||||
while (child) {
|
||||
node_t * tnext = child->next;
|
||||
delete child;
|
||||
checked_delete(child);
|
||||
child = tnext;
|
||||
}
|
||||
}
|
||||
|
|
@ -443,7 +443,10 @@ node_t * transaction_node_t::lookup_child(int _name_id) const
|
|||
|
||||
value_t transaction_node_t::to_value() const
|
||||
{
|
||||
return transaction->amount;
|
||||
if (transaction->amount)
|
||||
return *transaction->amount;
|
||||
else
|
||||
return value_t();
|
||||
}
|
||||
|
||||
node_t * entry_node_t::children() const
|
||||
|
|
@ -461,11 +464,14 @@ node_t * entry_node_t::lookup_child(int _name_id) const
|
|||
{
|
||||
switch (_name_id) {
|
||||
case document_t::CODE:
|
||||
if (! entry->code)
|
||||
return NULL;
|
||||
|
||||
// jww (2007-04-20): I have to save this and then delete it later
|
||||
terminal_node_t * code_node =
|
||||
new terminal_node_t(document, const_cast<entry_node_t *>(this));
|
||||
code_node->set_name(document_t::CODE);
|
||||
code_node->set_text(entry->code);
|
||||
code_node->set_text(*entry->code);
|
||||
return code_node;
|
||||
|
||||
case document_t::PAYEE:
|
||||
|
|
@ -489,11 +495,11 @@ node_t * account_node_t::children() const
|
|||
name_node->set_text(account->name);
|
||||
}
|
||||
|
||||
if (! account->note.empty()) {
|
||||
if (account->note) {
|
||||
terminal_node_t * note_node =
|
||||
new terminal_node_t(document, const_cast<account_node_t *>(this));
|
||||
note_node->set_name(document_t::NOTE);
|
||||
note_node->set_text(account->note);
|
||||
note_node->set_text(*account->note);
|
||||
}
|
||||
|
||||
for (accounts_map::iterator i = account->accounts.begin();
|
||||
|
|
|
|||
35
src/xml.h
35
src/xml.h
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _XML_H
|
||||
#define _XML_H
|
||||
|
||||
#include "journal.h"
|
||||
#include "value.h"
|
||||
#include "parser.h"
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ public:
|
|||
virtual ~node_t() {
|
||||
TRACE_DTOR(node_t);
|
||||
if (parent) extract();
|
||||
if (attrs) delete attrs;
|
||||
if (attrs) checked_delete(attrs);
|
||||
}
|
||||
|
||||
void extract(); // extract this node from its parent's child list
|
||||
|
|
@ -249,10 +250,10 @@ class xml_parser_t : public parser_t
|
|||
public:
|
||||
virtual bool test(std::istream& in) const;
|
||||
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const string * original_file = NULL);
|
||||
virtual unsigned int parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master = NULL,
|
||||
const optional<path>& original = optional<path>());
|
||||
};
|
||||
|
||||
DECLARE_EXCEPTION(parse_error);
|
||||
|
|
@ -319,7 +320,7 @@ public:
|
|||
virtual ~transaction_node_t() {
|
||||
TRACE_DTOR(transaction_node_t);
|
||||
if (payee_virtual_node)
|
||||
delete payee_virtual_node;
|
||||
checked_delete(payee_virtual_node);
|
||||
}
|
||||
|
||||
virtual node_t * children() const;
|
||||
|
|
@ -387,33 +388,33 @@ public:
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
inline parent_node_t * wrap_node(document_t * doc, T * item,
|
||||
void * parent_node = NULL) {
|
||||
assert(0);
|
||||
inline typename T::node_type *
|
||||
wrap_node(document_t * doc, T * item, void * parent_node = NULL) {
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline parent_node_t * wrap_node(document_t * doc, transaction_t * xact,
|
||||
void * parent_node) {
|
||||
inline transaction_t::node_type *
|
||||
wrap_node(document_t * doc, transaction_t * xact, void * parent_node) {
|
||||
return new transaction_node_t(doc, xact, (parent_node_t *)parent_node);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline parent_node_t * wrap_node(document_t * doc, entry_t * entry,
|
||||
void * parent_node) {
|
||||
inline entry_t::node_type *
|
||||
wrap_node(document_t * doc, entry_t * entry, void * parent_node) {
|
||||
return new entry_node_t(doc, entry, (parent_node_t *)parent_node);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline parent_node_t * wrap_node(document_t * doc, account_t * account,
|
||||
void * parent_node) {
|
||||
inline account_t::node_type *
|
||||
wrap_node(document_t * doc, account_t * account, void * parent_node) {
|
||||
return new account_node_t(doc, account, (parent_node_t *)parent_node);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline parent_node_t * wrap_node(document_t * doc, journal_t * journal,
|
||||
void * parent_node) {
|
||||
inline journal_t::node_type *
|
||||
wrap_node(document_t * doc, journal_t * journal, void * parent_node) {
|
||||
return new journal_node_t(doc, journal, (parent_node_t *)parent_node);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static void endElement(void *userData, const char *name)
|
|||
if (curr_journal->add_entry(curr_entry)) {
|
||||
count++;
|
||||
} else {
|
||||
delete curr_entry;
|
||||
checked_delete(curr_entry);
|
||||
have_error = "Entry cannot be balanced";
|
||||
}
|
||||
}
|
||||
|
|
@ -133,7 +133,10 @@ static void endElement(void *userData, const char *name)
|
|||
}
|
||||
#endif
|
||||
else if (std::strcmp(name, "quantity") == 0) {
|
||||
curr_entry->transactions.back()->amount.parse(data);
|
||||
amount_t temp;
|
||||
temp.parse(data);
|
||||
curr_entry->transactions.back()->amount = temp;
|
||||
|
||||
if (curr_comm) {
|
||||
string::size_type i = data.find('.');
|
||||
if (i != string::npos) {
|
||||
|
|
@ -141,7 +144,7 @@ static void endElement(void *userData, const char *name)
|
|||
if (precision > curr_comm->precision())
|
||||
curr_comm->set_precision(precision);
|
||||
}
|
||||
curr_entry->transactions.back()->amount.set_commodity(*curr_comm);
|
||||
curr_entry->transactions.back()->amount->set_commodity(*curr_comm);
|
||||
curr_comm = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -179,10 +182,10 @@ bool xml_parser_t::test(std::istream& in) const
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned int xml_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const string * original_file)
|
||||
unsigned int xml_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
const optional<path>& original)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
|
||||
|
|
|
|||
10
src/xpath.cc
10
src/xpath.cc
|
|
@ -15,7 +15,7 @@ void xpath_t::initialize()
|
|||
|
||||
void xpath_t::shutdown()
|
||||
{
|
||||
delete lookahead;
|
||||
checked_delete(lookahead);
|
||||
lookahead = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -555,7 +555,7 @@ xpath_t::op_t::~op_t()
|
|||
case VALUE:
|
||||
assert(! left);
|
||||
assert(valuep);
|
||||
delete valuep;
|
||||
checked_delete(valuep);
|
||||
break;
|
||||
|
||||
case NODE_NAME:
|
||||
|
|
@ -564,7 +564,7 @@ xpath_t::op_t::~op_t()
|
|||
case VAR_NAME:
|
||||
assert(! left);
|
||||
assert(name);
|
||||
delete name;
|
||||
checked_delete(name);
|
||||
break;
|
||||
|
||||
case ARG_INDEX:
|
||||
|
|
@ -573,14 +573,14 @@ xpath_t::op_t::~op_t()
|
|||
case FUNCTOR:
|
||||
assert(! left);
|
||||
assert(functor);
|
||||
delete functor;
|
||||
checked_delete(functor);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case MASK:
|
||||
assert(! left);
|
||||
assert(mask);
|
||||
delete mask;
|
||||
checked_delete(mask);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ public:
|
|||
"Releasing " << this << ", refc now " << refc - 1);
|
||||
assert(refc > 0);
|
||||
if (--refc == 0)
|
||||
delete this;
|
||||
checked_delete(this);
|
||||
}
|
||||
op_t * acquire() {
|
||||
DEBUG("ledger.xpath.memory",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue