summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2007-05-14 11:09:54 +0000
committerJohn Wiegley <johnw@newartisans.com>2008-04-13 03:38:50 -0400
commitf83705b847c59a8197f5098cb7dc2d484704e24d (patch)
tree1b314d07bb9f50a75781d703ec6c778056e74684
parent65af1688382331d91153fb2366026e94feb5afe2 (diff)
downloadfork-ledger-f83705b847c59a8197f5098cb7dc2d484704e24d.tar.gz
fork-ledger-f83705b847c59a8197f5098cb7dc2d484704e24d.tar.bz2
fork-ledger-f83705b847c59a8197f5098cb7dc2d484704e24d.zip
Changed xpath to use intrusive_ptr; got the xml command working
-rw-r--r--Makefile.am4
-rw-r--r--src/journal.cc5
-rw-r--r--src/journal.h82
-rw-r--r--src/ledger.h12
-rw-r--r--src/main.cc57
-rw-r--r--src/node.h7
-rw-r--r--src/option.cc63
-rw-r--r--src/parser.h6
-rw-r--r--src/pyinterp.cc4
-rw-r--r--src/pyinterp.h16
-rw-r--r--src/report.cc51
-rw-r--r--src/report.h4
-rw-r--r--src/session.cc65
-rw-r--r--src/session.h21
-rw-r--r--src/system.hh2
-rw-r--r--src/textual.cc11
-rw-r--r--src/textual.h6
-rw-r--r--src/transform.cc34
-rw-r--r--src/transform.h30
-rw-r--r--src/xpath.cc1316
-rw-r--r--src/xpath.h518
21 files changed, 924 insertions, 1390 deletions
diff --git a/Makefile.am b/Makefile.am
index d99c2538..7481a105 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,7 @@ libledger_la_SOURCES = \
src/utils.cc \
src/times.cc \
src/mask.cc \
+ src/abbrev.cc \
src/commodity.cc \
src/amount.cc \
src/balance.cc \
@@ -49,7 +50,6 @@ libledger_la_SOURCES = \
src/textual.cc \
src/binary.cc \
src/transform.cc \
- src/register.cc \
src/report.cc \
src/session.cc
@@ -94,6 +94,7 @@ libpyledger_la_SOURCES = \
pkginclude_HEADERS = \
+ src/abbrev.h \
src/amount.h \
src/balance.h \
src/balpair.h \
@@ -113,7 +114,6 @@ pkginclude_HEADERS = \
src/pyinterp.h \
src/pyledger.h \
src/pyutils.h \
- src/register.h \
src/report.h \
src/scoped_execute.h \
src/session.h \
diff --git a/src/journal.cc b/src/journal.cc
index 7fe6b285..9ff42832 100644
--- a/src/journal.cc
+++ b/src/journal.cc
@@ -293,7 +293,7 @@ bool entry_base_t::finalize()
entry_t::entry_t(const entry_t& e)
: entry_base_t(e), _date(e._date), _date_eff(e._date_eff),
- code(e.code), payee(e.payee), data(NULL)
+ code(e.code), payee(e.payee)
{
TRACE_CTOR(entry_t, "copy");
for (transactions_list::const_iterator i = transactions.begin();
@@ -538,9 +538,6 @@ journal_t::~journal_t()
assert(master);
checked_delete(master);
- if (document)
- checked_delete(document);
-
// Don't bother unhooking each entry's transactions from the
// accounts they refer to, because all accounts are about to
// be deleted.
diff --git a/src/journal.h b/src/journal.h
index 51f13f42..bb987397 100644
--- a/src/journal.h
+++ b/src/journal.h
@@ -33,19 +33,10 @@
#define _JOURNAL_H
#include "amount.h"
+#include "xpath.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
@@ -72,43 +63,20 @@ class transaction_t : public supports_flags<>
optional<amount_t> cost;
optional<string> cost_expr;
optional<string> note;
- unsigned long beg_pos;
- unsigned long beg_line;
- unsigned long end_pos;
- unsigned long end_line;
-
- typedef xml::transaction_node_t node_type;
- mutable node_type * data;
static bool use_effective_date;
explicit transaction_t(account_t * _account = NULL)
- : supports_flags<>(TRANSACTION_NORMAL),
- entry(NULL),
- state(UNCLEARED),
- account(_account),
- beg_pos(0),
- beg_line(0),
- end_pos(0),
- end_line(0),
- data(NULL) {
+ : supports_flags<>(TRANSACTION_NORMAL), entry(NULL),
+ state(UNCLEARED), account(_account) {
TRACE_CTOR(transaction_t, "account_t *");
}
explicit transaction_t(account_t * _account,
const amount_t& _amount,
unsigned int _flags = TRANSACTION_NORMAL,
const optional<string> _note = none)
- : supports_flags<>(_flags),
- entry(NULL),
- state(UNCLEARED),
- account(_account),
- amount(_amount),
- note(_note),
- beg_pos(0),
- beg_line(0),
- end_pos(0),
- end_line(0),
- data(NULL) {
+ : supports_flags<>(_flags), entry(NULL), state(UNCLEARED),
+ account(_account), amount(_amount), note(_note) {
TRACE_CTOR(transaction_t,
"account_t *, const amount_t&, unsigned int, const string&");
}
@@ -123,12 +91,7 @@ class transaction_t : public supports_flags<>
amount_expr(xact.amount_expr),
cost(xact.cost),
cost_expr(xact.cost_expr),
- note(xact.note),
- beg_pos(xact.beg_pos),
- beg_line(xact.beg_line),
- end_pos(xact.end_pos),
- end_line(xact.end_line),
- data(xact.data) {
+ note(xact.note) {
TRACE_CTOR(transaction_t, "copy");
}
~transaction_t();
@@ -164,19 +127,12 @@ class entry_base_t
{
public:
journal_t * journal;
- unsigned long src_idx;
- unsigned long beg_pos;
- unsigned long beg_line;
- unsigned long end_pos;
- unsigned long end_line;
transactions_list transactions;
- entry_base_t() : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0) {
+ entry_base_t() : journal(NULL) {
TRACE_CTOR(entry_base_t, "");
}
- entry_base_t(const entry_base_t& e) : journal(NULL),
- beg_pos(0), beg_line(0), end_pos(0), end_line(0)
+ entry_base_t(const entry_base_t& e) : journal(NULL)
{
TRACE_CTOR(entry_base_t, "copy");
for (transactions_list::const_iterator i = e.transactions.begin();
@@ -217,10 +173,7 @@ public:
optional<string> code;
string payee;
- typedef xml::entry_node_t node_type;
- mutable node_type * data;
-
- entry_t() : data(NULL) {
+ entry_t() {
TRACE_CTOR(entry_t, "");
}
entry_t(const entry_t& e);
@@ -337,9 +290,6 @@ class account_t
unsigned short depth;
accounts_map accounts;
- typedef xml::account_node_t node_type;
- mutable node_type * data;
-
mutable ident_t ident;
mutable string _fullname;
@@ -347,7 +297,7 @@ class account_t
const string& _name = "",
const optional<string> _note = none)
: parent(_parent), name(_name), note(_note),
- depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {
+ depth(parent ? parent->depth + 1 : 0), ident(0) {
TRACE_CTOR(account_t, "account_t *, const string&, const string&");
}
~account_t();
@@ -432,16 +382,6 @@ class journal_t
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).
- 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;
mutable accounts_map accounts_cache;
@@ -450,7 +390,7 @@ class journal_t
journal_t(session_t * _session)
: session(_session), basket(NULL),
- item_pool(NULL), item_pool_end(NULL), document(NULL) {
+ item_pool(NULL), item_pool_end(NULL) {
TRACE_CTOR(journal_t, "");
master = new account_t(NULL, "");
master->journal = this;
diff --git a/src/ledger.h b/src/ledger.h
index c9f0f9c4..c1d0ef1d 100644
--- a/src/ledger.h
+++ b/src/ledger.h
@@ -46,24 +46,12 @@
#include <value.h>
#include <xpath.h>
#include <format.h>
-//#include <quotes.h>
-
#include <session.h>
#include <journal.h>
#include <parser.h>
#include <textual.h>
#include <binary.h>
-
#include <report.h>
#include <transform.h>
-#include <register.h>
-
-#if 0
-#include <emacs.h>
-#include <csv.h>
-#include <derive.h>
-#include <reconcile.h>
-#endif
-
#endif // _LEDGER_H
diff --git a/src/main.cc b/src/main.cc
index 945587b1..9ef00571 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -116,18 +116,17 @@ static int read_and_report(report_t * report, int argc, char * argv[],
string verb = *arg++;
- std::auto_ptr<xml::xpath_t::functor_t> command;
+ xml::xpath_t::function_t command;
+#if 0
if (verb == "register" || verb == "reg" || verb == "r") {
-#if 1
- command.reset(new register_command);
-#else
+ command = register_command();
+#if 0
command = new format_command
("register", either_or(report->format_string,
report->session->register_format));
#endif
}
-#if 0
else if (verb == "balance" || verb == "bal" || verb == "b") {
if (! report->raw_mode) {
report->transforms.push_back(new accounts_transform);
@@ -166,9 +165,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
command = new csv_command;
else if (verb == "emacs" || verb == "lisp")
command = new emacs_command;
+ else
#endif
- else if (verb == "xml")
- command.reset(new xml_command);
+ if (verb == "xml")
+ command = xml_command();
else if (verb == "expr")
;
else if (verb == "xpath")
@@ -198,10 +198,10 @@ static int read_and_report(report_t * report, int argc, char * argv[],
// jww (2007-04-19): This is an error, since command is an
// auto_ptr!
- if (xml::xpath_t::op_t * def = report->lookup(buf))
- command.reset(def->functor_obj());
+ if (xml::xpath_t::ptr_op_t def = report->lookup(buf))
+ command = def->as_function();
- if (! command.get())
+ if (! command)
throw_(std::logic_error, string("Unrecognized command '") + verb + "'");
}
@@ -211,23 +211,15 @@ static int read_and_report(report_t * report, int argc, char * argv[],
session.read_init();
INFO_START(journal, "Read journal file");
- journal_t * journal = session.read_data(report->account);
- {
- textual_parser_t text_parser;
- ifstream input(session.data_file);
-#if 1
- xml::document_t temp(xml::LEDGER_NODE);
- xml::document_builder_t builder(temp);
- text_parser.parse(input, session.data_file, builder);
- temp.print(std::cout);
-#else
- xml::xml_writer_t writer(std::cout);
- text_parser.parse(input, session.data_file, writer);
-#endif
- }
+ xml::document_t xml_document(xml::LEDGER_NODE);
+ xml::document_builder_t builder(xml_document);
+ journal_t * journal = session.create_journal();
+ if (! session.read_data(builder, journal, report->account))
+ throw_(parse_error, "Failed to locate any journal entries; "
+ "did you specify a valid file with -f?");
+
INFO_FINISH(journal);
- return 0;
TRACE_FINISH(entry_text, 1);
TRACE_FINISH(entry_date, 1);
@@ -300,8 +292,7 @@ static int read_and_report(report_t * report, int argc, char * argv[],
*out << "Result of calculation: ";
}
- xml::document_t temp(xml::LEDGER_NODE);
- *out << expr.calc(temp, report).strip_annotations() << std::endl;
+ *out << expr.calc(xml_document, report).strip_annotations() << std::endl;
return 0;
}
@@ -322,13 +313,14 @@ static int read_and_report(report_t * report, int argc, char * argv[],
// Create the an argument scope containing the report command's
// arguments, and then invoke the command.
- std::auto_ptr<xml::xpath_t::scope_t> locals
+ scoped_ptr<xml::xpath_t::scope_t> locals
(new xml::xpath_t::scope_t(report, xml::xpath_t::scope_t::ARGUMENT));
locals->args = value_t::sequence_t();
locals->args.push_back(out);
- locals->args.push_back(journal->document);
+ locals->args.push_back(&xml_document);
+#if 0
if (command->wants_args) {
for (strings_list::iterator i = args.begin();
i != args.end();
@@ -381,14 +373,15 @@ static int read_and_report(report_t * report, int argc, char * argv[],
(string("//xact[account =~ /(") + regexps[0] + ")/]"));
#endif
}
+#endif
INFO_START(transforms, "Applied transforms");
- report->apply_transforms(journal->document);
+ report->apply_transforms(xml_document);
INFO_FINISH(transforms);
INFO_START(command, "Did user command '" << verb << "'");
value_t temp;
- (*command)(temp, locals.get());
+ command(temp, locals.get());
INFO_FINISH(command);
// Write out the binary cache, if need be
@@ -483,8 +476,8 @@ int main(int argc, char * argv[], char * envp[])
session->register_parser(new ofx_parser_t);
#endif
session->register_parser(new qif_parser_t);
- session->register_parser(new textual_parser_t);
#endif
+ session->register_parser(new textual_parser_t);
std::auto_ptr<ledger::report_t> report(new ledger::report_t(session.get()));
diff --git a/src/node.h b/src/node.h
index 20e741c7..5bc254ff 100644
--- a/src/node.h
+++ b/src/node.h
@@ -32,17 +32,10 @@
#ifndef _NODE_H
#define _NODE_H
-#include "journal.h"
#include "value.h"
//#include "parser.h"
namespace ledger {
-
-class transaction_t;
-class entry_t;
-class account_t;
-class journal_t;
-
namespace xml {
#define XML_NODE_IS_PARENT 0x1
diff --git a/src/option.cc b/src/option.cc
index dd0dad4b..24ee9bfe 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -40,8 +40,8 @@ static ledger::option_t * find_option(const string& name);
namespace ledger {
namespace {
- xml::xpath_t::op_t * find_option(xml::xpath_t::scope_t * scope,
- const string& name)
+ xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope,
+ const string& name)
{
char buf[128];
std::strcpy(buf, "option_");
@@ -57,7 +57,7 @@ namespace {
return scope->lookup(buf);
}
- xml::xpath_t::op_t * find_option(xml::xpath_t::scope_t * scope,
+ xml::xpath_t::ptr_op_t find_option(xml::xpath_t::scope_t * scope,
const char letter)
{
char buf[9];
@@ -68,20 +68,20 @@ namespace {
return scope->lookup(buf);
}
- void process_option(xml::xpath_t::functor_t * opt, xml::xpath_t::scope_t * scope,
- const char * arg)
+ void process_option(const xml::xpath_t::function_t& opt,
+ xml::xpath_t::scope_t * scope, const char * arg)
{
#if 0
try {
#endif
- std::auto_ptr<xml::xpath_t::scope_t> args;
+ scoped_ptr<xml::xpath_t::scope_t> args;
if (arg) {
args.reset(new xml::xpath_t::scope_t(scope, xml::xpath_t::scope_t::ARGUMENT));
args->args.set_string(arg);
}
value_t temp;
- (*opt)(temp, args.get());
+ opt(temp, args.get());
#if 0
}
catch (error * err) {
@@ -99,13 +99,10 @@ namespace {
bool process_option(const string& name, xml::xpath_t::scope_t * scope,
const char * arg)
{
- std::auto_ptr<xml::xpath_t::op_t> opt(find_option(scope, name));
- if (opt.get()) {
- xml::xpath_t::functor_t * def = opt->functor_obj();
- if (def) {
- process_option(def, scope, arg);
- return true;
- }
+ xml::xpath_t::ptr_op_t opt(find_option(scope, name));
+ if (opt) {
+ process_option(opt->as_function(), scope, arg);
+ return true;
}
return false;
}
@@ -134,7 +131,7 @@ void process_environment(const char ** envp, const string& tag,
#if 0
try {
#endif
- if (! process_option(buf, scope, q + 1))
+ if (! process_option(string(buf), scope, q + 1))
#if 0
throw new option_error("unknown option")
#endif
@@ -181,50 +178,37 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
value = p;
}
- std::auto_ptr<xml::xpath_t::op_t> opt(find_option(scope, name));
- if (! opt.get())
- throw_(option_error, "illegal option --" << name);
-
- xml::xpath_t::functor_t * def = opt->functor_obj();
- if (! def)
+ xml::xpath_t::ptr_op_t opt(find_option(scope, name));
+ if (! opt)
throw_(option_error, "illegal option --" << name);
- if (def->wants_args && value == NULL) {
+ if (/*def->wants_args &&*/ value == NULL) {
value = *++i;
if (value == NULL)
throw_(option_error, "missing option argument for --" << name);
}
- process_option(def, scope, value);
+ process_option(opt->as_function(), scope, value);
}
else if ((*i)[1] == '\0') {
throw_(option_error, "illegal option -");
}
else {
- std::list<xml::xpath_t::op_t *> option_queue;
+ std::list<xml::xpath_t::ptr_op_t> option_queue;
int x = 1;
for (char c = (*i)[x]; c != '\0'; x++, c = (*i)[x]) {
- xml::xpath_t::op_t * opt = find_option(scope, c);
+ xml::xpath_t::ptr_op_t opt = find_option(scope, c);
if (! opt)
throw_(option_error, "illegal option -" << c);
- xml::xpath_t::functor_t * def = opt->functor_obj();
- if (! def)
- throw_(option_error, "illegal option -" << c);
-
option_queue.push_back(opt);
}
- for (std::list<xml::xpath_t::op_t *>::iterator
- o = option_queue.begin();
- o != option_queue.end();
- o++) {
+ foreach (xml::xpath_t::ptr_op_t& o, option_queue) {
char * value = NULL;
-
- xml::xpath_t::functor_t * def = (*o)->functor_obj();
- assert(def);
-
+#if 0
if (def->wants_args) {
+#endif
value = *++i;
if (value == NULL)
throw_(option_error, "missing option argument for -" <<
@@ -234,10 +218,11 @@ void process_arguments(int argc, char ** argv, const bool anywhere,
'?'
#endif
);
+#if 0
}
- process_option(def, scope, value);
+#endif
+ process_option(o->as_function(), scope, value);
- checked_delete(*o);
}
}
}
diff --git a/src/parser.h b/src/parser.h
index 7cb1cd49..ecc73a6f 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -47,9 +47,9 @@ class parser_t
virtual bool test(std::istream& in) const = 0;
- virtual void parse(std::istream& in,
- const path& pathname,
- xml::builder_t& builder) = 0;
+ virtual std::size_t parse(std::istream& in,
+ const path& pathname,
+ xml::builder_t& builder) = 0;
};
DECLARE_EXCEPTION(parse_error);
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index b687ec05..fbc2eab4 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -198,7 +198,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
else if (PyObject * err = PyErr_Occurred()) {
PyErr_Print();
throw_(xml::xpath_t::calc_error,
- "While calling Python function '" << name() << "'");
+ "While calling Python function '" /*<< name() <<*/ "'");
} else {
assert(false);
}
@@ -210,7 +210,7 @@ void python_interpreter_t::functor_t::operator()(value_t& result,
catch (const error_already_set&) {
PyErr_Print();
throw_(xml::xpath_t::calc_error,
- "While calling Python function '" << name() << "'");
+ "While calling Python function '" /*<< name() <<*/ "'");
}
}
diff --git a/src/pyinterp.h b/src/pyinterp.h
index 1cfbd8d9..aee002f9 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -70,26 +70,24 @@ class python_interpreter_t : public xml::xpath_t::scope_t
return eval(str, mode);
}
- class functor_t : public xml::xpath_t::functor_t {
+ class functor_t {
protected:
boost::python::object func;
public:
- functor_t(const string& name, boost::python::object _func)
- : xml::xpath_t::functor_t(name), func(_func) {}
-
+ functor_t(const string& name, boost::python::object _func) : func(_func) {}
virtual void operator()(value_t& result, xml::xpath_t::scope_t * locals);
};
- virtual void define(const string& name, xml::xpath_t::op_t * def) {
+ virtual void define(const string& name, xml::xpath_t::ptr_op_t def) {
// Pass any definitions up to our parent
parent->define(name, def);
}
- virtual xml::xpath_t::op_t * lookup(const string& name) {
- boost::python::object func = eval(name);
- if (! func)
+ virtual xml::xpath_t::ptr_op_t lookup(const string& name) {
+ if (boost::python::object func = eval(name))
+ return xml::xpath_t::wrap_functor(functor_t(name, func));
+ else
return parent ? parent->lookup(name) : NULL;
- return xml::xpath_t::wrap_functor(new functor_t(name, func));
}
class lambda_t : public functor_t {
diff --git a/src/report.cc b/src/report.cc
index 4e90f680..31acfde0 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -38,12 +38,10 @@ report_t::~report_t()
TRACE_DTOR(report_t);
}
-void report_t::apply_transforms(xml::document_t * document)
+void report_t::apply_transforms(xml::document_t& document)
{
- for (ptr_list<transform_t>::iterator i = transforms.begin();
- i != transforms.end();
- i++)
- i->execute(document);
+ foreach (transform_t& transform, transforms)
+ transform.execute(document);
}
void report_t::abbrev(value_t& result, xml::xpath_t::scope_t * locals)
@@ -107,7 +105,7 @@ bool report_t::resolve(const string& name, value_t& result,
return xml::xpath_t::scope_t::resolve(name, result, locals);
}
-xml::xpath_t::op_t * report_t::lookup(const string& name)
+xml::xpath_t::ptr_op_t report_t::lookup(const string& name)
{
const char * p = name.c_str();
switch (*p) {
@@ -122,88 +120,91 @@ xml::xpath_t::op_t * report_t::lookup(const string& name)
else
#endif
if (std::strcmp(p, "amount") == 0)
- return MAKE_FUNCTOR(report_t, option_amount);
+ return MAKE_FUNCTOR(report_t::option_amount);
break;
case 'b':
if (std::strcmp(p, "bar") == 0)
- return MAKE_FUNCTOR(report_t, option_bar);
+ return MAKE_FUNCTOR(report_t::option_bar);
break;
#if 0
case 'c':
if (std::strcmp(p, "clean") == 0)
- return MAKE_FUNCTOR(report_t, option_clean);
+ return MAKE_FUNCTOR(report_t::option_clean);
else if (std::strcmp(p, "compact") == 0)
- return MAKE_FUNCTOR(report_t, option_compact);
+ return MAKE_FUNCTOR(report_t::option_compact);
break;
#endif
case 'e':
#if 0
if (std::strcmp(p, "entries") == 0)
- return MAKE_FUNCTOR(report_t, option_entries);
+ return MAKE_FUNCTOR(report_t::option_entries);
else if (std::strcmp(p, "eval") == 0)
- return MAKE_FUNCTOR(report_t, option_eval);
+ return MAKE_FUNCTOR(report_t::option_eval);
else if (std::strcmp(p, "exclude") == 0)
- return MAKE_FUNCTOR(report_t, option_remove);
+ return MAKE_FUNCTOR(report_t::option_remove);
#endif
break;
case 'f':
+#if 0
if (std::strcmp(p, "foo") == 0)
- return MAKE_FUNCTOR(report_t, option_foo);
- else if (std::strcmp(p, "format") == 0)
- return MAKE_FUNCTOR(report_t, option_format);
+ return MAKE_FUNCTOR(report_t::option_foo);
+ else
+#endif
+ if (std::strcmp(p, "format") == 0)
+ return MAKE_FUNCTOR(report_t::option_format);
break;
case 'i':
#if 0
if (std::strcmp(p, "include") == 0)
- return MAKE_FUNCTOR(report_t, option_select);
+ return MAKE_FUNCTOR(report_t::option_select);
#endif
break;
case 'l':
#if 0
if (! *(p + 1) || std::strcmp(p, "limit") == 0)
- return MAKE_FUNCTOR(report_t, option_limit);
+ return MAKE_FUNCTOR(report_t::option_limit);
#endif
break;
#if 0
case 'm':
if (std::strcmp(p, "merge") == 0)
- return MAKE_FUNCTOR(report_t, option_merge);
+ return MAKE_FUNCTOR(report_t::option_merge);
break;
#endif
case 'r':
#if 0
if (std::strcmp(p, "remove") == 0)
- return MAKE_FUNCTOR(report_t, option_remove);
+ return MAKE_FUNCTOR(report_t::option_remove);
#endif
break;
#if 0
case 's':
if (std::strcmp(p, "select") == 0)
- return MAKE_FUNCTOR(report_t, option_select);
+ return MAKE_FUNCTOR(report_t::option_select);
else if (std::strcmp(p, "split") == 0)
- return MAKE_FUNCTOR(report_t, option_split);
+ return MAKE_FUNCTOR(report_t::option_split);
break;
#endif
case 't':
if (! *(p + 1))
- return MAKE_FUNCTOR(report_t, option_amount);
+ return MAKE_FUNCTOR(report_t::option_amount);
else if (std::strcmp(p, "total") == 0)
- return MAKE_FUNCTOR(report_t, option_total);
+ return MAKE_FUNCTOR(report_t::option_total);
break;
case 'T':
if (! *(p + 1))
- return MAKE_FUNCTOR(report_t, option_total);
+ return MAKE_FUNCTOR(report_t::option_total);
break;
}
}
diff --git a/src/report.h b/src/report.h
index 51ee9386..0e0c30ad 100644
--- a/src/report.h
+++ b/src/report.h
@@ -74,7 +74,7 @@ class report_t : public xml::xpath_t::scope_t
virtual ~report_t();
- void apply_transforms(xml::document_t * document);
+ void apply_transforms(xml::document_t& document);
//
// Utility functions for value expressions
@@ -163,7 +163,7 @@ class report_t : public xml::xpath_t::scope_t
virtual bool resolve(const string& name, value_t& result,
xml::xpath_t::scope_t * locals);
- virtual xml::xpath_t::op_t * lookup(const string& name);
+ virtual xml::xpath_t::ptr_op_t lookup(const string& name);
};
string abbrev(const string& str, unsigned int width,
diff --git a/src/session.cc b/src/session.cc
index b94dc290..0affd370 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -68,24 +68,24 @@ void release_session_context()
#endif
}
-void session_t::read_journal(std::istream& in,
- const path& pathname,
- xml::builder_t& builder)
+std::size_t session_t::read_journal(std::istream& in,
+ const path& pathname,
+ xml::builder_t& builder)
{
#if 0
if (! master)
master = journal->master;
#endif
- for (ptr_list<parser_t>::iterator i = parsers.begin();
- i != parsers.end();
- i++)
- if (i->test(in))
- i->parse(in, pathname, builder);
+ foreach (parser_t& parser, parsers)
+ if (parser.test(in))
+ return parser.parse(in, pathname, builder);
+
+ return 0;
}
-void session_t::read_journal(const path& pathname,
- xml::builder_t& builder)
+std::size_t session_t::read_journal(const path& pathname,
+ xml::builder_t& builder)
{
#if 0
journal->sources.push_back(pathname);
@@ -95,7 +95,7 @@ void session_t::read_journal(const path& pathname,
throw_(std::logic_error, "Cannot read file" << pathname);
ifstream stream(pathname);
- read_journal(stream, pathname, builder);
+ return read_journal(stream, pathname, builder);
}
void session_t::read_init()
@@ -111,21 +111,16 @@ void session_t::read_init()
// jww (2006-09-15): Read initialization options here!
}
-journal_t * session_t::read_data(const string& master_account)
+std::size_t session_t::read_data(xml::builder_t& builder,
+ journal_t * journal,
+ const string& master_account)
{
-#if 1
- return NULL;
-#else
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();
- journal->document = new xml::document_t;
- journal->document->set_top(xml::wrap_node(journal->document, journal));
-
- unsigned int entry_count = 0;
+ std::size_t entry_count = 0;
DEBUG("ledger.cache", "3. use_cache = " << use_cache);
@@ -136,8 +131,7 @@ journal_t * session_t::read_data(const string& master_account)
scoped_variable<optional<path> >
save_price_db(journal->price_db, price_db);
- ifstream stream(*cache_file);
- entry_count += read_journal(stream, journal, NULL, data_file);
+ entry_count += read_journal(*cache_file, builder);
if (entry_count > 0)
cache_dirty = false;
}
@@ -150,7 +144,7 @@ journal_t * session_t::read_data(const string& master_account)
journal->price_db = price_db;
if (journal->price_db && exists(*journal->price_db)) {
- if (read_journal(*journal->price_db, journal)) {
+ if (read_journal(*journal->price_db, builder)) {
throw_(parse_error, "Entries not allowed in price history file");
} else {
DEBUG("ledger.cache",
@@ -163,10 +157,10 @@ journal_t * session_t::read_data(const string& master_account)
if (data_file == "-") {
use_cache = false;
journal->sources.push_back("<stdin>");
- entry_count += read_journal(std::cin, journal, acct);
+ entry_count += read_journal(std::cin, "<stdin>", builder);
}
else if (exists(data_file)) {
- entry_count += read_journal(data_file, journal, acct);
+ entry_count += read_journal(data_file, builder);
if (journal->price_db)
journal->sources.push_back(*journal->price_db);
}
@@ -174,14 +168,9 @@ journal_t * session_t::read_data(const string& master_account)
VERIFY(journal->valid());
- if (entry_count == 0)
- throw_(parse_error, "Failed to locate any journal entries; "
- "did you specify a valid file with -f?");
-
TRACE_STOP(parser, 1);
- return journal;
-#endif
+ return entry_count;
}
bool session_t::resolve(const string& name, value_t& result,
@@ -221,7 +210,7 @@ bool session_t::resolve(const string& name, value_t& result,
return xml::xpath_t::scope_t::resolve(name, result, locals);
}
-xml::xpath_t::op_t * session_t::lookup(const string& name)
+xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
{
const char * p = name.c_str();
switch (*p) {
@@ -231,24 +220,26 @@ xml::xpath_t::op_t * session_t::lookup(const string& name)
switch (*p) {
case 'd':
if (std::strcmp(p, "debug") == 0)
- return MAKE_FUNCTOR(session_t, option_debug);
+ return MAKE_FUNCTOR(session_t::option_debug);
break;
case 'f':
if (! *(p + 1) || std::strcmp(p, "file") == 0)
- return MAKE_FUNCTOR(session_t, option_file);
+ return MAKE_FUNCTOR(session_t::option_file);
break;
case 't':
if (std::strcmp(p, "trace") == 0)
- return MAKE_FUNCTOR(session_t, option_trace);
+ return MAKE_FUNCTOR(session_t::option_trace);
break;
case 'v':
+#if 0
if (! *(p + 1) || std::strcmp(p, "verbose") == 0)
- return MAKE_FUNCTOR(session_t, option_verbose);
+ return MAKE_FUNCTOR(session_t::option_verbose);
else if (std::strcmp(p, "verify") == 0)
- return MAKE_FUNCTOR(session_t, option_verify);
+ return MAKE_FUNCTOR(session_t::option_verify);
+#endif
break;
}
}
diff --git a/src/session.h b/src/session.h
index cf75b600..0fdd2881 100644
--- a/src/session.h
+++ b/src/session.h
@@ -32,9 +32,10 @@
#ifndef _SESSION_H
#define _SESSION_H
+#include "xpath.h"
#include "journal.h"
#include "parser.h"
-#include "register.h"
+#include "abbrev.h"
namespace ledger {
@@ -131,7 +132,7 @@ class session_t : public xml::xpath_t::scope_t
TRACE_DTOR(session_t);
}
- journal_t * new_journal() {
+ journal_t * create_journal() {
journal_t * journal = new journal_t(this);
journals.push_back(journal);
return journal;
@@ -148,15 +149,17 @@ class session_t : public xml::xpath_t::scope_t
checked_delete(journal);
}
- void read_journal(std::istream& in,
- const path& pathname,
- xml::builder_t& builder);
- void read_journal(const path& pathname,
- xml::builder_t& builder);
+ std::size_t read_journal(std::istream& in,
+ const path& pathname,
+ xml::builder_t& builder);
+ std::size_t read_journal(const path& pathname,
+ xml::builder_t& builder);
void read_init();
- journal_t * read_data(const string& master_account = "");
+ std::size_t read_data(xml::builder_t& builder,
+ journal_t * journal,
+ const string& master_account = "");
void register_parser(parser_t * parser) {
parsers.push_back(parser);
@@ -179,7 +182,7 @@ class session_t : public xml::xpath_t::scope_t
virtual bool resolve(const string& name, value_t& result,
xml::xpath_t::scope_t * locals = NULL);
- virtual xml::xpath_t::op_t * lookup(const string& name);
+ virtual xml::xpath_t::ptr_op_t lookup(const string& name);
//
// Debug options
diff --git a/src/system.hh b/src/system.hh
index 1c645794..a345bc9d 100644
--- a/src/system.hh
+++ b/src/system.hh
@@ -140,6 +140,7 @@ extern "C" {
#include <boost/filesystem/path.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
+#include <boost/intrusive_ptr.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lexical_cast.hpp>
@@ -154,5 +155,6 @@ extern "C" {
#include <boost/ptr_container/ptr_list.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/regex.hpp>
+#include <boost/variant.hpp>
#endif // _SYSTEM_HH
diff --git a/src/textual.cc b/src/textual.cc
index ba720187..8fdd4db1 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -275,9 +275,9 @@ bool textual_parser_t::test(std::istream& in) const
return true;
}
-void textual_parser_t::parse(std::istream& in,
- const path& pathname,
- builder_t& builder)
+std::size_t textual_parser_t::parse(std::istream& in,
+ const path& pathname,
+ builder_t& builder)
{
TRACE_START(parsing_total, 1, "Total time spent parsing text:");
@@ -285,6 +285,8 @@ void textual_parser_t::parse(std::istream& in,
builder.begin_node(JOURNAL_NODE);
+ std::size_t count = 0;
+
while (in.good() && ! in.eof()) {
static char line[MAX_LINE + 1];
in.getline(line, MAX_LINE);
@@ -460,6 +462,7 @@ void textual_parser_t::parse(std::istream& in,
default:
TRACE_START(entries, 1, "Time spent handling entries:");
parse_entry(in, builder, line, end_of_line);
+ count++;
TRACE_STOP(entries, 1);
break;
}
@@ -470,6 +473,8 @@ void textual_parser_t::parse(std::istream& in,
builder.end_node(JOURNAL_NODE);
TRACE_STOP(parsing_total, 1);
+
+ return count;
}
} // namespace ledger
diff --git a/src/textual.h b/src/textual.h
index c6654979..f4d81f19 100644
--- a/src/textual.h
+++ b/src/textual.h
@@ -41,9 +41,9 @@ class textual_parser_t : public parser_t
public:
virtual bool test(std::istream& in) const;
- virtual void parse(std::istream& in,
- const path& pathname,
- xml::builder_t& builder);
+ virtual std::size_t parse(std::istream& in,
+ const path& pathname,
+ xml::builder_t& builder);
};
} // namespace ledger
diff --git a/src/transform.cc b/src/transform.cc
index d13d9f7e..3331c2f3 100644
--- a/src/transform.cc
+++ b/src/transform.cc
@@ -34,7 +34,7 @@
namespace ledger {
#if 0
-void populate_account(account_t& acct, xml::document_t * document)
+void populate_account(account_t& acct, xml::document_t& document)
{
if (! acct.parent)
return;
@@ -61,7 +61,7 @@ void populate_account(account_t& acct, xml::document_t * document)
}
class populate_accounts : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
if (item->kind == repitem_t::TRANSACTION) {
item->extract();
populate_account(*static_cast<xact_repitem_t *>(item)->account(), item);
@@ -70,13 +70,13 @@ class populate_accounts : public repitem_t::select_callback_t {
};
class clear_account_data : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
if (item->kind == repitem_t::ACCOUNT)
static_cast<account_repitem_t *>(item)->account->data = NULL;
}
};
-void accounts_transform::execute(xml::document_t * document)
+void accounts_transform::execute(xml::document_t& document)
{
populate_accounts cb1;
items->select_all(cb1);
@@ -99,7 +99,7 @@ void accounts_transform::execute(xml::document_t * document)
items->select_all(cb2);
}
-void compact_transform::execute(xml::document_t * document)
+void compact_transform::execute(xml::document_t& document)
{
for (repitem_t * i = items; i; i = i->next) {
if (i->kind == repitem_t::ACCOUNT) {
@@ -138,7 +138,7 @@ void compact_transform::execute(xml::document_t * document)
}
}
-void clean_transform::execute(xml::document_t * document)
+void clean_transform::execute(xml::document_t& document)
{
repitem_t * i = items;
while (i) {
@@ -169,11 +169,11 @@ void clean_transform::execute(xml::document_t * document)
}
}
-void entries_transform::execute(xml::document_t * document)
+void entries_transform::execute(xml::document_t& document)
{
}
-void optimize_transform::execute(xml::document_t * document)
+void optimize_transform::execute(xml::document_t& document)
{
for (repitem_t * i = items; i; i = i->next) {
if (i->kind == repitem_t::ENTRY) {
@@ -194,7 +194,7 @@ void optimize_transform::execute(xml::document_t * document)
}
}
-void split_transform::execute(xml::document_t * document)
+void split_transform::execute(xml::document_t& document)
{
for (repitem_t * i = items; i; i = i->next) {
if (i->contents && i->contents->next) {
@@ -236,7 +236,7 @@ void split_transform::execute(xml::document_t * document)
}
}
-void merge_transform::execute(xml::document_t * document)
+void merge_transform::execute(xml::document_t& document)
{
for (repitem_t * i = items; i; i = i->next) {
if (i->next) {
@@ -290,13 +290,13 @@ namespace {
#define REPITEM_FLAGGED 0x1
class mark_selected : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
item->flags |= REPITEM_FLAGGED;
}
};
class mark_selected_and_ancestors : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
while (item->parent) {
item->flags |= REPITEM_FLAGGED;
item = item->parent;
@@ -305,27 +305,27 @@ namespace {
};
class delete_unmarked : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
if (item->parent && ! (item->flags & REPITEM_FLAGGED))
checked_delete(item);
}
};
class delete_marked : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
if (item->flags & REPITEM_FLAGGED)
checked_delete(item);
}
};
class clear_flags : public repitem_t::select_callback_t {
- virtual void operator()(xml::document_t * document) {
+ virtual void operator()(xml::document_t& document) {
item->flags = 0;
}
};
}
-void select_transform::execute(xml::document_t * document)
+void select_transform::execute(xml::document_t& document)
{
if (! path) {
items->clear();
@@ -340,7 +340,7 @@ void select_transform::execute(xml::document_t * document)
items->select_all(cb3);
}
-void remove_transform::execute(xml::document_t * document)
+void remove_transform::execute(xml::document_t& document)
{
if (! path)
return;
diff --git a/src/transform.h b/src/transform.h
index 92e16e01..5d6b1976 100644
--- a/src/transform.h
+++ b/src/transform.h
@@ -39,38 +39,38 @@ namespace ledger {
class transform_t {
public:
virtual ~transform_t() {}
- virtual void execute(xml::document_t * document) = 0;
+ virtual void execute(xml::document_t& document) = 0;
};
class check_transform : public transform_t {
// --check checks the validity of the item list.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class accounts_transform : public transform_t {
// --accounts transforms the report tree into an account-wise view.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class compact_transform : public transform_t {
// --compact compacts an account tree to remove accounts with only
// one child account.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class clean_transform : public transform_t {
// --clean clears out entries and accounts that have no contents.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class entries_transform : public transform_t {
// --entries transforms the report tree into an entries-wise view.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class optimize_transform : public transform_t {
@@ -79,7 +79,7 @@ class optimize_transform : public transform_t {
// commodity (one the negative of the other), the amount of the
// second transaction will be nulled out.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class split_transform : public transform_t {
@@ -89,7 +89,7 @@ class split_transform : public transform_t {
// useful before sorting, for exampel, in order to sort by
// transaction instead of by entry.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class merge_transform : public transform_t {
@@ -97,7 +97,7 @@ class merge_transform : public transform_t {
// which share the same entry will be merged into a group of
// transactions under one reported entry.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class combine_transform : public transform_t {
@@ -107,14 +107,14 @@ class combine_transform : public transform_t {
// will show the terminating date or a label that is characteristic
// of the set).
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class group_transform : public transform_t {
// --group groups all transactions that affect the same account
// within an entry, so that they appear as a single transaction.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class collapse_transform : public transform_t {
@@ -123,7 +123,7 @@ class collapse_transform : public transform_t {
// fictitous account "<total>" is used to represent the final sum,
// if multiple accounts are involved.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class subtotal_transform : public transform_t {
@@ -131,7 +131,7 @@ class subtotal_transform : public transform_t {
// one giant entry. When used in conjunction with --group, the
// affect is very similar to a regular balance report.
public:
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
#if 0
@@ -146,7 +146,7 @@ class select_transform : public transform_t
}
virtual ~select_transform() {}
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
class remove_transform : public select_transform
@@ -155,7 +155,7 @@ class remove_transform : public select_transform
remove_transform(const string& selection_path)
: select_transform(selection_path) {}
- virtual void execute(xml::document_t * document);
+ virtual void execute(xml::document_t& document);
};
#endif
diff --git a/src/xpath.cc b/src/xpath.cc
index caa7806a..492159e5 100644
--- a/src/xpath.cc
+++ b/src/xpath.cc
@@ -136,7 +136,7 @@ void xpath_t::token_t::parse_ident(std::istream& in)
value.set_string(buf);
}
-void xpath_t::token_t::next(std::istream& in, unsigned short flags)
+void xpath_t::token_t::next(std::istream& in, flags_t flags)
{
if (in.eof()) {
kind = TOK_EOF;
@@ -245,16 +245,6 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags)
length = 2;
break;
}
-#if 0
- else if (c == '~') {
- in.get(c);
- symbol[1] = c;
- symbol[2] = '\0';
- kind = NMATCH;
- length = 2;
- break;
- }
-#endif
kind = EXCLAM;
break;
@@ -282,33 +272,11 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags)
case '/':
in.get(c);
-#if 0
- if (flags & XPATH_PARSE_REGEXP) {
- char buf[1024];
- READ_INTO_(in, buf, 1023, c, length, c != '/');
- in.get(c);
- if (c != '/')
- unexpected(c, '/');
- kind = REGEXP;
- value.set_string(buf);
- break;
- }
-#endif
kind = SLASH;
break;
case '=':
in.get(c);
-#if 0
- if (in.peek() == '~') {
- in.get(c);
- symbol[1] = c;
- symbol[2] = '\0';
- kind = MATCH;
- length = 2;
- break;
- }
-#endif
kind = EQUAL;
break;
@@ -366,12 +334,6 @@ void xpath_t::token_t::next(std::istream& in, unsigned short flags)
in.get(c);
kind = COMMA;
break;
-#if 0
- case '%':
- in.get(c);
- kind = PERCENT;
- break;
-#endif
case '.':
in.get(c);
@@ -471,40 +433,35 @@ void xpath_t::token_t::unexpected(char c, char wanted)
}
}
-xpath_t::op_t * xpath_t::wrap_value(const value_t& val)
+xpath_t::ptr_op_t xpath_t::wrap_value(const value_t& val)
{
- xpath_t::op_t * temp = new xpath_t::op_t(xpath_t::op_t::VALUE);
- temp->valuep = new value_t(val);
+ xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::VALUE));
+ temp->set_value(new value_t(val));
return temp;
}
-xpath_t::op_t * xpath_t::wrap_sequence(const value_t::sequence_t& val)
+xpath_t::ptr_op_t xpath_t::wrap_sequence(const value_t::sequence_t& val)
{
+ xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::VALUE));
+
if (val.size() == 0)
- return wrap_value(false);
+ temp->set_value(new value_t(false));
else if (val.size() == 1)
- return wrap_value(val.front());
+ temp->set_value(new value_t(val.front()));
else
- return wrap_value(val);
-}
+ temp->set_value(new value_t(val));
-xpath_t::op_t * xpath_t::wrap_functor(functor_t * fobj)
-{
- xpath_t::op_t * temp = new xpath_t::op_t(xpath_t::op_t::FUNCTOR);
- temp->functor = fobj;
return temp;
}
-#if 0
-xpath_t::op_t * xpath_t::wrap_mask(const string& pattern)
+xpath_t::ptr_op_t xpath_t::wrap_functor(const function_t& fobj)
{
- xpath_t::op_t * temp = new xpath_t::op_t(xpath_t::op_t::MASK);
- temp->mask = new mask_t(pattern);
+ xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::FUNCTION));
+ temp->set_function(fobj);
return temp;
}
-#endif
-void xpath_t::scope_t::define(const string& name, op_t * def)
+void xpath_t::scope_t::define(const string& name, ptr_op_t def)
{
DEBUG("ledger.xpath.syms", "Defining '" << name << "' = " << def);
@@ -525,7 +482,7 @@ void xpath_t::scope_t::define(const string& name, op_t * def)
def->acquire();
}
-xpath_t::op_t *
+xpath_t::ptr_op_t
xpath_t::scope_t::lookup(const string& name)
{
symbol_map::const_iterator i = symbols.find(name);
@@ -536,7 +493,7 @@ xpath_t::scope_t::lookup(const string& name)
return NULL;
}
-void xpath_t::scope_t::define(const string& name, functor_t * def) {
+void xpath_t::scope_t::define(const string& name, const function_t& def) {
define(name, wrap_functor(def));
}
@@ -561,8 +518,8 @@ bool xpath_t::function_scope_t::resolve(const string& name,
case 't':
if (name == "text") {
- if (value->type == value_t::XML_NODE)
- result = value->as_xml_node()->to_value();
+ if (value.type == value_t::XML_NODE)
+ result = value.as_xml_node()->to_value();
else
throw_(calc_error, "Attempt to call text() on a non-node value");
return true;
@@ -572,82 +529,17 @@ bool xpath_t::function_scope_t::resolve(const string& name,
return scope_t::resolve(name, result, locals);
}
-xpath_t::op_t::~op_t()
+xpath_t::ptr_op_t
+xpath_t::parse_value_term(std::istream& in, flags_t tflags) const
{
- TRACE_DTOR(xpath_t::op_t);
-
- DEBUG("ledger.xpath.memory", "Destroying " << this);
- assert(refc == 0);
-
- switch (kind) {
- case VALUE:
- assert(! left);
- assert(valuep);
- checked_delete(valuep);
- break;
-
- case NODE_NAME:
- case FUNC_NAME:
- case ATTR_NAME:
- case VAR_NAME:
- assert(! left);
- assert(name);
- checked_delete(name);
- break;
-
- case ARG_INDEX:
- break;
-
- case FUNCTOR:
- assert(! left);
- assert(functor);
- checked_delete(functor);
- break;
-
-#if 0
- case MASK:
- assert(! left);
- assert(mask);
- checked_delete(mask);
- break;
-#endif
-
- default:
- assert(kind < LAST);
- if (left)
- left->release();
- if (kind > TERMINALS && right)
- right->release();
- break;
- }
-}
-
-void xpath_t::op_t::get_value(value_t& result) const
-{
- switch (kind) {
- case VALUE:
- result = *valuep;
- break;
- case ARG_INDEX:
- result = (long)arg_index;
- break;
- default:
- throw_(calc_error,
- "Cannot determine value of expression symbol '" << *this << "'");
- }
-}
-
-xpath_t::op_t *
-xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
-{
- std::auto_ptr<op_t> node;
+ ptr_op_t node;
token_t& tok = next_token(in, tflags);
switch (tok.kind) {
case token_t::VALUE:
- node.reset(new op_t(op_t::VALUE));
- node->valuep = new value_t(tok.value);
+ node = new op_t(op_t::VALUE);
+ node->set_value(new value_t(tok.value));
break;
case token_t::IDENT: {
@@ -660,15 +552,15 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
std::strcpy(buf, "lambda ");
READ_INTO(in, &buf[7], 4000, c, true);
- op_t * eval = new op_t(op_t::O_EVAL);
- op_t * lambda = new op_t(op_t::FUNCTOR);
+ ptr_op_t eval = new op_t(op_t::O_EVAL);
+ ptr_op_t lambda = new op_t(op_t::FUNCTION);
lambda->functor = new python_functor_t(python_eval(buf));
eval->set_left(lambda);
- op_t * sym = new op_t(op_t::SYMBOL);
+ ptr_op_t sym = new op_t(op_t::SYMBOL);
sym->name = new string("__ptr");
eval->set_right(sym);
- node.reset(eval);
+ node = eval;
goto done;
}
@@ -679,49 +571,57 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
#endif
string ident = tok.value.as_string();
- if (std::isdigit(ident[0])) {
- node.reset(new op_t(op_t::ARG_INDEX));
- node->arg_index = lexical_cast<unsigned int>(ident.c_str());
- }
- else if (optional<node_t::nameid_t> id =
- document_t::lookup_builtin_id(ident)) {
- node.reset(new op_t(op_t::NODE_ID));
- node->name_id = *id;
- }
- else {
- node.reset(new op_t(op_t::NODE_NAME));
- node->name = new string(ident);
- }
// An identifier followed by ( represents a function call
tok = next_token(in, tflags);
if (tok.kind == token_t::LPAREN) {
node->kind = op_t::FUNC_NAME;
+ node->set_string(ident);
- std::auto_ptr<op_t> call_node;
- call_node.reset(new op_t(op_t::O_EVAL));
- call_node->set_left(node.release());
+ ptr_op_t call_node(new op_t(op_t::O_EVAL));
+ call_node->set_left(node);
call_node->set_right(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN)
tok.unexpected(); // jww (2006-09-09): wanted )
- node.reset(call_node.release());
+ node = call_node;
} else {
+ if (std::isdigit(ident[0])) {
+ node = new op_t(op_t::ARG_INDEX);
+ node->set_long(lexical_cast<unsigned int>(ident.c_str()));
+ }
+ else if (optional<node_t::nameid_t> id =
+ document_t::lookup_builtin_id(ident)) {
+ node = new op_t(op_t::NODE_ID);
+ node->set_name(*id);
+ }
+ else {
+ node = new op_t(op_t::NODE_NAME);
+ node->set_string(ident);
+ }
push_token(tok);
}
break;
}
- case token_t::AT_SYM:
+ case token_t::AT_SYM: {
tok = next_token(in, tflags);
if (tok.kind != token_t::IDENT)
throw_(parse_error, "@ symbol must be followed by attribute name");
- node.reset(new op_t(op_t::ATTR_NAME));
- node->name = new string(tok.value.as_string());
+ string ident = tok.value.as_string();
+ if (optional<node_t::nameid_t> id = document_t::lookup_builtin_id(ident)) {
+ node = new op_t(op_t::ATTR_ID);
+ node->set_name(*id);
+ }
+ else {
+ node = new op_t(op_t::ATTR_NAME);
+ node->set_string(ident);
+ }
break;
+ }
#if 0
case token_t::DOLLAR:
@@ -729,32 +629,32 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
if (tok.kind != token_t::IDENT)
throw parse_error("$ symbol must be followed by variable name");
- node.reset(new op_t(op_t::VAR_NAME));
+ node = new op_t(op_t::VAR_NAME);
node->name = new string(tok.value.as_string());
break;
#endif
case token_t::DOT:
- node.reset(new op_t(op_t::NODE_ID));
- node->name_id = document_t::CURRENT;
+ node = new op_t(op_t::NODE_ID);
+ node->set_name(document_t::CURRENT);
break;
case token_t::DOTDOT:
- node.reset(new op_t(op_t::NODE_ID));
- node->name_id = document_t::PARENT;
+ node = new op_t(op_t::NODE_ID);
+ node->set_name(document_t::PARENT);
break;
case token_t::SLASH:
- node.reset(new op_t(op_t::NODE_ID));
- node->name_id = document_t::ROOT;
+ node = new op_t(op_t::NODE_ID);
+ node->set_name(document_t::ROOT);
push_token();
break;
case token_t::STAR:
- node.reset(new op_t(op_t::NODE_ID));
- node->name_id = document_t::ALL;
+ node = new op_t(op_t::NODE_ID);
+ node->set_name(document_t::ALL);
break;
case token_t::LPAREN:
- node.reset(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
- if (! node.get())
+ node = parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL);
+ if (! node)
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
@@ -762,12 +662,6 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
tok.unexpected(); // jww (2006-09-09): wanted )
break;
-#if 0
- case token_t::REGEXP:
- node.reset(wrap_mask(tok.value.as_string()));
- break;
-#endif
-
default:
push_token(tok);
break;
@@ -778,22 +672,22 @@ xpath_t::parse_value_term(std::istream& in, unsigned short tflags) const
done:
#endif
#endif
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_predicate_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_predicate_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_value_term(in, tflags));
+ ptr_op_t node(parse_value_term(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
while (tok.kind == token_t::LBRACKET) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(op_t::O_PRED));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_PRED);
+ node->set_left(prev);
node->set_right(parse_value_expr(in, tflags | XPATH_PARSE_PARTIAL));
- if (! node->right)
+ if (! node->right())
throw_(parse_error, "[ operator not followed by valid expression");
tok = next_token(in, tflags);
@@ -806,28 +700,28 @@ xpath_t::parse_predicate_expr(std::istream& in, unsigned short tflags) const
push_token(tok);
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_path_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_predicate_expr(in, tflags));
+ ptr_op_t node(parse_predicate_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
while (tok.kind == token_t::SLASH) {
- std::auto_ptr<op_t> prev(node.release());
+ ptr_op_t prev(node);
tok = next_token(in, tflags);
- node.reset(new op_t(tok.kind == token_t::SLASH ?
- op_t::O_RFIND : op_t::O_FIND));
+ node = new op_t(tok.kind == token_t::SLASH ?
+ op_t::O_RFIND : op_t::O_FIND);
if (tok.kind != token_t::SLASH)
push_token(tok);
- node->set_left(prev.release());
+ node->set_left(prev);
node->set_right(parse_predicate_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error, "/ operator not followed by a valid term");
tok = next_token(in, tflags);
@@ -836,113 +730,97 @@ xpath_t::parse_path_expr(std::istream& in, unsigned short tflags) const
push_token(tok);
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_unary_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_unary_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node;
+ ptr_op_t node;
token_t& tok = next_token(in, tflags);
switch (tok.kind) {
case token_t::EXCLAM: {
- std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
- if (! texpr.get())
+ ptr_op_t texpr(parse_path_expr(in, tflags));
+ if (! texpr)
throw_(parse_error,
tok.symbol << " operator not followed by argument");
+
// A very quick optimization
if (texpr->kind == op_t::VALUE) {
- *texpr->valuep = ! *texpr->valuep;
- node.reset(texpr.release());
+ texpr->as_value().in_place_negate();
+ node = texpr;
} else {
- node.reset(new op_t(op_t::O_NOT));
- node->set_left(texpr.release());
+ node = new op_t(op_t::O_NOT);
+ node->set_left(texpr);
}
break;
}
case token_t::MINUS: {
- std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
- if (! texpr.get())
+ ptr_op_t texpr(parse_path_expr(in, tflags));
+ if (! texpr)
throw_(parse_error,
tok.symbol << " operator not followed by argument");
- // A very quick optimization
- if (texpr->kind == op_t::VALUE) {
- texpr->valuep->in_place_negate();
- node.reset(texpr.release());
- } else {
- node.reset(new op_t(op_t::O_NEG));
- node->set_left(texpr.release());
- }
- break;
- }
-#if 0
- case token_t::PERCENT: {
- std::auto_ptr<op_t> texpr(parse_path_expr(in, tflags));
- if (! texpr.get())
- throw_(parse_error,
- tok.symbol << " operator not followed by argument");
// A very quick optimization
if (texpr->kind == op_t::VALUE) {
- static value_t perc("100.0%");
- *texpr->valuep = perc * *texpr->valuep;
- node.reset(texpr.release());
+ texpr->as_value().in_place_negate();
+ node = texpr;
} else {
- node.reset(new op_t(op_t::O_PERC));
- node->set_left(texpr.release());
+ node = new op_t(op_t::O_NEG);
+ node->set_left(texpr);
}
break;
}
-#endif
default:
push_token(tok);
- node.reset(parse_path_expr(in, tflags));
+ node = parse_path_expr(in, tflags);
break;
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_union_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_union_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_unary_expr(in, tflags));
+ ptr_op_t node(parse_unary_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::PIPE || tok.kind == token_t::KW_UNION) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(op_t::O_UNION));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_UNION);
+ node->set_left(prev);
node->set_right(parse_union_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
}
}
- return node.release();
+
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_mul_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_mul_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_union_expr(in, tflags));
+ ptr_op_t node(parse_union_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(tok.kind == token_t::STAR ?
- op_t::O_MUL : op_t::O_DIV));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(tok.kind == token_t::STAR ?
+ op_t::O_MUL : op_t::O_DIV);
+ node->set_left(prev);
node->set_right(parse_mul_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
@@ -951,24 +829,24 @@ xpath_t::parse_mul_expr(std::istream& in, unsigned short tflags) const
push_token(tok);
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_add_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_add_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_mul_expr(in, tflags));
+ ptr_op_t node(parse_mul_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::PLUS ||
tok.kind == token_t::MINUS) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(tok.kind == token_t::PLUS ?
- op_t::O_ADD : op_t::O_SUB));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(tok.kind == token_t::PLUS ?
+ op_t::O_ADD : op_t::O_SUB);
+ node->set_left(prev);
node->set_right(parse_add_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
@@ -977,20 +855,18 @@ xpath_t::parse_add_expr(std::istream& in, unsigned short tflags) const
push_token(tok);
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_logic_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_add_expr(in, tflags));
-
- if (node.get()) {
- op_t::kind_t kind = op_t::LAST;
-
- unsigned short _flags = tflags;
+ ptr_op_t node(parse_add_expr(in, tflags));
- token_t& tok = next_token(in, tflags);
+ if (node) {
+ op_t::kind_t kind = op_t::LAST;
+ flags_t _flags = tflags;
+ token_t& tok = next_token(in, tflags);
switch (tok.kind) {
case token_t::ASSIGN:
kind = op_t::O_DEFINE;
@@ -1001,16 +877,6 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const
case token_t::NEQUAL:
kind = op_t::O_NEQ;
break;
-#if 0
- case token_t::MATCH:
- kind = op_t::O_MATCH;
- _flags |= XPATH_PARSE_REGEXP;
- break;
- case token_t::NMATCH:
- kind = op_t::O_NMATCH;
- _flags |= XPATH_PARSE_REGEXP;
- break;
-#endif
case token_t::LESS:
kind = op_t::O_LT;
break;
@@ -1029,15 +895,15 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const
}
if (kind != op_t::LAST) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(kind));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(kind);
+ node->set_left(prev);
if (kind == op_t::O_DEFINE)
node->set_right(parse_querycolon_expr(in, tflags));
else
node->set_right(parse_add_expr(in, _flags));
- if (! node->right) {
+ if (! node->right()) {
if (tok.kind == token_t::PLUS)
throw_(parse_error,
tok.symbol << " operator not followed by argument");
@@ -1048,96 +914,96 @@ xpath_t::parse_logic_expr(std::istream& in, unsigned short tflags) const
}
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_and_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_and_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_logic_expr(in, tflags));
+ ptr_op_t node(parse_logic_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::KW_AND) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(op_t::O_AND));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_AND);
+ node->set_left(prev);
node->set_right(parse_and_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
}
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_or_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_or_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_and_expr(in, tflags));
+ ptr_op_t node(parse_and_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::KW_OR) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(op_t::O_OR));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_OR);
+ node->set_left(prev);
node->set_right(parse_or_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
}
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_querycolon_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_querycolon_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_or_expr(in, tflags));
+ ptr_op_t node(parse_or_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::QUESTION) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(op_t::O_QUES));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_QUES);
+ node->set_left(prev);
node->set_right(new op_t(op_t::O_COLON));
- node->right->set_left(parse_querycolon_expr(in, tflags));
- if (! node->right)
+ node->right()->set_left(parse_querycolon_expr(in, tflags));
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
if (tok.kind != token_t::COLON)
tok.unexpected(); // jww (2006-09-09): wanted :
- node->right->set_right(parse_querycolon_expr(in, tflags));
- if (! node->right)
+ node->right()->set_right(parse_querycolon_expr(in, tflags));
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
} else {
push_token(tok);
}
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_value_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_querycolon_expr(in, tflags));
+ ptr_op_t node(parse_querycolon_expr(in, tflags));
- if (node.get()) {
+ if (node) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::COMMA) {
- std::auto_ptr<op_t> prev(node.release());
- node.reset(new op_t(op_t::O_COMMA));
- node->set_left(prev.release());
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_COMMA);
+ node->set_left(prev);
node->set_right(parse_value_expr(in, tflags));
- if (! node->right)
+ if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
tok = next_token(in, tflags);
@@ -1154,13 +1020,13 @@ xpath_t::parse_value_expr(std::istream& in, unsigned short tflags) const
throw_(parse_error, "Failed to parse value expression");
}
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::parse_expr(std::istream& in, unsigned short tflags) const
+xpath_t::ptr_op_t
+xpath_t::parse_expr(std::istream& in, flags_t tflags) const
{
- std::auto_ptr<op_t> node(parse_value_expr(in, tflags));
+ ptr_op_t node(parse_value_expr(in, tflags));
if (use_lookahead) {
use_lookahead = false;
@@ -1176,74 +1042,72 @@ xpath_t::parse_expr(std::istream& in, unsigned short tflags) const
lookahead->clear();
#endif
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::op_t::new_node(kind_t kind, op_t * left, op_t * right)
+xpath_t::ptr_op_t
+xpath_t::op_t::new_node(kind_t kind, ptr_op_t left, ptr_op_t right)
{
- std::auto_ptr<op_t> node(new op_t(kind));
+ ptr_op_t node(new op_t(kind));
if (left)
node->set_left(left);
if (right)
node->set_right(right);
- return node.release();
+ return node;
}
-xpath_t::op_t *
-xpath_t::op_t::copy(op_t * tleft, op_t * tright) const
+xpath_t::ptr_op_t
+xpath_t::op_t::copy(ptr_op_t tleft, ptr_op_t tright) const
{
- std::auto_ptr<op_t> node(new op_t(kind));
+ ptr_op_t node(new op_t(kind));
if (tleft)
node->set_left(tleft);
if (tright)
node->set_right(tright);
- return node.release();
+ return node;
}
-void xpath_t::op_t::find_values(value_t * context, scope_t * scope,
+void xpath_t::op_t::find_values(value_t& context, scope_t * scope,
value_t::sequence_t& result_seq,
bool recursive)
{
xpath_t expr(compile(context, scope, true));
- if (expr->kind == VALUE)
- append_value(*expr->valuep, result_seq);
+ if (expr.ptr->kind == VALUE)
+ append_value(expr.ptr->as_value(), result_seq);
if (recursive) {
- if (context->type == value_t::XML_NODE) {
- node_t * ptr = context->as_xml_node();
- if (ptr->is_parent_node()) {
+ if (context.type == value_t::XML_NODE) {
+ node_t * ptr = context.as_xml_node();
+ if (ptr->is_parent_node())
foreach (node_t * node, ptr->as_parent_node()) {
value_t temp(node);
- find_values(&temp, scope, result_seq, recursive);
+ find_values(temp, scope, result_seq, recursive);
}
- }
} else {
throw_(calc_error, "Recursive path selection on a non-node value");
}
}
}
-bool xpath_t::op_t::test_value(value_t * context, scope_t * scope,
- int index)
+bool xpath_t::op_t::test_value(value_t& context, scope_t * scope, int index)
{
xpath_t expr(compile(context, scope, true));
- if (expr->kind != VALUE)
+ if (expr.ptr->kind != VALUE)
throw_(calc_error, "Predicate expression does not yield a constant value");
- switch (expr->valuep->type) {
+ switch (expr.ptr->as_value().type) {
case value_t::INTEGER:
case value_t::AMOUNT:
- return *expr->valuep == value_t((long)index + 1);
+ return expr.ptr->as_value() == value_t((long)index + 1);
default:
- return expr->valuep->as_boolean();
+ return expr.ptr->as_value().as_boolean();
}
}
-xpath_t::op_t * xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
+xpath_t::ptr_op_t xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
{
// If not all of the elements were constants, transform the result
// into an expression sequence using O_COMMA.
@@ -1251,30 +1115,34 @@ xpath_t::op_t * xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
assert(! result_seq.empty());
if (result_seq.size() == 1)
- return wrap_value(result_seq.front())->acquire();
+ return wrap_value(result_seq.front());
value_t::sequence_t::iterator i = result_seq.begin();
- std::auto_ptr<op_t> lit_seq(new op_t(O_COMMA));
+ ptr_op_t lit_seq(new op_t(O_COMMA));
lit_seq->set_left(wrap_value(*i++));
- op_t ** opp = &lit_seq->right;
+ ptr_op_t* opp = &lit_seq->right();
for (; i != result_seq.end(); i++) {
if (*opp) {
- op_t * val = *opp;
+ ptr_op_t val = *opp;
*opp = new op_t(O_COMMA);
(*opp)->set_left(val);
- opp = &(*opp)->right;
+ opp = &(*opp)->right();
}
if ((*i).type != value_t::POINTER)
- *opp = wrap_value(*i)->acquire();
+ *opp = wrap_value(*i);
else
- *opp = static_cast<op_t *>((*i).as_pointer());
+#if 1
+ assert(false);
+#else
+ *opp = static_cast<ptr_op_t>((*i).as_pointer());
+#endif
}
- return lit_seq.release();
+ return lit_seq;
}
void xpath_t::op_t::append_value(value_t& val,
@@ -1287,44 +1155,44 @@ void xpath_t::op_t::append_value(value_t& val,
result_seq.push_back(val);
}
-xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
- bool resolve)
+xpath_t::ptr_op_t xpath_t::op_t::compile(value_t& context, scope_t * scope,
+ bool resolve)
{
#if 0
try {
#endif
switch (kind) {
case VALUE:
- return acquire();
+ return this;
case NODE_ID:
- switch (name_id) {
+ switch (as_name()) {
case document_t::CURRENT:
- return wrap_value(context)->acquire();
+ return wrap_value(context);
case document_t::PARENT:
- if (context->type != value_t::XML_NODE)
+ if (context.type != value_t::XML_NODE)
throw_(compile_error, "Referencing parent node from a non-node value");
- else if (context->as_xml_node()->parent())
- return wrap_value(&*context->as_xml_node()->parent())->acquire();
+ else if (context.as_xml_node()->parent())
+ return wrap_value(&*context.as_xml_node()->parent());
else
throw_(compile_error, "Referencing parent node from the root node");
case document_t::ROOT:
- if (context->type != value_t::XML_NODE)
+ if (context.type != value_t::XML_NODE)
throw_(compile_error, "Referencing root node from a non-node value");
else
- return wrap_value(&context->as_xml_node()->document())->acquire();
+ return wrap_value(&context.as_xml_node()->document());
case document_t::ALL: {
- if (context->type != value_t::XML_NODE)
+ if (context.type != value_t::XML_NODE)
throw_(compile_error, "Referencing child nodes from a non-node value");
value_t::sequence_t nodes;
- foreach (node_t * node, context->as_xml_node()->as_parent_node())
+ foreach (node_t * node, context.as_xml_node()->as_parent_node())
nodes.push_back(node);
- return wrap_value(nodes)->acquire();
+ return wrap_value(nodes);
}
default:
@@ -1333,8 +1201,8 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
// fall through...
case NODE_NAME:
- if (context->type == value_t::XML_NODE) {
- node_t * ptr = context->as_xml_node();
+ if (context.type == value_t::XML_NODE) {
+ node_t * ptr = context.as_xml_node();
if (resolve) {
// First, look up the symbol as a node name within the current
// context. If any exist, then return the set of names.
@@ -1344,136 +1212,131 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
foreach (node_t * node, ptr->as_parent_node()) {
if ((kind == NODE_NAME &&
- std::strcmp(name->c_str(), node->name()) == 0) ||
- (kind == NODE_ID && name_id == node->name_id()))
+ std::strcmp(as_string().c_str(), node->name()) == 0) ||
+ (kind == NODE_ID && as_name() == node->name_id()))
nodes.push_back(node);
}
- return wrap_value(nodes)->acquire();
+ return wrap_value(nodes);
}
} else {
assert(ptr);
if (optional<node_t::nameid_t> id =
- ptr->document().lookup_name_id(*name)) {
- op_t * node = new_node(NODE_ID);
- node->name_id = *id;
- return node->acquire();
+ ptr->document().lookup_name_id(as_string())) {
+ ptr_op_t node = new_node(NODE_ID);
+ node->set_name(*id);
+ return node;
}
}
}
- return acquire();
+ return this;
+
+ case ATTR_ID:
+ if (optional<const string&> value = context.as_xml_node()->get_attr(as_long()))
+ return wrap_value(*value);
+ return this;
case ATTR_NAME:
if (optional<node_t::nameid_t> id =
- context->as_xml_node()->document().lookup_name_id(*name)) {
- optional<const string&> value = context->as_xml_node()->get_attr(*id);
- if (value)
- return wrap_value(*value)->acquire();
+ context.as_xml_node()->document().lookup_name_id(as_string())) {
+ if (optional<const string&> value = context.as_xml_node()->get_attr(*id))
+ return wrap_value(*value);
}
- return acquire();
+ return this;
case VAR_NAME:
case FUNC_NAME:
if (scope) {
if (resolve) {
value_t temp;
- if (scope->resolve(*name, temp))
- return wrap_value(temp)->acquire();
+ if (scope->resolve(as_string(), temp))
+ return wrap_value(temp);
}
- if (op_t * def = scope->lookup(*name))
+ if (ptr_op_t def = scope->lookup(as_string()))
return def->compile(context, scope, resolve);
}
- return acquire();
+ return this;
case ARG_INDEX:
if (scope && scope->kind == scope_t::ARGUMENT) {
assert(scope->args.type == value_t::SEQUENCE);
- if (arg_index < scope->args.as_sequence().size())
- return wrap_value(scope->args.as_sequence()[arg_index])->acquire();
+ if (as_long() < scope->args.as_sequence().size())
+ return wrap_value(scope->args.as_sequence()[as_long()]);
else
throw_(compile_error, "Reference to non-existing argument");
} else {
- return acquire();
+ return this;
}
- case FUNCTOR:
+ case FUNCTION:
if (resolve) {
value_t temp;
- (*functor)(temp, scope);
- return wrap_value(temp)->acquire();
+ as_function()(temp, scope);
+ return wrap_value(temp);
} else {
- return acquire();
+ return this;
}
break;
-#if 0
- case MASK:
- return acquire();
-#endif
-
case O_NOT: {
- assert(left);
- xpath_t expr(left->compile(context, scope, resolve));
- if (! expr->constant()) {
- if (left == expr)
- return acquire();
+ xpath_t expr(left()->compile(context, scope, resolve));
+ if (! expr.ptr->is_value()) {
+ if (left() == expr.ptr)
+ return this;
else
- return copy(expr)->acquire();
+ return copy(expr.ptr);
}
- if (left == expr) {
- if (expr->valuep->strip_annotations())
- return wrap_value(false)->acquire();
+ if (left() == expr.ptr) {
+ if (expr.ptr->as_value().strip_annotations())
+ return wrap_value(false);
else
- return wrap_value(true)->acquire();
+ return wrap_value(true);
} else {
- if (expr->valuep->strip_annotations())
- *expr->valuep = false;
+ if (expr.ptr->as_value().strip_annotations())
+ expr.ptr->set_value(new value_t(false));
else
- *expr->valuep = true;
+ expr.ptr->set_value(new value_t(true));
- return expr->acquire();
+ return expr.ptr;
}
}
case O_NEG: {
- assert(left);
- xpath_t expr(left->compile(context, scope, resolve));
- if (! expr->constant()) {
- if (left == expr)
- return acquire();
+ xpath_t expr(left()->compile(context, scope, resolve));
+ if (! expr.ptr->is_value()) {
+ if (left() == expr.ptr)
+ return this;
else
- return copy(expr)->acquire();
+ return copy(expr.ptr);
}
- if (left == expr) {
- return wrap_value(expr->valuep->negate())->acquire();
+ if (left() == expr.ptr) {
+ return wrap_value(expr.ptr->as_value().negate());
} else {
- expr->valuep->in_place_negate();
- return expr->acquire();
+ expr.ptr->as_value().in_place_negate();
+ return expr.ptr;
}
}
case O_UNION: {
- assert(left);
- assert(right);
- xpath_t lexpr(left->compile(context, scope, resolve));
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (! lexpr->constant() || ! rexpr->constant()) {
- if (left == lexpr && right == rexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (! lexpr.ptr->is_value() || ! rexpr.ptr->is_value()) {
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
value_t::sequence_t result_seq;
- append_value(*lexpr->valuep, result_seq);
- append_value(*rexpr->valuep, result_seq);
+ append_value(lexpr.ptr->as_value(), result_seq);
+ append_value(rexpr.ptr->as_value(), result_seq);
if (result_seq.size() == 1)
- return wrap_value(result_seq.front())->acquire();
+ return wrap_value(result_seq.front());
else
- return wrap_sequence(result_seq)->acquire();
+ return wrap_sequence(result_seq);
break;
}
@@ -1481,36 +1344,34 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
case O_SUB:
case O_MUL:
case O_DIV: {
- assert(left);
- assert(right);
- xpath_t lexpr(left->compile(context, scope, resolve));
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (! lexpr->constant() || ! rexpr->constant()) {
- if (left == lexpr && right == rexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (! lexpr.ptr->is_value() || ! rexpr.ptr->is_value()) {
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
- if (left == lexpr) {
- value_t temp(*lexpr->valuep);
+ if (left() == lexpr.ptr) {
+ value_t temp(lexpr.ptr->as_value());
switch (kind) {
- case O_ADD: temp += *rexpr->valuep; break;
- case O_SUB: temp -= *rexpr->valuep; break;
- case O_MUL: temp *= *rexpr->valuep; break;
- case O_DIV: temp /= *rexpr->valuep; break;
+ case O_ADD: temp += rexpr.ptr->as_value(); break;
+ case O_SUB: temp -= rexpr.ptr->as_value(); break;
+ case O_MUL: temp *= rexpr.ptr->as_value(); break;
+ case O_DIV: temp /= rexpr.ptr->as_value(); break;
default: assert(false); break;
}
- return wrap_value(temp)->acquire();
+ return wrap_value(temp);
} else {
switch (kind) {
- case O_ADD: *lexpr->valuep += *rexpr->valuep; break;
- case O_SUB: *lexpr->valuep -= *rexpr->valuep; break;
- case O_MUL: *lexpr->valuep *= *rexpr->valuep; break;
- case O_DIV: *lexpr->valuep /= *rexpr->valuep; break;
+ case O_ADD: lexpr.ptr->as_value() += rexpr.ptr->as_value(); break;
+ case O_SUB: lexpr.ptr->as_value() -= rexpr.ptr->as_value(); break;
+ case O_MUL: lexpr.ptr->as_value() *= rexpr.ptr->as_value(); break;
+ case O_DIV: lexpr.ptr->as_value() /= rexpr.ptr->as_value(); break;
default: assert(false); break;
}
- return lexpr->acquire();
+ return lexpr.ptr;
}
}
@@ -1520,209 +1381,179 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
case O_LTE:
case O_GT:
case O_GTE: {
- assert(left);
- assert(right);
- xpath_t lexpr(left->compile(context, scope, resolve));
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (! lexpr->constant() || ! rexpr->constant()) {
- if (left == lexpr && right == rexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (! lexpr.ptr->is_value() || ! rexpr.ptr->is_value()) {
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
- if (left == lexpr) {
+ if (left() == lexpr.ptr) {
switch (kind) {
case O_NEQ:
- return wrap_value(*lexpr->valuep != *rexpr->valuep)->acquire();
+ return wrap_value(lexpr.ptr->as_value() != rexpr.ptr->as_value());
break;
case O_EQ:
- return wrap_value(*lexpr->valuep == *rexpr->valuep)->acquire();
+ return wrap_value(lexpr.ptr->as_value() == rexpr.ptr->as_value());
break;
case O_LT:
- return wrap_value(*lexpr->valuep < *rexpr->valuep)->acquire();
+ return wrap_value(lexpr.ptr->as_value() < rexpr.ptr->as_value());
break;
case O_LTE:
- return wrap_value(*lexpr->valuep <= *rexpr->valuep)->acquire();
+ return wrap_value(lexpr.ptr->as_value() <= rexpr.ptr->as_value());
break;
case O_GT:
- return wrap_value(*lexpr->valuep > *rexpr->valuep)->acquire();
+ return wrap_value(lexpr.ptr->as_value() > rexpr.ptr->as_value());
break;
case O_GTE:
- return wrap_value(*lexpr->valuep >= *rexpr->valuep)->acquire();
+ return wrap_value(lexpr.ptr->as_value() >= rexpr.ptr->as_value());
break;
default: assert(false); break;
}
} else {
switch (kind) {
- case O_NEQ: *lexpr->valuep = *lexpr->valuep != *rexpr->valuep; break;
- case O_EQ: *lexpr->valuep = *lexpr->valuep == *rexpr->valuep; break;
- case O_LT: *lexpr->valuep = *lexpr->valuep < *rexpr->valuep; break;
- case O_LTE: *lexpr->valuep = *lexpr->valuep <= *rexpr->valuep; break;
- case O_GT: *lexpr->valuep = *lexpr->valuep > *rexpr->valuep; break;
- case O_GTE: *lexpr->valuep = *lexpr->valuep >= *rexpr->valuep; break;
- default: assert(false); break;
+ case O_NEQ:
+ lexpr.ptr->set_value(new value_t(lexpr.ptr->as_value() != rexpr.ptr->as_value()));
+ break;
+ case O_EQ:
+ lexpr.ptr->set_value(new value_t(lexpr.ptr->as_value() == rexpr.ptr->as_value()));
+ break;
+ case O_LT:
+ lexpr.ptr->set_value(new value_t(lexpr.ptr->as_value() < rexpr.ptr->as_value()));
+ break;
+ case O_LTE:
+ lexpr.ptr->set_value(new value_t(lexpr.ptr->as_value() <= rexpr.ptr->as_value()));
+ break;
+ case O_GT:
+ lexpr.ptr->set_value(new value_t(lexpr.ptr->as_value() > rexpr.ptr->as_value()));
+ break;
+ case O_GTE:
+ lexpr.ptr->set_value(new value_t(lexpr.ptr->as_value() >= rexpr.ptr->as_value()));
+ break;
+ default:
+ assert(false);
+ break;
}
- return lexpr->acquire();
+ return lexpr.ptr;
}
}
case O_AND: {
- assert(left);
- assert(right);
- xpath_t lexpr(left->compile(context, scope, resolve));
- if (lexpr->constant() && ! lexpr->valuep->strip_annotations()) {
- *lexpr->valuep = false;
- return lexpr->acquire();
- }
-
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (! lexpr->constant() || ! rexpr->constant()) {
- if (left == lexpr && right == rexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ if (lexpr.ptr->is_value() && ! lexpr.ptr->as_value().strip_annotations()) {
+ lexpr.ptr->set_value(new value_t(false));
+ return lexpr.ptr;
+ }
+
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (! lexpr.ptr->is_value() || ! rexpr.ptr->is_value()) {
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
- if (! rexpr->valuep->strip_annotations()) {
- if (left == lexpr) {
- return wrap_value(false)->acquire();
+ if (! rexpr.ptr->as_value().strip_annotations()) {
+ if (left() == lexpr.ptr) {
+ return wrap_value(false);
} else {
- *lexpr->valuep = false;
- return lexpr->acquire();
+ lexpr.ptr->set_value(new value_t(false));
+ return lexpr.ptr;
}
} else {
- return rexpr->acquire();
+ return rexpr.ptr;
}
}
case O_OR: {
- assert(left);
- assert(right);
- xpath_t lexpr(left->compile(context, scope, resolve));
- if (lexpr->constant() && lexpr->valuep->strip_annotations())
- return lexpr->acquire();
-
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (! lexpr->constant() || ! rexpr->constant()) {
- if (left == lexpr && right == rexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ if (lexpr.ptr->is_value() && lexpr.ptr->as_value().strip_annotations())
+ return lexpr.ptr;
+
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (! lexpr.ptr->is_value() || ! rexpr.ptr->is_value()) {
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
- if (rexpr->valuep->strip_annotations()) {
- return rexpr->acquire();
+ if (rexpr.ptr->as_value().strip_annotations()) {
+ return rexpr.ptr;
} else {
- if (left == lexpr) {
- return wrap_value(false)->acquire();
+ if (left() == lexpr.ptr) {
+ return wrap_value(false);
} else {
- *lexpr->valuep = false;
- return lexpr->acquire();
+ lexpr.ptr->set_value(new value_t(false));
+ return lexpr.ptr;
}
}
}
case O_QUES: {
- assert(left);
- assert(right);
- assert(right->kind == O_COLON);
- xpath_t lexpr(left->compile(context, scope, resolve));
- if (! lexpr->constant()) {
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (left == lexpr && right == rexpr)
- return acquire();
+ assert(right()->kind == O_COLON);
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ if (! lexpr.ptr->is_value()) {
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
- if (lexpr->valuep->strip_annotations())
- return right->left->compile(context, scope, resolve);
+ if (lexpr.ptr->as_value().strip_annotations())
+ return right()->left()->compile(context, scope, resolve);
else
- return right->right->compile(context, scope, resolve);
+ return right()->right()->compile(context, scope, resolve);
}
case O_COLON: {
- xpath_t lexpr(left->compile(context, scope, resolve));
- xpath_t rexpr(right->compile(context, scope, resolve));
- if (left == lexpr && right == rexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ xpath_t rexpr(right()->compile(context, scope, resolve));
+ if (left() == lexpr.ptr && right() == rexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
case O_COMMA: {
- assert(left);
- assert(right);
// jww (2006-09-29): This should act just like union
- xpath_t lexpr(left->compile(context, scope, resolve)); // for side-effects
- return right->compile(context, scope, resolve);
+ xpath_t lexpr(left()->compile(context, scope, resolve)); // for side-effects
+ return right()->compile(context, scope, resolve);
}
-#if 0
- case O_MATCH:
- case O_NMATCH: {
- assert(left);
- assert(right);
- xpath_t rexpr(right->compile(context, scope, resolve));
- xpath_t lexpr(left->compile(context, scope, resolve));
- if (! lexpr->constant() || rexpr->kind != MASK) {
- if (left == lexpr)
- return acquire();
- else
- return copy(lexpr, rexpr)->acquire();
- }
-
- if (lexpr->valuep->type != value_t::STRING)
- throw_(compile_error, "Left operand of mask operator is not a string");
-
- assert(rexpr->mask);
-
- bool result = rexpr->mask->match(lexpr->valuep->as_string());
- if (kind == O_NMATCH)
- result = ! result;
-
- if (left == lexpr) {
- return wrap_value(result)->acquire();
- } else {
- *lexpr->valuep = result;
- return lexpr->acquire();
- }
- }
-#endif
-
case O_DEFINE:
- assert(left);
- assert(right);
- if (left->kind == VAR_NAME || left->kind == FUNC_NAME) {
- xpath_t rexpr(right->compile(context, scope, resolve));
+ if (left()->kind == VAR_NAME || left()->kind == FUNC_NAME) {
+ xpath_t rexpr(right()->compile(context, scope, resolve));
if (scope)
- scope->define(*left->name, rexpr);
- return rexpr->acquire();
+ scope->define(left()->as_string(), rexpr.ptr);
+ return rexpr.ptr;
} else {
- assert(left->kind == O_EVAL);
- assert(left->left->kind == FUNC_NAME);
+ assert(left()->kind == O_EVAL);
+ assert(left()->left()->kind == FUNC_NAME);
std::auto_ptr<scope_t> arg_scope(new scope_t(scope));
- int index = 0;
- op_t * args = left->right;
+ unsigned int index = 0;
+ ptr_op_t args = left()->right();
while (args) {
- op_t * arg = args;
+ ptr_op_t arg = args;
if (args->kind == O_COMMA) {
- arg = args->left;
- args = args->right;
+ arg = args->left();
+ args = args->right();
} else {
args = NULL;
}
// Define the parameter so that on lookup the parser will find
// an ARG_INDEX value.
- std::auto_ptr<op_t> ref(new op_t(ARG_INDEX));
- ref->arg_index = index++;
+ ptr_op_t ref(new op_t(ARG_INDEX));
+ ref->set_long(index++);
assert(arg->kind == NODE_NAME);
- arg_scope->define(*arg->name, ref.release());
+ arg_scope->define(arg->as_string(), ref);
}
// jww (2006-09-16): If I compile the definition of a function,
@@ -1730,62 +1561,61 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
//xpath_t rexpr(right->compile(arg_scope.get(), resolve));
if (scope)
- scope->define(*left->left->name, right);
+ scope->define(left()->left()->as_string(), right());
- return right->acquire();
+ return right();
}
case O_EVAL: {
- assert(left);
-
std::auto_ptr<scope_t> call_args(new scope_t(scope));
call_args->kind = scope_t::ARGUMENT;
value_t::sequence_t call_seq;
- op_t * args = right;
+ ptr_op_t args = right();
while (args) {
- op_t * arg = args;
+ ptr_op_t arg = args;
if (args->kind == O_COMMA) {
- arg = args->left;
- args = args->right;
+ arg = args->left();
+ args = args->right();
} else {
args = NULL;
}
// jww (2006-09-15): Need to return a reference to these, if
// there are undetermined arguments!
- call_seq.push_back(arg->compile(context, scope, resolve)->value());
+ call_seq.push_back(arg->compile(context, scope, resolve)->as_value());
}
call_args->args = call_seq;
- if (left->kind == FUNC_NAME) {
+ if (left()->kind == FUNC_NAME) {
if (resolve) {
value_t temp;
- if (scope && scope->resolve(*left->name, temp, call_args.get()))
- return wrap_value(temp)->acquire();
+ if (scope && scope->resolve(left()->as_string(), temp, call_args.get()))
+ return wrap_value(temp);
}
// Don't compile to the left, otherwise the function name may
// get resolved before we have a chance to call it
- xpath_t func(left->compile(context, scope, false));
- if (func->kind == FUNCTOR) {
+ xpath_t func(left()->compile(context, scope, false));
+ if (func.ptr->kind == FUNCTION) {
value_t temp;
- (*func->functor)(temp, call_args.get());
- return wrap_value(temp)->acquire();
+ func.ptr->as_function()(temp, call_args.get());
+ return wrap_value(temp);
}
else if (! resolve) {
- return func->compile(context, call_args.get(), resolve);
+ return func.ptr->compile(context, call_args.get(), resolve);
}
else {
- throw_(calc_error, "Unknown function name '" << *left->name << "'");
+ throw_(calc_error,
+ "Unknown function name '" << left()->as_string() << "'");
}
}
- else if (left->kind == FUNCTOR) {
+ else if (left()->kind == FUNCTION) {
value_t temp;
- (*left->functor)(temp, call_args.get());
- return wrap_value(temp)->acquire();
+ left()->as_function()(temp, call_args.get());
+ return wrap_value(temp);
}
else {
assert(false);
@@ -1796,37 +1626,35 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
case O_FIND:
case O_RFIND:
case O_PRED: {
- assert(left);
- assert(right);
- xpath_t lexpr(left->compile(context, scope, resolve));
- xpath_t rexpr(resolve ? right->acquire() :
- right->compile(context, scope, false));
-
- if (! lexpr->constant() || ! resolve) {
- if (left == lexpr)
- return acquire();
+ xpath_t lexpr(left()->compile(context, scope, resolve));
+ xpath_t rexpr(resolve ? right() :
+ right()->compile(context, scope, false));
+
+ if (! lexpr.ptr->is_value() || ! resolve) {
+ if (left() == lexpr.ptr)
+ return this;
else
- return copy(lexpr, rexpr)->acquire();
+ return copy(lexpr.ptr, rexpr.ptr);
}
value_t::sequence_t result_seq;
// jww (2006-09-24): What about when nothing is found?
- switch (lexpr->valuep->type) {
+ switch (lexpr.ptr->as_value().type) {
case value_t::XML_NODE: {
- function_scope_t xpath_fscope(lexpr->valuep, 0, scope);
+ function_scope_t xpath_fscope(lexpr.ptr->as_value(), 0, scope);
if (kind == O_PRED) {
- if (rexpr->test_value(lexpr->valuep, &xpath_fscope))
- result_seq.push_back(*lexpr->valuep);
+ if (rexpr.ptr->test_value(lexpr.ptr->as_value(), &xpath_fscope))
+ result_seq.push_back(lexpr.ptr->as_value());
} else {
- rexpr->find_values(lexpr->valuep, &xpath_fscope, result_seq,
- kind == O_RFIND);
+ rexpr.ptr->find_values(lexpr.ptr->as_value(), &xpath_fscope, result_seq,
+ kind == O_RFIND);
}
break;
}
case value_t::SEQUENCE: {
- value_t::sequence_t& seq(lexpr->valuep->as_sequence());
+ value_t::sequence_t& seq(lexpr.ptr->as_value().as_sequence());
int index = 0;
for (value_t::sequence_t::iterator i = seq.begin();
@@ -1835,15 +1663,15 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
assert((*i).type != value_t::SEQUENCE);
if ((*i).type != value_t::XML_NODE)
throw_(compile_error, "Attempting to apply path selection "
- "to non-node(s)");
+ "to non-node(s)");
function_scope_t xpath_fscope(seq, &(*i), index, scope);
if (kind == O_PRED) {
- if (rexpr->test_value(&(*i), &xpath_fscope, index))
+ if (rexpr.ptr->test_value(*i, &xpath_fscope, index))
result_seq.push_back(*i);
} else {
- rexpr->find_values(&(*i), &xpath_fscope, result_seq,
- kind == O_RFIND);
+ rexpr.ptr->find_values(*i, &xpath_fscope, result_seq,
+ kind == O_RFIND);
}
}
break;
@@ -1855,27 +1683,10 @@ xpath_t::op_t * xpath_t::op_t::compile(value_t * context, scope_t * scope,
}
if (result_seq.size() == 1)
- return wrap_value(result_seq.front())->acquire();
+ return wrap_value(result_seq.front());
else
- return wrap_sequence(result_seq)->acquire();
- }
-
-#if 0
- case O_PERC: {
- assert(left);
- xpath_t expr(left->compile(context, scope, resolve));
- if (! expr->constant()) {
- if (left == expr)
- return acquire();
- else
- return copy(expr)->acquire();
- }
-
- static value_t perc("100.0%");
- *expr->valuep = perc * *expr->valuep;
- return expr->acquire();
+ return wrap_sequence(result_seq);
}
-#endif
case LAST:
default:
@@ -1905,10 +1716,10 @@ void xpath_t::calc(value_t& result, node_t& node, scope_t * scope) const
try {
#endif
value_t context_node(&node);
- xpath_t final(ptr->compile(&context_node, scope, true));
+ xpath_t final(ptr->compile(context_node, scope, true));
// jww (2006-09-09): Give a better error here if this is not
// actually a value
- final->get_value(result);
+ result = final.ptr->as_value();
#if 0
}
catch (error * err) {
@@ -1929,17 +1740,11 @@ void xpath_t::calc(value_t& result, node_t& node, scope_t * scope) const
}
#if 0
-xpath_t::context::context(const xpath_t& _xpath,
- const op_t * _err_node,
- const string& desc) throw()
+xpath_t::context::context(const xpath_t& _xpath,
+ const ptr_op_t& _err_node,
+ const string& desc) throw()
: error_context(desc), xpath(_xpath), err_node(_err_node)
{
- _err_node->acquire();
-}
-
-xpath_t::context::~context() throw()
-{
- if (err_node) err_node->release();
}
void xpath_t::context::describe(std::ostream& out) const throw()
@@ -1975,7 +1780,7 @@ void xpath_t::context::describe(std::ostream& out) const throw()
bool xpath_t::op_t::print(std::ostream& out,
const bool relaxed,
- const op_t * op_to_find,
+ const ptr_op_t& op_to_find,
unsigned long * start_pos,
unsigned long * end_pos) const
{
@@ -1990,10 +1795,11 @@ bool xpath_t::op_t::print(std::ostream& out,
string symbol;
switch (kind) {
- case VALUE:
- switch (valuep->type) {
+ case VALUE: {
+ const value_t& value(as_value());
+ switch (value.type) {
case value_t::BOOLEAN:
- if (*(valuep))
+ if (value)
out << "1";
else
out << "0";
@@ -2002,7 +1808,7 @@ bool xpath_t::op_t::print(std::ostream& out,
case value_t::AMOUNT:
if (! relaxed)
out << '{';
- out << *(valuep);
+ out << value;
if (! relaxed)
out << '}';
break;
@@ -2011,274 +1817,244 @@ bool xpath_t::op_t::print(std::ostream& out,
assert(false);
break;
case value_t::DATETIME:
- out << '[' << *valuep << ']';
+ out << '[' << value << ']';
break;
case value_t::STRING:
- out << '"' << *valuep << '"';
+ out << '"' << value << '"';
break;
case value_t::XML_NODE:
- out << '<' << valuep << '>';
+ out << '<' << value << '>';
break;
case value_t::POINTER:
- out << '&' << valuep;
+ out << '&' << value;
break;
case value_t::SEQUENCE:
- out << '~' << valuep << '~';
+ out << '~' << value << '~';
break;
}
break;
+ }
case NODE_ID:
- out << '%' << name_id;
+ out << '%' << as_name();
break;
case NODE_NAME:
case FUNC_NAME:
- out << *name;
+ out << as_string();
break;
case ATTR_NAME:
- out << '@' << *name;
+ out << '@' << as_string();
break;
case VAR_NAME:
- out << '$' << *name;
+ out << '$' << as_string();
break;
- case FUNCTOR:
- out << functor->name();
+ case FUNCTION:
+ out << as_function();
break;
-#if 0
- case MASK:
- out << '/' << mask->pattern << '/';
- break;
-#endif
-
case ARG_INDEX:
- out << '@' << arg_index;
+ out << '@' << as_long();
break;
case O_NOT:
out << "!";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_NEG:
out << "-";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_UNION:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " | ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_ADD:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " + ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_SUB:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " - ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_MUL:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " * ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_DIV:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " / ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_NEQ:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " != ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_EQ:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " == ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_LT:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " < ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_LTE:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " <= ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_GT:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " > ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_GTE:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " >= ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_AND:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " & ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_OR:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " | ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_QUES:
out << "(";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " ? ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_COLON:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << " : ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_COMMA:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ", ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
- found = true;
- break;
-
-#if 0
- case O_MATCH:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
- found = true;
- out << " =~ ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
- found = true;
- break;
- case O_NMATCH:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
- found = true;
- out << " !~ ";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
-#endif
case O_DEFINE:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << '=';
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_EVAL:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << "(";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << ")";
break;
case O_FIND:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << "/";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_RFIND:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << "//";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
break;
case O_PRED:
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (left() && left()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << "[";
- if (right && right->print(out, relaxed, op_to_find, start_pos, end_pos))
+ if (right() && right()->print(out, relaxed, op_to_find, start_pos, end_pos))
found = true;
out << "]";
break;
-#if 0
- case O_PERC:
- out << "%";
- if (left && left->print(out, relaxed, op_to_find, start_pos, end_pos))
- found = true;
- break;
-#endif
-
case LAST:
default:
assert(false);
@@ -2308,41 +2084,38 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
switch (kind) {
case VALUE:
- out << "VALUE - " << *valuep;
+ out << "VALUE - " << as_value();
break;
case NODE_NAME:
- out << "NODE_NAME - " << *name;
+ out << "NODE_NAME - " << as_string();
break;
-
case NODE_ID:
- out << "NODE_ID - " << name_id;
+ out << "NODE_ID - " << as_name();
break;
case ATTR_NAME:
- out << "ATTR_NAME - " << *name;
+ out << "ATTR_NAME - " << as_string();
+ break;
+ case ATTR_ID:
+ out << "ATTR_ID - " << as_name();
break;
case FUNC_NAME:
- out << "FUNC_NAME - " << *name;
+ out << "FUNC_NAME - " << as_string();
break;
case VAR_NAME:
- out << "VAR_NAME - " << *name;
+ out << "VAR_NAME - " << as_string();
break;
case ARG_INDEX:
- out << "ARG_INDEX - " << arg_index;
+ out << "ARG_INDEX - " << as_long();
break;
- case FUNCTOR:
- out << "FUNCTOR - " << functor->name();
- break;
-#if 0
- case MASK:
- out << "MASK - " << mask->pattern;
+ case FUNCTION:
+ out << "FUNCTION - " << as_function();
break;
-#endif
case O_NOT: out << "O_NOT"; break;
case O_NEG: out << "O_NEG"; break;
@@ -2369,11 +2142,6 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
case O_COMMA: out << "O_COMMA"; break;
-#if 0
- case O_MATCH: out << "O_MATCH"; break;
- case O_NMATCH: out << "O_NMATCH"; break;
-#endif
-
case O_DEFINE: out << "O_DEFINE"; break;
case O_EVAL: out << "O_EVAL"; break;
@@ -2381,10 +2149,6 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
case O_RFIND: out << "O_RFIND"; break;
case O_PRED: out << "O_PRED"; break;
-#if 0
- case O_PERC: out << "O_PERC"; break;
-#endif
-
case LAST:
default:
assert(false);
@@ -2394,15 +2158,15 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
out << " (" << refc << ')' << std::endl;
if (kind > TERMINALS) {
- if (left) {
- left->dump(out, depth + 1);
- if (right)
- right->dump(out, depth + 1);
+ if (left()) {
+ left()->dump(out, depth + 1);
+ if (right())
+ right()->dump(out, depth + 1);
} else {
- assert(! right);
+ assert(! right());
}
} else {
- assert(! left);
+ assert(! left());
}
}
diff --git a/src/xpath.h b/src/xpath.h
index 8819d49e..41dc36e4 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -41,6 +41,7 @@ class xpath_t
{
public:
struct op_t;
+ typedef intrusive_ptr<op_t> ptr_op_t;
static void initialize();
static void shutdown();
@@ -49,145 +50,24 @@ public:
DECLARE_EXCEPTION(compile_error);
DECLARE_EXCEPTION(calc_error);
-#if 0
- class context : public error_context {
- public:
- const xpath_t& xpath;
- const op_t * err_node;
-
- context(const xpath_t& _xpath,
- const op_t * _err_node,
- const string& desc = "") throw();
- virtual ~context() throw();
-
- virtual void describe(std::ostream& out) const throw();
- };
-#endif
-
public:
class scope_t;
- class functor_t {
- protected:
- string fname;
- public:
- bool wants_args;
-
- functor_t(const string& _fname, bool _wants_args = false)
- : fname(_fname), wants_args(_wants_args) {}
- virtual ~functor_t() {}
-
- virtual void operator()(value_t& result, scope_t * locals) = 0;
- virtual string name() const { return fname; }
- };
-
- template <typename T, typename U>
- class member_functor_t : public functor_t {
- public:
- T * ptr;
- U T::*dptr;
-
- member_functor_t(const string& _name, T * _ptr, U T::*_dptr)
- : functor_t(_name, false), ptr(_ptr), dptr(_dptr) {}
-
- virtual void operator()(value_t& result, scope_t * locals) {
- assert(ptr);
- assert(dptr);
- result = ptr->*dptr;
- }
- };
-
- template <typename T>
- class member_functor_t<T, string> : public functor_t {
- public:
- T * ptr;
- string T::*dptr;
-
- member_functor_t(const string& _name, T * _ptr, string T::*_dptr)
- : functor_t(_name, false), ptr(_ptr), dptr(_dptr) {}
-
- virtual void operator()(value_t& result, scope_t * locals) {
- assert(ptr);
- assert(dptr);
- result.set_string(ptr->*dptr);
- }
- };
-
- template <typename T>
- class memfun_functor_t : public functor_t {
- public:
- T * ptr;
- void (T::*mptr)(value_t& result);
-
- memfun_functor_t(const string& _name, T * _ptr,
- void (T::*_mptr)(value_t& result))
- : functor_t(_name, false), ptr(_ptr), mptr(_mptr) {}
-
- virtual void operator()(value_t& result, scope_t * locals = NULL) {
- assert(ptr);
- assert(mptr);
- assert(locals || locals == NULL);
- (ptr->*mptr)(result);
- }
- };
-
- template <typename T>
- class memfun_args_functor_t : public functor_t {
- public:
- T * ptr;
- void (T::*mptr)(value_t& result, scope_t * locals);
-
- memfun_args_functor_t(const string& _name, T * _ptr,
- void (T::*_mptr)(value_t& result, scope_t * locals))
- : functor_t(_name, true), ptr(_ptr), mptr(_mptr) {}
-
- virtual void operator()(value_t& result, scope_t * locals) {
- assert(ptr);
- assert(mptr);
- (ptr->*mptr)(result, locals);
- }
- };
+ typedef function<void (value_t&, scope_t *)> function_t;
- static op_t * wrap_value(const value_t& val);
- static op_t * wrap_sequence(const value_t::sequence_t& val);
- static op_t * wrap_functor(functor_t * fobj);
-#if 0
- static op_t * wrap_mask(const string& pattern);
-#endif
+#define MAKE_FUNCTOR(x) \
+ xml::xpath_t::wrap_functor(bind(&x, this, _1, _2))
- template <typename T, typename U>
- static op_t *
- make_functor(const string& name, T * ptr, U T::*mptr) {
- return wrap_functor(new member_functor_t<T, U>(name, ptr, mptr));
- }
-
- template <typename T>
- static op_t *
- make_functor(const string& fname, T * ptr,
- void (T::*mptr)(value_t& result)) {
- return wrap_functor(new memfun_functor_t<T>(fname, ptr, mptr));
- }
-
- template <typename T>
- static op_t *
- make_functor(const string& fname, T * ptr,
- void (T::*mptr)(value_t& result, scope_t * locals)) {
- return wrap_functor(new memfun_args_functor_t<T>(fname, ptr, mptr));
- }
-
-#define MAKE_FUNCTOR(cls, name) \
- xml::xpath_t::make_functor(#name, this, &cls::name)
+ static ptr_op_t wrap_value(const value_t& val);
+ static ptr_op_t wrap_sequence(const value_t::sequence_t& val);
+ static ptr_op_t wrap_functor(const function_t& fobj);
public:
- class scope_t
+ class scope_t : public noncopyable
{
- typedef std::map<const string, op_t *> symbol_map;
-
+ typedef std::map<const string, ptr_op_t> symbol_map;
symbol_map symbols;
- scope_t(const scope_t&);
- scope_t& operator=(const scope_t&);
-
public:
scope_t * parent;
value_t args;
@@ -201,23 +81,19 @@ public:
virtual ~scope_t() {
TRACE_DTOR(xpath_t::scope_t);
- for (symbol_map::iterator i = symbols.begin();
- i != symbols.end();
- i++)
- (*i).second->release();
}
public:
- virtual void define(const string& name, op_t * def);
+ virtual void define(const string& name, ptr_op_t def);
virtual bool resolve(const string& name, value_t& result,
scope_t * locals = NULL) {
if (parent)
return parent->resolve(name, result, locals);
return false;
}
- virtual op_t * lookup(const string& name);
+ virtual ptr_op_t lookup(const string& name);
- void define(const string& name, functor_t * def);
+ void define(const string& name, const function_t& def);
friend struct op_t;
};
@@ -225,15 +101,17 @@ public:
class function_scope_t : public scope_t
{
value_t::sequence_t sequence;
- value_t * value;
+ value_t value;
int index;
public:
function_scope_t(const value_t::sequence_t& _sequence,
- value_t * _value, int _index, scope_t * _parent = NULL)
+ value_t * _value, int _index,
+ scope_t * _parent = NULL)
: scope_t(_parent, STATIC),
sequence(_sequence), value(_value), index(_index) {}
- function_scope_t(value_t * _value, int _index, scope_t * _parent = NULL)
+ function_scope_t(const value_t& _value, int _index,
+ scope_t * _parent = NULL)
: scope_t(_parent, STATIC), value(_value), index(_index) {}
virtual bool resolve(const string& name, value_t& result,
@@ -245,10 +123,9 @@ public:
#define XPATH_PARSE_RELAXED 0x02
#define XPATH_PARSE_NO_MIGRATE 0x04
#define XPATH_PARSE_NO_REDUCE 0x08
-#if 0
-#define XPATH_PARSE_REGEXP 0x10
-#endif
-#define XPATH_PARSE_ALLOW_DATE 0x20
+#define XPATH_PARSE_ALLOW_DATE 0x10
+
+ typedef uint_least8_t flags_t;
private:
struct token_t
@@ -256,10 +133,6 @@ private:
enum kind_t {
IDENT, // [A-Za-z_][-A-Za-z0-9_:]*
VALUE, // any kind of literal value
-#if 0
- REGEXP, // /regexp/ jww (2006-09-24): deprecate
- // in favor of a "match" function
-#endif
AT_SYM, // @
DOLLAR, // $
DOT, // .
@@ -286,11 +159,6 @@ private:
QUESTION, // ?
COLON, // :
COMMA, // ,
-#if 0
- MATCH, // =~
- NMATCH, // !~
- PERCENT, // %
-#endif
KW_AND,
KW_OR,
KW_DIV,
@@ -336,34 +204,33 @@ private:
}
void parse_ident(std::istream& in);
- void next(std::istream& in, unsigned short flags);
+
+ void next(std::istream& in, flags_t flags);
void rewind(std::istream& in);
- void unexpected();
+ void unexpected();
static void unexpected(char c, char wanted = '\0');
};
public:
- struct op_t
+ struct op_t : public noncopyable
{
enum kind_t {
VOID,
VALUE,
- NODE_NAME,
NODE_ID,
- FUNC_NAME,
+ NODE_NAME,
+ ATTR_ID,
ATTR_NAME,
+ FUNC_NAME,
VAR_NAME,
ARG_INDEX,
CONSTANTS, // constants end here
- FUNCTOR,
-#if 0
- MASK,
-#endif
+ FUNCTION,
TERMINALS, // terminals end here
@@ -392,19 +259,10 @@ public:
O_COMMA,
-#if 0
- O_MATCH,
- O_NMATCH,
-#endif
-
O_DEFINE,
O_EVAL,
O_ARG,
-#if 0
- O_PERC,
-#endif
-
O_FIND,
O_RFIND,
O_PRED,
@@ -414,53 +272,96 @@ public:
kind_t kind;
mutable short refc;
- op_t * left;
+ ptr_op_t left_;
-#if 0
- optional<variant<value_t,
- string,
- unsigned int,
- functor_t,
- mask_t,
- op_t> > data;
-#else
- union {
- value_t * valuep; // used by constant VALUE
- string * name; // used by constant SYMBOL
- unsigned int arg_index; // used by ARG_INDEX and O_ARG
- functor_t * functor; // used by terminal FUNCTOR
- node_t::nameid_t name_id; // used by NODE_NAME and ATTR_NAME
-#if 0
- mask_t * mask; // used by terminal MASK
-#endif
- op_t * right; // used by all operators
- };
-#endif
+ variant<unsigned int, // used by ARG_INDEX and O_ARG
+ shared_ptr<value_t>, // used by constant VALUE
+ string, // used by constant SYMBOL
+ function_t, // used by terminal FUNCTION
+ node_t::nameid_t, // used by NODE_NAME and ATTR_NAME
+ ptr_op_t> // used by all binary operators
+ data;
- op_t(const kind_t _kind)
- : kind(_kind), refc(0), left(NULL), right(NULL) {
+ op_t(const kind_t _kind) : kind(_kind), refc(0){
TRACE_CTOR(xpath_t::op_t, "const kind_t");
}
- op_t(const op_t&);
- ~op_t();
+ ~op_t() {
+ TRACE_DTOR(xpath_t::op_t);
+
+ DEBUG("ledger.xpath.memory", "Destroying " << this);
+ assert(refc == 0);
+ }
op_t& operator=(const op_t&);
- bool constant() const {
+ bool is_value() const {
return kind == VALUE;
}
- void get_value(value_t& result) const;
- value_t value() const {
- value_t temp;
- get_value(temp);
- return temp;
+
+ unsigned int& as_long() {
+ assert(kind == ARG_INDEX || kind == O_ARG);
+ return boost::get<unsigned int>(data);
+ }
+ const unsigned int& as_long() const {
+ return const_cast<op_t *>(this)->as_long();
+ }
+ void set_long(unsigned int val) {
+ data = val;
}
- functor_t * functor_obj() const {
- if (kind == FUNCTOR)
- return functor;
- else
- return NULL;
+ value_t& as_value() {
+ assert(kind == VALUE);
+ value_t * val = boost::get<scoped_ptr<value_t> >(data).get();
+ assert(val);
+ return *val;
+ }
+ const value_t& as_value() const {
+ return const_cast<op_t *>(this)->as_value();
+ }
+ void set_value(value_t * val) {
+ // jww (2007-05-14): Ugh, fix this
+ data = shared_ptr<value_t>(val);
+ }
+
+ string& as_string() {
+ assert(kind == NODE_NAME || kind == ATTR_NAME || kind == FUNC_NAME);
+ return boost::get<string>(data);
+ }
+ const string& as_string() const {
+ return const_cast<op_t *>(this)->as_string();
+ }
+ void set_string(const string& val) {
+ data = val;
+ }
+
+ function_t& as_function() {
+ assert(kind == FUNCTION);
+ return boost::get<function_t>(data);
+ }
+ const function_t& as_function() const {
+ return const_cast<op_t *>(this)->as_function();
+ }
+ void set_function(const function_t& val) {
+ data = val;
+ }
+
+ node_t::nameid_t& as_name() {
+ assert(kind == NODE_ID || kind == ATTR_ID);
+ return boost::get<node_t::nameid_t>(data);
+ }
+ const node_t::nameid_t& as_name() const {
+ return const_cast<op_t *>(this)->as_name();
+ }
+ void set_name(const node_t::nameid_t& val) {
+ data = val;
+ }
+
+ ptr_op_t& as_op() {
+ assert(kind > TERMINALS);
+ return boost::get<ptr_op_t>(data);
+ }
+ const ptr_op_t& as_op() const {
+ return const_cast<op_t *>(this)->as_op();
}
void release() const {
@@ -470,54 +371,55 @@ public:
if (--refc == 0)
checked_delete(this);
}
- op_t * acquire() {
- DEBUG("ledger.xpath.memory",
- "Acquiring " << this << ", refc now " << refc + 1);
- assert(refc >= 0);
- refc++;
- return this;
- }
- const op_t * acquire() const {
+ void acquire() {
DEBUG("ledger.xpath.memory",
"Acquiring " << this << ", refc now " << refc + 1);
assert(refc >= 0);
refc++;
- return this;
}
- void set_left(op_t * expr) {
+ ptr_op_t& left() {
+ return left_;
+ }
+ const ptr_op_t& left() const {
+ assert(kind > TERMINALS);
+ return left_;
+ }
+ void set_left(const ptr_op_t& expr) {
assert(kind > TERMINALS);
- if (left)
- left->release();
- left = expr ? expr->acquire() : NULL;
+ left_ = expr;
}
- void set_right(op_t * expr) {
+ ptr_op_t& right() {
+ assert(kind > TERMINALS);
+ return as_op();
+ }
+ const ptr_op_t& right() const {
+ assert(kind > TERMINALS);
+ return as_op();
+ }
+ void set_right(const ptr_op_t& expr) {
assert(kind > TERMINALS);
- if (right)
- right->release();
- right = expr ? expr->acquire() : NULL;
+ data = expr;
}
- static op_t * new_node(kind_t kind, op_t * left = NULL,
- op_t * right = NULL);
+ static ptr_op_t new_node(kind_t kind, ptr_op_t left = NULL,
+ ptr_op_t right = NULL);
- op_t * copy(op_t * left = NULL,
- op_t * right = NULL) const;
- op_t * compile(value_t * context, scope_t * scope,
- bool resolve = false);
+ ptr_op_t copy(ptr_op_t left = NULL, ptr_op_t right = NULL) const;
+ ptr_op_t compile(value_t& context, scope_t * scope, bool resolve = false);
- void find_values(value_t * context, scope_t * scope,
+ void find_values(value_t& context, scope_t * scope,
value_t::sequence_t& result_seq, bool recursive);
- bool test_value(value_t * context, scope_t * scope, int index = 0);
+ bool test_value(value_t& context, scope_t * scope, int index = 0);
void append_value(value_t& value, value_t::sequence_t& result_seq);
- static op_t * defer_sequence(value_t::sequence_t& result_seq);
+ static ptr_op_t defer_sequence(value_t::sequence_t& result_seq);
bool print(std::ostream& out,
const bool relaxed = true,
- const op_t * op_to_find = NULL,
+ const ptr_op_t& op_to_find = NULL,
unsigned long * start_pos = NULL,
unsigned long * end_pos = NULL) const;
@@ -525,44 +427,14 @@ public:
};
public:
- op_t * ptr;
+ ptr_op_t ptr;
- xpath_t& operator=(op_t * _expr) {
+ xpath_t& operator=(ptr_op_t _expr) {
expr = "";
- reset(_expr);
+ ptr = _expr;
return *this;
}
- op_t& operator*() throw() {
- return *ptr;
- }
- const op_t& operator*() const throw() {
- return *ptr;
- }
- op_t * operator->() throw() {
- return ptr;
- }
- const op_t * operator->() const throw() {
- return ptr;
- }
-
- op_t * get() throw() { return ptr; }
- const op_t * get() const throw() { return ptr; }
-
- op_t * release() throw() {
- op_t * tmp = ptr;
- ptr = 0;
- return tmp;
- }
-
- void reset(op_t * p = 0) throw() {
- if (p != ptr) {
- if (ptr)
- ptr->release();
- ptr = p;
- }
- }
-
#ifdef THREADSAFE
mutable token_t lookahead;
#else
@@ -570,7 +442,7 @@ public:
#endif
mutable bool use_lookahead;
- token_t& next_token(std::istream& in, unsigned short tflags) const {
+ token_t& next_token(std::istream& in, flags_t tflags) const {
if (use_lookahead)
use_lookahead = false;
else
@@ -597,24 +469,24 @@ public:
use_lookahead = true;
}
- op_t * parse_value_term(std::istream& in, unsigned short flags) const;
- op_t * parse_predicate_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_path_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_unary_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_union_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_mul_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_add_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_logic_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_and_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_or_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_querycolon_expr(std::istream& in, unsigned short flags) const;
- op_t * parse_value_expr(std::istream& in, unsigned short flags) const;
-
- op_t * parse_expr(std::istream& in,
- unsigned short flags = XPATH_PARSE_RELAXED) const;
-
- op_t * parse_expr(const string& str,
- unsigned short tflags = XPATH_PARSE_RELAXED) const
+ ptr_op_t parse_value_term(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_predicate_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_path_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_unary_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_union_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_mul_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_add_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_logic_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_and_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_or_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_querycolon_expr(std::istream& in, flags_t flags) const;
+ ptr_op_t parse_value_expr(std::istream& in, flags_t flags) const;
+
+ ptr_op_t parse_expr(std::istream& in,
+ flags_t flags = XPATH_PARSE_RELAXED) const;
+
+ ptr_op_t parse_expr(const string& str,
+ flags_t tflags = XPATH_PARSE_RELAXED) const
{
std::istringstream stream(str);
#if 0
@@ -632,14 +504,14 @@ public:
#endif
}
- op_t * parse_expr(const char * p,
- unsigned short tflags = XPATH_PARSE_RELAXED) const {
+ ptr_op_t parse_expr(const char * p,
+ flags_t tflags = XPATH_PARSE_RELAXED) const {
return parse_expr(string(p), tflags);
}
bool print(std::ostream& out,
const bool relaxed,
- const op_t * op_to_find,
+ const ptr_op_t op_to_find,
unsigned long * start_pos,
unsigned long * end_pos) const {
if (ptr)
@@ -648,36 +520,34 @@ public:
}
public:
- string expr;
- unsigned short flags; // flags used to parse `expr'
+ string expr;
+ flags_t flags; // flags used to parse `expr'
xpath_t() : ptr(NULL), use_lookahead(false), flags(0) {
TRACE_CTOR(xpath_t, "");
}
- xpath_t(op_t * _ptr) : ptr(_ptr), use_lookahead(false) {
- TRACE_CTOR(xpath_t, "op_t *");
+ xpath_t(ptr_op_t _ptr) : ptr(_ptr), use_lookahead(false) {
+ TRACE_CTOR(xpath_t, "ptr_op_t");
}
- xpath_t(const string& _expr,
- unsigned short _flags = XPATH_PARSE_RELAXED)
+ xpath_t(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED)
: ptr(NULL), use_lookahead(false), flags(0) {
- TRACE_CTOR(xpath_t, "const string&, unsigned short");
+ TRACE_CTOR(xpath_t, "const string&, flags_t");
if (! _expr.empty())
parse(_expr, _flags);
}
- xpath_t(std::istream& in, unsigned short _flags = XPATH_PARSE_RELAXED)
+ xpath_t(std::istream& in, flags_t _flags = XPATH_PARSE_RELAXED)
: ptr(NULL), use_lookahead(false), flags(0) {
- TRACE_CTOR(xpath_t, "std::istream&, unsigned short");
+ TRACE_CTOR(xpath_t, "std::istream&, flags_t");
parse(in, _flags);
}
xpath_t(const xpath_t& other)
- : ptr(other.ptr ? other.ptr->acquire() : NULL),
- use_lookahead(false), expr(other.expr), flags(other.flags) {
+ : ptr(other.ptr), use_lookahead(false),
+ expr(other.expr), flags(other.flags) {
TRACE_CTOR(xpath_t, "copy");
}
virtual ~xpath_t() {
TRACE_DTOR(xpath_t);
- reset(NULL);
}
xpath_t& operator=(const string& _expr) {
@@ -686,14 +556,14 @@ public:
}
xpath_t& operator=(const xpath_t& _expr);
xpath_t& operator=(xpath_t& _xpath) {
- ptr = _xpath.ptr->acquire();
+ ptr = _xpath.ptr;
expr = _xpath.expr;
flags = _xpath.flags;
use_lookahead = false;
return *this;
}
- operator op_t *() throw() {
+ operator ptr_op_t() throw() {
return ptr;
}
@@ -704,29 +574,21 @@ public:
return expr;
}
- void parse(const string& _expr, unsigned short _flags = XPATH_PARSE_RELAXED) {
+ void parse(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED) {
expr = _expr;
flags = _flags;
- op_t * tmp = parse_expr(_expr, _flags);
- assert(tmp);
- reset(tmp ? tmp->acquire() : NULL);
+ ptr = parse_expr(_expr, _flags);
}
- void parse(std::istream& in, unsigned short _flags = XPATH_PARSE_RELAXED) {
+ void parse(std::istream& in, flags_t _flags = XPATH_PARSE_RELAXED) {
expr = "";
flags = _flags;
- op_t * tmp = parse_expr(in, _flags);
- assert(tmp);
- reset(tmp ? tmp->acquire() : NULL);
+ ptr = parse_expr(in, _flags);
}
void compile(node_t& top_node, scope_t * scope = NULL) {
- if (ptr) {
+ if (ptr.get()) {
value_t noderef(&top_node);
- op_t * compiled = ptr->compile(&noderef, scope);
- if (compiled == ptr)
- compiled->release();
- else
- reset(compiled);
+ ptr = ptr->compile(noderef, scope);
}
}
@@ -767,6 +629,13 @@ inline std::ostream& operator<<(std::ostream& out, const xpath_t::op_t& op) {
return out;
}
+inline void intrusive_ptr_add_ref(xpath_t::op_t * op) {
+ op->acquire();
+}
+inline void intrusive_ptr_release(xpath_t::op_t * op) {
+ op->release();
+}
+
} // namespace xml
template <typename T>
@@ -777,15 +646,20 @@ inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
return ptr;
}
-class xml_command : public xml::xpath_t::functor_t
+template <typename T>
+inline T * get_node_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
+ assert(locals->args.size() > idx);
+ T * ptr = polymorphic_downcast<T *>(locals->args[idx].as_xml_node());
+ assert(ptr);
+ return ptr;
+}
+
+class xml_command
{
public:
- xml_command() : xml::xpath_t::functor_t("xml") {}
-
- virtual void operator()(value_t&, xml::xpath_t::scope_t * locals) {
+ void operator()(value_t&, xml::xpath_t::scope_t * locals) {
std::ostream * out = get_ptr<std::ostream>(locals, 0);
- xml::document_t * doc = get_ptr<xml::document_t>(locals, 1);
-
+ xml::document_t * doc = get_node_ptr<xml::document_t>(locals, 1);
doc->print(*out);
}
};