summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-09-19 08:06:20 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-09-19 08:06:20 -0400
commitfdc7a4e4c5423e79df4ad8905b5a67d45d2f85bc (patch)
treeb7aa301f7d884315f00c42903778ea549e7833d7
parent43ba0bb03807eea3fdcd4dd40fba10b00f823e24 (diff)
downloadfork-ledger-fdc7a4e4c5423e79df4ad8905b5a67d45d2f85bc.tar.gz
fork-ledger-fdc7a4e4c5423e79df4ad8905b5a67d45d2f85bc.tar.bz2
fork-ledger-fdc7a4e4c5423e79df4ad8905b5a67d45d2f85bc.zip
Factored common parts of entry_t and xact_t into new item_t
-rw-r--r--Makefile.am4
-rw-r--r--src/account.cc7
-rw-r--r--src/account.h7
-rw-r--r--src/csv.cc23
-rw-r--r--src/emacs.cc8
-rw-r--r--src/entry.cc120
-rw-r--r--src/entry.h48
-rw-r--r--src/filters.cc28
-rw-r--r--src/filters.h4
-rw-r--r--src/gnucash.cc4
-rw-r--r--src/item.cc141
-rw-r--r--src/item.h135
-rw-r--r--src/journal.cc21
-rw-r--r--src/journal.h7
-rw-r--r--src/ofx.cc3
-rw-r--r--src/output.cc2
-rw-r--r--src/qif.cc2
-rw-r--r--src/reconcile.cc8
-rw-r--r--src/session.cc4
-rw-r--r--src/session.h2
-rw-r--r--src/textual.cc32
-rw-r--r--src/xact.cc153
-rw-r--r--src/xact.h89
-rw-r--r--src/xml.cc12
24 files changed, 445 insertions, 419 deletions
diff --git a/Makefile.am b/Makefile.am
index fb1ea9f2..3d9701f7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,8 +38,9 @@ endif
libledger_la_CPPFLAGS = $(libamounts_la_CPPFLAGS)
libledger_la_LDFLAGS = -release 3.0.0
-libledger_la_SOURCES = \
+libledger_la_SOURCES = \
src/journal.cc \
+ src/item.cc \
src/entry.cc \
src/xact.cc \
src/account.cc \
@@ -102,6 +103,7 @@ pkginclude_HEADERS = \
src/option.h \
\
src/journal.h \
+ src/item.h \
src/entry.h \
src/xact.h \
src/account.h \
diff --git a/src/account.cc b/src/account.cc
index f628817e..fc80a9d6 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -73,7 +73,7 @@ account_t * account_t::find_account(const string& name,
if (! auto_create)
return NULL;
- account = new account_t(owner, this, first);
+ account = new account_t(this, first);
std::pair<accounts_map::iterator, bool> result
= accounts.insert(accounts_map::value_type(first, account));
assert(result.second);
@@ -190,8 +190,7 @@ expr_t::ptr_op_t account_t::lookup(const string& name)
break;
}
- assert(owner == session_t::current);
- return owner->current_report->lookup(name);
+ return session_t::current->current_report->lookup(name);
}
bool account_t::valid() const
@@ -234,7 +233,7 @@ void account_t::calculate_sums()
}
call_scope_t args(*this);
- value_t amount(owner->current_report->get_amount_expr(args));
+ value_t amount(session_t::current->current_report->get_amount_expr(args));
if (! amount.is_null()) {
add_or_set_value(xd.total, amount);
xd.total_count += xd.count;
diff --git a/src/account.h b/src/account.h
index 6bd11704..ff79e3be 100644
--- a/src/account.h
+++ b/src/account.h
@@ -47,7 +47,6 @@ class account_t : public scope_t
public:
typedef unsigned long ident_t;
- session_t * owner;
account_t * parent;
string name;
optional<string> note;
@@ -58,17 +57,15 @@ class account_t : public scope_t
mutable ident_t ident;
mutable string _fullname;
- account_t(session_t * _owner,
- account_t * _parent = NULL,
+ account_t(account_t * _parent = NULL,
const string& _name = "",
const optional<string>& _note = none)
- : scope_t(), owner(_owner), parent(_parent), name(_name), note(_note),
+ : scope_t(), 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(const account_t& other)
: scope_t(),
- owner(other.owner),
parent(other.parent),
name(other.name),
note(other.note),
diff --git a/src/csv.cc b/src/csv.cc
index c075622e..e823ed41 100644
--- a/src/csv.cc
+++ b/src/csv.cc
@@ -102,28 +102,15 @@ void format_csv_xacts::operator()(xact_t& xact)
}
out << ',';
- switch (xact.state) {
- case xact_t::CLEARED:
+ switch (xact.state()) {
+ case item_t::CLEARED:
write_escaped_string(out, "*");
break;
- case xact_t::PENDING:
+ case item_t::PENDING:
write_escaped_string(out, "!");
break;
- default: {
- xact_t::state_t state;
- if (xact.entry->get_state(&state))
- switch (state) {
- case xact_t::CLEARED:
- write_escaped_string(out, "*");
- break;
- case xact_t::PENDING:
- write_escaped_string(out, "!");
- break;
- default:
- write_escaped_string(out, "");
- break;
- }
- }
+ default:
+ break;
}
out << ',';
diff --git a/src/emacs.cc b/src/emacs.cc
index cf787e75..dab9223f 100644
--- a/src/emacs.cc
+++ b/src/emacs.cc
@@ -45,7 +45,7 @@ void format_emacs_xacts::write_entry(entry_t& entry)
out << (static_cast<unsigned long>(entry.beg_line) + 1) << " ";
- tm when = gregorian::to_tm(entry.date());
+ tm when = gregorian::to_tm(*entry.date());
std::time_t date = std::mktime(&when); // jww (2008-04-20): Is this GMT or local?
out << "(" << (date / 65536) << " " << (date % 65536) << " 0) ";
@@ -83,11 +83,11 @@ void format_emacs_xacts::operator()(xact_t& xact)
out << "\"" << xact.reported_account()->fullname() << "\" \""
<< xact.amount << "\"";
- switch (xact.state) {
- case xact_t::CLEARED:
+ switch (xact.state()) {
+ case item_t::CLEARED:
out << " t";
break;
- case xact_t::PENDING:
+ case item_t::PENDING:
out << " pending";
break;
default:
diff --git a/src/entry.cc b/src/entry.cc
index a66b8852..9f3af62e 100644
--- a/src/entry.cc
+++ b/src/entry.cc
@@ -38,8 +38,7 @@
namespace ledger {
entry_base_t::entry_base_t(const entry_base_t& e)
- : supports_flags<>(), journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+ : item_t(), journal(NULL)
{
TRACE_CTOR(entry_base_t, "copy");
xacts.insert(xacts.end(), e.xacts.begin(), e.xacts.end());
@@ -53,8 +52,8 @@ entry_base_t::~entry_base_t()
// If the transaction is a temporary, it will be destructed when the
// temporary is. If it's from a binary cache, we can safely destruct it
// but its memory will be deallocated with the cache.
- if (! xact->has_flags(XACT_TEMP)) {
- if (! xact->has_flags(XACT_IN_CACHE))
+ if (! xact->has_flags(ITEM_TEMP)) {
+ if (! xact->has_flags(ITEM_IN_CACHE))
checked_delete(xact);
else
xact->~xact_t();
@@ -62,6 +61,20 @@ entry_base_t::~entry_base_t()
}
}
+item_t::state_t entry_base_t::state() const
+{
+ bool first = true;
+ state_t result = UNCLEARED;
+
+ foreach (xact_t * xact, xacts) {
+ if ((result == UNCLEARED && xact->_state != UNCLEARED) ||
+ (result == PENDING && xact->_state == CLEARED))
+ result = xact->_state;
+ }
+
+ return result;
+}
+
void entry_base_t::add_xact(xact_t * xact)
{
xacts.push_back(xact);
@@ -133,8 +146,8 @@ bool entry_base_t::finalize()
if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) {
// jww (2008-07-24): Need to make the rest of the code aware of what to do
// when it sees a generated xact.
- null_xact = new xact_t(journal->basket, XACT_GENERATED);
- null_xact->state = (*xacts.begin())->state;
+ null_xact = new xact_t(journal->basket, ITEM_GENERATED);
+ null_xact->_state = (*xacts.begin())->_state;
add_xact(null_xact);
}
@@ -170,7 +183,7 @@ bool entry_base_t::finalize()
first = false;
} else {
add_xact(new xact_t(null_xact->account, pair.second.negate(),
- XACT_GENERATED));
+ ITEM_GENERATED));
}
}
}
@@ -279,7 +292,7 @@ bool entry_base_t::finalize()
amount_t basis_cost;
amount_t ann_amount =
commodity_t::exchange(x_amt, final_cost, basis_cost, xact->cost, none,
- datetime_t(xact->actual_date(),
+ datetime_t(*xact->actual_date(),
time_duration_t(0, 0, 0)),
entry ? entry->code : optional<string>());
@@ -341,8 +354,7 @@ bool entry_base_t::finalize()
}
entry_t::entry_t(const entry_t& e)
- : entry_base_t(e), scope_t(), _date(e._date), _date_eff(e._date_eff),
- code(e.code), payee(e.payee)
+ : entry_base_t(e), code(e.code), payee(e.payee)
{
TRACE_CTOR(entry_t, "copy");
@@ -350,27 +362,6 @@ entry_t::entry_t(const entry_t& e)
xact->entry = this;
}
-bool entry_t::get_state(xact_t::state_t * state) const
-{
- bool first = true;
- bool hetero = false;
-
- foreach (xact_t * xact, xacts) {
- if (first ||
- xact->state == xact_t::CLEARED ||
- (xact->state == xact_t::PENDING && *state == xact_t::UNCLEARED)) {
- *state = xact->state;
- first = false;
- }
- else if (*state != xact->state) {
- hetero = true;
- break;
- }
- }
-
- return ! hetero;
-}
-
void entry_t::add_xact(xact_t * xact)
{
xact->entry = this;
@@ -378,26 +369,6 @@ void entry_t::add_xact(xact_t * xact)
}
namespace {
- value_t get_date(entry_t& entry) {
- return entry.date();
- }
-
- value_t get_status(entry_t& entry) {
- xact_t::state_t status;
- entry.get_state(&status);
- return long(status);
- }
- value_t get_cleared(entry_t& entry) {
- xact_t::state_t status;
- entry.get_state(&status);
- return status == xact_t::CLEARED;
- }
- value_t get_pending(entry_t& entry) {
- xact_t::state_t status;
- entry.get_state(&status);
- return status == xact_t::PENDING;
- }
-
value_t get_code(entry_t& entry) {
if (entry.code)
return string_value(*entry.code);
@@ -421,49 +392,20 @@ expr_t::ptr_op_t entry_t::lookup(const string& name)
case 'c':
if (name == "code")
return WRAP_FUNCTOR(get_wrapper<&get_code>);
- else if (name == "cleared")
- return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
- break;
-
- case 'd':
- if (name[1] == '\0' || name == "date")
- return WRAP_FUNCTOR(get_wrapper<&get_date>);
break;
case 'p':
if (name[1] == '\0' || name == "payee")
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
- else if (name == "pending")
- return WRAP_FUNCTOR(get_wrapper<&get_pending>);
- break;
-
- case 'u':
- if (name == "uncleared")
- return expr_t::op_t::wrap_value(1L);
- break;
-
- case 'X':
- if (name[1] == '\0')
- return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
- break;
-
- case 'Y':
- if (name[1] == '\0')
- return WRAP_FUNCTOR(get_wrapper<&get_pending>);
break;
}
- if (journal) {
- assert(journal->owner == session_t::current);
- return journal->owner->current_report->lookup(name);
- } else {
- return session_t::current->current_report->lookup(name);
- }
+ return item_t::lookup(name);
}
bool entry_t::valid() const
{
- if (! is_valid(_date) || ! journal) {
+ if (! _date || ! journal) {
DEBUG("ledger.validate", "entry_t: ! _date || ! journal");
return false;
}
@@ -514,19 +456,11 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
if (fullname == "$account" || fullname == "@account")
account = initial_xact->account;
- xact_t * new_xact
- = new xact_t(account, amt, xact->flags() | XACT_AUTO);
-
// Copy over details so that the resulting xact is a mirror of
// the automated entry's one.
- new_xact->state = xact->state;
- new_xact->_date = xact->_date;
- new_xact->_date_eff = xact->_date_eff;
- new_xact->note = xact->note;
- new_xact->beg_pos = xact->beg_pos;
- new_xact->beg_line = xact->beg_line;
- new_xact->end_pos = xact->end_pos;
- new_xact->end_line = xact->end_line;
+ xact_t * new_xact = new xact_t(account, amt);
+ new_xact->copy_details(*xact);
+ new_xact->add_flags(XACT_AUTO);
entry.add_xact(new_xact);
}
diff --git a/src/entry.h b/src/entry.h
index 2834942f..7d6623ae 100644
--- a/src/entry.h
+++ b/src/entry.h
@@ -39,35 +39,20 @@ namespace ledger {
class journal_t;
-class entry_base_t : public supports_flags<>
+class entry_base_t : public item_t
{
public:
-#define ENTRY_IN_CACHE 0x1
-
- journal_t * journal;
- string note;
- unsigned long src_idx;
- istream_pos_type beg_pos;
- unsigned long beg_line;
- istream_pos_type end_pos;
- unsigned long end_line;
- xacts_list xacts;
-
- entry_base_t() : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
- {
+ journal_t * journal;
+ xacts_list xacts;
+
+ entry_base_t() : journal(NULL) {
TRACE_CTOR(entry_base_t, "");
}
entry_base_t(const entry_base_t& e);
virtual ~entry_base_t();
- bool operator==(const entry_base_t& entry) {
- return this == &entry;
- }
- bool operator!=(const entry_base_t& entry) {
- return ! (*this == entry);
- }
+ virtual state_t state() const;
virtual void add_xact(xact_t * xact);
virtual bool remove_xact(xact_t * xact);
@@ -76,11 +61,9 @@ public:
virtual bool valid() const = 0;
};
-class entry_t : public entry_base_t, public scope_t
+class entry_t : public entry_base_t
{
public:
- date_t _date;
- optional<date_t> _date_eff;
optional<string> code;
string payee;
@@ -93,23 +76,6 @@ public:
TRACE_DTOR(entry_t);
}
- date_t actual_date() const {
- return _date;
- }
- date_t effective_date() const {
- if (! _date_eff)
- return _date;
- return *_date_eff;
- }
- date_t date() const {
- if (xact_t::use_effective_date)
- return effective_date();
- else
- return actual_date();
- }
-
- bool get_state(xact_t::state_t * state) const;
-
virtual void add_xact(xact_t * xact);
virtual expr_t::ptr_op_t lookup(const string& name);
diff --git a/src/filters.cc b/src/filters.cc
index 9b5aded4..0205f68c 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -180,7 +180,7 @@ void handle_value(const value_t& value,
temps.push_back(xact_t(account));
xact_t& xact(temps.back());
xact.entry = entry;
- xact.add_flags(XACT_TEMP);
+ xact.add_flags(ITEM_TEMP);
entry->add_xact(&xact);
// If there are component xacts to associate with this
@@ -390,9 +390,9 @@ void subtotal_xacts::report_subtotal(const char * spec_fmt)
void subtotal_xacts::operator()(xact_t& xact)
{
if (! is_valid(start) || xact.date() < start)
- start = xact.date();
+ start = *xact.date();
if (! is_valid(finish) || xact.date() > finish)
- finish = xact.date();
+ finish = *xact.date();
account_t * acct = xact.reported_account();
assert(acct);
@@ -432,7 +432,7 @@ void interval_xacts::report_subtotal(const date_t& date)
if (is_valid(date))
finish = date - gregorian::days(1);
else
- finish = last_xact->date();
+ finish = *last_xact->date();
subtotal_xacts::report_subtotal();
@@ -441,7 +441,7 @@ void interval_xacts::report_subtotal(const date_t& date)
void interval_xacts::operator()(xact_t& xact)
{
- const date_t& date(xact.date());
+ const date_t& date(*xact.date());
if ((is_valid(interval.begin) && date < interval.begin) ||
(is_valid(interval.end) && date >= interval.end))
@@ -512,7 +512,7 @@ void by_payee_xacts::operator()(xact_t& xact)
}
if (xact.date() > (*i).second->start)
- (*i).second->start = xact.date();
+ (*i).second->start = *xact.date();
(*(*i).second)(xact);
}
@@ -532,8 +532,8 @@ void set_comm_as_payee::operator()(xact_t& xact)
xact_temps.push_back(xact);
xact_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.state = xact.state;
- temp.add_flags(XACT_TEMP);
+ temp.set_state(xact.state());
+ temp.add_flags(ITEM_TEMP);
entry.add_xact(&temp);
@@ -554,8 +554,8 @@ void set_code_as_payee::operator()(xact_t& xact)
xact_temps.push_back(xact);
xact_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.state = xact.state;
- temp.add_flags(XACT_TEMP);
+ temp.set_state(xact.state());
+ temp.add_flags(ITEM_TEMP);
entry.add_xact(&temp);
@@ -619,7 +619,7 @@ void budget_xacts::report_budget_items(const date_t& date)
xact_temps.push_back(xact);
xact_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.add_flags(XACT_AUTO | XACT_TEMP);
+ temp.add_flags(XACT_AUTO | ITEM_TEMP);
temp.amount.negate();
entry.add_xact(&temp);
@@ -653,7 +653,7 @@ void budget_xacts::operator()(xact_t& xact)
handle:
if (xact_in_budget && flags & BUDGET_BUDGETED) {
- report_budget_items(xact.date());
+ report_budget_items(*xact.date());
item_handler<xact_t>::operator()(xact);
}
else if (! xact_in_budget && flags & BUDGET_UNBUDGETED) {
@@ -706,7 +706,7 @@ void forecast_xacts::flush()
xact_temps.push_back(xact);
xact_t& temp = xact_temps.back();
temp.entry = &entry;
- temp.add_flags(XACT_AUTO | XACT_TEMP);
+ temp.add_flags(XACT_AUTO | ITEM_TEMP);
entry.add_xact(&temp);
date_t next = (*least).first.increment(begin);
@@ -720,7 +720,7 @@ void forecast_xacts::flush()
temp.xdata().has_flags(XACT_EXT_MATCHES)) {
if (! pred(temp))
break;
- last = temp.date();
+ last = *temp.date();
passed.clear();
} else {
bool found = false;
diff --git a/src/filters.h b/src/filters.h
index 31c89b48..59c8f52c 100644
--- a/src/filters.h
+++ b/src/filters.h
@@ -290,7 +290,7 @@ public:
collapse_xacts(xact_handler_ptr handler, session_t& session)
: item_handler<xact_t>(handler), count(0),
last_entry(NULL), last_xact(NULL),
- totals_account(&session, NULL, "<Total>") {
+ totals_account(NULL, "<Total>") {
TRACE_CTOR(collapse_xacts, "xact_handler_ptr");
}
virtual ~collapse_xacts() {
@@ -588,7 +588,7 @@ public:
virtual void flush();
virtual void operator()(xact_t& xact) {
- days_of_the_week[xact.date().day_of_week()].push_back(&xact);
+ days_of_the_week[xact.date()->day_of_week()].push_back(&xact);
}
};
diff --git a/src/gnucash.cc b/src/gnucash.cc
index 6b9b5211..e2ee113a 100644
--- a/src/gnucash.cc
+++ b/src/gnucash.cc
@@ -89,7 +89,7 @@ static enum action_t {
static void startElement(void *, const char *name, const char **)
{
if (std::strcmp(name, "gnc:account") == 0) {
- curr_account = new account_t(master_account->owner, master_account);
+ curr_account = new account_t(master_account);
}
else if (std::strcmp(name, "act:name") == 0)
action = ACCOUNT_NAME;
@@ -193,7 +193,7 @@ static void endElement(void *, const char *name)
value = curr_quant;
}
- xact->state = curr_state;
+ xact->set_state(curr_state);
xact->amount = value;
if (value != curr_value)
xact->cost = curr_value;
diff --git a/src/item.cc b/src/item.cc
new file mode 100644
index 00000000..c6f77987
--- /dev/null
+++ b/src/item.cc
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "item.h"
+#include "session.h"
+#include "report.h"
+
+namespace ledger {
+
+bool item_t::use_effective_date = false;
+
+namespace {
+ value_t get_status(item_t& item) {
+ return long(item.state());
+ }
+ value_t get_cleared(item_t& item) {
+ return item.state() == item_t::CLEARED;
+ }
+ value_t get_pending(item_t& item) {
+ return item.state() == item_t::PENDING;
+ }
+
+ value_t get_date(item_t& item) {
+ if (optional<date_t> date = item.date())
+ return *date;
+ else
+ return 0L;
+ }
+
+ value_t get_note(item_t& item) {
+ return string_value(item.note ? *item.note : empty_string);
+ }
+
+ value_t get_beg_pos(item_t& item) {
+ return long(item.beg_pos);
+ }
+
+ value_t get_beg_line(item_t& item) {
+ return long(item.beg_line);
+ }
+
+ value_t get_end_pos(item_t& item) {
+ return long(item.end_pos);
+ }
+
+ value_t get_end_line(item_t& item) {
+ return long(item.end_line);
+ }
+
+ template <value_t (*Func)(item_t&)>
+ value_t get_wrapper(call_scope_t& scope) {
+ return (*Func)(find_scope<item_t>(scope));
+ }
+}
+
+expr_t::ptr_op_t item_t::lookup(const string& name)
+{
+ switch (name[0]) {
+ case 'c':
+ if (name == "cleared")
+ return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
+ break;
+
+ case 'd':
+ if (name[1] == '\0' || name == "date")
+ return WRAP_FUNCTOR(get_wrapper<&get_date>);
+ break;
+
+ case 'n':
+ if (name == "note")
+ return WRAP_FUNCTOR(get_wrapper<&get_note>);
+ break;
+
+ case 'p':
+ if (name == "pending")
+ return WRAP_FUNCTOR(get_wrapper<&get_pending>);
+ break;
+
+ case 's':
+ if (name == "status")
+ return WRAP_FUNCTOR(get_wrapper<&get_status>);
+ break;
+
+ case 'u':
+ if (name == "uncleared")
+ return expr_t::op_t::wrap_value(1L);
+ break;
+
+ case 'X':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
+ break;
+
+ case 'Y':
+ if (name[1] == '\0')
+ return WRAP_FUNCTOR(get_wrapper<&get_pending>);
+ break;
+ }
+
+ return session_t::current->current_report->lookup(name);
+}
+
+bool item_t::valid() const
+{
+ if (_state != UNCLEARED && _state != CLEARED && _state != PENDING) {
+ DEBUG("ledger.validate", "item_t: state is bad");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace ledger
diff --git a/src/item.h b/src/item.h
new file mode 100644
index 00000000..74edf563
--- /dev/null
+++ b/src/item.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of New Artisans LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ITEM_H
+#define _ITEM_H
+
+#include "utils.h"
+#include "scope.h"
+
+namespace ledger {
+
+class entry_t;
+class account_t;
+
+class item_t;
+typedef std::list<item_t *> items_list;
+
+class item_t : public supports_flags<>, public scope_t
+{
+public:
+#define ITEM_NORMAL 0x0000 // no flags at all, a basic transaction
+#define ITEM_IN_CACHE 0x0001 // transaction allocated by the binary cache
+#define ITEM_GENERATED 0x0002 // transaction was not found in a journal
+#define ITEM_TEMP 0x0004 // transaction is a temporary object
+
+ enum state_t { UNCLEARED = 0, CLEARED, PENDING };
+
+ state_t _state;
+
+ optional<date_t> _date;
+ optional<date_t> _date_eff;
+ optional<string> note;
+
+ unsigned short src_idx;
+ istream_pos_type beg_pos;
+ unsigned long beg_line;
+ istream_pos_type end_pos;
+ unsigned long end_line;
+
+ static bool use_effective_date;
+
+ item_t(flags_t _flags = ITEM_NORMAL, const optional<string>& _note = none)
+ : supports_flags<>(_flags), _state(UNCLEARED), note(_note),
+ beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+ {
+ TRACE_CTOR(item_t, "flags_t, const string&");
+ }
+ item_t(const item_t& item) : supports_flags<>(), scope_t()
+ {
+ TRACE_CTOR(item_t, "copy");
+ copy_details(item);
+ }
+ virtual ~item_t() {
+ TRACE_DTOR(item_t);
+ }
+
+ void copy_details(const item_t& item)
+ {
+ set_flags(item.flags());
+ set_state(item.state());
+
+ _date = item._date;
+ _date_eff = item._date_eff;
+
+ note = item.note;
+
+ beg_pos = item.beg_pos;
+ beg_line = item.beg_line;
+ end_pos = item.end_pos;
+ end_line = item.end_line;
+ }
+
+ virtual bool operator==(const item_t& entry) {
+ return this == &entry;
+ }
+ virtual bool operator!=(const item_t& entry) {
+ return ! (*this == entry);
+ }
+
+ virtual optional<date_t> actual_date() const {
+ return _date;
+ }
+ virtual optional<date_t> effective_date() const {
+ return _date_eff;
+ }
+ optional<date_t> date() const {
+ if (use_effective_date && _date_eff)
+ return effective_date();
+ else
+ return actual_date();
+ }
+
+ void set_state(state_t new_state) {
+ _state = new_state;
+ }
+ virtual state_t state() const {
+ return _state;
+ }
+
+ virtual expr_t::ptr_op_t lookup(const string& name);
+
+ bool valid() const;
+};
+
+} // namespace ledger
+
+#endif // _ITEM_H
diff --git a/src/journal.cc b/src/journal.cc
index 7d95d72f..c5a9e9fc 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -36,11 +36,10 @@ namespace ledger {
const string version = PACKAGE_VERSION;
-journal_t::journal_t(session_t * _owner)
- : owner(_owner), basket(NULL)
+journal_t::journal_t() : basket(NULL)
{
TRACE_CTOR(journal_t, "");
- master = owner->master.get();
+ master = session_t::current->master.get();
}
journal_t::~journal_t()
@@ -51,19 +50,19 @@ journal_t::~journal_t()
// accounts they refer to, because all accounts are about to
// be deleted.
foreach (entry_t * entry, entries)
- if (! entry->has_flags(ENTRY_IN_CACHE))
+ if (! entry->has_flags(ITEM_IN_CACHE))
checked_delete(entry);
else
entry->~entry_t();
foreach (auto_entry_t * entry, auto_entries)
- if (! entry->has_flags(ENTRY_IN_CACHE))
+ if (! entry->has_flags(ITEM_IN_CACHE))
checked_delete(entry);
else
entry->~auto_entry_t();
foreach (period_entry_t * entry, period_entries)
- if (! entry->has_flags(ENTRY_IN_CACHE))
+ if (! entry->has_flags(ITEM_IN_CACHE))
checked_delete(entry);
else
entry->~period_entry_t();
@@ -71,22 +70,22 @@ journal_t::~journal_t()
void journal_t::add_account(account_t * acct)
{
- owner->add_account(acct);
+ session_t::current->add_account(acct);
}
bool journal_t::remove_account(account_t * acct)
{
- return owner->remove_account(acct);
+ return session_t::current->remove_account(acct);
}
account_t * journal_t::find_account(const string& name, bool auto_create)
{
- return owner->find_account(name, auto_create);
+ return session_t::current->find_account(name, auto_create);
}
account_t * journal_t::find_account_re(const string& regexp)
{
- return owner->find_account_re(regexp);
+ return session_t::current->find_account_re(regexp);
}
bool journal_t::add_entry(entry_t * entry)
@@ -105,7 +104,7 @@ bool journal_t::add_entry(entry_t * entry)
foreach (const xact_t * xact, entry->xacts)
if (xact->cost) {
assert(xact->amount);
- xact->amount.commodity().add_price(datetime_t(entry->date(),
+ xact->amount.commodity().add_price(datetime_t(*entry->date(),
time_duration_t(0, 0, 0)),
*xact->cost / xact->amount.number());
}
diff --git a/src/journal.h b/src/journal.h
index 293439bb..487b0841 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -46,7 +46,6 @@ class account_t;
class journal_t : public noncopyable
{
public:
- session_t * owner;
account_t * master;
account_t * basket;
entries_list entries;
@@ -58,11 +57,11 @@ public:
hooks_t<entry_finalizer_t, entry_t> entry_finalize_hooks;
- journal_t(session_t * _owner);
+ journal_t();
~journal_t();
- // These four methods are delegated to 'owner', since all accounts processed
- // are gathered together at the session level.
+ // These four methods are delegated to the current session, since all
+ // accounts processed are gathered together at the session level.
void add_account(account_t * acct);
bool remove_account(account_t * acct);
account_t * find_account(const string& name, bool auto_create = true);
diff --git a/src/ofx.cc b/src/ofx.cc
index 0bc917e8..8940f62a 100644
--- a/src/ofx.cc
+++ b/src/ofx.cc
@@ -61,8 +61,7 @@ int ofx_proc_account_cb(struct OfxAccountData data, void *)
return -1;
DEBUG("ledger.ofx.parse", "account " << data.account_name);
- account_t * account = new account_t(master_account->owner, master_account,
- data.account_name);
+ account_t * account = new account_t(master_account, data.account_name);
curr_journal->add_account(account);
ofx_accounts.insert(accounts_pair(data.account_id, account));
diff --git a/src/output.cc b/src/output.cc
index 4ddcffb5..3db202cd 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -253,7 +253,7 @@ format_equity::format_equity(report_t& _report, const string& _format)
void format_equity::flush()
{
- account_t summary(&report.session, NULL, "Equity:Opening Balances");
+ account_t summary(NULL, "Equity:Opening Balances");
account_t::xdata_t& xdata(summary.xdata());
std::ostream& out(*report.output_stream);
diff --git a/src/qif.cc b/src/qif.cc
index 1c0f01b7..38bac7e9 100644
--- a/src/qif.cc
+++ b/src/qif.cc
@@ -166,7 +166,7 @@ unsigned int qif_parser_t::parse(std::istream& in,
c = in.peek();
if (c == '*' || c == 'X') {
in.get(c);
- xact->state = xact_t::CLEARED;
+ xact->set_state(item_t::CLEARED);
}
break;
diff --git a/src/reconcile.cc b/src/reconcile.cc
index aca1732e..0294d93e 100644
--- a/src/reconcile.cc
+++ b/src/reconcile.cc
@@ -72,12 +72,12 @@ void reconcile_xacts::flush()
foreach (xact_t * xact, xacts) {
if (! is_valid(cutoff) || xact->date() < cutoff) {
- switch (xact->state) {
- case xact_t::CLEARED:
+ switch (xact->state()) {
+ case item_t::CLEARED:
cleared_balance += xact->amount;
break;
- case xact_t::UNCLEARED:
- case xact_t::PENDING:
+ case item_t::UNCLEARED:
+ case item_t::PENDING:
pending_balance += xact->amount;
*last_ptr = xact;
last_ptr = xact_next_ptr(xact);
diff --git a/src/session.cc b/src/session.cc
index 6bcca89a..be7256a5 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -113,7 +113,7 @@ session_t::session_t()
ansi_codes(false),
ansi_invert(false),
- master(new account_t(this, NULL, ""))
+ master(new account_t(NULL, ""))
{
TRACE_CTOR(session_t, "");
}
@@ -161,7 +161,7 @@ void session_t::read_init()
ifstream init(*init_file);
- journal_t temp(this);
+ journal_t temp;
if (read_journal(temp, *init_file) > 0 ||
temp.auto_entries.size() > 0 ||
temp.period_entries.size() > 0)
diff --git a/src/session.h b/src/session.h
index a8c3fb4c..b45923d9 100644
--- a/src/session.h
+++ b/src/session.h
@@ -96,7 +96,7 @@ public:
virtual ~session_t();
journal_t * create_journal() {
- journal_t * journal = new journal_t(this);
+ journal_t * journal = new journal_t;
journals.push_back(journal);
return journal;
}
diff --git a/src/textual.cc b/src/textual.cc
index e167467f..a0efd4ef 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -127,14 +127,14 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
char p = peek_next_nonws(in);
switch (p) {
case '*':
- xact->state = xact_t::CLEARED;
+ xact->set_state(item_t::CLEARED);
in.get(p);
p = peek_next_nonws(in);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
"Parsed the CLEARED flag");
break;
case '!':
- xact->state = xact_t::PENDING;
+ xact->set_state(item_t::PENDING);
in.get(p);
p = peek_next_nonws(in);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
@@ -160,15 +160,17 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
char * b = &line[long(account_beg)];
char * e = &line[long(account_end)];
+
if ((*b == '[' && *(e - 1) == ']') ||
(*b == '(' && *(e - 1) == ')')) {
xact->add_flags(XACT_VIRTUAL);
- DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a virtual account name");
+ DEBUG("ledger.textual.parse",
+ "line " << linenum << ": " << "Parsed a virtual account name");
+
if (*b == '[') {
xact->add_flags(XACT_BALANCE);
- DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
- "Parsed a balanced virtual account name");
+ DEBUG("ledger.textual.parse",
+ "line " << linenum << ": " << "Transaction must balance");
}
b++; e--;
}
@@ -374,7 +376,7 @@ xact_t * parse_xact(char * line, account_t * account, entry_t * entry = NULL)
diff -= xact->amount;
if (! diff.is_zero()) {
xact_t * temp = new xact_t(xact->account, diff,
- XACT_GENERATED | XACT_CALCULATED);
+ ITEM_GENERATED | XACT_CALCULATED);
entry->add_xact(temp);
DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
@@ -496,15 +498,15 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
// Parse the optional cleared flag: *
- xact_t::state_t state = xact_t::UNCLEARED;
+ item_t::state_t state = item_t::UNCLEARED;
if (next) {
switch (*next) {
case '*':
- state = xact_t::CLEARED;
+ state = item_t::CLEARED;
next = skip_ws(++next);
break;
case '!':
- state = xact_t::PENDING;
+ state = item_t::PENDING;
next = skip_ws(++next);
break;
}
@@ -556,14 +558,13 @@ entry_t * parse_entry(std::istream& in, char * line, account_t * master,
}
if (xact_t * xact = parse_xact(line, master, curr.get())) {
- if (state != xact_t::UNCLEARED &&
- xact->state == xact_t::UNCLEARED)
- xact->state = state;
+ xact->set_state(state);
xact->beg_pos = beg_pos;
xact->beg_line = beg_line;
xact->end_pos = end_pos;
xact->end_line = linenum;
+
pos = end_pos;
curr->add_xact(xact);
@@ -674,9 +675,8 @@ static void clock_out_from_timelog(std::list<time_entry_t>& time_entries,
amt.parse(buf);
assert(amt.valid());
- xact_t * xact
- = new xact_t(event.account, amt, XACT_VIRTUAL);
- xact->state = xact_t::CLEARED;
+ xact_t * xact = new xact_t(event.account, amt, XACT_VIRTUAL);
+ xact->set_state(item_t::CLEARED);
curr->add_xact(xact);
if (! journal.add_entry(curr.get()))
diff --git a/src/xact.cc b/src/xact.cc
index 556a0776..66c08f5b 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -36,48 +36,32 @@
namespace ledger {
-bool xact_t::use_effective_date = false;
-
-xact_t::~xact_t()
+optional<date_t> xact_t::actual_date() const
{
- TRACE_DTOR(xact_t);
+ optional<date_t> date = item_t::actual_date();
+ if (! date && entry)
+ return entry->actual_date();
+ return date;
}
-date_t xact_t::actual_date() const
+optional<date_t> xact_t::effective_date() const
{
- if (! _date && entry)
- return entry->actual_date();
- return *_date;
+ optional<date_t> date = item_t::effective_date();
+ if (! date && entry)
+ return entry->effective_date();
+ return date;
}
-date_t xact_t::effective_date() const
+item_t::state_t xact_t::state() const
{
- if (! _date_eff && entry)
- return entry->effective_date();
- return *_date_eff;
+ state_t entry_state = entry->state();
+ if ((_state == UNCLEARED && entry_state != UNCLEARED) ||
+ (_state == PENDING && entry_state == CLEARED))
+ return entry_state;
+ return _state;
}
namespace {
- value_t get_state(xact_t& xact) {
- return long(xact.state);
- }
-
- value_t state_uncleared(call_scope_t&) {
- return 0L;
- }
-
- value_t state_cleared(call_scope_t&) {
- return 1L;
- }
-
- value_t state_pending(call_scope_t&) {
- return 2L;
- }
-
- value_t get_date(xact_t& xact) {
- return xact.date();
- }
-
value_t get_code(xact_t& xact) {
if (xact.entry->code)
return string_value(*xact.entry->code);
@@ -85,22 +69,6 @@ namespace {
return string_value(empty_string);
}
- value_t get_status(xact_t& xact) {
- xact_t::state_t status;
- xact.entry->get_state(&status);
- return long(status);
- }
- value_t get_cleared(xact_t& xact) {
- xact_t::state_t status;
- xact.entry->get_state(&status);
- return status == xact_t::CLEARED;
- }
- value_t get_pending(xact_t& xact) {
- xact_t::state_t status;
- xact.entry->get_state(&status);
- return status == xact_t::PENDING;
- }
-
value_t get_payee(xact_t& xact) {
return string_value(xact.entry->payee);
}
@@ -125,10 +93,6 @@ namespace {
return xact.cost ? *xact.cost : xact.amount;
}
- value_t get_note(xact_t& xact) {
- return string_value(xact.note ? *xact.note : empty_string);
- }
-
value_t get_account(call_scope_t& scope)
{
xact_t& xact(downcast<xact_t>(*scope.parent));
@@ -153,22 +117,6 @@ namespace {
return string_value(xact.reported_account()->name);
}
- value_t get_beg_pos(xact_t& xact) {
- return long(xact.beg_pos);
- }
-
- value_t get_beg_line(xact_t& xact) {
- return long(xact.beg_line);
- }
-
- value_t get_end_pos(xact_t& xact) {
- return long(xact.end_pos);
- }
-
- value_t get_end_line(xact_t& xact) {
- return long(xact.end_line);
- }
-
template <value_t (*Func)(xact_t&)>
value_t get_wrapper(call_scope_t& scope) {
return (*Func)(find_scope<xact_t>(scope));
@@ -188,68 +136,29 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
break;
case 'c':
- if (name == "cleared")
- return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
- else if (name == "code")
+ if (name == "code")
return WRAP_FUNCTOR(get_wrapper<&get_code>);
break;
- case 'd':
- if (name[1] == '\0' || name == "date")
- return WRAP_FUNCTOR(get_wrapper<&get_date>);
- break;
-
- case 'f':
- if (name.find("fmt_") == 0) {
- switch (name[4]) {
- case 'A':
- return WRAP_FUNCTOR(get_account);
- case 'D':
- return WRAP_FUNCTOR(get_wrapper<&get_date>);
- case 'P':
- return WRAP_FUNCTOR(get_wrapper<&get_payee>);
- }
- }
- break;
-
- case 'n':
- if (name == "note")
- return WRAP_FUNCTOR(get_wrapper<&get_note>);
- break;
-
case 'p':
- if (name == "pending")
- return WRAP_FUNCTOR(get_wrapper<&get_pending>);
- else if (name == "payee")
+ if (name == "payee")
return WRAP_FUNCTOR(get_wrapper<&get_payee>);
break;
- case 's':
- if (name == "status")
- return WRAP_FUNCTOR(get_wrapper<&get_status>);
- break;
-
case 't':
if (name[1] == '\0' || name == "total")
return WRAP_FUNCTOR(get_wrapper<&get_total>);
break;
-
- case 'u':
- if (name == "uncleared")
- return expr_t::op_t::wrap_value(1L);
- break;
-
- case 'X':
- if (name[1] == '\0')
- return WRAP_FUNCTOR(get_wrapper<&get_cleared>);
- break;
-
- case 'Y':
- if (name[1] == '\0')
- return WRAP_FUNCTOR(get_wrapper<&get_pending>);
- break;
}
+
+#if 0
+ // jww (2008-09-19): I don't think we can lookup in entry, because
+ // that means the functor returned would be expecting an entry to be
+ // passed to it, rather than a transaction.
return entry->lookup(name);
+#else
+ return item_t::lookup(name);
+#endif
}
bool xact_t::valid() const
@@ -259,11 +168,6 @@ bool xact_t::valid() const
return false;
}
- if (state != UNCLEARED && state != CLEARED && state != PENDING) {
- DEBUG("ledger.validate", "xact_t: state is bad");
- return false;
- }
-
xacts_list::const_iterator i =
std::find(entry->xacts.begin(),
entry->xacts.end(), this);
@@ -287,11 +191,6 @@ bool xact_t::valid() const
return false;
}
- if (flags() & ~0x003f) {
- DEBUG("ledger.validate", "xact_t: flags are bad");
- return false;
- }
-
return true;
}
diff --git a/src/xact.h b/src/xact.h
index 91630481..01268fc3 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -32,8 +32,7 @@
#ifndef _XACT_H
#define _XACT_H
-#include "utils.h"
-#include "scope.h"
+#include "item.h"
namespace ledger {
@@ -43,90 +42,59 @@ class account_t;
class xact_t;
typedef std::list<xact_t *> xacts_list;
-class xact_t : public supports_flags<>, public scope_t
+class xact_t : public item_t
{
public:
-#define XACT_NORMAL 0x0000 // no flags at all, a basic transaction
-#define XACT_VIRTUAL 0x0001 // the account was specified with (parens)
-#define XACT_BALANCE 0x0002 // the account was specified with [brackets]
-#define XACT_AUTO 0x0004 // transaction created by automated entry
-#define XACT_IN_CACHE 0x0008 // transaction allocated by the binary cache
-#define XACT_CALCULATED 0x0010 // transaction's amount was auto-calculated
-#define XACT_GENERATED 0x0020 // transaction was not found in a journal
-#define XACT_TEMP 0x0040 // transaction is a temporary object
-
- enum state_t { UNCLEARED = 0, CLEARED, PENDING };
-
- entry_t * entry;
- account_t * account;
- state_t state;
+#define XACT_VIRTUAL 0x0100 // the account was specified with (parens)
+#define XACT_BALANCE 0x0200 // the account was specified with [brackets]
+#define XACT_AUTO 0x0400 // transaction created by automated entry
+#define XACT_CALCULATED 0x0800 // transaction's amount was auto-calculated
- optional<date_t> _date;
- optional<date_t> _date_eff;
- optional<string> note;
+ entry_t * entry; // only set for xacts of regular entries
+ account_t * account;
- amount_t amount;
+ amount_t amount; // can be null until finalization
optional<expr_t> amount_expr;
optional<amount_t> cost;
optional<expr_t> cost_expr;
optional<amount_t> assigned_amount;
optional<expr_t> assigned_amount_expr;
- istream_pos_type beg_pos;
- unsigned long beg_line;
- istream_pos_type end_pos;
- unsigned long end_line;
-
- static bool use_effective_date;
-
xact_t(account_t * _account = NULL,
- flags_t _flags = XACT_NORMAL)
- : supports_flags<>(_flags), entry(NULL), account(_account),
- state(UNCLEARED), beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+ flags_t _flags = ITEM_NORMAL)
+ : item_t(_flags),
+ entry(NULL), account(_account)
{
TRACE_CTOR(xact_t, "account_t *, flags_t");
}
- xact_t(account_t * _account,
- const amount_t& _amount,
- flags_t _flags = XACT_NORMAL,
+ xact_t(account_t * _account,
+ const amount_t& _amount,
+ flags_t _flags = ITEM_NORMAL,
const optional<string>& _note = none)
- : supports_flags<>(_flags), entry(NULL), account(_account),
- state(UNCLEARED), note(_note), amount(_amount),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+ : item_t(_flags, _note),
+ entry(NULL), account(_account), amount(_amount)
{
- TRACE_CTOR(xact_t,
- "account_t *, const amount_t&, flags_t, const string&");
+ TRACE_CTOR(xact_t, "account_t *, const amount_t&, flags_t, const optional<string>&");
}
xact_t(const xact_t& xact)
- : supports_flags<>(xact),
- scope_t(),
+ : item_t(xact),
entry(xact.entry),
account(xact.account),
- state(xact.state),
- _date(xact._date),
- _date_eff(xact._date_eff),
- note(xact.note),
amount(xact.amount),
cost(xact.cost),
- beg_pos(xact.beg_pos),
- beg_line(xact.beg_line),
- end_pos(xact.end_pos),
- end_line(xact.end_line),
xdata_(xact.xdata_) // jww (2008-07-19): What are the copy semantics?
{
TRACE_CTOR(xact_t, "copy");
}
- ~xact_t();
-
- date_t actual_date() const;
- date_t effective_date() const;
- date_t date() const {
- if (use_effective_date)
- return effective_date();
- else
- return actual_date();
+ ~xact_t() {
+ TRACE_DTOR(xact_t);
}
+ virtual optional<date_t> actual_date() const;
+ virtual optional<date_t> effective_date() const;
+
+ virtual state_t state() const;
+
bool must_balance() const {
return ! has_flags(XACT_VIRTUAL) || has_flags(XACT_BALANCE);
}
@@ -221,8 +189,7 @@ public:
date_t reported_date() const {
if (xdata_ && is_valid(xdata_->date))
return xdata_->date;
- return
- date();
+ return *date();
}
account_t * reported_account() {
@@ -235,6 +202,8 @@ public:
const account_t * reported_account() const {
return const_cast<xact_t *>(this)->reported_account();
}
+
+ friend class entry_t;
};
} // namespace ledger
diff --git a/src/xml.cc b/src/xml.cc
index 715965cb..b6f139bb 100644
--- a/src/xml.cc
+++ b/src/xml.cc
@@ -64,8 +64,8 @@ static void startElement(void *userData, const char *name, const char **attrs)
else if (std::strcmp(name, "xact") == 0) {
assert(curr_entry);
curr_entry->add_xact(new xact_t);
- if (curr_state != xact_t::UNCLEARED)
- curr_entry->xacts.back()->state = curr_state;
+ if (curr_state != item_t::UNCLEARED)
+ curr_entry->xacts.back()->set_state(curr_state);
}
else if (std::strcmp(name, "commodity") == 0) {
if (string(attrs[0]) == "flags")
@@ -122,10 +122,10 @@ static void endElement(void *userData, const char *name)
curr_entry->xacts.back()->account = curr_journal->find_account(data);
}
else if (std::strcmp(name, "tr:cleared") == 0) {
- curr_entry->xacts.back()->state = xact_t::CLEARED;
+ curr_entry->xacts.back()->set_state(item_t::CLEARED);
}
else if (std::strcmp(name, "tr:pending") == 0) {
- curr_entry->xacts.back()->state = xact_t::PENDING;
+ curr_entry->xacts.back()->set_state(item_t::PENDING);
}
else if (std::strcmp(name, "tr:virtual") == 0) {
curr_entry->xacts.back()->add_flags(XACT_VIRTUAL);
@@ -437,9 +437,9 @@ void format_xml_entries::format_last_entry()
<< "</tr:date_eff>\n";
#endif
- if (xact->state == xact_t::CLEARED)
+ if (xact->state() == item_t::CLEARED)
out << " <tr:cleared/>\n";
- else if (xact->state == xact_t::PENDING)
+ else if (xact->state() == xact_t::PENDING)
out << " <tr:pending/>\n";
if (xact->has_flags(XACT_VIRTUAL))