summaryrefslogtreecommitdiff
path: root/xpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpath.c')
-rw-r--r--xpath.c636
1 files changed, 254 insertions, 382 deletions
diff --git a/xpath.c b/xpath.c
index 97410e7..d9d902c 100644
--- a/xpath.c
+++ b/xpath.c
@@ -55,8 +55,6 @@
#include <libxml/pattern.h>
#endif
-#include "buf.h"
-
#ifdef LIBXML_PATTERN_ENABLED
#define XPATH_STREAMING
#endif
@@ -66,15 +64,6 @@
"Unimplemented block at %s:%d\n", \
__FILE__, __LINE__);
-/**
- * WITH_TIM_SORT:
- *
- * Use the Timsort algorithm provided in timsort.h to sort
- * nodeset as this is a great improvement over the old Shell sort
- * used in xmlXPathNodeSetSort()
- */
-#define WITH_TIM_SORT
-
/*
* XP_OPTIMIZED_NON_ELEM_COMPARISON:
* If defined, this will use xmlXPathCmpNodesExt() instead of
@@ -101,76 +90,12 @@
/* #define XP_DEBUG_OBJ_USAGE */
/*
- * XPATH_MAX_STEPS:
- * when compiling an XPath expression we arbitrary limit the maximum
- * number of step operation in the compiled expression. 1000000 is
- * an insanely large value which should never be reached under normal
- * circumstances
- */
-#define XPATH_MAX_STEPS 1000000
-
-/*
- * XPATH_MAX_STACK_DEPTH:
- * when evaluating an XPath expression we arbitrary limit the maximum
- * number of object allowed to be pushed on the stack. 1000000 is
- * an insanely large value which should never be reached under normal
- * circumstances
- */
-#define XPATH_MAX_STACK_DEPTH 1000000
-
-/*
- * XPATH_MAX_NODESET_LENGTH:
- * when evaluating an XPath expression nodesets are created and we
- * arbitrary limit the maximum length of those node set. 10000000 is
- * an insanely large value which should never be reached under normal
- * circumstances, one would first need to construct an in memory tree
- * with more than 10 millions nodes.
- */
-#define XPATH_MAX_NODESET_LENGTH 10000000
-
-/*
* TODO:
* There are a few spots where some tests are done which depend upon ascii
* data. These should be enhanced for full UTF8 support (see particularly
* any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
*/
-/*
- * Wrapper for the Timsort argorithm from timsort.h
- */
-#ifdef WITH_TIM_SORT
-#define SORT_NAME libxml_domnode
-#define SORT_TYPE xmlNodePtr
-/**
- * wrap_cmp:
- * @x: a node
- * @y: another node
- *
- * Comparison function for the Timsort implementation
- *
- * Returns -2 in case of error -1 if first point < second point, 0 if
- * it's the same node, +1 otherwise
- */
-static
-int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
-#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
- static int xmlXPathCmpNodesExt(xmlNodePtr, xmlNodePtr);
- static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
- {
- int res = xmlXPathCmpNodesExt(x, y);
- return res == -2 ? res : -res;
- }
-#else
- static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
- {
- int res = xmlXPathCmpNodes(x, y);
- return res == -2 ? res : -res;
- }
-#endif
-#define SORT_CMP(x, y) (wrap_cmp(x, y))
-#include "timsort.h"
-#endif /* WITH_TIM_SORT */
-
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
/************************************************************************
@@ -328,7 +253,6 @@ static const char *xmlXPathErrorMessages[] = {
"Char out of XML range\n",
"Invalid or incomplete context\n",
"Stack usage errror\n",
- "Forbidden variable\n",
"?? Unknown error ??\n" /* Must be last in the list! */
};
#define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
@@ -496,7 +420,8 @@ xmlPointerListAddSize(xmlPointerListPtr list,
if (list->items == NULL) {
if (initialSize <= 0)
initialSize = 1;
- list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
+ list->items = (void **) xmlMalloc(
+ initialSize * sizeof(void *));
if (list->items == NULL) {
xmlXPathErrMemory(NULL,
"xmlPointerListCreate: allocating item\n");
@@ -505,17 +430,12 @@ xmlPointerListAddSize(xmlPointerListPtr list,
list->number = 0;
list->size = initialSize;
} else if (list->size <= list->number) {
- if (list->size > 50000000) {
- xmlXPathErrMemory(NULL,
- "xmlPointerListAddSize: re-allocating item\n");
- return(-1);
- }
list->size *= 2;
list->items = (void **) xmlRealloc(list->items,
list->size * sizeof(void *));
if (list->items == NULL) {
xmlXPathErrMemory(NULL,
- "xmlPointerListAddSize: re-allocating item\n");
+ "xmlPointerListCreate: re-allocating item\n");
list->size = 0;
return(-1);
}
@@ -633,6 +553,8 @@ typedef enum {
NODE_TYPE_PI = XML_PI_NODE
} xmlXPathTypeVal;
+#define XP_REWRITE_DOS_CHILD_ELEM 1
+
typedef struct _xmlXPathStepOp xmlXPathStepOp;
typedef xmlXPathStepOp *xmlXPathStepOpPtr;
struct _xmlXPathStepOp {
@@ -646,6 +568,7 @@ struct _xmlXPathStepOp {
void *value5;
void *cache;
void *cacheURI;
+ int rewriteType;
};
struct _xmlXPathCompExpr {
@@ -800,10 +723,6 @@ xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
if (comp->nbStep >= comp->maxStep) {
xmlXPathStepOp *real;
- if (comp->maxStep >= XPATH_MAX_STEPS) {
- xmlXPathErrMemory(NULL, "adding step\n");
- return(-1);
- }
comp->maxStep *= 2;
real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
comp->maxStep * sizeof(xmlXPathStepOp));
@@ -815,6 +734,7 @@ xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
comp->steps = real;
}
comp->last = comp->nbStep;
+ comp->steps[comp->nbStep].rewriteType = 0;
comp->steps[comp->nbStep].ch1 = ch1;
comp->steps[comp->nbStep].ch2 = ch2;
comp->steps[comp->nbStep].op = op;
@@ -2132,11 +2052,6 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val)
ret->type = XPATH_NODESET;
ret->boolval = 0;
ret->nodesetval = xmlXPathNodeSetCreate(val);
- if (ret->nodesetval == NULL) {
- ctxt->lastError.domain = XML_FROM_XPATH;
- ctxt->lastError.code = XML_ERR_NO_MEMORY;
- return(NULL);
- }
#ifdef XP_DEBUG_OBJ_USAGE
xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
#endif
@@ -2565,16 +2480,11 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
if (ctxt->valueNr >= ctxt->valueMax) {
xmlXPathObjectPtr *tmp;
- if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
- xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n");
- ctxt->error = XPATH_MEMORY_ERROR;
- return (0);
- }
tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
2 * ctxt->valueMax *
sizeof(ctxt->valueTab[0]));
if (tmp == NULL) {
- xmlXPathErrMemory(NULL, "pushing value\n");
+ xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
ctxt->error = XPATH_MEMORY_ERROR;
return (0);
}
@@ -3410,19 +3320,13 @@ turtle_comparison:
*/
void
xmlXPathNodeSetSort(xmlNodeSetPtr set) {
-#ifndef WITH_TIM_SORT
int i, j, incr, len;
xmlNodePtr tmp;
-#endif
if (set == NULL)
return;
-#ifndef WITH_TIM_SORT
- /*
- * Use the old Shell's sort implementation to sort the node-set
- * Timsort ought to be quite faster
- */
+ /* Use Shell's sort to sort the node-set */
len = set->nodeNr;
for (incr = len / 2; incr > 0; incr /= 2) {
for (i = incr; i < len; i++) {
@@ -3445,9 +3349,6 @@ xmlXPathNodeSetSort(xmlNodeSetPtr set) {
}
}
}
-#else /* WITH_TIM_SORT */
- libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
-#endif /* WITH_TIM_SORT */
}
#define XML_NODESET_DEFAULT 10
@@ -3626,10 +3527,8 @@ xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
* @ns: a the namespace node
*
* add a new namespace node to an existing NodeSet
- *
- * Returns 0 in case of success and -1 in case of error
*/
-int
+void
xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
int i;
@@ -3637,7 +3536,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
(ns->type != XML_NAMESPACE_DECL) ||
(node->type != XML_ELEMENT_NODE))
- return(-1);
+ return;
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
/*
@@ -3648,7 +3547,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
(cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
(((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
(xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
- return(0);
+ return;
}
/*
@@ -3659,7 +3558,7 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
sizeof(xmlNodePtr));
if (cur->nodeTab == NULL) {
xmlXPathErrMemory(NULL, "growing nodeset\n");
- return(-1);
+ return;
}
memset(cur->nodeTab, 0 ,
XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
@@ -3667,21 +3566,16 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
} else if (cur->nodeNr == cur->nodeMax) {
xmlNodePtr *temp;
- if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
- xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
- return(-1);
- }
temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
sizeof(xmlNodePtr));
if (temp == NULL) {
xmlXPathErrMemory(NULL, "growing nodeset\n");
- return(-1);
+ return;
}
cur->nodeMax *= 2;
cur->nodeTab = temp;
}
cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
- return(0);
}
/**
@@ -3690,21 +3584,24 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
* @val: a new xmlNodePtr
*
* add a new xmlNodePtr to an existing NodeSet
- *
- * Returns 0 in case of success, and -1 in case of error
*/
-int
+void
xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
int i;
- if ((cur == NULL) || (val == NULL)) return(-1);
+ if ((cur == NULL) || (val == NULL)) return;
+
+#if 0
+ if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
+ return; /* an XSLT fake node */
+#endif
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
/*
* prevent duplcates
*/
for (i = 0;i < cur->nodeNr;i++)
- if (cur->nodeTab[i] == val) return(0);
+ if (cur->nodeTab[i] == val) return;
/*
* grow the nodeTab if needed
@@ -3714,7 +3611,7 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
sizeof(xmlNodePtr));
if (cur->nodeTab == NULL) {
xmlXPathErrMemory(NULL, "growing nodeset\n");
- return(-1);
+ return;
}
memset(cur->nodeTab, 0 ,
XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
@@ -3722,15 +3619,11 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
} else if (cur->nodeNr == cur->nodeMax) {
xmlNodePtr *temp;
- if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
- xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
- return(-1);
- }
temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
sizeof(xmlNodePtr));
if (temp == NULL) {
xmlXPathErrMemory(NULL, "growing nodeset\n");
- return(-1);
+ return;
}
cur->nodeMax *= 2;
cur->nodeTab = temp;
@@ -3742,7 +3635,6 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
} else
cur->nodeTab[cur->nodeNr++] = val;
- return(0);
}
/**
@@ -3752,12 +3644,15 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
*
* add a new xmlNodePtr to an existing NodeSet, optimized version
* when we are sure the node is not already in the set.
- *
- * Returns 0 in case of success and -1 in case of failure
*/
-int
+void
xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
- if ((cur == NULL) || (val == NULL)) return(-1);
+ if ((cur == NULL) || (val == NULL)) return;
+
+#if 0
+ if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
+ return; /* an XSLT fake node */
+#endif
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
/*
@@ -3768,7 +3663,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
sizeof(xmlNodePtr));
if (cur->nodeTab == NULL) {
xmlXPathErrMemory(NULL, "growing nodeset\n");
- return(-1);
+ return;
}
memset(cur->nodeTab, 0 ,
XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
@@ -3776,15 +3671,11 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
} else if (cur->nodeNr == cur->nodeMax) {
xmlNodePtr *temp;
- if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
- xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
- return(-1);
- }
temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
sizeof(xmlNodePtr));
if (temp == NULL) {
xmlXPathErrMemory(NULL, "growing nodeset\n");
- return(-1);
+ return;
}
cur->nodeTab = temp;
cur->nodeMax *= 2;
@@ -3796,7 +3687,6 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
} else
cur->nodeTab[cur->nodeNr++] = val;
- return(0);
}
/**
@@ -3892,10 +3782,6 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
} else if (val1->nodeNr == val1->nodeMax) {
xmlNodePtr *temp;
- if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
- xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
- return(NULL);
- }
temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
sizeof(xmlNodePtr));
if (temp == NULL) {
@@ -3917,6 +3803,68 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
return(val1);
}
+#if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
+/**
+ * xmlXPathNodeSetMergeUnique:
+ * @val1: the first NodeSet or NULL
+ * @val2: the second NodeSet
+ *
+ * Merges two nodesets, all nodes from @val2 are added to @val1
+ * if @val1 is NULL, a new set is created and copied from @val2
+ *
+ * Returns @val1 once extended or NULL in case of error.
+ */
+static xmlNodeSetPtr
+xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
+ int i;
+
+ if (val2 == NULL) return(val1);
+ if (val1 == NULL) {
+ val1 = xmlXPathNodeSetCreate(NULL);
+ }
+ if (val1 == NULL)
+ return (NULL);
+
+ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
+
+ for (i = 0;i < val2->nodeNr;i++) {
+ /*
+ * grow the nodeTab if needed
+ */
+ if (val1->nodeMax == 0) {
+ val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
+ sizeof(xmlNodePtr));
+ if (val1->nodeTab == NULL) {
+ xmlXPathErrMemory(NULL, "merging nodeset\n");
+ return(NULL);
+ }
+ memset(val1->nodeTab, 0 ,
+ XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
+ val1->nodeMax = XML_NODESET_DEFAULT;
+ } else if (val1->nodeNr == val1->nodeMax) {
+ xmlNodePtr *temp;
+
+ val1->nodeMax *= 2;
+ temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
+ sizeof(xmlNodePtr));
+ if (temp == NULL) {
+ xmlXPathErrMemory(NULL, "merging nodeset\n");
+ return(NULL);
+ }
+ val1->nodeTab = temp;
+ }
+ if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
+
+ val1->nodeTab[val1->nodeNr++] =
+ xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
+ } else
+ val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
+ }
+
+ return(val1);
+}
+#endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
/**
* xmlXPathNodeSetMergeAndClear:
@@ -4003,10 +3951,6 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
} else if (set1->nodeNr >= set1->nodeMax) {
xmlNodePtr *temp;
- if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
- xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
- return(NULL);
- }
temp = (xmlNodePtr *) xmlRealloc(
set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
if (temp == NULL) {
@@ -4091,10 +4035,6 @@ xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
} else if (set1->nodeNr >= set1->nodeMax) {
xmlNodePtr *temp;
- if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
- xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
- return(NULL);
- }
temp = (xmlNodePtr *) xmlRealloc(
set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
if (temp == NULL) {
@@ -4393,12 +4333,9 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val)
ret = xmlXPathNewNodeSet(NULL);
else {
ret = xmlXPathNewNodeSet(val->nodeTab[0]);
- if (ret) {
- for (i = 1; i < val->nodeNr; ++i) {
- if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
- < 0) break;
- }
- }
+ if (ret)
+ for (i = 1; i < val->nodeNr; ++i)
+ xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);
}
return (ret);
@@ -4474,10 +4411,8 @@ xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
for (i = 0; i < l1; i++) {
cur = xmlXPathNodeSetItem(nodes1, i);
- if (!xmlXPathNodeSetContains(nodes2, cur)) {
- if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
- break;
- }
+ if (!xmlXPathNodeSetContains(nodes2, cur))
+ xmlXPathNodeSetAddUnique(ret, cur);
}
return(ret);
}
@@ -4510,10 +4445,8 @@ xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
for (i = 0; i < l1; i++) {
cur = xmlXPathNodeSetItem(nodes1, i);
- if (xmlXPathNodeSetContains(nodes2, cur)) {
- if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
- break;
- }
+ if (xmlXPathNodeSetContains(nodes2, cur))
+ xmlXPathNodeSetAddUnique(ret, cur);
}
return(ret);
}
@@ -4549,8 +4482,7 @@ xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
strval = xmlXPathCastNodeToString(cur);
if (xmlHashLookup(hash, strval) == NULL) {
xmlHashAddEntry(hash, strval, strval);
- if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
- break;
+ xmlXPathNodeSetAddUnique(ret, cur);
} else {
xmlFree(strval);
}
@@ -4642,8 +4574,7 @@ xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
cur = xmlXPathNodeSetItem(nodes, i);
if (cur == node)
break;
- if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
- break;
+ xmlXPathNodeSetAddUnique(ret, cur);
}
return(ret);
}
@@ -4747,8 +4678,7 @@ xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
cur = xmlXPathNodeSetItem(nodes, i);
if (cur == node)
break;
- if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
- break;
+ xmlXPathNodeSetAddUnique(ret, cur);
}
xmlXPathNodeSetSort(ret); /* bug 413451 */
return(ret);
@@ -7771,7 +7701,6 @@ xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
return(NULL);
}
-#if 0
/**
* xmlXPathNextDescendantOrSelfElemParent:
* @ctxt: the XPath Parser context
@@ -7799,7 +7728,7 @@ xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur,
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
- case XML_HTML_DOCUMENT_NODE:
+ case XML_HTML_DOCUMENT_NODE:
return(contextNode);
default:
return(NULL);
@@ -7847,7 +7776,6 @@ next_sibling:
}
return(NULL);
}
-#endif
/**
* xmlXPathNextDescendant:
@@ -7875,8 +7803,6 @@ xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
return(ctxt->context->node->children);
}
- if (cur->type == XML_NAMESPACE_DECL)
- return(NULL);
if (cur->children != NULL) {
/*
* Do not descend on entities declarations
@@ -8259,10 +8185,6 @@ xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
static int
xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
if ((ancestor == NULL) || (node == NULL)) return(0);
- if (node->type == XML_NAMESPACE_DECL)
- return(0);
- if (ancestor->type == XML_NAMESPACE_DECL)
- return(0);
/* nodes need to be in the same document */
if (ancestor->doc != node->doc) return(0);
/* avoid searching if ancestor or node is the root node */
@@ -8300,7 +8222,7 @@ xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
if (cur->type == XML_ATTRIBUTE_NODE)
return(cur->parent);
}
- if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
+ if (cur == NULL)
return (NULL);
if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
cur = cur->prev;
@@ -8347,8 +8269,6 @@ xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
return (NULL);
ctxt->ancestor = cur->parent;
}
- if (cur->type == XML_NAMESPACE_DECL)
- return(NULL);
if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
cur = cur->prev;
while (cur->prev == NULL) {
@@ -8556,7 +8476,7 @@ xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
int i = 0;
tmp = cur->nodesetval->nodeTab[0];
- if ((tmp != NULL) && (tmp->type != XML_NAMESPACE_DECL)) {
+ if (tmp != NULL) {
tmp = tmp->children;
while (tmp != NULL) {
tmp = tmp->next;
@@ -9226,7 +9146,7 @@ void
xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr str;
xmlXPathObjectPtr find;
- xmlBufPtr target;
+ xmlBufferPtr target;
const xmlChar *point;
int offset;
@@ -9236,16 +9156,16 @@ xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CAST_TO_STRING;
str = valuePop(ctxt);
- target = xmlBufCreate();
+ target = xmlBufferCreate();
if (target) {
point = xmlStrstr(str->stringval, find->stringval);
if (point) {
offset = (int)(point - str->stringval);
- xmlBufAdd(target, str->stringval, offset);
+ xmlBufferAdd(target, str->stringval, offset);
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
- xmlBufContent(target)));
- xmlBufFree(target);
+ xmlBufferContent(target)));
+ xmlBufferFree(target);
}
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, find);
@@ -9269,7 +9189,7 @@ void
xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr str;
xmlXPathObjectPtr find;
- xmlBufPtr target;
+ xmlBufferPtr target;
const xmlChar *point;
int offset;
@@ -9279,17 +9199,17 @@ xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CAST_TO_STRING;
str = valuePop(ctxt);
- target = xmlBufCreate();
+ target = xmlBufferCreate();
if (target) {
point = xmlStrstr(str->stringval, find->stringval);
if (point) {
offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
- xmlBufAdd(target, &str->stringval[offset],
+ xmlBufferAdd(target, &str->stringval[offset],
xmlStrlen(str->stringval) - offset);
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
- xmlBufContent(target)));
- xmlBufFree(target);
+ xmlBufferContent(target)));
+ xmlBufferFree(target);
}
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, find);
@@ -9313,7 +9233,7 @@ void
xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr obj = NULL;
xmlChar *source = NULL;
- xmlBufPtr target;
+ xmlBufferPtr target;
xmlChar blank;
if (ctxt == NULL) return;
@@ -9331,7 +9251,7 @@ xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
obj = valuePop(ctxt);
source = obj->stringval;
- target = xmlBufCreate();
+ target = xmlBufferCreate();
if (target && source) {
/* Skip leading whitespaces */
@@ -9345,16 +9265,16 @@ xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
blank = 0x20;
} else {
if (blank) {
- xmlBufAdd(target, &blank, 1);
+ xmlBufferAdd(target, &blank, 1);
blank = 0;
}
- xmlBufAdd(target, source, 1);
+ xmlBufferAdd(target, source, 1);
}
source++;
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
- xmlBufContent(target)));
- xmlBufFree(target);
+ xmlBufferContent(target)));
+ xmlBufferFree(target);
}
xmlXPathReleaseObject(ctxt->context, obj);
}
@@ -9385,7 +9305,7 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr str;
xmlXPathObjectPtr from;
xmlXPathObjectPtr to;
- xmlBufPtr target;
+ xmlBufferPtr target;
int offset, max;
xmlChar ch;
const xmlChar *point;
@@ -9400,7 +9320,7 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CAST_TO_STRING;
str = valuePop(ctxt);
- target = xmlBufCreate();
+ target = xmlBufferCreate();
if (target) {
max = xmlUTF8Strlen(to->stringval);
for (cptr = str->stringval; (ch=*cptr); ) {
@@ -9409,10 +9329,10 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
if (offset < max) {
point = xmlUTF8Strpos(to->stringval, offset);
if (point)
- xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
+ xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1));
}
} else
- xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
+ xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
/* Step to next character in input */
cptr++;
@@ -9438,8 +9358,8 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
}
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
- xmlBufContent(target)));
- xmlBufFree(target);
+ xmlBufferContent(target)));
+ xmlBufferFree(target);
xmlXPathReleaseObject(ctxt->context, str);
xmlXPathReleaseObject(ctxt->context, from);
xmlXPathReleaseObject(ctxt->context, to);
@@ -9946,7 +9866,7 @@ xmlChar *
xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
const xmlChar *in;
xmlChar *ret;
- size_t count = 0;
+ int count = 0;
if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
/*
@@ -9965,10 +9885,6 @@ xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
in++;
if ((*in > 0) && (*in < 0x80)) {
count = in - ctxt->cur;
- if (count > XML_MAX_NAME_LENGTH) {
- ctxt->cur = in;
- XP_ERRORNULL(XPATH_EXPR_ERROR);
- }
ret = xmlStrndup(ctxt->cur, count);
ctxt->cur = in;
return(ret);
@@ -10012,9 +9928,6 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
xmlChar *buffer;
int max = len * 2;
- if (len > XML_MAX_NAME_LENGTH) {
- XP_ERRORNULL(XPATH_EXPR_ERROR);
- }
buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
if (buffer == NULL) {
XP_ERRORNULL(XPATH_MEMORY_ERROR);
@@ -10026,9 +9939,6 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
if (len + 10 > max) {
- if (max > XML_MAX_NAME_LENGTH) {
- XP_ERRORNULL(XPATH_EXPR_ERROR);
- }
max *= 2;
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
@@ -10381,7 +10291,7 @@ xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
name, prefix);
SKIP_BLANKS;
if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
- XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
+ XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR);
}
}
@@ -11745,13 +11655,9 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
*/
if (contextObj == NULL)
contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
- else {
- if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
- contextNode) < 0) {
- ctxt->error = XPATH_MEMORY_ERROR;
- goto evaluation_exit;
- }
- }
+ else
+ xmlXPathNodeSetAddUnique(contextObj->nodesetval,
+ contextNode);
valuePush(ctxt, contextObj);
@@ -11897,13 +11803,9 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
*/
if (contextObj == NULL)
contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
- else {
- if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
- contextNode) < 0) {
- ctxt->error = XPATH_MEMORY_ERROR;
- goto evaluation_exit;
- }
- }
+ else
+ xmlXPathNodeSetAddUnique(contextObj->nodesetval,
+ contextNode);
frame = xmlXPathSetFrame(ctxt);
valuePush(ctxt, contextObj);
@@ -12075,25 +11977,22 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
#define XP_TEST_HIT \
if (hasAxisRange != 0) { \
if (++pos == maxPos) { \
- if (addNode(seq, cur) < 0) \
- ctxt->error = XPATH_MEMORY_ERROR; \
- goto axis_range_end; } \
+ addNode(seq, cur); \
+ goto axis_range_end; } \
} else { \
- if (addNode(seq, cur) < 0) \
- ctxt->error = XPATH_MEMORY_ERROR; \
+ addNode(seq, cur); \
if (breakOnFirstHit) goto first_hit; }
#define XP_TEST_HIT_NS \
if (hasAxisRange != 0) { \
if (++pos == maxPos) { \
hasNsNodes = 1; \
- if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
- ctxt->error = XPATH_MEMORY_ERROR; \
+ xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur); \
goto axis_range_end; } \
} else { \
hasNsNodes = 1; \
- if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
- ctxt->error = XPATH_MEMORY_ERROR; \
+ xmlXPathNodeSetAddNs(seq, \
+ xpctxt->node, (xmlNsPtr) cur); \
if (breakOnFirstHit) goto first_hit; }
xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
@@ -12113,6 +12012,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
xmlNodeSetPtr contextSeq;
int contextIdx;
xmlNodePtr contextNode;
+ /* The context node for a compound traversal */
+ xmlNodePtr outerContextNode;
/* The final resulting node set wrt to all context nodes */
xmlNodeSetPtr outSeq;
/*
@@ -12128,7 +12029,9 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
int breakOnFirstHit;
xmlXPathTraversalFunction next = NULL;
- int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
+ /* compound axis traversal */
+ xmlXPathTraversalFunctionExt outerNext = NULL;
+ void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
xmlXPathNodeSetMergeFunction mergeAndClear;
xmlNodePtr oldContextNode;
xmlXPathContextPtr xpctxt = ctxt->context;
@@ -12177,6 +12080,13 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
break;
case AXIS_CHILD:
last = NULL;
+ if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) {
+ /*
+ * This iterator will give us only nodes which can
+ * hold element nodes.
+ */
+ outerNext = xmlXPathNextDescendantOrSelfElemParent;
+ }
if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
(type == NODE_TYPE_NODE))
{
@@ -12306,13 +12216,32 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
addNode = xmlXPathNodeSetAddUnique;
outSeq = NULL;
seq = NULL;
+ outerContextNode = NULL;
contextNode = NULL;
contextIdx = 0;
- while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
- (ctxt->error == XPATH_EXPRESSION_OK)) {
- xpctxt->node = contextSeq->nodeTab[contextIdx++];
+ while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) {
+ if (outerNext != NULL) {
+ /*
+ * This is a compound traversal.
+ */
+ if (contextNode == NULL) {
+ /*
+ * Set the context for the outer traversal.
+ */
+ outerContextNode = contextSeq->nodeTab[contextIdx++];
+ contextNode = outerNext(NULL, outerContextNode);
+ } else
+ contextNode = outerNext(contextNode, outerContextNode);
+ if (contextNode == NULL)
+ continue;
+ /*
+ * Set the context for the main traversal.
+ */
+ xpctxt->node = contextNode;
+ } else
+ xpctxt->node = contextSeq->nodeTab[contextIdx++];
if (seq == NULL) {
seq = xmlXPathNodeSetCreate(NULL);
@@ -12399,7 +12328,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
break;
}
} else if (cur->type == type) {
- if (cur->type == XML_NAMESPACE_DECL)
+ if (type == XML_NAMESPACE_DECL)
XP_TEST_HIT_NS
else
XP_TEST_HIT
@@ -12510,7 +12439,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
}
break;
} /* switch(test) */
- } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
+ } while (cur != NULL);
goto apply_predicates;
@@ -12551,16 +12480,13 @@ first_hit: /* ---------------------------------------------------------- */
#endif
apply_predicates: /* --------------------------------------------------- */
- if (ctxt->error != XPATH_EXPRESSION_OK)
- goto error;
-
/*
* Apply predicates.
*/
if ((predOp != NULL) && (seq->nodeNr > 0)) {
/*
* E.g. when we have a "/foo[some expression][n]".
- */
+ */
/*
* QUESTION TODO: The old predicate evaluation took into
* account location-sets.
@@ -12569,7 +12495,7 @@ apply_predicates: /* --------------------------------------------------- */
* All what I learned now from the evaluation semantics
* does not indicate that a location-set will be processed
* here, so this looks OK.
- */
+ */
/*
* Iterate over all predicates, starting with the outermost
* predicate.
@@ -13062,10 +12988,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
tmp = xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node);
} else {
- if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
- ctxt->context->node) < 0) {
- ctxt->error = XPATH_MEMORY_ERROR;
- }
+ xmlXPathNodeSetAddUnique(tmp->nodesetval,
+ ctxt->context->node);
}
valuePush(ctxt, tmp);
if (op->ch2 != -1)
@@ -13178,10 +13102,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
tmp = xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node);
} else {
- if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
- ctxt->context->node) < 0) {
- ctxt->error = XPATH_MEMORY_ERROR;
- }
+ xmlXPathNodeSetAddUnique(tmp->nodesetval,
+ ctxt->context->node);
}
valuePush(ctxt, tmp);
ctxt->context->contextSize = oldset->nodeNr;
@@ -13199,8 +13121,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
*/
res = valuePop(ctxt);
if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
- if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) < 0)
- ctxt->error = XPATH_MEMORY_ERROR;
+ xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
}
/*
* Cleanup
@@ -13879,10 +13800,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
tmp = xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node);
} else {
- if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
- ctxt->context->node) < 0) {
- ctxt->error = XPATH_MEMORY_ERROR;
- }
+ xmlXPathNodeSetAddUnique(tmp->nodesetval,
+ ctxt->context->node);
}
valuePush(ctxt, tmp);
ctxt->context->contextSize = oldset->nodeNr;
@@ -13912,9 +13831,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
*/
res = valuePop(ctxt);
if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
- if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i])
- < 0)
- ctxt->error = XPATH_MEMORY_ERROR;
+ xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
}
/*
@@ -14277,7 +14194,7 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
if (toBool)
return(1);
xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
- (xmlNodePtr) ctxt->doc);
+ (xmlNodePtr) ctxt->doc);
} else {
/* Select "self::node()" */
if (toBool)
@@ -14370,11 +14287,7 @@ next_node:
} else if (ret == 1) {
if (toBool)
goto return_1;
- if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur)
- < 0) {
- ctxt->lastError.domain = XML_FROM_XPATH;
- ctxt->lastError.code = XML_ERR_NO_MEMORY;
- }
+ xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur);
}
if ((cur->children == NULL) || (depth >= max_depth)) {
ret = xmlStreamPop(patstream);
@@ -14390,7 +14303,6 @@ next_node:
}
scan_children:
- if (cur->type == XML_NAMESPACE_DECL) break;
if ((cur->children != NULL) && (depth < max_depth)) {
/*
* Do not descend on entities declarations
@@ -14711,63 +14623,57 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
}
#endif /* XPATH_STREAMING */
+static int
+xmlXPathCanRewriteDosExpression(xmlChar *expr)
+{
+ if (expr == NULL)
+ return(0);
+ do {
+ if ((*expr == '/') && (*(++expr) == '/'))
+ return(1);
+ } while (*expr++);
+ return(0);
+}
static void
-xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
+xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
{
/*
* Try to rewrite "descendant-or-self::node()/foo" to an optimized
* internal representation.
*/
-
- if ((op->ch1 != -1) &&
- (op->op == XPATH_OP_COLLECT /* 11 */))
- {
- xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
-
- if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
- ((xmlXPathAxisVal) prevop->value ==
- AXIS_DESCENDANT_OR_SELF) &&
- (prevop->ch2 == -1) &&
- ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
- ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
- {
- /*
- * This is a "descendant-or-self::node()" without predicates.
- * Try to eliminate it.
- */
-
- switch ((xmlXPathAxisVal) op->value) {
- case AXIS_CHILD:
- case AXIS_DESCENDANT:
- /*
- * Convert "descendant-or-self::node()/child::" or
- * "descendant-or-self::node()/descendant::" to
- * "descendant::"
- */
- op->ch1 = prevop->ch1;
- op->value = AXIS_DESCENDANT;
- break;
- case AXIS_SELF:
- case AXIS_DESCENDANT_OR_SELF:
- /*
- * Convert "descendant-or-self::node()/self::" or
- * "descendant-or-self::node()/descendant-or-self::" to
- * to "descendant-or-self::"
- */
- op->ch1 = prevop->ch1;
- op->value = AXIS_DESCENDANT_OR_SELF;
- break;
- default:
- break;
- }
+ if (op->ch1 != -1) {
+ if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
+ ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) &&
+ ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) &&
+ ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */))
+ {
+ /*
+ * This is a "child::foo"
+ */
+ xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
+
+ if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
+ (prevop->ch1 != -1) &&
+ ((xmlXPathAxisVal) prevop->value ==
+ AXIS_DESCENDANT_OR_SELF) &&
+ (prevop->ch2 == -1) &&
+ ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
+ ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) &&
+ (comp->steps[prevop->ch1].op == XPATH_OP_ROOT))
+ {
+ /*
+ * This is a "/descendant-or-self::node()" without predicates.
+ * Eliminate it.
+ */
+ op->ch1 = prevop->ch1;
+ op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM;
+ }
}
+ if (op->ch1 != -1)
+ xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]);
}
-
- /* Recurse */
- if (op->ch1 != -1)
- xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);
if (op->ch2 != -1)
- xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]);
+ xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]);
}
/**
@@ -14825,8 +14731,12 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
comp->string = xmlStrdup(str);
comp->nb = 0;
#endif
- if ((comp->nbStep > 1) && (comp->last >= 0)) {
- xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]);
+ if ((comp->expr != NULL) &&
+ (comp->nbStep > 2) &&
+ (comp->last >= 0) &&
+ (xmlXPathCanRewriteDosExpression(comp->expr) == 1))
+ {
+ xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]);
}
}
return(comp);
@@ -15003,12 +14913,17 @@ xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
#endif
{
xmlXPathCompileExpr(ctxt, 1);
+ /*
+ * In this scenario the expression string will sit in ctxt->base.
+ */
if ((ctxt->error == XPATH_EXPRESSION_OK) &&
(ctxt->comp != NULL) &&
- (ctxt->comp->nbStep > 1) &&
- (ctxt->comp->last >= 0))
+ (ctxt->base != NULL) &&
+ (ctxt->comp->nbStep > 2) &&
+ (ctxt->comp->last >= 0) &&
+ (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1))
{
- xmlXPathOptimizeExpression(ctxt->comp,
+ xmlXPathRewriteDOSExpression(ctxt->comp,
&ctxt->comp->steps[ctxt->comp->last]);
}
}
@@ -15079,49 +14994,6 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
}
/**
- * xmlXPathSetContextNode:
- * @node: the node to to use as the context node
- * @ctx: the XPath context
- *
- * Sets 'node' as the context node. The node must be in the same
- * document as that associated with the context.
- *
- * Returns -1 in case of error or 0 if successful
- */
-int
-xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
- if ((node == NULL) || (ctx == NULL))
- return(-1);
-
- if (node->doc == ctx->doc) {
- ctx->node = node;
- return(0);
- }
- return(-1);
-}
-
-/**
- * xmlXPathNodeEval:
- * @node: the node to to use as the context node
- * @str: the XPath expression
- * @ctx: the XPath context
- *
- * Evaluate the XPath Location Path in the given context. The node 'node'
- * is set as the context node. The context node is not restored.
- *
- * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
- * the caller has to free the object.
- */
-xmlXPathObjectPtr
-xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
- if (str == NULL)
- return(NULL);
- if (xmlXPathSetContextNode(node, ctx) < 0)
- return(NULL);
- return(xmlXPathEval(str, ctx));
-}
-
-/**
* xmlXPathEvalExpression:
* @str: the XPath expression
* @ctxt: the XPath context
@@ -15225,7 +15097,7 @@ static void
xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr str;
int escape_reserved;
- xmlBufPtr target;
+ xmlBufferPtr target;
xmlChar *cptr;
xmlChar escape[4];
@@ -15236,7 +15108,7 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CAST_TO_STRING;
str = valuePop(ctxt);
- target = xmlBufCreate();
+ target = xmlBufferCreate();
escape[0] = '%';
escape[3] = 0;
@@ -15261,7 +15133,7 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
*cptr == ':' || *cptr == '@' || *cptr == '&' ||
*cptr == '=' || *cptr == '+' || *cptr == '$' ||
*cptr == ','))) {
- xmlBufAdd(target, cptr, 1);
+ xmlBufferAdd(target, cptr, 1);
} else {
if ((*cptr >> 4) < 10)
escape[1] = '0' + (*cptr >> 4);
@@ -15272,13 +15144,13 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
else
escape[2] = 'A' - 10 + (*cptr & 0xF);
- xmlBufAdd(target, &escape[0], 3);
+ xmlBufferAdd(target, &escape[0], 3);
}
}
}
valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
- xmlBufContent(target)));
- xmlBufFree(target);
+ xmlBufferContent(target)));
+ xmlBufferFree(target);
xmlXPathReleaseObject(ctxt->context, str);
}