Started using boost::optional<T>.

This commit is contained in:
John Wiegley 2007-05-01 04:36:49 +00:00
parent 50a9caf302
commit e92bcf411d
37 changed files with 655 additions and 694 deletions

View file

@ -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;
}
}

View file

@ -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;
};

View file

@ -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;
}
};

View file

@ -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());

View file

@ -1,7 +1,7 @@
#ifndef _DERIVE_H
#define _DERIVE_H
#include "journal.h"
#include "xpath.h"
namespace ledger {

View file

@ -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();
}

View file

@ -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

View file

@ -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);
};

View file

@ -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 =

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -207,7 +207,7 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
}
process_option(def, scope, value);
delete *o;
checked_delete(*o);
}
}

View file

@ -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);

View file

@ -4,6 +4,8 @@
namespace ledger {
using namespace boost::python;
struct python_run
{
object result;

View file

@ -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);
};
};

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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)

View file

@ -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),

View file

@ -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);
}
}

View file

@ -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);
}
//

View file

@ -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>

View file

@ -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))

View file

@ -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

View file

@ -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);
}
};

View file

@ -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);
};

View file

@ -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

View file

@ -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[]);

View file

@ -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()

View file

@ -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();

View file

@ -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();

View file

@ -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);
}

View file

@ -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];

View file

@ -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

View file

@ -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",