diff options
author | John Wiegley <johnw@newartisans.com> | 2007-05-14 11:09:54 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:50 -0400 |
commit | f83705b847c59a8197f5098cb7dc2d484704e24d (patch) | |
tree | 1b314d07bb9f50a75781d703ec6c778056e74684 | |
parent | 65af1688382331d91153fb2366026e94feb5afe2 (diff) | |
download | fork-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.am | 4 | ||||
-rw-r--r-- | src/journal.cc | 5 | ||||
-rw-r--r-- | src/journal.h | 82 | ||||
-rw-r--r-- | src/ledger.h | 12 | ||||
-rw-r--r-- | src/main.cc | 57 | ||||
-rw-r--r-- | src/node.h | 7 | ||||
-rw-r--r-- | src/option.cc | 63 | ||||
-rw-r--r-- | src/parser.h | 6 | ||||
-rw-r--r-- | src/pyinterp.cc | 4 | ||||
-rw-r--r-- | src/pyinterp.h | 16 | ||||
-rw-r--r-- | src/report.cc | 51 | ||||
-rw-r--r-- | src/report.h | 4 | ||||
-rw-r--r-- | src/session.cc | 65 | ||||
-rw-r--r-- | src/session.h | 21 | ||||
-rw-r--r-- | src/system.hh | 2 | ||||
-rw-r--r-- | src/textual.cc | 11 | ||||
-rw-r--r-- | src/textual.h | 6 | ||||
-rw-r--r-- | src/transform.cc | 34 | ||||
-rw-r--r-- | src/transform.h | 30 | ||||
-rw-r--r-- | src/xpath.cc | 1316 | ||||
-rw-r--r-- | src/xpath.h | 518 |
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())); @@ -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); } }; |