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