summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pyinterp.h1
-rw-r--r--src/xpath.cc159
-rw-r--r--src/xpath.h47
-rw-r--r--tests/numerics/t_amount.cc10
4 files changed, 76 insertions, 141 deletions
diff --git a/src/pyinterp.h b/src/pyinterp.h
index a8f4784f..2258c6c0 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -75,6 +75,7 @@ class python_interpreter_t : public xml::xpath_t::scope_t
boost::python::object func;
public:
functor_t(const string& name, boost::python::object _func) : func(_func) {}
+ virtual ~functor_t() {}
virtual value_t operator()(xml::xpath_t::scope_t * locals);
};
diff --git a/src/xpath.cc b/src/xpath.cc
index 2a9ec1e5..b96df49d 100644
--- a/src/xpath.cc
+++ b/src/xpath.cc
@@ -689,7 +689,7 @@ xpath_t::parse_path_expr(std::istream& in, flags_t tflags) const
if (node) {
token_t& tok = next_token(in, tflags);
- while (tok.kind == token_t::SLASH) {
+ if (tok.kind == token_t::SLASH) {
ptr_op_t prev(node);
tok = next_token(in, tflags);
@@ -699,14 +699,12 @@ xpath_t::parse_path_expr(std::istream& in, flags_t tflags) const
push_token(tok);
node->set_left(prev);
- node->set_right(parse_predicate_expr(in, tflags));
+ node->set_right(parse_path_expr(in, tflags));
if (! node->right())
throw_(parse_error, "/ operator not followed by a valid term");
-
- tok = next_token(in, tflags);
+ } else {
+ push_token(tok);
}
-
- push_token(tok);
}
return node;
@@ -2117,101 +2115,40 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const
}
}
-xpath_t::path_t::path_t(const xpath_t& path_expr)
-{
- ptr_op_t op = path_expr.ptr;
-
- while (true) {
- element_t element;
-
- switch (op->kind) {
- case op_t::O_RFIND:
- element.recurse = true;
- // fall through...
- case op_t::O_FIND: {
- ptr_op_t name;
- if (op->right()->kind == op_t::O_PRED) {
- element.predicate = op_predicate(op->right()->right());
- name = op->right()->left();
- } else {
- name = op->right();
- }
-
- switch (name->kind) {
- case op_t::NODE_ID: {
- //case op_t::ATTR_ID:
- node_t::nameid_t name_id = name->as_name();
- if (name_id < document_t::LAST_BUILTIN)
- element.ident = document_t::special_names_t(name_id);
- else
- element.ident = name_id;
- break;
- }
- case op_t::NODE_NAME:
- //case op_t::ATTR_NAME:
- element.ident = name->as_string();
- break;
- default:
- break;
- }
- break;
- }
-
- case op_t::NODE_ID: {
- //case op_t::ATTR_ID:
- node_t::nameid_t name_id = op->as_name();
- if (name_id < document_t::LAST_BUILTIN)
- element.ident = document_t::special_names_t(name_id);
- else
- element.ident = name_id;
- break;
- }
- case op_t::NODE_NAME:
- //case op_t::ATTR_NAME:
- element.ident = op->as_string();
- break;
-
- default:
- throw_(std::logic_error, "XPath expression is not strictly a path selection");
- break;
- }
-
- elements.push_front(element);
-
- if (op->kind < op_t::TERMINALS)
- break;
- else
- op = op->left();
- }
-}
-
-void xpath_t::path_t::check_element(node_t& start,
- const element_iterator& element,
- scope_t * scope,
- std::size_t index,
- std::size_t size,
- const visitor_t& func)
+void xpath_t::path_t::check_element(node_t& start,
+ const ptr_op_t& element,
+ scope_t * scope,
+ std::size_t index,
+ std::size_t size,
+ const visitor_t& func)
{
- if (element->predicate) {
+ if (element->kind > op_t::TERMINALS &&
+ element->left()->kind == op_t::O_PRED) {
function_scope_t xpath_fscope(start, index, size, scope);
- if (! element->predicate(start, &xpath_fscope))
+ if (! op_predicate(element->left()->right())(start, &xpath_fscope))
return;
}
- element_iterator next_element = next(element);
- if (next_element == elements.end())
+ if (element->kind < op_t::TERMINALS)
func(start);
else
- walk_elements(start, next_element, scope, func);
+ walk_elements(start, element->right(), element->kind == op_t::O_RFIND,
+ scope, func);
}
-void xpath_t::path_t::walk_elements(node_t& start,
- const element_iterator& element,
- scope_t * scope,
- const visitor_t& func)
+void xpath_t::path_t::walk_elements(node_t& start,
+ const ptr_op_t& element,
+ const bool recurse,
+ scope_t * scope,
+ const visitor_t& func)
{
- if (element->ident.type() == typeid(document_t::special_names_t)) {
- switch (boost::get<document_t::special_names_t>(element->ident)) {
+ ptr_op_t name(element->kind < op_t::TERMINALS ? element : element->left());
+ if (name->kind == op_t::O_PRED)
+ name = name->left();
+
+ switch (name->kind) {
+ case op_t::NODE_ID:
+ switch (name->as_name()) {
case document_t::CURRENT:
check_element(start, element, scope, 0, 1, func);
break;
@@ -2239,24 +2176,32 @@ void xpath_t::path_t::walk_elements(node_t& start,
}
default:
- assert(false);
- break;
+ break; // pass down to the NODE_NAME case
}
- }
- else if (start.is_parent_node()) {
- bool have_name_id = element->ident.type() == typeid(node_t::nameid_t);
-
- std::size_t index = 0;
- std::size_t size = start.as_parent_node().size();
- foreach (node_t * child, start.as_parent_node()) {
- if ((have_name_id &&
- boost::get<node_t::nameid_t>(element->ident) == child->name_id()) ||
- (! have_name_id &&
- boost::get<string>(element->ident) == child->name()))
- check_element(*child, element, scope, index++, size, func);
- else if (element->recurse)
- walk_elements(*child, element, scope, func);
+ // fall through...
+
+ case op_t::NODE_NAME:
+ if (start.is_parent_node()) {
+ bool have_name_id = name->kind == op_t::NODE_ID;
+
+ std::size_t index = 0;
+ std::size_t size = start.as_parent_node().size();
+ foreach (node_t * child, start.as_parent_node()) {
+ if ((have_name_id && name->as_name() == child->name_id()) ||
+ (! have_name_id && name->as_string() == child->name()))
+ check_element(*child, element, scope, index++, size, func);
+ else if (recurse)
+ walk_elements(*child, element, recurse, scope, func);
+ }
}
+ break;
+
+ default:
+ // jww (2007-05-15): Instead of a name, this might be an
+ // expression resulting in a nodelist with respect to the current
+ // context.
+ throw_(std::logic_error, "XPath expression is not strictly a path selection");
+ break;
}
}
diff --git a/src/xpath.h b/src/xpath.h
index 0bb234a5..1838a6e2 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -219,19 +219,6 @@ public:
typedef function<void (node_t&)> visitor_t;
typedef function<bool (node_t&, scope_t *)> predicate_t;
- struct element_t
- {
- variant<node_t::nameid_t, string,
- document_t::special_names_t> ident;
-
- bool recurse;
- predicate_t predicate;
- };
-
- std::list<element_t> elements;
-
- typedef std::list<element_t>::const_iterator element_iterator;
-
struct value_node_appender_t {
value_t::sequence_t& sequence;
value_node_appender_t(value_t::sequence_t& _sequence)
@@ -241,34 +228,36 @@ public:
}
};
+ ptr_op_t path_expr;
+
public:
- path_t(const xpath_t& path_expr);
+ path_t(const xpath_t& xpath) : path_expr(xpath.ptr) {}
value_t find_all(node_t& start, scope_t * scope) {
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;
}
void visit(node_t& start, scope_t * scope,
const function<void (node_t&)>& func) {
- if (elements.begin() != elements.end())
- walk_elements(start, elements.begin(), scope, func);
+ if (path_expr)
+ walk_elements(start, path_expr, false, scope, func);
}
private:
- void walk_elements(node_t& start,
- const element_iterator& element,
- scope_t * scope,
- const visitor_t& func);
-
- void check_element(node_t& start,
- const element_iterator& element,
- scope_t * scope,
- std::size_t index,
- std::size_t size,
- const visitor_t& func);
+ void walk_elements(node_t& start,
+ const ptr_op_t& element,
+ const bool recurse,
+ scope_t * scope,
+ const visitor_t& func);
+
+ void check_element(node_t& start,
+ const ptr_op_t& element,
+ scope_t * scope,
+ std::size_t index,
+ std::size_t size,
+ const visitor_t& func);
};
class path_iterator_t
diff --git a/tests/numerics/t_amount.cc b/tests/numerics/t_amount.cc
index a70959a4..a47e9bb3 100644
--- a/tests/numerics/t_amount.cc
+++ b/tests/numerics/t_amount.cc
@@ -357,10 +357,10 @@ void AmountTestCase::testCommodityEquality()
assertTrue(x0.is_null());
assertThrow(x0.is_zero(), amount_error);
assertThrow(x0.is_realzero(), amount_error);
- assertThrow(x0.sign() == 0, amount_error);
- assertThrow(x0.compare(x1) < 0, amount_error);
- assertThrow(x0.compare(x2) > 0, amount_error);
- assertThrow(x0.compare(x0) == 0, amount_error);
+ assertThrow(assert(x0.sign() == 0), amount_error);
+ assertThrow(assert(x0.compare(x1) < 0), amount_error);
+ assertThrow(assert(x0.compare(x2) > 0), amount_error);
+ assertThrow(assert(x0.compare(x0) == 0), amount_error);
assertTrue(x1 != x2);
assertTrue(x1 != x4);
@@ -1311,7 +1311,7 @@ void AmountTestCase::testTruth()
amount_t x1("1234");
amount_t x2("1234.56");
- assertThrow(x0 ? 1 : 0, amount_error);
+ assertThrow(assert(x0 ? 1 : 0), amount_error);
assertTrue(x1);
assertTrue(x2);