diff options
author | John Wiegley <johnw@newartisans.com> | 2007-05-16 05:38:32 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:52 -0400 |
commit | 7c7e5c5e367778c6d54a1bb2be2db5c73db0492b (patch) | |
tree | 16ed5bde7719aa10b4d7cde25eaaf2ea64fa7f80 /src/xpath.cc | |
parent | 74ecceb2ba0cb1592f570bcb52619f882c15bd27 (diff) | |
download | fork-ledger-7c7e5c5e367778c6d54a1bb2be2db5c73db0492b.tar.gz fork-ledger-7c7e5c5e367778c6d54a1bb2be2db5c73db0492b.tar.bz2 fork-ledger-7c7e5c5e367778c6d54a1bb2be2db5c73db0492b.zip |
Now using xpath_t::path_t to select nodes.
Diffstat (limited to 'src/xpath.cc')
-rw-r--r-- | src/xpath.cc | 214 |
1 files changed, 58 insertions, 156 deletions
diff --git a/src/xpath.cc b/src/xpath.cc index b96df49d..3799e260 100644 --- a/src/xpath.cc +++ b/src/xpath.cc @@ -1044,39 +1044,6 @@ xpath_t::op_t::copy(ptr_op_t tleft, ptr_op_t tright) const 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) { // 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(); } - if (! (*i).is_type(value_t::POINTER)) + if (! (*i).is_pointer()) *opp = wrap_value(*i); else #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) { - if (val.is_type(value_t::SEQUENCE)) + if (val.is_sequence()) std::for_each(val.as_sequence().begin(), val.as_sequence().end(), bind(&value_t::sequence_t::push_back, ref(result_seq), _1)); else @@ -1134,57 +1101,6 @@ xpath_t::op_t::compile(const node_t& context, scope_t * scope, bool resolve) case VALUE: 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: if (optional<const string&> value = context.get_attr(as_long())) 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_RFIND: - case O_PRED: { - xpath_t lexpr(left()->compile(context, scope, resolve)); - xpath_t rexpr(resolve ? right() : right()->compile(context, scope, false)); - - if (! lexpr.ptr->is_value() || ! resolve) { - if (left() == lexpr.ptr) - return this; - else - return copy(lexpr.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; - } - - 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; - } + case NODE_ID: + case NODE_NAME: + return wrap_value(path_t(ptr_op_t(this)).find_all(context, scope)); - default: - throw_(compile_error, "Attempting to apply path selection " - "to non-node(s)"); - } - return wrap_value(result_seq); - } + case O_PRED: + assert(false); // this should never occur by itself + break; case LAST: default: @@ -1763,6 +1628,7 @@ bool xpath_t::op_t::print(std::ostream& out, break; case value_t::XML_NODE: + case value_t::CONST_XML_NODE: out << '<' << value << '>'; break; 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, - const ptr_op_t& element, - scope_t * scope, - std::size_t index, - std::size_t size, - const visitor_t& func) +template <typename NodeType, typename FuncType> +void xpath_t::path_t::check_element(NodeType& start, + const ptr_op_t& element, + scope_t * scope, + std::size_t index, + std::size_t size, + const FuncType& func) { if (element->kind > op_t::TERMINALS && 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) func(start); else - walk_elements(start, element->right(), element->kind == op_t::O_RFIND, - scope, func); + walk_elements<NodeType, FuncType> + (start, element->right(), element->kind == op_t::O_RFIND, scope, 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) +template <typename NodeType, typename FuncType> +void xpath_t::path_t::walk_elements(NodeType& start, + const ptr_op_t& element, + const bool recurse, + scope_t * scope, + const FuncType& func) { ptr_op_t name(element->kind < op_t::TERMINALS ? element : element->left()); 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 ledger |