Completely revised the way XPath expressions are calculated.
This commit is contained in:
parent
2d8512af88
commit
b6ab7deb63
16 changed files with 1033 additions and 1340 deletions
|
|
@ -126,13 +126,13 @@ commodity_t::operator bool() const
|
||||||
annotated_commodity_t& commodity_t::as_annotated()
|
annotated_commodity_t& commodity_t::as_annotated()
|
||||||
{
|
{
|
||||||
assert(annotated);
|
assert(annotated);
|
||||||
return *polymorphic_downcast<annotated_commodity_t *>(this);
|
return downcast<annotated_commodity_t>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const annotated_commodity_t& commodity_t::as_annotated() const
|
const annotated_commodity_t& commodity_t::as_annotated() const
|
||||||
{
|
{
|
||||||
assert(annotated);
|
assert(annotated);
|
||||||
return *polymorphic_downcast<const annotated_commodity_t *>(this);
|
return downcast<const annotated_commodity_t>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool commodity_t::symbol_needs_quotes(const string& symbol)
|
bool commodity_t::symbol_needs_quotes(const string& symbol)
|
||||||
|
|
|
||||||
35
src/main.cc
35
src/main.cc
|
|
@ -136,7 +136,7 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (verb == "xml")
|
if (verb == "xml")
|
||||||
command = xml_command();
|
command = bind(xml_command, _1);
|
||||||
else if (verb == "expr")
|
else if (verb == "expr")
|
||||||
;
|
;
|
||||||
else if (verb == "xpath")
|
else if (verb == "xpath")
|
||||||
|
|
@ -145,17 +145,19 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
|
||||||
xml::xpath_t expr(*arg);
|
xml::xpath_t expr(*arg);
|
||||||
xml::document_t temp(xml::LEDGER_NODE);
|
xml::document_t temp(xml::LEDGER_NODE);
|
||||||
|
|
||||||
|
xml::xpath_t::document_scope_t doc_scope(report, temp);
|
||||||
|
|
||||||
IF_INFO() {
|
IF_INFO() {
|
||||||
std::cout << "Value expression tree:" << std::endl;
|
std::cout << "Value expression tree:" << std::endl;
|
||||||
expr.dump(std::cout);
|
expr.dump(std::cout);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << "Value expression parsed was:" << std::endl;
|
std::cout << "Value expression parsed was:" << std::endl;
|
||||||
expr.print(std::cout, temp);
|
expr.print(std::cout, doc_scope);
|
||||||
std::cout << std::endl << std::endl;
|
std::cout << std::endl << std::endl;
|
||||||
std::cout << "Result of calculation: ";
|
std::cout << "Result of calculation: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << expr.calc(temp, report).strip_annotations() << std::endl;
|
std::cout << expr.calc(doc_scope).strip_annotations() << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -242,8 +244,12 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
report.define("ostream", value_t(out));
|
||||||
|
|
||||||
// Are we handling the expr commands? Do so now.
|
// Are we handling the expr commands? Do so now.
|
||||||
|
|
||||||
|
xml::xpath_t::document_scope_t doc_scope(report, xml_document);
|
||||||
|
|
||||||
if (verb == "expr") {
|
if (verb == "expr") {
|
||||||
xml::xpath_t expr(*arg);
|
xml::xpath_t expr(*arg);
|
||||||
|
|
||||||
|
|
@ -252,12 +258,12 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
|
||||||
expr.dump(*out);
|
expr.dump(*out);
|
||||||
*out << std::endl;
|
*out << std::endl;
|
||||||
*out << "Value expression parsed was:" << std::endl;
|
*out << "Value expression parsed was:" << std::endl;
|
||||||
expr.print(*out, xml_document);
|
expr.print(*out, doc_scope);
|
||||||
*out << std::endl << std::endl;
|
*out << std::endl << std::endl;
|
||||||
*out << "Result of calculation: ";
|
*out << "Result of calculation: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
*out << expr.calc(xml_document, report).strip_annotations() << std::endl;
|
*out << expr.calc(doc_scope).strip_annotations() << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -265,9 +271,10 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
|
||||||
std::cout << "XPath parsed:" << std::endl;
|
std::cout << "XPath parsed:" << std::endl;
|
||||||
|
|
||||||
xml::xpath_t xpath(*arg);
|
xml::xpath_t xpath(*arg);
|
||||||
xpath.print(*out, xml_document);
|
xpath.print(*out, doc_scope);
|
||||||
*out << std::endl;
|
*out << std::endl;
|
||||||
|
|
||||||
|
#if 0
|
||||||
foreach (const value_t& value, xpath.find_all(xml_document, report)) {
|
foreach (const value_t& value, xpath.find_all(xml_document, report)) {
|
||||||
if (value.is_xml_node()) {
|
if (value.is_xml_node()) {
|
||||||
value.as_xml_node()->print(std::cout);
|
value.as_xml_node()->print(std::cout);
|
||||||
|
|
@ -276,31 +283,27 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[],
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply transforms to the hierarchical document structure
|
// Apply transforms to the hierarchical document structure
|
||||||
|
|
||||||
INFO_START(transforms, "Applied transforms");
|
INFO_START(transforms, "Applied transforms");
|
||||||
report.apply_transforms(xml_document);
|
report.apply_transforms(doc_scope);
|
||||||
INFO_FINISH(transforms);
|
INFO_FINISH(transforms);
|
||||||
|
|
||||||
// Create an argument scope containing the report command's
|
// Create an argument scope containing the report command's
|
||||||
// arguments, and then invoke the command.
|
// arguments, and then invoke the command.
|
||||||
|
|
||||||
xml::xpath_t::scope_t locals(report, xml::xpath_t::scope_t::ARGUMENT);
|
xml::xpath_t::call_scope_t command_args(doc_scope);
|
||||||
|
|
||||||
locals.args.push_back(out);
|
for (strings_list::iterator i = arg; i != args.end(); i++)
|
||||||
locals.args.push_back(&xml_document);
|
command_args.push_back(value_t(*i, true));
|
||||||
|
|
||||||
value_t::sequence_t args_list;
|
|
||||||
foreach (string& i, args)
|
|
||||||
args_list.push_back(value_t(i, true));
|
|
||||||
locals.args.push_back(args_list);
|
|
||||||
|
|
||||||
INFO_START(command, "Did user command '" << verb << "'");
|
INFO_START(command, "Did user command '" << verb << "'");
|
||||||
|
|
||||||
command(locals);
|
command(command_args);
|
||||||
|
|
||||||
INFO_FINISH(command);
|
INFO_FINISH(command);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,15 @@ const char * node_t::name() const
|
||||||
return *document().lookup_name(name_id());
|
return *document().lookup_name(name_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<const string&> node_t::get_attr(const string& _name) const
|
||||||
|
{
|
||||||
|
optional<nameid_t> name_id = document().lookup_name_id(_name);
|
||||||
|
if (name_id)
|
||||||
|
return get_attr(*name_id);
|
||||||
|
else
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
void output_xml_string(std::ostream& out, const string& str)
|
void output_xml_string(std::ostream& out, const string& str)
|
||||||
{
|
{
|
||||||
for (const char * s = str.c_str(); *s; s++) {
|
for (const char * s = str.c_str(); *s; s++) {
|
||||||
|
|
|
||||||
|
|
@ -87,12 +87,12 @@ public:
|
||||||
parent_node_t& as_parent_node() {
|
parent_node_t& as_parent_node() {
|
||||||
if (! is_parent_node())
|
if (! is_parent_node())
|
||||||
throw_(std::logic_error, "Request to cast leaf node to a parent node");
|
throw_(std::logic_error, "Request to cast leaf node to a parent node");
|
||||||
return *polymorphic_downcast<parent_node_t *>(this);
|
return downcast<parent_node_t>(*this);
|
||||||
}
|
}
|
||||||
const parent_node_t& as_parent_node() const {
|
const parent_node_t& as_parent_node() const {
|
||||||
if (! is_parent_node())
|
if (! is_parent_node())
|
||||||
throw_(std::logic_error, "Request to cast leaf node to a parent node");
|
throw_(std::logic_error, "Request to cast leaf node to a parent node");
|
||||||
return *polymorphic_downcast<const parent_node_t *>(this);
|
return downcast<const parent_node_t>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual value_t to_value() const = 0;
|
virtual value_t to_value() const = 0;
|
||||||
|
|
@ -116,6 +116,7 @@ public:
|
||||||
attributes = attributes_t();
|
attributes = attributes_t();
|
||||||
attributes->push_back(attr_pair(_name_id, value));
|
attributes->push_back(attr_pair(_name_id, value));
|
||||||
}
|
}
|
||||||
|
optional<const string&> get_attr(const string& _name) const;
|
||||||
optional<const string&> get_attr(const nameid_t _name_id) const {
|
optional<const string&> get_attr(const nameid_t _name_id) const {
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
typedef attributes_t::nth_index<1>::type attributes_by_name;
|
typedef attributes_t::nth_index<1>::type attributes_by_name;
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,11 @@ namespace {
|
||||||
#if 0
|
#if 0
|
||||||
try {
|
try {
|
||||||
#endif
|
#endif
|
||||||
xml::xpath_t::scope_t arguments(scope, xml::xpath_t::scope_t::ARGUMENT);
|
xml::xpath_t::call_scope_t args(scope);
|
||||||
if (arg)
|
if (arg)
|
||||||
arguments.args.push_back(value_t(arg, true));
|
args.push_back(value_t(arg, true));
|
||||||
|
|
||||||
opt(arguments);
|
opt(args);
|
||||||
#if 0
|
#if 0
|
||||||
}
|
}
|
||||||
catch (error * err) {
|
catch (error * err) {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ struct python_run
|
||||||
};
|
};
|
||||||
|
|
||||||
python_interpreter_t::python_interpreter_t(xml::xpath_t::scope_t& parent)
|
python_interpreter_t::python_interpreter_t(xml::xpath_t::scope_t& parent)
|
||||||
: xml::xpath_t::scope_t(parent),
|
: xml::xpath_t::symbol_scope_t(parent),
|
||||||
mmodule(borrowed(PyImport_AddModule("__main__"))),
|
mmodule(borrowed(PyImport_AddModule("__main__"))),
|
||||||
nspace(handle<>(borrowed(PyModule_GetDict(mmodule.get()))))
|
nspace(handle<>(borrowed(PyModule_GetDict(mmodule.get()))))
|
||||||
{
|
{
|
||||||
|
|
@ -176,16 +176,20 @@ object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
|
||||||
return object();
|
return object();
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t python_interpreter_t::functor_t::operator()(xml::xpath_t::scope_t& locals)
|
value_t python_interpreter_t::functor_t::operator()
|
||||||
|
(xml::xpath_t::call_scope_t& args)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (! PyCallable_Check(func.ptr())) {
|
if (! PyCallable_Check(func.ptr())) {
|
||||||
return extract<value_t>(func.ptr());
|
return extract<value_t>(func.ptr());
|
||||||
} else {
|
} else {
|
||||||
if (locals.args.size() > 0) {
|
if (args.size() > 0) {
|
||||||
list arglist;
|
list arglist;
|
||||||
foreach (const value_t& value, locals.args)
|
if (args.value().is_sequence())
|
||||||
arglist.append(value);
|
foreach (const value_t& value, args.value().as_sequence())
|
||||||
|
arglist.append(value);
|
||||||
|
else
|
||||||
|
arglist.append(args.value());
|
||||||
|
|
||||||
if (PyObject * val =
|
if (PyObject * val =
|
||||||
PyObject_CallObject(func.ptr(),
|
PyObject_CallObject(func.ptr(),
|
||||||
|
|
@ -215,11 +219,11 @@ value_t python_interpreter_t::functor_t::operator()(xml::xpath_t::scope_t& local
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t python_interpreter_t::lambda_t::operator()
|
value_t python_interpreter_t::lambda_t::operator()
|
||||||
(xml::xpath_t::scope_t& locals)
|
(xml::xpath_t::call_scope_t& args)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
assert(locals.args.size() == 1);
|
assert(args.size() == 1);
|
||||||
value_t item = locals.args[0];
|
value_t item = args[0];
|
||||||
assert(item.is_xml_node());
|
assert(item.is_xml_node());
|
||||||
return call<value_t>(func.ptr(), item.as_xml_node());
|
return call<value_t>(func.ptr(), item.as_xml_node());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PY_EVAL_H
|
#ifndef _PYINTERP_H
|
||||||
#define _PY_EVAL_H
|
#define _PYINTERP_H
|
||||||
|
|
||||||
#include "xpath.h"
|
#include "xpath.h"
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
class python_interpreter_t : public xml::xpath_t::scope_t
|
class python_interpreter_t : public xml::xpath_t::symbol_scope_t
|
||||||
{
|
{
|
||||||
boost::python::handle<> mmodule;
|
boost::python::handle<> mmodule;
|
||||||
|
|
||||||
|
|
@ -76,28 +76,23 @@ class python_interpreter_t : public xml::xpath_t::scope_t
|
||||||
public:
|
public:
|
||||||
functor_t(const string& name, boost::python::object _func) : func(_func) {}
|
functor_t(const string& name, boost::python::object _func) : func(_func) {}
|
||||||
virtual ~functor_t() {}
|
virtual ~functor_t() {}
|
||||||
virtual value_t operator()(xml::xpath_t::scope_t& locals);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
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::ptr_op_t lookup(const string& name) {
|
virtual xml::xpath_t::ptr_op_t lookup(const string& name) {
|
||||||
if (boost::python::object func = eval(name))
|
if (boost::python::object func = eval(name))
|
||||||
return xml::xpath_t::wrap_functor(functor_t(name, func));
|
return WRAP_FUNCTOR(functor_t(name, func));
|
||||||
else
|
else
|
||||||
return parent ? parent->lookup(name) : NULL;
|
return xml::xpath_t::symbol_scope_t::lookup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
class lambda_t : public functor_t {
|
class lambda_t : public functor_t {
|
||||||
public:
|
public:
|
||||||
lambda_t(boost::python::object code) : functor_t("<lambda>", code) {}
|
lambda_t(boost::python::object code) : functor_t("<lambda>", code) {}
|
||||||
virtual value_t operator()(xml::xpath_t::scope_t& locals);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _PY_EVAL_H
|
#endif // _PYINTERP_H
|
||||||
|
|
|
||||||
|
|
@ -38,41 +38,46 @@ report_t::~report_t()
|
||||||
TRACE_DTOR(report_t);
|
TRACE_DTOR(report_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void report_t::apply_transforms(xml::document_t& document)
|
void report_t::apply_transforms(xml::xpath_t::scope_t& scope)
|
||||||
{
|
{
|
||||||
foreach (transform_t& transform, transforms)
|
typedef tuple<shared_ptr<transform_t>, value_t> transform_details_tuple;
|
||||||
transform.execute(document);
|
|
||||||
|
foreach (transform_details_tuple& transform_details, transforms) {
|
||||||
|
xml::xpath_t::call_scope_t call_args(scope);
|
||||||
|
call_args.set_args(transform_details.get<1>());
|
||||||
|
(*transform_details.get<0>())(call_args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t report_t::abbrev(xml::xpath_t::scope_t& locals)
|
value_t report_t::abbrev(xml::xpath_t::call_scope_t& args)
|
||||||
{
|
{
|
||||||
if (locals.args.size() < 2)
|
if (args.size() < 2)
|
||||||
throw_(std::logic_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
|
throw_(std::logic_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
|
||||||
|
|
||||||
string str = locals.args[0].as_string();
|
string str = args[0].as_string();
|
||||||
long wid = locals.args[1];
|
long wid = args[1];
|
||||||
|
|
||||||
elision_style_t style = session.elision_style;
|
elision_style_t style = session.elision_style;
|
||||||
if (locals.args.size() == 3)
|
if (args.size() == 3)
|
||||||
style = (elision_style_t)locals.args[2].as_long();
|
style = (elision_style_t)args[2].as_long();
|
||||||
|
|
||||||
long abbrev_len = session.abbrev_length;
|
long abbrev_len = session.abbrev_length;
|
||||||
if (locals.args.size() == 4)
|
if (args.size() == 4)
|
||||||
abbrev_len = locals.args[3].as_long();
|
abbrev_len = args[3].as_long();
|
||||||
|
|
||||||
return value_t(abbreviate(str, wid, style, true, (int)abbrev_len), true);
|
return value_t(abbreviate(str, wid, style, true, (int)abbrev_len), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t report_t::ftime(xml::xpath_t::scope_t& locals)
|
value_t report_t::ftime(xml::xpath_t::call_scope_t& args)
|
||||||
{
|
{
|
||||||
if (locals.args.size() < 1)
|
if (args.size() < 1)
|
||||||
throw_(std::logic_error, "usage: ftime(DATE [, DATE_FORMAT])");
|
throw_(std::logic_error, "usage: ftime(DATE [, DATE_FORMAT])");
|
||||||
|
|
||||||
moment_t date = locals.args[0].as_datetime();
|
moment_t date = args[0].as_datetime();
|
||||||
|
|
||||||
string date_format;
|
string date_format;
|
||||||
if (locals.args.size() == 2)
|
if (args.size() == 2)
|
||||||
date_format = locals.args[1].as_string();
|
date_format = args[1].as_string();
|
||||||
#if 0
|
#if 0
|
||||||
// jww (2007-04-18): Need to setup an output facet here
|
// jww (2007-04-18): Need to setup an output facet here
|
||||||
else
|
else
|
||||||
|
|
@ -84,25 +89,27 @@ value_t report_t::ftime(xml::xpath_t::scope_t& locals)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
optional<value_t>
|
optional<value_t>
|
||||||
report_t::resolve(const string& name, xml::xpath_t::scope_t& locals)
|
report_t::resolve(const string& name, xml::xpath_t::call_scope_t& args)
|
||||||
{
|
{
|
||||||
const char * p = name.c_str();
|
const char * p = name.c_str();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (name == "abbrev") {
|
if (name == "abbrev") {
|
||||||
return abbrev(locals);
|
return abbrev(args);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if (name == "ftime") {
|
if (name == "ftime") {
|
||||||
return ftime(locals);
|
return ftime(args);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return xml::xpath_t::scope_t::resolve(name, locals);
|
return xml::xpath_t::scope_t::resolve(name, args);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
xml::xpath_t::ptr_op_t report_t::lookup(const string& name)
|
xml::xpath_t::ptr_op_t report_t::lookup(const string& name)
|
||||||
{
|
{
|
||||||
|
|
@ -210,7 +217,7 @@ xml::xpath_t::ptr_op_t report_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xml::xpath_t::scope_t::lookup(name);
|
return xml::xpath_t::symbol_scope_t::lookup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
64
src/report.h
64
src/report.h
|
|
@ -39,9 +39,9 @@ namespace ledger {
|
||||||
|
|
||||||
typedef std::list<string> strings_list;
|
typedef std::list<string> strings_list;
|
||||||
|
|
||||||
class report_t : public xml::xpath_t::scope_t
|
class report_t : public xml::xpath_t::symbol_scope_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
optional<path> output_file;
|
optional<path> output_file;
|
||||||
string format_string;
|
string format_string;
|
||||||
string amount_expr;
|
string amount_expr;
|
||||||
|
|
@ -59,10 +59,10 @@ class report_t : public xml::xpath_t::scope_t
|
||||||
session_t& session;
|
session_t& session;
|
||||||
transform_t * last_transform;
|
transform_t * last_transform;
|
||||||
|
|
||||||
ptr_list<transform_t> transforms;
|
std::list<tuple<shared_ptr<transform_t>, value_t> > transforms;
|
||||||
|
|
||||||
explicit report_t(session_t& _session)
|
explicit report_t(session_t& _session)
|
||||||
: xml::xpath_t::scope_t(_session),
|
: xml::xpath_t::symbol_scope_t(downcast<xml::xpath_t::scope_t>(_session)),
|
||||||
show_totals(false),
|
show_totals(false),
|
||||||
raw_mode(false),
|
raw_mode(false),
|
||||||
session(_session),
|
session(_session),
|
||||||
|
|
@ -76,14 +76,14 @@ class report_t : public xml::xpath_t::scope_t
|
||||||
|
|
||||||
virtual ~report_t();
|
virtual ~report_t();
|
||||||
|
|
||||||
void apply_transforms(xml::document_t& document);
|
void apply_transforms(xml::xpath_t::scope_t& scope);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Utility functions for value expressions
|
// Utility functions for value expressions
|
||||||
//
|
//
|
||||||
|
|
||||||
value_t ftime(xml::xpath_t::scope_t& locals);
|
value_t ftime(xml::xpath_t::call_scope_t& args);
|
||||||
value_t abbrev(xml::xpath_t::scope_t& locals);
|
value_t abbrev(xml::xpath_t::call_scope_t& args);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Config options
|
// Config options
|
||||||
|
|
@ -94,36 +94,36 @@ class report_t : public xml::xpath_t::scope_t
|
||||||
xml::xpath_t(expr).compile((xml::document_t *)NULL, this);
|
xml::xpath_t(expr).compile((xml::document_t *)NULL, this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
value_t option_eval(xml::xpath_t::scope_t& locals) {
|
value_t option_eval(xml::xpath_t::call_scope_t& args) {
|
||||||
eval(locals.args[0].as_string());
|
eval(args[0].as_string());
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_amount(xml::xpath_t::scope_t& locals) {
|
value_t option_amount(xml::xpath_t::call_scope_t& args) {
|
||||||
eval(string("t=") + locals.args[0].as_string());
|
eval(string("t=") + args[0].as_string());
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_total(xml::xpath_t::scope_t& locals) {
|
value_t option_total(xml::xpath_t::call_scope_t& args) {
|
||||||
eval(string("T()=") + locals.args[0].as_string());
|
eval(string("T()=") + args[0].as_string());
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_format(xml::xpath_t::scope_t& locals) {
|
value_t option_format(xml::xpath_t::call_scope_t& args) {
|
||||||
format_string = locals.args[0].as_string();
|
format_string = args[0].as_string();
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_raw(xml::xpath_t::scope_t& locals) {
|
value_t option_raw(xml::xpath_t::call_scope_t& args) {
|
||||||
raw_mode = true;
|
raw_mode = true;
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_foo(xml::xpath_t::scope_t& locals) {
|
value_t option_foo(xml::xpath_t::call_scope_t& args) {
|
||||||
std::cout << "This is foo" << std::endl;
|
std::cout << "This is foo" << std::endl;
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_bar(xml::xpath_t::scope_t& locals) {
|
value_t option_bar(xml::xpath_t::call_scope_t& args) {
|
||||||
std::cout << "This is bar: " << locals.args[0] << std::endl;
|
std::cout << "This is bar: " << args[0] << std::endl;
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,44 +132,44 @@ class report_t : public xml::xpath_t::scope_t
|
||||||
//
|
//
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
value_t option_select(xml::xpath_t::scope_t& locals) {
|
value_t option_select(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new select_transform(locals.args[0].as_string()));
|
transforms.push_back(new select_transform(args[0].as_string()));
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_limit(xml::xpath_t::scope_t& locals) {
|
value_t option_limit(xml::xpath_t::call_scope_t& args) {
|
||||||
string expr = (string("//xact[") +
|
string expr = (string("//xact[") +
|
||||||
locals.args[0].as_string() + "]");
|
args[0].as_string() + "]");
|
||||||
transforms.push_back(new select_transform(expr));
|
transforms.push_back(new select_transform(expr));
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_remove(xml::xpath_t::scope_t& locals) {
|
value_t option_remove(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new remove_transform(locals.args[0].as_string()));
|
transforms.push_back(new remove_transform(args[0].as_string()));
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_accounts(xml::xpath_t::scope_t& locals) {
|
value_t option_accounts(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new accounts_transform);
|
transforms.push_back(new accounts_transform);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_compact(xml::xpath_t::scope_t& locals) {
|
value_t option_compact(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new compact_transform);
|
transforms.push_back(new compact_transform);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_clean(xml::xpath_t::scope_t& locals) {
|
value_t option_clean(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new clean_transform);
|
transforms.push_back(new clean_transform);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_entries(xml::xpath_t::scope_t& locals) {
|
value_t option_entries(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new entries_transform);
|
transforms.push_back(new entries_transform);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t option_split(xml::xpath_t::scope_t& locals) {
|
value_t option_split(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new split_transform);
|
transforms.push_back(new split_transform);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_merge(xml::xpath_t::scope_t& locals) {
|
value_t option_merge(xml::xpath_t::call_scope_t& args) {
|
||||||
transforms.push_back(new merge_transform);
|
transforms.push_back(new merge_transform);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
@ -179,8 +179,6 @@ class report_t : public xml::xpath_t::scope_t
|
||||||
// Scope members
|
// Scope members
|
||||||
//
|
//
|
||||||
|
|
||||||
virtual optional<value_t> resolve(const string& name,
|
|
||||||
xml::xpath_t::scope_t& locals);
|
|
||||||
virtual xml::xpath_t::ptr_op_t lookup(const string& name);
|
virtual xml::xpath_t::ptr_op_t lookup(const string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,56 @@ void release_session_context()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session_t::session_t()
|
||||||
|
: symbol_scope_t(),
|
||||||
|
|
||||||
|
register_format
|
||||||
|
("%((//entry)%{date} %-.20{payee}"
|
||||||
|
"%((./xact)%32|%-22{abbrev(account, 22)} %12.67t %12.80T\n))"),
|
||||||
|
wide_register_format
|
||||||
|
("%D %-.35P %-.38A %22.108t %!22.132T\n%/"
|
||||||
|
"%48|%-.38A %22.108t %!22.132T\n"),
|
||||||
|
print_format
|
||||||
|
#if 1
|
||||||
|
("%(/%(/%{date} %-.20{payee}\n%(: %-34{account} %12t\n)\n))"),
|
||||||
|
#else
|
||||||
|
("\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n"),
|
||||||
|
#endif
|
||||||
|
balance_format
|
||||||
|
("%(/%(//%20t %{\" \" * rdepth}%{rname}\n))--------------------\n%20t\n"),
|
||||||
|
equity_format
|
||||||
|
|
||||||
|
("%((/)%{ftime(now, date_format)} %-.20{\"Opening Balance\"}\n%((.//account[value != 0]) %-34{fullname} %12{value}\n)\n)"),
|
||||||
|
plot_amount_format
|
||||||
|
("%D %(@S(@t))\n"),
|
||||||
|
plot_total_format
|
||||||
|
("%D %(@S(@T))\n"),
|
||||||
|
write_hdr_format
|
||||||
|
("%d %Y%C%P\n"),
|
||||||
|
write_xact_format
|
||||||
|
(" %-34W %12o%n\n"),
|
||||||
|
prices_format
|
||||||
|
("%[%Y/%m/%d %H:%M:%S %Z] %-10A %12t %12T\n"),
|
||||||
|
pricesdb_format
|
||||||
|
("P %[%Y/%m/%d %H:%M:%S] %A %t\n"),
|
||||||
|
|
||||||
|
pricing_leeway(24 * 3600),
|
||||||
|
|
||||||
|
download_quotes(false),
|
||||||
|
use_cache(false),
|
||||||
|
cache_dirty(false),
|
||||||
|
|
||||||
|
now(now),
|
||||||
|
|
||||||
|
elision_style(ABBREVIATE),
|
||||||
|
abbrev_length(2),
|
||||||
|
|
||||||
|
ansi_codes(false),
|
||||||
|
ansi_invert(false)
|
||||||
|
{
|
||||||
|
TRACE_CTOR(session_t, "xml::xpath_t::scope_t&");
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t session_t::read_journal(std::istream& in,
|
std::size_t session_t::read_journal(std::istream& in,
|
||||||
const path& pathname,
|
const path& pathname,
|
||||||
xml::builder_t& builder)
|
xml::builder_t& builder)
|
||||||
|
|
@ -173,6 +223,7 @@ std::size_t session_t::read_data(xml::builder_t& builder,
|
||||||
return entry_count;
|
return entry_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
optional<value_t>
|
optional<value_t>
|
||||||
session_t::resolve(const string& name, xml::xpath_t::scope_t& locals)
|
session_t::resolve(const string& name, xml::xpath_t::scope_t& locals)
|
||||||
{
|
{
|
||||||
|
|
@ -203,6 +254,7 @@ session_t::resolve(const string& name, xml::xpath_t::scope_t& locals)
|
||||||
}
|
}
|
||||||
return xml::xpath_t::scope_t::resolve(name, locals);
|
return xml::xpath_t::scope_t::resolve(name, locals);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
|
xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
|
||||||
{
|
{
|
||||||
|
|
@ -239,7 +291,7 @@ xml::xpath_t::ptr_op_t session_t::lookup(const string& name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xml::xpath_t::scope_t::lookup(name);
|
return xml::xpath_t::symbol_scope_t::lookup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// jww (2007-04-26): All of Ledger should be accessed through a
|
// jww (2007-04-26): All of Ledger should be accessed through a
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
class session_t : public xml::xpath_t::scope_t
|
class session_t : public xml::xpath_t::symbol_scope_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static session_t * current;
|
static session_t * current;
|
||||||
|
|
@ -79,53 +79,7 @@ class session_t : public xml::xpath_t::scope_t
|
||||||
ptr_list<journal_t> journals;
|
ptr_list<journal_t> journals;
|
||||||
ptr_list<parser_t> parsers;
|
ptr_list<parser_t> parsers;
|
||||||
|
|
||||||
session_t() :
|
session_t();
|
||||||
register_format
|
|
||||||
("%((//entry)%{date} %-.20{payee}"
|
|
||||||
"%((./xact)%32|%-22{abbrev(account, 22)} %12.67t %12.80T\n))"),
|
|
||||||
wide_register_format
|
|
||||||
("%D %-.35P %-.38A %22.108t %!22.132T\n%/"
|
|
||||||
"%48|%-.38A %22.108t %!22.132T\n"),
|
|
||||||
print_format
|
|
||||||
#if 1
|
|
||||||
("%(/%(/%{date} %-.20{payee}\n%(: %-34{account} %12t\n)\n))"),
|
|
||||||
#else
|
|
||||||
("\n%d %Y%C%P\n %-34W %12o%n\n%/ %-34W %12o%n\n"),
|
|
||||||
#endif
|
|
||||||
balance_format
|
|
||||||
("%(/%(//%20t %{\" \" * rdepth}%{rname}\n))--------------------\n%20t\n"),
|
|
||||||
equity_format
|
|
||||||
|
|
||||||
("%((/)%{ftime(now, date_format)} %-.20{\"Opening Balance\"}\n%((.//account[value != 0]) %-34{fullname} %12{value}\n)\n)"),
|
|
||||||
plot_amount_format
|
|
||||||
("%D %(@S(@t))\n"),
|
|
||||||
plot_total_format
|
|
||||||
("%D %(@S(@T))\n"),
|
|
||||||
write_hdr_format
|
|
||||||
("%d %Y%C%P\n"),
|
|
||||||
write_xact_format
|
|
||||||
(" %-34W %12o%n\n"),
|
|
||||||
prices_format
|
|
||||||
("%[%Y/%m/%d %H:%M:%S %Z] %-10A %12t %12T\n"),
|
|
||||||
pricesdb_format
|
|
||||||
("P %[%Y/%m/%d %H:%M:%S] %A %t\n"),
|
|
||||||
|
|
||||||
pricing_leeway(24 * 3600),
|
|
||||||
|
|
||||||
download_quotes(false),
|
|
||||||
use_cache(false),
|
|
||||||
cache_dirty(false),
|
|
||||||
|
|
||||||
now(now),
|
|
||||||
|
|
||||||
elision_style(ABBREVIATE),
|
|
||||||
abbrev_length(2),
|
|
||||||
|
|
||||||
ansi_codes(false),
|
|
||||||
ansi_invert(false) {
|
|
||||||
TRACE_CTOR(session_t, "xml::xpath_t::scope_t&");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~session_t() {
|
virtual ~session_t() {
|
||||||
TRACE_DTOR(session_t);
|
TRACE_DTOR(session_t);
|
||||||
}
|
}
|
||||||
|
|
@ -178,8 +132,6 @@ class session_t : public xml::xpath_t::scope_t
|
||||||
// Scope members
|
// Scope members
|
||||||
//
|
//
|
||||||
|
|
||||||
virtual optional<value_t> resolve(const string& name,
|
|
||||||
xml::xpath_t::scope_t& locals = NULL);
|
|
||||||
virtual xml::xpath_t::ptr_op_t lookup(const string& name);
|
virtual xml::xpath_t::ptr_op_t lookup(const string& name);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -208,19 +160,19 @@ class session_t : public xml::xpath_t::scope_t
|
||||||
// Option handlers
|
// Option handlers
|
||||||
//
|
//
|
||||||
|
|
||||||
value_t option_file_(xml::xpath_t::scope_t& locals) {
|
value_t option_file_(xml::xpath_t::call_scope_t& args) {
|
||||||
assert(locals.args.size() == 1);
|
assert(args.size() == 1);
|
||||||
data_file = locals.args[0].as_string();
|
data_file = args[0].as_string();
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#if defined(USE_BOOST_PYTHON)
|
#if defined(USE_BOOST_PYTHON)
|
||||||
value_t option_import_(xml::xpath_t::scope_t& locals) {
|
value_t option_import_(xml::xpath_t::call_scope_t& args) {
|
||||||
python_import(optarg);
|
python_import(optarg);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
value_t option_import_stdin(xml::xpath_t::scope_t& locals) {
|
value_t option_import_stdin(xml::xpath_t::call_scope_t& args) {
|
||||||
python_eval(std::cin, PY_EVAL_MULTI);
|
python_eval(std::cin, PY_EVAL_MULTI);
|
||||||
return NULL_VALUE;
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,38 +39,38 @@ namespace ledger {
|
||||||
class transform_t {
|
class transform_t {
|
||||||
public:
|
public:
|
||||||
virtual ~transform_t() {}
|
virtual ~transform_t() {}
|
||||||
virtual void execute(xml::document_t& document) = 0;
|
virtual value_t operator()(xml::xpath_t::scope_t& args) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class check_transform : public transform_t {
|
class check_transform : public transform_t {
|
||||||
// --check checks the validity of the item list.
|
// --check checks the validity of the item list.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class accounts_transform : public transform_t {
|
class accounts_transform : public transform_t {
|
||||||
// --accounts transforms the report tree into an account-wise view.
|
// --accounts transforms the report tree into an account-wise view.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class compact_transform : public transform_t {
|
class compact_transform : public transform_t {
|
||||||
// --compact compacts an account tree to remove accounts with only
|
// --compact compacts an account tree to remove accounts with only
|
||||||
// one child account.
|
// one child account.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class clean_transform : public transform_t {
|
class clean_transform : public transform_t {
|
||||||
// --clean clears out entries and accounts that have no contents.
|
// --clean clears out entries and accounts that have no contents.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class entries_transform : public transform_t {
|
class entries_transform : public transform_t {
|
||||||
// --entries transforms the report tree into an entries-wise view.
|
// --entries transforms the report tree into an entries-wise view.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class optimize_transform : public transform_t {
|
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
|
// commodity (one the negative of the other), the amount of the
|
||||||
// second transaction will be nulled out.
|
// second transaction will be nulled out.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class split_transform : public transform_t {
|
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
|
// useful before sorting, for exampel, in order to sort by
|
||||||
// transaction instead of by entry.
|
// transaction instead of by entry.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class merge_transform : public transform_t {
|
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
|
// which share the same entry will be merged into a group of
|
||||||
// transactions under one reported entry.
|
// transactions under one reported entry.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class combine_transform : public transform_t {
|
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
|
// will show the terminating date or a label that is characteristic
|
||||||
// of the set).
|
// of the set).
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class group_transform : public transform_t {
|
class group_transform : public transform_t {
|
||||||
// --group groups all transactions that affect the same account
|
// --group groups all transactions that affect the same account
|
||||||
// within an entry, so that they appear as a single transaction.
|
// within an entry, so that they appear as a single transaction.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class collapse_transform : public transform_t {
|
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,
|
// fictitous account "<total>" is used to represent the final sum,
|
||||||
// if multiple accounts are involved.
|
// if multiple accounts are involved.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class subtotal_transform : public transform_t {
|
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
|
// one giant entry. When used in conjunction with --group, the
|
||||||
// affect is very similar to a regular balance report.
|
// affect is very similar to a regular balance report.
|
||||||
public:
|
public:
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -146,7 +146,7 @@ class select_transform : public transform_t
|
||||||
}
|
}
|
||||||
virtual ~select_transform() {}
|
virtual ~select_transform() {}
|
||||||
|
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
class remove_transform : public select_transform
|
class remove_transform : public select_transform
|
||||||
|
|
@ -155,7 +155,7 @@ class remove_transform : public select_transform
|
||||||
remove_transform(const string& selection_path)
|
remove_transform(const string& selection_path)
|
||||||
: select_transform(selection_path) {}
|
: select_transform(selection_path) {}
|
||||||
|
|
||||||
virtual void execute(xml::document_t& document);
|
virtual value_t operator()(xml::xpath_t::call_scope_t& args);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -521,6 +521,11 @@ inline void throw_unexpected_error(char, char) {
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
inline T& downcast(U& object) {
|
||||||
|
return *polymorphic_downcast<T *>(&object);
|
||||||
|
}
|
||||||
|
|
||||||
path resolve_path(const path& pathname);
|
path resolve_path(const path& pathname);
|
||||||
|
|
||||||
#ifdef HAVE_REALPATH
|
#ifdef HAVE_REALPATH
|
||||||
|
|
|
||||||
134
src/value.h
134
src/value.h
|
|
@ -61,6 +61,10 @@ class value_t
|
||||||
public:
|
public:
|
||||||
typedef std::vector<value_t> sequence_t;
|
typedef std::vector<value_t> sequence_t;
|
||||||
|
|
||||||
|
typedef sequence_t::iterator iterator;
|
||||||
|
typedef sequence_t::const_iterator const_iterator;
|
||||||
|
typedef sequence_t::difference_type difference_type;
|
||||||
|
|
||||||
enum type_t {
|
enum type_t {
|
||||||
VOID,
|
VOID,
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
|
|
@ -72,7 +76,6 @@ public:
|
||||||
STRING,
|
STRING,
|
||||||
SEQUENCE,
|
SEQUENCE,
|
||||||
XML_NODE,
|
XML_NODE,
|
||||||
CONST_XML_NODE,
|
|
||||||
POINTER
|
POINTER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -217,12 +220,9 @@ public:
|
||||||
TRACE_CTOR(value_t, "xml::node_t *");
|
TRACE_CTOR(value_t, "xml::node_t *");
|
||||||
set_xml_node(xml_node);
|
set_xml_node(xml_node);
|
||||||
}
|
}
|
||||||
value_t(const xml::node_t * xml_node) {
|
template <typename T>
|
||||||
TRACE_CTOR(value_t, "const xml::node_t *");
|
value_t(T * item) {
|
||||||
set_xml_node(xml_node);
|
TRACE_CTOR(value_t, "T *");
|
||||||
}
|
|
||||||
value_t(void * item) {
|
|
||||||
TRACE_CTOR(value_t, "void *");
|
|
||||||
set_pointer(item);
|
set_pointer(item);
|
||||||
}
|
}
|
||||||
~value_t() {
|
~value_t() {
|
||||||
|
|
@ -254,11 +254,22 @@ public:
|
||||||
else
|
else
|
||||||
storage->destroy();
|
storage->destroy();
|
||||||
}
|
}
|
||||||
|
void _reset() {
|
||||||
|
if (storage) {
|
||||||
|
storage->destroy();
|
||||||
|
storage = intrusive_ptr<storage_t>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
bool is_null() const {
|
bool is_null() const {
|
||||||
return ! storage || is_type(VOID);
|
if (! storage) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
assert(! is_type(VOID));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
type_t type() const {
|
type_t type() const {
|
||||||
type_t result = storage ? storage->type : VOID;
|
type_t result = storage ? storage->type : VOID;
|
||||||
|
|
@ -272,9 +283,14 @@ private:
|
||||||
}
|
}
|
||||||
void set_type(type_t new_type) {
|
void set_type(type_t new_type) {
|
||||||
assert(new_type >= VOID && new_type <= POINTER);
|
assert(new_type >= VOID && new_type <= POINTER);
|
||||||
_clear();
|
if (new_type == VOID) {
|
||||||
storage->type = new_type;
|
_reset();
|
||||||
assert(is_type(new_type));
|
assert(is_null());
|
||||||
|
} else {
|
||||||
|
_clear();
|
||||||
|
storage->type = new_type;
|
||||||
|
assert(is_type(new_type));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -415,36 +431,21 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_xml_node() const {
|
bool is_xml_node() const {
|
||||||
return is_type(XML_NODE) || is_type(CONST_XML_NODE);
|
return is_type(XML_NODE);
|
||||||
}
|
}
|
||||||
xml::node_t *& as_xml_node_lval() {
|
xml::node_t *& as_xml_node_lval() {
|
||||||
assert(is_xml_node());
|
assert(is_xml_node());
|
||||||
assert(! is_type(CONST_XML_NODE));
|
|
||||||
_dup();
|
_dup();
|
||||||
return *(xml::node_t **) storage->data;
|
return *(xml::node_t **) storage->data;
|
||||||
}
|
}
|
||||||
xml::node_t * as_xml_node_mutable() {
|
xml::node_t * as_xml_node() const {
|
||||||
assert(is_xml_node());
|
assert(is_xml_node());
|
||||||
assert(! is_type(CONST_XML_NODE));
|
|
||||||
return *(xml::node_t **) storage->data;
|
return *(xml::node_t **) storage->data;
|
||||||
}
|
}
|
||||||
const xml::node_t * as_xml_node() const {
|
|
||||||
assert(is_xml_node());
|
|
||||||
return *(const xml::node_t **) storage->data;
|
|
||||||
}
|
|
||||||
template <typename T>
|
|
||||||
T * as_xml_node() const {
|
|
||||||
assert(is_xml_node());
|
|
||||||
return *(T **) storage->data;
|
|
||||||
}
|
|
||||||
void set_xml_node(xml::node_t * val) {
|
void set_xml_node(xml::node_t * val) {
|
||||||
set_type(XML_NODE);
|
set_type(XML_NODE);
|
||||||
*(xml::node_t **) storage->data = val;
|
*(xml::node_t **) storage->data = val;
|
||||||
}
|
}
|
||||||
void set_xml_node(const xml::node_t * val) {
|
|
||||||
set_type(CONST_XML_NODE);
|
|
||||||
*(const xml::node_t **) storage->data = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_pointer() const {
|
bool is_pointer() const {
|
||||||
return is_type(POINTER);
|
return is_type(POINTER);
|
||||||
|
|
@ -460,6 +461,12 @@ public:
|
||||||
_dup();
|
_dup();
|
||||||
return any_cast<T *>(*(boost::any *) storage->data);
|
return any_cast<T *>(*(boost::any *) storage->data);
|
||||||
}
|
}
|
||||||
|
template <typename T>
|
||||||
|
T& as_ref_lval() {
|
||||||
|
assert(is_pointer());
|
||||||
|
_dup();
|
||||||
|
return *any_cast<T *>(*(boost::any *) storage->data);
|
||||||
|
}
|
||||||
boost::any as_any_pointer() const {
|
boost::any as_any_pointer() const {
|
||||||
assert(is_pointer());
|
assert(is_pointer());
|
||||||
return *(boost::any *) storage->data;
|
return *(boost::any *) storage->data;
|
||||||
|
|
@ -469,6 +476,11 @@ public:
|
||||||
assert(is_pointer());
|
assert(is_pointer());
|
||||||
return any_cast<T *>(*(boost::any *) storage->data);
|
return any_cast<T *>(*(boost::any *) storage->data);
|
||||||
}
|
}
|
||||||
|
template <typename T>
|
||||||
|
T& as_ref() const {
|
||||||
|
assert(is_pointer());
|
||||||
|
return *any_cast<T *>(*(boost::any *) storage->data);
|
||||||
|
}
|
||||||
void set_any_pointer(const boost::any& val) {
|
void set_any_pointer(const boost::any& val) {
|
||||||
set_type(POINTER);
|
set_type(POINTER);
|
||||||
new((boost::any *) storage->data) boost::any(val);
|
new((boost::any *) storage->data) boost::any(val);
|
||||||
|
|
@ -496,18 +508,66 @@ public:
|
||||||
void in_place_simplify();
|
void in_place_simplify();
|
||||||
|
|
||||||
value_t& operator[](const int index) {
|
value_t& operator[](const int index) {
|
||||||
return as_sequence_lval()[index];
|
assert(! is_null());
|
||||||
|
if (is_sequence())
|
||||||
|
return as_sequence_lval()[index];
|
||||||
|
else if (index == 0)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
static value_t null;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
const value_t& operator[](const int index) const {
|
const value_t& operator[](const int index) const {
|
||||||
return as_sequence()[index];
|
assert(! is_null());
|
||||||
|
if (is_sequence())
|
||||||
|
return as_sequence()[index];
|
||||||
|
else if (index == 0)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
static value_t null;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_back(const value_t& val) {
|
void push_back(const value_t& val) {
|
||||||
return as_sequence_lval().push_back(val);
|
if (is_null()) {
|
||||||
|
*this = val;
|
||||||
|
} else {
|
||||||
|
if (! is_sequence())
|
||||||
|
in_place_cast(SEQUENCE);
|
||||||
|
|
||||||
|
if (! val.is_sequence())
|
||||||
|
as_sequence_lval().push_back(val);
|
||||||
|
else
|
||||||
|
std::copy(val.as_sequence().begin(), val.as_sequence().end(),
|
||||||
|
as_sequence_lval().end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back() {
|
||||||
|
assert(! is_null());
|
||||||
|
|
||||||
|
if (! is_sequence()) {
|
||||||
|
_reset();
|
||||||
|
} else {
|
||||||
|
as_sequence_lval().pop_back();
|
||||||
|
|
||||||
|
std::size_t new_size = as_sequence().size();
|
||||||
|
if (new_size == 0)
|
||||||
|
_reset();
|
||||||
|
else if (new_size == 1)
|
||||||
|
*this = as_sequence().front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t size() const {
|
const std::size_t size() const {
|
||||||
return as_sequence().size();
|
if (is_null())
|
||||||
|
return 0;
|
||||||
|
else if (is_sequence())
|
||||||
|
return as_sequence().size();
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t& operator+=(const value_t& val);
|
value_t& operator+=(const value_t& val);
|
||||||
|
|
@ -542,7 +602,6 @@ public:
|
||||||
case SEQUENCE:
|
case SEQUENCE:
|
||||||
return "a sequence";
|
return "a sequence";
|
||||||
case XML_NODE:
|
case XML_NODE:
|
||||||
case CONST_XML_NODE:
|
|
||||||
return "an xml node";
|
return "an xml node";
|
||||||
case POINTER:
|
case POINTER:
|
||||||
return "a pointer";
|
return "a pointer";
|
||||||
|
|
@ -602,19 +661,12 @@ public:
|
||||||
friend std::ostream& operator<<(std::ostream& out, const value_t& val);
|
friend std::ostream& operator<<(std::ostream& out, const value_t& val);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
#define NULL_VALUE (value_t())
|
||||||
inline const xml::node_t * value_t::as_xml_node() const {
|
|
||||||
assert(is_xml_node());
|
|
||||||
assert(! is_type(CONST_XML_NODE));
|
|
||||||
return *(const xml::node_t **) storage->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const value_t& val);
|
std::ostream& operator<<(std::ostream& out, const value_t& val);
|
||||||
|
|
||||||
DECLARE_EXCEPTION(value_error);
|
DECLARE_EXCEPTION(value_error);
|
||||||
|
|
||||||
#define NULL_VALUE (value_t())
|
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
#endif // _VALUE_H
|
#endif // _VALUE_H
|
||||||
|
|
|
||||||
1218
src/xpath.cc
1218
src/xpath.cc
File diff suppressed because it is too large
Load diff
657
src/xpath.h
657
src/xpath.h
|
|
@ -51,77 +51,259 @@ public:
|
||||||
DECLARE_EXCEPTION(calc_error);
|
DECLARE_EXCEPTION(calc_error);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class scope_t;
|
class call_scope_t;
|
||||||
|
|
||||||
typedef function<value_t (scope_t&)> function_t;
|
typedef function<value_t (call_scope_t&)> function_t;
|
||||||
|
|
||||||
#define MAKE_FUNCTOR(x) \
|
#define MAKE_FUNCTOR(x) \
|
||||||
xml::xpath_t::wrap_functor(bind(&x, this, _1))
|
xml::xpath_t::op_t::wrap_functor(bind(&x, this, _1))
|
||||||
|
#define WRAP_FUNCTOR(x) \
|
||||||
static ptr_op_t wrap_value(const value_t& val);
|
xml::xpath_t::op_t::wrap_functor(x)
|
||||||
static ptr_op_t wrap_functor(const function_t& fobj);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class scope_t : public noncopyable
|
class scope_t : public noncopyable
|
||||||
{
|
{
|
||||||
typedef std::map<const string, ptr_op_t> symbol_map;
|
|
||||||
symbol_map symbols;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
optional<scope_t&> parent;
|
enum type_t {
|
||||||
value_t::sequence_t args;
|
CHILD_SCOPE,
|
||||||
|
SYMBOL_SCOPE,
|
||||||
|
CALL_SCOPE,
|
||||||
|
CONTEXT_SCOPE,
|
||||||
|
NODE_SCOPE,
|
||||||
|
PREDICATE_SCOPE
|
||||||
|
} type_;
|
||||||
|
|
||||||
enum kind_t { NORMAL, STATIC, ARGUMENT } kind;
|
explicit scope_t(type_t _type) : type_(_type) {
|
||||||
|
TRACE_CTOR(xpath_t::scope_t, "type_t");
|
||||||
explicit scope_t(const optional<scope_t&>& _parent = none,
|
|
||||||
kind_t _kind = NORMAL)
|
|
||||||
: parent(_parent), kind(_kind) {
|
|
||||||
TRACE_CTOR(xpath_t::scope_t, "kind_t, const optional<scope_t&>&");
|
|
||||||
}
|
|
||||||
explicit scope_t(scope_t& _parent, kind_t _kind = NORMAL)
|
|
||||||
: parent(_parent), kind(_kind) {
|
|
||||||
TRACE_CTOR(xpath_t::scope_t, "scope_t&, kind_t");
|
|
||||||
}
|
}
|
||||||
virtual ~scope_t() {
|
virtual ~scope_t() {
|
||||||
TRACE_DTOR(xpath_t::scope_t);
|
TRACE_DTOR(xpath_t::scope_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
const type_t type() const {
|
||||||
virtual void define(const string& name, ptr_op_t def);
|
return type_;
|
||||||
void define(const string& name, const function_t& def);
|
|
||||||
virtual ptr_op_t lookup(const string& name);
|
|
||||||
|
|
||||||
virtual optional<value_t> resolve(const string& name, scope_t& locals) {
|
|
||||||
if (parent)
|
|
||||||
return parent->resolve(name, locals);
|
|
||||||
return none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend struct op_t;
|
virtual void define(const string& name, ptr_op_t def) = 0;
|
||||||
|
void define(const string& name, const value_t& val);
|
||||||
|
virtual ptr_op_t lookup(const string& name) = 0;
|
||||||
|
value_t resolve(const string& name) {
|
||||||
|
return lookup(name)->calc(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual optional<scope_t&> find_scope(const type_t _type,
|
||||||
|
bool skip_this = false) = 0;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T& find_scope(bool skip_this = false) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class function_scope_t : public scope_t
|
class child_scope_t : public scope_t
|
||||||
{
|
{
|
||||||
const node_t& node;
|
scope_t * parent;
|
||||||
std::size_t index;
|
|
||||||
std::size_t size;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
function_scope_t(const value_t::sequence_t& _sequence,
|
explicit child_scope_t(type_t _type = CHILD_SCOPE)
|
||||||
const node_t& _node,
|
: scope_t(_type), parent(NULL) {
|
||||||
std::size_t _index,
|
TRACE_CTOR(xpath_t::child_scope_t, "type_t");
|
||||||
const optional<scope_t&>& _parent = none)
|
}
|
||||||
: scope_t(_parent, STATIC), node(_node), index(_index),
|
explicit child_scope_t(scope_t& _parent, type_t _type = CHILD_SCOPE)
|
||||||
size(_sequence.size()) {}
|
: scope_t(_type), parent(&_parent) {
|
||||||
|
TRACE_CTOR(xpath_t::child_scope_t, "scope_t&, type_t");
|
||||||
|
}
|
||||||
|
virtual ~child_scope_t() {
|
||||||
|
TRACE_DTOR(xpath_t::child_scope_t);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
virtual void define(const string& name, ptr_op_t def) {
|
||||||
|
if (parent)
|
||||||
|
parent->define(name, def);
|
||||||
|
}
|
||||||
|
virtual ptr_op_t lookup(const string& name) {
|
||||||
|
if (parent)
|
||||||
|
return parent->lookup(name);
|
||||||
|
return ptr_op_t();
|
||||||
|
}
|
||||||
|
|
||||||
function_scope_t(const node_t& _node,
|
virtual optional<scope_t&> find_scope(type_t _type,
|
||||||
std::size_t _index,
|
bool skip_this = false) {
|
||||||
std::size_t _size,
|
for (scope_t * ptr = (skip_this ? parent : this); ptr; ) {
|
||||||
const optional<scope_t&>& _parent = none)
|
if (ptr->type() == _type)
|
||||||
: scope_t(_parent, STATIC), node(_node), index(_index),
|
return *ptr;
|
||||||
size(_size) {}
|
|
||||||
|
|
||||||
virtual optional<value_t> resolve(const string& name, scope_t& locals);
|
ptr = polymorphic_downcast<child_scope_t *>(ptr)->parent;
|
||||||
|
}
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class symbol_scope_t : public child_scope_t
|
||||||
|
{
|
||||||
|
typedef std::map<const string, ptr_op_t> symbol_map;
|
||||||
|
symbol_map symbols;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit symbol_scope_t()
|
||||||
|
: child_scope_t(SYMBOL_SCOPE) {
|
||||||
|
TRACE_CTOR(xpath_t::symbol_scope_t, "");
|
||||||
|
}
|
||||||
|
explicit symbol_scope_t(scope_t& _parent)
|
||||||
|
: child_scope_t(_parent, SYMBOL_SCOPE) {
|
||||||
|
TRACE_CTOR(xpath_t::symbol_scope_t, "scope_t&");
|
||||||
|
}
|
||||||
|
virtual ~symbol_scope_t() {
|
||||||
|
TRACE_DTOR(xpath_t::symbol_scope_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void define(const string& name, ptr_op_t def);
|
||||||
|
void define(const string& name, const value_t& val) {
|
||||||
|
scope_t::define(name, val);
|
||||||
|
}
|
||||||
|
virtual ptr_op_t lookup(const string& name);
|
||||||
|
};
|
||||||
|
|
||||||
|
class call_scope_t : public child_scope_t
|
||||||
|
{
|
||||||
|
value_t args;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit call_scope_t(scope_t& _parent)
|
||||||
|
: child_scope_t(_parent, CALL_SCOPE) {
|
||||||
|
TRACE_CTOR(xpath_t::call_scope_t, "scope_t&");
|
||||||
|
}
|
||||||
|
virtual ~call_scope_t() {
|
||||||
|
TRACE_DTOR(xpath_t::call_scope_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_args(const value_t& _args) {
|
||||||
|
args = _args;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& value() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& operator[](const int index) {
|
||||||
|
return args[index];
|
||||||
|
}
|
||||||
|
const value_t& operator[](const int index) const {
|
||||||
|
return args[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const value_t& val) {
|
||||||
|
args.push_back(val);
|
||||||
|
}
|
||||||
|
void pop_back() {
|
||||||
|
args.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t size() const {
|
||||||
|
return args.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class context_scope_t : public child_scope_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
value_t element;
|
||||||
|
optional<value_t> sequence;
|
||||||
|
|
||||||
|
explicit context_scope_t(scope_t& _parent,
|
||||||
|
const value_t& _element,
|
||||||
|
const optional<value_t>& _sequence = none)
|
||||||
|
: child_scope_t(_parent, CONTEXT_SCOPE),
|
||||||
|
element(_element), sequence(_sequence)
|
||||||
|
{
|
||||||
|
TRACE_CTOR(xpath_t::context_scope_t,
|
||||||
|
"scope_t&, const value_t&, const optional<value_t>&");
|
||||||
|
assert(! element.is_sequence());
|
||||||
|
|
||||||
|
if (DO_VERIFY() && sequence) {
|
||||||
|
if (sequence->is_sequence()) {
|
||||||
|
value_t::sequence_t seq(sequence->as_sequence());
|
||||||
|
value_t::iterator i = std::find(seq.begin(), seq.end(), element);
|
||||||
|
assert(i != seq.end());
|
||||||
|
} else {
|
||||||
|
assert(element == *sequence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual ~context_scope_t() {
|
||||||
|
TRACE_DTOR(xpath_t::context_scope_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t index() const {
|
||||||
|
if (! sequence) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
value_t::sequence_t seq(sequence->as_sequence());
|
||||||
|
value_t::iterator i = std::find(seq.begin(), seq.end(), element);
|
||||||
|
assert(i != seq.end());
|
||||||
|
int_least16_t offset = i - seq.begin();
|
||||||
|
assert(offset >= 0);
|
||||||
|
return std::size_t(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t size() const {
|
||||||
|
return sequence ? sequence->size() : (element.is_null() ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& value() {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_t& xml_node() {
|
||||||
|
if (! element.is_xml_node())
|
||||||
|
throw_(calc_error, "The current context value is not an XML node");
|
||||||
|
return *element.as_xml_node();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class node_scope_t : public context_scope_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
node_scope_t(scope_t& _parent, node_t& _node)
|
||||||
|
: context_scope_t(_parent, &_node) {
|
||||||
|
TRACE_CTOR(xpath_t::node_scope_t, "scope_t&, node_t&");
|
||||||
|
type_ = NODE_SCOPE;
|
||||||
|
}
|
||||||
|
virtual ~node_scope_t() {
|
||||||
|
TRACE_DTOR(xpath_t::node_scope_t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef node_scope_t document_scope_t;
|
||||||
|
|
||||||
|
class predicate_scope_t : public child_scope_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ptr_op_t predicate;
|
||||||
|
|
||||||
|
explicit predicate_scope_t(scope_t& _parent,
|
||||||
|
const ptr_op_t& _predicate)
|
||||||
|
: child_scope_t(_parent, PREDICATE_SCOPE), predicate(_predicate)
|
||||||
|
{
|
||||||
|
TRACE_CTOR(xpath_t::predicate_scope_t, "scope_t&, const ptr_op_t&");
|
||||||
|
}
|
||||||
|
virtual ~predicate_scope_t() {
|
||||||
|
TRACE_DTOR(xpath_t::predicate_scope_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test(scope_t& scope,
|
||||||
|
const value_t& val,
|
||||||
|
const optional<value_t>& sequence = none) const {
|
||||||
|
context_scope_t context_scope(scope, val, sequence);
|
||||||
|
|
||||||
|
if (predicate->is_value()) {
|
||||||
|
value_t& predicate_value(predicate->as_value());
|
||||||
|
if (predicate_value.is_long())
|
||||||
|
return predicate_value.as_long() == (long)context_scope.index() + 1;
|
||||||
|
}
|
||||||
|
return predicate->calc(context_scope).to_boolean();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define XPATH_PARSE_NORMAL 0x00
|
#define XPATH_PARSE_NORMAL 0x00
|
||||||
|
|
@ -137,57 +319,59 @@ private:
|
||||||
struct token_t
|
struct token_t
|
||||||
{
|
{
|
||||||
enum kind_t {
|
enum kind_t {
|
||||||
IDENT, // [A-Za-z_][-A-Za-z0-9_:]*
|
|
||||||
VALUE, // any kind of literal value
|
VALUE, // any kind of literal value
|
||||||
AT_SYM, // @
|
|
||||||
|
IDENT, // [A-Za-z_][-A-Za-z0-9_:]*
|
||||||
DOLLAR, // $
|
DOLLAR, // $
|
||||||
|
AT_SYM, // @
|
||||||
|
|
||||||
DOT, // .
|
DOT, // .
|
||||||
DOTDOT, // ..
|
DOTDOT, // ..
|
||||||
|
SLASH, // /
|
||||||
|
|
||||||
LPAREN, // (
|
LPAREN, // (
|
||||||
RPAREN, // )
|
RPAREN, // )
|
||||||
LBRACKET, // (
|
LBRACKET, // [
|
||||||
RBRACKET, // )
|
RBRACKET, // ]
|
||||||
EXCLAM, // !
|
|
||||||
NEQUAL, // !=
|
|
||||||
MINUS, // -
|
|
||||||
PLUS, // +
|
|
||||||
STAR, // *
|
|
||||||
POWER, // **
|
|
||||||
SLASH, // /
|
|
||||||
EQUAL, // =
|
EQUAL, // =
|
||||||
ASSIGN, // :=
|
NEQUAL, // !=
|
||||||
LESS, // <
|
LESS, // <
|
||||||
LESSEQ, // <=
|
LESSEQ, // <=
|
||||||
GREATER, // >
|
GREATER, // >
|
||||||
GREATEREQ, // >=
|
GREATEREQ, // >=
|
||||||
AMPER, // &
|
|
||||||
PIPE, // |
|
MINUS, // -
|
||||||
QUESTION, // ?
|
PLUS, // +
|
||||||
COLON, // :
|
STAR, // *
|
||||||
COMMA, // ,
|
KW_DIV,
|
||||||
|
|
||||||
|
EXCLAM, // !
|
||||||
KW_AND,
|
KW_AND,
|
||||||
KW_OR,
|
KW_OR,
|
||||||
KW_DIV,
|
|
||||||
KW_MOD,
|
KW_MOD,
|
||||||
|
|
||||||
|
PIPE, // |
|
||||||
KW_UNION,
|
KW_UNION,
|
||||||
|
|
||||||
|
COMMA, // ,
|
||||||
|
|
||||||
TOK_EOF,
|
TOK_EOF,
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
} kind;
|
} kind;
|
||||||
|
|
||||||
char symbol[3];
|
char symbol[3];
|
||||||
value_t value;
|
value_t value;
|
||||||
unsigned int length;
|
std::size_t length;
|
||||||
|
|
||||||
token_t() : kind(UNKNOWN), length(0) {
|
explicit token_t() : kind(UNKNOWN), length(0) {
|
||||||
TRACE_CTOR(xpath_t::token_t, "");
|
TRACE_CTOR(xpath_t::token_t, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
token_t(const token_t& other) {
|
token_t(const token_t& other) {
|
||||||
assert(false);
|
assert(false);
|
||||||
TRACE_CTOR(xpath_t::token_t, "copy");
|
TRACE_CTOR(xpath_t::token_t, "copy");
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
~token_t() {
|
~token_t() {
|
||||||
TRACE_DTOR(xpath_t::token_t);
|
TRACE_DTOR(xpath_t::token_t);
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +386,7 @@ private:
|
||||||
void clear() {
|
void clear() {
|
||||||
kind = UNKNOWN;
|
kind = UNKNOWN;
|
||||||
length = 0;
|
length = 0;
|
||||||
value = 0L;
|
value = NULL_VALUE;
|
||||||
|
|
||||||
symbol[0] = '\0';
|
symbol[0] = '\0';
|
||||||
symbol[1] = '\0';
|
symbol[1] = '\0';
|
||||||
|
|
@ -210,82 +394,23 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_ident(std::istream& in);
|
void parse_ident(std::istream& in);
|
||||||
|
|
||||||
void next(std::istream& in, flags_t flags);
|
void next(std::istream& in, flags_t flags);
|
||||||
void rewind(std::istream& in);
|
void rewind(std::istream& in);
|
||||||
|
|
||||||
void unexpected();
|
void unexpected();
|
||||||
|
|
||||||
static void unexpected(char c, char wanted = '\0');
|
static void unexpected(char c, char wanted = '\0');
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class path_t
|
#if 0
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef function<void (const value_t&)> visitor_t;
|
|
||||||
typedef function<bool (const node_t&, scope_t&)> predicate_t;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct value_appender_t {
|
|
||||||
value_t::sequence_t& sequence;
|
|
||||||
value_appender_t(value_t::sequence_t& _sequence)
|
|
||||||
: sequence(_sequence) {}
|
|
||||||
void operator()(const value_t& val) {
|
|
||||||
sequence.push_back(val);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ptr_op_t path_expr;
|
|
||||||
|
|
||||||
template <typename NodeType>
|
|
||||||
void walk_elements(NodeType& start,
|
|
||||||
const ptr_op_t& element,
|
|
||||||
const bool recurse,
|
|
||||||
scope_t& scope,
|
|
||||||
const visitor_t& func);
|
|
||||||
|
|
||||||
template <typename NodeType>
|
|
||||||
void check_element(NodeType& start,
|
|
||||||
const ptr_op_t& element,
|
|
||||||
scope_t& scope,
|
|
||||||
std::size_t index,
|
|
||||||
std::size_t size,
|
|
||||||
const visitor_t& func);
|
|
||||||
|
|
||||||
public:
|
|
||||||
path_t(const xpath_t& xpath) : path_expr(xpath.ptr) {}
|
|
||||||
path_t(const ptr_op_t& _path_expr) : path_expr(_path_expr) {}
|
|
||||||
|
|
||||||
value_t find_all(node_t& start, scope_t& scope) {
|
|
||||||
value_t result = value_t::sequence_t();
|
|
||||||
visit(start, scope, value_appender_t(result.as_sequence_lval()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
value_t find_all(const node_t& start, scope_t& scope) {
|
|
||||||
value_t result = value_t::sequence_t();
|
|
||||||
visit(start, scope, value_appender_t(result.as_sequence_lval()));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void visit(node_t& start, scope_t& scope, const visitor_t& func) {
|
|
||||||
if (path_expr)
|
|
||||||
walk_elements<node_t>(start, path_expr, false, scope, func);
|
|
||||||
}
|
|
||||||
void visit(const node_t& start, scope_t& scope, const visitor_t& func) {
|
|
||||||
if (path_expr)
|
|
||||||
walk_elements<const node_t>(start, path_expr, false, scope, func);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename NodeType>
|
|
||||||
class path_iterator_t
|
class path_iterator_t
|
||||||
{
|
{
|
||||||
typedef NodeType * pointer;
|
typedef NodeType * pointer;
|
||||||
typedef NodeType& reference;
|
typedef NodeType& reference;
|
||||||
|
|
||||||
path_t path;
|
path_t path;
|
||||||
reference start;
|
node_t& start;
|
||||||
scope_t& scope;
|
scope_t& scope;
|
||||||
|
|
||||||
mutable value_t::sequence_t sequence;
|
mutable value_t::sequence_t sequence;
|
||||||
mutable bool searched;
|
mutable bool searched;
|
||||||
|
|
@ -304,7 +429,7 @@ public:
|
||||||
typedef value_t::sequence_t::const_iterator const_iterator;
|
typedef value_t::sequence_t::const_iterator const_iterator;
|
||||||
|
|
||||||
path_iterator_t(const xpath_t& path_expr,
|
path_iterator_t(const xpath_t& path_expr,
|
||||||
reference _start, scope_t& _scope)
|
node_t& _start, scope_t& _scope)
|
||||||
: path(path_expr), start(_start), scope(_scope),
|
: path(path_expr), start(_start), scope(_scope),
|
||||||
searched(false) {
|
searched(false) {
|
||||||
}
|
}
|
||||||
|
|
@ -323,21 +448,21 @@ public:
|
||||||
iterator end() { return sequence.end(); }
|
iterator end() { return sequence.end(); }
|
||||||
const_iterator end() const { return sequence.end(); }
|
const_iterator end() const { return sequence.end(); }
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct op_t : public noncopyable
|
struct op_t : public noncopyable
|
||||||
{
|
{
|
||||||
enum kind_t {
|
enum kind_t {
|
||||||
VOID,
|
|
||||||
VALUE,
|
VALUE,
|
||||||
|
|
||||||
|
FUNC_NAME,
|
||||||
|
VAR_NAME,
|
||||||
|
ARG_INDEX,
|
||||||
|
|
||||||
NODE_ID,
|
NODE_ID,
|
||||||
NODE_NAME,
|
NODE_NAME,
|
||||||
ATTR_ID,
|
ATTR_ID,
|
||||||
ATTR_NAME,
|
ATTR_NAME,
|
||||||
FUNC_NAME,
|
|
||||||
VAR_NAME,
|
|
||||||
|
|
||||||
ARG_INDEX,
|
|
||||||
|
|
||||||
CONSTANTS, // constants end here
|
CONSTANTS, // constants end here
|
||||||
|
|
||||||
|
|
@ -345,15 +470,12 @@ public:
|
||||||
|
|
||||||
TERMINALS, // terminals end here
|
TERMINALS, // terminals end here
|
||||||
|
|
||||||
O_NOT,
|
O_CALL,
|
||||||
O_NEG,
|
O_ARG,
|
||||||
|
|
||||||
O_UNION,
|
O_FIND,
|
||||||
|
O_RFIND,
|
||||||
O_ADD,
|
O_PRED,
|
||||||
O_SUB,
|
|
||||||
O_MUL,
|
|
||||||
O_DIV,
|
|
||||||
|
|
||||||
O_NEQ,
|
O_NEQ,
|
||||||
O_EQ,
|
O_EQ,
|
||||||
|
|
@ -362,22 +484,20 @@ public:
|
||||||
O_GT,
|
O_GT,
|
||||||
O_GTE,
|
O_GTE,
|
||||||
|
|
||||||
|
O_ADD,
|
||||||
|
O_SUB,
|
||||||
|
O_MUL,
|
||||||
|
O_DIV,
|
||||||
|
O_NEG,
|
||||||
|
|
||||||
|
O_NOT,
|
||||||
O_AND,
|
O_AND,
|
||||||
O_OR,
|
O_OR,
|
||||||
|
|
||||||
O_QUES,
|
O_UNION,
|
||||||
O_COLON,
|
|
||||||
|
|
||||||
O_COMMA,
|
O_COMMA,
|
||||||
|
|
||||||
O_DEFINE,
|
|
||||||
O_EVAL,
|
|
||||||
O_ARG,
|
|
||||||
|
|
||||||
O_FIND,
|
|
||||||
O_RFIND,
|
|
||||||
O_PRED,
|
|
||||||
|
|
||||||
LAST // operators end here
|
LAST // operators end here
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -387,13 +507,13 @@ public:
|
||||||
|
|
||||||
variant<unsigned int, // used by ARG_INDEX and O_ARG
|
variant<unsigned int, // used by ARG_INDEX and O_ARG
|
||||||
value_t, // used by constant VALUE
|
value_t, // used by constant VALUE
|
||||||
string, // used by constant SYMBOL
|
string, // used by constants SYMBOL, *_NAME
|
||||||
function_t, // used by terminal FUNCTION
|
function_t, // used by terminal FUNCTION
|
||||||
node_t::nameid_t, // used by NODE_NAME and ATTR_NAME
|
node_t::nameid_t, // used by NODE_ID and ATTR_ID
|
||||||
ptr_op_t> // used by all binary operators
|
ptr_op_t> // used by all binary operators
|
||||||
data;
|
data;
|
||||||
|
|
||||||
op_t(const kind_t _kind) : kind(_kind), refc(0){
|
explicit op_t(const kind_t _kind) : kind(_kind), refc(0){
|
||||||
TRACE_CTOR(xpath_t::op_t, "const kind_t");
|
TRACE_CTOR(xpath_t::op_t, "const kind_t");
|
||||||
}
|
}
|
||||||
~op_t() {
|
~op_t() {
|
||||||
|
|
@ -403,8 +523,6 @@ public:
|
||||||
assert(refc == 0);
|
assert(refc == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
op_t& operator=(const op_t&);
|
|
||||||
|
|
||||||
bool is_long() const {
|
bool is_long() const {
|
||||||
return data.type() == typeid(unsigned int);
|
return data.type() == typeid(unsigned int);
|
||||||
}
|
}
|
||||||
|
|
@ -475,22 +593,6 @@ public:
|
||||||
data = val;
|
data = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool is_path() const {
|
|
||||||
return kind == PATH;
|
|
||||||
}
|
|
||||||
path_t& as_path() {
|
|
||||||
assert(kind == PATH);
|
|
||||||
return boost::get<path_t>(data);
|
|
||||||
}
|
|
||||||
const path_t& as_path() const {
|
|
||||||
return const_cast<op_t *>(this)->as_path();
|
|
||||||
}
|
|
||||||
void set_path(const path_t& val) {
|
|
||||||
data = val;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ptr_op_t& as_op() {
|
ptr_op_t& as_op() {
|
||||||
assert(kind > TERMINALS);
|
assert(kind > TERMINALS);
|
||||||
return boost::get<ptr_op_t>(data);
|
return boost::get<ptr_op_t>(data);
|
||||||
|
|
@ -538,23 +640,38 @@ public:
|
||||||
data = expr;
|
data = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ptr_op_t new_node(kind_t kind, ptr_op_t left = NULL,
|
static ptr_op_t new_node(kind_t _kind, ptr_op_t _left = NULL,
|
||||||
ptr_op_t right = NULL);
|
ptr_op_t _right = NULL);
|
||||||
|
ptr_op_t copy(ptr_op_t _left = NULL, ptr_op_t _right = NULL) const {
|
||||||
|
return new_node(kind, _left, _right);
|
||||||
|
}
|
||||||
|
|
||||||
ptr_op_t copy(ptr_op_t left = NULL, ptr_op_t right = NULL) const;
|
static ptr_op_t wrap_value(const value_t& val);
|
||||||
ptr_op_t compile(const node_t& context, scope_t& scope, bool resolve = false);
|
static ptr_op_t wrap_functor(const function_t& fobj);
|
||||||
|
|
||||||
void append_value(value_t::sequence_t& result_seq, value_t& value);
|
ptr_op_t compile(scope_t& scope);
|
||||||
|
value_t current_value(scope_t& scope);
|
||||||
|
node_t& current_xml_node(scope_t& scope);
|
||||||
|
value_t calc(scope_t& scope);
|
||||||
|
|
||||||
static ptr_op_t defer_sequence(value_t::sequence_t& result_seq);
|
struct print_context_t
|
||||||
|
{
|
||||||
|
scope_t& scope;
|
||||||
|
const bool relaxed;
|
||||||
|
const ptr_op_t& op_to_find;
|
||||||
|
unsigned long * start_pos;
|
||||||
|
unsigned long * end_pos;
|
||||||
|
|
||||||
bool print(std::ostream& out,
|
print_context_t(scope_t& _scope,
|
||||||
document_t& document,
|
const bool _relaxed = false,
|
||||||
const bool relaxed = true,
|
const ptr_op_t& _op_to_find = ptr_op_t(),
|
||||||
const ptr_op_t& op_to_find = NULL,
|
unsigned long * _start_pos = NULL,
|
||||||
unsigned long * start_pos = NULL,
|
unsigned long * _end_pos = NULL)
|
||||||
unsigned long * end_pos = NULL) const;
|
: scope(_scope), relaxed(_relaxed), op_to_find(_op_to_find),
|
||||||
|
start_pos(_start_pos), end_pos(_end_pos) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool print(std::ostream& out, print_context_t& context) const;
|
||||||
void dump(std::ostream& out, const int depth) const;
|
void dump(std::ostream& out, const int depth) const;
|
||||||
|
|
||||||
friend inline void intrusive_ptr_add_ref(xpath_t::op_t * op) {
|
friend inline void intrusive_ptr_add_ref(xpath_t::op_t * op) {
|
||||||
|
|
@ -565,15 +682,12 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class op_predicate : public noncopyable
|
class op_predicate : public noncopyable {
|
||||||
{
|
|
||||||
ptr_op_t op;
|
ptr_op_t op;
|
||||||
public:
|
public:
|
||||||
explicit op_predicate(ptr_op_t _op) : op(_op) {}
|
explicit op_predicate(ptr_op_t _op) : op(_op) {}
|
||||||
|
bool operator()(scope_t& scope) const {
|
||||||
bool operator()(const node_t& node, scope_t& scope) {
|
return op->calc(scope).to_boolean();
|
||||||
xpath_t result(op->compile(node, scope, true));
|
|
||||||
return result.ptr->as_value().to_boolean();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -660,14 +774,9 @@ public:
|
||||||
return parse_expr(string(p), tflags);
|
return parse_expr(string(p), tflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print(std::ostream& out,
|
bool print(std::ostream& out, op_t::print_context_t& context) const {
|
||||||
document_t& document,
|
|
||||||
const bool relaxed,
|
|
||||||
const ptr_op_t op_to_find,
|
|
||||||
unsigned long * start_pos,
|
|
||||||
unsigned long * end_pos) const {
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
ptr->print(out, document, relaxed, op_to_find, start_pos, end_pos);
|
ptr->print(out, context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -675,20 +784,20 @@ public:
|
||||||
string expr;
|
string expr;
|
||||||
flags_t flags; // flags used to parse `expr'
|
flags_t flags; // flags used to parse `expr'
|
||||||
|
|
||||||
xpath_t() : ptr(NULL), use_lookahead(false), flags(0) {
|
explicit xpath_t() : ptr(NULL), use_lookahead(false), flags(0) {
|
||||||
TRACE_CTOR(xpath_t, "");
|
TRACE_CTOR(xpath_t, "");
|
||||||
}
|
}
|
||||||
xpath_t(ptr_op_t _ptr) : ptr(_ptr), use_lookahead(false) {
|
explicit xpath_t(ptr_op_t _ptr) : ptr(_ptr), use_lookahead(false) {
|
||||||
TRACE_CTOR(xpath_t, "ptr_op_t");
|
TRACE_CTOR(xpath_t, "ptr_op_t");
|
||||||
}
|
}
|
||||||
|
|
||||||
xpath_t(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED)
|
explicit xpath_t(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED)
|
||||||
: ptr(NULL), use_lookahead(false), flags(0) {
|
: ptr(NULL), use_lookahead(false), flags(0) {
|
||||||
TRACE_CTOR(xpath_t, "const string&, flags_t");
|
TRACE_CTOR(xpath_t, "const string&, flags_t");
|
||||||
if (! _expr.empty())
|
if (! _expr.empty())
|
||||||
parse(_expr, _flags);
|
parse(_expr, _flags);
|
||||||
}
|
}
|
||||||
xpath_t(std::istream& in, flags_t _flags = XPATH_PARSE_RELAXED)
|
explicit xpath_t(std::istream& in, flags_t _flags = XPATH_PARSE_RELAXED)
|
||||||
: ptr(NULL), use_lookahead(false), flags(0) {
|
: ptr(NULL), use_lookahead(false), flags(0) {
|
||||||
TRACE_CTOR(xpath_t, "std::istream&, flags_t");
|
TRACE_CTOR(xpath_t, "std::istream&, flags_t");
|
||||||
parse(in, _flags);
|
parse(in, _flags);
|
||||||
|
|
@ -698,33 +807,29 @@ public:
|
||||||
expr(other.expr), flags(other.flags) {
|
expr(other.expr), flags(other.flags) {
|
||||||
TRACE_CTOR(xpath_t, "copy");
|
TRACE_CTOR(xpath_t, "copy");
|
||||||
}
|
}
|
||||||
virtual ~xpath_t() {
|
~xpath_t() {
|
||||||
TRACE_DTOR(xpath_t);
|
TRACE_DTOR(xpath_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
xpath_t& operator=(const string& _expr) {
|
xpath_t& operator=(const string& _expr) {
|
||||||
parse(_expr);
|
parse(_expr);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
xpath_t& operator=(const xpath_t& _expr);
|
xpath_t& operator=(const xpath_t& _expr);
|
||||||
xpath_t& operator=(xpath_t& _xpath) {
|
|
||||||
ptr = _xpath.ptr;
|
|
||||||
expr = _xpath.expr;
|
|
||||||
flags = _xpath.flags;
|
|
||||||
use_lookahead = false;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
operator ptr_op_t() throw() {
|
operator ptr_op_t() throw() {
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool() const throw() {
|
operator bool() const throw() {
|
||||||
return ptr != NULL;
|
return ptr != NULL;
|
||||||
}
|
}
|
||||||
operator string() const throw() {
|
operator string() const throw() {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void parse(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED) {
|
void parse(const string& _expr, flags_t _flags = XPATH_PARSE_RELAXED) {
|
||||||
expr = _expr;
|
expr = _expr;
|
||||||
|
|
@ -737,18 +842,22 @@ public:
|
||||||
ptr = parse_expr(in, _flags);
|
ptr = parse_expr(in, _flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile(const node_t& context, scope_t& scope) {
|
void compile(scope_t& scope) {
|
||||||
if (ptr.get())
|
if (ptr.get())
|
||||||
ptr = ptr->compile(context, scope);
|
ptr = ptr->compile(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual value_t calc(const node_t& context, scope_t& scope) const;
|
value_t calc(scope_t& scope) const {
|
||||||
|
if (ptr.get())
|
||||||
static value_t eval(const string& _expr, const node_t& context,
|
return ptr->calc(scope);
|
||||||
scope_t& scope) {
|
return NULL_VALUE;
|
||||||
return xpath_t(_expr).calc(context, scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static value_t eval(const string& _expr, scope_t& scope) {
|
||||||
|
return xpath_t(_expr).calc(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
path_iterator_t<node_t>
|
path_iterator_t<node_t>
|
||||||
find_all(node_t& start, scope_t& scope) {
|
find_all(node_t& start, scope_t& scope) {
|
||||||
return path_iterator_t<node_t>(*this, start, scope);
|
return path_iterator_t<node_t>(*this, start, scope);
|
||||||
|
|
@ -765,47 +874,81 @@ public:
|
||||||
path_t::visitor_t& func) {
|
path_t::visitor_t& func) {
|
||||||
path_t(*this).visit(start, scope, func);
|
path_t(*this).visit(start, scope, func);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void print(std::ostream& out, xml::document_t& document) const {
|
void print(std::ostream& out, scope_t& scope) const {
|
||||||
print(out, document, true, NULL, NULL, NULL);
|
op_t::print_context_t context(scope);
|
||||||
|
print(out, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump(std::ostream& out) const {
|
void dump(std::ostream& out) const {
|
||||||
if (ptr)
|
if (ptr)
|
||||||
ptr->dump(out, 0);
|
ptr->dump(out, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class scope_t;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline xpath_t::ptr_op_t
|
||||||
|
xpath_t::op_t::new_node(kind_t _kind, ptr_op_t _left, ptr_op_t _right) {
|
||||||
|
ptr_op_t node(new op_t(_kind));
|
||||||
|
if (_left)
|
||||||
|
node->set_left(_left);
|
||||||
|
if (_right)
|
||||||
|
node->set_right(_right);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline xpath_t::ptr_op_t
|
||||||
|
xpath_t::op_t::wrap_value(const value_t& val) {
|
||||||
|
xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::VALUE));
|
||||||
|
temp->set_value(val);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline xpath_t::ptr_op_t
|
||||||
|
xpath_t::op_t::wrap_functor(const function_t& fobj) {
|
||||||
|
xpath_t::ptr_op_t temp(new xpath_t::op_t(xpath_t::op_t::FUNCTION));
|
||||||
|
temp->set_function(fobj);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline xpath_t::symbol_scope_t&
|
||||||
|
xpath_t::scope_t::find_scope<xpath_t::symbol_scope_t>(bool skip_this) {
|
||||||
|
optional<scope_t&> scope = find_scope(SYMBOL_SCOPE, skip_this);
|
||||||
|
assert(scope);
|
||||||
|
return downcast<symbol_scope_t>(*scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline xpath_t::call_scope_t&
|
||||||
|
xpath_t::scope_t::find_scope<xpath_t::call_scope_t>(bool skip_this) {
|
||||||
|
optional<scope_t&> scope = find_scope(CALL_SCOPE, skip_this);
|
||||||
|
assert(scope);
|
||||||
|
return downcast<call_scope_t>(*scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline xpath_t::context_scope_t&
|
||||||
|
xpath_t::scope_t::find_scope<xpath_t::context_scope_t>(bool skip_this) {
|
||||||
|
optional<scope_t&> scope = find_scope(CONTEXT_SCOPE, skip_this);
|
||||||
|
assert(scope);
|
||||||
|
return downcast<context_scope_t>(*scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline xpath_t::node_scope_t&
|
||||||
|
xpath_t::scope_t::find_scope<xpath_t::node_scope_t>(bool skip_this) {
|
||||||
|
optional<scope_t&> scope = find_scope(NODE_SCOPE, skip_this);
|
||||||
|
assert(scope);
|
||||||
|
return downcast<node_scope_t>(*scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIND_SCOPE(scope_type, scope_ref) \
|
||||||
|
downcast<xml::xpath_t::scope_t>(scope_ref).find_scope<scope_type>()
|
||||||
|
|
||||||
} // namespace xml
|
} // namespace xml
|
||||||
|
|
||||||
template <typename T>
|
value_t xml_command(xml::xpath_t::call_scope_t& args);
|
||||||
inline T * get_ptr(xml::xpath_t::scope_t& locals, unsigned int idx) {
|
|
||||||
assert(locals.args.size() > idx);
|
|
||||||
T * ptr = locals.args[idx].as_pointer<T>();
|
|
||||||
assert(ptr);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_mutable());
|
|
||||||
assert(ptr);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
class xml_command
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
value_t operator()(xml::xpath_t::scope_t& locals) {
|
|
||||||
std::ostream * out = get_ptr<std::ostream>(locals, 0);
|
|
||||||
xml::document_t * doc = get_node_ptr<xml::document_t>(locals, 1);
|
|
||||||
doc->print(*out);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue