Now using xpath_t::path_t to select nodes.
This commit is contained in:
parent
74ecceb2ba
commit
7c7e5c5e36
8 changed files with 233 additions and 337 deletions
|
|
@ -153,7 +153,7 @@ bool entry_base_t::finalize()
|
||||||
// account if one has been set.
|
// account if one has been set.
|
||||||
|
|
||||||
if (journal && journal->basket && transactions.size() == 1) {
|
if (journal && journal->basket && transactions.size() == 1) {
|
||||||
assert(balance.is_type(value_t::AMOUNT));
|
assert(balance.is_amount());
|
||||||
transaction_t * nxact = new transaction_t(journal->basket);
|
transaction_t * nxact = new transaction_t(journal->basket);
|
||||||
// The amount doesn't need to be set because the code below will
|
// The amount doesn't need to be set because the code below will
|
||||||
// balance this transaction against the other.
|
// balance this transaction against the other.
|
||||||
|
|
@ -166,7 +166,7 @@ bool entry_base_t::finalize()
|
||||||
// determine its price by dividing the unit count into the value of
|
// determine its price by dividing the unit count into the value of
|
||||||
// the balance. This is done for the last eligible commodity.
|
// the balance. This is done for the last eligible commodity.
|
||||||
|
|
||||||
if (! saw_null && balance && balance.is_type(value_t::BALANCE) &&
|
if (! saw_null && balance && balance.is_balance() &&
|
||||||
balance.as_balance().amounts.size() == 2) {
|
balance.as_balance().amounts.size() == 2) {
|
||||||
transactions_list::const_iterator x = transactions.begin();
|
transactions_list::const_iterator x = transactions.begin();
|
||||||
assert((*x)->amount);
|
assert((*x)->amount);
|
||||||
|
|
|
||||||
12
src/main.cc
12
src/main.cc
|
|
@ -268,10 +268,18 @@ static int read_and_report(ledger::report_t * report, int argc, char * argv[],
|
||||||
xpath.print(*out, xml_document);
|
xpath.print(*out, xml_document);
|
||||||
*out << std::endl;
|
*out << std::endl;
|
||||||
|
|
||||||
foreach (xml::node_t * node, xpath.find_all(xml_document, report)) {
|
value_t result = xpath.calc(xml_document, report);
|
||||||
node->print(std::cout);
|
|
||||||
|
if (result.is_sequence()) {
|
||||||
|
foreach (const value_t& value, result.as_sequence()) {
|
||||||
|
if (value.is_xml_node()) {
|
||||||
|
value.as_xml_node()->print(std::cout);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << result << std::endl;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ object python_interpreter_t::import(const string& str)
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
throw_(std::logic_error, "Importing Python module " << str);
|
throw_(std::logic_error, "Importing Python module " << str);
|
||||||
}
|
}
|
||||||
|
return object();
|
||||||
}
|
}
|
||||||
|
|
||||||
object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
|
object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
|
||||||
|
|
@ -153,6 +154,7 @@ object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
throw_(std::logic_error, "Evaluating Python code");
|
throw_(std::logic_error, "Evaluating Python code");
|
||||||
}
|
}
|
||||||
|
return object();
|
||||||
}
|
}
|
||||||
|
|
||||||
object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
|
object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
|
||||||
|
|
@ -171,6 +173,7 @@ object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
throw_(std::logic_error, "Evaluating Python code");
|
throw_(std::logic_error, "Evaluating Python code");
|
||||||
}
|
}
|
||||||
|
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::scope_t * locals)
|
||||||
|
|
@ -194,7 +197,7 @@ value_t python_interpreter_t::functor_t::operator()(xml::xpath_t::scope_t * loca
|
||||||
else if (PyObject * err = PyErr_Occurred()) {
|
else if (PyObject * err = PyErr_Occurred()) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
throw_(xml::xpath_t::calc_error,
|
throw_(xml::xpath_t::calc_error,
|
||||||
"While calling Python function '" /*<< name() <<*/ "'");
|
"While calling Python function '" /*<< name() <<*/ "': " << err);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
@ -208,6 +211,7 @@ value_t python_interpreter_t::functor_t::operator()(xml::xpath_t::scope_t * loca
|
||||||
throw_(xml::xpath_t::calc_error,
|
throw_(xml::xpath_t::calc_error,
|
||||||
"While calling Python function '" /*<< name() <<*/ "'");
|
"While calling Python function '" /*<< name() <<*/ "'");
|
||||||
}
|
}
|
||||||
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t python_interpreter_t::lambda_t::operator()
|
value_t python_interpreter_t::lambda_t::operator()
|
||||||
|
|
@ -216,7 +220,7 @@ value_t python_interpreter_t::lambda_t::operator()
|
||||||
try {
|
try {
|
||||||
assert(locals->args.size() == 1);
|
assert(locals->args.size() == 1);
|
||||||
value_t item = locals->args[0];
|
value_t item = locals->args[0];
|
||||||
assert(item.is_type(value_t::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());
|
||||||
}
|
}
|
||||||
catch (const error_already_set&) {
|
catch (const error_already_set&) {
|
||||||
|
|
@ -224,6 +228,7 @@ value_t python_interpreter_t::lambda_t::operator()
|
||||||
throw_(xml::xpath_t::calc_error,
|
throw_(xml::xpath_t::calc_error,
|
||||||
"While evaluating Python lambda expression");
|
"While evaluating Python lambda expression");
|
||||||
}
|
}
|
||||||
|
return NULL_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <boost/algorithm/string/classification.hpp>
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/any.hpp>
|
||||||
#include <boost/cast.hpp>
|
#include <boost/cast.hpp>
|
||||||
#include <boost/current_function.hpp>
|
#include <boost/current_function.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
|
||||||
177
src/value.cc
177
src/value.cc
|
|
@ -55,6 +55,9 @@ void value_t::storage_t::destroy()
|
||||||
case SEQUENCE:
|
case SEQUENCE:
|
||||||
((sequence_t *)data)->~sequence_t();
|
((sequence_t *)data)->~sequence_t();
|
||||||
break;
|
break;
|
||||||
|
case POINTER:
|
||||||
|
((boost::any *)data)->~any();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -84,79 +87,7 @@ value_t& value_t::operator=(const value_t& val)
|
||||||
if (this == &val || storage == val.storage)
|
if (this == &val || storage == val.storage)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (type() == val.type())
|
storage = val.storage;
|
||||||
switch (type()) {
|
|
||||||
case VOID:
|
|
||||||
assert(false);
|
|
||||||
return *this;
|
|
||||||
case BOOLEAN:
|
|
||||||
as_boolean_lval() = val.as_boolean();
|
|
||||||
return *this;
|
|
||||||
case INTEGER:
|
|
||||||
as_long_lval() = val.as_long();
|
|
||||||
return *this;
|
|
||||||
case DATETIME:
|
|
||||||
as_datetime_lval() = val.as_datetime();
|
|
||||||
return *this;
|
|
||||||
case AMOUNT:
|
|
||||||
as_amount_lval() = val.as_amount();
|
|
||||||
return *this;
|
|
||||||
case BALANCE:
|
|
||||||
as_balance_lval() = val.as_balance();
|
|
||||||
return *this;
|
|
||||||
case BALANCE_PAIR:
|
|
||||||
as_balance_pair_lval() = val.as_balance_pair();
|
|
||||||
return *this;
|
|
||||||
case STRING:
|
|
||||||
as_string_lval() = val.as_string();
|
|
||||||
return *this;
|
|
||||||
case SEQUENCE:
|
|
||||||
as_sequence_lval() = val.as_sequence();
|
|
||||||
return *this;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (val.type()) {
|
|
||||||
case VOID:
|
|
||||||
set_type(VOID);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BOOLEAN:
|
|
||||||
set_boolean(val.as_boolean());
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
set_long(val.as_long());
|
|
||||||
break;
|
|
||||||
case DATETIME:
|
|
||||||
set_datetime(val.as_datetime());
|
|
||||||
break;
|
|
||||||
case AMOUNT:
|
|
||||||
set_amount(val.as_amount());
|
|
||||||
break;
|
|
||||||
case BALANCE:
|
|
||||||
set_balance(val.as_balance());
|
|
||||||
break;
|
|
||||||
case BALANCE_PAIR:
|
|
||||||
set_balance_pair(val.as_balance_pair());
|
|
||||||
break;
|
|
||||||
case STRING:
|
|
||||||
set_string(val.as_string());
|
|
||||||
break;
|
|
||||||
case SEQUENCE:
|
|
||||||
set_sequence(val.as_sequence());
|
|
||||||
break;
|
|
||||||
case XML_NODE:
|
|
||||||
set_xml_node(val.as_xml_node());
|
|
||||||
break;
|
|
||||||
case POINTER:
|
|
||||||
set_pointer(val.as_pointer());
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +114,7 @@ value_t::operator bool() const
|
||||||
case XML_NODE:
|
case XML_NODE:
|
||||||
return as_xml_node()->to_value();
|
return as_xml_node()->to_value();
|
||||||
case POINTER:
|
case POINTER:
|
||||||
return as_pointer() != NULL;
|
return ! as_any_pointer().empty();
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
|
|
@ -291,19 +222,19 @@ void value_t::in_place_simplify()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type(BALANCE_PAIR) &&
|
if (is_balance_pair() &&
|
||||||
(! as_balance_pair().cost || as_balance_pair().cost->is_realzero())) {
|
(! as_balance_pair().cost || as_balance_pair().cost->is_realzero())) {
|
||||||
DEBUG_("Reducing balance pair to balance");
|
DEBUG_("Reducing balance pair to balance");
|
||||||
in_place_cast(BALANCE);
|
in_place_cast(BALANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type(BALANCE) && as_balance().amounts.size() == 1) {
|
if (is_balance() && as_balance().amounts.size() == 1) {
|
||||||
DEBUG_("Reducing balance to amount");
|
DEBUG_("Reducing balance to amount");
|
||||||
in_place_cast(AMOUNT);
|
in_place_cast(AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (is_type(AMOUNT) && ! as_amount().has_commodity() &&
|
if (is_amount() && ! as_amount().has_commodity() &&
|
||||||
as_amount().fits_in_long()) {
|
as_amount().fits_in_long()) {
|
||||||
DEBUG_("Reducing amount to integer");
|
DEBUG_("Reducing amount to integer");
|
||||||
in_place_cast(INTEGER);
|
in_place_cast(INTEGER);
|
||||||
|
|
@ -313,15 +244,15 @@ void value_t::in_place_simplify()
|
||||||
|
|
||||||
value_t& value_t::operator+=(const value_t& val)
|
value_t& value_t::operator+=(const value_t& val)
|
||||||
{
|
{
|
||||||
if (is_type(STRING)) {
|
if (is_string()) {
|
||||||
if (val.is_type(STRING))
|
if (val.is_string())
|
||||||
as_string_lval() += val.as_string();
|
as_string_lval() += val.as_string();
|
||||||
else
|
else
|
||||||
as_string_lval() += val.to_string();
|
as_string_lval() += val.to_string();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
else if (is_type(SEQUENCE)) {
|
else if (is_sequence()) {
|
||||||
if (val.is_type(SEQUENCE)) {
|
if (val.is_sequence()) {
|
||||||
sequence_t& seq(as_sequence_lval());
|
sequence_t& seq(as_sequence_lval());
|
||||||
seq.insert(seq.end(), val.as_sequence().begin(),
|
seq.insert(seq.end(), val.as_sequence().begin(),
|
||||||
val.as_sequence().end());
|
val.as_sequence().end());
|
||||||
|
|
@ -331,7 +262,7 @@ value_t& value_t::operator+=(const value_t& val)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val.is_type(XML_NODE)) // recurse
|
if (val.is_xml_node()) // recurse
|
||||||
return *this += val.as_xml_node()->to_value();
|
return *this += val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
|
|
@ -456,10 +387,10 @@ value_t& value_t::operator+=(const value_t& val)
|
||||||
|
|
||||||
value_t& value_t::operator-=(const value_t& val)
|
value_t& value_t::operator-=(const value_t& val)
|
||||||
{
|
{
|
||||||
if (is_type(SEQUENCE)) {
|
if (is_sequence()) {
|
||||||
sequence_t& seq(as_sequence_lval());
|
sequence_t& seq(as_sequence_lval());
|
||||||
|
|
||||||
if (val.is_type(SEQUENCE)) {
|
if (val.is_sequence()) {
|
||||||
for (sequence_t::const_iterator i = val.as_sequence().begin();
|
for (sequence_t::const_iterator i = val.as_sequence().begin();
|
||||||
i != val.as_sequence().end();
|
i != val.as_sequence().end();
|
||||||
i++) {
|
i++) {
|
||||||
|
|
@ -475,7 +406,7 @@ value_t& value_t::operator-=(const value_t& val)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val.is_type(XML_NODE)) // recurse
|
if (val.is_xml_node()) // recurse
|
||||||
return *this -= val.as_xml_node()->to_value();
|
return *this -= val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
|
|
@ -619,7 +550,7 @@ value_t& value_t::operator-=(const value_t& val)
|
||||||
|
|
||||||
value_t& value_t::operator*=(const value_t& val)
|
value_t& value_t::operator*=(const value_t& val)
|
||||||
{
|
{
|
||||||
if (is_type(STRING)) {
|
if (is_string()) {
|
||||||
string temp;
|
string temp;
|
||||||
long count = val.to_long();
|
long count = val.to_long();
|
||||||
for (long i = 0; i < count; i++)
|
for (long i = 0; i < count; i++)
|
||||||
|
|
@ -627,7 +558,7 @@ value_t& value_t::operator*=(const value_t& val)
|
||||||
set_string(temp);
|
set_string(temp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
else if (is_type(SEQUENCE)) {
|
else if (is_sequence()) {
|
||||||
value_t temp;
|
value_t temp;
|
||||||
long count = val.to_long();
|
long count = val.to_long();
|
||||||
for (long i = 0; i < count; i++)
|
for (long i = 0; i < count; i++)
|
||||||
|
|
@ -635,7 +566,7 @@ value_t& value_t::operator*=(const value_t& val)
|
||||||
return *this = temp;
|
return *this = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val.is_type(XML_NODE)) // recurse
|
if (val.is_xml_node()) // recurse
|
||||||
return *this *= val.as_xml_node()->to_value();
|
return *this *= val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
|
|
@ -712,7 +643,7 @@ value_t& value_t::operator*=(const value_t& val)
|
||||||
|
|
||||||
value_t& value_t::operator/=(const value_t& val)
|
value_t& value_t::operator/=(const value_t& val)
|
||||||
{
|
{
|
||||||
if (val.is_type(XML_NODE)) // recurse
|
if (val.is_xml_node()) // recurse
|
||||||
return *this /= val.as_xml_node()->to_value();
|
return *this /= val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
|
|
@ -791,21 +722,21 @@ value_t& value_t::operator/=(const value_t& val)
|
||||||
|
|
||||||
bool value_t::operator==(const value_t& val) const
|
bool value_t::operator==(const value_t& val) const
|
||||||
{
|
{
|
||||||
if (is_type(XML_NODE) && val.is_type(XML_NODE))
|
if (is_xml_node() && val.is_xml_node())
|
||||||
return as_xml_node() == val.as_xml_node();
|
return as_xml_node() == val.as_xml_node();
|
||||||
else if (is_type(XML_NODE))
|
else if (is_xml_node())
|
||||||
return as_xml_node()->to_value() == val;
|
return as_xml_node()->to_value() == val;
|
||||||
else if (val.is_type(XML_NODE))
|
else if (val.is_xml_node())
|
||||||
return *this == val.as_xml_node()->to_value();
|
return *this == val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
if (val.is_type(BOOLEAN))
|
if (val.is_boolean())
|
||||||
return as_boolean() == val.as_boolean();
|
return as_boolean() == val.as_boolean();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
if (val.is_type(DATETIME))
|
if (val.is_datetime())
|
||||||
return as_datetime() == val.as_datetime();
|
return as_datetime() == val.as_datetime();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -870,20 +801,15 @@ bool value_t::operator==(const value_t& val) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
if (val.is_type(STRING))
|
if (val.is_string())
|
||||||
return as_string() == val.as_string();
|
return as_string() == val.as_string();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEQUENCE:
|
case SEQUENCE:
|
||||||
if (val.is_type(SEQUENCE))
|
if (val.is_sequence())
|
||||||
return as_sequence() == val.as_sequence();
|
return as_sequence() == val.as_sequence();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POINTER:
|
|
||||||
if (val.is_type(POINTER))
|
|
||||||
return as_pointer() == val.as_pointer();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -895,16 +821,16 @@ bool value_t::operator==(const value_t& val) const
|
||||||
|
|
||||||
bool value_t::operator<(const value_t& val) const
|
bool value_t::operator<(const value_t& val) const
|
||||||
{
|
{
|
||||||
if (is_type(XML_NODE) && val.is_type(XML_NODE))
|
if (is_xml_node() && val.is_xml_node())
|
||||||
return as_xml_node() < val.as_xml_node();
|
return as_xml_node() < val.as_xml_node();
|
||||||
else if (is_type(XML_NODE))
|
else if (is_xml_node())
|
||||||
return as_xml_node()->to_value() < val;
|
return as_xml_node()->to_value() < val;
|
||||||
else if (val.is_type(XML_NODE))
|
else if (val.is_xml_node())
|
||||||
return *this < val.as_xml_node()->to_value();
|
return *this < val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
if (val.is_type(DATETIME))
|
if (val.is_datetime())
|
||||||
return as_datetime() < val.as_datetime();
|
return as_datetime() < val.as_datetime();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -931,15 +857,10 @@ bool value_t::operator<(const value_t& val) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
if (val.is_type(STRING))
|
if (val.is_string())
|
||||||
return as_string() < val.as_string();
|
return as_string() < val.as_string();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POINTER:
|
|
||||||
if (val.is_type(POINTER))
|
|
||||||
return as_pointer() < val.as_pointer();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -952,16 +873,16 @@ bool value_t::operator<(const value_t& val) const
|
||||||
#if 0
|
#if 0
|
||||||
bool value_t::operator>(const value_t& val) const
|
bool value_t::operator>(const value_t& val) const
|
||||||
{
|
{
|
||||||
if (is_type(XML_NODE) && val.is_type(XML_NODE))
|
if (is_xml_node() && val.is_xml_node())
|
||||||
return as_xml_node() > val.as_xml_node();
|
return as_xml_node() > val.as_xml_node();
|
||||||
else if (is_type(XML_NODE))
|
else if (is_xml_node())
|
||||||
return as_xml_node()->to_value() > val;
|
return as_xml_node()->to_value() > val;
|
||||||
else if (val.is_type(XML_NODE))
|
else if (val.is_xml_node())
|
||||||
return *this > val.as_xml_node()->to_value();
|
return *this > val.as_xml_node()->to_value();
|
||||||
|
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
if (val.is_type(DATETIME))
|
if (val.is_datetime())
|
||||||
return as_datetime() > val.as_datetime();
|
return as_datetime() > val.as_datetime();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -988,15 +909,10 @@ bool value_t::operator>(const value_t& val) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
if (val.is_type(STRING))
|
if (val.is_string())
|
||||||
return as_string() > val.as_string();
|
return as_string() > val.as_string();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POINTER:
|
|
||||||
if (val.is_type(POINTER))
|
|
||||||
return as_pointer() > val.as_pointer();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1028,7 +944,7 @@ void value_t::in_place_cast(type_t cast_type)
|
||||||
// This must came after the if's above, otherwise it would be
|
// This must came after the if's above, otherwise it would be
|
||||||
// impossible to turn an XML node into a sequence containing that
|
// impossible to turn an XML node into a sequence containing that
|
||||||
// same XML node.
|
// same XML node.
|
||||||
if (is_type(XML_NODE)) {
|
if (is_xml_node()) {
|
||||||
*this = as_xml_node()->to_value().cast(cast_type);
|
*this = as_xml_node()->to_value().cast(cast_type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1214,7 +1130,7 @@ bool value_t::is_realzero() const
|
||||||
case XML_NODE:
|
case XML_NODE:
|
||||||
return as_xml_node() == NULL;
|
return as_xml_node() == NULL;
|
||||||
case POINTER:
|
case POINTER:
|
||||||
return as_pointer() == NULL;
|
return as_any_pointer().empty();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
@ -1310,18 +1226,23 @@ value_t value_t::unround() const
|
||||||
throw_(value_error, "Cannot un-round a boolean");
|
throw_(value_error, "Cannot un-round a boolean");
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
throw_(value_error, "Cannot un-round a date/time");
|
throw_(value_error, "Cannot un-round a date/time");
|
||||||
|
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
return as_amount().unround();
|
return as_amount().unround();
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
return as_balance().unround();
|
return as_balance().unround();
|
||||||
case BALANCE_PAIR:
|
case BALANCE_PAIR:
|
||||||
return as_balance_pair().unround();
|
return as_balance_pair().unround();
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
throw_(value_error, "Cannot un-round a string");
|
throw_(value_error, "Cannot un-round a string");
|
||||||
|
|
||||||
case XML_NODE:
|
case XML_NODE:
|
||||||
return as_xml_node()->to_value().unround();
|
return as_xml_node()->to_value().unround();
|
||||||
|
|
||||||
case POINTER:
|
case POINTER:
|
||||||
throw_(value_error, "Cannot un-round a pointer");
|
throw_(value_error, "Cannot un-round a pointer");
|
||||||
case SEQUENCE:
|
case SEQUENCE:
|
||||||
|
|
@ -1496,10 +1417,12 @@ value_t value_t::cost() const
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
throw_(value_error, "Cannot find the cost of a boolean");
|
throw_(value_error, "Cannot find the cost of a boolean");
|
||||||
|
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
throw_(value_error, "Cannot find the cost of a date/time");
|
throw_(value_error, "Cannot find the cost of a date/time");
|
||||||
|
|
||||||
|
|
@ -1512,8 +1435,10 @@ value_t value_t::cost() const
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
throw_(value_error, "Cannot find the cost of a string");
|
throw_(value_error, "Cannot find the cost of a string");
|
||||||
|
|
||||||
case XML_NODE:
|
case XML_NODE:
|
||||||
return as_xml_node()->to_value().cost();
|
return as_xml_node()->to_value().cost();
|
||||||
|
|
||||||
case POINTER:
|
case POINTER:
|
||||||
throw_(value_error, "Cannot find the cost of a pointer");
|
throw_(value_error, "Cannot find the cost of a pointer");
|
||||||
case SEQUENCE:
|
case SEQUENCE:
|
||||||
|
|
@ -1541,13 +1466,13 @@ value_t& value_t::add(const amount_t& amount, const optional<amount_t>& tcost)
|
||||||
in_place_cast(BALANCE_PAIR);
|
in_place_cast(BALANCE_PAIR);
|
||||||
return add(amount, tcost);
|
return add(amount, tcost);
|
||||||
}
|
}
|
||||||
else if ((is_type(AMOUNT) &&
|
else if ((is_amount() &&
|
||||||
as_amount().commodity() != amount.commodity()) ||
|
as_amount().commodity() != amount.commodity()) ||
|
||||||
(! is_type(AMOUNT) && amount.commodity())) {
|
(! is_amount() && amount.commodity())) {
|
||||||
in_place_cast(BALANCE);
|
in_place_cast(BALANCE);
|
||||||
return add(amount, tcost);
|
return add(amount, tcost);
|
||||||
}
|
}
|
||||||
else if (! is_type(AMOUNT)) {
|
else if (! is_amount()) {
|
||||||
in_place_cast(AMOUNT);
|
in_place_cast(AMOUNT);
|
||||||
}
|
}
|
||||||
*this += amount;
|
*this += amount;
|
||||||
|
|
|
||||||
61
src/value.h
61
src/value.h
|
|
@ -72,6 +72,7 @@ public:
|
||||||
STRING,
|
STRING,
|
||||||
SEQUENCE,
|
SEQUENCE,
|
||||||
XML_NODE,
|
XML_NODE,
|
||||||
|
CONST_XML_NODE,
|
||||||
POINTER
|
POINTER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -216,6 +217,10 @@ 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) {
|
||||||
|
TRACE_CTOR(value_t, "const xml::node_t *");
|
||||||
|
set_xml_node(xml_node);
|
||||||
|
}
|
||||||
value_t(void * item) {
|
value_t(void * item) {
|
||||||
TRACE_CTOR(value_t, "void *");
|
TRACE_CTOR(value_t, "void *");
|
||||||
set_pointer(item);
|
set_pointer(item);
|
||||||
|
|
@ -248,14 +253,16 @@ public:
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
bool is_null() const {
|
bool is_null() const {
|
||||||
return ! storage || storage->type == VOID;
|
return ! storage || is_type(VOID);
|
||||||
|
}
|
||||||
|
type_t type() const {
|
||||||
|
type_t result = storage ? storage->type : VOID;
|
||||||
|
assert(result >= VOID && result <= POINTER);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_t type() const {
|
private:
|
||||||
return storage ? storage->type : VOID;
|
|
||||||
}
|
|
||||||
bool is_type(type_t _type) const {
|
bool is_type(type_t _type) const {
|
||||||
assert(_type >= VOID && _type <= POINTER);
|
|
||||||
return type() == _type;
|
return type() == _type;
|
||||||
}
|
}
|
||||||
void set_type(type_t new_type) {
|
void set_type(type_t new_type) {
|
||||||
|
|
@ -265,6 +272,7 @@ public:
|
||||||
assert(is_type(new_type));
|
assert(is_type(new_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
bool is_boolean() const {
|
bool is_boolean() const {
|
||||||
return is_type(BOOLEAN);
|
return is_type(BOOLEAN);
|
||||||
}
|
}
|
||||||
|
|
@ -402,37 +410,63 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_xml_node() const {
|
bool is_xml_node() const {
|
||||||
return is_type(XML_NODE);
|
return is_type(XML_NODE) || is_type(CONST_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() const {
|
xml::node_t * as_xml_node_mutable() {
|
||||||
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;
|
||||||
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
void *& as_pointer_lval() {
|
boost::any& as_any_pointer_lval() {
|
||||||
assert(is_pointer());
|
assert(is_pointer());
|
||||||
_dup();
|
_dup();
|
||||||
return *(void **) storage->data;
|
return *(boost::any *) storage->data;
|
||||||
}
|
}
|
||||||
void * as_pointer() const {
|
template <typename T>
|
||||||
|
T *& as_pointer_lval() {
|
||||||
assert(is_pointer());
|
assert(is_pointer());
|
||||||
return *(void **) storage->data;
|
_dup();
|
||||||
|
return any_cast<T *>(*(boost::any *) storage->data);
|
||||||
}
|
}
|
||||||
void set_pointer(void * val) {
|
boost::any as_any_pointer() const {
|
||||||
|
assert(is_pointer());
|
||||||
|
return *(boost::any *) storage->data;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
T * as_pointer() const {
|
||||||
|
assert(is_pointer());
|
||||||
|
return any_cast<T *>(*(boost::any *) storage->data);
|
||||||
|
}
|
||||||
|
void set_any_pointer(const boost::any& val) {
|
||||||
set_type(POINTER);
|
set_type(POINTER);
|
||||||
*(void **) storage->data = val;
|
new((boost::any *) storage->data) boost::any(val);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
void set_pointer(T * val) {
|
||||||
|
set_type(POINTER);
|
||||||
|
new((boost::any *) storage->data) boost::any(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool to_boolean() const;
|
bool to_boolean() const;
|
||||||
|
|
@ -498,6 +532,7 @@ 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";
|
||||||
|
|
|
||||||
198
src/xpath.cc
198
src/xpath.cc
|
|
@ -1044,39 +1044,6 @@ xpath_t::op_t::copy(ptr_op_t tleft, ptr_op_t tright) const
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xpath_t::op_t::find_values(const node_t& context, scope_t * scope,
|
|
||||||
value_t::sequence_t& result_seq,
|
|
||||||
bool recursive)
|
|
||||||
{
|
|
||||||
xpath_t expr(compile(context, scope, true));
|
|
||||||
|
|
||||||
if (expr.ptr->is_value() &&
|
|
||||||
(expr.ptr->as_value().is_xml_node() ||
|
|
||||||
expr.ptr->as_value().is_sequence()))
|
|
||||||
append_value(result_seq, expr.ptr->as_value());
|
|
||||||
|
|
||||||
if (recursive && context.is_parent_node())
|
|
||||||
foreach (node_t * node, context.as_parent_node())
|
|
||||||
find_values(*node, scope, result_seq, recursive);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool xpath_t::op_t::test_value(const node_t& context, scope_t * scope, int index)
|
|
||||||
{
|
|
||||||
xpath_t expr(compile(context, scope, true));
|
|
||||||
|
|
||||||
if (expr.ptr->kind != VALUE)
|
|
||||||
throw_(calc_error, "Predicate expression does not yield a constant value");
|
|
||||||
|
|
||||||
switch (expr.ptr->as_value().type()) {
|
|
||||||
case value_t::INTEGER:
|
|
||||||
case value_t::AMOUNT:
|
|
||||||
return expr.ptr->as_value() == value_t((long)index + 1);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return expr.ptr->as_value().as_boolean();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xpath_t::ptr_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
|
// If not all of the elements were constants, transform the result
|
||||||
|
|
@ -1102,7 +1069,7 @@ xpath_t::ptr_op_t xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
|
||||||
opp = &(*opp)->right();
|
opp = &(*opp)->right();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (*i).is_type(value_t::POINTER))
|
if (! (*i).is_pointer())
|
||||||
*opp = wrap_value(*i);
|
*opp = wrap_value(*i);
|
||||||
else
|
else
|
||||||
#if 1
|
#if 1
|
||||||
|
|
@ -1117,7 +1084,7 @@ xpath_t::ptr_op_t xpath_t::op_t::defer_sequence(value_t::sequence_t& result_seq)
|
||||||
|
|
||||||
void xpath_t::op_t::append_value(value_t::sequence_t& result_seq, value_t& val)
|
void xpath_t::op_t::append_value(value_t::sequence_t& result_seq, value_t& val)
|
||||||
{
|
{
|
||||||
if (val.is_type(value_t::SEQUENCE))
|
if (val.is_sequence())
|
||||||
std::for_each(val.as_sequence().begin(), val.as_sequence().end(),
|
std::for_each(val.as_sequence().begin(), val.as_sequence().end(),
|
||||||
bind(&value_t::sequence_t::push_back, ref(result_seq), _1));
|
bind(&value_t::sequence_t::push_back, ref(result_seq), _1));
|
||||||
else
|
else
|
||||||
|
|
@ -1134,57 +1101,6 @@ xpath_t::op_t::compile(const node_t& context, scope_t * scope, bool resolve)
|
||||||
case VALUE:
|
case VALUE:
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
case NODE_ID:
|
|
||||||
switch (as_name()) {
|
|
||||||
case document_t::CURRENT:
|
|
||||||
return wrap_value(&context);
|
|
||||||
|
|
||||||
case document_t::PARENT:
|
|
||||||
if (context.parent())
|
|
||||||
return wrap_value(&*context.parent());
|
|
||||||
else
|
|
||||||
throw_(compile_error, "Referencing parent node from the root node");
|
|
||||||
|
|
||||||
case document_t::ROOT:
|
|
||||||
return wrap_value(&context.document());
|
|
||||||
|
|
||||||
case document_t::ALL: {
|
|
||||||
value_t::sequence_t nodes;
|
|
||||||
foreach (node_t * node, context.as_parent_node())
|
|
||||||
nodes.push_back(node);
|
|
||||||
return wrap_value(nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break; // pass down to the NODE_NAME case
|
|
||||||
}
|
|
||||||
// fall through...
|
|
||||||
|
|
||||||
case NODE_NAME:
|
|
||||||
if (resolve) {
|
|
||||||
// First, look up the symbol as a node name within the current
|
|
||||||
// context. If any exist, then return the set of names.
|
|
||||||
|
|
||||||
if (context.is_parent_node()) {
|
|
||||||
value_t::sequence_t nodes;
|
|
||||||
|
|
||||||
foreach (node_t * node, context.as_parent_node()) {
|
|
||||||
if ((kind == NODE_NAME &&
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (optional<node_t::nameid_t> id =
|
|
||||||
context.document().lookup_name_id(as_string())) {
|
|
||||||
ptr_op_t node = new_node(NODE_ID);
|
|
||||||
node->set_name(*id);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
|
|
||||||
case ATTR_ID:
|
case ATTR_ID:
|
||||||
if (optional<const string&> value = context.get_attr(as_long()))
|
if (optional<const string&> value = context.get_attr(as_long()))
|
||||||
return wrap_value(*value);
|
return wrap_value(*value);
|
||||||
|
|
@ -1566,64 +1482,13 @@ xpath_t::op_t::compile(const node_t& context, scope_t * scope, bool resolve)
|
||||||
|
|
||||||
case O_FIND:
|
case O_FIND:
|
||||||
case O_RFIND:
|
case O_RFIND:
|
||||||
case O_PRED: {
|
case NODE_ID:
|
||||||
xpath_t lexpr(left()->compile(context, scope, resolve));
|
case NODE_NAME:
|
||||||
xpath_t rexpr(resolve ? right() : right()->compile(context, scope, false));
|
return wrap_value(path_t(ptr_op_t(this)).find_all(context, scope));
|
||||||
|
|
||||||
if (! lexpr.ptr->is_value() || ! resolve) {
|
case O_PRED:
|
||||||
if (left() == lexpr.ptr)
|
assert(false); // this should never occur by itself
|
||||||
return this;
|
|
||||||
else
|
|
||||||
return copy(lexpr.ptr, rexpr.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t::sequence_t result_seq;
|
|
||||||
|
|
||||||
// jww (2006-09-24): What about when nothing is found?
|
|
||||||
switch (lexpr.ptr->as_value().type()) {
|
|
||||||
case value_t::XML_NODE: {
|
|
||||||
value_t& value(lexpr.ptr->as_value());
|
|
||||||
function_scope_t xpath_fscope(*value.as_xml_node(), 0, 1, scope);
|
|
||||||
if (kind == O_PRED) {
|
|
||||||
if (rexpr.ptr->test_value(*value.as_xml_node(), &xpath_fscope))
|
|
||||||
result_seq.push_back(value);
|
|
||||||
} else {
|
|
||||||
rexpr.ptr->find_values(*value.as_xml_node(), &xpath_fscope,
|
|
||||||
result_seq, kind == O_RFIND);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::SEQUENCE: {
|
|
||||||
const value_t::sequence_t& seq(lexpr.ptr->as_value().as_sequence());
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
for (value_t::sequence_t::const_iterator i = seq.begin();
|
|
||||||
i != seq.end();
|
|
||||||
i++, index++) {
|
|
||||||
assert(! (*i).is_type(value_t::SEQUENCE));
|
|
||||||
if (! (*i).is_type(value_t::XML_NODE))
|
|
||||||
throw_(compile_error, "Attempting to apply path selection "
|
|
||||||
"to non-node(s)");
|
|
||||||
|
|
||||||
function_scope_t xpath_fscope(seq, *(*i).as_xml_node(), index, scope);
|
|
||||||
if (kind == O_PRED) {
|
|
||||||
if (rexpr.ptr->test_value(*(*i).as_xml_node(), &xpath_fscope, index))
|
|
||||||
result_seq.push_back(*i);
|
|
||||||
} else {
|
|
||||||
rexpr.ptr->find_values(*(*i).as_xml_node(), &xpath_fscope, result_seq,
|
|
||||||
kind == O_RFIND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw_(compile_error, "Attempting to apply path selection "
|
|
||||||
"to non-node(s)");
|
|
||||||
}
|
|
||||||
return wrap_value(result_seq);
|
|
||||||
}
|
|
||||||
|
|
||||||
case LAST:
|
case LAST:
|
||||||
default:
|
default:
|
||||||
|
|
@ -1763,6 +1628,7 @@ bool xpath_t::op_t::print(std::ostream& out,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case value_t::XML_NODE:
|
case value_t::XML_NODE:
|
||||||
|
case value_t::CONST_XML_NODE:
|
||||||
out << '<' << value << '>';
|
out << '<' << value << '>';
|
||||||
break;
|
break;
|
||||||
case value_t::POINTER:
|
case value_t::POINTER:
|
||||||
|
|
@ -2115,12 +1981,13 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xpath_t::path_t::check_element(node_t& start,
|
template <typename NodeType, typename FuncType>
|
||||||
|
void xpath_t::path_t::check_element(NodeType& start,
|
||||||
const ptr_op_t& element,
|
const ptr_op_t& element,
|
||||||
scope_t * scope,
|
scope_t * scope,
|
||||||
std::size_t index,
|
std::size_t index,
|
||||||
std::size_t size,
|
std::size_t size,
|
||||||
const visitor_t& func)
|
const FuncType& func)
|
||||||
{
|
{
|
||||||
if (element->kind > op_t::TERMINALS &&
|
if (element->kind > op_t::TERMINALS &&
|
||||||
element->left()->kind == op_t::O_PRED) {
|
element->left()->kind == op_t::O_PRED) {
|
||||||
|
|
@ -2132,15 +1999,16 @@ void xpath_t::path_t::check_element(node_t& start,
|
||||||
if (element->kind < op_t::TERMINALS)
|
if (element->kind < op_t::TERMINALS)
|
||||||
func(start);
|
func(start);
|
||||||
else
|
else
|
||||||
walk_elements(start, element->right(), element->kind == op_t::O_RFIND,
|
walk_elements<NodeType, FuncType>
|
||||||
scope, func);
|
(start, element->right(), element->kind == op_t::O_RFIND, scope, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xpath_t::path_t::walk_elements(node_t& start,
|
template <typename NodeType, typename FuncType>
|
||||||
|
void xpath_t::path_t::walk_elements(NodeType& start,
|
||||||
const ptr_op_t& element,
|
const ptr_op_t& element,
|
||||||
const bool recurse,
|
const bool recurse,
|
||||||
scope_t * scope,
|
scope_t * scope,
|
||||||
const visitor_t& func)
|
const FuncType& func)
|
||||||
{
|
{
|
||||||
ptr_op_t name(element->kind < op_t::TERMINALS ? element : element->left());
|
ptr_op_t name(element->kind < op_t::TERMINALS ? element : element->left());
|
||||||
if (name->kind == op_t::O_PRED)
|
if (name->kind == op_t::O_PRED)
|
||||||
|
|
@ -2205,5 +2073,39 @@ void xpath_t::path_t::walk_elements(node_t& start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
void xpath_t::path_t::walk_elements<node_t, xpath_t::path_t::visitor_t>
|
||||||
|
(node_t& start,
|
||||||
|
const ptr_op_t& element,
|
||||||
|
const bool recurse,
|
||||||
|
scope_t * scope,
|
||||||
|
const visitor_t& func);
|
||||||
|
|
||||||
|
template
|
||||||
|
void xpath_t::path_t::walk_elements<const node_t, xpath_t::path_t::const_visitor_t>
|
||||||
|
(const node_t& start,
|
||||||
|
const ptr_op_t& element,
|
||||||
|
const bool recurse,
|
||||||
|
scope_t * scope,
|
||||||
|
const const_visitor_t& func);
|
||||||
|
|
||||||
|
template
|
||||||
|
void xpath_t::path_t::check_element<node_t, xpath_t::path_t::visitor_t>
|
||||||
|
(node_t& start,
|
||||||
|
const ptr_op_t& element,
|
||||||
|
scope_t * scope,
|
||||||
|
std::size_t index,
|
||||||
|
std::size_t size,
|
||||||
|
const visitor_t& func);
|
||||||
|
|
||||||
|
template
|
||||||
|
void xpath_t::path_t::check_element<const node_t, xpath_t::path_t::const_visitor_t>
|
||||||
|
(const node_t& start,
|
||||||
|
const ptr_op_t& element,
|
||||||
|
scope_t * scope,
|
||||||
|
std::size_t index,
|
||||||
|
std::size_t size,
|
||||||
|
const const_visitor_t& func);
|
||||||
|
|
||||||
} // namespace xml
|
} // namespace xml
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
88
src/xpath.h
88
src/xpath.h
|
|
@ -217,7 +217,9 @@ public:
|
||||||
class path_t
|
class path_t
|
||||||
{
|
{
|
||||||
typedef function<void (node_t&)> visitor_t;
|
typedef function<void (node_t&)> visitor_t;
|
||||||
typedef function<bool (node_t&, scope_t *)> predicate_t;
|
typedef function<void (const node_t&)> const_visitor_t;
|
||||||
|
|
||||||
|
typedef function<bool (const node_t&, scope_t *)> predicate_t;
|
||||||
|
|
||||||
struct value_node_appender_t {
|
struct value_node_appender_t {
|
||||||
value_t::sequence_t& sequence;
|
value_t::sequence_t& sequence;
|
||||||
|
|
@ -228,36 +230,59 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct const_value_node_appender_t {
|
||||||
|
value_t::sequence_t& sequence;
|
||||||
|
const_value_node_appender_t(value_t::sequence_t& _sequence)
|
||||||
|
: sequence(_sequence) {}
|
||||||
|
void operator()(const node_t& node) {
|
||||||
|
sequence.push_back(&node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ptr_op_t path_expr;
|
ptr_op_t path_expr;
|
||||||
|
|
||||||
|
template <typename NodeType, typename FuncType>
|
||||||
|
void walk_elements(NodeType& start,
|
||||||
|
const ptr_op_t& element,
|
||||||
|
const bool recurse,
|
||||||
|
scope_t * scope,
|
||||||
|
const FuncType& func);
|
||||||
|
|
||||||
|
template <typename NodeType, typename FuncType>
|
||||||
|
void check_element(NodeType& start,
|
||||||
|
const ptr_op_t& element,
|
||||||
|
scope_t * scope,
|
||||||
|
std::size_t index,
|
||||||
|
std::size_t size,
|
||||||
|
const FuncType& func);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
path_t(const xpath_t& xpath) : path_expr(xpath.ptr) {}
|
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 find_all(node_t& start, scope_t * scope) {
|
||||||
value_t result = value_t::sequence_t();
|
value_t result = value_t::sequence_t();
|
||||||
visit(start, scope, value_node_appender_t(result.as_sequence_lval()));
|
visit(start, scope, value_node_appender_t(result.as_sequence_lval()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
value_t find_all(const node_t& start, scope_t * scope) {
|
||||||
void visit(node_t& start, scope_t * scope,
|
value_t result = value_t::sequence_t();
|
||||||
const function<void (node_t&)>& func) {
|
visit(start, scope,
|
||||||
if (path_expr)
|
const_value_node_appender_t(result.as_sequence_lval()));
|
||||||
walk_elements(start, path_expr, false, scope, func);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void visit(node_t& start, scope_t * scope, const visitor_t& func) {
|
||||||
void walk_elements(node_t& start,
|
if (path_expr)
|
||||||
const ptr_op_t& element,
|
walk_elements<node_t, visitor_t>
|
||||||
const bool recurse,
|
(start, path_expr, false, scope, func);
|
||||||
scope_t * scope,
|
}
|
||||||
const visitor_t& func);
|
void visit(const node_t& start, scope_t * scope,
|
||||||
|
const const_visitor_t& func) {
|
||||||
void check_element(node_t& start,
|
if (path_expr)
|
||||||
const ptr_op_t& element,
|
walk_elements<const node_t, const_visitor_t>
|
||||||
scope_t * scope,
|
(start, path_expr, false, scope, func);
|
||||||
std::size_t index,
|
}
|
||||||
std::size_t size,
|
|
||||||
const visitor_t& func);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class path_iterator_t
|
class path_iterator_t
|
||||||
|
|
@ -523,10 +548,6 @@ public:
|
||||||
ptr_op_t copy(ptr_op_t left = NULL, ptr_op_t right = NULL) const;
|
ptr_op_t copy(ptr_op_t left = NULL, ptr_op_t right = NULL) const;
|
||||||
ptr_op_t compile(const node_t& context, scope_t * scope, bool resolve = false);
|
ptr_op_t compile(const node_t& context, scope_t * scope, bool resolve = false);
|
||||||
|
|
||||||
void find_values(const node_t& context, scope_t * scope,
|
|
||||||
value_t::sequence_t& result_seq, bool recursive);
|
|
||||||
bool test_value(const node_t& context, scope_t * scope, int index = 0);
|
|
||||||
|
|
||||||
void append_value(value_t::sequence_t& result_seq, value_t& value);
|
void append_value(value_t::sequence_t& result_seq, value_t& value);
|
||||||
|
|
||||||
static ptr_op_t defer_sequence(value_t::sequence_t& result_seq);
|
static ptr_op_t defer_sequence(value_t::sequence_t& result_seq);
|
||||||
|
|
@ -539,16 +560,22 @@ public:
|
||||||
unsigned long * end_pos = NULL) const;
|
unsigned long * end_pos = NULL) 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) {
|
||||||
|
op->acquire();
|
||||||
|
}
|
||||||
|
friend inline void intrusive_ptr_release(xpath_t::op_t * op) {
|
||||||
|
op->release();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class op_predicate
|
class op_predicate
|
||||||
{
|
{
|
||||||
ptr_op_t op;
|
ptr_op_t op;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
op_predicate(ptr_op_t _op) : op(_op) {}
|
op_predicate(ptr_op_t _op) : op(_op) {}
|
||||||
|
|
||||||
bool operator()(node_t& node, scope_t * scope) {
|
bool operator()(const node_t& node, scope_t * scope) {
|
||||||
xpath_t result(op->compile(node, scope, true));
|
xpath_t result(op->compile(node, scope, true));
|
||||||
return result.ptr->as_value().to_boolean();
|
return result.ptr->as_value().to_boolean();
|
||||||
}
|
}
|
||||||
|
|
@ -746,19 +773,12 @@ public:
|
||||||
friend class scope_t;
|
friend class scope_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
} // namespace xml
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
||||||
assert(locals->args.size() > idx);
|
assert(locals->args.size() > idx);
|
||||||
T * ptr = static_cast<T *>(locals->args[idx].as_pointer());
|
T * ptr = locals->args[idx].as_pointer<T>();
|
||||||
assert(ptr);
|
assert(ptr);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
@ -766,7 +786,7 @@ inline T * get_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T * get_node_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
inline T * get_node_ptr(xml::xpath_t::scope_t * locals, unsigned int idx) {
|
||||||
assert(locals->args.size() > idx);
|
assert(locals->args.size() > idx);
|
||||||
T * ptr = polymorphic_downcast<T *>(locals->args[idx].as_xml_node());
|
T * ptr = polymorphic_downcast<T *>(locals->args[idx].as_xml_node_mutable());
|
||||||
assert(ptr);
|
assert(ptr);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue