From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- axiom/src/xpath/Makefile.am | 22 + axiom/src/xpath/xpath.c | 462 ++++++++++ axiom/src/xpath/xpath_functions.c | 46 + axiom/src/xpath/xpath_functions.h | 47 + axiom/src/xpath/xpath_internals.c | 38 + axiom/src/xpath/xpath_internals.h | 199 +++++ axiom/src/xpath/xpath_internals_engine.c | 1203 ++++++++++++++++++++++++++ axiom/src/xpath/xpath_internals_engine.h | 265 ++++++ axiom/src/xpath/xpath_internals_iterators.c | 588 +++++++++++++ axiom/src/xpath/xpath_internals_iterators.h | 298 +++++++ axiom/src/xpath/xpath_internals_parser.c | 1245 +++++++++++++++++++++++++++ axiom/src/xpath/xpath_internals_parser.h | 421 +++++++++ axiom/src/xpath/xpath_streaming.c | 213 +++++ axiom/src/xpath/xpath_streaming.h | 126 +++ 14 files changed, 5173 insertions(+) create mode 100644 axiom/src/xpath/Makefile.am create mode 100755 axiom/src/xpath/xpath.c create mode 100755 axiom/src/xpath/xpath_functions.c create mode 100755 axiom/src/xpath/xpath_functions.h create mode 100755 axiom/src/xpath/xpath_internals.c create mode 100755 axiom/src/xpath/xpath_internals.h create mode 100644 axiom/src/xpath/xpath_internals_engine.c create mode 100755 axiom/src/xpath/xpath_internals_engine.h create mode 100644 axiom/src/xpath/xpath_internals_iterators.c create mode 100755 axiom/src/xpath/xpath_internals_iterators.h create mode 100755 axiom/src/xpath/xpath_internals_parser.c create mode 100755 axiom/src/xpath/xpath_internals_parser.h create mode 100755 axiom/src/xpath/xpath_streaming.c create mode 100755 axiom/src/xpath/xpath_streaming.h (limited to 'axiom/src/xpath') diff --git a/axiom/src/xpath/Makefile.am b/axiom/src/xpath/Makefile.am new file mode 100644 index 0000000..5d4f42f --- /dev/null +++ b/axiom/src/xpath/Makefile.am @@ -0,0 +1,22 @@ +lib_LTLIBRARIES = libaxis2_xpath.la +libaxis2_xpath_la_SOURCES = xpath.c \ + xpath_functions.c \ + xpath_internals.c \ + xpath_internals_engine.c \ + xpath_internals_iterators.c \ + xpath_internals_parser.c \ + xpath_streaming.c + +libaxis2_xpath_la_LDFLAGS = -version-info $(VERSION_NO) + +libaxis2_xpath_la_LIBADD = +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/parser \ + -I$(top_builddir)/src/om \ + -I ../../../util/include \ + -I ../../../include + +EXTRA_DIST = xpath_functions.h xpath_internals_engine.h \ + xpath_internals.h xpath_internals_iterators.h \ + xpath_internals_parser.h xpath_streaming.h + diff --git a/axiom/src/xpath/xpath.c b/axiom/src/xpath/xpath.c new file mode 100755 index 0000000..38f422c --- /dev/null +++ b/axiom/src/xpath/xpath.c @@ -0,0 +1,462 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_internals.h" +#include "xpath_internals_parser.h" +#include "xpath_internals_engine.h" +#include "xpath_functions.h" +#include "xpath_streaming.h" + +/* Create XPath context */ +AXIS2_EXTERN axiom_xpath_context_t * AXIS2_CALL +axiom_xpath_context_create( + const axutil_env_t *env, + axiom_node_t * root_node) +{ + axiom_xpath_context_t* context; + + /*HACK: xpath impl requires a dummy root node in order to process properly.*/ + axiom_node_t * dummy_root; + dummy_root = axiom_node_create(env); + axiom_node_add_child(dummy_root, env, root_node); + + context = AXIS2_MALLOC(env->allocator, + sizeof(axiom_xpath_context_t)); + + context->env = env; + context->root_node = dummy_root; + context->node = dummy_root; + context->expr = NULL; + context->attribute = NULL; + context->namespaces = NULL; + context->functions = NULL; + + axiom_xpath_register_default_functions_set(context); + + return context; +} + +/* Compile XPath expression */ +AXIS2_EXTERN axiom_xpath_expression_t * AXIS2_CALL +axiom_xpath_compile_expression( + const axutil_env_t *env, + const axis2_char_t* xpath_expr) +{ + axiom_xpath_expression_t* expr; + + expr = AXIS2_MALLOC(env->allocator, + sizeof(axiom_xpath_expression_t)); + + expr->expr_str = axutil_strdup(env, xpath_expr); + + if (axiom_xpath_compile(env, expr) == AXIOM_XPATH_PARSE_ERROR) + { + AXIS2_FREE(env->allocator, expr->expr_str); + AXIS2_FREE(env->allocator, expr); + + return NULL; + } + else + { + return expr; + } +} + +/* Evaluate compiled XPath expression */ +AXIS2_EXTERN axiom_xpath_result_t * AXIS2_CALL +axiom_xpath_evaluate( + axiom_xpath_context_t *context, + axiom_xpath_expression_t *xpath_expr) +{ + axiom_xpath_expression_copy(context, xpath_expr); + + context->streaming = AXIS2_FALSE; + + return axiom_xpath_run(context); +} + +AXIS2_EXTERN axiom_xpath_result_t * AXIS2_CALL +axiom_xpath_evaluate_streaming( + axiom_xpath_context_t *context, + axiom_xpath_expression_t *xpath_expr) +{ + axiom_xpath_result_t *res; + + axiom_xpath_expression_copy(context, xpath_expr); + + if (axiom_xpath_streaming_check(context->env, xpath_expr)) + { + context->streaming = AXIS2_TRUE; + return axiom_xpath_run(context); + } + else + { + res = AXIS2_MALLOC( + context->env->allocator, sizeof(axiom_xpath_result_t)); + res->nodes = NULL; + res->flag = AXIOM_XPATH_ERROR_STREAMING_NOT_SUPPORTED; + + return res; + } +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_register_default_functions_set( + axiom_xpath_context_t *context) +{ + axiom_xpath_register_function( + context, "count", axiom_xpath_function_count); +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_register_function( + axiom_xpath_context_t *context, + axis2_char_t *name, + axiom_xpath_function_t func) +{ + if (name && func) + { + if (!context->functions) + { + context->functions = axutil_hash_make(context->env); + } + + axutil_hash_set(context->functions, name, AXIS2_HASH_KEY_STRING, func); + } +} + +AXIS2_EXTERN axiom_xpath_function_t AXIS2_CALL +axiom_xpath_get_function( + axiom_xpath_context_t *context, + axis2_char_t *name) +{ + axiom_xpath_function_t func = NULL; + + if(context->functions) + { + func = axutil_hash_get(context->functions, name, AXIS2_HASH_KEY_STRING); + } + + return func; +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_register_namespace( + axiom_xpath_context_t *context, + axiom_namespace_t *ns) +{ + axis2_char_t *prefix = NULL; + + if (!context->namespaces) + { + context->namespaces = axutil_hash_make(context->env); + } + + prefix = axiom_namespace_get_prefix(ns, context->env); + + if (prefix) + { + axutil_hash_set( + context->namespaces, prefix, AXIS2_HASH_KEY_STRING, ns); + } +} + +AXIS2_EXTERN axiom_namespace_t * AXIS2_CALL +axiom_xpath_get_namespace( + axiom_xpath_context_t *context, + axis2_char_t *prefix) +{ + axiom_namespace_t *ns = NULL; + + if (context->namespaces) + { + ns = axutil_hash_get(context->namespaces, prefix, AXIS2_HASH_KEY_STRING); + } + + return ns; +} + +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_clear_namespaces( + axiom_xpath_context_t *context) +{ + axutil_hash_index_t *hi; + void *val; + + if (context->namespaces) + { + for (hi = axutil_hash_first(context->namespaces, context->env); + hi; + hi = axutil_hash_next(context->env, hi)) + { + axutil_hash_this(hi, NULL, NULL, &val); + axiom_namespace_free((axiom_namespace_t *)val, context->env); + } + + axutil_hash_free(context->namespaces, context->env); + } + + context->namespaces = NULL; +} + +/* Cast to boolean */ +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axiom_xpath_cast_node_to_boolean( + const axutil_env_t *env, + axiom_xpath_result_node_t * node) +{ + if(node->type == AXIOM_XPATH_TYPE_BOOLEAN) + { + return *(axis2_bool_t *)node->value; + } + else if(node->type == AXIOM_XPATH_TYPE_NUMBER) + { + /* Cannot evaluate as *(double *)(node->value) == 1e-12 + since there might be an precision error */ + if(*(double *)(node->value) > 1e-12 || *(double *)(node->value) < -1e-12) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + else if(node->value) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } +} + +/* Cast to double */ +AXIS2_EXTERN double AXIS2_CALL +axiom_xpath_cast_node_to_number( + const axutil_env_t *env, + axiom_xpath_result_node_t * node) +{ + if (node->type == AXIOM_XPATH_TYPE_BOOLEAN) + { + if (*(axis2_bool_t *)(node->value) == AXIS2_TRUE) + { + return 1.0; + } + else + { + return 0.0; + } + } + else if (node->type == AXIOM_XPATH_TYPE_NUMBER) + { + return *(double *)node->value; + } + else if (node->value) + { + return 1.0; + } + else + { + return 0.0; + } +} + +/* Cast to text */ +AXIS2_EXTERN axis2_char_t * AXIS2_CALL +axiom_xpath_cast_node_to_string( + const axutil_env_t *env, + axiom_xpath_result_node_t * node) +{ + axiom_element_t *ele; + axis2_char_t *res; + + if (!node->value) + { + return NULL; + } + + if (node->type == AXIOM_XPATH_TYPE_BOOLEAN) + { + if (*(axis2_bool_t *)(node->value) == AXIS2_TRUE) + { + return axutil_strdup(env, "true"); + } + else + { + return axutil_strdup(env, "false"); + } + } + else if (node->type == AXIOM_XPATH_TYPE_NUMBER) + { + /* Allocate 50 bytes */ + res = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 50); + + sprintf(res, "%lf", *(double *)(node->value)); + + return res; + } + else if (node->type == AXIOM_XPATH_TYPE_TEXT) + { + return (axis2_char_t *)node->value; + } + else if (node->type == AXIOM_XPATH_TYPE_NODE) + { + ele = (axiom_element_t *)axiom_node_get_data_element( + (axiom_node_t *)(node->value), env); + + if (ele) + { + return axiom_element_get_text( + ele, env, (axiom_node_t *)(node->value)); + } + else + { + return NULL; + } + } + else if (node->type == AXIOM_XPATH_TYPE_ATTRIBUTE) + { + return axiom_attribute_get_value( + (axiom_attribute_t *)(node->value), env); + } + else if (node->type == AXIOM_XPATH_TYPE_NAMESPACE) + { + return axiom_namespace_get_prefix( + (axiom_namespace_t *)(node->value), env); + } + + return NULL; +} + +/* Cast to axiom node */ +AXIS2_EXTERN axiom_node_t * AXIS2_CALL +axiom_xpath_cast_node2axiom_node( + const axutil_env_t *env, + axiom_xpath_result_node_t * node) +{ + if (node->type == AXIOM_XPATH_TYPE_NODE && node->value) + { + return (axiom_node_t *)node->value; + } + else + { + return NULL; + } +} + +/* Free context */ +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_free_context( + const axutil_env_t *env, + axiom_xpath_context_t *context) +{ + if (context) + { + /* Free the expression if not freed */ + if (context->expr) + { + /* axiom_xpath_free_expression(env, context->expr); */ + + context->expr = NULL; + } + + if (context->root_node) + { + axiom_node_detach(axiom_node_get_first_child(context->root_node, context->env), context->env); + axiom_node_free_tree(context->root_node, context->env); + context->root_node = NULL; + } + + if (context->functions) + { + axutil_hash_free(context->functions, context->env); + context->functions = NULL; + } + + if(context->namespaces) + { + axiom_xpath_clear_namespaces(context); + context->namespaces = NULL; + } + + AXIS2_FREE(env->allocator, context); + } +} + +/* Free expression */ +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_free_expression( + const axutil_env_t *env, + axiom_xpath_expression_t * xpath_expr) +{ + if (xpath_expr) + { + if (xpath_expr->expr_str) + { + AXIS2_FREE(env->allocator, xpath_expr->expr_str); + + xpath_expr->expr_str = NULL; + } + + if (xpath_expr->operations) + { + axutil_array_list_free(xpath_expr->operations, env); + xpath_expr->operations = NULL; + } + + AXIS2_FREE(env->allocator, xpath_expr); + } +} + +/* Free result set */ +AXIS2_EXTERN void AXIS2_CALL +axiom_xpath_free_result( + const axutil_env_t *env, + axiom_xpath_result_t* result) +{ + if (result) + { + if (result->nodes) + { + axutil_array_list_free(result->nodes, env); + } + + AXIS2_FREE(env->allocator, result); + } +} + +/* Check if the expression can be evaluated on streaming XML */ +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axiom_xpath_streaming_check( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + axiom_xpath_streaming_t r = AXIOM_XPATH_CHECK(expr->start); + + if(r == AXIOM_XPATH_STREAMING_NOT_SUPPORTED) + { + return AXIS2_FALSE; + } + else + { + return AXIS2_TRUE; + } +} + diff --git a/axiom/src/xpath/xpath_functions.c b/axiom/src/xpath/xpath_functions.c new file mode 100755 index 0000000..bdf65c2 --- /dev/null +++ b/axiom/src/xpath/xpath_functions.c @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_functions.h" +#include "xpath_internals_engine.h" + +int +axiom_xpath_function_count( + axiom_xpath_context_t *context, + int np) +{ + axiom_xpath_result_node_t *node; + double * v; + int i; + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + v = AXIS2_MALLOC(context->env->allocator, sizeof(double)); + + *v = np; + node->value = v; + node->type = AXIOM_XPATH_TYPE_NUMBER; + + for(i = 0; i < np; i++) + { + axutil_stack_pop(context->stack, context->env); + } + + axutil_stack_push(context->stack, context->env, node); + + return 1; +} diff --git a/axiom/src/xpath/xpath_functions.h b/axiom/src/xpath/xpath_functions.h new file mode 100755 index 0000000..d44f0a2 --- /dev/null +++ b/axiom/src/xpath/xpath_functions.h @@ -0,0 +1,47 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIOM_XPATH_FUNCTIONS_H +#define AXIOM_XPATH_FUNCTIONS_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @defgroup axiom_xpath_functions functions + * @ingroup axiom_xpath + * @{ + */ + + /** + * count(node-set) function + * http://www.w3.org/TR/xpath#function-count + */ + int axiom_xpath_function_count(axiom_xpath_context_t *context, int np); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/axiom/src/xpath/xpath_internals.c b/axiom/src/xpath/xpath_internals.c new file mode 100755 index 0000000..c313baf --- /dev/null +++ b/axiom/src/xpath/xpath_internals.c @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_internals.h" + +/* Make a copy of the xpath expression */ +void +axiom_xpath_expression_copy( + axiom_xpath_context_t *context, + axiom_xpath_expression_t* expr) +{ + int i; + axiom_xpath_operation_t *op; + + context->expr = expr; + + /* Set value of pos in every operation to 0 */ + for(i = 0; i < axutil_array_list_size(expr->operations, context->env); i++) + { + op = AXIOM_XPATH_OPR_GET(i); + op->pos = 0; + } +} diff --git a/axiom/src/xpath/xpath_internals.h b/axiom/src/xpath/xpath_internals.h new file mode 100755 index 0000000..891d543 --- /dev/null +++ b/axiom/src/xpath/xpath_internals.h @@ -0,0 +1,199 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIOM_XPATH_INTERNALS_H +#define AXIOM_XPATH_INTERNALS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @defgroup axiom_xpath_internals internals + * @ingroup axiom_xpath + * @{ + */ + + + /** Get operation at index ind */ +#define AXIOM_XPATH_OPR_GET(ind) (axiom_xpath_operation_t *) \ + axutil_array_list_get(context->expr->operations, context->env, ind) + + /** + * An error has occured while parsing + */ +#define AXIOM_XPATH_PARSE_ERROR -2 + + /** + * XPath expression was successfully compiled + */ +#define AXIOM_XPATH_PARSE_SUCCESS 0 + + /** + * End of expression reached + */ +#define AXIOM_XPATH_PARSE_END -1 + + /* Types */ + + /** + * XPath operation + * Contains the operands and parameters + */ + typedef struct axiom_xpath_operation axiom_xpath_operation_t; + + /** + * XPath node test + * Stores the components of a node test + */ + typedef struct axiom_xpath_node_test axiom_xpath_node_test_t; + + /** + * Functions to process a XPath operator + */ + typedef int (*axiom_xpath_operator_t)(axiom_xpath_context_t *context, + axiom_xpath_operation_t * op); + + /** + * Functions to iterate through different XPath axes + */ + typedef int (*axiom_xpath_iterator_t)(axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * XPath node test types + */ + typedef enum axiom_xpath_node_test_type_t + { + AXIOM_XPATH_NODE_TEST_NONE = 0, + AXIOM_XPATH_NODE_TEST_ALL, + AXIOM_XPATH_NODE_TYPE_COMMENT, + AXIOM_XPATH_NODE_TYPE_NODE, + AXIOM_XPATH_NODE_TYPE_PI, + AXIOM_XPATH_NODE_TYPE_TEXT, + AXIOM_XPATH_NODE_TEST_STANDARD + } axiom_xpath_node_test_type_t; + + /** + * XPath operations + */ + typedef enum axiom_xpath_operation_type_t + { + AXIOM_XPATH_OPERATION_ROOT_NODE = 0, + AXIOM_XPATH_OPERATION_CONTEXT_NODE, + AXIOM_XPATH_OPERATION_NODE_TEST, + AXIOM_XPATH_OPERATION_STEP, + AXIOM_XPATH_OPERATION_RESULT, + AXIOM_XPATH_OPERATION_UNION, + AXIOM_XPATH_OPERATION_EQUAL_EXPR, + AXIOM_XPATH_OPERATION_AND_EXPR, + AXIOM_XPATH_OPERATION_OR_EXPR, + AXIOM_XPATH_OPERATION_PREDICATE, + AXIOM_XPATH_OPERATION_LITERAL, + AXIOM_XPATH_OPERATION_NUMBER, + AXIOM_XPATH_OPERATION_PATH_EXPRESSION, + AXIOM_XPATH_OPERATION_FUNCTION_CALL, + AXIOM_XPATH_OPERATION_ARGUMENT + } axiom_xpath_operation_type_t; + + /** + * XPath axes + */ + typedef enum axiom_xpath_axis_t + { + AXIOM_XPATH_AXIS_NONE = -1, + AXIOM_XPATH_AXIS_CHILD, + AXIOM_XPATH_AXIS_DESCENDANT, + AXIOM_XPATH_AXIS_PARENT, + AXIOM_XPATH_AXIS_ANCESTOR, + AXIOM_XPATH_AXIS_FOLLOWING_SIBLING, + AXIOM_XPATH_AXIS_PRECEDING_SIBLING, + AXIOM_XPATH_AXIS_FOLLOWING, + AXIOM_XPATH_AXIS_PRECEDING, + AXIOM_XPATH_AXIS_ATTRIBUTE, + AXIOM_XPATH_AXIS_NAMESPACE, + AXIOM_XPATH_AXIS_SELF, + AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF, + AXIOM_XPATH_AXIS_ANCESTOR_OR_SELF + } axiom_xpath_axis_t; + + /** + * XPath node test structure + */ + struct axiom_xpath_node_test + { + /** Node test type */ + axiom_xpath_node_test_type_t type; + + /** Prefix + * NULL if no prefix + */ + axis2_char_t *prefix; + + /** Name */ + axis2_char_t *name; + + /** Literal for processing instruction (PI) */ + axis2_char_t *lit; + }; + + /** + * XPath operation structure + */ + struct axiom_xpath_operation + { + /** Type of operator */ + axiom_xpath_operation_type_t opr; + + /** Parameters of the operation */ + void *par1; + void *par2; + + /** Position: Used for predicate evaluation + */ + int pos; + + /** Operands pointing to other operations */ + int op1; + int op2; + }; + + /** + * Copies an XPath expression to a context + * + * No data is duplicated just the reference is assigned. + * Some parameters in the expression are reset. + * - pos in every operation + * + * @param context XPath context must not be NULL + * @param expr Expression to be copied + */ + void axiom_xpath_expression_copy( + axiom_xpath_context_t *context, + axiom_xpath_expression_t* expr); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/axiom/src/xpath/xpath_internals_engine.c b/axiom/src/xpath/xpath_internals_engine.c new file mode 100644 index 0000000..3c96d0e --- /dev/null +++ b/axiom/src/xpath/xpath_internals_engine.c @@ -0,0 +1,1203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_internals.h" +#include "xpath_internals_engine.h" +#include "xpath_internals_iterators.h" + +/* Evaluates the expath expression */ +axiom_xpath_result_t * +axiom_xpath_run( + axiom_xpath_context_t *context) +{ + axiom_xpath_result_t* res; + + /* Initialize result ret */ + res = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_t)); + + res->flag = 0; + + res->nodes = axutil_array_list_create(context->env, 0); + + /* Expression is empty */ + if(context->expr->start == AXIOM_XPATH_PARSE_END) + { + return res; + } + + context->stack = axutil_stack_create(context->env); + + axiom_xpath_evaluate_operation(context, context->expr->start); + + /* Add nodes to the result set from the stack */ + while(axutil_stack_size(context->stack, context->env) > 0) + { + axutil_array_list_add(res->nodes, context->env, + axutil_stack_pop(context->stack, context->env)); + } + + axutil_stack_free(context->stack, context->env); + + return res; +} + +/* Casting functions; these make use of the casting functions defined in xpath.h */ +void +axiom_xpath_cast_boolean( + axiom_xpath_result_node_t *node, + axiom_xpath_context_t *context) +{ + axis2_bool_t v = axiom_xpath_cast_node_to_boolean(context->env, node); + + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, v); + + node->type = AXIOM_XPATH_TYPE_BOOLEAN; +} + +void +axiom_xpath_cast_number( + axiom_xpath_result_node_t *node, + axiom_xpath_context_t *context) +{ + double v = axiom_xpath_cast_node_to_number(context->env, node); + + AXIOM_XPATH_CAST_SET_VALUE(double, v); + + node->type = AXIOM_XPATH_TYPE_NUMBER; +} + +void +axiom_xpath_cast_string( + axiom_xpath_result_node_t *node, + axiom_xpath_context_t *context) +{ + node->value = axiom_xpath_cast_node_to_string(context->env, node); + + node->type = AXIOM_XPATH_TYPE_TEXT; +} + +/* Evaluate whether two results are equal + + If either node is a boolean other is casted to a boolean; + Otherwise, if either node is a number other is casted to a number; + Otherwise, both nodes are casted to strings.*/ +axis2_bool_t +axiom_xpath_compare_equal( + axiom_xpath_result_node_t *node1, + axiom_xpath_result_node_t *node2, + axiom_xpath_context_t *context) +{ + if(node1->type == AXIOM_XPATH_TYPE_BOOLEAN || node2->type == AXIOM_XPATH_TYPE_BOOLEAN) + { + axiom_xpath_cast_boolean(node1, context); + axiom_xpath_cast_boolean(node2, context); + + if(*(axis2_bool_t*)(node1->value) == *(axis2_bool_t*)(node2->value)) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + + if(node1->type == AXIOM_XPATH_TYPE_NUMBER || node2->type == AXIOM_XPATH_TYPE_NUMBER) + { + axiom_xpath_cast_number(node1, context); + axiom_xpath_cast_number(node2, context); + + if(*(double *)(node1->value) == *(double *)(node2->value)) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + + axiom_xpath_cast_string(node1, context); + axiom_xpath_cast_string(node2, context); + + if(axutil_strcmp((axis2_char_t *)(node1->value), (axis2_char_t *)(node2->value)) == 0) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } +} + +/* Convert a node set to boolean */ +axis2_bool_t +axiom_xpath_convert_to_boolean( + axutil_array_list_t *node_set, + axiom_xpath_context_t *context) +{ + if(axutil_array_list_size(node_set, context->env) == 0) + { + return AXIS2_FALSE; + } + else if(axutil_array_list_size(node_set, context->env) >= 2) + { + return AXIS2_TRUE; + } + else + { + axiom_xpath_result_node_t *node = axutil_array_list_get(node_set, context->env, 0); + axiom_xpath_cast_boolean(node, context); + + return *(axis2_bool_t *)node->value; + } +} + +/* Operators */ + +/* Literal */ +int +axiom_xpath_literal_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_result_node_t *node; + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + + /* Set the context node to NULL */ + /* This is not required; it gives some problems */ + /* context->node = NULL;*/ + + node->value = op->par1; + node->type = AXIOM_XPATH_TYPE_TEXT; + + axutil_stack_push(context->stack, context->env, node); + + return 1; +} + +/* Number */ +int +axiom_xpath_number_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_result_node_t *node; + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + + /* Set the context node to NULL */ + /* This is not required; it gives some problems */ + /* context->node = NULL;*/ + + node->value = op->par1; + node->type = AXIOM_XPATH_TYPE_NUMBER; + + axutil_stack_push(context->stack, context->env, node); + + return 1; +} + +/* Path Expression */ +int +axiom_xpath_path_expression_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + int filter_res_n, n_nodes = 0; + axiom_xpath_operation_t *rel_loc_op; + axiom_xpath_operator_t rel_loc_func; + axutil_array_list_t *arr; + axiom_xpath_result_node_t *res_node; + int i; + + /* Filter operation */ + if(op->op1 == AXIOM_XPATH_PARSE_END) + { + return 0; + } + + filter_res_n = axiom_xpath_evaluate_operation(context, op->op1); + + /* Relative location path */ + if(op->op2 == AXIOM_XPATH_PARSE_END) + { + return filter_res_n; + } + + rel_loc_op = AXIOM_XPATH_OPR_GET(op->op2); + rel_loc_func = axiom_xpath_get_operator(rel_loc_op); + + /* Array list to add all results from the filter expression */ + arr = axutil_array_list_create(context->env, 0); + + for(i = 0; i < filter_res_n; i++) + { + axutil_array_list_add(arr, context->env, axutil_stack_pop(context->stack, context->env)); + } + + /* Evaluate relative location path for all results from the + filter expression */ + for(i = 0; i < axutil_array_list_size(arr, context->env); i++) + { + res_node = (axiom_xpath_result_node_t *)axutil_array_list_get(arr, context->env, i); + + if(res_node->type == AXIOM_XPATH_TYPE_NODE) + { + context->node = (axiom_node_t *)res_node->value; + context->position = i + 1; + context->size = filter_res_n; + + n_nodes += rel_loc_func(context, rel_loc_op); + } + + AXIS2_FREE(context->env->allocator, res_node); + } + + axutil_array_list_free(arr, context->env); + + return n_nodes; +} + +/* Or Expression */ +int +axiom_xpath_orexpr_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_result_node_t *node; + axiom_xpath_result_node_t *res_node; + int n_nodes[2]; + int i, j; + int op12[2]; + axutil_array_list_t *arr[2]; + + op12[0] = op->op1; + op12[1] = op->op2; + + /* Evaluate both operands and get number of results */ + for(i = 0; i < 2; i++) + { + if(op12[i] == AXIOM_XPATH_PARSE_END) + { + continue; + } + + n_nodes[i] = axiom_xpath_evaluate_operation(context, op12[i]); + } + + for(i = 1; i >= 0; i--) + { + arr[i] = axutil_array_list_create(context->env, 0); + + for(j = 0; j < n_nodes[i]; j++) + { + axutil_array_list_add(arr[i], context->env, axutil_stack_pop(context->stack, + context->env)); + } + } + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + + node->type = AXIOM_XPATH_TYPE_BOOLEAN; + node->value = NULL; + + /* Checking equality + - If any node from the first set is equal to any node from the second set + the result is true */ + if(axiom_xpath_convert_to_boolean(arr[0], context) || axiom_xpath_convert_to_boolean(arr[1], + context)) + { + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_TRUE); + + axutil_stack_push(context->stack, context->env, node); + } + else + { + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_FALSE); + + axutil_stack_push(context->stack, context->env, node); + } + + for (i = 1; i >= 0; i--) + { + for (j = 0; j < n_nodes[i]; j++) + { + res_node = (axiom_xpath_result_node_t *)axutil_array_list_get(arr[i], context->env, j); + AXIS2_FREE(context->env->allocator, res_node); + } + + axutil_array_list_free(arr[i], context->env); + } + + return 1; +} + +/* And Expression */ +int +axiom_xpath_andexpr_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_result_node_t *node; + axiom_xpath_result_node_t *res_node; + int n_nodes[2]; + int i, j; + int op12[2]; + axutil_array_list_t *arr[2]; + + op12[0] = op->op1; + op12[1] = op->op2; + + /* Evaluate both operands and get number of results */ + for(i = 0; i < 2; i++) + { + if(op12[i] == AXIOM_XPATH_PARSE_END) + { + continue; + } + + n_nodes[i] = axiom_xpath_evaluate_operation(context, op12[i]); + } + + for(i = 1; i >= 0; i--) + { + arr[i] = axutil_array_list_create(context->env, 0); + + for(j = 0; j < n_nodes[i]; j++) + { + axutil_array_list_add(arr[i], context->env, axutil_stack_pop(context->stack, + context->env)); + } + } + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + + node->type = AXIOM_XPATH_TYPE_BOOLEAN; + node->value = NULL; + + /* Checking equality + - If any node from the first set is equal to any node from the second set + the result is true */ + if(axiom_xpath_convert_to_boolean(arr[0], context) && axiom_xpath_convert_to_boolean(arr[1], + context)) + { + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_TRUE); + + axutil_stack_push(context->stack, context->env, node); + } + else + { + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_FALSE); + + axutil_stack_push(context->stack, context->env, node); + } + + for (i = 1; i >= 0; i--) + { + for (j = 0; j < n_nodes[i]; j++) + { + res_node = (axiom_xpath_result_node_t *)axutil_array_list_get(arr[i], context->env, j); + AXIS2_FREE(context->env->allocator, res_node); + } + + axutil_array_list_free(arr[i], context->env); + } + + return 1; +} + +/* Equal Expression */ +int +axiom_xpath_equalexpr_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_result_node_t *node; + axiom_xpath_result_node_t *res_node; + int n_nodes[2]; + int i, j; + int op12[2]; + axutil_array_list_t *arr[2]; + + op12[0] = op->op1; + op12[1] = op->op2; + + /* Evaluate both operands and get number of results */ + for(i = 0; i < 2; i++) + { + if(op12[i] == AXIOM_XPATH_PARSE_END) + { + continue; + } + + n_nodes[i] = axiom_xpath_evaluate_operation(context, op12[i]); + } + + for(i = 1; i >= 0; i--) + { + arr[i] = axutil_array_list_create(context->env, 0); + + for(j = 0; j < n_nodes[i]; j++) + { + axutil_array_list_add(arr[i], context->env, axutil_stack_pop(context->stack, + context->env)); + } + } + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + + node->type = AXIOM_XPATH_TYPE_BOOLEAN; + node->value = NULL; + + /* Checking equality + - If any node from the first set is equal to any node from the second set + the result is true */ + for(i = 0; i < n_nodes[0]; i++) + { + for(j = 0; j < n_nodes[1]; j++) + { + if(axiom_xpath_compare_equal(axutil_array_list_get(arr[0], context->env, i), + axutil_array_list_get(arr[1], context->env, j), context)) + { + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_TRUE); + + axutil_stack_push(context->stack, context->env, node); + + break; + } + } + + if(j < n_nodes[1]) + { + break; + } + } + + if(!node->value) + { + AXIOM_XPATH_CAST_SET_VALUE(axis2_bool_t, AXIS2_FALSE); + + axutil_stack_push(context->stack, context->env, node); + } + + for (i = 1; i >= 0; i--) + { + for (j = 0; j < n_nodes[i]; j++) + { + res_node =(axiom_xpath_result_node_t *)axutil_array_list_get(arr[i], context->env, j); + AXIS2_FREE(context->env->allocator, res_node); + } + + axutil_array_list_free(arr[i], context->env); + } + + return 1; +} + +/* Union */ +int +axiom_xpath_union_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + int n_nodes = 0; + int i; + int op12[2]; + + op12[0] = op->op1; + op12[1] = op->op2; + + for(i = 0; i < 2; i++) + { + if(op12[i] == AXIOM_XPATH_PARSE_END) + { + continue; + } + + n_nodes += axiom_xpath_evaluate_operation(context, op12[i]); + } + + return n_nodes; +} + +/* Set context node depending on whether relative or absolute location path */ +int +axiom_xpath_start_node_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + int n_nodes = 0; + + if(op->op1 == AXIOM_XPATH_PARSE_END) + { + return 0; + } + + if(op->opr == AXIOM_XPATH_OPERATION_ROOT_NODE) + { + context->node = context->root_node; + n_nodes += axiom_xpath_evaluate_operation(context, op->op1); + } + else if(op->opr == AXIOM_XPATH_OPERATION_CONTEXT_NODE) + { + n_nodes += axiom_xpath_evaluate_operation(context, op->op1); + } + + return n_nodes; +} + +/* Step */ +int +axiom_xpath_step_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_operation_t * node_test_op; + axiom_xpath_iterator_t iter; + axiom_xpath_axis_t axis; + + if(op->op1 == AXIOM_XPATH_PARSE_END) + { +#ifdef AXIOM_XPATH_DEBUG + printf("Node test operator empty\n"); +#endif + + return AXIOM_XPATH_EVALUATION_ERROR; + } + + if(op->op2 == AXIOM_XPATH_PARSE_END) + { + return 0; + } + + /* Get the name */ + node_test_op = AXIOM_XPATH_OPR_GET(op->op1); + + /* Get the axis */ + if(!node_test_op->par2) + { +#ifdef AXIOM_XPATH_DEBUG + printf("axis is NULL in the step operator\n"); +#endif + return AXIOM_XPATH_EVALUATION_ERROR; + } + axis = *((axiom_xpath_axis_t *)node_test_op->par2); + + /* Get the iteration for the axis */ + iter = axiom_xpath_get_iterator(axis); + + return iter(context, op->op1 /* node test */, op->op2 /* next step */, node_test_op->op1 /* predicate */); +} + +/* Predicates */ +axis2_bool_t +axiom_xpath_evaluate_predicate_condition( + axiom_xpath_context_t *context, + int n_nodes) +{ + axiom_xpath_result_node_t *res; + int i; + + if(n_nodes <= 0) + { + return AXIS2_FALSE; + } + else if(n_nodes > 1) + { + for(i = 0; i < n_nodes; i++) + { + res = (axiom_xpath_result_node_t *)axutil_stack_pop(context->stack, context->env); + + if (res->type > AXIOM_XPATH_TYPE_NAMESPACE) + { + AXIS2_FREE(context->env->allocator, res->value); + } + + AXIS2_FREE(context->env->allocator, res); + } + + return AXIS2_TRUE; + } + else + { + res = (axiom_xpath_result_node_t *)axutil_stack_pop(context->stack, context->env); + + if(res->type == AXIOM_XPATH_TYPE_NUMBER) + { + if(*(double *)(res->value) == context->position) + { + AXIS2_FREE(context->env->allocator, res); + return AXIS2_TRUE; + } + else + { + AXIS2_FREE(context->env->allocator, res); + return AXIS2_FALSE; + } + } + else if(res->type == AXIOM_XPATH_TYPE_BOOLEAN) + { + if(*(axis2_bool_t *)(res->value)) + { + AXIS2_FREE(context->env->allocator, res); + return AXIS2_TRUE; + } + else + { + AXIS2_FREE(context->env->allocator, res); + return AXIS2_FALSE; + } + } + else + { + AXIS2_FREE(context->env->allocator, res); + return AXIS2_TRUE; + } + } +} + +/* Predicate */ +int +axiom_xpath_evaluate_predicate( + axiom_xpath_context_t *context, + int op_next, + int op_predicate) +{ + int n_res; + axis2_bool_t res; + + axiom_xpath_operation_t * pred_op; + axiom_node_t *context_node = context->node; + + if(op_predicate == AXIOM_XPATH_PARSE_END) + { + return axiom_xpath_evaluate_operation(context, op_next); + } + else + { + pred_op = AXIOM_XPATH_OPR_GET(op_predicate); + + pred_op->pos++; + + /* Evaluate the predicate */ + if(pred_op->op1 != AXIOM_XPATH_PARSE_END) + { + n_res = axiom_xpath_evaluate_operation(context, pred_op->op1); + context->position = pred_op->pos; + + res = axiom_xpath_evaluate_predicate_condition(context, n_res); + } + else + { + res = AXIS2_TRUE; + } + /* A PredicateExpr is evaluated by evaluating the Expr and + converting the result to a boolean. If the result is a number, + the result will be converted to true if the number is equal to the + context position and will be converted to false otherwise; if the + result is not a number, then the result will be converted as if + by a call to the boolean function. */ + + /* Transform the result to number or boolean ? */ + + if(res) + { + context->node = context_node; + + return axiom_xpath_evaluate_predicate(context, op_next, pred_op->op2); + } + } + + return 0; +} + +/* Node test match */ +axis2_bool_t +axiom_xpath_node_test_match( + axiom_xpath_context_t *context, + axiom_xpath_node_test_t *node_test) +{ + axiom_types_t type; + axiom_element_t *element = NULL; + axis2_char_t *name = NULL; + axiom_namespace_t *ns = NULL, *xpath_ns = NULL; + + if(!context->node && !context->attribute && !context->ns) + { +#ifdef AXIOM_XPATH_DEBUG + printf("Both context node and attribute are NULL."); + printf(" May be a literal or a number.\n"); +#endif + return AXIS2_FALSE; + } + else if(context->node) + { + /* Test if the node matches */ + type = axiom_node_get_node_type(context->node, context->env); + + if(type == AXIOM_ELEMENT) + { + element = axiom_node_get_data_element(context->node, context->env); + + name = axiom_element_get_localname(element, context->env); + + ns = axiom_element_get_namespace(element, context->env, context->node); + } + + if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE) + { + return AXIS2_FALSE; + } + else + { + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL || node_test->type + == AXIOM_XPATH_NODE_TEST_STANDARD) + { + if(type != AXIOM_ELEMENT) + { + return AXIS2_FALSE; + } + + /* Check namespace */ + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL) + { + if(!ns && node_test->prefix) + { + return AXIS2_FALSE; + } + } + else + { + if((ns && !node_test->prefix) || (!ns && node_test->prefix)) + { + return AXIS2_FALSE; + } + } + + if(ns && node_test->prefix) + { + xpath_ns = axiom_xpath_get_namespace(context, node_test->prefix); + + if(!xpath_ns) + { + return AXIS2_FALSE; + } + + if(axutil_strcmp(axiom_namespace_get_uri(ns, context->env), + axiom_namespace_get_uri(xpath_ns, context->env))) + { + return AXIS2_FALSE; + } + } + + /* Check local name */ + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL) + { + return AXIS2_TRUE; + } + else if(node_test->type == AXIOM_XPATH_NODE_TEST_STANDARD) + { + if(name && axutil_strcmp(node_test->name, name) == 0) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + } + else if(node_test->type == AXIOM_XPATH_NODE_TYPE_COMMENT) + { + if(type == AXIOM_COMMENT) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + else if(node_test->type == AXIOM_XPATH_NODE_TYPE_PI) + { + if(type == AXIOM_PROCESSING_INSTRUCTION) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + else if(node_test->type == AXIOM_XPATH_NODE_TYPE_NODE) + { + if(type == AXIOM_ELEMENT) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + else if(node_test->type == AXIOM_XPATH_NODE_TYPE_TEXT) + { + if(type == AXIOM_TEXT) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + } + } + /* Attributes */ + else if(context->attribute) + { + name = axiom_attribute_get_localname(context->attribute, context->env); + ns = axiom_attribute_get_namespace(context->attribute, context->env); + + if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE) + { + return AXIS2_FALSE; + } + else + { + /* Check namespace */ + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL) + { + if(!ns && node_test->prefix) + { + return AXIS2_FALSE; + } + } + else + { + if((ns && !node_test->prefix) || (!ns && node_test->prefix)) + { + return AXIS2_FALSE; + } + } + + if(ns && node_test->prefix) + { + xpath_ns = axiom_xpath_get_namespace(context, node_test->prefix); + + if(!xpath_ns) + { + return AXIS2_FALSE; + } + + if(axutil_strcmp(axiom_namespace_get_uri(ns, context->env), + axiom_namespace_get_uri(xpath_ns, context->env))) + { + return AXIS2_FALSE; + } + } + + /* Check local name */ + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL) + { + return AXIS2_TRUE; + } + else if(node_test->type == AXIOM_XPATH_NODE_TEST_STANDARD) + { + if(name && axutil_strcmp(node_test->name, name) == 0) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + } + } + + /* Namespace */ + else if(context->ns) + { + /* Prefix is checked ??? If changed to uri the cast + method in xpath.c needs to be changed as well */ + name = axiom_namespace_get_prefix(context->ns, context->env); + ns = NULL; + + if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE) + { + return AXIS2_FALSE; + } + else + { + /* Check namespace */ + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL) + { + if(!ns && node_test->prefix) + { + return AXIS2_FALSE; + } + } + else + { + if((ns && !node_test->prefix) || (!ns && node_test->prefix)) + { + return AXIS2_FALSE; + } + } + + if(ns && node_test->prefix) + { + xpath_ns = axiom_xpath_get_namespace(context, node_test->prefix); + + if(!xpath_ns) + { + return AXIS2_FALSE; + } + + if(axutil_strcmp(axiom_namespace_get_uri(ns, context->env), + axiom_namespace_get_uri(xpath_ns, context->env))) + { + return AXIS2_FALSE; + } + } + + /* Check local name */ + if(node_test->type == AXIOM_XPATH_NODE_TEST_ALL) + { + return AXIS2_TRUE; + } + else if(node_test->type == AXIOM_XPATH_NODE_TEST_STANDARD) + { + if(name && axutil_strcmp(node_test->name, name) == 0) + { + return AXIS2_TRUE; + } + else + { + return AXIS2_FALSE; + } + } + } + } + + return AXIS2_FALSE; +} + +int +axiom_xpath_function_call_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_function_t func = axiom_xpath_get_function(context, op->par1); + int n_args = 0; + + if(!func) + { +#ifdef AXIOM_XPATH_DEBUG + printf("Function %s not found\n", (char *)op->par1); +#endif + + return AXIOM_XPATH_EVALUATION_ERROR; + } + + if(op->op1 != AXIOM_XPATH_PARSE_END) + { + n_args = axiom_xpath_evaluate_operation(context, op->op1); + } + + return func(context, n_args); +} + +int +axiom_xpath_argument_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + int n_args = 0; + + if(op->op1 != AXIOM_XPATH_PARSE_END) + { + n_args += axiom_xpath_evaluate_operation(context, op->op1); + } + + if(op->op2 != AXIOM_XPATH_PARSE_END) + { + n_args += axiom_xpath_evaluate_operation(context, op->op1); + } + + return n_args; +} + +/* Collect the current node to the results list */ +int +axiom_xpath_collect_operator( + axiom_xpath_context_t *context, + axiom_xpath_operation_t * op) +{ + axiom_xpath_result_node_t *node; + + node = AXIS2_MALLOC(context->env->allocator, sizeof(axiom_xpath_result_node_t)); + + if(context->node) + { + node->value = context->node; + node->type = AXIOM_XPATH_TYPE_NODE; + } + else if(context->attribute) + { + node->value = context->attribute; + node->type = AXIOM_XPATH_TYPE_ATTRIBUTE; + } + else if(context->ns) + { + node->value = context->ns; + node->type = AXIOM_XPATH_TYPE_NAMESPACE; + } + + axutil_stack_push(context->stack, context->env, node); + + return 1; +} + +/* Returns a pointer to the respective processing function */ +axiom_xpath_operator_t +axiom_xpath_get_operator( + axiom_xpath_operation_t * op) +{ + switch(op->opr) + { + case AXIOM_XPATH_OPERATION_STEP: + return axiom_xpath_step_operator; + + case AXIOM_XPATH_OPERATION_ROOT_NODE: + case AXIOM_XPATH_OPERATION_CONTEXT_NODE: + return axiom_xpath_start_node_operator; + + case AXIOM_XPATH_OPERATION_RESULT: + return axiom_xpath_collect_operator; + + case AXIOM_XPATH_OPERATION_UNION: + return axiom_xpath_union_operator; + + case AXIOM_XPATH_OPERATION_OR_EXPR: + return axiom_xpath_orexpr_operator; + + case AXIOM_XPATH_OPERATION_AND_EXPR: + return axiom_xpath_andexpr_operator; + + case AXIOM_XPATH_OPERATION_EQUAL_EXPR: + return axiom_xpath_equalexpr_operator; + + case AXIOM_XPATH_OPERATION_LITERAL: + return axiom_xpath_literal_operator; + + case AXIOM_XPATH_OPERATION_NUMBER: + return axiom_xpath_number_operator; + + case AXIOM_XPATH_OPERATION_PATH_EXPRESSION: + return axiom_xpath_path_expression_operator; + + case AXIOM_XPATH_OPERATION_FUNCTION_CALL: + return axiom_xpath_function_call_operator; + + case AXIOM_XPATH_OPERATION_ARGUMENT: + return axiom_xpath_argument_operator; + + default: +#ifdef AXIOM_XPATH_DEBUG + printf("Unidentified operation.\n"); +#endif + + return NULL; + } +} + +/* Returns a pointer to the respective processing function */ +axiom_xpath_iterator_t +axiom_xpath_get_iterator( + axiom_xpath_axis_t axis) +{ + switch(axis) + { + case AXIOM_XPATH_AXIS_CHILD: + return axiom_xpath_child_iterator; + + case AXIOM_XPATH_AXIS_DESCENDANT: + return axiom_xpath_descendant_iterator; + + case AXIOM_XPATH_AXIS_PARENT: + return axiom_xpath_parent_iterator; + + case AXIOM_XPATH_AXIS_ANCESTOR: + return axiom_xpath_ancestor_iterator; + + case AXIOM_XPATH_AXIS_FOLLOWING_SIBLING: + return axiom_xpath_following_sibling_iterator; + + case AXIOM_XPATH_AXIS_PRECEDING_SIBLING: + return axiom_xpath_preceding_sibling_iterator; + + case AXIOM_XPATH_AXIS_FOLLOWING: + return axiom_xpath_following_iterator; + + case AXIOM_XPATH_AXIS_PRECEDING: + return axiom_xpath_preceding_iterator; + + case AXIOM_XPATH_AXIS_ATTRIBUTE: + return axiom_xpath_attribute_iterator; + + case AXIOM_XPATH_AXIS_NAMESPACE: + return axiom_xpath_namespace_iterator; + + case AXIOM_XPATH_AXIS_SELF: + return axiom_xpath_self_iterator; + + case AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF: + return axiom_xpath_descendant_self_iterator; + + case AXIOM_XPATH_AXIS_ANCESTOR_OR_SELF: + return axiom_xpath_ancestor_self_iterator; + + default: +#ifdef AXIOM_XPATH_DEBUG + printf("Unidentified axis.\n"); +#endif + + return NULL; + } +} + +int +axiom_xpath_evaluate_operation( + axiom_xpath_context_t *context, + int op) +{ + axiom_xpath_operation_t * operation; + axiom_xpath_operator_t function; + + /* Get a pointer to the operation */ + operation = AXIOM_XPATH_OPR_GET(op); + + /* Get the funciton which processes the operations */ + function = axiom_xpath_get_operator(operation); + + return function(context, operation); +} diff --git a/axiom/src/xpath/xpath_internals_engine.h b/axiom/src/xpath/xpath_internals_engine.h new file mode 100755 index 0000000..bffc8a7 --- /dev/null +++ b/axiom/src/xpath/xpath_internals_engine.h @@ -0,0 +1,265 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIOM_XPATH_INTERNALS_ENGINE_H +#define AXIOM_XPATH_INTERNALS_ENGINE_H + +#include "xpath_internals.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @defgroup axiom_xpath_engine engine + * @ingroup axiom_xpath + * @{ + */ + + + /* Macros */ + + /** Set node->value to _value */ +#define AXIOM_XPATH_CAST_SET_VALUE(_type, _value) { \ + _type * _var; \ + if(node->value \ + && node->type != AXIOM_XPATH_TYPE_NODE \ + && node->type != AXIOM_XPATH_TYPE_ATTRIBUTE \ + && node->type != AXIOM_XPATH_TYPE_NAMESPACE) \ + { AXIS2_FREE(context->env->allocator, node->value); } \ + _var = AXIS2_MALLOC(context->env->allocator, sizeof(_type)); \ + *_var = _value; \ + node->value = (void *) _var; \ +} + + /* Functions */ + + /** + * Evaluate an XPath context, which containes a parsed expression + * + * @param context XPath context + * @return Result set + */ + axiom_xpath_result_t* axiom_xpath_run(axiom_xpath_context_t *context); + + /** + * Finds the operator function for a given operation + * + * @param op Operation + * @return Pointer to the function which process the given operation + */ + axiom_xpath_operator_t axiom_xpath_get_operator(axiom_xpath_operation_t * op); + + /** + * Get the iterotor for give axis + * + * @param axis XPath axis + * @return Pointer to the function which iterater through the given axis + */ + axiom_xpath_iterator_t axiom_xpath_get_iterator(axiom_xpath_axis_t axis); + + /* Operators */ + + /** + * Select the start node depending on whether it is an absolute or relative location path + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack + */ + int axiom_xpath_start_node_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Add the context node or attribute to the results stack + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack + */ + int axiom_xpath_collect_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Process union operator + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack + */ + int axiom_xpath_union_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Perform or operation + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_orexpr_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Perform and operation + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_andexpr_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Perform equality test operation + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_equalexpr_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Evaluate function call operation + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_function_call_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Evaluate argument operation + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_argument_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Process a path expression + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack + */ + int axiom_xpath_path_expression_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Process a number; push the value to the stack + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_number_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + /** + * Process a literal; push the string to the stack + * + * @param context XPath context + * @param op XPath operation + * @return Number of nodes added to the stack; which is one + */ + int axiom_xpath_literal_operator(axiom_xpath_context_t *context, axiom_xpath_operation_t * op); + + + /** + * Converts an XPath result to a boolean result + * + * @param node Result + * @param context XPath context + */ + void axiom_xpath_cast_boolean(axiom_xpath_result_node_t *node, axiom_xpath_context_t *context); + + /** + * Converts an XPath result to a number + * + * @param node Result + * @param context XPath context + */ + void axiom_xpath_cast_number(axiom_xpath_result_node_t *node, axiom_xpath_context_t *context); + + /** + * Converts an XPath result to a string + * + * @param node Result + * @param context XPath context + */ + void axiom_xpath_cast_string(axiom_xpath_result_node_t *node, axiom_xpath_context_t *context); + + /* Convert a node set to boolean */ + /** + * Convert a XPath node set to boolean + * + * @param node_set Node set + * @return AXIS2_TRUE if true; AXIS2_FALSE otherwise + */ + axis2_bool_t axiom_xpath_convert_to_boolean(axutil_array_list_t *node_set, axiom_xpath_context_t *context); + + /** + * Test if two result nodes are equal + * + * @param node1 First node + * @param node2 Second node + * @param context XPath context + * @return AXIS2_TRUE if equal; AXIS2_FALSE otherwise + */ + axis2_bool_t axiom_xpath_compare_equal(axiom_xpath_result_node_t *node1, axiom_xpath_result_node_t *node2, axiom_xpath_context_t *context); + + /** + * Test if the axiom node matches node test + * + * @param context XPath context + * @param node_test Node test + * @return AXIS2_TRUE if matches; AXIS2_FALSE otherwise + */ + axis2_bool_t axiom_xpath_node_test_match(axiom_xpath_context_t *context, axiom_xpath_node_test_t *node_test); + + /** + * Evaluate if the predicate is true + * + * @param context XPath context + * @param n_nodes Number of results after evaluating the expression in the predicate + * @return AXIS2_TRUE if matches; AXIS2_FALSE otherwise + */ + axis2_bool_t axiom_xpath_evaluate_predicate_condition(axiom_xpath_context_t *context, int n_nodes); + + /** + * Evaluate if the predicate(s) is true using axiom_xpath_evaluate_predicate_condition and executes the operation op_next + * + * @param context XPath context + * @param op_next The operation to be executed if all predicates are true + * @param op_predicate Reference to predicate + * @return Number of nodes added to the stack + */ + int axiom_xpath_evaluate_predicate(axiom_xpath_context_t *context, int op_next, int op_predicate); + + /** + * Evaluate operation pointed by op + * + * @param context XPath context + * @param op The index of the operation in the operations list + * @return Number of nodes added to the stack + */ + int axiom_xpath_evaluate_operation(axiom_xpath_context_t *context, int op); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/axiom/src/xpath/xpath_internals_iterators.c b/axiom/src/xpath/xpath_internals_iterators.c new file mode 100644 index 0000000..225bea6 --- /dev/null +++ b/axiom/src/xpath/xpath_internals_iterators.c @@ -0,0 +1,588 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_internals.h" +#include "xpath_internals_engine.h" +#include "xpath_internals_iterators.h" + + +/* child */ +int +axiom_xpath_child_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes_tot = 0; + int n_nodes; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *cur = NULL; + axiom_node_t *context_node = NULL; + /* For streaming */ + axiom_node_t *prev = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + cur = axiom_node_get_first_child(context->node, context->env); + + while(cur != NULL) + { + n_nodes = 0; + context->node = cur; + prev = cur; + cur = axiom_node_get_next_sibling(cur, context->env); + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes = axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + n_nodes_tot += n_nodes; + } + } + + /* Change the context node back to what it was */ + context->node = context_node; + + return n_nodes_tot; +} + +/* descendant */ +int +axiom_xpath_descendant_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *child = NULL; + axiom_node_t *context_node = NULL; + axutil_stack_t *stack; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + /* Setting up the stack */ + stack = axutil_stack_create(context->env); + + child = axiom_node_get_first_child(context->node, context->env); + while(child) + { + axutil_stack_push(stack, context->env, child); + child = axiom_node_get_first_child(child, context->env); + } + + /* Processing nodes */ + while(axutil_stack_size(stack, context->env) > 0) + { + child = (axiom_node_t *)axutil_stack_pop(stack, context->env); + + context->node = child; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + child = axiom_node_get_next_sibling(child, context->env); + while(child) + { + axutil_stack_push(stack, context->env, child); + child = axiom_node_get_first_child(child, context->env); + } + } + + context->node = context_node; + + axutil_stack_free(stack, context->env); + + return n_nodes; +} + +/* parent */ +int +axiom_xpath_parent_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *parent = NULL; + axiom_node_t *context_node = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + parent = axiom_node_get_parent(context->node, context->env); + + if(parent != NULL) + { + context->node = parent; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes = axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + } + + /* Change the context node back to what it was */ + context->node = context_node; + + return n_nodes; +} + +/* ancestor axis */ +int +axiom_xpath_ancestor_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *cur = NULL; + axiom_node_t *context_node = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + cur = axiom_node_get_parent(context->node, context->env); + + while(cur != NULL) + { + context->node = cur; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + cur = axiom_node_get_parent(cur, context->env); + } + + /* Change the context node back to what it was */ + context->node = context_node; + + return n_nodes; +} + +/* following-sibling axis */ +int +axiom_xpath_following_sibling_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *cur = NULL; + axiom_node_t *context_node = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + cur = axiom_node_get_next_sibling(context->node, context->env); + + while(cur != NULL) + { + context->node = cur; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + cur = axiom_node_get_next_sibling(cur, context->env); + } + + /* Change the context node back to what it was */ + context->node = context_node; + + return n_nodes; +} + +/* preceding-sibling axis */ +int +axiom_xpath_preceding_sibling_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *cur = NULL; + axiom_node_t *context_node = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + cur = axiom_node_get_previous_sibling(context->node, context->env); + + while(cur != NULL) + { + context->node = cur; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + cur = axiom_node_get_previous_sibling(cur, context->env); + } + + /* Change the context node back to what it was */ + context->node = context_node; + + return n_nodes; +} + +/* following */ +int +axiom_xpath_following_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *child = NULL, *parent = NULL; + axiom_node_t *context_node = NULL; + axutil_stack_t *stack; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + /* Setting up the stack */ + stack = axutil_stack_create(context->env); + axutil_stack_push(stack, context->env, context->node); + + parent = context->node; + + while(parent) + { + axutil_stack_push(stack, context->env, parent); + + while(axutil_stack_size(stack, context->env) > 0) + { + child = (axiom_node_t *)axutil_stack_pop(stack, context->env); + + child = axiom_node_get_next_sibling(child, context->env); + + while(child) + { + context->node = child; + if(axiom_xpath_node_test_match(context, + (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + axutil_stack_push(stack, context->env, child); + child = axiom_node_get_first_child(child, context->env); + } + } + parent = axiom_node_get_parent(parent, context->env); + } + + /* Change the context node back to what it was */ + context->node = context_node; + + axutil_stack_free(stack, context->env); + + return n_nodes; +} + +/* preceding */ +int +axiom_xpath_preceding_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *child = NULL, *parent = NULL; + axiom_node_t *context_node = NULL; + axutil_stack_t *stack; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + /* Setting up the stack */ + stack = axutil_stack_create(context->env); + + parent = context->node; + + while(parent) + { + axutil_stack_push(stack, context->env, parent); + + while(axutil_stack_size(stack, context->env) > 0) + { + child = (axiom_node_t *)axutil_stack_pop(stack, context->env); + + child = axiom_node_get_previous_sibling(child, context->env); + + while(child) + { + context->node = child; + if(axiom_xpath_node_test_match(context, + (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + axutil_stack_push(stack, context->env, child); + + child = axiom_node_get_last_child(child, context->env); + } + } + parent = axiom_node_get_parent(parent, context->env); + } + + /* Change the context node back to what it was */ + context->node = context_node; + + axutil_stack_free(stack, context->env); + + return n_nodes; +} + +/* attribute axis */ +int +axiom_xpath_attribute_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_types_t type; + axiom_node_t *context_node = NULL; + axiom_element_t *element; + axutil_hash_t *ht; + axutil_hash_index_t *hi; + + /* void *key; + * axis2_ssize_t klen; + */ + void *attr; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + type = axiom_node_get_node_type(context_node, context->env); + + if(type != AXIOM_ELEMENT) + { + return 0; + } + + element = axiom_node_get_data_element(context_node, context->env); + + context->node = NULL; + + ht = axiom_element_get_all_attributes(element, context->env); + + if(ht) + { + for(hi = axutil_hash_first(ht, context->env); hi; hi = axutil_hash_next(context->env, hi)) + { + attr = &context->attribute; + axutil_hash_this(hi, NULL, NULL, attr); + + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + } + } + + context->node = context_node; + context->attribute = NULL; + + return n_nodes; +} + +/* namespace axis */ +int +axiom_xpath_namespace_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_types_t type; + axiom_node_t *context_node = NULL; + axiom_element_t *element; + axutil_hash_t *ht; + axutil_hash_index_t *hi; + + /* void *key; + * axis2_ssize_t klen; + */ + + void *ns; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + type = axiom_node_get_node_type(context_node, context->env); + + if(type != AXIOM_ELEMENT) + { + return 0; + } + + element = axiom_node_get_data_element(context_node, context->env); + + context->node = NULL; + + ht = axiom_element_get_namespaces(element, context->env); + + if(ht) + { + for(hi = axutil_hash_first(ht, context->env); hi; hi = axutil_hash_next(context->env, hi)) + { + ns = &context->ns; + axutil_hash_this(hi, NULL, NULL, ns); + + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + } + } + + context->node = context_node; + context->ns = NULL; + + return n_nodes; +} + +/* self axis */ +int +axiom_xpath_self_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *context_node = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + context->node = context_node; + + return n_nodes; +} + +/* descendant-or-self axis */ +int +axiom_xpath_descendant_self_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *child = NULL; + axiom_node_t *context_node = NULL; + axutil_stack_t *stack; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + /* Setting up the stack */ + stack = axutil_stack_create(context->env); + + child = axiom_node_get_first_child(context->node, context->env); + while(child) + { + axutil_stack_push(stack, context->env, child); + child = axiom_node_get_first_child(child, context->env); + } + + /* Processing nodes */ + while(axutil_stack_size(stack, context->env) > 0) + { + child = (axiom_node_t *)axutil_stack_pop(stack, context->env); + + context->node = child; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + child = axiom_node_get_next_sibling(child, context->env); + while(child) + { + axutil_stack_push(stack, context->env, child); + child = axiom_node_get_first_child(child, context->env); + } + } + + /* Change the context node back to what it was */ + context->node = context_node; + + axutil_stack_free(stack, context->env); + + return n_nodes; +} + +/* ancestor-or-self axis */ +int +axiom_xpath_ancestor_self_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate) +{ + int n_nodes = 0; + axiom_xpath_operation_t * node_test_op; + axiom_node_t *parent = NULL; + axiom_node_t *context_node = NULL; + + AXIOM_XPATH_ITERATOR_INITIALIZE; + + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + parent = axiom_node_get_parent(context->node, context->env); + + while(parent != NULL) + { + context->node = parent; + if(axiom_xpath_node_test_match(context, (axiom_xpath_node_test_t *)node_test_op->par1)) + { + n_nodes += axiom_xpath_evaluate_predicate(context, op_next, op_predicate); + } + + parent = axiom_node_get_parent(parent, context->env); + } + + /* Change the context node back to what it was */ + context->node = context_node; + + return n_nodes; +} diff --git a/axiom/src/xpath/xpath_internals_iterators.h b/axiom/src/xpath/xpath_internals_iterators.h new file mode 100755 index 0000000..67d06c4 --- /dev/null +++ b/axiom/src/xpath/xpath_internals_iterators.h @@ -0,0 +1,298 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIOM_XPATH_INTERNALS_ITERATORS_H +#define AXIOM_XPATH_INTERNALS_ITERATORS_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @defgroup axiom_xpath_iterators iterators + * @ingroup axiom_xpath + * @{ + */ + + +#ifdef AXIOM_XPATH_DEBUG +#define AXIOM_XPATH_ITERATOR_INITIALIZE { \ + if(!context->node) { \ + printf("Context node NULL; cannot evaluate self or descendent axis.\n"); \ + return AXIOM_XPATH_EVALUATION_ERROR; } \ + node_test_op = AXIOM_XPATH_OPR_GET(op_node_test); \ + if(!node_test_op) { \ + printf("Node test not present.\n"); \ + return AXIOM_XPATH_EVALUATION_ERROR; } \ + context_node = context->node; \ +} +#else +#define AXIOM_XPATH_ITERATOR_INITIALIZE { \ + if(!context->node) { \ + return AXIOM_XPATH_EVALUATION_ERROR; } \ + node_test_op = AXIOM_XPATH_OPR_GET(op_node_test); \ + if(!node_test_op) { \ + return AXIOM_XPATH_EVALUATION_ERROR; } \ + context_node = context->node; \ +} +#endif + + /** + * Iterate through children + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_child_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through descendents + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_descendant_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through parent node. (Only one node) + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_parent_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through ancestors + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_ancestor_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through siblings following the context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_following_sibling_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through sibling preceding the context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_preceding_sibling_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through all nodes following the context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_following_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through all nodes preceding the context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_preceding_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through attributes + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_attribute_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through namespaces defined in the context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_namespace_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through self node (Only one node) + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_self_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through descendents and context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_descendant_self_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** + * Iterate through ancestors and context node + * + * @param context XPath context + * @param op_node_test Reference to the node test operation + * in the parsed expression + * @param op_next Reference to the next step in the location path, + * in the parsed expression + * @param op_predicate Reference to the first predicate in the + * parsed expression + * @return Number of nodes added to the stack + */ + int axiom_xpath_ancestor_self_iterator( + axiom_xpath_context_t *context, + int op_node_test, + int op_next, + int op_predicate); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/axiom/src/xpath/xpath_internals_parser.c b/axiom/src/xpath/xpath_internals_parser.c new file mode 100755 index 0000000..a1ce79a --- /dev/null +++ b/axiom/src/xpath/xpath_internals_parser.c @@ -0,0 +1,1245 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_internals.h" +#include "xpath_internals_parser.h" +#include + +/* Compile an XPath expression */ +int +axiom_xpath_compile( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + if(!expr || !expr->expr_str) + { +#ifdef AXIOM_XPATH_DEBUG + printf("Expression in NULL.\n"); +#endif + + return AXIS2_FAILURE; + } + + expr->expr_len = (int)axutil_strlen(expr->expr_str); + + expr->operations = axutil_array_list_create(env, 0); + + expr->expr_ptr = 0; + + expr->start = axiom_xpath_compile_orexpr(env, expr); + + if(expr->start == AXIOM_XPATH_PARSE_ERROR) + { + axutil_array_list_free(expr->operations, env); + + return AXIOM_XPATH_PARSE_ERROR; + } + else + { +#ifdef AXIOM_XPATH_DEBUG + printf("Expression successfully parsed\n"); +#endif + + return AXIOM_XPATH_PARSE_SUCCESS; + } +} + +/* Parse Or Expression */ +int +axiom_xpath_compile_orexpr( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1, op2; + + if(!AXIOM_XPATH_HAS_MORE) + { + return AXIOM_XPATH_PARSE_END; + } + + op1 = axiom_xpath_compile_andexpr(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: AndEpxr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + while(AXIOM_XPATH_CURRENT == 'o' && AXIOM_XPATH_NEXT(1) == 'r') + { + AXIOM_XPATH_READ(2); + AXIOM_XPATH_SKIP_WHITESPACES; + + op2 = axiom_xpath_compile_andexpr(env, expr); + + if(op2 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: AndEpxr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op1 = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_OR_EXPR, op1, op2); + + AXIOM_XPATH_SKIP_WHITESPACES; + } + + return op1; +} + +/* Parse And Expression */ +int +axiom_xpath_compile_andexpr( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1, op2; + + if(!AXIOM_XPATH_HAS_MORE) + { + return AXIOM_XPATH_PARSE_END; + } + + op1 = axiom_xpath_compile_equalexpr(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: EqualityExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + while(AXIOM_XPATH_CURRENT == 'a' && AXIOM_XPATH_NEXT(1) == 'n' && AXIOM_XPATH_NEXT(1) == 'd') + { + AXIOM_XPATH_READ(2); + AXIOM_XPATH_SKIP_WHITESPACES; + + op2 = axiom_xpath_compile_equalexpr(env, expr); + + if(op2 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: EqualityExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op1 = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_AND_EXPR, op1, op2); + + AXIOM_XPATH_SKIP_WHITESPACES; + } + + return op1; +} + +/* Parse Equality Expression */ +int +axiom_xpath_compile_equalexpr( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1, op2; + + if(!AXIOM_XPATH_HAS_MORE) + { + return AXIOM_XPATH_PARSE_END; + } + + op1 = axiom_xpath_compile_union(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: UnionExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + while(AXIOM_XPATH_CURRENT == '=') + { + AXIOM_XPATH_SKIP_WHITESPACES; + AXIOM_XPATH_READ(1); + AXIOM_XPATH_SKIP_WHITESPACES; + + op2 = axiom_xpath_compile_union(env, expr); + + if(op2 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: UnionExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op1 = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_EQUAL_EXPR, op1, op2); + + AXIOM_XPATH_SKIP_WHITESPACES; + } + + return op1; +} + +/* Parse Union */ +int +axiom_xpath_compile_union( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1, op2; + + if(!AXIOM_XPATH_HAS_MORE) + { + return AXIOM_XPATH_PARSE_END; + } + + op1 = axiom_xpath_compile_path_expression(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: PathExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(AXIOM_XPATH_CURRENT == '|') + { + AXIOM_XPATH_READ(1); + AXIOM_XPATH_SKIP_WHITESPACES; + op2 = axiom_xpath_compile_union(env, expr); + + if(op2 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: UnionExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_UNION, op1, op2); + } + + /* Just a location path */ + return op1; +} + +/* Compile Filter expression */ +int +axiom_xpath_compile_filter( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op = AXIOM_XPATH_PARSE_END; + + if(AXIOM_XPATH_CURRENT == '(') + { + AXIOM_XPATH_READ(1); + op = axiom_xpath_compile_orexpr(env, expr); + AXIOM_XPATH_SKIP_WHITESPACES; + if(AXIOM_XPATH_CURRENT == ')') + { + AXIOM_XPATH_READ(1); + return op; + } + else + { + return AXIOM_XPATH_PARSE_ERROR; + } + } + else if(AXIOM_XPATH_CURRENT == '\'' || AXIOM_XPATH_CURRENT == '\"') + { + return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_LITERAL, axiom_xpath_compile_literal(env, + expr), NULL, AXIOM_XPATH_PARSE_END); + } + else if(isdigit(AXIOM_XPATH_CURRENT) || (AXIOM_XPATH_CURRENT == '.' && isdigit( + AXIOM_XPATH_NEXT(1)))) + { + return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_NUMBER, axiom_xpath_compile_number(env, + expr), NULL, AXIOM_XPATH_PARSE_END); + } + else if(AXIOM_XPATH_CURRENT == '$') + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: Variables are not supported, yet - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + } + else + { + return axiom_xpath_compile_function_call(env, expr); + } + +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: Invalid Filter expression - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + /* TODO: functions and variables */ +} + +/* Parse Path expression (not a location path) */ +int +axiom_xpath_path_compile_path_expression_filter( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op_filter, op_next; + + op_filter = axiom_xpath_compile_filter(env, expr); + + if(op_filter == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: FilterExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(AXIOM_XPATH_NEXT(0) == '/' && AXIOM_XPATH_NEXT(1) == '/') + { + AXIOM_XPATH_READ(2); + + op_next = axiom_xpath_compile_relative_location(env, expr); + + if(op_next == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op_next = AXIOM_XPATH_WRAP_SELF_DESCENDANT(op_next); + } + else if(AXIOM_XPATH_NEXT(0) == '/') + { + AXIOM_XPATH_READ(1); + + op_next = axiom_xpath_compile_relative_location(env, expr); + + if(op_next == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + } + else + { + op_next = AXIOM_XPATH_PARSE_END; + } + + return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_PATH_EXPRESSION, op_filter, op_next); +} + +/* Parse Path expression */ +int +axiom_xpath_compile_path_expression( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int temp_ptr = expr->expr_ptr; + axis2_char_t *name; + axis2_char_t *node_types[] = { "comment", "node", "processing-instruction", "text" }; + axis2_char_t filter_start[] = { '$', '\'', '\"', '(' }; + int i; + + /* if | FilterExpr + | FilterExpr '/' RelativeLocationPath + | FilterExpr '//' RelativeLocationPath */ + for(i = 0; i < 4; i++) + { + if(AXIOM_XPATH_CURRENT == filter_start[i]) + { + return axiom_xpath_path_compile_path_expression_filter(env, expr); + } + } + + if(isdigit(AXIOM_XPATH_CURRENT) || (AXIOM_XPATH_CURRENT == '.' && isdigit(AXIOM_XPATH_NEXT(1)))) + { + return axiom_xpath_path_compile_path_expression_filter(env, expr); + } + + /* Funciton calls */ + name = axiom_xpath_compile_ncname(env, expr); + AXIOM_XPATH_SKIP_WHITESPACES; + + if(name != NULL && AXIOM_XPATH_CURRENT == '(') + { + expr->expr_ptr = temp_ptr; + for(i = 0; i < 4; i++) + { + /* If node type */ + if(axutil_strcmp(name, node_types[i]) == 0) + { + return axiom_xpath_compile_location_path(env, expr); + } + } + + return axiom_xpath_path_compile_path_expression_filter(env, expr); + } + + expr->expr_ptr = temp_ptr; + + return axiom_xpath_compile_location_path(env, expr); +} + +/* Parses Location Path */ +int +axiom_xpath_compile_location_path( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1; + axiom_xpath_operation_type_t opr; + + if(!AXIOM_XPATH_HAS_MORE) + { + return AXIOM_XPATH_PARSE_END; + } + + if(AXIOM_XPATH_CURRENT == '/') + { + /* Descendent */ + if(AXIOM_XPATH_NEXT(1) == '/') + { + opr = AXIOM_XPATH_OPERATION_CONTEXT_NODE; + AXIOM_XPATH_READ(2); + AXIOM_XPATH_SKIP_WHITESPACES; + + op1 = axiom_xpath_compile_relative_location(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op1 = AXIOM_XPATH_WRAP_SELF_DESCENDANT(op1); + } + else + { + opr = AXIOM_XPATH_OPERATION_ROOT_NODE; + AXIOM_XPATH_READ(1); + + op1 = axiom_xpath_compile_relative_location(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + } + } + else + { + opr = AXIOM_XPATH_OPERATION_CONTEXT_NODE; + + op1 = axiom_xpath_compile_relative_location(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + } + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + return AXIOM_XPATH_PUSH(opr, op1, AXIOM_XPATH_PARSE_END); +} + +/* Parses Relative Location Path */ +int +axiom_xpath_compile_relative_location( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op_step, op_next; + + if(!AXIOM_XPATH_HAS_MORE) + { + return AXIOM_XPATH_PARSE_END; + } + + op_step = axiom_xpath_compile_step(env, expr); + op_next = AXIOM_XPATH_PARSE_END; /* Will change if there are more steps */ + + if(op_step == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: Step expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(AXIOM_XPATH_NEXT(0) == '/' && AXIOM_XPATH_NEXT(1) == '/') + { + AXIOM_XPATH_READ(2); + + op_next = axiom_xpath_compile_relative_location(env, expr); + + if(op_next == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op_next = AXIOM_XPATH_WRAP_SELF_DESCENDANT(op_next); + } + else if(AXIOM_XPATH_NEXT(0) == '/') + { + AXIOM_XPATH_READ(1); + + op_next = axiom_xpath_compile_relative_location(env, expr); + + if(op_next == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: RelativeLocation expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + } + + /* End of the location path */ + if(op_next == AXIOM_XPATH_PARSE_END) + { + op_next = AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_RESULT, AXIOM_XPATH_PARSE_END, + AXIOM_XPATH_PARSE_END); + } + + return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_STEP, op_step, op_next); +} + +/* Parses Step */ +int +axiom_xpath_compile_step( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op_predicate = AXIOM_XPATH_PARSE_END; + axiom_xpath_node_test_t *node_test; + int temp_ptr; + axis2_char_t *name = NULL; + axiom_xpath_axis_t axis = AXIOM_XPATH_AXIS_NONE; + + AXIOM_XPATH_SKIP_WHITESPACES; + + /* . and .. */ + if(AXIOM_XPATH_CURRENT == '.') + { + if(AXIOM_XPATH_NEXT(1) == '.') + { + AXIOM_XPATH_READ(2); + axis = AXIOM_XPATH_AXIS_PARENT; + } + else + { + AXIOM_XPATH_READ(1); + axis = AXIOM_XPATH_AXIS_SELF; + } + + return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_NODE_TEST, + axiom_xpath_create_node_test_node(env), axiom_xpath_create_axis(env, axis), + op_predicate); + } + else if(AXIOM_XPATH_CURRENT == '@') + { + axis = AXIOM_XPATH_AXIS_ATTRIBUTE; + + AXIOM_XPATH_READ(1); + AXIOM_XPATH_SKIP_WHITESPACES; + } + else + { + temp_ptr = expr->expr_ptr; + + name = axiom_xpath_compile_ncname(env, expr); + + if(name) + { + AXIOM_XPATH_SKIP_WHITESPACES; + + /* An axis */ + if(AXIOM_XPATH_CURRENT == ':' && AXIOM_XPATH_NEXT(1) == ':') + { + axis = axiom_xpath_get_axis(env, name); + + if(axis == AXIOM_XPATH_AXIS_NONE) + { +#ifdef AXIOM_XPATH_DEBUG + printf("Parse error: Invalid axis - %s\n", name); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_READ(2); + AXIOM_XPATH_SKIP_WHITESPACES; + } + else + { + axis = AXIOM_XPATH_AXIS_CHILD; + + expr->expr_ptr = temp_ptr; + } + } + else + { + axis = AXIOM_XPATH_AXIS_CHILD; + + expr->expr_ptr = temp_ptr; + } + } + + node_test = axiom_xpath_compile_node_test(env, expr); + + if(!node_test) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: NodeTest expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + op_predicate = axiom_xpath_compile_predicate(env, expr); + + if(op_predicate == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: Predicate expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_NODE_TEST, node_test, + axiom_xpath_create_axis(env, axis), op_predicate); +} + +axiom_xpath_node_test_t* +axiom_xpath_compile_node_test( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + axis2_char_t* name; + axiom_xpath_node_test_t *node_test; + + node_test = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_node_test_t)); + node_test->type = AXIOM_XPATH_NODE_TEST_NONE; + node_test->prefix = NULL; + node_test->name = NULL; + node_test->lit = NULL; + + if(AXIOM_XPATH_CURRENT == '*') + { + AXIOM_XPATH_READ(1); + + node_test->type = AXIOM_XPATH_NODE_TEST_ALL; + + return node_test; + } + + name = axiom_xpath_compile_ncname(env, expr); + + if(!name) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: NCName expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + AXIS2_FREE(env->allocator, node_test); + + return NULL; + } + + /* Node type */ + + if(AXIOM_XPATH_CURRENT == '(') + { + AXIOM_XPATH_READ(1); + + if(axutil_strcmp(name, "comment") == 0) + { + node_test->type = AXIOM_XPATH_NODE_TYPE_COMMENT; + } + if(axutil_strcmp(name, "node") == 0) + { + node_test->type = AXIOM_XPATH_NODE_TYPE_NODE; + } + if(axutil_strcmp(name, "processing-instruction") == 0) + { + node_test->type = AXIOM_XPATH_NODE_TYPE_PI; + + node_test->lit = axiom_xpath_compile_literal(env, expr); + } + if(axutil_strcmp(name, "text") == 0) + { + node_test->type = AXIOM_XPATH_NODE_TYPE_TEXT; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(node_test->type == AXIOM_XPATH_NODE_TEST_NONE || AXIOM_XPATH_CURRENT != ')') + { +#ifdef AXIOM_XPATH_DEBUG + printf("Parse error: Invalid node type - %s\n", name); +#endif + + AXIS2_FREE(env->allocator, node_test); + + return NULL; + } + + AXIOM_XPATH_READ(1); + } + else + { + node_test->type = AXIOM_XPATH_NODE_TEST_STANDARD; + + if(AXIOM_XPATH_CURRENT == ':') + { + AXIOM_XPATH_READ(1); + + node_test->prefix = name; + + if(AXIOM_XPATH_CURRENT == '*') + { + AXIOM_XPATH_READ(1); + + node_test->type = AXIOM_XPATH_NODE_TEST_ALL; + + return node_test; + } + + node_test->name = axiom_xpath_compile_ncname(env, expr); + + if(!node_test->name) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: NCName expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + AXIS2_FREE(env->allocator, node_test); + + return NULL; + } + } + else + { + node_test->name = name; + } + } + + return node_test; +} + +int +axiom_xpath_compile_function_call( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + axis2_char_t *name; + int op1 = AXIOM_XPATH_PARSE_END; + + name = axiom_xpath_compile_ncname(env, expr); + + if(!name) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: NCName expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + if(AXIOM_XPATH_CURRENT != '(') + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: '(' expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_READ(1); + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(AXIOM_XPATH_CURRENT != ')') + { + op1 = axiom_xpath_compile_argument(env, expr); + } + + if(AXIOM_XPATH_CURRENT != ')') + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: ')' expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_READ(1); + + return AXIOM_XPATH_PUSH_PAR(AXIOM_XPATH_OPERATION_FUNCTION_CALL, name, NULL, op1); +} + +int +axiom_xpath_compile_argument( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1 = AXIOM_XPATH_PARSE_END; + int op2 = AXIOM_XPATH_PARSE_END; + + op1 = axiom_xpath_compile_orexpr(env, expr); + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(AXIOM_XPATH_CURRENT == ',') + { + op2 = axiom_xpath_compile_argument(env, expr); + } + + return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_ARGUMENT, op1, op2); +} + +axiom_xpath_node_test_t* +axiom_xpath_create_node_test_all( + const axutil_env_t *env) +{ + axiom_xpath_node_test_t *node_test; + + node_test = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_node_test_t)); + node_test->type = AXIOM_XPATH_NODE_TEST_ALL; + node_test->prefix = NULL; + node_test->name = NULL; + node_test->lit = NULL; + + return node_test; +} + +axiom_xpath_node_test_t* +axiom_xpath_create_node_test_node( + const axutil_env_t *env) +{ + axiom_xpath_node_test_t *node_test; + + node_test = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_node_test_t)); + node_test->type = AXIOM_XPATH_NODE_TYPE_NODE; + node_test->prefix = NULL; + node_test->name = NULL; + node_test->lit = NULL; + + return node_test; +} + +double* +axiom_xpath_compile_number( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + double *ret = AXIS2_MALLOC(env->allocator, sizeof(double)); + double res = 0, dec = 0.1; + axis2_bool_t dot = AXIS2_FALSE; + + *ret = 0; + + while(1) + { + if(isdigit(AXIOM_XPATH_CURRENT)) + { + if(!dot) + { + res = res * 10 + (AXIOM_XPATH_CURRENT - '0'); + } + else + { + res += dec * (AXIOM_XPATH_CURRENT - '0'); + dec /= 10; + } + } + else if(AXIOM_XPATH_CURRENT == '.') + { + if(dot) + { + return ret; + } + else + { + dot = AXIS2_TRUE; + dec = 0.1; + } + } + else + { + break; + } + + AXIOM_XPATH_READ(1); + } + + *ret = res; + return ret; +} + +axis2_char_t* +axiom_xpath_compile_literal( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + axis2_char_t lit[255]; + int i = 0; + axis2_char_t del; + + if(AXIOM_XPATH_CURRENT == '\"') + { + del = '\"'; + } + else if(AXIOM_XPATH_CURRENT == '\'') + { + del = '\''; + } + else + return NULL; + + AXIOM_XPATH_READ(1); + + while(AXIOM_XPATH_HAS_MORE && AXIOM_XPATH_CURRENT != del) + { + lit[i] = AXIOM_XPATH_CURRENT; + AXIOM_XPATH_READ(1); + ++i; + } + + if(AXIOM_XPATH_HAS_MORE) + { + AXIOM_XPATH_READ(1); + } + + lit[i] = '\0'; + + return axutil_strdup(env, lit); + +} + +/* Get axis for name */ +axiom_xpath_axis_t +axiom_xpath_get_axis( + const axutil_env_t *env, + axis2_char_t* name) +{ + if(axutil_strcmp(name, "child") == 0) + { + return AXIOM_XPATH_AXIS_CHILD; + } + else if(axutil_strcmp(name, "descendant") == 0) + { + return AXIOM_XPATH_AXIS_DESCENDANT; + } + else if(axutil_strcmp(name, "parent") == 0) + { + return AXIOM_XPATH_AXIS_PARENT; + } + else if(axutil_strcmp(name, "ancestor") == 0) + { + return AXIOM_XPATH_AXIS_ANCESTOR; + } + else if(axutil_strcmp(name, "following-sibling") == 0) + { + return AXIOM_XPATH_AXIS_FOLLOWING_SIBLING; + } + else if(axutil_strcmp(name, "preceding-sibling") == 0) + { + return AXIOM_XPATH_AXIS_PRECEDING_SIBLING; + } + else if(axutil_strcmp(name, "following") == 0) + { + return AXIOM_XPATH_AXIS_FOLLOWING; + } + else if(axutil_strcmp(name, "preceding") == 0) + { + return AXIOM_XPATH_AXIS_PRECEDING; + } + else if(axutil_strcmp(name, "attribute") == 0) + { + return AXIOM_XPATH_AXIS_ATTRIBUTE; + } + else if(axutil_strcmp(name, "namespace") == 0) + { + return AXIOM_XPATH_AXIS_NAMESPACE; + } + else if(axutil_strcmp(name, "self") == 0) + { + return AXIOM_XPATH_AXIS_SELF; + } + else if(axutil_strcmp(name, "descendant-or-self") == 0) + { + return AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF; + } + else if(axutil_strcmp(name, "ancestor-or-self") == 0) + { + return AXIOM_XPATH_AXIS_ANCESTOR_OR_SELF; + } + else + { +#ifdef AXIOM_XPATH_DEBUG + printf("Unidentified axis name.\n"); +#endif + + return AXIOM_XPATH_AXIS_NONE; + } +} + +/* Parse Predicate */ +int +axiom_xpath_compile_predicate( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + int op1, op_next_predicate; + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(!AXIOM_XPATH_HAS_MORE || AXIOM_XPATH_CURRENT != '[') + { + return AXIOM_XPATH_PARSE_END; + } + + AXIOM_XPATH_READ(1); + AXIOM_XPATH_SKIP_WHITESPACES; + + /* A PredicateExpr is evaluated by evaluating the Expr and converting the result to a boolean. + If the result is a number, the result will be converted to true if the number is equal to the + context position and will be converted to false otherwise; if the result is not a number, + then the result will be converted as if by a call to the boolean function. */ + + op1 = axiom_xpath_compile_orexpr(env, expr); + + if(op1 == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: EqualExpr expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_SKIP_WHITESPACES; + + if(AXIOM_XPATH_CURRENT != ']') + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: ] expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + AXIOM_XPATH_READ(1); + + op_next_predicate = axiom_xpath_compile_predicate(env, expr); + + if(op_next_predicate == AXIOM_XPATH_PARSE_ERROR) + { +#ifdef AXIOM_XPATH_DEBUG + printf( + "Parse error: Predicate expected - %s\n", + expr->expr_str + expr->expr_ptr); +#endif + + return AXIOM_XPATH_PARSE_ERROR; + } + + return AXIOM_XPATH_PUSH(AXIOM_XPATH_OPERATION_PREDICATE, op1, op_next_predicate); +} + +/* Parse Node Test */ +axis2_char_t * +axiom_xpath_compile_ncname( + const axutil_env_t *env, + axiom_xpath_expression_t* expr) +{ + axis2_char_t name[255]; + int i = 0; + + if(!isalpha(AXIOM_XPATH_CURRENT) && AXIOM_XPATH_CURRENT != '_') + { + return NULL; + } + + /* TODO: Add CombiningChar and Extender + * Link http://www.w3.org/TR/REC-xml/#NT-NameChar */ + while(AXIOM_XPATH_HAS_MORE && (isalnum(AXIOM_XPATH_CURRENT) || AXIOM_XPATH_CURRENT == '_' + || AXIOM_XPATH_CURRENT == '.' || AXIOM_XPATH_CURRENT == '-')) + { + name[i] = AXIOM_XPATH_CURRENT; + AXIOM_XPATH_READ(1); + ++i; + } + + name[i] = '\0'; + + return axutil_strdup(env, name); +} + +/* Supporting functions */ +int +axiom_xpath_add_operation( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + axiom_xpath_operation_type_t op_type, + int op1, + int op2, + void *par1, + void *par2) +{ + axiom_xpath_operation_t *op; + + op = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_operation_t)); + op->opr = op_type; + op->op1 = op1; + op->op2 = op2; + + op->pos = 0; + + op->par1 = par1; + op->par2 = par2; + + axutil_array_list_add(expr->operations, env, op); + + return axutil_array_list_size(expr->operations, env) - 1; +} + +axiom_xpath_axis_t * +axiom_xpath_create_axis( + const axutil_env_t *env, + axiom_xpath_axis_t axis) +{ + axiom_xpath_axis_t *axis_p = AXIS2_MALLOC(env->allocator, sizeof(axiom_xpath_axis_t)); + + *axis_p = axis; + return axis_p; +} diff --git a/axiom/src/xpath/xpath_internals_parser.h b/axiom/src/xpath/xpath_internals_parser.h new file mode 100755 index 0000000..7d1a2d0 --- /dev/null +++ b/axiom/src/xpath/xpath_internals_parser.h @@ -0,0 +1,421 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIOM_XPATH_INTERNALS_PARSER_H +#define AXIOM_XPATH_INTERNALS_PARSER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @defgroup axiom_xpath_parser parser + * @ingroup axiom_xpath + * @{ + */ + + + /* Macros */ + + /** Get the current character in the expression */ +#define AXIOM_XPATH_CURRENT (expr->expr_ptr < expr->expr_len ? \ + expr->expr_str[expr->expr_ptr] : -1) + + /** Get a character after the current */ +#define AXIOM_XPATH_NEXT(ind) (expr->expr_ptr + ind < expr->expr_len ? \ + expr->expr_str[expr->expr_ptr + ind] : -1) + + /** Increment the pointer to the expression */ +#define AXIOM_XPATH_READ(n) (expr->expr_ptr += n) + + /** Check if expression has finished parsing */ +#define AXIOM_XPATH_HAS_MORE (expr->expr_ptr < expr->expr_len) + + /** Skip white spaces */ +#define AXIOM_XPATH_SKIP_WHITESPACES \ + { while(AXIOM_XPATH_CURRENT == ' ') \ + AXIOM_XPATH_READ(1); \ + } + + /** Wrape an operation in a self_or_descendent step; used to handle '//' */ +#define AXIOM_XPATH_WRAP_SELF_DESCENDANT(_op2) \ + axiom_xpath_add_operation(env, expr, AXIOM_XPATH_OPERATION_STEP, \ + axiom_xpath_add_operation(env, expr, AXIOM_XPATH_OPERATION_NODE_TEST, \ + AXIOM_XPATH_PARSE_END, AXIOM_XPATH_PARSE_END, \ + axiom_xpath_create_node_test_node(env), \ + axiom_xpath_create_axis(env, AXIOM_XPATH_AXIS_DESCENDANT_OR_SELF)), \ + _op2, NULL, NULL) + + /** Adds an operation */ +#define AXIOM_XPATH_PUSH(_opr, _op1, _op2) axiom_xpath_add_operation( \ + env, expr, _opr, _op1, _op2, NULL, NULL) + + /** Adds an operation with parameters */ +#define AXIOM_XPATH_PUSH_PAR(_opr, _par1, _par2, _op1) axiom_xpath_add_operation( \ + env, expr, _opr, _op1, AXIOM_XPATH_PARSE_END, (void *)_par1, (void *)_par2) + + /* Functions */ + + /** + * Add an operation to the operations array + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @param op_type Type of the operation + * @param op1 First operand + * @param op2 Second operand + * @param par1 First parameter + * @param par2 Second parameter + * @return Index of the operation in the array + */ + int axiom_xpath_add_operation( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + axiom_xpath_operation_type_t op_type, + int op1, + int op2, + void *par1, + void *par2); + + /** + * Compile a XPath expression + * + * [14] Expr ::= OrExpr + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the main operation in the array + */ + int axiom_xpath_compile( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile an equals expression + * + * ***Not completed*** + * [23] EqualityExpr ::= UnionExpr '=' UnionExpr + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_equalexpr( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile an union + * + * [18] UnionExpr ::= PathExpr + * | UnionExpr '|' PathExpr + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_union( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a path expression + * + * [19] PathExpr ::= LocationPath + * | FilterExpr + * | FilterExpr '/' RelativeLocationPath + * | FilterExpr '//' RelativeLocationPath + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_path_expression( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a path expression with a filter + * + * [19] PathExpr ::= FilterExpr + * | FilterExpr '/' RelativeLocationPath + * | FilterExpr '//' RelativeLocationPath + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_path_compile_path_expression_filter( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a filter expression + * + * 20] FilterExpr ::= PrimaryExpr + * | FilterExpr Predicate + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_filter( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a location path + * + * [1] LocationPath ::= RelativeLocationPath + * | AbsoluteLocationPath + * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? + * | AbbreviatedAbsoluteLocationPath + * + * [10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath + * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_location_path( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a relative location + * + * [3] RelativeLocationPath ::= Step + * | RelativeLocationPath '/' Step + * | AbbreviatedRelativeLocationPath + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_relative_location( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a step + * + * [4] Step ::= AxisSpecifier NodeTest Predicate* + * | AbbreviatedStep + * [5] AxisSpecifier ::= AxisName '::' + * | AbbreviatedAxisSpecifier + * + * [12] AbbreviatedStep ::= '.' | '..' + * [13] AbbreviatedAxisSpecifier ::= '@'? + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_step( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compiles an OrExpr. + * + * [21] OrExpr ::= AndExpr + * | OrExpr 'or' AndExpr + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_orexpr( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compiles an AndExpr. + * + * [22] AndExpr ::= EqualityExpr + * | AndExpr 'and' EqualityExpr + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_andexpr( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + + /** + * Compiles a FunctionCall + * + * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_function_call( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compiles an Argument. + * + * [17] Argument ::= Expr + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_argument( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a node test + * + * [7] NodeTest ::= NameTest + * | NodeType '(' ')' + * | 'processing-instruction' '(' Literal ')' + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + axiom_xpath_node_test_t* axiom_xpath_compile_node_test( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a predicate(s) + * + * [8] Predicate ::= '[' PredicateExpr ']' + * [9] PredicateExpr ::= Expr + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return Index of the operation in the array + */ + int axiom_xpath_compile_predicate( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + + + /** + * Compile a literal + * + * [29] Literal ::= '"' [^"]* '"' + * | "'" [^']* "'" + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return The literal parsed + */ + axis2_char_t* axiom_xpath_compile_literal( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a number + * + * [30] Number ::= Digits ('.' Digits?)? + * | '.' Digits + * [31] Digits ::= [0-9]+ + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return The number parsed + */ + double* axiom_xpath_compile_number( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + /** + * Compile a ncname + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @return The ncname parsed + */ + axis2_char_t* axiom_xpath_compile_ncname( + const axutil_env_t *env, + axiom_xpath_expression_t* expr); + + + + /** + * Get the XPath axis by axis name + * + * [6] AxisName ::= 'ancestor' + * | 'ancestor-or-self' + * | 'attribute' + * | 'child' + * | 'descendant' + * | 'descendant-or-self' + * | 'following' + * | 'following-sibling' + * | 'namespace' + * | 'parent' + * | 'preceding' + * | 'preceding-sibling' + * | 'self' + * + * @param env Environment must not be null + * @param name Name of the axis + * @return XPath axis; returns AXIOM_XPATH_AXIS_NONE if invalid name + */ + axiom_xpath_axis_t axiom_xpath_get_axis( + const axutil_env_t *env, + axis2_char_t* name); + + /** + * Create a node test which matches all nodes (*) + * + * @param env Environment must not be null + * @return Node test + */ + axiom_xpath_node_test_t* axiom_xpath_create_node_test_all( + const axutil_env_t *env); + + /** + * Create a node test which matches all nodes (nodes()) + * + * @param env Environment must not be null + * @return Node test + */ + axiom_xpath_node_test_t* axiom_xpath_create_node_test_node( + const axutil_env_t *env); + + /** + * Create a pointer to an axis; allocate memory using the allocator + * + * @param env Environment must not be null + * @param axis XPath axis + * @return Pointer to the axis created + */ + axiom_xpath_axis_t *axiom_xpath_create_axis( + const axutil_env_t *env, + axiom_xpath_axis_t axis); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/axiom/src/xpath/xpath_streaming.c b/axiom/src/xpath/xpath_streaming.c new file mode 100755 index 0000000..0488d5f --- /dev/null +++ b/axiom/src/xpath/xpath_streaming.c @@ -0,0 +1,213 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "xpath_streaming.h" +#include "xpath_internals.h" +#include "xpath_internals_engine.h" + +axiom_xpath_streaming_t +axiom_xpath_streaming_check_operation( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + int op_p) +{ + axiom_xpath_operation_t *op; + + if(op_p == AXIOM_XPATH_PARSE_END) + { + return AXIOM_XPATH_STREAMING_CONSTANT; + } + + op = AXIOM_XPATH_OPR_EXPR_GET(op_p); + + switch(op->opr) + { + case AXIOM_XPATH_OPERATION_CONTEXT_NODE: + case AXIOM_XPATH_OPERATION_ROOT_NODE: + return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), + AXIOM_XPATH_STREAMING_CONSTANT); + + case AXIOM_XPATH_OPERATION_STEP: + return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), + AXIOM_XPATH_CHECK(op->op2)); + + case AXIOM_XPATH_OPERATION_RESULT: + return AXIOM_XPATH_STREAMING_CONSTANT; + + case AXIOM_XPATH_OPERATION_UNION: + return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1), + AXIOM_XPATH_CHECK(op->op2)); + + case AXIOM_XPATH_OPERATION_EQUAL_EXPR: + return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1), + AXIOM_XPATH_CHECK(op->op2)); + + case AXIOM_XPATH_OPERATION_LITERAL: + return AXIOM_XPATH_STREAMING_CONSTANT; + + case AXIOM_XPATH_OPERATION_NUMBER: + return AXIOM_XPATH_STREAMING_CONSTANT; + + case AXIOM_XPATH_OPERATION_PATH_EXPRESSION: + return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), + AXIOM_XPATH_CHECK(op->op2)); + + case AXIOM_XPATH_OPERATION_NODE_TEST: + return axiom_xpath_streaming_check_node_test(env, expr, op); + + case AXIOM_XPATH_OPERATION_PREDICATE: + return axiom_xpath_streaming_check_predicate(env, expr, op_p); + + default: +#ifdef AXIOM_XPATH_DEBUG + printf("Unidentified operation.\n"); +#endif + + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } +} + +axiom_xpath_streaming_t +axiom_xpath_streaming_check_predicate( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + int op_p) +{ + axiom_xpath_operation_t *op; + + if(op_p == AXIOM_XPATH_PARSE_END) + { + return AXIOM_XPATH_STREAMING_CONSTANT; + } + + op = AXIOM_XPATH_OPR_EXPR_GET(op_p); + + return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), AXIOM_XPATH_CHECK( + op->op2)); +} + +axiom_xpath_streaming_t +axiom_xpath_streaming_check_node_test( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + axiom_xpath_operation_t *op) +{ + axiom_xpath_axis_t axis = AXIOM_XPATH_AXIS_NONE; + axiom_xpath_streaming_t r; + + if(!op->par2) + { +#ifdef AXIOM_XPATH_DEBUG + printf("axis is NULL in the step operator\n"); +#endif + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } + + axis = *((axiom_xpath_axis_t *)op->par2); + + switch(axis) + { + case AXIOM_XPATH_AXIS_ATTRIBUTE: + case AXIOM_XPATH_AXIS_CHILD: + break; + + default: + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } + + r = axiom_xpath_streaming_check_predicate(env, expr, op->op1); + + if(r != AXIOM_XPATH_STREAMING_ATTRIBUTE && r != AXIOM_XPATH_STREAMING_CONSTANT) + { + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } + + if(axis == AXIOM_XPATH_AXIS_ATTRIBUTE) + { + return AXIOM_XPATH_STREAMING_ATTRIBUTE; + } + else + { + return AXIOM_XPATH_STREAMING_SUPPORTED; + } +} + +axiom_xpath_streaming_t +axiom_xpath_streaming_combine_dependent( + axiom_xpath_streaming_t r1, + axiom_xpath_streaming_t r2) +{ + if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED) + { + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } + else if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED) + { + return AXIOM_XPATH_STREAMING_SUPPORTED; + } + else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE) + { + return AXIOM_XPATH_STREAMING_ATTRIBUTE; + } + else + { + return AXIOM_XPATH_STREAMING_CONSTANT; + } +} + +axiom_xpath_streaming_t +axiom_xpath_streaming_combine_independent( + axiom_xpath_streaming_t r1, + axiom_xpath_streaming_t r2) +{ + if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED) + { + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } + else if(r1 == AXIOM_XPATH_STREAMING_CONSTANT || r2 == AXIOM_XPATH_STREAMING_CONSTANT) + { + if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED) + { + return AXIOM_XPATH_STREAMING_SUPPORTED; + } + else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE) + { + return AXIOM_XPATH_STREAMING_ATTRIBUTE; + } + else + { + return AXIOM_XPATH_STREAMING_CONSTANT; + } + } + else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE) + { + if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED) + { + return AXIOM_XPATH_STREAMING_SUPPORTED; + } + else + { + return AXIOM_XPATH_STREAMING_ATTRIBUTE; + } + } + else + { + return AXIOM_XPATH_STREAMING_NOT_SUPPORTED; + } +} + diff --git a/axiom/src/xpath/xpath_streaming.h b/axiom/src/xpath/xpath_streaming.h new file mode 100755 index 0000000..63b1ee5 --- /dev/null +++ b/axiom/src/xpath/xpath_streaming.h @@ -0,0 +1,126 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIOM_XPATH_STREAMING_H +#define AXIOM_XPATH_STREAMING_H + +#include "xpath_internals.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @defgroup axiom_xpath_streaming streaming + * @ingroup axiom_xpath + * @{ + */ + + + /** + * XPath streaming support + */ + typedef enum axiom_xpath_streaming_t + { + AXIOM_XPATH_STREAMING_NOT_SUPPORTED = 0, + AXIOM_XPATH_STREAMING_SUPPORTED, + AXIOM_XPATH_STREAMING_CONSTANT, + AXIOM_XPATH_STREAMING_ATTRIBUTE + } axiom_xpath_streaming_t; + + /** Check whether the given expression is supported on streaming XML */ +#define AXIOM_XPATH_CHECK(op) axiom_xpath_streaming_check_operation(env, expr, op) + + /** Get an operation from the list of operations */ +#define AXIOM_XPATH_OPR_EXPR_GET(ind) (axiom_xpath_operation_t *) \ + axutil_array_list_get(expr->operations, env, ind) + + /** + * Checks whether the given expression is supported on streaming XML + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @param op_p Index of the operation in the list of operations + * @return Whether the given operation can be evaluated on streaming XML + */ + axiom_xpath_streaming_t axiom_xpath_streaming_check_operation( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + int op_p); + + /** + * Checks whether the predicate is supported on streaming XML. + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @param op_p Index of the operation in the list of operations + * @return Whether the given operation can be evaluated on streaming XML + */ + axiom_xpath_streaming_t axiom_xpath_streaming_check_predicate( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + int op_p); + + /** + * Checks whether the predicate is supported on streaming XML. + * + * @param env Environment must not be null + * @param expr A pointer to the XPath expression + * @param op Index of the operation in the list of operations + * @return Whether the given operation can be evaluated on streaming XML + */ + axiom_xpath_streaming_t axiom_xpath_streaming_check_node_test( + const axutil_env_t *env, + axiom_xpath_expression_t* expr, + axiom_xpath_operation_t* op); + + + /** + * Checks whether the two operations can be evaluated on streaming XML + * sequencially (one after the other), where the result of the first + * operation is the context of the next + * + * @param r1 Type of first operation + * @param r2 Type of second operation + * @return Whether the given operations can be evaluated on streaming XML + */ + axiom_xpath_streaming_t axiom_xpath_streaming_combine_dependent( + axiom_xpath_streaming_t r1, + axiom_xpath_streaming_t r2); + + + /** + * Checks whether the two operations can be evaluated on streaming XML + * simultaneousy + * + * @param r1 Type of first operation + * @param r2 Type of second operation + * @return Whether the given operations can be evaluated on streaming XML + */ + axiom_xpath_streaming_t axiom_xpath_streaming_combine_independent( + axiom_xpath_streaming_t r1, + axiom_xpath_streaming_t r2); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.1-32-gdbae