summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-05-19 07:34:52 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:39:05 -0400
commit3e0f510b296c0b72353f146912bb0225af0a5647 (patch)
tree8ff4098ea790bbaf2b26a13d1b76487fe80b6041
parent5a72d17d026aa6a1bb0cd32f413963ef9f24ab64 (diff)
downloadfork-ledger-3e0f510b296c0b72353f146912bb0225af0a5647.tar.gz
fork-ledger-3e0f510b296c0b72353f146912bb0225af0a5647.tar.bz2
fork-ledger-3e0f510b296c0b72353f146912bb0225af0a5647.zip
More work on the compilation of nodes.
-rw-r--r--src/compile.cc222
-rw-r--r--src/compile.h68
-rw-r--r--src/document.cc2
-rw-r--r--src/document.h2
-rw-r--r--src/journal.cc38
-rw-r--r--src/journal.h13
-rw-r--r--src/main.cc3
-rw-r--r--src/node.cc23
-rw-r--r--src/node.h104
-rw-r--r--src/session.h2
-rw-r--r--src/value.cc10
-rw-r--r--src/xpath.cc9
12 files changed, 362 insertions, 134 deletions
diff --git a/src/compile.cc b/src/compile.cc
index b5d575a0..0b924418 100644
--- a/src/compile.cc
+++ b/src/compile.cc
@@ -30,31 +30,213 @@
*/
#include "compile.h"
+#include "parser.h"
namespace ledger {
namespace xml {
-void entry_node_t::compile()
+void compile_node(node_t& node, xpath_t::scope_t& scope)
{
- typedef std::list<attributes_t::iterator> iterator_list;
-
- iterator_list to_update;
-
- for (attributes_t::iterator i = attributes->begin();
- i != attributes->end();
- i++)
- if (i->first == DATE_ATTR && i->second.is_string())
- //i->second = parse_datetime(i->second.as_string().c_str());
- to_update.push_back(i);
-
- for (iterator_list::iterator i = to_update.begin();
- i != to_update.end();
- i++) {
- attr_pair attr_def = **i;
- attributes->erase(*i);
-
- attr_def.second = parse_datetime(attr_def.second.as_string().c_str());
- attributes->push_back(attr_def);
+ switch (node.name_id()) {
+ case JOURNAL_NODE:
+ downcast<journal_node_t>(node).compile(scope);
+ break;
+ case ENTRY_NODE:
+ downcast<entry_node_t>(node).compile(scope);
+ break;
+ case TRANSACTION_NODE:
+ downcast<transaction_node_t>(node).compile(scope);
+ break;
+
+ default:
+ break;
+ }
+
+ node.compiled = true;
+
+ if (node.is_parent_node())
+ foreach (node_t * child, node.as_parent_node())
+ compile_node(*child, scope);
+}
+
+void journal_node_t::compile(xpath_t::scope_t& scope)
+{
+ if (! journal.get())
+ journal.reset(new journal_t);
+}
+
+void entry_node_t::compile(xpath_t::scope_t& scope)
+{
+ parent_node_t& parent_node(*parent());
+
+ assert(parent_node.name_id() == JOURNAL_NODE);
+ assert(parent_node.is_compiled());
+
+ journal_t * journal = downcast<journal_node_t>(parent_node).journal.get();
+
+ if (! entry.get()) {
+ entry.reset(new entry_t);
+#if 0
+ journal->add_entry(entry.get());
+#endif
+ }
+ entry->journal = journal;
+
+ foreach (attr_pair& attr, *attributes) {
+ if (attr.first == DATE_ATTR && attr.second.is_string())
+ entry->_date = parse_datetime(attr.second.as_string().c_str());
+ else if (attr.first == EFF_DATE_ATTR && attr.second.is_string())
+ entry->_date_eff = parse_datetime(attr.second.as_string().c_str());
+ else if (attr.first == CODE_ATTR)
+ entry->code = attr.second.as_string();
+ }
+}
+
+void transaction_node_t::parse_amount_expr(xpath_t::scope_t& scope,
+ const char * amount_expr)
+{
+ value_t * amount;
+
+ std::istringstream in(amount_expr);
+
+ PUSH_CONTEXT();
+
+ // jww (2006-09-15): Make sure it doesn't gobble up the upcoming @ symbol
+
+ unsigned long beg = (long)in.tellg();
+
+ amount_t temp;
+ temp.parse(in, AMOUNT_PARSE_NO_REDUCE);
+
+ char c;
+ if (! in.eof() && (c = peek_next_nonws(in)) != '@' &&
+ c != ';' && ! in.eof()) {
+ in.seekg(beg, std::ios::beg);
+
+ xpath_t xpath(in, (XPATH_PARSE_NO_REDUCE | XPATH_PARSE_RELAXED |
+ XPATH_PARSE_PARTIAL));
+
+ xpath_t::context_scope_t node_scope(scope, this);
+ amount = &set_attr(AMOUNT_ATTR, xpath.calc(node_scope));
+
+ //unsigned long end = (long)in.tellg();
+ } else {
+ amount = &set_attr(AMOUNT_ATTR, temp);
+ }
+
+ // jww (2007-04-30): This should be a string context, or perhaps a
+ // file context
+ POP_CONTEXT(context("While parsing transaction amount"));
+
+ // Parse the optional cost (@ PER-UNIT-COST, @@ TOTAL-COST)
+
+ unsigned int linenum = -1;
+
+ if (in.good() && ! in.eof()) {
+ char c = peek_next_nonws(in);
+ if (c == '@') {
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Found a price indicator");
+ bool per_unit = true;
+ in.get(c);
+ if (in.peek() == '@') {
+ in.get(c);
+ per_unit = false;
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "And it's for a total price");
+ }
+
+ if (in.good() && ! in.eof()) {
+ amount_t temp;
+
+ PUSH_CONTEXT();
+
+ //unsigned long beg = (long)in.tellg();
+
+ temp.parse(in);
+
+ if (temp.sign() < 0)
+ throw_(parse_error, "A transaction's cost may not be negative");
+
+ //unsigned long end = (long)in.tellg();
+
+ POP_CONTEXT(context("While parsing transaction cost"));
+
+ amount_t per_unit_cost(temp);
+ amount_t& base_amount(amount->as_amount_lval());
+ if (per_unit)
+ temp *= base_amount.number();
+ else
+ per_unit_cost /= base_amount.number();
+
+ value_t& cost = set_attr(COST_ATTR, temp);
+
+ if (base_amount.commodity() && ! base_amount.commodity().annotated) {
+ assert(transaction);
+ assert(transaction->entry);
+ base_amount.annotate_commodity
+ (annotation_t(per_unit_cost, transaction->entry->actual_date(),
+ transaction->entry->code));
+ }
+
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Total cost is " << cost);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Per-unit cost is " << per_unit_cost);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Annotated amount is " << base_amount);
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Bare amount is " << base_amount.number());
+ }
+ }
+ }
+
+ amount->in_place_reduce();
+
+ DEBUG("ledger.textual.parse", "line " << linenum << ": " <<
+ "Reduced amount is " << *amount);
+}
+
+void transaction_node_t::compile(xpath_t::scope_t& scope)
+{
+ parent_node_t& parent_node(*parent());
+
+ assert(parent_node.name_id() == ENTRY_NODE);
+ assert(parent_node.is_compiled());
+
+ entry_t * entry = downcast<entry_node_t>(parent_node).entry.get();
+
+ if (! transaction.get()) {
+ transaction.reset(new transaction_t);
+#if 0
+ entry->add_transaction(transaction.get());
+#endif
+ }
+ transaction->entry = entry;
+
+ foreach (node_t * child, *this) {
+ switch (child->name_id()) {
+ case AMOUNT_EXPR_NODE:
+ parse_amount_expr(scope, child->as_terminal_node().text());
+ break;
+
+ case ACCOUNT_PATH_NODE: {
+ assert(entry);
+
+ journal_t * journal = entry->journal;
+ assert(journal);
+
+ transaction->account =
+ journal->find_account(child->as_terminal_node().text());
+
+ // jww (2007-05-18): Need to set an attribute that refers to the
+ // unique id of the account
+ break;
+ }
+
+ default:
+ break;
+ }
}
}
diff --git a/src/compile.h b/src/compile.h
index 81319345..d8b9f536 100644
--- a/src/compile.h
+++ b/src/compile.h
@@ -38,6 +38,8 @@
namespace ledger {
namespace xml {
+void compile_node(node_t& node, xml::xpath_t::scope_t& scope);
+
#if 0
class commodity_node_t : public parent_node_t
{
@@ -82,6 +84,25 @@ public:
};
#endif
+class journal_node_t : public parent_node_t
+{
+public:
+ shared_ptr<journal_t> journal;
+
+ journal_node_t(nameid_t _name_id,
+ document_t& _document,
+ const optional<parent_node_t&>& _parent = none,
+ journal_t * _journal = NULL)
+ : parent_node_t(_name_id, _document, _parent), journal(_journal) {
+ TRACE_CTOR(journal_node_t, "document_t *, journal_t *, parent_node_t *");
+ }
+ virtual ~journal_node_t() {
+ TRACE_DTOR(journal_node_t);
+ }
+
+ void compile(xpath_t::scope_t& scope);
+};
+
class entry_node_t : public parent_node_t
{
public:
@@ -99,7 +120,7 @@ public:
TRACE_DTOR(entry_node_t);
}
- virtual void compile();
+ void compile(xpath_t::scope_t& scope);
};
class transaction_node_t : public parent_node_t
@@ -120,30 +141,15 @@ public:
virtual ~transaction_node_t() {
TRACE_DTOR(transaction_node_t);
}
-};
-#if 0
-class entry_node_t : public parent_node_t
-{
- entry_t * entry;
+ void compile(xpath_t::scope_t& scope);
-public:
- entry_node_t(document_t * _document, entry_t * _entry,
- parent_node_t * _parent = NULL)
- : parent_node_t(_document, _parent), entry(_entry) {
- TRACE_CTOR(entry_node_t, "document_t *, entry_t *, parent_node_t *");
- set_name(document_t::ENTRY);
- }
- virtual ~entry_node_t() {
- TRACE_DTOR(entry_node_t);
- }
-
- virtual node_t * children() const;
- virtual node_t * lookup_child(int _name_id) const;
-
- friend class transaction_node_t;
+private:
+ void parse_amount_expr(xpath_t::scope_t& scope,
+ const char * amount_expr);
};
+#if 0
class account_node_t : public parent_node_t
{
account_t * account;
@@ -162,26 +168,6 @@ public:
virtual node_t * children() const;
};
-class journal_node_t : public parent_node_t
-{
- journal_t * journal;
-
-public:
- journal_node_t(document_t * _document, journal_t * _journal,
- parent_node_t * _parent = NULL)
- : parent_node_t(_document, _parent), journal(_journal) {
- TRACE_CTOR(journal_node_t, "document_t *, journal_t *, parent_node_t *");
- set_name(document_t::JOURNAL);
- }
- virtual ~journal_node_t() {
- TRACE_DTOR(journal_node_t);
- }
-
- virtual node_t * children() const;
-
- friend class transaction_node_t;
-};
-
template <typename T>
inline typename T::node_type *
wrap_node(document_t * doc, T * item, void * parent_node = NULL) {
diff --git a/src/document.cc b/src/document.cc
index da7db95e..120440b0 100644
--- a/src/document.cc
+++ b/src/document.cc
@@ -40,6 +40,7 @@ namespace {
"account",
"account-path",
"amount",
+ "amount",
"amount-expr",
"arg",
"auto-entry",
@@ -51,6 +52,7 @@ namespace {
"commodity-conversion",
"commodity-nomarket",
"commodity-template",
+ "cost",
"current-year",
"date",
"default-account",
diff --git a/src/document.h b/src/document.h
index 869c89af..c1dcf88e 100644
--- a/src/document.h
+++ b/src/document.h
@@ -41,6 +41,7 @@ namespace xml {
enum ledger_builtins_t {
ACCOUNT_ATTR = 10,
ACCOUNT_PATH_NODE,
+ AMOUNT_ATTR,
AMOUNT_NODE,
AMOUNT_EXPR_NODE,
ARG_ATTR,
@@ -53,6 +54,7 @@ enum ledger_builtins_t {
COMMODITY_CONVERSION_NODE,
COMMODITY_NOMARKET_NODE,
COMMODITY_TEMPLATE_NODE,
+ COST_ATTR,
CURRENT_YEAR_NODE,
DATE_ATTR,
DEFAULT_ACCOUNT_NODE,
diff --git a/src/journal.cc b/src/journal.cc
index 295db452..32e45697 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -83,7 +83,7 @@ bool transaction_t::valid() const
return false;
}
- if (amount && ! amount->valid()) {
+ if (! amount.valid()) {
DEBUG("ledger.validate", "transaction_t: ! amount.valid()");
return false;
}
@@ -122,22 +122,22 @@ bool entry_base_t::finalize()
x++)
if (! (*x)->has_flags(TRANSACTION_VIRTUAL) ||
(*x)->has_flags(TRANSACTION_BALANCE)) {
- optional<amount_t>& p((*x)->cost ? (*x)->cost : (*x)->amount);
+ amount_t& p((*x)->cost ? *(*x)->cost : (*x)->amount);
if (p) {
if (no_amounts) {
- balance = *p;
+ balance = p;
no_amounts = false;
} else {
- balance += *p;
+ balance += p;
}
assert((*x)->amount);
- if ((*x)->cost && (*x)->amount->commodity().annotated) {
+ 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.details.price)
- balance += (*ann_comm.details.price * (*x)->amount->number() -
+ balance += (*ann_comm.details.price * (*x)->amount.number() -
*((*x)->cost));
}
} else {
@@ -170,7 +170,7 @@ bool entry_base_t::finalize()
balance.as_balance().amounts.size() == 2) {
transactions_list::const_iterator x = transactions.begin();
assert((*x)->amount);
- commodity_t& this_comm = (*x)->amount->commodity();
+ commodity_t& this_comm = (*x)->amount.commodity();
balance_t::amounts_map::const_iterator this_bal =
balance.as_balance().amounts.find(&this_comm);
@@ -184,22 +184,21 @@ bool entry_base_t::finalize()
for (; x != transactions.end(); x++) {
if ((*x)->cost || (*x)->has_flags(TRANSACTION_VIRTUAL) ||
- ! (*x)->amount || (*x)->amount->commodity() != this_comm)
+ (*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
(annotation_t(per_unit_cost.abs(),
entry ? entry->actual_date() : optional<moment_t>(),
entry ? entry->code : optional<string>()));
- (*x)->cost = - (per_unit_cost * (*x)->amount->number());
+ (*x)->cost = - (per_unit_cost * (*x)->amount.number());
balance += *(*x)->cost;
}
}
@@ -267,7 +266,7 @@ bool entry_base_t::finalize()
(*x)->amount = balance.as_amount().negate();
(*x)->add_flags(TRANSACTION_CALCULATED);
- balance += *(*x)->amount;
+ balance += (*x)->amount;
break;
default:
@@ -378,7 +377,7 @@ void auto_entry_t::extend_entry(entry_base_t& entry, bool post)
t++) {
amount_t amt;
assert((*t)->amount);
- if (! (*t)->amount->commodity()) {
+ if (! (*t)->amount.commodity()) {
if (! post)
continue;
assert((*i)->amount);
@@ -590,9 +589,8 @@ bool journal_t::add_entry(entry_t * entry)
i++)
if ((*i)->cost) {
assert((*i)->amount);
- assert(*(*i)->amount);
- (*i)->amount->commodity().add_price(entry->date(),
- *(*i)->cost / (*i)->amount->number());
+ (*i)->amount.commodity().add_price(entry->date(),
+ *(*i)->cost / (*i)->amount.number());
}
return true;
diff --git a/src/journal.h b/src/journal.h
index bb987397..b32bdcaa 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -58,10 +58,8 @@ class transaction_t : public supports_flags<>
account_t * account;
optional<moment_t> _date;
optional<moment_t> _date_eff;
- optional<amount_t> amount;
- optional<string> amount_expr;
+ amount_t amount;
optional<amount_t> cost;
- optional<string> cost_expr;
optional<string> note;
static bool use_effective_date;
@@ -88,9 +86,7 @@ class transaction_t : public supports_flags<>
_date(xact._date),
_date_eff(xact._date_eff),
amount(xact.amount),
- amount_expr(xact.amount_expr),
cost(xact.cost),
- cost_expr(xact.cost_expr),
note(xact.note) {
TRACE_CTOR(transaction_t, "copy");
}
@@ -368,12 +364,9 @@ typedef std::list<period_entry_t *> period_entries_list;
typedef std::list<path> path_list;
typedef std::list<string> strings_list;
-class session_t;
-
class journal_t
{
public:
- session_t * session;
account_t * master;
account_t * basket;
entries_list entries;
@@ -388,9 +381,7 @@ class journal_t
std::list<entry_finalizer_t *> entry_finalize_hooks;
- journal_t(session_t * _session)
- : session(_session), basket(NULL),
- item_pool(NULL), item_pool_end(NULL) {
+ journal_t() : basket(NULL), item_pool(NULL), item_pool_end(NULL) {
TRACE_CTOR(journal_t, "");
master = new account_t(NULL, "");
master->journal = this;
diff --git a/src/main.cc b/src/main.cc
index a0bf035b..469bb5ee 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -37,6 +37,7 @@
//#include "qif.h"
//#include "ofx.h"
#include "jbuilder.h"
+#include "compile.h"
#include <ledger.h>
@@ -300,7 +301,7 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
*out << "Compiled results:" << std::endl;
}
- xml_document.compile();
+ xml::compile_node(xml_document, report);
foreach (const value_t& value, xpath.find_all(doc_scope)) {
if (value.is_xml_node())
diff --git a/src/node.cc b/src/node.cc
index b03f5f5a..0ca0a04c 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -40,7 +40,19 @@ const char * node_t::name() const
return *document().lookup_name(name_id());
}
-optional<value_t> node_t::get_attr(const string& _name) const
+value_t& node_t::set_attr(const string& _name, const char * value)
+{
+ nameid_t name_id = document().register_name(_name);
+ return set_attr(name_id, value);
+}
+
+value_t& node_t::set_attr(const string& _name, const value_t& value)
+{
+ nameid_t name_id = document().register_name(_name);
+ return set_attr(name_id, value);
+}
+
+optional<value_t&> node_t::get_attr(const string& _name)
{
optional<nameid_t> name_id = document().lookup_name_id(_name);
if (name_id)
@@ -71,10 +83,17 @@ void output_xml_string(std::ostream& out, const string& str)
void node_t::print_attributes(std::ostream& out) const
{
- if (attributes)
+ if (attributes) {
+#if 1
+ foreach (const attr_pair& attr, *attributes)
+ out << ' ' << *document().lookup_name(attr.first)
+ << "=\"" << attr.second << "\"";
+#else
foreach (const attr_pair& attr, attributes->get<0>())
out << ' ' << *document().lookup_name(attr.first)
<< "=\"" << attr.second << "\"";
+#endif
+ }
IF_VERIFY()
out << " type=\"parent_node_t\"";
diff --git a/src/node.h b/src/node.h
index 8d221049..b0324ca0 100644
--- a/src/node.h
+++ b/src/node.h
@@ -33,7 +33,6 @@
#define _NODE_H
#include "value.h"
-//#include "parser.h"
namespace ledger {
namespace xml {
@@ -42,8 +41,9 @@ namespace xml {
DECLARE_EXCEPTION(conversion_error);
-class parent_node_t;
class document_t;
+class parent_node_t;
+class terminal_node_t;
class node_t : public supports_flags<>, public noncopyable
{
@@ -58,6 +58,10 @@ protected:
document_t& document_;
optional<parent_node_t&> parent_;
+#if 1
+ typedef std::map<const nameid_t, value_t> attributes_t;
+ typedef std::pair<const nameid_t, value_t> attr_pair;
+#else
typedef std::pair<nameid_t, value_t> attr_pair;
typedef multi_index_container<
@@ -69,14 +73,15 @@ protected:
>
> attributes_t;
- optional<attributes_t> attributes;
-
typedef attributes_t::nth_index<0>::type attributes_by_order;
typedef attributes_t::nth_index<1>::type attributes_hashed;
+#endif
- bool compiled;
+ optional<attributes_t> attributes;
public:
+ bool compiled; // so that compile_node() can access it
+
node_t(nameid_t _name_id, document_t& _document,
const optional<parent_node_t&>& _parent = none, flags_t _flags = 0)
: supports_flags<>(_flags), name_id_(_name_id),
@@ -88,10 +93,11 @@ public:
TRACE_DTOR(node_t);
}
+ void extract();
+
bool is_compiled() const {
return compiled;
}
- virtual void compile() {}
bool is_parent_node() const {
return has_flags(XML_NODE_IS_PARENT);
@@ -102,9 +108,19 @@ public:
return downcast<parent_node_t>(*this);
}
const parent_node_t& as_parent_node() const {
- if (! is_parent_node())
- throw_(std::logic_error, "Request to cast leaf node to a parent node");
- return downcast<const parent_node_t>(*this);
+ return const_cast<node_t *>(this)->as_parent_node();
+ }
+
+ bool is_terminal_node() const {
+ return ! has_flags(XML_NODE_IS_PARENT);
+ }
+ terminal_node_t& as_terminal_node() {
+ if (! is_terminal_node())
+ throw_(std::logic_error, "Request to cast parent node to a leaf node");
+ return downcast<terminal_node_t>(*this);
+ }
+ const terminal_node_t& as_terminal_node() const {
+ return const_cast<node_t *>(this)->as_terminal_node();
}
virtual value_t to_value() const = 0;
@@ -123,29 +139,61 @@ public:
return parent_;
}
- void set_attr(const nameid_t _name_id, const char * value) {
- if (! attributes)
- attributes = attributes_t();
- attributes->push_back(attr_pair(_name_id, string_value(value)));
+ value_t& set_attr(const string& _name, const char * value);
+ value_t& set_attr(const string& _name, const value_t& value);
+
+ value_t& set_attr(const nameid_t _name_id, const char * value) {
+ return set_attr(_name_id, string_value(value));
}
- void set_attr(const nameid_t _name_id, const value_t& value) {
+ value_t& set_attr(const nameid_t _name_id, const value_t& value) {
if (! attributes)
attributes = attributes_t();
- attributes->push_back(attr_pair(_name_id, value));
+
+ attributes_t::iterator i = attributes->find(_name_id);
+ if (i == attributes->end()) {
+ std::pair<attributes_t::iterator, bool> result =
+ attributes->insert(attr_pair(_name_id, value));
+ assert(result.second);
+ return (*result.first).second;
+ } else {
+ i->second = value;
+ return i->second;
+ }
}
- optional<value_t> get_attr(const string& _name) const;
- optional<value_t> get_attr(const nameid_t _name_id) const {
+ optional<value_t&> get_attr(const string& _name);
+ optional<value_t&> get_attr(const nameid_t _name_id) {
if (attributes) {
+#if 1
+ attributes_t::iterator i = attributes->find(_name_id);
+ if (i != attributes->end())
+ return (*i).second;
+#else
typedef attributes_t::nth_index<1>::type attributes_by_name;
const attributes_by_name& name_index = attributes->get<1>();
- attributes_by_name::const_iterator i = name_index.find(_name_id);
+ attributes_by_name::iterator i = name_index.find(_name_id);
if (i != name_index.end())
return (*i).second;
+#endif
}
return none;
}
+
+ optional<const value_t&> get_attr(const string& _name) const {
+ if (optional<value_t&> value =
+ const_cast<node_t *>(this)->get_attr(_name))
+ return *value;
+ else
+ return none;
+ }
+ optional<const value_t&> get_attr(const nameid_t _name_id) const {
+ if (optional<value_t&> value =
+ const_cast<node_t *>(this)->get_attr(_name_id))
+ return *value;
+ else
+ return none;
+ }
};
class parent_node_t : public node_t
@@ -177,11 +225,6 @@ public:
clear_children();
}
- virtual void compile() {
- foreach (node_t * child, *this)
- child->compile();
- }
-
template <typename T>
T * create_child(nameid_t _name_id) {
T * child = new T(_name_id, document(), *this);
@@ -189,14 +232,17 @@ public:
return child;
}
- void delete_child(node_t * child) {
+ void remove_child(node_t * child) {
children_by_ptr& ptr_index = children.get<2>();
children_by_ptr::iterator i = ptr_index.find(child);
if (i == ptr_index.end())
throw_(std::logic_error, "Request to delete node which is not a child");
- node_t * ptr = *i;
ptr_index.erase(i);
- checked_delete(ptr);
+ }
+
+ void delete_child(node_t * child) {
+ remove_child(child);
+ checked_delete(child);
}
struct match_nameid {
@@ -262,6 +308,12 @@ public:
void print(std::ostream& out) const;
};
+inline void node_t::extract()
+{
+ if (parent_)
+ parent_->remove_child(this);
+}
+
class terminal_node_t : public node_t
{
string data;
diff --git a/src/session.h b/src/session.h
index 206144c6..43d7d722 100644
--- a/src/session.h
+++ b/src/session.h
@@ -85,7 +85,7 @@ class session_t : public xml::xpath_t::symbol_scope_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/value.cc b/src/value.cc
index 25145695..2985df45 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1203,20 +1203,20 @@ void value_t::in_place_reduce()
{
switch (type()) {
case INTEGER:
- break;
+ return;
case AMOUNT:
as_amount_lval().in_place_reduce();
- break;
+ return;
case BALANCE:
as_balance_lval().in_place_reduce();
- break;
+ return;
case BALANCE_PAIR:
as_balance_pair_lval().in_place_reduce();
- break;
+ return;
case XML_NODE:
*this = as_xml_node()->to_value();
in_place_reduce(); // recurse
- break;
+ return;
default:
break;
}
diff --git a/src/xpath.cc b/src/xpath.cc
index 98988c64..f779ebc6 100644
--- a/src/xpath.cc
+++ b/src/xpath.cc
@@ -1208,16 +1208,11 @@ value_t xpath_t::op_t::calc(scope_t& scope)
case ATTR_ID:
case ATTR_NAME:
- if (optional<value_t> value =
+ if (optional<value_t&> value =
kind == ATTR_ID ? current_xml_node(scope).get_attr(as_name()) :
current_xml_node(scope).get_attr(as_string()))
return *value;
- else
- throw_(calc_error, "Attribute '"
- << (kind == ATTR_ID ?
- *current_xml_node(scope).document().lookup_name(as_long()) :
- as_string().c_str())
- << "' was not found");
+
break;
case O_NEQ: