summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/amount.cc222
-rw-r--r--src/amount.h64
-rw-r--r--src/balance.h79
-rw-r--r--src/binary.cc20
-rw-r--r--src/derive.h2
-rw-r--r--src/format.h8
-rw-r--r--src/gnucash.cc14
-rw-r--r--src/gnucash.h10
-rw-r--r--src/journal.cc113
-rw-r--r--src/journal.h185
-rw-r--r--src/main.cc74
-rw-r--r--src/ofx.cc2
-rw-r--r--src/option.cc2
-rw-r--r--src/parser.h8
-rw-r--r--src/pyinterp.cc2
-rw-r--r--src/pyinterp.h30
-rw-r--r--src/qif.cc16
-rw-r--r--src/qif.h8
-rw-r--r--src/register.cc6
-rw-r--r--src/report.cc8
-rw-r--r--src/report.h14
-rw-r--r--src/session.cc92
-rw-r--r--src/session.h70
-rw-r--r--src/system.hh2
-rw-r--r--src/textual.cc94
-rw-r--r--src/textual.h8
-rw-r--r--src/transform.cc12
-rw-r--r--src/transform.h5
-rw-r--r--src/utils.cc48
-rw-r--r--src/utils.h2
-rw-r--r--src/value.cc45
-rw-r--r--src/value.h6
-rw-r--r--src/xml.cc20
-rw-r--r--src/xml.h35
-rw-r--r--src/xmlparse.cc17
-rw-r--r--src/xpath.cc10
-rw-r--r--src/xpath.h2
37 files changed, 658 insertions, 697 deletions
diff --git a/src/amount.cc b/src/amount.cc
index 6020a0aa..7a74ef34 100644
--- a/src/amount.cc
+++ b/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);
-
- 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)
+ << *this << std::endl
+ << " price " << (tprice ? tprice->to_string() : "NONE") << " "
+ << " date " << (tdate ? *tdate : moment_t()) << " "
+ << " ttag " << (ttag ? *ttag : "NONE"));
+
+ 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;
}
}
diff --git a/src/amount.h b/src/amount.h
index 84be02b3..e1f7d6ef 100644
--- a/src/amount.h
+++ b/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 * find_or_create(const commodity_t& comm,
- const amount_t& price,
- const moment_t& date,
- const string& tag);
+ 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 optional<amount_t>& price,
+ const optional<moment_t>& date,
+ const optional<string>& tag);
friend class amount_t;
};
diff --git a/src/balance.h b/src/balance.h
index e8665335..463191b7 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -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;
}
};
diff --git a/src/binary.cc b/src/binary.cc
index d3238b5a..55d8e03a 100644
--- a/src/binary.cc
+++ b/src/binary.cc
@@ -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());
diff --git a/src/derive.h b/src/derive.h
index c0607fc2..dfc65c00 100644
--- a/src/derive.h
+++ b/src/derive.h
@@ -1,7 +1,7 @@
#ifndef _DERIVE_H
#define _DERIVE_H
-#include "journal.h"
+#include "xpath.h"
namespace ledger {
diff --git a/src/format.h b/src/format.h
index e271fcf7..e169011f 100644
--- a/src/format.h
+++ b/src/format.h
@@ -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();
}
diff --git a/src/gnucash.cc b/src/gnucash.cc
index 3859ebb4..0fb62bf0 100644
--- a/src/gnucash.cc
+++ b/src/gnucash.cc
@@ -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 = &in;
- 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
diff --git a/src/gnucash.h b/src/gnucash.h
index a0d9fb18..cddf9df9 100644
--- a/src/gnucash.h
+++ b/src/gnucash.h
@@ -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);
};
diff --git a/src/journal.cc b/src/journal.cc
index 9bb453ef..6d50f50e 100644
--- a/src/journal.cc
+++ b/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 =
diff --git a/src/journal.h b/src/journal.h
index a2490efc..711cac19 100644
--- a/src/journal.h
+++ b/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;
-
- mutable void * data;
+ 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;
+
+ 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&");
+ 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&");
}
- transaction_t(const transaction_t& xact)
+ explicit 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),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0), data(NULL) {
+ 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;
- }
- bool operator!=(const account_t& account) {
- return ! (*this == account);
+ operator string() const {
+ return fullname();
}
-
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;
diff --git a/src/main.cc b/src/main.cc
index 0af4da0d..f70d0bd9 100644
--- a/src/main.cc
+++ b/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) {
diff --git a/src/ofx.cc b/src/ofx.cc
index 7ac95e8d..4cc22202 100644
--- a/src/ofx.cc
+++ b/src/ofx.cc
@@ -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;
diff --git a/src/option.cc b/src/option.cc
index 64672211..0773030c 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -207,7 +207,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
}
process_option(def, scope, value);
- delete *o;
+ checked_delete(*o);
}
}
diff --git a/src/parser.h b/src/parser.h
index c1289b47..a95a9e21 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -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);
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index 21363450..0ab25cc3 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -4,6 +4,8 @@
namespace ledger {
+using namespace boost::python;
+
struct python_run
{
object result;
diff --git a/src/pyinterp.h b/src/pyinterp.h
index 9c801a48..f32f4811 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -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);
};
};
diff --git a/src/qif.cc b/src/qif.cc
index ef1089a7..2f1d720c 100644
--- a/src/qif.cc
+++ b/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;
}
diff --git a/src/qif.h b/src/qif.h
index 6c68a99b..7256af89 100644
--- a/src/qif.h
+++ b/src/qif.h
@@ -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
diff --git a/src/register.cc b/src/register.cc
index 9f33bd0c..de0344de 100644
--- a/src/register.cc
+++ b/src/register.cc
@@ -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);
}
diff --git a/src/report.cc b/src/report.cc
index 072d0d8b..2d49b62b 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -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)
diff --git a/src/report.h b/src/report.h
index 11a0b759..ca066566 100644
--- a/src/report.h
+++ b/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),
diff --git a/src/session.cc b/src/session.cc
index 65490b38..ecbc929f 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -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());
-
- 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
+ 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;
+
+ 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);
}
}
diff --git a/src/session.h b/src/session.h
index a1fd304b..1a28e6ee 100644
--- a/src/session.h
+++ b/src/session.h
@@ -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);
}
//
diff --git a/src/system.hh b/src/system.hh
index ce7a71be..55e64734 100644
--- a/src/system.hh
+++ b/src/system.hh
@@ -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>
diff --git a/src/textual.cc b/src/textual.cc
index 9bbf3dbc..7d1d224e 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -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<path, int>(journal->sources.back(), linenum - 1));
- 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();
+ 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))
diff --git a/src/textual.h b/src/textual.h
index bf05b1fc..bcdaee1c 100644
--- a/src/textual.h
+++ b/src/textual.h
@@ -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
diff --git a/src/transform.cc b/src/transform.cc
index b6a25cee..7e2405fb 100644
--- a/src/transform.cc
+++ b/src/transform.cc
@@ -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);
}
};
diff --git a/src/transform.h b/src/transform.h
index 1a5286a1..d54ab499 100644
--- a/src/transform.h
+++ b/src/transform.h
@@ -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);
};
diff --git a/src/utils.cc b/src/utils.cc
index 41bca6be..f18ccca1 100644
--- a/src/utils.cc
+++ b/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
diff --git a/src/utils.h b/src/utils.h
index da6aaa27..89b9a2d0 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -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[]);
diff --git a/src/value.cc b/src/value.cc
index 74a3bd8f..7956af12 100644
--- a/src/value.cc
+++ b/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()
diff --git a/src/value.h b/src/value.h
index 0737fac1..4c6e0f18 100644
--- a/src/value.h
+++ b/src/value.h
@@ -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();
diff --git a/src/xml.cc b/src/xml.cc
index da2c2531..41fbc248 100644
--- a/src/xml.cc
+++ b/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();
diff --git a/src/xml.h b/src/xml.h
index cf80455d..87f2c802 100644
--- a/src/xml.h
+++ b/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);
}
diff --git a/src/xmlparse.cc b/src/xmlparse.cc
index 1b9e9a45..51da13f4 100644
--- a/src/xmlparse.cc
+++ b/src/xmlparse.cc
@@ -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];
diff --git a/src/xpath.cc b/src/xpath.cc
index b7927cb4..53d337ea 100644
--- a/src/xpath.cc
+++ b/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
diff --git a/src/xpath.h b/src/xpath.h
index 76625436..638ec482 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -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",