diff options
-rw-r--r-- | src/pyinterp.h | 1 | ||||
-rw-r--r-- | src/xpath.cc | 159 | ||||
-rw-r--r-- | src/xpath.h | 47 | ||||
-rw-r--r-- | tests/numerics/t_amount.cc | 10 |
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); |