Paul Cercueil / libxml2

Dependents:   libiio

Committer:
pcercuei
Date:
Thu Aug 25 10:05:35 2016 +0000
Revision:
0:03b5121a232e
Add basic C files of libxml2 2.9.4

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pcercuei 0:03b5121a232e 1 /*
pcercuei 0:03b5121a232e 2 * xpath.c: XML Path Language implementation
pcercuei 0:03b5121a232e 3 * XPath is a language for addressing parts of an XML document,
pcercuei 0:03b5121a232e 4 * designed to be used by both XSLT and XPointer
pcercuei 0:03b5121a232e 5 *f
pcercuei 0:03b5121a232e 6 * Reference: W3C Recommendation 16 November 1999
pcercuei 0:03b5121a232e 7 * http://www.w3.org/TR/1999/REC-xpath-19991116
pcercuei 0:03b5121a232e 8 * Public reference:
pcercuei 0:03b5121a232e 9 * http://www.w3.org/TR/xpath
pcercuei 0:03b5121a232e 10 *
pcercuei 0:03b5121a232e 11 * See Copyright for the status of this software
pcercuei 0:03b5121a232e 12 *
pcercuei 0:03b5121a232e 13 * Author: daniel@veillard.com
pcercuei 0:03b5121a232e 14 *
pcercuei 0:03b5121a232e 15 */
pcercuei 0:03b5121a232e 16
pcercuei 0:03b5121a232e 17 #define IN_LIBXML
pcercuei 0:03b5121a232e 18 #include "libxml.h"
pcercuei 0:03b5121a232e 19
pcercuei 0:03b5121a232e 20 #include <string.h>
pcercuei 0:03b5121a232e 21
pcercuei 0:03b5121a232e 22 #ifdef HAVE_SYS_TYPES_H
pcercuei 0:03b5121a232e 23 #include <sys/types.h>
pcercuei 0:03b5121a232e 24 #endif
pcercuei 0:03b5121a232e 25 #ifdef HAVE_MATH_H
pcercuei 0:03b5121a232e 26 #include <math.h>
pcercuei 0:03b5121a232e 27 #endif
pcercuei 0:03b5121a232e 28 #ifdef HAVE_FLOAT_H
pcercuei 0:03b5121a232e 29 #include <float.h>
pcercuei 0:03b5121a232e 30 #endif
pcercuei 0:03b5121a232e 31 #ifdef HAVE_CTYPE_H
pcercuei 0:03b5121a232e 32 #include <ctype.h>
pcercuei 0:03b5121a232e 33 #endif
pcercuei 0:03b5121a232e 34 #ifdef HAVE_SIGNAL_H
pcercuei 0:03b5121a232e 35 #include <signal.h>
pcercuei 0:03b5121a232e 36 #endif
pcercuei 0:03b5121a232e 37
pcercuei 0:03b5121a232e 38 #include <libxml/xmlmemory.h>
pcercuei 0:03b5121a232e 39 #include <libxml/tree.h>
pcercuei 0:03b5121a232e 40 #include <libxml/valid.h>
pcercuei 0:03b5121a232e 41 #include <libxml/xpath.h>
pcercuei 0:03b5121a232e 42 #include <libxml/xpathInternals.h>
pcercuei 0:03b5121a232e 43 #include <libxml/parserInternals.h>
pcercuei 0:03b5121a232e 44 #include <libxml/hash.h>
pcercuei 0:03b5121a232e 45 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 46 #include <libxml/xpointer.h>
pcercuei 0:03b5121a232e 47 #endif
pcercuei 0:03b5121a232e 48 #ifdef LIBXML_DEBUG_ENABLED
pcercuei 0:03b5121a232e 49 #include <libxml/debugXML.h>
pcercuei 0:03b5121a232e 50 #endif
pcercuei 0:03b5121a232e 51 #include <libxml/xmlerror.h>
pcercuei 0:03b5121a232e 52 #include <libxml/threads.h>
pcercuei 0:03b5121a232e 53 #include <libxml/globals.h>
pcercuei 0:03b5121a232e 54 #ifdef LIBXML_PATTERN_ENABLED
pcercuei 0:03b5121a232e 55 #include <libxml/pattern.h>
pcercuei 0:03b5121a232e 56 #endif
pcercuei 0:03b5121a232e 57
pcercuei 0:03b5121a232e 58 #include "buf.h"
pcercuei 0:03b5121a232e 59
pcercuei 0:03b5121a232e 60 #ifdef LIBXML_PATTERN_ENABLED
pcercuei 0:03b5121a232e 61 #define XPATH_STREAMING
pcercuei 0:03b5121a232e 62 #endif
pcercuei 0:03b5121a232e 63
pcercuei 0:03b5121a232e 64 #define TODO \
pcercuei 0:03b5121a232e 65 xmlGenericError(xmlGenericErrorContext, \
pcercuei 0:03b5121a232e 66 "Unimplemented block at %s:%d\n", \
pcercuei 0:03b5121a232e 67 __FILE__, __LINE__);
pcercuei 0:03b5121a232e 68
pcercuei 0:03b5121a232e 69 /**
pcercuei 0:03b5121a232e 70 * WITH_TIM_SORT:
pcercuei 0:03b5121a232e 71 *
pcercuei 0:03b5121a232e 72 * Use the Timsort algorithm provided in timsort.h to sort
pcercuei 0:03b5121a232e 73 * nodeset as this is a great improvement over the old Shell sort
pcercuei 0:03b5121a232e 74 * used in xmlXPathNodeSetSort()
pcercuei 0:03b5121a232e 75 */
pcercuei 0:03b5121a232e 76 #define WITH_TIM_SORT
pcercuei 0:03b5121a232e 77
pcercuei 0:03b5121a232e 78 /*
pcercuei 0:03b5121a232e 79 * XP_OPTIMIZED_NON_ELEM_COMPARISON:
pcercuei 0:03b5121a232e 80 * If defined, this will use xmlXPathCmpNodesExt() instead of
pcercuei 0:03b5121a232e 81 * xmlXPathCmpNodes(). The new function is optimized comparison of
pcercuei 0:03b5121a232e 82 * non-element nodes; actually it will speed up comparison only if
pcercuei 0:03b5121a232e 83 * xmlXPathOrderDocElems() was called in order to index the elements of
pcercuei 0:03b5121a232e 84 * a tree in document order; Libxslt does such an indexing, thus it will
pcercuei 0:03b5121a232e 85 * benefit from this optimization.
pcercuei 0:03b5121a232e 86 */
pcercuei 0:03b5121a232e 87 #define XP_OPTIMIZED_NON_ELEM_COMPARISON
pcercuei 0:03b5121a232e 88
pcercuei 0:03b5121a232e 89 /*
pcercuei 0:03b5121a232e 90 * XP_OPTIMIZED_FILTER_FIRST:
pcercuei 0:03b5121a232e 91 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]"
pcercuei 0:03b5121a232e 92 * in a way, that it stop evaluation at the first node.
pcercuei 0:03b5121a232e 93 */
pcercuei 0:03b5121a232e 94 #define XP_OPTIMIZED_FILTER_FIRST
pcercuei 0:03b5121a232e 95
pcercuei 0:03b5121a232e 96 /*
pcercuei 0:03b5121a232e 97 * XP_DEBUG_OBJ_USAGE:
pcercuei 0:03b5121a232e 98 * Internal flag to enable tracking of how much XPath objects have been
pcercuei 0:03b5121a232e 99 * created.
pcercuei 0:03b5121a232e 100 */
pcercuei 0:03b5121a232e 101 /* #define XP_DEBUG_OBJ_USAGE */
pcercuei 0:03b5121a232e 102
pcercuei 0:03b5121a232e 103 /*
pcercuei 0:03b5121a232e 104 * XPATH_MAX_STEPS:
pcercuei 0:03b5121a232e 105 * when compiling an XPath expression we arbitrary limit the maximum
pcercuei 0:03b5121a232e 106 * number of step operation in the compiled expression. 1000000 is
pcercuei 0:03b5121a232e 107 * an insanely large value which should never be reached under normal
pcercuei 0:03b5121a232e 108 * circumstances
pcercuei 0:03b5121a232e 109 */
pcercuei 0:03b5121a232e 110 #define XPATH_MAX_STEPS 1000000
pcercuei 0:03b5121a232e 111
pcercuei 0:03b5121a232e 112 /*
pcercuei 0:03b5121a232e 113 * XPATH_MAX_STACK_DEPTH:
pcercuei 0:03b5121a232e 114 * when evaluating an XPath expression we arbitrary limit the maximum
pcercuei 0:03b5121a232e 115 * number of object allowed to be pushed on the stack. 1000000 is
pcercuei 0:03b5121a232e 116 * an insanely large value which should never be reached under normal
pcercuei 0:03b5121a232e 117 * circumstances
pcercuei 0:03b5121a232e 118 */
pcercuei 0:03b5121a232e 119 #define XPATH_MAX_STACK_DEPTH 1000000
pcercuei 0:03b5121a232e 120
pcercuei 0:03b5121a232e 121 /*
pcercuei 0:03b5121a232e 122 * XPATH_MAX_NODESET_LENGTH:
pcercuei 0:03b5121a232e 123 * when evaluating an XPath expression nodesets are created and we
pcercuei 0:03b5121a232e 124 * arbitrary limit the maximum length of those node set. 10000000 is
pcercuei 0:03b5121a232e 125 * an insanely large value which should never be reached under normal
pcercuei 0:03b5121a232e 126 * circumstances, one would first need to construct an in memory tree
pcercuei 0:03b5121a232e 127 * with more than 10 millions nodes.
pcercuei 0:03b5121a232e 128 */
pcercuei 0:03b5121a232e 129 #define XPATH_MAX_NODESET_LENGTH 10000000
pcercuei 0:03b5121a232e 130
pcercuei 0:03b5121a232e 131 /*
pcercuei 0:03b5121a232e 132 * TODO:
pcercuei 0:03b5121a232e 133 * There are a few spots where some tests are done which depend upon ascii
pcercuei 0:03b5121a232e 134 * data. These should be enhanced for full UTF8 support (see particularly
pcercuei 0:03b5121a232e 135 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
pcercuei 0:03b5121a232e 136 */
pcercuei 0:03b5121a232e 137
pcercuei 0:03b5121a232e 138 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
pcercuei 0:03b5121a232e 139 /**
pcercuei 0:03b5121a232e 140 * xmlXPathCmpNodesExt:
pcercuei 0:03b5121a232e 141 * @node1: the first node
pcercuei 0:03b5121a232e 142 * @node2: the second node
pcercuei 0:03b5121a232e 143 *
pcercuei 0:03b5121a232e 144 * Compare two nodes w.r.t document order.
pcercuei 0:03b5121a232e 145 * This one is optimized for handling of non-element nodes.
pcercuei 0:03b5121a232e 146 *
pcercuei 0:03b5121a232e 147 * Returns -2 in case of error 1 if first point < second point, 0 if
pcercuei 0:03b5121a232e 148 * it's the same node, -1 otherwise
pcercuei 0:03b5121a232e 149 */
pcercuei 0:03b5121a232e 150 static int
pcercuei 0:03b5121a232e 151 xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
pcercuei 0:03b5121a232e 152 int depth1, depth2;
pcercuei 0:03b5121a232e 153 int misc = 0, precedence1 = 0, precedence2 = 0;
pcercuei 0:03b5121a232e 154 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
pcercuei 0:03b5121a232e 155 xmlNodePtr cur, root;
pcercuei 0:03b5121a232e 156 long l1, l2;
pcercuei 0:03b5121a232e 157
pcercuei 0:03b5121a232e 158 if ((node1 == NULL) || (node2 == NULL))
pcercuei 0:03b5121a232e 159 return(-2);
pcercuei 0:03b5121a232e 160
pcercuei 0:03b5121a232e 161 if (node1 == node2)
pcercuei 0:03b5121a232e 162 return(0);
pcercuei 0:03b5121a232e 163
pcercuei 0:03b5121a232e 164 /*
pcercuei 0:03b5121a232e 165 * a couple of optimizations which will avoid computations in most cases
pcercuei 0:03b5121a232e 166 */
pcercuei 0:03b5121a232e 167 switch (node1->type) {
pcercuei 0:03b5121a232e 168 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 169 if (node2->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 170 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */
pcercuei 0:03b5121a232e 171 (0 > (long) node2->content) &&
pcercuei 0:03b5121a232e 172 (node1->doc == node2->doc))
pcercuei 0:03b5121a232e 173 {
pcercuei 0:03b5121a232e 174 l1 = -((long) node1->content);
pcercuei 0:03b5121a232e 175 l2 = -((long) node2->content);
pcercuei 0:03b5121a232e 176 if (l1 < l2)
pcercuei 0:03b5121a232e 177 return(1);
pcercuei 0:03b5121a232e 178 if (l1 > l2)
pcercuei 0:03b5121a232e 179 return(-1);
pcercuei 0:03b5121a232e 180 } else
pcercuei 0:03b5121a232e 181 goto turtle_comparison;
pcercuei 0:03b5121a232e 182 }
pcercuei 0:03b5121a232e 183 break;
pcercuei 0:03b5121a232e 184 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 185 precedence1 = 1; /* element is owner */
pcercuei 0:03b5121a232e 186 miscNode1 = node1;
pcercuei 0:03b5121a232e 187 node1 = node1->parent;
pcercuei 0:03b5121a232e 188 misc = 1;
pcercuei 0:03b5121a232e 189 break;
pcercuei 0:03b5121a232e 190 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 191 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 192 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 193 case XML_PI_NODE: {
pcercuei 0:03b5121a232e 194 miscNode1 = node1;
pcercuei 0:03b5121a232e 195 /*
pcercuei 0:03b5121a232e 196 * Find nearest element node.
pcercuei 0:03b5121a232e 197 */
pcercuei 0:03b5121a232e 198 if (node1->prev != NULL) {
pcercuei 0:03b5121a232e 199 do {
pcercuei 0:03b5121a232e 200 node1 = node1->prev;
pcercuei 0:03b5121a232e 201 if (node1->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 202 precedence1 = 3; /* element in prev-sibl axis */
pcercuei 0:03b5121a232e 203 break;
pcercuei 0:03b5121a232e 204 }
pcercuei 0:03b5121a232e 205 if (node1->prev == NULL) {
pcercuei 0:03b5121a232e 206 precedence1 = 2; /* element is parent */
pcercuei 0:03b5121a232e 207 /*
pcercuei 0:03b5121a232e 208 * URGENT TODO: Are there any cases, where the
pcercuei 0:03b5121a232e 209 * parent of such a node is not an element node?
pcercuei 0:03b5121a232e 210 */
pcercuei 0:03b5121a232e 211 node1 = node1->parent;
pcercuei 0:03b5121a232e 212 break;
pcercuei 0:03b5121a232e 213 }
pcercuei 0:03b5121a232e 214 } while (1);
pcercuei 0:03b5121a232e 215 } else {
pcercuei 0:03b5121a232e 216 precedence1 = 2; /* element is parent */
pcercuei 0:03b5121a232e 217 node1 = node1->parent;
pcercuei 0:03b5121a232e 218 }
pcercuei 0:03b5121a232e 219 if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
pcercuei 0:03b5121a232e 220 (0 <= (long) node1->content)) {
pcercuei 0:03b5121a232e 221 /*
pcercuei 0:03b5121a232e 222 * Fallback for whatever case.
pcercuei 0:03b5121a232e 223 */
pcercuei 0:03b5121a232e 224 node1 = miscNode1;
pcercuei 0:03b5121a232e 225 precedence1 = 0;
pcercuei 0:03b5121a232e 226 } else
pcercuei 0:03b5121a232e 227 misc = 1;
pcercuei 0:03b5121a232e 228 }
pcercuei 0:03b5121a232e 229 break;
pcercuei 0:03b5121a232e 230 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 231 /*
pcercuei 0:03b5121a232e 232 * TODO: why do we return 1 for namespace nodes?
pcercuei 0:03b5121a232e 233 */
pcercuei 0:03b5121a232e 234 return(1);
pcercuei 0:03b5121a232e 235 default:
pcercuei 0:03b5121a232e 236 break;
pcercuei 0:03b5121a232e 237 }
pcercuei 0:03b5121a232e 238 switch (node2->type) {
pcercuei 0:03b5121a232e 239 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 240 break;
pcercuei 0:03b5121a232e 241 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 242 precedence2 = 1; /* element is owner */
pcercuei 0:03b5121a232e 243 miscNode2 = node2;
pcercuei 0:03b5121a232e 244 node2 = node2->parent;
pcercuei 0:03b5121a232e 245 misc = 1;
pcercuei 0:03b5121a232e 246 break;
pcercuei 0:03b5121a232e 247 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 248 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 249 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 250 case XML_PI_NODE: {
pcercuei 0:03b5121a232e 251 miscNode2 = node2;
pcercuei 0:03b5121a232e 252 if (node2->prev != NULL) {
pcercuei 0:03b5121a232e 253 do {
pcercuei 0:03b5121a232e 254 node2 = node2->prev;
pcercuei 0:03b5121a232e 255 if (node2->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 256 precedence2 = 3; /* element in prev-sibl axis */
pcercuei 0:03b5121a232e 257 break;
pcercuei 0:03b5121a232e 258 }
pcercuei 0:03b5121a232e 259 if (node2->prev == NULL) {
pcercuei 0:03b5121a232e 260 precedence2 = 2; /* element is parent */
pcercuei 0:03b5121a232e 261 node2 = node2->parent;
pcercuei 0:03b5121a232e 262 break;
pcercuei 0:03b5121a232e 263 }
pcercuei 0:03b5121a232e 264 } while (1);
pcercuei 0:03b5121a232e 265 } else {
pcercuei 0:03b5121a232e 266 precedence2 = 2; /* element is parent */
pcercuei 0:03b5121a232e 267 node2 = node2->parent;
pcercuei 0:03b5121a232e 268 }
pcercuei 0:03b5121a232e 269 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
pcercuei 0:03b5121a232e 270 (0 <= (long) node2->content))
pcercuei 0:03b5121a232e 271 {
pcercuei 0:03b5121a232e 272 node2 = miscNode2;
pcercuei 0:03b5121a232e 273 precedence2 = 0;
pcercuei 0:03b5121a232e 274 } else
pcercuei 0:03b5121a232e 275 misc = 1;
pcercuei 0:03b5121a232e 276 }
pcercuei 0:03b5121a232e 277 break;
pcercuei 0:03b5121a232e 278 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 279 return(1);
pcercuei 0:03b5121a232e 280 default:
pcercuei 0:03b5121a232e 281 break;
pcercuei 0:03b5121a232e 282 }
pcercuei 0:03b5121a232e 283 if (misc) {
pcercuei 0:03b5121a232e 284 if (node1 == node2) {
pcercuei 0:03b5121a232e 285 if (precedence1 == precedence2) {
pcercuei 0:03b5121a232e 286 /*
pcercuei 0:03b5121a232e 287 * The ugly case; but normally there aren't many
pcercuei 0:03b5121a232e 288 * adjacent non-element nodes around.
pcercuei 0:03b5121a232e 289 */
pcercuei 0:03b5121a232e 290 cur = miscNode2->prev;
pcercuei 0:03b5121a232e 291 while (cur != NULL) {
pcercuei 0:03b5121a232e 292 if (cur == miscNode1)
pcercuei 0:03b5121a232e 293 return(1);
pcercuei 0:03b5121a232e 294 if (cur->type == XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 295 return(-1);
pcercuei 0:03b5121a232e 296 cur = cur->prev;
pcercuei 0:03b5121a232e 297 }
pcercuei 0:03b5121a232e 298 return (-1);
pcercuei 0:03b5121a232e 299 } else {
pcercuei 0:03b5121a232e 300 /*
pcercuei 0:03b5121a232e 301 * Evaluate based on higher precedence wrt to the element.
pcercuei 0:03b5121a232e 302 * TODO: This assumes attributes are sorted before content.
pcercuei 0:03b5121a232e 303 * Is this 100% correct?
pcercuei 0:03b5121a232e 304 */
pcercuei 0:03b5121a232e 305 if (precedence1 < precedence2)
pcercuei 0:03b5121a232e 306 return(1);
pcercuei 0:03b5121a232e 307 else
pcercuei 0:03b5121a232e 308 return(-1);
pcercuei 0:03b5121a232e 309 }
pcercuei 0:03b5121a232e 310 }
pcercuei 0:03b5121a232e 311 /*
pcercuei 0:03b5121a232e 312 * Special case: One of the helper-elements is contained by the other.
pcercuei 0:03b5121a232e 313 * <foo>
pcercuei 0:03b5121a232e 314 * <node2>
pcercuei 0:03b5121a232e 315 * <node1>Text-1(precedence1 == 2)</node1>
pcercuei 0:03b5121a232e 316 * </node2>
pcercuei 0:03b5121a232e 317 * Text-6(precedence2 == 3)
pcercuei 0:03b5121a232e 318 * </foo>
pcercuei 0:03b5121a232e 319 */
pcercuei 0:03b5121a232e 320 if ((precedence2 == 3) && (precedence1 > 1)) {
pcercuei 0:03b5121a232e 321 cur = node1->parent;
pcercuei 0:03b5121a232e 322 while (cur) {
pcercuei 0:03b5121a232e 323 if (cur == node2)
pcercuei 0:03b5121a232e 324 return(1);
pcercuei 0:03b5121a232e 325 cur = cur->parent;
pcercuei 0:03b5121a232e 326 }
pcercuei 0:03b5121a232e 327 }
pcercuei 0:03b5121a232e 328 if ((precedence1 == 3) && (precedence2 > 1)) {
pcercuei 0:03b5121a232e 329 cur = node2->parent;
pcercuei 0:03b5121a232e 330 while (cur) {
pcercuei 0:03b5121a232e 331 if (cur == node1)
pcercuei 0:03b5121a232e 332 return(-1);
pcercuei 0:03b5121a232e 333 cur = cur->parent;
pcercuei 0:03b5121a232e 334 }
pcercuei 0:03b5121a232e 335 }
pcercuei 0:03b5121a232e 336 }
pcercuei 0:03b5121a232e 337
pcercuei 0:03b5121a232e 338 /*
pcercuei 0:03b5121a232e 339 * Speedup using document order if availble.
pcercuei 0:03b5121a232e 340 */
pcercuei 0:03b5121a232e 341 if ((node1->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 342 (node2->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 343 (0 > (long) node1->content) &&
pcercuei 0:03b5121a232e 344 (0 > (long) node2->content) &&
pcercuei 0:03b5121a232e 345 (node1->doc == node2->doc)) {
pcercuei 0:03b5121a232e 346
pcercuei 0:03b5121a232e 347 l1 = -((long) node1->content);
pcercuei 0:03b5121a232e 348 l2 = -((long) node2->content);
pcercuei 0:03b5121a232e 349 if (l1 < l2)
pcercuei 0:03b5121a232e 350 return(1);
pcercuei 0:03b5121a232e 351 if (l1 > l2)
pcercuei 0:03b5121a232e 352 return(-1);
pcercuei 0:03b5121a232e 353 }
pcercuei 0:03b5121a232e 354
pcercuei 0:03b5121a232e 355 turtle_comparison:
pcercuei 0:03b5121a232e 356
pcercuei 0:03b5121a232e 357 if (node1 == node2->prev)
pcercuei 0:03b5121a232e 358 return(1);
pcercuei 0:03b5121a232e 359 if (node1 == node2->next)
pcercuei 0:03b5121a232e 360 return(-1);
pcercuei 0:03b5121a232e 361 /*
pcercuei 0:03b5121a232e 362 * compute depth to root
pcercuei 0:03b5121a232e 363 */
pcercuei 0:03b5121a232e 364 for (depth2 = 0, cur = node2; cur->parent != NULL; cur = cur->parent) {
pcercuei 0:03b5121a232e 365 if (cur->parent == node1)
pcercuei 0:03b5121a232e 366 return(1);
pcercuei 0:03b5121a232e 367 depth2++;
pcercuei 0:03b5121a232e 368 }
pcercuei 0:03b5121a232e 369 root = cur;
pcercuei 0:03b5121a232e 370 for (depth1 = 0, cur = node1; cur->parent != NULL; cur = cur->parent) {
pcercuei 0:03b5121a232e 371 if (cur->parent == node2)
pcercuei 0:03b5121a232e 372 return(-1);
pcercuei 0:03b5121a232e 373 depth1++;
pcercuei 0:03b5121a232e 374 }
pcercuei 0:03b5121a232e 375 /*
pcercuei 0:03b5121a232e 376 * Distinct document (or distinct entities :-( ) case.
pcercuei 0:03b5121a232e 377 */
pcercuei 0:03b5121a232e 378 if (root != cur) {
pcercuei 0:03b5121a232e 379 return(-2);
pcercuei 0:03b5121a232e 380 }
pcercuei 0:03b5121a232e 381 /*
pcercuei 0:03b5121a232e 382 * get the nearest common ancestor.
pcercuei 0:03b5121a232e 383 */
pcercuei 0:03b5121a232e 384 while (depth1 > depth2) {
pcercuei 0:03b5121a232e 385 depth1--;
pcercuei 0:03b5121a232e 386 node1 = node1->parent;
pcercuei 0:03b5121a232e 387 }
pcercuei 0:03b5121a232e 388 while (depth2 > depth1) {
pcercuei 0:03b5121a232e 389 depth2--;
pcercuei 0:03b5121a232e 390 node2 = node2->parent;
pcercuei 0:03b5121a232e 391 }
pcercuei 0:03b5121a232e 392 while (node1->parent != node2->parent) {
pcercuei 0:03b5121a232e 393 node1 = node1->parent;
pcercuei 0:03b5121a232e 394 node2 = node2->parent;
pcercuei 0:03b5121a232e 395 /* should not happen but just in case ... */
pcercuei 0:03b5121a232e 396 if ((node1 == NULL) || (node2 == NULL))
pcercuei 0:03b5121a232e 397 return(-2);
pcercuei 0:03b5121a232e 398 }
pcercuei 0:03b5121a232e 399 /*
pcercuei 0:03b5121a232e 400 * Find who's first.
pcercuei 0:03b5121a232e 401 */
pcercuei 0:03b5121a232e 402 if (node1 == node2->prev)
pcercuei 0:03b5121a232e 403 return(1);
pcercuei 0:03b5121a232e 404 if (node1 == node2->next)
pcercuei 0:03b5121a232e 405 return(-1);
pcercuei 0:03b5121a232e 406 /*
pcercuei 0:03b5121a232e 407 * Speedup using document order if availble.
pcercuei 0:03b5121a232e 408 */
pcercuei 0:03b5121a232e 409 if ((node1->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 410 (node2->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 411 (0 > (long) node1->content) &&
pcercuei 0:03b5121a232e 412 (0 > (long) node2->content) &&
pcercuei 0:03b5121a232e 413 (node1->doc == node2->doc)) {
pcercuei 0:03b5121a232e 414
pcercuei 0:03b5121a232e 415 l1 = -((long) node1->content);
pcercuei 0:03b5121a232e 416 l2 = -((long) node2->content);
pcercuei 0:03b5121a232e 417 if (l1 < l2)
pcercuei 0:03b5121a232e 418 return(1);
pcercuei 0:03b5121a232e 419 if (l1 > l2)
pcercuei 0:03b5121a232e 420 return(-1);
pcercuei 0:03b5121a232e 421 }
pcercuei 0:03b5121a232e 422
pcercuei 0:03b5121a232e 423 for (cur = node1->next;cur != NULL;cur = cur->next)
pcercuei 0:03b5121a232e 424 if (cur == node2)
pcercuei 0:03b5121a232e 425 return(1);
pcercuei 0:03b5121a232e 426 return(-1); /* assume there is no sibling list corruption */
pcercuei 0:03b5121a232e 427 }
pcercuei 0:03b5121a232e 428 #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
pcercuei 0:03b5121a232e 429
pcercuei 0:03b5121a232e 430 /*
pcercuei 0:03b5121a232e 431 * Wrapper for the Timsort argorithm from timsort.h
pcercuei 0:03b5121a232e 432 */
pcercuei 0:03b5121a232e 433 #ifdef WITH_TIM_SORT
pcercuei 0:03b5121a232e 434 #define SORT_NAME libxml_domnode
pcercuei 0:03b5121a232e 435 #define SORT_TYPE xmlNodePtr
pcercuei 0:03b5121a232e 436 /**
pcercuei 0:03b5121a232e 437 * wrap_cmp:
pcercuei 0:03b5121a232e 438 * @x: a node
pcercuei 0:03b5121a232e 439 * @y: another node
pcercuei 0:03b5121a232e 440 *
pcercuei 0:03b5121a232e 441 * Comparison function for the Timsort implementation
pcercuei 0:03b5121a232e 442 *
pcercuei 0:03b5121a232e 443 * Returns -2 in case of error -1 if first point < second point, 0 if
pcercuei 0:03b5121a232e 444 * it's the same node, +1 otherwise
pcercuei 0:03b5121a232e 445 */
pcercuei 0:03b5121a232e 446 static
pcercuei 0:03b5121a232e 447 int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
pcercuei 0:03b5121a232e 448 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
pcercuei 0:03b5121a232e 449 static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
pcercuei 0:03b5121a232e 450 {
pcercuei 0:03b5121a232e 451 int res = xmlXPathCmpNodesExt(x, y);
pcercuei 0:03b5121a232e 452 return res == -2 ? res : -res;
pcercuei 0:03b5121a232e 453 }
pcercuei 0:03b5121a232e 454 #else
pcercuei 0:03b5121a232e 455 static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
pcercuei 0:03b5121a232e 456 {
pcercuei 0:03b5121a232e 457 int res = xmlXPathCmpNodes(x, y);
pcercuei 0:03b5121a232e 458 return res == -2 ? res : -res;
pcercuei 0:03b5121a232e 459 }
pcercuei 0:03b5121a232e 460 #endif
pcercuei 0:03b5121a232e 461 #define SORT_CMP(x, y) (wrap_cmp(x, y))
pcercuei 0:03b5121a232e 462 #include "timsort.h"
pcercuei 0:03b5121a232e 463 #endif /* WITH_TIM_SORT */
pcercuei 0:03b5121a232e 464
pcercuei 0:03b5121a232e 465 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
pcercuei 0:03b5121a232e 466
pcercuei 0:03b5121a232e 467 /************************************************************************
pcercuei 0:03b5121a232e 468 * *
pcercuei 0:03b5121a232e 469 * Floating point stuff *
pcercuei 0:03b5121a232e 470 * *
pcercuei 0:03b5121a232e 471 ************************************************************************/
pcercuei 0:03b5121a232e 472
pcercuei 0:03b5121a232e 473 #ifndef TRIO_REPLACE_STDIO
pcercuei 0:03b5121a232e 474 #define TRIO_PUBLIC static
pcercuei 0:03b5121a232e 475 #endif
pcercuei 0:03b5121a232e 476 #include "trionan.c"
pcercuei 0:03b5121a232e 477
pcercuei 0:03b5121a232e 478 /*
pcercuei 0:03b5121a232e 479 * The lack of portability of this section of the libc is annoying !
pcercuei 0:03b5121a232e 480 */
pcercuei 0:03b5121a232e 481 double xmlXPathNAN = 0;
pcercuei 0:03b5121a232e 482 double xmlXPathPINF = 1;
pcercuei 0:03b5121a232e 483 double xmlXPathNINF = -1;
pcercuei 0:03b5121a232e 484 static double xmlXPathNZERO = 0; /* not exported from headers */
pcercuei 0:03b5121a232e 485 static int xmlXPathInitialized = 0;
pcercuei 0:03b5121a232e 486
pcercuei 0:03b5121a232e 487 /**
pcercuei 0:03b5121a232e 488 * xmlXPathInit:
pcercuei 0:03b5121a232e 489 *
pcercuei 0:03b5121a232e 490 * Initialize the XPath environment
pcercuei 0:03b5121a232e 491 */
pcercuei 0:03b5121a232e 492 void
pcercuei 0:03b5121a232e 493 xmlXPathInit(void) {
pcercuei 0:03b5121a232e 494 if (xmlXPathInitialized) return;
pcercuei 0:03b5121a232e 495
pcercuei 0:03b5121a232e 496 xmlXPathPINF = trio_pinf();
pcercuei 0:03b5121a232e 497 xmlXPathNINF = trio_ninf();
pcercuei 0:03b5121a232e 498 xmlXPathNAN = trio_nan();
pcercuei 0:03b5121a232e 499 xmlXPathNZERO = trio_nzero();
pcercuei 0:03b5121a232e 500
pcercuei 0:03b5121a232e 501 xmlXPathInitialized = 1;
pcercuei 0:03b5121a232e 502 }
pcercuei 0:03b5121a232e 503
pcercuei 0:03b5121a232e 504 /**
pcercuei 0:03b5121a232e 505 * xmlXPathIsNaN:
pcercuei 0:03b5121a232e 506 * @val: a double value
pcercuei 0:03b5121a232e 507 *
pcercuei 0:03b5121a232e 508 * Provides a portable isnan() function to detect whether a double
pcercuei 0:03b5121a232e 509 * is a NotaNumber. Based on trio code
pcercuei 0:03b5121a232e 510 * http://sourceforge.net/projects/ctrio/
pcercuei 0:03b5121a232e 511 *
pcercuei 0:03b5121a232e 512 * Returns 1 if the value is a NaN, 0 otherwise
pcercuei 0:03b5121a232e 513 */
pcercuei 0:03b5121a232e 514 int
pcercuei 0:03b5121a232e 515 xmlXPathIsNaN(double val) {
pcercuei 0:03b5121a232e 516 return(trio_isnan(val));
pcercuei 0:03b5121a232e 517 }
pcercuei 0:03b5121a232e 518
pcercuei 0:03b5121a232e 519 /**
pcercuei 0:03b5121a232e 520 * xmlXPathIsInf:
pcercuei 0:03b5121a232e 521 * @val: a double value
pcercuei 0:03b5121a232e 522 *
pcercuei 0:03b5121a232e 523 * Provides a portable isinf() function to detect whether a double
pcercuei 0:03b5121a232e 524 * is a +Infinite or -Infinite. Based on trio code
pcercuei 0:03b5121a232e 525 * http://sourceforge.net/projects/ctrio/
pcercuei 0:03b5121a232e 526 *
pcercuei 0:03b5121a232e 527 * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise
pcercuei 0:03b5121a232e 528 */
pcercuei 0:03b5121a232e 529 int
pcercuei 0:03b5121a232e 530 xmlXPathIsInf(double val) {
pcercuei 0:03b5121a232e 531 return(trio_isinf(val));
pcercuei 0:03b5121a232e 532 }
pcercuei 0:03b5121a232e 533
pcercuei 0:03b5121a232e 534 #endif /* SCHEMAS or XPATH */
pcercuei 0:03b5121a232e 535 #ifdef LIBXML_XPATH_ENABLED
pcercuei 0:03b5121a232e 536 /**
pcercuei 0:03b5121a232e 537 * xmlXPathGetSign:
pcercuei 0:03b5121a232e 538 * @val: a double value
pcercuei 0:03b5121a232e 539 *
pcercuei 0:03b5121a232e 540 * Provides a portable function to detect the sign of a double
pcercuei 0:03b5121a232e 541 * Modified from trio code
pcercuei 0:03b5121a232e 542 * http://sourceforge.net/projects/ctrio/
pcercuei 0:03b5121a232e 543 *
pcercuei 0:03b5121a232e 544 * Returns 1 if the value is Negative, 0 if positive
pcercuei 0:03b5121a232e 545 */
pcercuei 0:03b5121a232e 546 static int
pcercuei 0:03b5121a232e 547 xmlXPathGetSign(double val) {
pcercuei 0:03b5121a232e 548 return(trio_signbit(val));
pcercuei 0:03b5121a232e 549 }
pcercuei 0:03b5121a232e 550
pcercuei 0:03b5121a232e 551
pcercuei 0:03b5121a232e 552 /*
pcercuei 0:03b5121a232e 553 * TODO: when compatibility allows remove all "fake node libxslt" strings
pcercuei 0:03b5121a232e 554 * the test should just be name[0] = ' '
pcercuei 0:03b5121a232e 555 */
pcercuei 0:03b5121a232e 556 #ifdef DEBUG_XPATH_EXPRESSION
pcercuei 0:03b5121a232e 557 #define DEBUG_STEP
pcercuei 0:03b5121a232e 558 #define DEBUG_EXPR
pcercuei 0:03b5121a232e 559 #define DEBUG_EVAL_COUNTS
pcercuei 0:03b5121a232e 560 #endif
pcercuei 0:03b5121a232e 561
pcercuei 0:03b5121a232e 562 static xmlNs xmlXPathXMLNamespaceStruct = {
pcercuei 0:03b5121a232e 563 NULL,
pcercuei 0:03b5121a232e 564 XML_NAMESPACE_DECL,
pcercuei 0:03b5121a232e 565 XML_XML_NAMESPACE,
pcercuei 0:03b5121a232e 566 BAD_CAST "xml",
pcercuei 0:03b5121a232e 567 NULL,
pcercuei 0:03b5121a232e 568 NULL
pcercuei 0:03b5121a232e 569 };
pcercuei 0:03b5121a232e 570 static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
pcercuei 0:03b5121a232e 571 #ifndef LIBXML_THREAD_ENABLED
pcercuei 0:03b5121a232e 572 /*
pcercuei 0:03b5121a232e 573 * Optimizer is disabled only when threaded apps are detected while
pcercuei 0:03b5121a232e 574 * the library ain't compiled for thread safety.
pcercuei 0:03b5121a232e 575 */
pcercuei 0:03b5121a232e 576 static int xmlXPathDisableOptimizer = 0;
pcercuei 0:03b5121a232e 577 #endif
pcercuei 0:03b5121a232e 578
pcercuei 0:03b5121a232e 579 /************************************************************************
pcercuei 0:03b5121a232e 580 * *
pcercuei 0:03b5121a232e 581 * Error handling routines *
pcercuei 0:03b5121a232e 582 * *
pcercuei 0:03b5121a232e 583 ************************************************************************/
pcercuei 0:03b5121a232e 584
pcercuei 0:03b5121a232e 585 /**
pcercuei 0:03b5121a232e 586 * XP_ERRORNULL:
pcercuei 0:03b5121a232e 587 * @X: the error code
pcercuei 0:03b5121a232e 588 *
pcercuei 0:03b5121a232e 589 * Macro to raise an XPath error and return NULL.
pcercuei 0:03b5121a232e 590 */
pcercuei 0:03b5121a232e 591 #define XP_ERRORNULL(X) \
pcercuei 0:03b5121a232e 592 { xmlXPathErr(ctxt, X); return(NULL); }
pcercuei 0:03b5121a232e 593
pcercuei 0:03b5121a232e 594 /*
pcercuei 0:03b5121a232e 595 * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
pcercuei 0:03b5121a232e 596 */
pcercuei 0:03b5121a232e 597 static const char *xmlXPathErrorMessages[] = {
pcercuei 0:03b5121a232e 598 "Ok\n",
pcercuei 0:03b5121a232e 599 "Number encoding\n",
pcercuei 0:03b5121a232e 600 "Unfinished literal\n",
pcercuei 0:03b5121a232e 601 "Start of literal\n",
pcercuei 0:03b5121a232e 602 "Expected $ for variable reference\n",
pcercuei 0:03b5121a232e 603 "Undefined variable\n",
pcercuei 0:03b5121a232e 604 "Invalid predicate\n",
pcercuei 0:03b5121a232e 605 "Invalid expression\n",
pcercuei 0:03b5121a232e 606 "Missing closing curly brace\n",
pcercuei 0:03b5121a232e 607 "Unregistered function\n",
pcercuei 0:03b5121a232e 608 "Invalid operand\n",
pcercuei 0:03b5121a232e 609 "Invalid type\n",
pcercuei 0:03b5121a232e 610 "Invalid number of arguments\n",
pcercuei 0:03b5121a232e 611 "Invalid context size\n",
pcercuei 0:03b5121a232e 612 "Invalid context position\n",
pcercuei 0:03b5121a232e 613 "Memory allocation error\n",
pcercuei 0:03b5121a232e 614 "Syntax error\n",
pcercuei 0:03b5121a232e 615 "Resource error\n",
pcercuei 0:03b5121a232e 616 "Sub resource error\n",
pcercuei 0:03b5121a232e 617 "Undefined namespace prefix\n",
pcercuei 0:03b5121a232e 618 "Encoding error\n",
pcercuei 0:03b5121a232e 619 "Char out of XML range\n",
pcercuei 0:03b5121a232e 620 "Invalid or incomplete context\n",
pcercuei 0:03b5121a232e 621 "Stack usage error\n",
pcercuei 0:03b5121a232e 622 "Forbidden variable\n",
pcercuei 0:03b5121a232e 623 "?? Unknown error ??\n" /* Must be last in the list! */
pcercuei 0:03b5121a232e 624 };
pcercuei 0:03b5121a232e 625 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
pcercuei 0:03b5121a232e 626 sizeof(xmlXPathErrorMessages[0])) - 1)
pcercuei 0:03b5121a232e 627 /**
pcercuei 0:03b5121a232e 628 * xmlXPathErrMemory:
pcercuei 0:03b5121a232e 629 * @ctxt: an XPath context
pcercuei 0:03b5121a232e 630 * @extra: extra informations
pcercuei 0:03b5121a232e 631 *
pcercuei 0:03b5121a232e 632 * Handle a redefinition of attribute error
pcercuei 0:03b5121a232e 633 */
pcercuei 0:03b5121a232e 634 static void
pcercuei 0:03b5121a232e 635 xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra)
pcercuei 0:03b5121a232e 636 {
pcercuei 0:03b5121a232e 637 if (ctxt != NULL) {
pcercuei 0:03b5121a232e 638 if (extra) {
pcercuei 0:03b5121a232e 639 xmlChar buf[200];
pcercuei 0:03b5121a232e 640
pcercuei 0:03b5121a232e 641 xmlStrPrintf(buf, 200,
pcercuei 0:03b5121a232e 642 BAD_CAST "Memory allocation failed : %s\n",
pcercuei 0:03b5121a232e 643 extra);
pcercuei 0:03b5121a232e 644 ctxt->lastError.message = (char *) xmlStrdup(buf);
pcercuei 0:03b5121a232e 645 } else {
pcercuei 0:03b5121a232e 646 ctxt->lastError.message = (char *)
pcercuei 0:03b5121a232e 647 xmlStrdup(BAD_CAST "Memory allocation failed\n");
pcercuei 0:03b5121a232e 648 }
pcercuei 0:03b5121a232e 649 ctxt->lastError.domain = XML_FROM_XPATH;
pcercuei 0:03b5121a232e 650 ctxt->lastError.code = XML_ERR_NO_MEMORY;
pcercuei 0:03b5121a232e 651 if (ctxt->error != NULL)
pcercuei 0:03b5121a232e 652 ctxt->error(ctxt->userData, &ctxt->lastError);
pcercuei 0:03b5121a232e 653 } else {
pcercuei 0:03b5121a232e 654 if (extra)
pcercuei 0:03b5121a232e 655 __xmlRaiseError(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 656 NULL, NULL, XML_FROM_XPATH,
pcercuei 0:03b5121a232e 657 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
pcercuei 0:03b5121a232e 658 extra, NULL, NULL, 0, 0,
pcercuei 0:03b5121a232e 659 "Memory allocation failed : %s\n", extra);
pcercuei 0:03b5121a232e 660 else
pcercuei 0:03b5121a232e 661 __xmlRaiseError(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 662 NULL, NULL, XML_FROM_XPATH,
pcercuei 0:03b5121a232e 663 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
pcercuei 0:03b5121a232e 664 NULL, NULL, NULL, 0, 0,
pcercuei 0:03b5121a232e 665 "Memory allocation failed\n");
pcercuei 0:03b5121a232e 666 }
pcercuei 0:03b5121a232e 667 }
pcercuei 0:03b5121a232e 668
pcercuei 0:03b5121a232e 669 /**
pcercuei 0:03b5121a232e 670 * xmlXPathPErrMemory:
pcercuei 0:03b5121a232e 671 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 672 * @extra: extra informations
pcercuei 0:03b5121a232e 673 *
pcercuei 0:03b5121a232e 674 * Handle a redefinition of attribute error
pcercuei 0:03b5121a232e 675 */
pcercuei 0:03b5121a232e 676 static void
pcercuei 0:03b5121a232e 677 xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra)
pcercuei 0:03b5121a232e 678 {
pcercuei 0:03b5121a232e 679 if (ctxt == NULL)
pcercuei 0:03b5121a232e 680 xmlXPathErrMemory(NULL, extra);
pcercuei 0:03b5121a232e 681 else {
pcercuei 0:03b5121a232e 682 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 683 xmlXPathErrMemory(ctxt->context, extra);
pcercuei 0:03b5121a232e 684 }
pcercuei 0:03b5121a232e 685 }
pcercuei 0:03b5121a232e 686
pcercuei 0:03b5121a232e 687 /**
pcercuei 0:03b5121a232e 688 * xmlXPathErr:
pcercuei 0:03b5121a232e 689 * @ctxt: a XPath parser context
pcercuei 0:03b5121a232e 690 * @error: the error code
pcercuei 0:03b5121a232e 691 *
pcercuei 0:03b5121a232e 692 * Handle an XPath error
pcercuei 0:03b5121a232e 693 */
pcercuei 0:03b5121a232e 694 void
pcercuei 0:03b5121a232e 695 xmlXPathErr(xmlXPathParserContextPtr ctxt, int error)
pcercuei 0:03b5121a232e 696 {
pcercuei 0:03b5121a232e 697 if ((error < 0) || (error > MAXERRNO))
pcercuei 0:03b5121a232e 698 error = MAXERRNO;
pcercuei 0:03b5121a232e 699 if (ctxt == NULL) {
pcercuei 0:03b5121a232e 700 __xmlRaiseError(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 701 NULL, NULL, XML_FROM_XPATH,
pcercuei 0:03b5121a232e 702 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
pcercuei 0:03b5121a232e 703 XML_ERR_ERROR, NULL, 0,
pcercuei 0:03b5121a232e 704 NULL, NULL, NULL, 0, 0,
pcercuei 0:03b5121a232e 705 "%s", xmlXPathErrorMessages[error]);
pcercuei 0:03b5121a232e 706 return;
pcercuei 0:03b5121a232e 707 }
pcercuei 0:03b5121a232e 708 ctxt->error = error;
pcercuei 0:03b5121a232e 709 if (ctxt->context == NULL) {
pcercuei 0:03b5121a232e 710 __xmlRaiseError(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 711 NULL, NULL, XML_FROM_XPATH,
pcercuei 0:03b5121a232e 712 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
pcercuei 0:03b5121a232e 713 XML_ERR_ERROR, NULL, 0,
pcercuei 0:03b5121a232e 714 (const char *) ctxt->base, NULL, NULL,
pcercuei 0:03b5121a232e 715 ctxt->cur - ctxt->base, 0,
pcercuei 0:03b5121a232e 716 "%s", xmlXPathErrorMessages[error]);
pcercuei 0:03b5121a232e 717 return;
pcercuei 0:03b5121a232e 718 }
pcercuei 0:03b5121a232e 719
pcercuei 0:03b5121a232e 720 /* cleanup current last error */
pcercuei 0:03b5121a232e 721 xmlResetError(&ctxt->context->lastError);
pcercuei 0:03b5121a232e 722
pcercuei 0:03b5121a232e 723 ctxt->context->lastError.domain = XML_FROM_XPATH;
pcercuei 0:03b5121a232e 724 ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK -
pcercuei 0:03b5121a232e 725 XPATH_EXPRESSION_OK;
pcercuei 0:03b5121a232e 726 ctxt->context->lastError.level = XML_ERR_ERROR;
pcercuei 0:03b5121a232e 727 ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
pcercuei 0:03b5121a232e 728 ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
pcercuei 0:03b5121a232e 729 ctxt->context->lastError.node = ctxt->context->debugNode;
pcercuei 0:03b5121a232e 730 if (ctxt->context->error != NULL) {
pcercuei 0:03b5121a232e 731 ctxt->context->error(ctxt->context->userData,
pcercuei 0:03b5121a232e 732 &ctxt->context->lastError);
pcercuei 0:03b5121a232e 733 } else {
pcercuei 0:03b5121a232e 734 __xmlRaiseError(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 735 NULL, ctxt->context->debugNode, XML_FROM_XPATH,
pcercuei 0:03b5121a232e 736 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
pcercuei 0:03b5121a232e 737 XML_ERR_ERROR, NULL, 0,
pcercuei 0:03b5121a232e 738 (const char *) ctxt->base, NULL, NULL,
pcercuei 0:03b5121a232e 739 ctxt->cur - ctxt->base, 0,
pcercuei 0:03b5121a232e 740 "%s", xmlXPathErrorMessages[error]);
pcercuei 0:03b5121a232e 741 }
pcercuei 0:03b5121a232e 742
pcercuei 0:03b5121a232e 743 }
pcercuei 0:03b5121a232e 744
pcercuei 0:03b5121a232e 745 /**
pcercuei 0:03b5121a232e 746 * xmlXPatherror:
pcercuei 0:03b5121a232e 747 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 748 * @file: the file name
pcercuei 0:03b5121a232e 749 * @line: the line number
pcercuei 0:03b5121a232e 750 * @no: the error number
pcercuei 0:03b5121a232e 751 *
pcercuei 0:03b5121a232e 752 * Formats an error message.
pcercuei 0:03b5121a232e 753 */
pcercuei 0:03b5121a232e 754 void
pcercuei 0:03b5121a232e 755 xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
pcercuei 0:03b5121a232e 756 int line ATTRIBUTE_UNUSED, int no) {
pcercuei 0:03b5121a232e 757 xmlXPathErr(ctxt, no);
pcercuei 0:03b5121a232e 758 }
pcercuei 0:03b5121a232e 759
pcercuei 0:03b5121a232e 760 /************************************************************************
pcercuei 0:03b5121a232e 761 * *
pcercuei 0:03b5121a232e 762 * Utilities *
pcercuei 0:03b5121a232e 763 * *
pcercuei 0:03b5121a232e 764 ************************************************************************/
pcercuei 0:03b5121a232e 765
pcercuei 0:03b5121a232e 766 /**
pcercuei 0:03b5121a232e 767 * xsltPointerList:
pcercuei 0:03b5121a232e 768 *
pcercuei 0:03b5121a232e 769 * Pointer-list for various purposes.
pcercuei 0:03b5121a232e 770 */
pcercuei 0:03b5121a232e 771 typedef struct _xmlPointerList xmlPointerList;
pcercuei 0:03b5121a232e 772 typedef xmlPointerList *xmlPointerListPtr;
pcercuei 0:03b5121a232e 773 struct _xmlPointerList {
pcercuei 0:03b5121a232e 774 void **items;
pcercuei 0:03b5121a232e 775 int number;
pcercuei 0:03b5121a232e 776 int size;
pcercuei 0:03b5121a232e 777 };
pcercuei 0:03b5121a232e 778 /*
pcercuei 0:03b5121a232e 779 * TODO: Since such a list-handling is used in xmlschemas.c and libxslt
pcercuei 0:03b5121a232e 780 * and here, we should make the functions public.
pcercuei 0:03b5121a232e 781 */
pcercuei 0:03b5121a232e 782 static int
pcercuei 0:03b5121a232e 783 xmlPointerListAddSize(xmlPointerListPtr list,
pcercuei 0:03b5121a232e 784 void *item,
pcercuei 0:03b5121a232e 785 int initialSize)
pcercuei 0:03b5121a232e 786 {
pcercuei 0:03b5121a232e 787 if (list->items == NULL) {
pcercuei 0:03b5121a232e 788 if (initialSize <= 0)
pcercuei 0:03b5121a232e 789 initialSize = 1;
pcercuei 0:03b5121a232e 790 list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
pcercuei 0:03b5121a232e 791 if (list->items == NULL) {
pcercuei 0:03b5121a232e 792 xmlXPathErrMemory(NULL,
pcercuei 0:03b5121a232e 793 "xmlPointerListCreate: allocating item\n");
pcercuei 0:03b5121a232e 794 return(-1);
pcercuei 0:03b5121a232e 795 }
pcercuei 0:03b5121a232e 796 list->number = 0;
pcercuei 0:03b5121a232e 797 list->size = initialSize;
pcercuei 0:03b5121a232e 798 } else if (list->size <= list->number) {
pcercuei 0:03b5121a232e 799 if (list->size > 50000000) {
pcercuei 0:03b5121a232e 800 xmlXPathErrMemory(NULL,
pcercuei 0:03b5121a232e 801 "xmlPointerListAddSize: re-allocating item\n");
pcercuei 0:03b5121a232e 802 return(-1);
pcercuei 0:03b5121a232e 803 }
pcercuei 0:03b5121a232e 804 list->size *= 2;
pcercuei 0:03b5121a232e 805 list->items = (void **) xmlRealloc(list->items,
pcercuei 0:03b5121a232e 806 list->size * sizeof(void *));
pcercuei 0:03b5121a232e 807 if (list->items == NULL) {
pcercuei 0:03b5121a232e 808 xmlXPathErrMemory(NULL,
pcercuei 0:03b5121a232e 809 "xmlPointerListAddSize: re-allocating item\n");
pcercuei 0:03b5121a232e 810 list->size = 0;
pcercuei 0:03b5121a232e 811 return(-1);
pcercuei 0:03b5121a232e 812 }
pcercuei 0:03b5121a232e 813 }
pcercuei 0:03b5121a232e 814 list->items[list->number++] = item;
pcercuei 0:03b5121a232e 815 return(0);
pcercuei 0:03b5121a232e 816 }
pcercuei 0:03b5121a232e 817
pcercuei 0:03b5121a232e 818 /**
pcercuei 0:03b5121a232e 819 * xsltPointerListCreate:
pcercuei 0:03b5121a232e 820 *
pcercuei 0:03b5121a232e 821 * Creates an xsltPointerList structure.
pcercuei 0:03b5121a232e 822 *
pcercuei 0:03b5121a232e 823 * Returns a xsltPointerList structure or NULL in case of an error.
pcercuei 0:03b5121a232e 824 */
pcercuei 0:03b5121a232e 825 static xmlPointerListPtr
pcercuei 0:03b5121a232e 826 xmlPointerListCreate(int initialSize)
pcercuei 0:03b5121a232e 827 {
pcercuei 0:03b5121a232e 828 xmlPointerListPtr ret;
pcercuei 0:03b5121a232e 829
pcercuei 0:03b5121a232e 830 ret = xmlMalloc(sizeof(xmlPointerList));
pcercuei 0:03b5121a232e 831 if (ret == NULL) {
pcercuei 0:03b5121a232e 832 xmlXPathErrMemory(NULL,
pcercuei 0:03b5121a232e 833 "xmlPointerListCreate: allocating item\n");
pcercuei 0:03b5121a232e 834 return (NULL);
pcercuei 0:03b5121a232e 835 }
pcercuei 0:03b5121a232e 836 memset(ret, 0, sizeof(xmlPointerList));
pcercuei 0:03b5121a232e 837 if (initialSize > 0) {
pcercuei 0:03b5121a232e 838 xmlPointerListAddSize(ret, NULL, initialSize);
pcercuei 0:03b5121a232e 839 ret->number = 0;
pcercuei 0:03b5121a232e 840 }
pcercuei 0:03b5121a232e 841 return (ret);
pcercuei 0:03b5121a232e 842 }
pcercuei 0:03b5121a232e 843
pcercuei 0:03b5121a232e 844 /**
pcercuei 0:03b5121a232e 845 * xsltPointerListFree:
pcercuei 0:03b5121a232e 846 *
pcercuei 0:03b5121a232e 847 * Frees the xsltPointerList structure. This does not free
pcercuei 0:03b5121a232e 848 * the content of the list.
pcercuei 0:03b5121a232e 849 */
pcercuei 0:03b5121a232e 850 static void
pcercuei 0:03b5121a232e 851 xmlPointerListFree(xmlPointerListPtr list)
pcercuei 0:03b5121a232e 852 {
pcercuei 0:03b5121a232e 853 if (list == NULL)
pcercuei 0:03b5121a232e 854 return;
pcercuei 0:03b5121a232e 855 if (list->items != NULL)
pcercuei 0:03b5121a232e 856 xmlFree(list->items);
pcercuei 0:03b5121a232e 857 xmlFree(list);
pcercuei 0:03b5121a232e 858 }
pcercuei 0:03b5121a232e 859
pcercuei 0:03b5121a232e 860 /************************************************************************
pcercuei 0:03b5121a232e 861 * *
pcercuei 0:03b5121a232e 862 * Parser Types *
pcercuei 0:03b5121a232e 863 * *
pcercuei 0:03b5121a232e 864 ************************************************************************/
pcercuei 0:03b5121a232e 865
pcercuei 0:03b5121a232e 866 /*
pcercuei 0:03b5121a232e 867 * Types are private:
pcercuei 0:03b5121a232e 868 */
pcercuei 0:03b5121a232e 869
pcercuei 0:03b5121a232e 870 typedef enum {
pcercuei 0:03b5121a232e 871 XPATH_OP_END=0,
pcercuei 0:03b5121a232e 872 XPATH_OP_AND,
pcercuei 0:03b5121a232e 873 XPATH_OP_OR,
pcercuei 0:03b5121a232e 874 XPATH_OP_EQUAL,
pcercuei 0:03b5121a232e 875 XPATH_OP_CMP,
pcercuei 0:03b5121a232e 876 XPATH_OP_PLUS,
pcercuei 0:03b5121a232e 877 XPATH_OP_MULT,
pcercuei 0:03b5121a232e 878 XPATH_OP_UNION,
pcercuei 0:03b5121a232e 879 XPATH_OP_ROOT,
pcercuei 0:03b5121a232e 880 XPATH_OP_NODE,
pcercuei 0:03b5121a232e 881 XPATH_OP_RESET, /* 10 */
pcercuei 0:03b5121a232e 882 XPATH_OP_COLLECT,
pcercuei 0:03b5121a232e 883 XPATH_OP_VALUE, /* 12 */
pcercuei 0:03b5121a232e 884 XPATH_OP_VARIABLE,
pcercuei 0:03b5121a232e 885 XPATH_OP_FUNCTION,
pcercuei 0:03b5121a232e 886 XPATH_OP_ARG,
pcercuei 0:03b5121a232e 887 XPATH_OP_PREDICATE,
pcercuei 0:03b5121a232e 888 XPATH_OP_FILTER, /* 17 */
pcercuei 0:03b5121a232e 889 XPATH_OP_SORT /* 18 */
pcercuei 0:03b5121a232e 890 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 891 ,XPATH_OP_RANGETO
pcercuei 0:03b5121a232e 892 #endif
pcercuei 0:03b5121a232e 893 } xmlXPathOp;
pcercuei 0:03b5121a232e 894
pcercuei 0:03b5121a232e 895 typedef enum {
pcercuei 0:03b5121a232e 896 AXIS_ANCESTOR = 1,
pcercuei 0:03b5121a232e 897 AXIS_ANCESTOR_OR_SELF,
pcercuei 0:03b5121a232e 898 AXIS_ATTRIBUTE,
pcercuei 0:03b5121a232e 899 AXIS_CHILD,
pcercuei 0:03b5121a232e 900 AXIS_DESCENDANT,
pcercuei 0:03b5121a232e 901 AXIS_DESCENDANT_OR_SELF,
pcercuei 0:03b5121a232e 902 AXIS_FOLLOWING,
pcercuei 0:03b5121a232e 903 AXIS_FOLLOWING_SIBLING,
pcercuei 0:03b5121a232e 904 AXIS_NAMESPACE,
pcercuei 0:03b5121a232e 905 AXIS_PARENT,
pcercuei 0:03b5121a232e 906 AXIS_PRECEDING,
pcercuei 0:03b5121a232e 907 AXIS_PRECEDING_SIBLING,
pcercuei 0:03b5121a232e 908 AXIS_SELF
pcercuei 0:03b5121a232e 909 } xmlXPathAxisVal;
pcercuei 0:03b5121a232e 910
pcercuei 0:03b5121a232e 911 typedef enum {
pcercuei 0:03b5121a232e 912 NODE_TEST_NONE = 0,
pcercuei 0:03b5121a232e 913 NODE_TEST_TYPE = 1,
pcercuei 0:03b5121a232e 914 NODE_TEST_PI = 2,
pcercuei 0:03b5121a232e 915 NODE_TEST_ALL = 3,
pcercuei 0:03b5121a232e 916 NODE_TEST_NS = 4,
pcercuei 0:03b5121a232e 917 NODE_TEST_NAME = 5
pcercuei 0:03b5121a232e 918 } xmlXPathTestVal;
pcercuei 0:03b5121a232e 919
pcercuei 0:03b5121a232e 920 typedef enum {
pcercuei 0:03b5121a232e 921 NODE_TYPE_NODE = 0,
pcercuei 0:03b5121a232e 922 NODE_TYPE_COMMENT = XML_COMMENT_NODE,
pcercuei 0:03b5121a232e 923 NODE_TYPE_TEXT = XML_TEXT_NODE,
pcercuei 0:03b5121a232e 924 NODE_TYPE_PI = XML_PI_NODE
pcercuei 0:03b5121a232e 925 } xmlXPathTypeVal;
pcercuei 0:03b5121a232e 926
pcercuei 0:03b5121a232e 927 typedef struct _xmlXPathStepOp xmlXPathStepOp;
pcercuei 0:03b5121a232e 928 typedef xmlXPathStepOp *xmlXPathStepOpPtr;
pcercuei 0:03b5121a232e 929 struct _xmlXPathStepOp {
pcercuei 0:03b5121a232e 930 xmlXPathOp op; /* The identifier of the operation */
pcercuei 0:03b5121a232e 931 int ch1; /* First child */
pcercuei 0:03b5121a232e 932 int ch2; /* Second child */
pcercuei 0:03b5121a232e 933 int value;
pcercuei 0:03b5121a232e 934 int value2;
pcercuei 0:03b5121a232e 935 int value3;
pcercuei 0:03b5121a232e 936 void *value4;
pcercuei 0:03b5121a232e 937 void *value5;
pcercuei 0:03b5121a232e 938 void *cache;
pcercuei 0:03b5121a232e 939 void *cacheURI;
pcercuei 0:03b5121a232e 940 };
pcercuei 0:03b5121a232e 941
pcercuei 0:03b5121a232e 942 struct _xmlXPathCompExpr {
pcercuei 0:03b5121a232e 943 int nbStep; /* Number of steps in this expression */
pcercuei 0:03b5121a232e 944 int maxStep; /* Maximum number of steps allocated */
pcercuei 0:03b5121a232e 945 xmlXPathStepOp *steps; /* ops for computation of this expression */
pcercuei 0:03b5121a232e 946 int last; /* index of last step in expression */
pcercuei 0:03b5121a232e 947 xmlChar *expr; /* the expression being computed */
pcercuei 0:03b5121a232e 948 xmlDictPtr dict; /* the dictionnary to use if any */
pcercuei 0:03b5121a232e 949 #ifdef DEBUG_EVAL_COUNTS
pcercuei 0:03b5121a232e 950 int nb;
pcercuei 0:03b5121a232e 951 xmlChar *string;
pcercuei 0:03b5121a232e 952 #endif
pcercuei 0:03b5121a232e 953 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 954 xmlPatternPtr stream;
pcercuei 0:03b5121a232e 955 #endif
pcercuei 0:03b5121a232e 956 };
pcercuei 0:03b5121a232e 957
pcercuei 0:03b5121a232e 958 /************************************************************************
pcercuei 0:03b5121a232e 959 * *
pcercuei 0:03b5121a232e 960 * Forward declarations *
pcercuei 0:03b5121a232e 961 * *
pcercuei 0:03b5121a232e 962 ************************************************************************/
pcercuei 0:03b5121a232e 963 static void
pcercuei 0:03b5121a232e 964 xmlXPathFreeValueTree(xmlNodeSetPtr obj);
pcercuei 0:03b5121a232e 965 static void
pcercuei 0:03b5121a232e 966 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj);
pcercuei 0:03b5121a232e 967 static int
pcercuei 0:03b5121a232e 968 xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 969 xmlXPathStepOpPtr op, xmlNodePtr *first);
pcercuei 0:03b5121a232e 970 static int
pcercuei 0:03b5121a232e 971 xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 972 xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 973 int isPredicate);
pcercuei 0:03b5121a232e 974
pcercuei 0:03b5121a232e 975 /************************************************************************
pcercuei 0:03b5121a232e 976 * *
pcercuei 0:03b5121a232e 977 * Parser Type functions *
pcercuei 0:03b5121a232e 978 * *
pcercuei 0:03b5121a232e 979 ************************************************************************/
pcercuei 0:03b5121a232e 980
pcercuei 0:03b5121a232e 981 /**
pcercuei 0:03b5121a232e 982 * xmlXPathNewCompExpr:
pcercuei 0:03b5121a232e 983 *
pcercuei 0:03b5121a232e 984 * Create a new Xpath component
pcercuei 0:03b5121a232e 985 *
pcercuei 0:03b5121a232e 986 * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
pcercuei 0:03b5121a232e 987 */
pcercuei 0:03b5121a232e 988 static xmlXPathCompExprPtr
pcercuei 0:03b5121a232e 989 xmlXPathNewCompExpr(void) {
pcercuei 0:03b5121a232e 990 xmlXPathCompExprPtr cur;
pcercuei 0:03b5121a232e 991
pcercuei 0:03b5121a232e 992 cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
pcercuei 0:03b5121a232e 993 if (cur == NULL) {
pcercuei 0:03b5121a232e 994 xmlXPathErrMemory(NULL, "allocating component\n");
pcercuei 0:03b5121a232e 995 return(NULL);
pcercuei 0:03b5121a232e 996 }
pcercuei 0:03b5121a232e 997 memset(cur, 0, sizeof(xmlXPathCompExpr));
pcercuei 0:03b5121a232e 998 cur->maxStep = 10;
pcercuei 0:03b5121a232e 999 cur->nbStep = 0;
pcercuei 0:03b5121a232e 1000 cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
pcercuei 0:03b5121a232e 1001 sizeof(xmlXPathStepOp));
pcercuei 0:03b5121a232e 1002 if (cur->steps == NULL) {
pcercuei 0:03b5121a232e 1003 xmlXPathErrMemory(NULL, "allocating steps\n");
pcercuei 0:03b5121a232e 1004 xmlFree(cur);
pcercuei 0:03b5121a232e 1005 return(NULL);
pcercuei 0:03b5121a232e 1006 }
pcercuei 0:03b5121a232e 1007 memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
pcercuei 0:03b5121a232e 1008 cur->last = -1;
pcercuei 0:03b5121a232e 1009 #ifdef DEBUG_EVAL_COUNTS
pcercuei 0:03b5121a232e 1010 cur->nb = 0;
pcercuei 0:03b5121a232e 1011 #endif
pcercuei 0:03b5121a232e 1012 return(cur);
pcercuei 0:03b5121a232e 1013 }
pcercuei 0:03b5121a232e 1014
pcercuei 0:03b5121a232e 1015 /**
pcercuei 0:03b5121a232e 1016 * xmlXPathFreeCompExpr:
pcercuei 0:03b5121a232e 1017 * @comp: an XPATH comp
pcercuei 0:03b5121a232e 1018 *
pcercuei 0:03b5121a232e 1019 * Free up the memory allocated by @comp
pcercuei 0:03b5121a232e 1020 */
pcercuei 0:03b5121a232e 1021 void
pcercuei 0:03b5121a232e 1022 xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
pcercuei 0:03b5121a232e 1023 {
pcercuei 0:03b5121a232e 1024 xmlXPathStepOpPtr op;
pcercuei 0:03b5121a232e 1025 int i;
pcercuei 0:03b5121a232e 1026
pcercuei 0:03b5121a232e 1027 if (comp == NULL)
pcercuei 0:03b5121a232e 1028 return;
pcercuei 0:03b5121a232e 1029 if (comp->dict == NULL) {
pcercuei 0:03b5121a232e 1030 for (i = 0; i < comp->nbStep; i++) {
pcercuei 0:03b5121a232e 1031 op = &comp->steps[i];
pcercuei 0:03b5121a232e 1032 if (op->value4 != NULL) {
pcercuei 0:03b5121a232e 1033 if (op->op == XPATH_OP_VALUE)
pcercuei 0:03b5121a232e 1034 xmlXPathFreeObject(op->value4);
pcercuei 0:03b5121a232e 1035 else
pcercuei 0:03b5121a232e 1036 xmlFree(op->value4);
pcercuei 0:03b5121a232e 1037 }
pcercuei 0:03b5121a232e 1038 if (op->value5 != NULL)
pcercuei 0:03b5121a232e 1039 xmlFree(op->value5);
pcercuei 0:03b5121a232e 1040 }
pcercuei 0:03b5121a232e 1041 } else {
pcercuei 0:03b5121a232e 1042 for (i = 0; i < comp->nbStep; i++) {
pcercuei 0:03b5121a232e 1043 op = &comp->steps[i];
pcercuei 0:03b5121a232e 1044 if (op->value4 != NULL) {
pcercuei 0:03b5121a232e 1045 if (op->op == XPATH_OP_VALUE)
pcercuei 0:03b5121a232e 1046 xmlXPathFreeObject(op->value4);
pcercuei 0:03b5121a232e 1047 }
pcercuei 0:03b5121a232e 1048 }
pcercuei 0:03b5121a232e 1049 xmlDictFree(comp->dict);
pcercuei 0:03b5121a232e 1050 }
pcercuei 0:03b5121a232e 1051 if (comp->steps != NULL) {
pcercuei 0:03b5121a232e 1052 xmlFree(comp->steps);
pcercuei 0:03b5121a232e 1053 }
pcercuei 0:03b5121a232e 1054 #ifdef DEBUG_EVAL_COUNTS
pcercuei 0:03b5121a232e 1055 if (comp->string != NULL) {
pcercuei 0:03b5121a232e 1056 xmlFree(comp->string);
pcercuei 0:03b5121a232e 1057 }
pcercuei 0:03b5121a232e 1058 #endif
pcercuei 0:03b5121a232e 1059 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 1060 if (comp->stream != NULL) {
pcercuei 0:03b5121a232e 1061 xmlFreePatternList(comp->stream);
pcercuei 0:03b5121a232e 1062 }
pcercuei 0:03b5121a232e 1063 #endif
pcercuei 0:03b5121a232e 1064 if (comp->expr != NULL) {
pcercuei 0:03b5121a232e 1065 xmlFree(comp->expr);
pcercuei 0:03b5121a232e 1066 }
pcercuei 0:03b5121a232e 1067
pcercuei 0:03b5121a232e 1068 xmlFree(comp);
pcercuei 0:03b5121a232e 1069 }
pcercuei 0:03b5121a232e 1070
pcercuei 0:03b5121a232e 1071 /**
pcercuei 0:03b5121a232e 1072 * xmlXPathCompExprAdd:
pcercuei 0:03b5121a232e 1073 * @comp: the compiled expression
pcercuei 0:03b5121a232e 1074 * @ch1: first child index
pcercuei 0:03b5121a232e 1075 * @ch2: second child index
pcercuei 0:03b5121a232e 1076 * @op: an op
pcercuei 0:03b5121a232e 1077 * @value: the first int value
pcercuei 0:03b5121a232e 1078 * @value2: the second int value
pcercuei 0:03b5121a232e 1079 * @value3: the third int value
pcercuei 0:03b5121a232e 1080 * @value4: the first string value
pcercuei 0:03b5121a232e 1081 * @value5: the second string value
pcercuei 0:03b5121a232e 1082 *
pcercuei 0:03b5121a232e 1083 * Add a step to an XPath Compiled Expression
pcercuei 0:03b5121a232e 1084 *
pcercuei 0:03b5121a232e 1085 * Returns -1 in case of failure, the index otherwise
pcercuei 0:03b5121a232e 1086 */
pcercuei 0:03b5121a232e 1087 static int
pcercuei 0:03b5121a232e 1088 xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
pcercuei 0:03b5121a232e 1089 xmlXPathOp op, int value,
pcercuei 0:03b5121a232e 1090 int value2, int value3, void *value4, void *value5) {
pcercuei 0:03b5121a232e 1091 if (comp->nbStep >= comp->maxStep) {
pcercuei 0:03b5121a232e 1092 xmlXPathStepOp *real;
pcercuei 0:03b5121a232e 1093
pcercuei 0:03b5121a232e 1094 if (comp->maxStep >= XPATH_MAX_STEPS) {
pcercuei 0:03b5121a232e 1095 xmlXPathErrMemory(NULL, "adding step\n");
pcercuei 0:03b5121a232e 1096 return(-1);
pcercuei 0:03b5121a232e 1097 }
pcercuei 0:03b5121a232e 1098 comp->maxStep *= 2;
pcercuei 0:03b5121a232e 1099 real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
pcercuei 0:03b5121a232e 1100 comp->maxStep * sizeof(xmlXPathStepOp));
pcercuei 0:03b5121a232e 1101 if (real == NULL) {
pcercuei 0:03b5121a232e 1102 comp->maxStep /= 2;
pcercuei 0:03b5121a232e 1103 xmlXPathErrMemory(NULL, "adding step\n");
pcercuei 0:03b5121a232e 1104 return(-1);
pcercuei 0:03b5121a232e 1105 }
pcercuei 0:03b5121a232e 1106 comp->steps = real;
pcercuei 0:03b5121a232e 1107 }
pcercuei 0:03b5121a232e 1108 comp->last = comp->nbStep;
pcercuei 0:03b5121a232e 1109 comp->steps[comp->nbStep].ch1 = ch1;
pcercuei 0:03b5121a232e 1110 comp->steps[comp->nbStep].ch2 = ch2;
pcercuei 0:03b5121a232e 1111 comp->steps[comp->nbStep].op = op;
pcercuei 0:03b5121a232e 1112 comp->steps[comp->nbStep].value = value;
pcercuei 0:03b5121a232e 1113 comp->steps[comp->nbStep].value2 = value2;
pcercuei 0:03b5121a232e 1114 comp->steps[comp->nbStep].value3 = value3;
pcercuei 0:03b5121a232e 1115 if ((comp->dict != NULL) &&
pcercuei 0:03b5121a232e 1116 ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
pcercuei 0:03b5121a232e 1117 (op == XPATH_OP_COLLECT))) {
pcercuei 0:03b5121a232e 1118 if (value4 != NULL) {
pcercuei 0:03b5121a232e 1119 comp->steps[comp->nbStep].value4 = (xmlChar *)
pcercuei 0:03b5121a232e 1120 (void *)xmlDictLookup(comp->dict, value4, -1);
pcercuei 0:03b5121a232e 1121 xmlFree(value4);
pcercuei 0:03b5121a232e 1122 } else
pcercuei 0:03b5121a232e 1123 comp->steps[comp->nbStep].value4 = NULL;
pcercuei 0:03b5121a232e 1124 if (value5 != NULL) {
pcercuei 0:03b5121a232e 1125 comp->steps[comp->nbStep].value5 = (xmlChar *)
pcercuei 0:03b5121a232e 1126 (void *)xmlDictLookup(comp->dict, value5, -1);
pcercuei 0:03b5121a232e 1127 xmlFree(value5);
pcercuei 0:03b5121a232e 1128 } else
pcercuei 0:03b5121a232e 1129 comp->steps[comp->nbStep].value5 = NULL;
pcercuei 0:03b5121a232e 1130 } else {
pcercuei 0:03b5121a232e 1131 comp->steps[comp->nbStep].value4 = value4;
pcercuei 0:03b5121a232e 1132 comp->steps[comp->nbStep].value5 = value5;
pcercuei 0:03b5121a232e 1133 }
pcercuei 0:03b5121a232e 1134 comp->steps[comp->nbStep].cache = NULL;
pcercuei 0:03b5121a232e 1135 return(comp->nbStep++);
pcercuei 0:03b5121a232e 1136 }
pcercuei 0:03b5121a232e 1137
pcercuei 0:03b5121a232e 1138 /**
pcercuei 0:03b5121a232e 1139 * xmlXPathCompSwap:
pcercuei 0:03b5121a232e 1140 * @comp: the compiled expression
pcercuei 0:03b5121a232e 1141 * @op: operation index
pcercuei 0:03b5121a232e 1142 *
pcercuei 0:03b5121a232e 1143 * Swaps 2 operations in the compiled expression
pcercuei 0:03b5121a232e 1144 */
pcercuei 0:03b5121a232e 1145 static void
pcercuei 0:03b5121a232e 1146 xmlXPathCompSwap(xmlXPathStepOpPtr op) {
pcercuei 0:03b5121a232e 1147 int tmp;
pcercuei 0:03b5121a232e 1148
pcercuei 0:03b5121a232e 1149 #ifndef LIBXML_THREAD_ENABLED
pcercuei 0:03b5121a232e 1150 /*
pcercuei 0:03b5121a232e 1151 * Since this manipulates possibly shared variables, this is
pcercuei 0:03b5121a232e 1152 * disabled if one detects that the library is used in a multithreaded
pcercuei 0:03b5121a232e 1153 * application
pcercuei 0:03b5121a232e 1154 */
pcercuei 0:03b5121a232e 1155 if (xmlXPathDisableOptimizer)
pcercuei 0:03b5121a232e 1156 return;
pcercuei 0:03b5121a232e 1157 #endif
pcercuei 0:03b5121a232e 1158
pcercuei 0:03b5121a232e 1159 tmp = op->ch1;
pcercuei 0:03b5121a232e 1160 op->ch1 = op->ch2;
pcercuei 0:03b5121a232e 1161 op->ch2 = tmp;
pcercuei 0:03b5121a232e 1162 }
pcercuei 0:03b5121a232e 1163
pcercuei 0:03b5121a232e 1164 #define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \
pcercuei 0:03b5121a232e 1165 xmlXPathCompExprAdd(ctxt->comp, (op1), (op2), \
pcercuei 0:03b5121a232e 1166 (op), (val), (val2), (val3), (val4), (val5))
pcercuei 0:03b5121a232e 1167 #define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \
pcercuei 0:03b5121a232e 1168 xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1, \
pcercuei 0:03b5121a232e 1169 (op), (val), (val2), (val3), (val4), (val5))
pcercuei 0:03b5121a232e 1170
pcercuei 0:03b5121a232e 1171 #define PUSH_LEAVE_EXPR(op, val, val2) \
pcercuei 0:03b5121a232e 1172 xmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
pcercuei 0:03b5121a232e 1173
pcercuei 0:03b5121a232e 1174 #define PUSH_UNARY_EXPR(op, ch, val, val2) \
pcercuei 0:03b5121a232e 1175 xmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
pcercuei 0:03b5121a232e 1176
pcercuei 0:03b5121a232e 1177 #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) \
pcercuei 0:03b5121a232e 1178 xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), \
pcercuei 0:03b5121a232e 1179 (val), (val2), 0 ,NULL ,NULL)
pcercuei 0:03b5121a232e 1180
pcercuei 0:03b5121a232e 1181 /************************************************************************
pcercuei 0:03b5121a232e 1182 * *
pcercuei 0:03b5121a232e 1183 * XPath object cache structures *
pcercuei 0:03b5121a232e 1184 * *
pcercuei 0:03b5121a232e 1185 ************************************************************************/
pcercuei 0:03b5121a232e 1186
pcercuei 0:03b5121a232e 1187 /* #define XP_DEFAULT_CACHE_ON */
pcercuei 0:03b5121a232e 1188
pcercuei 0:03b5121a232e 1189 #define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL))
pcercuei 0:03b5121a232e 1190
pcercuei 0:03b5121a232e 1191 typedef struct _xmlXPathContextCache xmlXPathContextCache;
pcercuei 0:03b5121a232e 1192 typedef xmlXPathContextCache *xmlXPathContextCachePtr;
pcercuei 0:03b5121a232e 1193 struct _xmlXPathContextCache {
pcercuei 0:03b5121a232e 1194 xmlPointerListPtr nodesetObjs; /* contains xmlXPathObjectPtr */
pcercuei 0:03b5121a232e 1195 xmlPointerListPtr stringObjs; /* contains xmlXPathObjectPtr */
pcercuei 0:03b5121a232e 1196 xmlPointerListPtr booleanObjs; /* contains xmlXPathObjectPtr */
pcercuei 0:03b5121a232e 1197 xmlPointerListPtr numberObjs; /* contains xmlXPathObjectPtr */
pcercuei 0:03b5121a232e 1198 xmlPointerListPtr miscObjs; /* contains xmlXPathObjectPtr */
pcercuei 0:03b5121a232e 1199 int maxNodeset;
pcercuei 0:03b5121a232e 1200 int maxString;
pcercuei 0:03b5121a232e 1201 int maxBoolean;
pcercuei 0:03b5121a232e 1202 int maxNumber;
pcercuei 0:03b5121a232e 1203 int maxMisc;
pcercuei 0:03b5121a232e 1204 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 1205 int dbgCachedAll;
pcercuei 0:03b5121a232e 1206 int dbgCachedNodeset;
pcercuei 0:03b5121a232e 1207 int dbgCachedString;
pcercuei 0:03b5121a232e 1208 int dbgCachedBool;
pcercuei 0:03b5121a232e 1209 int dbgCachedNumber;
pcercuei 0:03b5121a232e 1210 int dbgCachedPoint;
pcercuei 0:03b5121a232e 1211 int dbgCachedRange;
pcercuei 0:03b5121a232e 1212 int dbgCachedLocset;
pcercuei 0:03b5121a232e 1213 int dbgCachedUsers;
pcercuei 0:03b5121a232e 1214 int dbgCachedXSLTTree;
pcercuei 0:03b5121a232e 1215 int dbgCachedUndefined;
pcercuei 0:03b5121a232e 1216
pcercuei 0:03b5121a232e 1217
pcercuei 0:03b5121a232e 1218 int dbgReusedAll;
pcercuei 0:03b5121a232e 1219 int dbgReusedNodeset;
pcercuei 0:03b5121a232e 1220 int dbgReusedString;
pcercuei 0:03b5121a232e 1221 int dbgReusedBool;
pcercuei 0:03b5121a232e 1222 int dbgReusedNumber;
pcercuei 0:03b5121a232e 1223 int dbgReusedPoint;
pcercuei 0:03b5121a232e 1224 int dbgReusedRange;
pcercuei 0:03b5121a232e 1225 int dbgReusedLocset;
pcercuei 0:03b5121a232e 1226 int dbgReusedUsers;
pcercuei 0:03b5121a232e 1227 int dbgReusedXSLTTree;
pcercuei 0:03b5121a232e 1228 int dbgReusedUndefined;
pcercuei 0:03b5121a232e 1229
pcercuei 0:03b5121a232e 1230 #endif
pcercuei 0:03b5121a232e 1231 };
pcercuei 0:03b5121a232e 1232
pcercuei 0:03b5121a232e 1233 /************************************************************************
pcercuei 0:03b5121a232e 1234 * *
pcercuei 0:03b5121a232e 1235 * Debugging related functions *
pcercuei 0:03b5121a232e 1236 * *
pcercuei 0:03b5121a232e 1237 ************************************************************************/
pcercuei 0:03b5121a232e 1238
pcercuei 0:03b5121a232e 1239 #define STRANGE \
pcercuei 0:03b5121a232e 1240 xmlGenericError(xmlGenericErrorContext, \
pcercuei 0:03b5121a232e 1241 "Internal error at %s:%d\n", \
pcercuei 0:03b5121a232e 1242 __FILE__, __LINE__);
pcercuei 0:03b5121a232e 1243
pcercuei 0:03b5121a232e 1244 #ifdef LIBXML_DEBUG_ENABLED
pcercuei 0:03b5121a232e 1245 static void
pcercuei 0:03b5121a232e 1246 xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
pcercuei 0:03b5121a232e 1247 int i;
pcercuei 0:03b5121a232e 1248 char shift[100];
pcercuei 0:03b5121a232e 1249
pcercuei 0:03b5121a232e 1250 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1251 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1252 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1253 if (cur == NULL) {
pcercuei 0:03b5121a232e 1254 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1255 fprintf(output, "Node is NULL !\n");
pcercuei 0:03b5121a232e 1256 return;
pcercuei 0:03b5121a232e 1257
pcercuei 0:03b5121a232e 1258 }
pcercuei 0:03b5121a232e 1259
pcercuei 0:03b5121a232e 1260 if ((cur->type == XML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 1261 (cur->type == XML_HTML_DOCUMENT_NODE)) {
pcercuei 0:03b5121a232e 1262 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1263 fprintf(output, " /\n");
pcercuei 0:03b5121a232e 1264 } else if (cur->type == XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 1265 xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
pcercuei 0:03b5121a232e 1266 else
pcercuei 0:03b5121a232e 1267 xmlDebugDumpOneNode(output, cur, depth);
pcercuei 0:03b5121a232e 1268 }
pcercuei 0:03b5121a232e 1269 static void
pcercuei 0:03b5121a232e 1270 xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
pcercuei 0:03b5121a232e 1271 xmlNodePtr tmp;
pcercuei 0:03b5121a232e 1272 int i;
pcercuei 0:03b5121a232e 1273 char shift[100];
pcercuei 0:03b5121a232e 1274
pcercuei 0:03b5121a232e 1275 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1276 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1277 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1278 if (cur == NULL) {
pcercuei 0:03b5121a232e 1279 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1280 fprintf(output, "Node is NULL !\n");
pcercuei 0:03b5121a232e 1281 return;
pcercuei 0:03b5121a232e 1282
pcercuei 0:03b5121a232e 1283 }
pcercuei 0:03b5121a232e 1284
pcercuei 0:03b5121a232e 1285 while (cur != NULL) {
pcercuei 0:03b5121a232e 1286 tmp = cur;
pcercuei 0:03b5121a232e 1287 cur = cur->next;
pcercuei 0:03b5121a232e 1288 xmlDebugDumpOneNode(output, tmp, depth);
pcercuei 0:03b5121a232e 1289 }
pcercuei 0:03b5121a232e 1290 }
pcercuei 0:03b5121a232e 1291
pcercuei 0:03b5121a232e 1292 static void
pcercuei 0:03b5121a232e 1293 xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
pcercuei 0:03b5121a232e 1294 int i;
pcercuei 0:03b5121a232e 1295 char shift[100];
pcercuei 0:03b5121a232e 1296
pcercuei 0:03b5121a232e 1297 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1298 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1299 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1300
pcercuei 0:03b5121a232e 1301 if (cur == NULL) {
pcercuei 0:03b5121a232e 1302 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1303 fprintf(output, "NodeSet is NULL !\n");
pcercuei 0:03b5121a232e 1304 return;
pcercuei 0:03b5121a232e 1305
pcercuei 0:03b5121a232e 1306 }
pcercuei 0:03b5121a232e 1307
pcercuei 0:03b5121a232e 1308 if (cur != NULL) {
pcercuei 0:03b5121a232e 1309 fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
pcercuei 0:03b5121a232e 1310 for (i = 0;i < cur->nodeNr;i++) {
pcercuei 0:03b5121a232e 1311 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1312 fprintf(output, "%d", i + 1);
pcercuei 0:03b5121a232e 1313 xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
pcercuei 0:03b5121a232e 1314 }
pcercuei 0:03b5121a232e 1315 }
pcercuei 0:03b5121a232e 1316 }
pcercuei 0:03b5121a232e 1317
pcercuei 0:03b5121a232e 1318 static void
pcercuei 0:03b5121a232e 1319 xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
pcercuei 0:03b5121a232e 1320 int i;
pcercuei 0:03b5121a232e 1321 char shift[100];
pcercuei 0:03b5121a232e 1322
pcercuei 0:03b5121a232e 1323 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1324 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1325 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1326
pcercuei 0:03b5121a232e 1327 if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
pcercuei 0:03b5121a232e 1328 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1329 fprintf(output, "Value Tree is NULL !\n");
pcercuei 0:03b5121a232e 1330 return;
pcercuei 0:03b5121a232e 1331
pcercuei 0:03b5121a232e 1332 }
pcercuei 0:03b5121a232e 1333
pcercuei 0:03b5121a232e 1334 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1335 fprintf(output, "%d", i + 1);
pcercuei 0:03b5121a232e 1336 xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
pcercuei 0:03b5121a232e 1337 }
pcercuei 0:03b5121a232e 1338 #if defined(LIBXML_XPTR_ENABLED)
pcercuei 0:03b5121a232e 1339 static void
pcercuei 0:03b5121a232e 1340 xmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
pcercuei 0:03b5121a232e 1341 int i;
pcercuei 0:03b5121a232e 1342 char shift[100];
pcercuei 0:03b5121a232e 1343
pcercuei 0:03b5121a232e 1344 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1345 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1346 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1347
pcercuei 0:03b5121a232e 1348 if (cur == NULL) {
pcercuei 0:03b5121a232e 1349 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1350 fprintf(output, "LocationSet is NULL !\n");
pcercuei 0:03b5121a232e 1351 return;
pcercuei 0:03b5121a232e 1352
pcercuei 0:03b5121a232e 1353 }
pcercuei 0:03b5121a232e 1354
pcercuei 0:03b5121a232e 1355 for (i = 0;i < cur->locNr;i++) {
pcercuei 0:03b5121a232e 1356 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1357 fprintf(output, "%d : ", i + 1);
pcercuei 0:03b5121a232e 1358 xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
pcercuei 0:03b5121a232e 1359 }
pcercuei 0:03b5121a232e 1360 }
pcercuei 0:03b5121a232e 1361 #endif /* LIBXML_XPTR_ENABLED */
pcercuei 0:03b5121a232e 1362
pcercuei 0:03b5121a232e 1363 /**
pcercuei 0:03b5121a232e 1364 * xmlXPathDebugDumpObject:
pcercuei 0:03b5121a232e 1365 * @output: the FILE * to dump the output
pcercuei 0:03b5121a232e 1366 * @cur: the object to inspect
pcercuei 0:03b5121a232e 1367 * @depth: indentation level
pcercuei 0:03b5121a232e 1368 *
pcercuei 0:03b5121a232e 1369 * Dump the content of the object for debugging purposes
pcercuei 0:03b5121a232e 1370 */
pcercuei 0:03b5121a232e 1371 void
pcercuei 0:03b5121a232e 1372 xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
pcercuei 0:03b5121a232e 1373 int i;
pcercuei 0:03b5121a232e 1374 char shift[100];
pcercuei 0:03b5121a232e 1375
pcercuei 0:03b5121a232e 1376 if (output == NULL) return;
pcercuei 0:03b5121a232e 1377
pcercuei 0:03b5121a232e 1378 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1379 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1380 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1381
pcercuei 0:03b5121a232e 1382
pcercuei 0:03b5121a232e 1383 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1384
pcercuei 0:03b5121a232e 1385 if (cur == NULL) {
pcercuei 0:03b5121a232e 1386 fprintf(output, "Object is empty (NULL)\n");
pcercuei 0:03b5121a232e 1387 return;
pcercuei 0:03b5121a232e 1388 }
pcercuei 0:03b5121a232e 1389 switch(cur->type) {
pcercuei 0:03b5121a232e 1390 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 1391 fprintf(output, "Object is uninitialized\n");
pcercuei 0:03b5121a232e 1392 break;
pcercuei 0:03b5121a232e 1393 case XPATH_NODESET:
pcercuei 0:03b5121a232e 1394 fprintf(output, "Object is a Node Set :\n");
pcercuei 0:03b5121a232e 1395 xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
pcercuei 0:03b5121a232e 1396 break;
pcercuei 0:03b5121a232e 1397 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 1398 fprintf(output, "Object is an XSLT value tree :\n");
pcercuei 0:03b5121a232e 1399 xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
pcercuei 0:03b5121a232e 1400 break;
pcercuei 0:03b5121a232e 1401 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 1402 fprintf(output, "Object is a Boolean : ");
pcercuei 0:03b5121a232e 1403 if (cur->boolval) fprintf(output, "true\n");
pcercuei 0:03b5121a232e 1404 else fprintf(output, "false\n");
pcercuei 0:03b5121a232e 1405 break;
pcercuei 0:03b5121a232e 1406 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 1407 switch (xmlXPathIsInf(cur->floatval)) {
pcercuei 0:03b5121a232e 1408 case 1:
pcercuei 0:03b5121a232e 1409 fprintf(output, "Object is a number : Infinity\n");
pcercuei 0:03b5121a232e 1410 break;
pcercuei 0:03b5121a232e 1411 case -1:
pcercuei 0:03b5121a232e 1412 fprintf(output, "Object is a number : -Infinity\n");
pcercuei 0:03b5121a232e 1413 break;
pcercuei 0:03b5121a232e 1414 default:
pcercuei 0:03b5121a232e 1415 if (xmlXPathIsNaN(cur->floatval)) {
pcercuei 0:03b5121a232e 1416 fprintf(output, "Object is a number : NaN\n");
pcercuei 0:03b5121a232e 1417 } else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) {
pcercuei 0:03b5121a232e 1418 fprintf(output, "Object is a number : 0\n");
pcercuei 0:03b5121a232e 1419 } else {
pcercuei 0:03b5121a232e 1420 fprintf(output, "Object is a number : %0g\n", cur->floatval);
pcercuei 0:03b5121a232e 1421 }
pcercuei 0:03b5121a232e 1422 }
pcercuei 0:03b5121a232e 1423 break;
pcercuei 0:03b5121a232e 1424 case XPATH_STRING:
pcercuei 0:03b5121a232e 1425 fprintf(output, "Object is a string : ");
pcercuei 0:03b5121a232e 1426 xmlDebugDumpString(output, cur->stringval);
pcercuei 0:03b5121a232e 1427 fprintf(output, "\n");
pcercuei 0:03b5121a232e 1428 break;
pcercuei 0:03b5121a232e 1429 case XPATH_POINT:
pcercuei 0:03b5121a232e 1430 fprintf(output, "Object is a point : index %d in node", cur->index);
pcercuei 0:03b5121a232e 1431 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
pcercuei 0:03b5121a232e 1432 fprintf(output, "\n");
pcercuei 0:03b5121a232e 1433 break;
pcercuei 0:03b5121a232e 1434 case XPATH_RANGE:
pcercuei 0:03b5121a232e 1435 if ((cur->user2 == NULL) ||
pcercuei 0:03b5121a232e 1436 ((cur->user2 == cur->user) && (cur->index == cur->index2))) {
pcercuei 0:03b5121a232e 1437 fprintf(output, "Object is a collapsed range :\n");
pcercuei 0:03b5121a232e 1438 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1439 if (cur->index >= 0)
pcercuei 0:03b5121a232e 1440 fprintf(output, "index %d in ", cur->index);
pcercuei 0:03b5121a232e 1441 fprintf(output, "node\n");
pcercuei 0:03b5121a232e 1442 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
pcercuei 0:03b5121a232e 1443 depth + 1);
pcercuei 0:03b5121a232e 1444 } else {
pcercuei 0:03b5121a232e 1445 fprintf(output, "Object is a range :\n");
pcercuei 0:03b5121a232e 1446 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1447 fprintf(output, "From ");
pcercuei 0:03b5121a232e 1448 if (cur->index >= 0)
pcercuei 0:03b5121a232e 1449 fprintf(output, "index %d in ", cur->index);
pcercuei 0:03b5121a232e 1450 fprintf(output, "node\n");
pcercuei 0:03b5121a232e 1451 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
pcercuei 0:03b5121a232e 1452 depth + 1);
pcercuei 0:03b5121a232e 1453 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1454 fprintf(output, "To ");
pcercuei 0:03b5121a232e 1455 if (cur->index2 >= 0)
pcercuei 0:03b5121a232e 1456 fprintf(output, "index %d in ", cur->index2);
pcercuei 0:03b5121a232e 1457 fprintf(output, "node\n");
pcercuei 0:03b5121a232e 1458 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
pcercuei 0:03b5121a232e 1459 depth + 1);
pcercuei 0:03b5121a232e 1460 fprintf(output, "\n");
pcercuei 0:03b5121a232e 1461 }
pcercuei 0:03b5121a232e 1462 break;
pcercuei 0:03b5121a232e 1463 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 1464 #if defined(LIBXML_XPTR_ENABLED)
pcercuei 0:03b5121a232e 1465 fprintf(output, "Object is a Location Set:\n");
pcercuei 0:03b5121a232e 1466 xmlXPathDebugDumpLocationSet(output,
pcercuei 0:03b5121a232e 1467 (xmlLocationSetPtr) cur->user, depth);
pcercuei 0:03b5121a232e 1468 #endif
pcercuei 0:03b5121a232e 1469 break;
pcercuei 0:03b5121a232e 1470 case XPATH_USERS:
pcercuei 0:03b5121a232e 1471 fprintf(output, "Object is user defined\n");
pcercuei 0:03b5121a232e 1472 break;
pcercuei 0:03b5121a232e 1473 }
pcercuei 0:03b5121a232e 1474 }
pcercuei 0:03b5121a232e 1475
pcercuei 0:03b5121a232e 1476 static void
pcercuei 0:03b5121a232e 1477 xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
pcercuei 0:03b5121a232e 1478 xmlXPathStepOpPtr op, int depth) {
pcercuei 0:03b5121a232e 1479 int i;
pcercuei 0:03b5121a232e 1480 char shift[100];
pcercuei 0:03b5121a232e 1481
pcercuei 0:03b5121a232e 1482 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1483 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1484 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1485
pcercuei 0:03b5121a232e 1486 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1487 if (op == NULL) {
pcercuei 0:03b5121a232e 1488 fprintf(output, "Step is NULL\n");
pcercuei 0:03b5121a232e 1489 return;
pcercuei 0:03b5121a232e 1490 }
pcercuei 0:03b5121a232e 1491 switch (op->op) {
pcercuei 0:03b5121a232e 1492 case XPATH_OP_END:
pcercuei 0:03b5121a232e 1493 fprintf(output, "END"); break;
pcercuei 0:03b5121a232e 1494 case XPATH_OP_AND:
pcercuei 0:03b5121a232e 1495 fprintf(output, "AND"); break;
pcercuei 0:03b5121a232e 1496 case XPATH_OP_OR:
pcercuei 0:03b5121a232e 1497 fprintf(output, "OR"); break;
pcercuei 0:03b5121a232e 1498 case XPATH_OP_EQUAL:
pcercuei 0:03b5121a232e 1499 if (op->value)
pcercuei 0:03b5121a232e 1500 fprintf(output, "EQUAL =");
pcercuei 0:03b5121a232e 1501 else
pcercuei 0:03b5121a232e 1502 fprintf(output, "EQUAL !=");
pcercuei 0:03b5121a232e 1503 break;
pcercuei 0:03b5121a232e 1504 case XPATH_OP_CMP:
pcercuei 0:03b5121a232e 1505 if (op->value)
pcercuei 0:03b5121a232e 1506 fprintf(output, "CMP <");
pcercuei 0:03b5121a232e 1507 else
pcercuei 0:03b5121a232e 1508 fprintf(output, "CMP >");
pcercuei 0:03b5121a232e 1509 if (!op->value2)
pcercuei 0:03b5121a232e 1510 fprintf(output, "=");
pcercuei 0:03b5121a232e 1511 break;
pcercuei 0:03b5121a232e 1512 case XPATH_OP_PLUS:
pcercuei 0:03b5121a232e 1513 if (op->value == 0)
pcercuei 0:03b5121a232e 1514 fprintf(output, "PLUS -");
pcercuei 0:03b5121a232e 1515 else if (op->value == 1)
pcercuei 0:03b5121a232e 1516 fprintf(output, "PLUS +");
pcercuei 0:03b5121a232e 1517 else if (op->value == 2)
pcercuei 0:03b5121a232e 1518 fprintf(output, "PLUS unary -");
pcercuei 0:03b5121a232e 1519 else if (op->value == 3)
pcercuei 0:03b5121a232e 1520 fprintf(output, "PLUS unary - -");
pcercuei 0:03b5121a232e 1521 break;
pcercuei 0:03b5121a232e 1522 case XPATH_OP_MULT:
pcercuei 0:03b5121a232e 1523 if (op->value == 0)
pcercuei 0:03b5121a232e 1524 fprintf(output, "MULT *");
pcercuei 0:03b5121a232e 1525 else if (op->value == 1)
pcercuei 0:03b5121a232e 1526 fprintf(output, "MULT div");
pcercuei 0:03b5121a232e 1527 else
pcercuei 0:03b5121a232e 1528 fprintf(output, "MULT mod");
pcercuei 0:03b5121a232e 1529 break;
pcercuei 0:03b5121a232e 1530 case XPATH_OP_UNION:
pcercuei 0:03b5121a232e 1531 fprintf(output, "UNION"); break;
pcercuei 0:03b5121a232e 1532 case XPATH_OP_ROOT:
pcercuei 0:03b5121a232e 1533 fprintf(output, "ROOT"); break;
pcercuei 0:03b5121a232e 1534 case XPATH_OP_NODE:
pcercuei 0:03b5121a232e 1535 fprintf(output, "NODE"); break;
pcercuei 0:03b5121a232e 1536 case XPATH_OP_RESET:
pcercuei 0:03b5121a232e 1537 fprintf(output, "RESET"); break;
pcercuei 0:03b5121a232e 1538 case XPATH_OP_SORT:
pcercuei 0:03b5121a232e 1539 fprintf(output, "SORT"); break;
pcercuei 0:03b5121a232e 1540 case XPATH_OP_COLLECT: {
pcercuei 0:03b5121a232e 1541 xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
pcercuei 0:03b5121a232e 1542 xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
pcercuei 0:03b5121a232e 1543 xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
pcercuei 0:03b5121a232e 1544 const xmlChar *prefix = op->value4;
pcercuei 0:03b5121a232e 1545 const xmlChar *name = op->value5;
pcercuei 0:03b5121a232e 1546
pcercuei 0:03b5121a232e 1547 fprintf(output, "COLLECT ");
pcercuei 0:03b5121a232e 1548 switch (axis) {
pcercuei 0:03b5121a232e 1549 case AXIS_ANCESTOR:
pcercuei 0:03b5121a232e 1550 fprintf(output, " 'ancestors' "); break;
pcercuei 0:03b5121a232e 1551 case AXIS_ANCESTOR_OR_SELF:
pcercuei 0:03b5121a232e 1552 fprintf(output, " 'ancestors-or-self' "); break;
pcercuei 0:03b5121a232e 1553 case AXIS_ATTRIBUTE:
pcercuei 0:03b5121a232e 1554 fprintf(output, " 'attributes' "); break;
pcercuei 0:03b5121a232e 1555 case AXIS_CHILD:
pcercuei 0:03b5121a232e 1556 fprintf(output, " 'child' "); break;
pcercuei 0:03b5121a232e 1557 case AXIS_DESCENDANT:
pcercuei 0:03b5121a232e 1558 fprintf(output, " 'descendant' "); break;
pcercuei 0:03b5121a232e 1559 case AXIS_DESCENDANT_OR_SELF:
pcercuei 0:03b5121a232e 1560 fprintf(output, " 'descendant-or-self' "); break;
pcercuei 0:03b5121a232e 1561 case AXIS_FOLLOWING:
pcercuei 0:03b5121a232e 1562 fprintf(output, " 'following' "); break;
pcercuei 0:03b5121a232e 1563 case AXIS_FOLLOWING_SIBLING:
pcercuei 0:03b5121a232e 1564 fprintf(output, " 'following-siblings' "); break;
pcercuei 0:03b5121a232e 1565 case AXIS_NAMESPACE:
pcercuei 0:03b5121a232e 1566 fprintf(output, " 'namespace' "); break;
pcercuei 0:03b5121a232e 1567 case AXIS_PARENT:
pcercuei 0:03b5121a232e 1568 fprintf(output, " 'parent' "); break;
pcercuei 0:03b5121a232e 1569 case AXIS_PRECEDING:
pcercuei 0:03b5121a232e 1570 fprintf(output, " 'preceding' "); break;
pcercuei 0:03b5121a232e 1571 case AXIS_PRECEDING_SIBLING:
pcercuei 0:03b5121a232e 1572 fprintf(output, " 'preceding-sibling' "); break;
pcercuei 0:03b5121a232e 1573 case AXIS_SELF:
pcercuei 0:03b5121a232e 1574 fprintf(output, " 'self' "); break;
pcercuei 0:03b5121a232e 1575 }
pcercuei 0:03b5121a232e 1576 switch (test) {
pcercuei 0:03b5121a232e 1577 case NODE_TEST_NONE:
pcercuei 0:03b5121a232e 1578 fprintf(output, "'none' "); break;
pcercuei 0:03b5121a232e 1579 case NODE_TEST_TYPE:
pcercuei 0:03b5121a232e 1580 fprintf(output, "'type' "); break;
pcercuei 0:03b5121a232e 1581 case NODE_TEST_PI:
pcercuei 0:03b5121a232e 1582 fprintf(output, "'PI' "); break;
pcercuei 0:03b5121a232e 1583 case NODE_TEST_ALL:
pcercuei 0:03b5121a232e 1584 fprintf(output, "'all' "); break;
pcercuei 0:03b5121a232e 1585 case NODE_TEST_NS:
pcercuei 0:03b5121a232e 1586 fprintf(output, "'namespace' "); break;
pcercuei 0:03b5121a232e 1587 case NODE_TEST_NAME:
pcercuei 0:03b5121a232e 1588 fprintf(output, "'name' "); break;
pcercuei 0:03b5121a232e 1589 }
pcercuei 0:03b5121a232e 1590 switch (type) {
pcercuei 0:03b5121a232e 1591 case NODE_TYPE_NODE:
pcercuei 0:03b5121a232e 1592 fprintf(output, "'node' "); break;
pcercuei 0:03b5121a232e 1593 case NODE_TYPE_COMMENT:
pcercuei 0:03b5121a232e 1594 fprintf(output, "'comment' "); break;
pcercuei 0:03b5121a232e 1595 case NODE_TYPE_TEXT:
pcercuei 0:03b5121a232e 1596 fprintf(output, "'text' "); break;
pcercuei 0:03b5121a232e 1597 case NODE_TYPE_PI:
pcercuei 0:03b5121a232e 1598 fprintf(output, "'PI' "); break;
pcercuei 0:03b5121a232e 1599 }
pcercuei 0:03b5121a232e 1600 if (prefix != NULL)
pcercuei 0:03b5121a232e 1601 fprintf(output, "%s:", prefix);
pcercuei 0:03b5121a232e 1602 if (name != NULL)
pcercuei 0:03b5121a232e 1603 fprintf(output, "%s", (const char *) name);
pcercuei 0:03b5121a232e 1604 break;
pcercuei 0:03b5121a232e 1605
pcercuei 0:03b5121a232e 1606 }
pcercuei 0:03b5121a232e 1607 case XPATH_OP_VALUE: {
pcercuei 0:03b5121a232e 1608 xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
pcercuei 0:03b5121a232e 1609
pcercuei 0:03b5121a232e 1610 fprintf(output, "ELEM ");
pcercuei 0:03b5121a232e 1611 xmlXPathDebugDumpObject(output, object, 0);
pcercuei 0:03b5121a232e 1612 goto finish;
pcercuei 0:03b5121a232e 1613 }
pcercuei 0:03b5121a232e 1614 case XPATH_OP_VARIABLE: {
pcercuei 0:03b5121a232e 1615 const xmlChar *prefix = op->value5;
pcercuei 0:03b5121a232e 1616 const xmlChar *name = op->value4;
pcercuei 0:03b5121a232e 1617
pcercuei 0:03b5121a232e 1618 if (prefix != NULL)
pcercuei 0:03b5121a232e 1619 fprintf(output, "VARIABLE %s:%s", prefix, name);
pcercuei 0:03b5121a232e 1620 else
pcercuei 0:03b5121a232e 1621 fprintf(output, "VARIABLE %s", name);
pcercuei 0:03b5121a232e 1622 break;
pcercuei 0:03b5121a232e 1623 }
pcercuei 0:03b5121a232e 1624 case XPATH_OP_FUNCTION: {
pcercuei 0:03b5121a232e 1625 int nbargs = op->value;
pcercuei 0:03b5121a232e 1626 const xmlChar *prefix = op->value5;
pcercuei 0:03b5121a232e 1627 const xmlChar *name = op->value4;
pcercuei 0:03b5121a232e 1628
pcercuei 0:03b5121a232e 1629 if (prefix != NULL)
pcercuei 0:03b5121a232e 1630 fprintf(output, "FUNCTION %s:%s(%d args)",
pcercuei 0:03b5121a232e 1631 prefix, name, nbargs);
pcercuei 0:03b5121a232e 1632 else
pcercuei 0:03b5121a232e 1633 fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
pcercuei 0:03b5121a232e 1634 break;
pcercuei 0:03b5121a232e 1635 }
pcercuei 0:03b5121a232e 1636 case XPATH_OP_ARG: fprintf(output, "ARG"); break;
pcercuei 0:03b5121a232e 1637 case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
pcercuei 0:03b5121a232e 1638 case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
pcercuei 0:03b5121a232e 1639 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 1640 case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break;
pcercuei 0:03b5121a232e 1641 #endif
pcercuei 0:03b5121a232e 1642 default:
pcercuei 0:03b5121a232e 1643 fprintf(output, "UNKNOWN %d\n", op->op); return;
pcercuei 0:03b5121a232e 1644 }
pcercuei 0:03b5121a232e 1645 fprintf(output, "\n");
pcercuei 0:03b5121a232e 1646 finish:
pcercuei 0:03b5121a232e 1647 if (op->ch1 >= 0)
pcercuei 0:03b5121a232e 1648 xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
pcercuei 0:03b5121a232e 1649 if (op->ch2 >= 0)
pcercuei 0:03b5121a232e 1650 xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
pcercuei 0:03b5121a232e 1651 }
pcercuei 0:03b5121a232e 1652
pcercuei 0:03b5121a232e 1653 /**
pcercuei 0:03b5121a232e 1654 * xmlXPathDebugDumpCompExpr:
pcercuei 0:03b5121a232e 1655 * @output: the FILE * for the output
pcercuei 0:03b5121a232e 1656 * @comp: the precompiled XPath expression
pcercuei 0:03b5121a232e 1657 * @depth: the indentation level.
pcercuei 0:03b5121a232e 1658 *
pcercuei 0:03b5121a232e 1659 * Dumps the tree of the compiled XPath expression.
pcercuei 0:03b5121a232e 1660 */
pcercuei 0:03b5121a232e 1661 void
pcercuei 0:03b5121a232e 1662 xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
pcercuei 0:03b5121a232e 1663 int depth) {
pcercuei 0:03b5121a232e 1664 int i;
pcercuei 0:03b5121a232e 1665 char shift[100];
pcercuei 0:03b5121a232e 1666
pcercuei 0:03b5121a232e 1667 if ((output == NULL) || (comp == NULL)) return;
pcercuei 0:03b5121a232e 1668
pcercuei 0:03b5121a232e 1669 for (i = 0;((i < depth) && (i < 25));i++)
pcercuei 0:03b5121a232e 1670 shift[2 * i] = shift[2 * i + 1] = ' ';
pcercuei 0:03b5121a232e 1671 shift[2 * i] = shift[2 * i + 1] = 0;
pcercuei 0:03b5121a232e 1672
pcercuei 0:03b5121a232e 1673 fprintf(output, "%s", shift);
pcercuei 0:03b5121a232e 1674
pcercuei 0:03b5121a232e 1675 fprintf(output, "Compiled Expression : %d elements\n",
pcercuei 0:03b5121a232e 1676 comp->nbStep);
pcercuei 0:03b5121a232e 1677 i = comp->last;
pcercuei 0:03b5121a232e 1678 xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
pcercuei 0:03b5121a232e 1679 }
pcercuei 0:03b5121a232e 1680
pcercuei 0:03b5121a232e 1681 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 1682
pcercuei 0:03b5121a232e 1683 /*
pcercuei 0:03b5121a232e 1684 * XPath object usage related debugging variables.
pcercuei 0:03b5121a232e 1685 */
pcercuei 0:03b5121a232e 1686 static int xmlXPathDebugObjCounterUndefined = 0;
pcercuei 0:03b5121a232e 1687 static int xmlXPathDebugObjCounterNodeset = 0;
pcercuei 0:03b5121a232e 1688 static int xmlXPathDebugObjCounterBool = 0;
pcercuei 0:03b5121a232e 1689 static int xmlXPathDebugObjCounterNumber = 0;
pcercuei 0:03b5121a232e 1690 static int xmlXPathDebugObjCounterString = 0;
pcercuei 0:03b5121a232e 1691 static int xmlXPathDebugObjCounterPoint = 0;
pcercuei 0:03b5121a232e 1692 static int xmlXPathDebugObjCounterRange = 0;
pcercuei 0:03b5121a232e 1693 static int xmlXPathDebugObjCounterLocset = 0;
pcercuei 0:03b5121a232e 1694 static int xmlXPathDebugObjCounterUsers = 0;
pcercuei 0:03b5121a232e 1695 static int xmlXPathDebugObjCounterXSLTTree = 0;
pcercuei 0:03b5121a232e 1696 static int xmlXPathDebugObjCounterAll = 0;
pcercuei 0:03b5121a232e 1697
pcercuei 0:03b5121a232e 1698 static int xmlXPathDebugObjTotalUndefined = 0;
pcercuei 0:03b5121a232e 1699 static int xmlXPathDebugObjTotalNodeset = 0;
pcercuei 0:03b5121a232e 1700 static int xmlXPathDebugObjTotalBool = 0;
pcercuei 0:03b5121a232e 1701 static int xmlXPathDebugObjTotalNumber = 0;
pcercuei 0:03b5121a232e 1702 static int xmlXPathDebugObjTotalString = 0;
pcercuei 0:03b5121a232e 1703 static int xmlXPathDebugObjTotalPoint = 0;
pcercuei 0:03b5121a232e 1704 static int xmlXPathDebugObjTotalRange = 0;
pcercuei 0:03b5121a232e 1705 static int xmlXPathDebugObjTotalLocset = 0;
pcercuei 0:03b5121a232e 1706 static int xmlXPathDebugObjTotalUsers = 0;
pcercuei 0:03b5121a232e 1707 static int xmlXPathDebugObjTotalXSLTTree = 0;
pcercuei 0:03b5121a232e 1708 static int xmlXPathDebugObjTotalAll = 0;
pcercuei 0:03b5121a232e 1709
pcercuei 0:03b5121a232e 1710 static int xmlXPathDebugObjMaxUndefined = 0;
pcercuei 0:03b5121a232e 1711 static int xmlXPathDebugObjMaxNodeset = 0;
pcercuei 0:03b5121a232e 1712 static int xmlXPathDebugObjMaxBool = 0;
pcercuei 0:03b5121a232e 1713 static int xmlXPathDebugObjMaxNumber = 0;
pcercuei 0:03b5121a232e 1714 static int xmlXPathDebugObjMaxString = 0;
pcercuei 0:03b5121a232e 1715 static int xmlXPathDebugObjMaxPoint = 0;
pcercuei 0:03b5121a232e 1716 static int xmlXPathDebugObjMaxRange = 0;
pcercuei 0:03b5121a232e 1717 static int xmlXPathDebugObjMaxLocset = 0;
pcercuei 0:03b5121a232e 1718 static int xmlXPathDebugObjMaxUsers = 0;
pcercuei 0:03b5121a232e 1719 static int xmlXPathDebugObjMaxXSLTTree = 0;
pcercuei 0:03b5121a232e 1720 static int xmlXPathDebugObjMaxAll = 0;
pcercuei 0:03b5121a232e 1721
pcercuei 0:03b5121a232e 1722 /* REVISIT TODO: Make this static when committing */
pcercuei 0:03b5121a232e 1723 static void
pcercuei 0:03b5121a232e 1724 xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt)
pcercuei 0:03b5121a232e 1725 {
pcercuei 0:03b5121a232e 1726 if (ctxt != NULL) {
pcercuei 0:03b5121a232e 1727 if (ctxt->cache != NULL) {
pcercuei 0:03b5121a232e 1728 xmlXPathContextCachePtr cache =
pcercuei 0:03b5121a232e 1729 (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 1730
pcercuei 0:03b5121a232e 1731 cache->dbgCachedAll = 0;
pcercuei 0:03b5121a232e 1732 cache->dbgCachedNodeset = 0;
pcercuei 0:03b5121a232e 1733 cache->dbgCachedString = 0;
pcercuei 0:03b5121a232e 1734 cache->dbgCachedBool = 0;
pcercuei 0:03b5121a232e 1735 cache->dbgCachedNumber = 0;
pcercuei 0:03b5121a232e 1736 cache->dbgCachedPoint = 0;
pcercuei 0:03b5121a232e 1737 cache->dbgCachedRange = 0;
pcercuei 0:03b5121a232e 1738 cache->dbgCachedLocset = 0;
pcercuei 0:03b5121a232e 1739 cache->dbgCachedUsers = 0;
pcercuei 0:03b5121a232e 1740 cache->dbgCachedXSLTTree = 0;
pcercuei 0:03b5121a232e 1741 cache->dbgCachedUndefined = 0;
pcercuei 0:03b5121a232e 1742
pcercuei 0:03b5121a232e 1743 cache->dbgReusedAll = 0;
pcercuei 0:03b5121a232e 1744 cache->dbgReusedNodeset = 0;
pcercuei 0:03b5121a232e 1745 cache->dbgReusedString = 0;
pcercuei 0:03b5121a232e 1746 cache->dbgReusedBool = 0;
pcercuei 0:03b5121a232e 1747 cache->dbgReusedNumber = 0;
pcercuei 0:03b5121a232e 1748 cache->dbgReusedPoint = 0;
pcercuei 0:03b5121a232e 1749 cache->dbgReusedRange = 0;
pcercuei 0:03b5121a232e 1750 cache->dbgReusedLocset = 0;
pcercuei 0:03b5121a232e 1751 cache->dbgReusedUsers = 0;
pcercuei 0:03b5121a232e 1752 cache->dbgReusedXSLTTree = 0;
pcercuei 0:03b5121a232e 1753 cache->dbgReusedUndefined = 0;
pcercuei 0:03b5121a232e 1754 }
pcercuei 0:03b5121a232e 1755 }
pcercuei 0:03b5121a232e 1756
pcercuei 0:03b5121a232e 1757 xmlXPathDebugObjCounterUndefined = 0;
pcercuei 0:03b5121a232e 1758 xmlXPathDebugObjCounterNodeset = 0;
pcercuei 0:03b5121a232e 1759 xmlXPathDebugObjCounterBool = 0;
pcercuei 0:03b5121a232e 1760 xmlXPathDebugObjCounterNumber = 0;
pcercuei 0:03b5121a232e 1761 xmlXPathDebugObjCounterString = 0;
pcercuei 0:03b5121a232e 1762 xmlXPathDebugObjCounterPoint = 0;
pcercuei 0:03b5121a232e 1763 xmlXPathDebugObjCounterRange = 0;
pcercuei 0:03b5121a232e 1764 xmlXPathDebugObjCounterLocset = 0;
pcercuei 0:03b5121a232e 1765 xmlXPathDebugObjCounterUsers = 0;
pcercuei 0:03b5121a232e 1766 xmlXPathDebugObjCounterXSLTTree = 0;
pcercuei 0:03b5121a232e 1767 xmlXPathDebugObjCounterAll = 0;
pcercuei 0:03b5121a232e 1768
pcercuei 0:03b5121a232e 1769 xmlXPathDebugObjTotalUndefined = 0;
pcercuei 0:03b5121a232e 1770 xmlXPathDebugObjTotalNodeset = 0;
pcercuei 0:03b5121a232e 1771 xmlXPathDebugObjTotalBool = 0;
pcercuei 0:03b5121a232e 1772 xmlXPathDebugObjTotalNumber = 0;
pcercuei 0:03b5121a232e 1773 xmlXPathDebugObjTotalString = 0;
pcercuei 0:03b5121a232e 1774 xmlXPathDebugObjTotalPoint = 0;
pcercuei 0:03b5121a232e 1775 xmlXPathDebugObjTotalRange = 0;
pcercuei 0:03b5121a232e 1776 xmlXPathDebugObjTotalLocset = 0;
pcercuei 0:03b5121a232e 1777 xmlXPathDebugObjTotalUsers = 0;
pcercuei 0:03b5121a232e 1778 xmlXPathDebugObjTotalXSLTTree = 0;
pcercuei 0:03b5121a232e 1779 xmlXPathDebugObjTotalAll = 0;
pcercuei 0:03b5121a232e 1780
pcercuei 0:03b5121a232e 1781 xmlXPathDebugObjMaxUndefined = 0;
pcercuei 0:03b5121a232e 1782 xmlXPathDebugObjMaxNodeset = 0;
pcercuei 0:03b5121a232e 1783 xmlXPathDebugObjMaxBool = 0;
pcercuei 0:03b5121a232e 1784 xmlXPathDebugObjMaxNumber = 0;
pcercuei 0:03b5121a232e 1785 xmlXPathDebugObjMaxString = 0;
pcercuei 0:03b5121a232e 1786 xmlXPathDebugObjMaxPoint = 0;
pcercuei 0:03b5121a232e 1787 xmlXPathDebugObjMaxRange = 0;
pcercuei 0:03b5121a232e 1788 xmlXPathDebugObjMaxLocset = 0;
pcercuei 0:03b5121a232e 1789 xmlXPathDebugObjMaxUsers = 0;
pcercuei 0:03b5121a232e 1790 xmlXPathDebugObjMaxXSLTTree = 0;
pcercuei 0:03b5121a232e 1791 xmlXPathDebugObjMaxAll = 0;
pcercuei 0:03b5121a232e 1792
pcercuei 0:03b5121a232e 1793 }
pcercuei 0:03b5121a232e 1794
pcercuei 0:03b5121a232e 1795 static void
pcercuei 0:03b5121a232e 1796 xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt,
pcercuei 0:03b5121a232e 1797 xmlXPathObjectType objType)
pcercuei 0:03b5121a232e 1798 {
pcercuei 0:03b5121a232e 1799 int isCached = 0;
pcercuei 0:03b5121a232e 1800
pcercuei 0:03b5121a232e 1801 if (ctxt != NULL) {
pcercuei 0:03b5121a232e 1802 if (ctxt->cache != NULL) {
pcercuei 0:03b5121a232e 1803 xmlXPathContextCachePtr cache =
pcercuei 0:03b5121a232e 1804 (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 1805
pcercuei 0:03b5121a232e 1806 isCached = 1;
pcercuei 0:03b5121a232e 1807
pcercuei 0:03b5121a232e 1808 cache->dbgReusedAll++;
pcercuei 0:03b5121a232e 1809 switch (objType) {
pcercuei 0:03b5121a232e 1810 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 1811 cache->dbgReusedUndefined++;
pcercuei 0:03b5121a232e 1812 break;
pcercuei 0:03b5121a232e 1813 case XPATH_NODESET:
pcercuei 0:03b5121a232e 1814 cache->dbgReusedNodeset++;
pcercuei 0:03b5121a232e 1815 break;
pcercuei 0:03b5121a232e 1816 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 1817 cache->dbgReusedBool++;
pcercuei 0:03b5121a232e 1818 break;
pcercuei 0:03b5121a232e 1819 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 1820 cache->dbgReusedNumber++;
pcercuei 0:03b5121a232e 1821 break;
pcercuei 0:03b5121a232e 1822 case XPATH_STRING:
pcercuei 0:03b5121a232e 1823 cache->dbgReusedString++;
pcercuei 0:03b5121a232e 1824 break;
pcercuei 0:03b5121a232e 1825 case XPATH_POINT:
pcercuei 0:03b5121a232e 1826 cache->dbgReusedPoint++;
pcercuei 0:03b5121a232e 1827 break;
pcercuei 0:03b5121a232e 1828 case XPATH_RANGE:
pcercuei 0:03b5121a232e 1829 cache->dbgReusedRange++;
pcercuei 0:03b5121a232e 1830 break;
pcercuei 0:03b5121a232e 1831 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 1832 cache->dbgReusedLocset++;
pcercuei 0:03b5121a232e 1833 break;
pcercuei 0:03b5121a232e 1834 case XPATH_USERS:
pcercuei 0:03b5121a232e 1835 cache->dbgReusedUsers++;
pcercuei 0:03b5121a232e 1836 break;
pcercuei 0:03b5121a232e 1837 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 1838 cache->dbgReusedXSLTTree++;
pcercuei 0:03b5121a232e 1839 break;
pcercuei 0:03b5121a232e 1840 default:
pcercuei 0:03b5121a232e 1841 break;
pcercuei 0:03b5121a232e 1842 }
pcercuei 0:03b5121a232e 1843 }
pcercuei 0:03b5121a232e 1844 }
pcercuei 0:03b5121a232e 1845
pcercuei 0:03b5121a232e 1846 switch (objType) {
pcercuei 0:03b5121a232e 1847 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 1848 if (! isCached)
pcercuei 0:03b5121a232e 1849 xmlXPathDebugObjTotalUndefined++;
pcercuei 0:03b5121a232e 1850 xmlXPathDebugObjCounterUndefined++;
pcercuei 0:03b5121a232e 1851 if (xmlXPathDebugObjCounterUndefined >
pcercuei 0:03b5121a232e 1852 xmlXPathDebugObjMaxUndefined)
pcercuei 0:03b5121a232e 1853 xmlXPathDebugObjMaxUndefined =
pcercuei 0:03b5121a232e 1854 xmlXPathDebugObjCounterUndefined;
pcercuei 0:03b5121a232e 1855 break;
pcercuei 0:03b5121a232e 1856 case XPATH_NODESET:
pcercuei 0:03b5121a232e 1857 if (! isCached)
pcercuei 0:03b5121a232e 1858 xmlXPathDebugObjTotalNodeset++;
pcercuei 0:03b5121a232e 1859 xmlXPathDebugObjCounterNodeset++;
pcercuei 0:03b5121a232e 1860 if (xmlXPathDebugObjCounterNodeset >
pcercuei 0:03b5121a232e 1861 xmlXPathDebugObjMaxNodeset)
pcercuei 0:03b5121a232e 1862 xmlXPathDebugObjMaxNodeset =
pcercuei 0:03b5121a232e 1863 xmlXPathDebugObjCounterNodeset;
pcercuei 0:03b5121a232e 1864 break;
pcercuei 0:03b5121a232e 1865 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 1866 if (! isCached)
pcercuei 0:03b5121a232e 1867 xmlXPathDebugObjTotalBool++;
pcercuei 0:03b5121a232e 1868 xmlXPathDebugObjCounterBool++;
pcercuei 0:03b5121a232e 1869 if (xmlXPathDebugObjCounterBool >
pcercuei 0:03b5121a232e 1870 xmlXPathDebugObjMaxBool)
pcercuei 0:03b5121a232e 1871 xmlXPathDebugObjMaxBool =
pcercuei 0:03b5121a232e 1872 xmlXPathDebugObjCounterBool;
pcercuei 0:03b5121a232e 1873 break;
pcercuei 0:03b5121a232e 1874 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 1875 if (! isCached)
pcercuei 0:03b5121a232e 1876 xmlXPathDebugObjTotalNumber++;
pcercuei 0:03b5121a232e 1877 xmlXPathDebugObjCounterNumber++;
pcercuei 0:03b5121a232e 1878 if (xmlXPathDebugObjCounterNumber >
pcercuei 0:03b5121a232e 1879 xmlXPathDebugObjMaxNumber)
pcercuei 0:03b5121a232e 1880 xmlXPathDebugObjMaxNumber =
pcercuei 0:03b5121a232e 1881 xmlXPathDebugObjCounterNumber;
pcercuei 0:03b5121a232e 1882 break;
pcercuei 0:03b5121a232e 1883 case XPATH_STRING:
pcercuei 0:03b5121a232e 1884 if (! isCached)
pcercuei 0:03b5121a232e 1885 xmlXPathDebugObjTotalString++;
pcercuei 0:03b5121a232e 1886 xmlXPathDebugObjCounterString++;
pcercuei 0:03b5121a232e 1887 if (xmlXPathDebugObjCounterString >
pcercuei 0:03b5121a232e 1888 xmlXPathDebugObjMaxString)
pcercuei 0:03b5121a232e 1889 xmlXPathDebugObjMaxString =
pcercuei 0:03b5121a232e 1890 xmlXPathDebugObjCounterString;
pcercuei 0:03b5121a232e 1891 break;
pcercuei 0:03b5121a232e 1892 case XPATH_POINT:
pcercuei 0:03b5121a232e 1893 if (! isCached)
pcercuei 0:03b5121a232e 1894 xmlXPathDebugObjTotalPoint++;
pcercuei 0:03b5121a232e 1895 xmlXPathDebugObjCounterPoint++;
pcercuei 0:03b5121a232e 1896 if (xmlXPathDebugObjCounterPoint >
pcercuei 0:03b5121a232e 1897 xmlXPathDebugObjMaxPoint)
pcercuei 0:03b5121a232e 1898 xmlXPathDebugObjMaxPoint =
pcercuei 0:03b5121a232e 1899 xmlXPathDebugObjCounterPoint;
pcercuei 0:03b5121a232e 1900 break;
pcercuei 0:03b5121a232e 1901 case XPATH_RANGE:
pcercuei 0:03b5121a232e 1902 if (! isCached)
pcercuei 0:03b5121a232e 1903 xmlXPathDebugObjTotalRange++;
pcercuei 0:03b5121a232e 1904 xmlXPathDebugObjCounterRange++;
pcercuei 0:03b5121a232e 1905 if (xmlXPathDebugObjCounterRange >
pcercuei 0:03b5121a232e 1906 xmlXPathDebugObjMaxRange)
pcercuei 0:03b5121a232e 1907 xmlXPathDebugObjMaxRange =
pcercuei 0:03b5121a232e 1908 xmlXPathDebugObjCounterRange;
pcercuei 0:03b5121a232e 1909 break;
pcercuei 0:03b5121a232e 1910 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 1911 if (! isCached)
pcercuei 0:03b5121a232e 1912 xmlXPathDebugObjTotalLocset++;
pcercuei 0:03b5121a232e 1913 xmlXPathDebugObjCounterLocset++;
pcercuei 0:03b5121a232e 1914 if (xmlXPathDebugObjCounterLocset >
pcercuei 0:03b5121a232e 1915 xmlXPathDebugObjMaxLocset)
pcercuei 0:03b5121a232e 1916 xmlXPathDebugObjMaxLocset =
pcercuei 0:03b5121a232e 1917 xmlXPathDebugObjCounterLocset;
pcercuei 0:03b5121a232e 1918 break;
pcercuei 0:03b5121a232e 1919 case XPATH_USERS:
pcercuei 0:03b5121a232e 1920 if (! isCached)
pcercuei 0:03b5121a232e 1921 xmlXPathDebugObjTotalUsers++;
pcercuei 0:03b5121a232e 1922 xmlXPathDebugObjCounterUsers++;
pcercuei 0:03b5121a232e 1923 if (xmlXPathDebugObjCounterUsers >
pcercuei 0:03b5121a232e 1924 xmlXPathDebugObjMaxUsers)
pcercuei 0:03b5121a232e 1925 xmlXPathDebugObjMaxUsers =
pcercuei 0:03b5121a232e 1926 xmlXPathDebugObjCounterUsers;
pcercuei 0:03b5121a232e 1927 break;
pcercuei 0:03b5121a232e 1928 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 1929 if (! isCached)
pcercuei 0:03b5121a232e 1930 xmlXPathDebugObjTotalXSLTTree++;
pcercuei 0:03b5121a232e 1931 xmlXPathDebugObjCounterXSLTTree++;
pcercuei 0:03b5121a232e 1932 if (xmlXPathDebugObjCounterXSLTTree >
pcercuei 0:03b5121a232e 1933 xmlXPathDebugObjMaxXSLTTree)
pcercuei 0:03b5121a232e 1934 xmlXPathDebugObjMaxXSLTTree =
pcercuei 0:03b5121a232e 1935 xmlXPathDebugObjCounterXSLTTree;
pcercuei 0:03b5121a232e 1936 break;
pcercuei 0:03b5121a232e 1937 default:
pcercuei 0:03b5121a232e 1938 break;
pcercuei 0:03b5121a232e 1939 }
pcercuei 0:03b5121a232e 1940 if (! isCached)
pcercuei 0:03b5121a232e 1941 xmlXPathDebugObjTotalAll++;
pcercuei 0:03b5121a232e 1942 xmlXPathDebugObjCounterAll++;
pcercuei 0:03b5121a232e 1943 if (xmlXPathDebugObjCounterAll >
pcercuei 0:03b5121a232e 1944 xmlXPathDebugObjMaxAll)
pcercuei 0:03b5121a232e 1945 xmlXPathDebugObjMaxAll =
pcercuei 0:03b5121a232e 1946 xmlXPathDebugObjCounterAll;
pcercuei 0:03b5121a232e 1947 }
pcercuei 0:03b5121a232e 1948
pcercuei 0:03b5121a232e 1949 static void
pcercuei 0:03b5121a232e 1950 xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt,
pcercuei 0:03b5121a232e 1951 xmlXPathObjectType objType)
pcercuei 0:03b5121a232e 1952 {
pcercuei 0:03b5121a232e 1953 int isCached = 0;
pcercuei 0:03b5121a232e 1954
pcercuei 0:03b5121a232e 1955 if (ctxt != NULL) {
pcercuei 0:03b5121a232e 1956 if (ctxt->cache != NULL) {
pcercuei 0:03b5121a232e 1957 xmlXPathContextCachePtr cache =
pcercuei 0:03b5121a232e 1958 (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 1959
pcercuei 0:03b5121a232e 1960 isCached = 1;
pcercuei 0:03b5121a232e 1961
pcercuei 0:03b5121a232e 1962 cache->dbgCachedAll++;
pcercuei 0:03b5121a232e 1963 switch (objType) {
pcercuei 0:03b5121a232e 1964 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 1965 cache->dbgCachedUndefined++;
pcercuei 0:03b5121a232e 1966 break;
pcercuei 0:03b5121a232e 1967 case XPATH_NODESET:
pcercuei 0:03b5121a232e 1968 cache->dbgCachedNodeset++;
pcercuei 0:03b5121a232e 1969 break;
pcercuei 0:03b5121a232e 1970 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 1971 cache->dbgCachedBool++;
pcercuei 0:03b5121a232e 1972 break;
pcercuei 0:03b5121a232e 1973 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 1974 cache->dbgCachedNumber++;
pcercuei 0:03b5121a232e 1975 break;
pcercuei 0:03b5121a232e 1976 case XPATH_STRING:
pcercuei 0:03b5121a232e 1977 cache->dbgCachedString++;
pcercuei 0:03b5121a232e 1978 break;
pcercuei 0:03b5121a232e 1979 case XPATH_POINT:
pcercuei 0:03b5121a232e 1980 cache->dbgCachedPoint++;
pcercuei 0:03b5121a232e 1981 break;
pcercuei 0:03b5121a232e 1982 case XPATH_RANGE:
pcercuei 0:03b5121a232e 1983 cache->dbgCachedRange++;
pcercuei 0:03b5121a232e 1984 break;
pcercuei 0:03b5121a232e 1985 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 1986 cache->dbgCachedLocset++;
pcercuei 0:03b5121a232e 1987 break;
pcercuei 0:03b5121a232e 1988 case XPATH_USERS:
pcercuei 0:03b5121a232e 1989 cache->dbgCachedUsers++;
pcercuei 0:03b5121a232e 1990 break;
pcercuei 0:03b5121a232e 1991 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 1992 cache->dbgCachedXSLTTree++;
pcercuei 0:03b5121a232e 1993 break;
pcercuei 0:03b5121a232e 1994 default:
pcercuei 0:03b5121a232e 1995 break;
pcercuei 0:03b5121a232e 1996 }
pcercuei 0:03b5121a232e 1997
pcercuei 0:03b5121a232e 1998 }
pcercuei 0:03b5121a232e 1999 }
pcercuei 0:03b5121a232e 2000 switch (objType) {
pcercuei 0:03b5121a232e 2001 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 2002 xmlXPathDebugObjCounterUndefined--;
pcercuei 0:03b5121a232e 2003 break;
pcercuei 0:03b5121a232e 2004 case XPATH_NODESET:
pcercuei 0:03b5121a232e 2005 xmlXPathDebugObjCounterNodeset--;
pcercuei 0:03b5121a232e 2006 break;
pcercuei 0:03b5121a232e 2007 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 2008 xmlXPathDebugObjCounterBool--;
pcercuei 0:03b5121a232e 2009 break;
pcercuei 0:03b5121a232e 2010 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 2011 xmlXPathDebugObjCounterNumber--;
pcercuei 0:03b5121a232e 2012 break;
pcercuei 0:03b5121a232e 2013 case XPATH_STRING:
pcercuei 0:03b5121a232e 2014 xmlXPathDebugObjCounterString--;
pcercuei 0:03b5121a232e 2015 break;
pcercuei 0:03b5121a232e 2016 case XPATH_POINT:
pcercuei 0:03b5121a232e 2017 xmlXPathDebugObjCounterPoint--;
pcercuei 0:03b5121a232e 2018 break;
pcercuei 0:03b5121a232e 2019 case XPATH_RANGE:
pcercuei 0:03b5121a232e 2020 xmlXPathDebugObjCounterRange--;
pcercuei 0:03b5121a232e 2021 break;
pcercuei 0:03b5121a232e 2022 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 2023 xmlXPathDebugObjCounterLocset--;
pcercuei 0:03b5121a232e 2024 break;
pcercuei 0:03b5121a232e 2025 case XPATH_USERS:
pcercuei 0:03b5121a232e 2026 xmlXPathDebugObjCounterUsers--;
pcercuei 0:03b5121a232e 2027 break;
pcercuei 0:03b5121a232e 2028 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 2029 xmlXPathDebugObjCounterXSLTTree--;
pcercuei 0:03b5121a232e 2030 break;
pcercuei 0:03b5121a232e 2031 default:
pcercuei 0:03b5121a232e 2032 break;
pcercuei 0:03b5121a232e 2033 }
pcercuei 0:03b5121a232e 2034 xmlXPathDebugObjCounterAll--;
pcercuei 0:03b5121a232e 2035 }
pcercuei 0:03b5121a232e 2036
pcercuei 0:03b5121a232e 2037 /* REVISIT TODO: Make this static when committing */
pcercuei 0:03b5121a232e 2038 static void
pcercuei 0:03b5121a232e 2039 xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt)
pcercuei 0:03b5121a232e 2040 {
pcercuei 0:03b5121a232e 2041 int reqAll, reqNodeset, reqString, reqBool, reqNumber,
pcercuei 0:03b5121a232e 2042 reqXSLTTree, reqUndefined;
pcercuei 0:03b5121a232e 2043 int caAll = 0, caNodeset = 0, caString = 0, caBool = 0,
pcercuei 0:03b5121a232e 2044 caNumber = 0, caXSLTTree = 0, caUndefined = 0;
pcercuei 0:03b5121a232e 2045 int reAll = 0, reNodeset = 0, reString = 0, reBool = 0,
pcercuei 0:03b5121a232e 2046 reNumber = 0, reXSLTTree = 0, reUndefined = 0;
pcercuei 0:03b5121a232e 2047 int leftObjs = xmlXPathDebugObjCounterAll;
pcercuei 0:03b5121a232e 2048
pcercuei 0:03b5121a232e 2049 reqAll = xmlXPathDebugObjTotalAll;
pcercuei 0:03b5121a232e 2050 reqNodeset = xmlXPathDebugObjTotalNodeset;
pcercuei 0:03b5121a232e 2051 reqString = xmlXPathDebugObjTotalString;
pcercuei 0:03b5121a232e 2052 reqBool = xmlXPathDebugObjTotalBool;
pcercuei 0:03b5121a232e 2053 reqNumber = xmlXPathDebugObjTotalNumber;
pcercuei 0:03b5121a232e 2054 reqXSLTTree = xmlXPathDebugObjTotalXSLTTree;
pcercuei 0:03b5121a232e 2055 reqUndefined = xmlXPathDebugObjTotalUndefined;
pcercuei 0:03b5121a232e 2056
pcercuei 0:03b5121a232e 2057 printf("# XPath object usage:\n");
pcercuei 0:03b5121a232e 2058
pcercuei 0:03b5121a232e 2059 if (ctxt != NULL) {
pcercuei 0:03b5121a232e 2060 if (ctxt->cache != NULL) {
pcercuei 0:03b5121a232e 2061 xmlXPathContextCachePtr cache =
pcercuei 0:03b5121a232e 2062 (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2063
pcercuei 0:03b5121a232e 2064 reAll = cache->dbgReusedAll;
pcercuei 0:03b5121a232e 2065 reqAll += reAll;
pcercuei 0:03b5121a232e 2066 reNodeset = cache->dbgReusedNodeset;
pcercuei 0:03b5121a232e 2067 reqNodeset += reNodeset;
pcercuei 0:03b5121a232e 2068 reString = cache->dbgReusedString;
pcercuei 0:03b5121a232e 2069 reqString += reString;
pcercuei 0:03b5121a232e 2070 reBool = cache->dbgReusedBool;
pcercuei 0:03b5121a232e 2071 reqBool += reBool;
pcercuei 0:03b5121a232e 2072 reNumber = cache->dbgReusedNumber;
pcercuei 0:03b5121a232e 2073 reqNumber += reNumber;
pcercuei 0:03b5121a232e 2074 reXSLTTree = cache->dbgReusedXSLTTree;
pcercuei 0:03b5121a232e 2075 reqXSLTTree += reXSLTTree;
pcercuei 0:03b5121a232e 2076 reUndefined = cache->dbgReusedUndefined;
pcercuei 0:03b5121a232e 2077 reqUndefined += reUndefined;
pcercuei 0:03b5121a232e 2078
pcercuei 0:03b5121a232e 2079 caAll = cache->dbgCachedAll;
pcercuei 0:03b5121a232e 2080 caBool = cache->dbgCachedBool;
pcercuei 0:03b5121a232e 2081 caNodeset = cache->dbgCachedNodeset;
pcercuei 0:03b5121a232e 2082 caString = cache->dbgCachedString;
pcercuei 0:03b5121a232e 2083 caNumber = cache->dbgCachedNumber;
pcercuei 0:03b5121a232e 2084 caXSLTTree = cache->dbgCachedXSLTTree;
pcercuei 0:03b5121a232e 2085 caUndefined = cache->dbgCachedUndefined;
pcercuei 0:03b5121a232e 2086
pcercuei 0:03b5121a232e 2087 if (cache->nodesetObjs)
pcercuei 0:03b5121a232e 2088 leftObjs -= cache->nodesetObjs->number;
pcercuei 0:03b5121a232e 2089 if (cache->stringObjs)
pcercuei 0:03b5121a232e 2090 leftObjs -= cache->stringObjs->number;
pcercuei 0:03b5121a232e 2091 if (cache->booleanObjs)
pcercuei 0:03b5121a232e 2092 leftObjs -= cache->booleanObjs->number;
pcercuei 0:03b5121a232e 2093 if (cache->numberObjs)
pcercuei 0:03b5121a232e 2094 leftObjs -= cache->numberObjs->number;
pcercuei 0:03b5121a232e 2095 if (cache->miscObjs)
pcercuei 0:03b5121a232e 2096 leftObjs -= cache->miscObjs->number;
pcercuei 0:03b5121a232e 2097 }
pcercuei 0:03b5121a232e 2098 }
pcercuei 0:03b5121a232e 2099
pcercuei 0:03b5121a232e 2100 printf("# all\n");
pcercuei 0:03b5121a232e 2101 printf("# total : %d\n", reqAll);
pcercuei 0:03b5121a232e 2102 printf("# left : %d\n", leftObjs);
pcercuei 0:03b5121a232e 2103 printf("# created: %d\n", xmlXPathDebugObjTotalAll);
pcercuei 0:03b5121a232e 2104 printf("# reused : %d\n", reAll);
pcercuei 0:03b5121a232e 2105 printf("# max : %d\n", xmlXPathDebugObjMaxAll);
pcercuei 0:03b5121a232e 2106
pcercuei 0:03b5121a232e 2107 printf("# node-sets\n");
pcercuei 0:03b5121a232e 2108 printf("# total : %d\n", reqNodeset);
pcercuei 0:03b5121a232e 2109 printf("# created: %d\n", xmlXPathDebugObjTotalNodeset);
pcercuei 0:03b5121a232e 2110 printf("# reused : %d\n", reNodeset);
pcercuei 0:03b5121a232e 2111 printf("# max : %d\n", xmlXPathDebugObjMaxNodeset);
pcercuei 0:03b5121a232e 2112
pcercuei 0:03b5121a232e 2113 printf("# strings\n");
pcercuei 0:03b5121a232e 2114 printf("# total : %d\n", reqString);
pcercuei 0:03b5121a232e 2115 printf("# created: %d\n", xmlXPathDebugObjTotalString);
pcercuei 0:03b5121a232e 2116 printf("# reused : %d\n", reString);
pcercuei 0:03b5121a232e 2117 printf("# max : %d\n", xmlXPathDebugObjMaxString);
pcercuei 0:03b5121a232e 2118
pcercuei 0:03b5121a232e 2119 printf("# booleans\n");
pcercuei 0:03b5121a232e 2120 printf("# total : %d\n", reqBool);
pcercuei 0:03b5121a232e 2121 printf("# created: %d\n", xmlXPathDebugObjTotalBool);
pcercuei 0:03b5121a232e 2122 printf("# reused : %d\n", reBool);
pcercuei 0:03b5121a232e 2123 printf("# max : %d\n", xmlXPathDebugObjMaxBool);
pcercuei 0:03b5121a232e 2124
pcercuei 0:03b5121a232e 2125 printf("# numbers\n");
pcercuei 0:03b5121a232e 2126 printf("# total : %d\n", reqNumber);
pcercuei 0:03b5121a232e 2127 printf("# created: %d\n", xmlXPathDebugObjTotalNumber);
pcercuei 0:03b5121a232e 2128 printf("# reused : %d\n", reNumber);
pcercuei 0:03b5121a232e 2129 printf("# max : %d\n", xmlXPathDebugObjMaxNumber);
pcercuei 0:03b5121a232e 2130
pcercuei 0:03b5121a232e 2131 printf("# XSLT result tree fragments\n");
pcercuei 0:03b5121a232e 2132 printf("# total : %d\n", reqXSLTTree);
pcercuei 0:03b5121a232e 2133 printf("# created: %d\n", xmlXPathDebugObjTotalXSLTTree);
pcercuei 0:03b5121a232e 2134 printf("# reused : %d\n", reXSLTTree);
pcercuei 0:03b5121a232e 2135 printf("# max : %d\n", xmlXPathDebugObjMaxXSLTTree);
pcercuei 0:03b5121a232e 2136
pcercuei 0:03b5121a232e 2137 printf("# undefined\n");
pcercuei 0:03b5121a232e 2138 printf("# total : %d\n", reqUndefined);
pcercuei 0:03b5121a232e 2139 printf("# created: %d\n", xmlXPathDebugObjTotalUndefined);
pcercuei 0:03b5121a232e 2140 printf("# reused : %d\n", reUndefined);
pcercuei 0:03b5121a232e 2141 printf("# max : %d\n", xmlXPathDebugObjMaxUndefined);
pcercuei 0:03b5121a232e 2142
pcercuei 0:03b5121a232e 2143 }
pcercuei 0:03b5121a232e 2144
pcercuei 0:03b5121a232e 2145 #endif /* XP_DEBUG_OBJ_USAGE */
pcercuei 0:03b5121a232e 2146
pcercuei 0:03b5121a232e 2147 #endif /* LIBXML_DEBUG_ENABLED */
pcercuei 0:03b5121a232e 2148
pcercuei 0:03b5121a232e 2149 /************************************************************************
pcercuei 0:03b5121a232e 2150 * *
pcercuei 0:03b5121a232e 2151 * XPath object caching *
pcercuei 0:03b5121a232e 2152 * *
pcercuei 0:03b5121a232e 2153 ************************************************************************/
pcercuei 0:03b5121a232e 2154
pcercuei 0:03b5121a232e 2155 /**
pcercuei 0:03b5121a232e 2156 * xmlXPathNewCache:
pcercuei 0:03b5121a232e 2157 *
pcercuei 0:03b5121a232e 2158 * Create a new object cache
pcercuei 0:03b5121a232e 2159 *
pcercuei 0:03b5121a232e 2160 * Returns the xmlXPathCache just allocated.
pcercuei 0:03b5121a232e 2161 */
pcercuei 0:03b5121a232e 2162 static xmlXPathContextCachePtr
pcercuei 0:03b5121a232e 2163 xmlXPathNewCache(void)
pcercuei 0:03b5121a232e 2164 {
pcercuei 0:03b5121a232e 2165 xmlXPathContextCachePtr ret;
pcercuei 0:03b5121a232e 2166
pcercuei 0:03b5121a232e 2167 ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache));
pcercuei 0:03b5121a232e 2168 if (ret == NULL) {
pcercuei 0:03b5121a232e 2169 xmlXPathErrMemory(NULL, "creating object cache\n");
pcercuei 0:03b5121a232e 2170 return(NULL);
pcercuei 0:03b5121a232e 2171 }
pcercuei 0:03b5121a232e 2172 memset(ret, 0 , (size_t) sizeof(xmlXPathContextCache));
pcercuei 0:03b5121a232e 2173 ret->maxNodeset = 100;
pcercuei 0:03b5121a232e 2174 ret->maxString = 100;
pcercuei 0:03b5121a232e 2175 ret->maxBoolean = 100;
pcercuei 0:03b5121a232e 2176 ret->maxNumber = 100;
pcercuei 0:03b5121a232e 2177 ret->maxMisc = 100;
pcercuei 0:03b5121a232e 2178 return(ret);
pcercuei 0:03b5121a232e 2179 }
pcercuei 0:03b5121a232e 2180
pcercuei 0:03b5121a232e 2181 static void
pcercuei 0:03b5121a232e 2182 xmlXPathCacheFreeObjectList(xmlPointerListPtr list)
pcercuei 0:03b5121a232e 2183 {
pcercuei 0:03b5121a232e 2184 int i;
pcercuei 0:03b5121a232e 2185 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 2186
pcercuei 0:03b5121a232e 2187 if (list == NULL)
pcercuei 0:03b5121a232e 2188 return;
pcercuei 0:03b5121a232e 2189
pcercuei 0:03b5121a232e 2190 for (i = 0; i < list->number; i++) {
pcercuei 0:03b5121a232e 2191 obj = list->items[i];
pcercuei 0:03b5121a232e 2192 /*
pcercuei 0:03b5121a232e 2193 * Note that it is already assured that we don't need to
pcercuei 0:03b5121a232e 2194 * look out for namespace nodes in the node-set.
pcercuei 0:03b5121a232e 2195 */
pcercuei 0:03b5121a232e 2196 if (obj->nodesetval != NULL) {
pcercuei 0:03b5121a232e 2197 if (obj->nodesetval->nodeTab != NULL)
pcercuei 0:03b5121a232e 2198 xmlFree(obj->nodesetval->nodeTab);
pcercuei 0:03b5121a232e 2199 xmlFree(obj->nodesetval);
pcercuei 0:03b5121a232e 2200 }
pcercuei 0:03b5121a232e 2201 xmlFree(obj);
pcercuei 0:03b5121a232e 2202 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2203 xmlXPathDebugObjCounterAll--;
pcercuei 0:03b5121a232e 2204 #endif
pcercuei 0:03b5121a232e 2205 }
pcercuei 0:03b5121a232e 2206 xmlPointerListFree(list);
pcercuei 0:03b5121a232e 2207 }
pcercuei 0:03b5121a232e 2208
pcercuei 0:03b5121a232e 2209 static void
pcercuei 0:03b5121a232e 2210 xmlXPathFreeCache(xmlXPathContextCachePtr cache)
pcercuei 0:03b5121a232e 2211 {
pcercuei 0:03b5121a232e 2212 if (cache == NULL)
pcercuei 0:03b5121a232e 2213 return;
pcercuei 0:03b5121a232e 2214 if (cache->nodesetObjs)
pcercuei 0:03b5121a232e 2215 xmlXPathCacheFreeObjectList(cache->nodesetObjs);
pcercuei 0:03b5121a232e 2216 if (cache->stringObjs)
pcercuei 0:03b5121a232e 2217 xmlXPathCacheFreeObjectList(cache->stringObjs);
pcercuei 0:03b5121a232e 2218 if (cache->booleanObjs)
pcercuei 0:03b5121a232e 2219 xmlXPathCacheFreeObjectList(cache->booleanObjs);
pcercuei 0:03b5121a232e 2220 if (cache->numberObjs)
pcercuei 0:03b5121a232e 2221 xmlXPathCacheFreeObjectList(cache->numberObjs);
pcercuei 0:03b5121a232e 2222 if (cache->miscObjs)
pcercuei 0:03b5121a232e 2223 xmlXPathCacheFreeObjectList(cache->miscObjs);
pcercuei 0:03b5121a232e 2224 xmlFree(cache);
pcercuei 0:03b5121a232e 2225 }
pcercuei 0:03b5121a232e 2226
pcercuei 0:03b5121a232e 2227 /**
pcercuei 0:03b5121a232e 2228 * xmlXPathContextSetCache:
pcercuei 0:03b5121a232e 2229 *
pcercuei 0:03b5121a232e 2230 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2231 * @active: enables/disables (creates/frees) the cache
pcercuei 0:03b5121a232e 2232 * @value: a value with semantics dependant on @options
pcercuei 0:03b5121a232e 2233 * @options: options (currently only the value 0 is used)
pcercuei 0:03b5121a232e 2234 *
pcercuei 0:03b5121a232e 2235 * Creates/frees an object cache on the XPath context.
pcercuei 0:03b5121a232e 2236 * If activates XPath objects (xmlXPathObject) will be cached internally
pcercuei 0:03b5121a232e 2237 * to be reused.
pcercuei 0:03b5121a232e 2238 * @options:
pcercuei 0:03b5121a232e 2239 * 0: This will set the XPath object caching:
pcercuei 0:03b5121a232e 2240 * @value:
pcercuei 0:03b5121a232e 2241 * This will set the maximum number of XPath objects
pcercuei 0:03b5121a232e 2242 * to be cached per slot
pcercuei 0:03b5121a232e 2243 * There are 5 slots for: node-set, string, number, boolean, and
pcercuei 0:03b5121a232e 2244 * misc objects. Use <0 for the default number (100).
pcercuei 0:03b5121a232e 2245 * Other values for @options have currently no effect.
pcercuei 0:03b5121a232e 2246 *
pcercuei 0:03b5121a232e 2247 * Returns 0 if the setting succeeded, and -1 on API or internal errors.
pcercuei 0:03b5121a232e 2248 */
pcercuei 0:03b5121a232e 2249 int
pcercuei 0:03b5121a232e 2250 xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
pcercuei 0:03b5121a232e 2251 int active,
pcercuei 0:03b5121a232e 2252 int value,
pcercuei 0:03b5121a232e 2253 int options)
pcercuei 0:03b5121a232e 2254 {
pcercuei 0:03b5121a232e 2255 if (ctxt == NULL)
pcercuei 0:03b5121a232e 2256 return(-1);
pcercuei 0:03b5121a232e 2257 if (active) {
pcercuei 0:03b5121a232e 2258 xmlXPathContextCachePtr cache;
pcercuei 0:03b5121a232e 2259
pcercuei 0:03b5121a232e 2260 if (ctxt->cache == NULL) {
pcercuei 0:03b5121a232e 2261 ctxt->cache = xmlXPathNewCache();
pcercuei 0:03b5121a232e 2262 if (ctxt->cache == NULL)
pcercuei 0:03b5121a232e 2263 return(-1);
pcercuei 0:03b5121a232e 2264 }
pcercuei 0:03b5121a232e 2265 cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2266 if (options == 0) {
pcercuei 0:03b5121a232e 2267 if (value < 0)
pcercuei 0:03b5121a232e 2268 value = 100;
pcercuei 0:03b5121a232e 2269 cache->maxNodeset = value;
pcercuei 0:03b5121a232e 2270 cache->maxString = value;
pcercuei 0:03b5121a232e 2271 cache->maxNumber = value;
pcercuei 0:03b5121a232e 2272 cache->maxBoolean = value;
pcercuei 0:03b5121a232e 2273 cache->maxMisc = value;
pcercuei 0:03b5121a232e 2274 }
pcercuei 0:03b5121a232e 2275 } else if (ctxt->cache != NULL) {
pcercuei 0:03b5121a232e 2276 xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
pcercuei 0:03b5121a232e 2277 ctxt->cache = NULL;
pcercuei 0:03b5121a232e 2278 }
pcercuei 0:03b5121a232e 2279 return(0);
pcercuei 0:03b5121a232e 2280 }
pcercuei 0:03b5121a232e 2281
pcercuei 0:03b5121a232e 2282 /**
pcercuei 0:03b5121a232e 2283 * xmlXPathCacheWrapNodeSet:
pcercuei 0:03b5121a232e 2284 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2285 * @val: the NodePtr value
pcercuei 0:03b5121a232e 2286 *
pcercuei 0:03b5121a232e 2287 * This is the cached version of xmlXPathWrapNodeSet().
pcercuei 0:03b5121a232e 2288 * Wrap the Nodeset @val in a new xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2289 *
pcercuei 0:03b5121a232e 2290 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2291 */
pcercuei 0:03b5121a232e 2292 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2293 xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val)
pcercuei 0:03b5121a232e 2294 {
pcercuei 0:03b5121a232e 2295 if ((ctxt != NULL) && (ctxt->cache != NULL)) {
pcercuei 0:03b5121a232e 2296 xmlXPathContextCachePtr cache =
pcercuei 0:03b5121a232e 2297 (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2298
pcercuei 0:03b5121a232e 2299 if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2300 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2301 {
pcercuei 0:03b5121a232e 2302 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2303
pcercuei 0:03b5121a232e 2304 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2305 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2306 ret->type = XPATH_NODESET;
pcercuei 0:03b5121a232e 2307 ret->nodesetval = val;
pcercuei 0:03b5121a232e 2308 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2309 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
pcercuei 0:03b5121a232e 2310 #endif
pcercuei 0:03b5121a232e 2311 return(ret);
pcercuei 0:03b5121a232e 2312 }
pcercuei 0:03b5121a232e 2313 }
pcercuei 0:03b5121a232e 2314
pcercuei 0:03b5121a232e 2315 return(xmlXPathWrapNodeSet(val));
pcercuei 0:03b5121a232e 2316
pcercuei 0:03b5121a232e 2317 }
pcercuei 0:03b5121a232e 2318
pcercuei 0:03b5121a232e 2319 /**
pcercuei 0:03b5121a232e 2320 * xmlXPathCacheWrapString:
pcercuei 0:03b5121a232e 2321 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2322 * @val: the xmlChar * value
pcercuei 0:03b5121a232e 2323 *
pcercuei 0:03b5121a232e 2324 * This is the cached version of xmlXPathWrapString().
pcercuei 0:03b5121a232e 2325 * Wraps the @val string into an XPath object.
pcercuei 0:03b5121a232e 2326 *
pcercuei 0:03b5121a232e 2327 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2328 */
pcercuei 0:03b5121a232e 2329 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2330 xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val)
pcercuei 0:03b5121a232e 2331 {
pcercuei 0:03b5121a232e 2332 if ((ctxt != NULL) && (ctxt->cache != NULL)) {
pcercuei 0:03b5121a232e 2333 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2334
pcercuei 0:03b5121a232e 2335 if ((cache->stringObjs != NULL) &&
pcercuei 0:03b5121a232e 2336 (cache->stringObjs->number != 0))
pcercuei 0:03b5121a232e 2337 {
pcercuei 0:03b5121a232e 2338
pcercuei 0:03b5121a232e 2339 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2340
pcercuei 0:03b5121a232e 2341 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2342 cache->stringObjs->items[--cache->stringObjs->number];
pcercuei 0:03b5121a232e 2343 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 2344 ret->stringval = val;
pcercuei 0:03b5121a232e 2345 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2346 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
pcercuei 0:03b5121a232e 2347 #endif
pcercuei 0:03b5121a232e 2348 return(ret);
pcercuei 0:03b5121a232e 2349 } else if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2350 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2351 {
pcercuei 0:03b5121a232e 2352 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2353 /*
pcercuei 0:03b5121a232e 2354 * Fallback to misc-cache.
pcercuei 0:03b5121a232e 2355 */
pcercuei 0:03b5121a232e 2356 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2357 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2358
pcercuei 0:03b5121a232e 2359 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 2360 ret->stringval = val;
pcercuei 0:03b5121a232e 2361 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2362 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
pcercuei 0:03b5121a232e 2363 #endif
pcercuei 0:03b5121a232e 2364 return(ret);
pcercuei 0:03b5121a232e 2365 }
pcercuei 0:03b5121a232e 2366 }
pcercuei 0:03b5121a232e 2367 return(xmlXPathWrapString(val));
pcercuei 0:03b5121a232e 2368 }
pcercuei 0:03b5121a232e 2369
pcercuei 0:03b5121a232e 2370 /**
pcercuei 0:03b5121a232e 2371 * xmlXPathCacheNewNodeSet:
pcercuei 0:03b5121a232e 2372 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2373 * @val: the NodePtr value
pcercuei 0:03b5121a232e 2374 *
pcercuei 0:03b5121a232e 2375 * This is the cached version of xmlXPathNewNodeSet().
pcercuei 0:03b5121a232e 2376 * Acquire an xmlXPathObjectPtr of type NodeSet and initialize
pcercuei 0:03b5121a232e 2377 * it with the single Node @val
pcercuei 0:03b5121a232e 2378 *
pcercuei 0:03b5121a232e 2379 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2380 */
pcercuei 0:03b5121a232e 2381 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2382 xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val)
pcercuei 0:03b5121a232e 2383 {
pcercuei 0:03b5121a232e 2384 if ((ctxt != NULL) && (ctxt->cache)) {
pcercuei 0:03b5121a232e 2385 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2386
pcercuei 0:03b5121a232e 2387 if ((cache->nodesetObjs != NULL) &&
pcercuei 0:03b5121a232e 2388 (cache->nodesetObjs->number != 0))
pcercuei 0:03b5121a232e 2389 {
pcercuei 0:03b5121a232e 2390 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2391 /*
pcercuei 0:03b5121a232e 2392 * Use the nodset-cache.
pcercuei 0:03b5121a232e 2393 */
pcercuei 0:03b5121a232e 2394 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2395 cache->nodesetObjs->items[--cache->nodesetObjs->number];
pcercuei 0:03b5121a232e 2396 ret->type = XPATH_NODESET;
pcercuei 0:03b5121a232e 2397 ret->boolval = 0;
pcercuei 0:03b5121a232e 2398 if (val) {
pcercuei 0:03b5121a232e 2399 if ((ret->nodesetval->nodeMax == 0) ||
pcercuei 0:03b5121a232e 2400 (val->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 2401 {
pcercuei 0:03b5121a232e 2402 xmlXPathNodeSetAddUnique(ret->nodesetval, val);
pcercuei 0:03b5121a232e 2403 } else {
pcercuei 0:03b5121a232e 2404 ret->nodesetval->nodeTab[0] = val;
pcercuei 0:03b5121a232e 2405 ret->nodesetval->nodeNr = 1;
pcercuei 0:03b5121a232e 2406 }
pcercuei 0:03b5121a232e 2407 }
pcercuei 0:03b5121a232e 2408 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2409 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
pcercuei 0:03b5121a232e 2410 #endif
pcercuei 0:03b5121a232e 2411 return(ret);
pcercuei 0:03b5121a232e 2412 } else if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2413 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2414 {
pcercuei 0:03b5121a232e 2415 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2416 /*
pcercuei 0:03b5121a232e 2417 * Fallback to misc-cache.
pcercuei 0:03b5121a232e 2418 */
pcercuei 0:03b5121a232e 2419
pcercuei 0:03b5121a232e 2420 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2421 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2422
pcercuei 0:03b5121a232e 2423 ret->type = XPATH_NODESET;
pcercuei 0:03b5121a232e 2424 ret->boolval = 0;
pcercuei 0:03b5121a232e 2425 ret->nodesetval = xmlXPathNodeSetCreate(val);
pcercuei 0:03b5121a232e 2426 if (ret->nodesetval == NULL) {
pcercuei 0:03b5121a232e 2427 ctxt->lastError.domain = XML_FROM_XPATH;
pcercuei 0:03b5121a232e 2428 ctxt->lastError.code = XML_ERR_NO_MEMORY;
pcercuei 0:03b5121a232e 2429 return(NULL);
pcercuei 0:03b5121a232e 2430 }
pcercuei 0:03b5121a232e 2431 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2432 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
pcercuei 0:03b5121a232e 2433 #endif
pcercuei 0:03b5121a232e 2434 return(ret);
pcercuei 0:03b5121a232e 2435 }
pcercuei 0:03b5121a232e 2436 }
pcercuei 0:03b5121a232e 2437 return(xmlXPathNewNodeSet(val));
pcercuei 0:03b5121a232e 2438 }
pcercuei 0:03b5121a232e 2439
pcercuei 0:03b5121a232e 2440 /**
pcercuei 0:03b5121a232e 2441 * xmlXPathCacheNewCString:
pcercuei 0:03b5121a232e 2442 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2443 * @val: the char * value
pcercuei 0:03b5121a232e 2444 *
pcercuei 0:03b5121a232e 2445 * This is the cached version of xmlXPathNewCString().
pcercuei 0:03b5121a232e 2446 * Acquire an xmlXPathObjectPtr of type string and of value @val
pcercuei 0:03b5121a232e 2447 *
pcercuei 0:03b5121a232e 2448 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2449 */
pcercuei 0:03b5121a232e 2450 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2451 xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val)
pcercuei 0:03b5121a232e 2452 {
pcercuei 0:03b5121a232e 2453 if ((ctxt != NULL) && (ctxt->cache)) {
pcercuei 0:03b5121a232e 2454 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2455
pcercuei 0:03b5121a232e 2456 if ((cache->stringObjs != NULL) &&
pcercuei 0:03b5121a232e 2457 (cache->stringObjs->number != 0))
pcercuei 0:03b5121a232e 2458 {
pcercuei 0:03b5121a232e 2459 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2460
pcercuei 0:03b5121a232e 2461 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2462 cache->stringObjs->items[--cache->stringObjs->number];
pcercuei 0:03b5121a232e 2463
pcercuei 0:03b5121a232e 2464 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 2465 ret->stringval = xmlStrdup(BAD_CAST val);
pcercuei 0:03b5121a232e 2466 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2467 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
pcercuei 0:03b5121a232e 2468 #endif
pcercuei 0:03b5121a232e 2469 return(ret);
pcercuei 0:03b5121a232e 2470 } else if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2471 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2472 {
pcercuei 0:03b5121a232e 2473 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2474
pcercuei 0:03b5121a232e 2475 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2476 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2477
pcercuei 0:03b5121a232e 2478 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 2479 ret->stringval = xmlStrdup(BAD_CAST val);
pcercuei 0:03b5121a232e 2480 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2481 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
pcercuei 0:03b5121a232e 2482 #endif
pcercuei 0:03b5121a232e 2483 return(ret);
pcercuei 0:03b5121a232e 2484 }
pcercuei 0:03b5121a232e 2485 }
pcercuei 0:03b5121a232e 2486 return(xmlXPathNewCString(val));
pcercuei 0:03b5121a232e 2487 }
pcercuei 0:03b5121a232e 2488
pcercuei 0:03b5121a232e 2489 /**
pcercuei 0:03b5121a232e 2490 * xmlXPathCacheNewString:
pcercuei 0:03b5121a232e 2491 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2492 * @val: the xmlChar * value
pcercuei 0:03b5121a232e 2493 *
pcercuei 0:03b5121a232e 2494 * This is the cached version of xmlXPathNewString().
pcercuei 0:03b5121a232e 2495 * Acquire an xmlXPathObjectPtr of type string and of value @val
pcercuei 0:03b5121a232e 2496 *
pcercuei 0:03b5121a232e 2497 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2498 */
pcercuei 0:03b5121a232e 2499 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2500 xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val)
pcercuei 0:03b5121a232e 2501 {
pcercuei 0:03b5121a232e 2502 if ((ctxt != NULL) && (ctxt->cache)) {
pcercuei 0:03b5121a232e 2503 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2504
pcercuei 0:03b5121a232e 2505 if ((cache->stringObjs != NULL) &&
pcercuei 0:03b5121a232e 2506 (cache->stringObjs->number != 0))
pcercuei 0:03b5121a232e 2507 {
pcercuei 0:03b5121a232e 2508 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2509
pcercuei 0:03b5121a232e 2510 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2511 cache->stringObjs->items[--cache->stringObjs->number];
pcercuei 0:03b5121a232e 2512 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 2513 if (val != NULL)
pcercuei 0:03b5121a232e 2514 ret->stringval = xmlStrdup(val);
pcercuei 0:03b5121a232e 2515 else
pcercuei 0:03b5121a232e 2516 ret->stringval = xmlStrdup((const xmlChar *)"");
pcercuei 0:03b5121a232e 2517 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2518 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
pcercuei 0:03b5121a232e 2519 #endif
pcercuei 0:03b5121a232e 2520 return(ret);
pcercuei 0:03b5121a232e 2521 } else if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2522 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2523 {
pcercuei 0:03b5121a232e 2524 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2525
pcercuei 0:03b5121a232e 2526 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2527 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2528
pcercuei 0:03b5121a232e 2529 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 2530 if (val != NULL)
pcercuei 0:03b5121a232e 2531 ret->stringval = xmlStrdup(val);
pcercuei 0:03b5121a232e 2532 else
pcercuei 0:03b5121a232e 2533 ret->stringval = xmlStrdup((const xmlChar *)"");
pcercuei 0:03b5121a232e 2534 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2535 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING);
pcercuei 0:03b5121a232e 2536 #endif
pcercuei 0:03b5121a232e 2537 return(ret);
pcercuei 0:03b5121a232e 2538 }
pcercuei 0:03b5121a232e 2539 }
pcercuei 0:03b5121a232e 2540 return(xmlXPathNewString(val));
pcercuei 0:03b5121a232e 2541 }
pcercuei 0:03b5121a232e 2542
pcercuei 0:03b5121a232e 2543 /**
pcercuei 0:03b5121a232e 2544 * xmlXPathCacheNewBoolean:
pcercuei 0:03b5121a232e 2545 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2546 * @val: the boolean value
pcercuei 0:03b5121a232e 2547 *
pcercuei 0:03b5121a232e 2548 * This is the cached version of xmlXPathNewBoolean().
pcercuei 0:03b5121a232e 2549 * Acquires an xmlXPathObjectPtr of type boolean and of value @val
pcercuei 0:03b5121a232e 2550 *
pcercuei 0:03b5121a232e 2551 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2552 */
pcercuei 0:03b5121a232e 2553 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2554 xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val)
pcercuei 0:03b5121a232e 2555 {
pcercuei 0:03b5121a232e 2556 if ((ctxt != NULL) && (ctxt->cache)) {
pcercuei 0:03b5121a232e 2557 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2558
pcercuei 0:03b5121a232e 2559 if ((cache->booleanObjs != NULL) &&
pcercuei 0:03b5121a232e 2560 (cache->booleanObjs->number != 0))
pcercuei 0:03b5121a232e 2561 {
pcercuei 0:03b5121a232e 2562 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2563
pcercuei 0:03b5121a232e 2564 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2565 cache->booleanObjs->items[--cache->booleanObjs->number];
pcercuei 0:03b5121a232e 2566 ret->type = XPATH_BOOLEAN;
pcercuei 0:03b5121a232e 2567 ret->boolval = (val != 0);
pcercuei 0:03b5121a232e 2568 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2569 xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN);
pcercuei 0:03b5121a232e 2570 #endif
pcercuei 0:03b5121a232e 2571 return(ret);
pcercuei 0:03b5121a232e 2572 } else if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2573 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2574 {
pcercuei 0:03b5121a232e 2575 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2576
pcercuei 0:03b5121a232e 2577 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2578 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2579
pcercuei 0:03b5121a232e 2580 ret->type = XPATH_BOOLEAN;
pcercuei 0:03b5121a232e 2581 ret->boolval = (val != 0);
pcercuei 0:03b5121a232e 2582 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2583 xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN);
pcercuei 0:03b5121a232e 2584 #endif
pcercuei 0:03b5121a232e 2585 return(ret);
pcercuei 0:03b5121a232e 2586 }
pcercuei 0:03b5121a232e 2587 }
pcercuei 0:03b5121a232e 2588 return(xmlXPathNewBoolean(val));
pcercuei 0:03b5121a232e 2589 }
pcercuei 0:03b5121a232e 2590
pcercuei 0:03b5121a232e 2591 /**
pcercuei 0:03b5121a232e 2592 * xmlXPathCacheNewFloat:
pcercuei 0:03b5121a232e 2593 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2594 * @val: the double value
pcercuei 0:03b5121a232e 2595 *
pcercuei 0:03b5121a232e 2596 * This is the cached version of xmlXPathNewFloat().
pcercuei 0:03b5121a232e 2597 * Acquires an xmlXPathObjectPtr of type double and of value @val
pcercuei 0:03b5121a232e 2598 *
pcercuei 0:03b5121a232e 2599 * Returns the created or reused object.
pcercuei 0:03b5121a232e 2600 */
pcercuei 0:03b5121a232e 2601 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2602 xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val)
pcercuei 0:03b5121a232e 2603 {
pcercuei 0:03b5121a232e 2604 if ((ctxt != NULL) && (ctxt->cache)) {
pcercuei 0:03b5121a232e 2605 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 2606
pcercuei 0:03b5121a232e 2607 if ((cache->numberObjs != NULL) &&
pcercuei 0:03b5121a232e 2608 (cache->numberObjs->number != 0))
pcercuei 0:03b5121a232e 2609 {
pcercuei 0:03b5121a232e 2610 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2611
pcercuei 0:03b5121a232e 2612 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2613 cache->numberObjs->items[--cache->numberObjs->number];
pcercuei 0:03b5121a232e 2614 ret->type = XPATH_NUMBER;
pcercuei 0:03b5121a232e 2615 ret->floatval = val;
pcercuei 0:03b5121a232e 2616 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2617 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER);
pcercuei 0:03b5121a232e 2618 #endif
pcercuei 0:03b5121a232e 2619 return(ret);
pcercuei 0:03b5121a232e 2620 } else if ((cache->miscObjs != NULL) &&
pcercuei 0:03b5121a232e 2621 (cache->miscObjs->number != 0))
pcercuei 0:03b5121a232e 2622 {
pcercuei 0:03b5121a232e 2623 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2624
pcercuei 0:03b5121a232e 2625 ret = (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 2626 cache->miscObjs->items[--cache->miscObjs->number];
pcercuei 0:03b5121a232e 2627
pcercuei 0:03b5121a232e 2628 ret->type = XPATH_NUMBER;
pcercuei 0:03b5121a232e 2629 ret->floatval = val;
pcercuei 0:03b5121a232e 2630 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 2631 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER);
pcercuei 0:03b5121a232e 2632 #endif
pcercuei 0:03b5121a232e 2633 return(ret);
pcercuei 0:03b5121a232e 2634 }
pcercuei 0:03b5121a232e 2635 }
pcercuei 0:03b5121a232e 2636 return(xmlXPathNewFloat(val));
pcercuei 0:03b5121a232e 2637 }
pcercuei 0:03b5121a232e 2638
pcercuei 0:03b5121a232e 2639 /**
pcercuei 0:03b5121a232e 2640 * xmlXPathCacheConvertString:
pcercuei 0:03b5121a232e 2641 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2642 * @val: an XPath object
pcercuei 0:03b5121a232e 2643 *
pcercuei 0:03b5121a232e 2644 * This is the cached version of xmlXPathConvertString().
pcercuei 0:03b5121a232e 2645 * Converts an existing object to its string() equivalent
pcercuei 0:03b5121a232e 2646 *
pcercuei 0:03b5121a232e 2647 * Returns a created or reused object, the old one is freed (cached)
pcercuei 0:03b5121a232e 2648 * (or the operation is done directly on @val)
pcercuei 0:03b5121a232e 2649 */
pcercuei 0:03b5121a232e 2650
pcercuei 0:03b5121a232e 2651 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2652 xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 2653 xmlChar *res = NULL;
pcercuei 0:03b5121a232e 2654
pcercuei 0:03b5121a232e 2655 if (val == NULL)
pcercuei 0:03b5121a232e 2656 return(xmlXPathCacheNewCString(ctxt, ""));
pcercuei 0:03b5121a232e 2657
pcercuei 0:03b5121a232e 2658 switch (val->type) {
pcercuei 0:03b5121a232e 2659 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 2660 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 2661 xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
pcercuei 0:03b5121a232e 2662 #endif
pcercuei 0:03b5121a232e 2663 break;
pcercuei 0:03b5121a232e 2664 case XPATH_NODESET:
pcercuei 0:03b5121a232e 2665 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 2666 res = xmlXPathCastNodeSetToString(val->nodesetval);
pcercuei 0:03b5121a232e 2667 break;
pcercuei 0:03b5121a232e 2668 case XPATH_STRING:
pcercuei 0:03b5121a232e 2669 return(val);
pcercuei 0:03b5121a232e 2670 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 2671 res = xmlXPathCastBooleanToString(val->boolval);
pcercuei 0:03b5121a232e 2672 break;
pcercuei 0:03b5121a232e 2673 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 2674 res = xmlXPathCastNumberToString(val->floatval);
pcercuei 0:03b5121a232e 2675 break;
pcercuei 0:03b5121a232e 2676 case XPATH_USERS:
pcercuei 0:03b5121a232e 2677 case XPATH_POINT:
pcercuei 0:03b5121a232e 2678 case XPATH_RANGE:
pcercuei 0:03b5121a232e 2679 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 2680 TODO;
pcercuei 0:03b5121a232e 2681 break;
pcercuei 0:03b5121a232e 2682 }
pcercuei 0:03b5121a232e 2683 xmlXPathReleaseObject(ctxt, val);
pcercuei 0:03b5121a232e 2684 if (res == NULL)
pcercuei 0:03b5121a232e 2685 return(xmlXPathCacheNewCString(ctxt, ""));
pcercuei 0:03b5121a232e 2686 return(xmlXPathCacheWrapString(ctxt, res));
pcercuei 0:03b5121a232e 2687 }
pcercuei 0:03b5121a232e 2688
pcercuei 0:03b5121a232e 2689 /**
pcercuei 0:03b5121a232e 2690 * xmlXPathCacheObjectCopy:
pcercuei 0:03b5121a232e 2691 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2692 * @val: the original object
pcercuei 0:03b5121a232e 2693 *
pcercuei 0:03b5121a232e 2694 * This is the cached version of xmlXPathObjectCopy().
pcercuei 0:03b5121a232e 2695 * Acquire a copy of a given object
pcercuei 0:03b5121a232e 2696 *
pcercuei 0:03b5121a232e 2697 * Returns a created or reused created object.
pcercuei 0:03b5121a232e 2698 */
pcercuei 0:03b5121a232e 2699 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2700 xmlXPathCacheObjectCopy(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val)
pcercuei 0:03b5121a232e 2701 {
pcercuei 0:03b5121a232e 2702 if (val == NULL)
pcercuei 0:03b5121a232e 2703 return(NULL);
pcercuei 0:03b5121a232e 2704
pcercuei 0:03b5121a232e 2705 if (XP_HAS_CACHE(ctxt)) {
pcercuei 0:03b5121a232e 2706 switch (val->type) {
pcercuei 0:03b5121a232e 2707 case XPATH_NODESET:
pcercuei 0:03b5121a232e 2708 return(xmlXPathCacheWrapNodeSet(ctxt,
pcercuei 0:03b5121a232e 2709 xmlXPathNodeSetMerge(NULL, val->nodesetval)));
pcercuei 0:03b5121a232e 2710 case XPATH_STRING:
pcercuei 0:03b5121a232e 2711 return(xmlXPathCacheNewString(ctxt, val->stringval));
pcercuei 0:03b5121a232e 2712 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 2713 return(xmlXPathCacheNewBoolean(ctxt, val->boolval));
pcercuei 0:03b5121a232e 2714 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 2715 return(xmlXPathCacheNewFloat(ctxt, val->floatval));
pcercuei 0:03b5121a232e 2716 default:
pcercuei 0:03b5121a232e 2717 break;
pcercuei 0:03b5121a232e 2718 }
pcercuei 0:03b5121a232e 2719 }
pcercuei 0:03b5121a232e 2720 return(xmlXPathObjectCopy(val));
pcercuei 0:03b5121a232e 2721 }
pcercuei 0:03b5121a232e 2722
pcercuei 0:03b5121a232e 2723 /**
pcercuei 0:03b5121a232e 2724 * xmlXPathCacheConvertBoolean:
pcercuei 0:03b5121a232e 2725 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2726 * @val: an XPath object
pcercuei 0:03b5121a232e 2727 *
pcercuei 0:03b5121a232e 2728 * This is the cached version of xmlXPathConvertBoolean().
pcercuei 0:03b5121a232e 2729 * Converts an existing object to its boolean() equivalent
pcercuei 0:03b5121a232e 2730 *
pcercuei 0:03b5121a232e 2731 * Returns a created or reused object, the old one is freed (or the operation
pcercuei 0:03b5121a232e 2732 * is done directly on @val)
pcercuei 0:03b5121a232e 2733 */
pcercuei 0:03b5121a232e 2734 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2735 xmlXPathCacheConvertBoolean(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 2736 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2737
pcercuei 0:03b5121a232e 2738 if (val == NULL)
pcercuei 0:03b5121a232e 2739 return(xmlXPathCacheNewBoolean(ctxt, 0));
pcercuei 0:03b5121a232e 2740 if (val->type == XPATH_BOOLEAN)
pcercuei 0:03b5121a232e 2741 return(val);
pcercuei 0:03b5121a232e 2742 ret = xmlXPathCacheNewBoolean(ctxt, xmlXPathCastToBoolean(val));
pcercuei 0:03b5121a232e 2743 xmlXPathReleaseObject(ctxt, val);
pcercuei 0:03b5121a232e 2744 return(ret);
pcercuei 0:03b5121a232e 2745 }
pcercuei 0:03b5121a232e 2746
pcercuei 0:03b5121a232e 2747 /**
pcercuei 0:03b5121a232e 2748 * xmlXPathCacheConvertNumber:
pcercuei 0:03b5121a232e 2749 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 2750 * @val: an XPath object
pcercuei 0:03b5121a232e 2751 *
pcercuei 0:03b5121a232e 2752 * This is the cached version of xmlXPathConvertNumber().
pcercuei 0:03b5121a232e 2753 * Converts an existing object to its number() equivalent
pcercuei 0:03b5121a232e 2754 *
pcercuei 0:03b5121a232e 2755 * Returns a created or reused object, the old one is freed (or the operation
pcercuei 0:03b5121a232e 2756 * is done directly on @val)
pcercuei 0:03b5121a232e 2757 */
pcercuei 0:03b5121a232e 2758 static xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2759 xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 2760 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2761
pcercuei 0:03b5121a232e 2762 if (val == NULL)
pcercuei 0:03b5121a232e 2763 return(xmlXPathCacheNewFloat(ctxt, 0.0));
pcercuei 0:03b5121a232e 2764 if (val->type == XPATH_NUMBER)
pcercuei 0:03b5121a232e 2765 return(val);
pcercuei 0:03b5121a232e 2766 ret = xmlXPathCacheNewFloat(ctxt, xmlXPathCastToNumber(val));
pcercuei 0:03b5121a232e 2767 xmlXPathReleaseObject(ctxt, val);
pcercuei 0:03b5121a232e 2768 return(ret);
pcercuei 0:03b5121a232e 2769 }
pcercuei 0:03b5121a232e 2770
pcercuei 0:03b5121a232e 2771 /************************************************************************
pcercuei 0:03b5121a232e 2772 * *
pcercuei 0:03b5121a232e 2773 * Parser stacks related functions and macros *
pcercuei 0:03b5121a232e 2774 * *
pcercuei 0:03b5121a232e 2775 ************************************************************************/
pcercuei 0:03b5121a232e 2776
pcercuei 0:03b5121a232e 2777 /**
pcercuei 0:03b5121a232e 2778 * xmlXPathSetFrame:
pcercuei 0:03b5121a232e 2779 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2780 *
pcercuei 0:03b5121a232e 2781 * Set the callee evaluation frame
pcercuei 0:03b5121a232e 2782 *
pcercuei 0:03b5121a232e 2783 * Returns the previous frame value to be restored once done
pcercuei 0:03b5121a232e 2784 */
pcercuei 0:03b5121a232e 2785 static int
pcercuei 0:03b5121a232e 2786 xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 2787 int ret;
pcercuei 0:03b5121a232e 2788
pcercuei 0:03b5121a232e 2789 if (ctxt == NULL)
pcercuei 0:03b5121a232e 2790 return(0);
pcercuei 0:03b5121a232e 2791 ret = ctxt->valueFrame;
pcercuei 0:03b5121a232e 2792 ctxt->valueFrame = ctxt->valueNr;
pcercuei 0:03b5121a232e 2793 return(ret);
pcercuei 0:03b5121a232e 2794 }
pcercuei 0:03b5121a232e 2795
pcercuei 0:03b5121a232e 2796 /**
pcercuei 0:03b5121a232e 2797 * xmlXPathPopFrame:
pcercuei 0:03b5121a232e 2798 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2799 * @frame: the previous frame value
pcercuei 0:03b5121a232e 2800 *
pcercuei 0:03b5121a232e 2801 * Remove the callee evaluation frame
pcercuei 0:03b5121a232e 2802 */
pcercuei 0:03b5121a232e 2803 static void
pcercuei 0:03b5121a232e 2804 xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
pcercuei 0:03b5121a232e 2805 if (ctxt == NULL)
pcercuei 0:03b5121a232e 2806 return;
pcercuei 0:03b5121a232e 2807 if (ctxt->valueNr < ctxt->valueFrame) {
pcercuei 0:03b5121a232e 2808 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
pcercuei 0:03b5121a232e 2809 }
pcercuei 0:03b5121a232e 2810 ctxt->valueFrame = frame;
pcercuei 0:03b5121a232e 2811 }
pcercuei 0:03b5121a232e 2812
pcercuei 0:03b5121a232e 2813 /**
pcercuei 0:03b5121a232e 2814 * valuePop:
pcercuei 0:03b5121a232e 2815 * @ctxt: an XPath evaluation context
pcercuei 0:03b5121a232e 2816 *
pcercuei 0:03b5121a232e 2817 * Pops the top XPath object from the value stack
pcercuei 0:03b5121a232e 2818 *
pcercuei 0:03b5121a232e 2819 * Returns the XPath object just removed
pcercuei 0:03b5121a232e 2820 */
pcercuei 0:03b5121a232e 2821 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 2822 valuePop(xmlXPathParserContextPtr ctxt)
pcercuei 0:03b5121a232e 2823 {
pcercuei 0:03b5121a232e 2824 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 2825
pcercuei 0:03b5121a232e 2826 if ((ctxt == NULL) || (ctxt->valueNr <= 0))
pcercuei 0:03b5121a232e 2827 return (NULL);
pcercuei 0:03b5121a232e 2828
pcercuei 0:03b5121a232e 2829 if (ctxt->valueNr <= ctxt->valueFrame) {
pcercuei 0:03b5121a232e 2830 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
pcercuei 0:03b5121a232e 2831 return (NULL);
pcercuei 0:03b5121a232e 2832 }
pcercuei 0:03b5121a232e 2833
pcercuei 0:03b5121a232e 2834 ctxt->valueNr--;
pcercuei 0:03b5121a232e 2835 if (ctxt->valueNr > 0)
pcercuei 0:03b5121a232e 2836 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
pcercuei 0:03b5121a232e 2837 else
pcercuei 0:03b5121a232e 2838 ctxt->value = NULL;
pcercuei 0:03b5121a232e 2839 ret = ctxt->valueTab[ctxt->valueNr];
pcercuei 0:03b5121a232e 2840 ctxt->valueTab[ctxt->valueNr] = NULL;
pcercuei 0:03b5121a232e 2841 return (ret);
pcercuei 0:03b5121a232e 2842 }
pcercuei 0:03b5121a232e 2843 /**
pcercuei 0:03b5121a232e 2844 * valuePush:
pcercuei 0:03b5121a232e 2845 * @ctxt: an XPath evaluation context
pcercuei 0:03b5121a232e 2846 * @value: the XPath object
pcercuei 0:03b5121a232e 2847 *
pcercuei 0:03b5121a232e 2848 * Pushes a new XPath object on top of the value stack
pcercuei 0:03b5121a232e 2849 *
pcercuei 0:03b5121a232e 2850 * returns the number of items on the value stack
pcercuei 0:03b5121a232e 2851 */
pcercuei 0:03b5121a232e 2852 int
pcercuei 0:03b5121a232e 2853 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
pcercuei 0:03b5121a232e 2854 {
pcercuei 0:03b5121a232e 2855 if ((ctxt == NULL) || (value == NULL)) return(-1);
pcercuei 0:03b5121a232e 2856 if (ctxt->valueNr >= ctxt->valueMax) {
pcercuei 0:03b5121a232e 2857 xmlXPathObjectPtr *tmp;
pcercuei 0:03b5121a232e 2858
pcercuei 0:03b5121a232e 2859 if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
pcercuei 0:03b5121a232e 2860 xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n");
pcercuei 0:03b5121a232e 2861 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 2862 return (0);
pcercuei 0:03b5121a232e 2863 }
pcercuei 0:03b5121a232e 2864 tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
pcercuei 0:03b5121a232e 2865 2 * ctxt->valueMax *
pcercuei 0:03b5121a232e 2866 sizeof(ctxt->valueTab[0]));
pcercuei 0:03b5121a232e 2867 if (tmp == NULL) {
pcercuei 0:03b5121a232e 2868 xmlXPathErrMemory(NULL, "pushing value\n");
pcercuei 0:03b5121a232e 2869 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 2870 return (0);
pcercuei 0:03b5121a232e 2871 }
pcercuei 0:03b5121a232e 2872 ctxt->valueMax *= 2;
pcercuei 0:03b5121a232e 2873 ctxt->valueTab = tmp;
pcercuei 0:03b5121a232e 2874 }
pcercuei 0:03b5121a232e 2875 ctxt->valueTab[ctxt->valueNr] = value;
pcercuei 0:03b5121a232e 2876 ctxt->value = value;
pcercuei 0:03b5121a232e 2877 return (ctxt->valueNr++);
pcercuei 0:03b5121a232e 2878 }
pcercuei 0:03b5121a232e 2879
pcercuei 0:03b5121a232e 2880 /**
pcercuei 0:03b5121a232e 2881 * xmlXPathPopBoolean:
pcercuei 0:03b5121a232e 2882 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2883 *
pcercuei 0:03b5121a232e 2884 * Pops a boolean from the stack, handling conversion if needed.
pcercuei 0:03b5121a232e 2885 * Check error with #xmlXPathCheckError.
pcercuei 0:03b5121a232e 2886 *
pcercuei 0:03b5121a232e 2887 * Returns the boolean
pcercuei 0:03b5121a232e 2888 */
pcercuei 0:03b5121a232e 2889 int
pcercuei 0:03b5121a232e 2890 xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 2891 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 2892 int ret;
pcercuei 0:03b5121a232e 2893
pcercuei 0:03b5121a232e 2894 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 2895 if (obj == NULL) {
pcercuei 0:03b5121a232e 2896 xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 2897 return(0);
pcercuei 0:03b5121a232e 2898 }
pcercuei 0:03b5121a232e 2899 if (obj->type != XPATH_BOOLEAN)
pcercuei 0:03b5121a232e 2900 ret = xmlXPathCastToBoolean(obj);
pcercuei 0:03b5121a232e 2901 else
pcercuei 0:03b5121a232e 2902 ret = obj->boolval;
pcercuei 0:03b5121a232e 2903 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 2904 return(ret);
pcercuei 0:03b5121a232e 2905 }
pcercuei 0:03b5121a232e 2906
pcercuei 0:03b5121a232e 2907 /**
pcercuei 0:03b5121a232e 2908 * xmlXPathPopNumber:
pcercuei 0:03b5121a232e 2909 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2910 *
pcercuei 0:03b5121a232e 2911 * Pops a number from the stack, handling conversion if needed.
pcercuei 0:03b5121a232e 2912 * Check error with #xmlXPathCheckError.
pcercuei 0:03b5121a232e 2913 *
pcercuei 0:03b5121a232e 2914 * Returns the number
pcercuei 0:03b5121a232e 2915 */
pcercuei 0:03b5121a232e 2916 double
pcercuei 0:03b5121a232e 2917 xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 2918 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 2919 double ret;
pcercuei 0:03b5121a232e 2920
pcercuei 0:03b5121a232e 2921 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 2922 if (obj == NULL) {
pcercuei 0:03b5121a232e 2923 xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 2924 return(0);
pcercuei 0:03b5121a232e 2925 }
pcercuei 0:03b5121a232e 2926 if (obj->type != XPATH_NUMBER)
pcercuei 0:03b5121a232e 2927 ret = xmlXPathCastToNumber(obj);
pcercuei 0:03b5121a232e 2928 else
pcercuei 0:03b5121a232e 2929 ret = obj->floatval;
pcercuei 0:03b5121a232e 2930 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 2931 return(ret);
pcercuei 0:03b5121a232e 2932 }
pcercuei 0:03b5121a232e 2933
pcercuei 0:03b5121a232e 2934 /**
pcercuei 0:03b5121a232e 2935 * xmlXPathPopString:
pcercuei 0:03b5121a232e 2936 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2937 *
pcercuei 0:03b5121a232e 2938 * Pops a string from the stack, handling conversion if needed.
pcercuei 0:03b5121a232e 2939 * Check error with #xmlXPathCheckError.
pcercuei 0:03b5121a232e 2940 *
pcercuei 0:03b5121a232e 2941 * Returns the string
pcercuei 0:03b5121a232e 2942 */
pcercuei 0:03b5121a232e 2943 xmlChar *
pcercuei 0:03b5121a232e 2944 xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 2945 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 2946 xmlChar * ret;
pcercuei 0:03b5121a232e 2947
pcercuei 0:03b5121a232e 2948 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 2949 if (obj == NULL) {
pcercuei 0:03b5121a232e 2950 xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 2951 return(NULL);
pcercuei 0:03b5121a232e 2952 }
pcercuei 0:03b5121a232e 2953 ret = xmlXPathCastToString(obj); /* this does required strdup */
pcercuei 0:03b5121a232e 2954 /* TODO: needs refactoring somewhere else */
pcercuei 0:03b5121a232e 2955 if (obj->stringval == ret)
pcercuei 0:03b5121a232e 2956 obj->stringval = NULL;
pcercuei 0:03b5121a232e 2957 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 2958 return(ret);
pcercuei 0:03b5121a232e 2959 }
pcercuei 0:03b5121a232e 2960
pcercuei 0:03b5121a232e 2961 /**
pcercuei 0:03b5121a232e 2962 * xmlXPathPopNodeSet:
pcercuei 0:03b5121a232e 2963 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2964 *
pcercuei 0:03b5121a232e 2965 * Pops a node-set from the stack, handling conversion if needed.
pcercuei 0:03b5121a232e 2966 * Check error with #xmlXPathCheckError.
pcercuei 0:03b5121a232e 2967 *
pcercuei 0:03b5121a232e 2968 * Returns the node-set
pcercuei 0:03b5121a232e 2969 */
pcercuei 0:03b5121a232e 2970 xmlNodeSetPtr
pcercuei 0:03b5121a232e 2971 xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 2972 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 2973 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 2974
pcercuei 0:03b5121a232e 2975 if (ctxt == NULL) return(NULL);
pcercuei 0:03b5121a232e 2976 if (ctxt->value == NULL) {
pcercuei 0:03b5121a232e 2977 xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 2978 return(NULL);
pcercuei 0:03b5121a232e 2979 }
pcercuei 0:03b5121a232e 2980 if (!xmlXPathStackIsNodeSet(ctxt)) {
pcercuei 0:03b5121a232e 2981 xmlXPathSetTypeError(ctxt);
pcercuei 0:03b5121a232e 2982 return(NULL);
pcercuei 0:03b5121a232e 2983 }
pcercuei 0:03b5121a232e 2984 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 2985 ret = obj->nodesetval;
pcercuei 0:03b5121a232e 2986 #if 0
pcercuei 0:03b5121a232e 2987 /* to fix memory leak of not clearing obj->user */
pcercuei 0:03b5121a232e 2988 if (obj->boolval && obj->user != NULL)
pcercuei 0:03b5121a232e 2989 xmlFreeNodeList((xmlNodePtr) obj->user);
pcercuei 0:03b5121a232e 2990 #endif
pcercuei 0:03b5121a232e 2991 obj->nodesetval = NULL;
pcercuei 0:03b5121a232e 2992 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 2993 return(ret);
pcercuei 0:03b5121a232e 2994 }
pcercuei 0:03b5121a232e 2995
pcercuei 0:03b5121a232e 2996 /**
pcercuei 0:03b5121a232e 2997 * xmlXPathPopExternal:
pcercuei 0:03b5121a232e 2998 * @ctxt: an XPath parser context
pcercuei 0:03b5121a232e 2999 *
pcercuei 0:03b5121a232e 3000 * Pops an external object from the stack, handling conversion if needed.
pcercuei 0:03b5121a232e 3001 * Check error with #xmlXPathCheckError.
pcercuei 0:03b5121a232e 3002 *
pcercuei 0:03b5121a232e 3003 * Returns the object
pcercuei 0:03b5121a232e 3004 */
pcercuei 0:03b5121a232e 3005 void *
pcercuei 0:03b5121a232e 3006 xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 3007 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 3008 void * ret;
pcercuei 0:03b5121a232e 3009
pcercuei 0:03b5121a232e 3010 if ((ctxt == NULL) || (ctxt->value == NULL)) {
pcercuei 0:03b5121a232e 3011 xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 3012 return(NULL);
pcercuei 0:03b5121a232e 3013 }
pcercuei 0:03b5121a232e 3014 if (ctxt->value->type != XPATH_USERS) {
pcercuei 0:03b5121a232e 3015 xmlXPathSetTypeError(ctxt);
pcercuei 0:03b5121a232e 3016 return(NULL);
pcercuei 0:03b5121a232e 3017 }
pcercuei 0:03b5121a232e 3018 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 3019 ret = obj->user;
pcercuei 0:03b5121a232e 3020 obj->user = NULL;
pcercuei 0:03b5121a232e 3021 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 3022 return(ret);
pcercuei 0:03b5121a232e 3023 }
pcercuei 0:03b5121a232e 3024
pcercuei 0:03b5121a232e 3025 /*
pcercuei 0:03b5121a232e 3026 * Macros for accessing the content. Those should be used only by the parser,
pcercuei 0:03b5121a232e 3027 * and not exported.
pcercuei 0:03b5121a232e 3028 *
pcercuei 0:03b5121a232e 3029 * Dirty macros, i.e. one need to make assumption on the context to use them
pcercuei 0:03b5121a232e 3030 *
pcercuei 0:03b5121a232e 3031 * CUR_PTR return the current pointer to the xmlChar to be parsed.
pcercuei 0:03b5121a232e 3032 * CUR returns the current xmlChar value, i.e. a 8 bit value
pcercuei 0:03b5121a232e 3033 * in ISO-Latin or UTF-8.
pcercuei 0:03b5121a232e 3034 * This should be used internally by the parser
pcercuei 0:03b5121a232e 3035 * only to compare to ASCII values otherwise it would break when
pcercuei 0:03b5121a232e 3036 * running with UTF-8 encoding.
pcercuei 0:03b5121a232e 3037 * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
pcercuei 0:03b5121a232e 3038 * to compare on ASCII based substring.
pcercuei 0:03b5121a232e 3039 * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
pcercuei 0:03b5121a232e 3040 * strings within the parser.
pcercuei 0:03b5121a232e 3041 * CURRENT Returns the current char value, with the full decoding of
pcercuei 0:03b5121a232e 3042 * UTF-8 if we are using this mode. It returns an int.
pcercuei 0:03b5121a232e 3043 * NEXT Skip to the next character, this does the proper decoding
pcercuei 0:03b5121a232e 3044 * in UTF-8 mode. It also pop-up unfinished entities on the fly.
pcercuei 0:03b5121a232e 3045 * It returns the pointer to the current xmlChar.
pcercuei 0:03b5121a232e 3046 */
pcercuei 0:03b5121a232e 3047
pcercuei 0:03b5121a232e 3048 #define CUR (*ctxt->cur)
pcercuei 0:03b5121a232e 3049 #define SKIP(val) ctxt->cur += (val)
pcercuei 0:03b5121a232e 3050 #define NXT(val) ctxt->cur[(val)]
pcercuei 0:03b5121a232e 3051 #define CUR_PTR ctxt->cur
pcercuei 0:03b5121a232e 3052 #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
pcercuei 0:03b5121a232e 3053
pcercuei 0:03b5121a232e 3054 #define COPY_BUF(l,b,i,v) \
pcercuei 0:03b5121a232e 3055 if (l == 1) b[i++] = (xmlChar) v; \
pcercuei 0:03b5121a232e 3056 else i += xmlCopyChar(l,&b[i],v)
pcercuei 0:03b5121a232e 3057
pcercuei 0:03b5121a232e 3058 #define NEXTL(l) ctxt->cur += l
pcercuei 0:03b5121a232e 3059
pcercuei 0:03b5121a232e 3060 #define SKIP_BLANKS \
pcercuei 0:03b5121a232e 3061 while (IS_BLANK_CH(*(ctxt->cur))) NEXT
pcercuei 0:03b5121a232e 3062
pcercuei 0:03b5121a232e 3063 #define CURRENT (*ctxt->cur)
pcercuei 0:03b5121a232e 3064 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
pcercuei 0:03b5121a232e 3065
pcercuei 0:03b5121a232e 3066
pcercuei 0:03b5121a232e 3067 #ifndef DBL_DIG
pcercuei 0:03b5121a232e 3068 #define DBL_DIG 16
pcercuei 0:03b5121a232e 3069 #endif
pcercuei 0:03b5121a232e 3070 #ifndef DBL_EPSILON
pcercuei 0:03b5121a232e 3071 #define DBL_EPSILON 1E-9
pcercuei 0:03b5121a232e 3072 #endif
pcercuei 0:03b5121a232e 3073
pcercuei 0:03b5121a232e 3074 #define UPPER_DOUBLE 1E9
pcercuei 0:03b5121a232e 3075 #define LOWER_DOUBLE 1E-5
pcercuei 0:03b5121a232e 3076 #define LOWER_DOUBLE_EXP 5
pcercuei 0:03b5121a232e 3077
pcercuei 0:03b5121a232e 3078 #define INTEGER_DIGITS DBL_DIG
pcercuei 0:03b5121a232e 3079 #define FRACTION_DIGITS (DBL_DIG + 1 + (LOWER_DOUBLE_EXP))
pcercuei 0:03b5121a232e 3080 #define EXPONENT_DIGITS (3 + 2)
pcercuei 0:03b5121a232e 3081
pcercuei 0:03b5121a232e 3082 /**
pcercuei 0:03b5121a232e 3083 * xmlXPathFormatNumber:
pcercuei 0:03b5121a232e 3084 * @number: number to format
pcercuei 0:03b5121a232e 3085 * @buffer: output buffer
pcercuei 0:03b5121a232e 3086 * @buffersize: size of output buffer
pcercuei 0:03b5121a232e 3087 *
pcercuei 0:03b5121a232e 3088 * Convert the number into a string representation.
pcercuei 0:03b5121a232e 3089 */
pcercuei 0:03b5121a232e 3090 static void
pcercuei 0:03b5121a232e 3091 xmlXPathFormatNumber(double number, char buffer[], int buffersize)
pcercuei 0:03b5121a232e 3092 {
pcercuei 0:03b5121a232e 3093 switch (xmlXPathIsInf(number)) {
pcercuei 0:03b5121a232e 3094 case 1:
pcercuei 0:03b5121a232e 3095 if (buffersize > (int)sizeof("Infinity"))
pcercuei 0:03b5121a232e 3096 snprintf(buffer, buffersize, "Infinity");
pcercuei 0:03b5121a232e 3097 break;
pcercuei 0:03b5121a232e 3098 case -1:
pcercuei 0:03b5121a232e 3099 if (buffersize > (int)sizeof("-Infinity"))
pcercuei 0:03b5121a232e 3100 snprintf(buffer, buffersize, "-Infinity");
pcercuei 0:03b5121a232e 3101 break;
pcercuei 0:03b5121a232e 3102 default:
pcercuei 0:03b5121a232e 3103 if (xmlXPathIsNaN(number)) {
pcercuei 0:03b5121a232e 3104 if (buffersize > (int)sizeof("NaN"))
pcercuei 0:03b5121a232e 3105 snprintf(buffer, buffersize, "NaN");
pcercuei 0:03b5121a232e 3106 } else if (number == 0 && xmlXPathGetSign(number) != 0) {
pcercuei 0:03b5121a232e 3107 snprintf(buffer, buffersize, "0");
pcercuei 0:03b5121a232e 3108 } else if (number == ((int) number)) {
pcercuei 0:03b5121a232e 3109 char work[30];
pcercuei 0:03b5121a232e 3110 char *ptr, *cur;
pcercuei 0:03b5121a232e 3111 int value = (int) number;
pcercuei 0:03b5121a232e 3112
pcercuei 0:03b5121a232e 3113 ptr = &buffer[0];
pcercuei 0:03b5121a232e 3114 if (value == 0) {
pcercuei 0:03b5121a232e 3115 *ptr++ = '0';
pcercuei 0:03b5121a232e 3116 } else {
pcercuei 0:03b5121a232e 3117 snprintf(work, 29, "%d", value);
pcercuei 0:03b5121a232e 3118 cur = &work[0];
pcercuei 0:03b5121a232e 3119 while ((*cur) && (ptr - buffer < buffersize)) {
pcercuei 0:03b5121a232e 3120 *ptr++ = *cur++;
pcercuei 0:03b5121a232e 3121 }
pcercuei 0:03b5121a232e 3122 }
pcercuei 0:03b5121a232e 3123 if (ptr - buffer < buffersize) {
pcercuei 0:03b5121a232e 3124 *ptr = 0;
pcercuei 0:03b5121a232e 3125 } else if (buffersize > 0) {
pcercuei 0:03b5121a232e 3126 ptr--;
pcercuei 0:03b5121a232e 3127 *ptr = 0;
pcercuei 0:03b5121a232e 3128 }
pcercuei 0:03b5121a232e 3129 } else {
pcercuei 0:03b5121a232e 3130 /*
pcercuei 0:03b5121a232e 3131 For the dimension of work,
pcercuei 0:03b5121a232e 3132 DBL_DIG is number of significant digits
pcercuei 0:03b5121a232e 3133 EXPONENT is only needed for "scientific notation"
pcercuei 0:03b5121a232e 3134 3 is sign, decimal point, and terminating zero
pcercuei 0:03b5121a232e 3135 LOWER_DOUBLE_EXP is max number of leading zeroes in fraction
pcercuei 0:03b5121a232e 3136 Note that this dimension is slightly (a few characters)
pcercuei 0:03b5121a232e 3137 larger than actually necessary.
pcercuei 0:03b5121a232e 3138 */
pcercuei 0:03b5121a232e 3139 char work[DBL_DIG + EXPONENT_DIGITS + 3 + LOWER_DOUBLE_EXP];
pcercuei 0:03b5121a232e 3140 int integer_place, fraction_place;
pcercuei 0:03b5121a232e 3141 char *ptr;
pcercuei 0:03b5121a232e 3142 char *after_fraction;
pcercuei 0:03b5121a232e 3143 double absolute_value;
pcercuei 0:03b5121a232e 3144 int size;
pcercuei 0:03b5121a232e 3145
pcercuei 0:03b5121a232e 3146 absolute_value = fabs(number);
pcercuei 0:03b5121a232e 3147
pcercuei 0:03b5121a232e 3148 /*
pcercuei 0:03b5121a232e 3149 * First choose format - scientific or regular floating point.
pcercuei 0:03b5121a232e 3150 * In either case, result is in work, and after_fraction points
pcercuei 0:03b5121a232e 3151 * just past the fractional part.
pcercuei 0:03b5121a232e 3152 */
pcercuei 0:03b5121a232e 3153 if ( ((absolute_value > UPPER_DOUBLE) ||
pcercuei 0:03b5121a232e 3154 (absolute_value < LOWER_DOUBLE)) &&
pcercuei 0:03b5121a232e 3155 (absolute_value != 0.0) ) {
pcercuei 0:03b5121a232e 3156 /* Use scientific notation */
pcercuei 0:03b5121a232e 3157 integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
pcercuei 0:03b5121a232e 3158 fraction_place = DBL_DIG - 1;
pcercuei 0:03b5121a232e 3159 size = snprintf(work, sizeof(work),"%*.*e",
pcercuei 0:03b5121a232e 3160 integer_place, fraction_place, number);
pcercuei 0:03b5121a232e 3161 while ((size > 0) && (work[size] != 'e')) size--;
pcercuei 0:03b5121a232e 3162
pcercuei 0:03b5121a232e 3163 }
pcercuei 0:03b5121a232e 3164 else {
pcercuei 0:03b5121a232e 3165 /* Use regular notation */
pcercuei 0:03b5121a232e 3166 if (absolute_value > 0.0) {
pcercuei 0:03b5121a232e 3167 integer_place = (int)log10(absolute_value);
pcercuei 0:03b5121a232e 3168 if (integer_place > 0)
pcercuei 0:03b5121a232e 3169 fraction_place = DBL_DIG - integer_place - 1;
pcercuei 0:03b5121a232e 3170 else
pcercuei 0:03b5121a232e 3171 fraction_place = DBL_DIG - integer_place;
pcercuei 0:03b5121a232e 3172 } else {
pcercuei 0:03b5121a232e 3173 fraction_place = 1;
pcercuei 0:03b5121a232e 3174 }
pcercuei 0:03b5121a232e 3175 size = snprintf(work, sizeof(work), "%0.*f",
pcercuei 0:03b5121a232e 3176 fraction_place, number);
pcercuei 0:03b5121a232e 3177 }
pcercuei 0:03b5121a232e 3178
pcercuei 0:03b5121a232e 3179 /* Remove leading spaces sometimes inserted by snprintf */
pcercuei 0:03b5121a232e 3180 while (work[0] == ' ') {
pcercuei 0:03b5121a232e 3181 for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++);
pcercuei 0:03b5121a232e 3182 size--;
pcercuei 0:03b5121a232e 3183 }
pcercuei 0:03b5121a232e 3184
pcercuei 0:03b5121a232e 3185 /* Remove fractional trailing zeroes */
pcercuei 0:03b5121a232e 3186 after_fraction = work + size;
pcercuei 0:03b5121a232e 3187 ptr = after_fraction;
pcercuei 0:03b5121a232e 3188 while (*(--ptr) == '0')
pcercuei 0:03b5121a232e 3189 ;
pcercuei 0:03b5121a232e 3190 if (*ptr != '.')
pcercuei 0:03b5121a232e 3191 ptr++;
pcercuei 0:03b5121a232e 3192 while ((*ptr++ = *after_fraction++) != 0);
pcercuei 0:03b5121a232e 3193
pcercuei 0:03b5121a232e 3194 /* Finally copy result back to caller */
pcercuei 0:03b5121a232e 3195 size = strlen(work) + 1;
pcercuei 0:03b5121a232e 3196 if (size > buffersize) {
pcercuei 0:03b5121a232e 3197 work[buffersize - 1] = 0;
pcercuei 0:03b5121a232e 3198 size = buffersize;
pcercuei 0:03b5121a232e 3199 }
pcercuei 0:03b5121a232e 3200 memmove(buffer, work, size);
pcercuei 0:03b5121a232e 3201 }
pcercuei 0:03b5121a232e 3202 break;
pcercuei 0:03b5121a232e 3203 }
pcercuei 0:03b5121a232e 3204 }
pcercuei 0:03b5121a232e 3205
pcercuei 0:03b5121a232e 3206
pcercuei 0:03b5121a232e 3207 /************************************************************************
pcercuei 0:03b5121a232e 3208 * *
pcercuei 0:03b5121a232e 3209 * Routines to handle NodeSets *
pcercuei 0:03b5121a232e 3210 * *
pcercuei 0:03b5121a232e 3211 ************************************************************************/
pcercuei 0:03b5121a232e 3212
pcercuei 0:03b5121a232e 3213 /**
pcercuei 0:03b5121a232e 3214 * xmlXPathOrderDocElems:
pcercuei 0:03b5121a232e 3215 * @doc: an input document
pcercuei 0:03b5121a232e 3216 *
pcercuei 0:03b5121a232e 3217 * Call this routine to speed up XPath computation on static documents.
pcercuei 0:03b5121a232e 3218 * This stamps all the element nodes with the document order
pcercuei 0:03b5121a232e 3219 * Like for line information, the order is kept in the element->content
pcercuei 0:03b5121a232e 3220 * field, the value stored is actually - the node number (starting at -1)
pcercuei 0:03b5121a232e 3221 * to be able to differentiate from line numbers.
pcercuei 0:03b5121a232e 3222 *
pcercuei 0:03b5121a232e 3223 * Returns the number of elements found in the document or -1 in case
pcercuei 0:03b5121a232e 3224 * of error.
pcercuei 0:03b5121a232e 3225 */
pcercuei 0:03b5121a232e 3226 long
pcercuei 0:03b5121a232e 3227 xmlXPathOrderDocElems(xmlDocPtr doc) {
pcercuei 0:03b5121a232e 3228 long count = 0;
pcercuei 0:03b5121a232e 3229 xmlNodePtr cur;
pcercuei 0:03b5121a232e 3230
pcercuei 0:03b5121a232e 3231 if (doc == NULL)
pcercuei 0:03b5121a232e 3232 return(-1);
pcercuei 0:03b5121a232e 3233 cur = doc->children;
pcercuei 0:03b5121a232e 3234 while (cur != NULL) {
pcercuei 0:03b5121a232e 3235 if (cur->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 3236 cur->content = (void *) (-(++count));
pcercuei 0:03b5121a232e 3237 if (cur->children != NULL) {
pcercuei 0:03b5121a232e 3238 cur = cur->children;
pcercuei 0:03b5121a232e 3239 continue;
pcercuei 0:03b5121a232e 3240 }
pcercuei 0:03b5121a232e 3241 }
pcercuei 0:03b5121a232e 3242 if (cur->next != NULL) {
pcercuei 0:03b5121a232e 3243 cur = cur->next;
pcercuei 0:03b5121a232e 3244 continue;
pcercuei 0:03b5121a232e 3245 }
pcercuei 0:03b5121a232e 3246 do {
pcercuei 0:03b5121a232e 3247 cur = cur->parent;
pcercuei 0:03b5121a232e 3248 if (cur == NULL)
pcercuei 0:03b5121a232e 3249 break;
pcercuei 0:03b5121a232e 3250 if (cur == (xmlNodePtr) doc) {
pcercuei 0:03b5121a232e 3251 cur = NULL;
pcercuei 0:03b5121a232e 3252 break;
pcercuei 0:03b5121a232e 3253 }
pcercuei 0:03b5121a232e 3254 if (cur->next != NULL) {
pcercuei 0:03b5121a232e 3255 cur = cur->next;
pcercuei 0:03b5121a232e 3256 break;
pcercuei 0:03b5121a232e 3257 }
pcercuei 0:03b5121a232e 3258 } while (cur != NULL);
pcercuei 0:03b5121a232e 3259 }
pcercuei 0:03b5121a232e 3260 return(count);
pcercuei 0:03b5121a232e 3261 }
pcercuei 0:03b5121a232e 3262
pcercuei 0:03b5121a232e 3263 /**
pcercuei 0:03b5121a232e 3264 * xmlXPathCmpNodes:
pcercuei 0:03b5121a232e 3265 * @node1: the first node
pcercuei 0:03b5121a232e 3266 * @node2: the second node
pcercuei 0:03b5121a232e 3267 *
pcercuei 0:03b5121a232e 3268 * Compare two nodes w.r.t document order
pcercuei 0:03b5121a232e 3269 *
pcercuei 0:03b5121a232e 3270 * Returns -2 in case of error 1 if first point < second point, 0 if
pcercuei 0:03b5121a232e 3271 * it's the same node, -1 otherwise
pcercuei 0:03b5121a232e 3272 */
pcercuei 0:03b5121a232e 3273 int
pcercuei 0:03b5121a232e 3274 xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
pcercuei 0:03b5121a232e 3275 int depth1, depth2;
pcercuei 0:03b5121a232e 3276 int attr1 = 0, attr2 = 0;
pcercuei 0:03b5121a232e 3277 xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
pcercuei 0:03b5121a232e 3278 xmlNodePtr cur, root;
pcercuei 0:03b5121a232e 3279
pcercuei 0:03b5121a232e 3280 if ((node1 == NULL) || (node2 == NULL))
pcercuei 0:03b5121a232e 3281 return(-2);
pcercuei 0:03b5121a232e 3282 /*
pcercuei 0:03b5121a232e 3283 * a couple of optimizations which will avoid computations in most cases
pcercuei 0:03b5121a232e 3284 */
pcercuei 0:03b5121a232e 3285 if (node1 == node2) /* trivial case */
pcercuei 0:03b5121a232e 3286 return(0);
pcercuei 0:03b5121a232e 3287 if (node1->type == XML_ATTRIBUTE_NODE) {
pcercuei 0:03b5121a232e 3288 attr1 = 1;
pcercuei 0:03b5121a232e 3289 attrNode1 = node1;
pcercuei 0:03b5121a232e 3290 node1 = node1->parent;
pcercuei 0:03b5121a232e 3291 }
pcercuei 0:03b5121a232e 3292 if (node2->type == XML_ATTRIBUTE_NODE) {
pcercuei 0:03b5121a232e 3293 attr2 = 1;
pcercuei 0:03b5121a232e 3294 attrNode2 = node2;
pcercuei 0:03b5121a232e 3295 node2 = node2->parent;
pcercuei 0:03b5121a232e 3296 }
pcercuei 0:03b5121a232e 3297 if (node1 == node2) {
pcercuei 0:03b5121a232e 3298 if (attr1 == attr2) {
pcercuei 0:03b5121a232e 3299 /* not required, but we keep attributes in order */
pcercuei 0:03b5121a232e 3300 if (attr1 != 0) {
pcercuei 0:03b5121a232e 3301 cur = attrNode2->prev;
pcercuei 0:03b5121a232e 3302 while (cur != NULL) {
pcercuei 0:03b5121a232e 3303 if (cur == attrNode1)
pcercuei 0:03b5121a232e 3304 return (1);
pcercuei 0:03b5121a232e 3305 cur = cur->prev;
pcercuei 0:03b5121a232e 3306 }
pcercuei 0:03b5121a232e 3307 return (-1);
pcercuei 0:03b5121a232e 3308 }
pcercuei 0:03b5121a232e 3309 return(0);
pcercuei 0:03b5121a232e 3310 }
pcercuei 0:03b5121a232e 3311 if (attr2 == 1)
pcercuei 0:03b5121a232e 3312 return(1);
pcercuei 0:03b5121a232e 3313 return(-1);
pcercuei 0:03b5121a232e 3314 }
pcercuei 0:03b5121a232e 3315 if ((node1->type == XML_NAMESPACE_DECL) ||
pcercuei 0:03b5121a232e 3316 (node2->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 3317 return(1);
pcercuei 0:03b5121a232e 3318 if (node1 == node2->prev)
pcercuei 0:03b5121a232e 3319 return(1);
pcercuei 0:03b5121a232e 3320 if (node1 == node2->next)
pcercuei 0:03b5121a232e 3321 return(-1);
pcercuei 0:03b5121a232e 3322
pcercuei 0:03b5121a232e 3323 /*
pcercuei 0:03b5121a232e 3324 * Speedup using document order if availble.
pcercuei 0:03b5121a232e 3325 */
pcercuei 0:03b5121a232e 3326 if ((node1->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 3327 (node2->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 3328 (0 > (long) node1->content) &&
pcercuei 0:03b5121a232e 3329 (0 > (long) node2->content) &&
pcercuei 0:03b5121a232e 3330 (node1->doc == node2->doc)) {
pcercuei 0:03b5121a232e 3331 long l1, l2;
pcercuei 0:03b5121a232e 3332
pcercuei 0:03b5121a232e 3333 l1 = -((long) node1->content);
pcercuei 0:03b5121a232e 3334 l2 = -((long) node2->content);
pcercuei 0:03b5121a232e 3335 if (l1 < l2)
pcercuei 0:03b5121a232e 3336 return(1);
pcercuei 0:03b5121a232e 3337 if (l1 > l2)
pcercuei 0:03b5121a232e 3338 return(-1);
pcercuei 0:03b5121a232e 3339 }
pcercuei 0:03b5121a232e 3340
pcercuei 0:03b5121a232e 3341 /*
pcercuei 0:03b5121a232e 3342 * compute depth to root
pcercuei 0:03b5121a232e 3343 */
pcercuei 0:03b5121a232e 3344 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
pcercuei 0:03b5121a232e 3345 if (cur == node1)
pcercuei 0:03b5121a232e 3346 return(1);
pcercuei 0:03b5121a232e 3347 depth2++;
pcercuei 0:03b5121a232e 3348 }
pcercuei 0:03b5121a232e 3349 root = cur;
pcercuei 0:03b5121a232e 3350 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
pcercuei 0:03b5121a232e 3351 if (cur == node2)
pcercuei 0:03b5121a232e 3352 return(-1);
pcercuei 0:03b5121a232e 3353 depth1++;
pcercuei 0:03b5121a232e 3354 }
pcercuei 0:03b5121a232e 3355 /*
pcercuei 0:03b5121a232e 3356 * Distinct document (or distinct entities :-( ) case.
pcercuei 0:03b5121a232e 3357 */
pcercuei 0:03b5121a232e 3358 if (root != cur) {
pcercuei 0:03b5121a232e 3359 return(-2);
pcercuei 0:03b5121a232e 3360 }
pcercuei 0:03b5121a232e 3361 /*
pcercuei 0:03b5121a232e 3362 * get the nearest common ancestor.
pcercuei 0:03b5121a232e 3363 */
pcercuei 0:03b5121a232e 3364 while (depth1 > depth2) {
pcercuei 0:03b5121a232e 3365 depth1--;
pcercuei 0:03b5121a232e 3366 node1 = node1->parent;
pcercuei 0:03b5121a232e 3367 }
pcercuei 0:03b5121a232e 3368 while (depth2 > depth1) {
pcercuei 0:03b5121a232e 3369 depth2--;
pcercuei 0:03b5121a232e 3370 node2 = node2->parent;
pcercuei 0:03b5121a232e 3371 }
pcercuei 0:03b5121a232e 3372 while (node1->parent != node2->parent) {
pcercuei 0:03b5121a232e 3373 node1 = node1->parent;
pcercuei 0:03b5121a232e 3374 node2 = node2->parent;
pcercuei 0:03b5121a232e 3375 /* should not happen but just in case ... */
pcercuei 0:03b5121a232e 3376 if ((node1 == NULL) || (node2 == NULL))
pcercuei 0:03b5121a232e 3377 return(-2);
pcercuei 0:03b5121a232e 3378 }
pcercuei 0:03b5121a232e 3379 /*
pcercuei 0:03b5121a232e 3380 * Find who's first.
pcercuei 0:03b5121a232e 3381 */
pcercuei 0:03b5121a232e 3382 if (node1 == node2->prev)
pcercuei 0:03b5121a232e 3383 return(1);
pcercuei 0:03b5121a232e 3384 if (node1 == node2->next)
pcercuei 0:03b5121a232e 3385 return(-1);
pcercuei 0:03b5121a232e 3386 /*
pcercuei 0:03b5121a232e 3387 * Speedup using document order if availble.
pcercuei 0:03b5121a232e 3388 */
pcercuei 0:03b5121a232e 3389 if ((node1->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 3390 (node2->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 3391 (0 > (long) node1->content) &&
pcercuei 0:03b5121a232e 3392 (0 > (long) node2->content) &&
pcercuei 0:03b5121a232e 3393 (node1->doc == node2->doc)) {
pcercuei 0:03b5121a232e 3394 long l1, l2;
pcercuei 0:03b5121a232e 3395
pcercuei 0:03b5121a232e 3396 l1 = -((long) node1->content);
pcercuei 0:03b5121a232e 3397 l2 = -((long) node2->content);
pcercuei 0:03b5121a232e 3398 if (l1 < l2)
pcercuei 0:03b5121a232e 3399 return(1);
pcercuei 0:03b5121a232e 3400 if (l1 > l2)
pcercuei 0:03b5121a232e 3401 return(-1);
pcercuei 0:03b5121a232e 3402 }
pcercuei 0:03b5121a232e 3403
pcercuei 0:03b5121a232e 3404 for (cur = node1->next;cur != NULL;cur = cur->next)
pcercuei 0:03b5121a232e 3405 if (cur == node2)
pcercuei 0:03b5121a232e 3406 return(1);
pcercuei 0:03b5121a232e 3407 return(-1); /* assume there is no sibling list corruption */
pcercuei 0:03b5121a232e 3408 }
pcercuei 0:03b5121a232e 3409
pcercuei 0:03b5121a232e 3410 /**
pcercuei 0:03b5121a232e 3411 * xmlXPathNodeSetSort:
pcercuei 0:03b5121a232e 3412 * @set: the node set
pcercuei 0:03b5121a232e 3413 *
pcercuei 0:03b5121a232e 3414 * Sort the node set in document order
pcercuei 0:03b5121a232e 3415 */
pcercuei 0:03b5121a232e 3416 void
pcercuei 0:03b5121a232e 3417 xmlXPathNodeSetSort(xmlNodeSetPtr set) {
pcercuei 0:03b5121a232e 3418 #ifndef WITH_TIM_SORT
pcercuei 0:03b5121a232e 3419 int i, j, incr, len;
pcercuei 0:03b5121a232e 3420 xmlNodePtr tmp;
pcercuei 0:03b5121a232e 3421 #endif
pcercuei 0:03b5121a232e 3422
pcercuei 0:03b5121a232e 3423 if (set == NULL)
pcercuei 0:03b5121a232e 3424 return;
pcercuei 0:03b5121a232e 3425
pcercuei 0:03b5121a232e 3426 #ifndef WITH_TIM_SORT
pcercuei 0:03b5121a232e 3427 /*
pcercuei 0:03b5121a232e 3428 * Use the old Shell's sort implementation to sort the node-set
pcercuei 0:03b5121a232e 3429 * Timsort ought to be quite faster
pcercuei 0:03b5121a232e 3430 */
pcercuei 0:03b5121a232e 3431 len = set->nodeNr;
pcercuei 0:03b5121a232e 3432 for (incr = len / 2; incr > 0; incr /= 2) {
pcercuei 0:03b5121a232e 3433 for (i = incr; i < len; i++) {
pcercuei 0:03b5121a232e 3434 j = i - incr;
pcercuei 0:03b5121a232e 3435 while (j >= 0) {
pcercuei 0:03b5121a232e 3436 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
pcercuei 0:03b5121a232e 3437 if (xmlXPathCmpNodesExt(set->nodeTab[j],
pcercuei 0:03b5121a232e 3438 set->nodeTab[j + incr]) == -1)
pcercuei 0:03b5121a232e 3439 #else
pcercuei 0:03b5121a232e 3440 if (xmlXPathCmpNodes(set->nodeTab[j],
pcercuei 0:03b5121a232e 3441 set->nodeTab[j + incr]) == -1)
pcercuei 0:03b5121a232e 3442 #endif
pcercuei 0:03b5121a232e 3443 {
pcercuei 0:03b5121a232e 3444 tmp = set->nodeTab[j];
pcercuei 0:03b5121a232e 3445 set->nodeTab[j] = set->nodeTab[j + incr];
pcercuei 0:03b5121a232e 3446 set->nodeTab[j + incr] = tmp;
pcercuei 0:03b5121a232e 3447 j -= incr;
pcercuei 0:03b5121a232e 3448 } else
pcercuei 0:03b5121a232e 3449 break;
pcercuei 0:03b5121a232e 3450 }
pcercuei 0:03b5121a232e 3451 }
pcercuei 0:03b5121a232e 3452 }
pcercuei 0:03b5121a232e 3453 #else /* WITH_TIM_SORT */
pcercuei 0:03b5121a232e 3454 libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
pcercuei 0:03b5121a232e 3455 #endif /* WITH_TIM_SORT */
pcercuei 0:03b5121a232e 3456 }
pcercuei 0:03b5121a232e 3457
pcercuei 0:03b5121a232e 3458 #define XML_NODESET_DEFAULT 10
pcercuei 0:03b5121a232e 3459 /**
pcercuei 0:03b5121a232e 3460 * xmlXPathNodeSetDupNs:
pcercuei 0:03b5121a232e 3461 * @node: the parent node of the namespace XPath node
pcercuei 0:03b5121a232e 3462 * @ns: the libxml namespace declaration node.
pcercuei 0:03b5121a232e 3463 *
pcercuei 0:03b5121a232e 3464 * Namespace node in libxml don't match the XPath semantic. In a node set
pcercuei 0:03b5121a232e 3465 * the namespace nodes are duplicated and the next pointer is set to the
pcercuei 0:03b5121a232e 3466 * parent node in the XPath semantic.
pcercuei 0:03b5121a232e 3467 *
pcercuei 0:03b5121a232e 3468 * Returns the newly created object.
pcercuei 0:03b5121a232e 3469 */
pcercuei 0:03b5121a232e 3470 static xmlNodePtr
pcercuei 0:03b5121a232e 3471 xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
pcercuei 0:03b5121a232e 3472 xmlNsPtr cur;
pcercuei 0:03b5121a232e 3473
pcercuei 0:03b5121a232e 3474 if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 3475 return(NULL);
pcercuei 0:03b5121a232e 3476 if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 3477 return((xmlNodePtr) ns);
pcercuei 0:03b5121a232e 3478
pcercuei 0:03b5121a232e 3479 /*
pcercuei 0:03b5121a232e 3480 * Allocate a new Namespace and fill the fields.
pcercuei 0:03b5121a232e 3481 */
pcercuei 0:03b5121a232e 3482 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
pcercuei 0:03b5121a232e 3483 if (cur == NULL) {
pcercuei 0:03b5121a232e 3484 xmlXPathErrMemory(NULL, "duplicating namespace\n");
pcercuei 0:03b5121a232e 3485 return(NULL);
pcercuei 0:03b5121a232e 3486 }
pcercuei 0:03b5121a232e 3487 memset(cur, 0, sizeof(xmlNs));
pcercuei 0:03b5121a232e 3488 cur->type = XML_NAMESPACE_DECL;
pcercuei 0:03b5121a232e 3489 if (ns->href != NULL)
pcercuei 0:03b5121a232e 3490 cur->href = xmlStrdup(ns->href);
pcercuei 0:03b5121a232e 3491 if (ns->prefix != NULL)
pcercuei 0:03b5121a232e 3492 cur->prefix = xmlStrdup(ns->prefix);
pcercuei 0:03b5121a232e 3493 cur->next = (xmlNsPtr) node;
pcercuei 0:03b5121a232e 3494 return((xmlNodePtr) cur);
pcercuei 0:03b5121a232e 3495 }
pcercuei 0:03b5121a232e 3496
pcercuei 0:03b5121a232e 3497 /**
pcercuei 0:03b5121a232e 3498 * xmlXPathNodeSetFreeNs:
pcercuei 0:03b5121a232e 3499 * @ns: the XPath namespace node found in a nodeset.
pcercuei 0:03b5121a232e 3500 *
pcercuei 0:03b5121a232e 3501 * Namespace nodes in libxml don't match the XPath semantic. In a node set
pcercuei 0:03b5121a232e 3502 * the namespace nodes are duplicated and the next pointer is set to the
pcercuei 0:03b5121a232e 3503 * parent node in the XPath semantic. Check if such a node needs to be freed
pcercuei 0:03b5121a232e 3504 */
pcercuei 0:03b5121a232e 3505 void
pcercuei 0:03b5121a232e 3506 xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
pcercuei 0:03b5121a232e 3507 if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 3508 return;
pcercuei 0:03b5121a232e 3509
pcercuei 0:03b5121a232e 3510 if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
pcercuei 0:03b5121a232e 3511 if (ns->href != NULL)
pcercuei 0:03b5121a232e 3512 xmlFree((xmlChar *)ns->href);
pcercuei 0:03b5121a232e 3513 if (ns->prefix != NULL)
pcercuei 0:03b5121a232e 3514 xmlFree((xmlChar *)ns->prefix);
pcercuei 0:03b5121a232e 3515 xmlFree(ns);
pcercuei 0:03b5121a232e 3516 }
pcercuei 0:03b5121a232e 3517 }
pcercuei 0:03b5121a232e 3518
pcercuei 0:03b5121a232e 3519 /**
pcercuei 0:03b5121a232e 3520 * xmlXPathNodeSetCreate:
pcercuei 0:03b5121a232e 3521 * @val: an initial xmlNodePtr, or NULL
pcercuei 0:03b5121a232e 3522 *
pcercuei 0:03b5121a232e 3523 * Create a new xmlNodeSetPtr of type double and of value @val
pcercuei 0:03b5121a232e 3524 *
pcercuei 0:03b5121a232e 3525 * Returns the newly created object.
pcercuei 0:03b5121a232e 3526 */
pcercuei 0:03b5121a232e 3527 xmlNodeSetPtr
pcercuei 0:03b5121a232e 3528 xmlXPathNodeSetCreate(xmlNodePtr val) {
pcercuei 0:03b5121a232e 3529 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 3530
pcercuei 0:03b5121a232e 3531 ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
pcercuei 0:03b5121a232e 3532 if (ret == NULL) {
pcercuei 0:03b5121a232e 3533 xmlXPathErrMemory(NULL, "creating nodeset\n");
pcercuei 0:03b5121a232e 3534 return(NULL);
pcercuei 0:03b5121a232e 3535 }
pcercuei 0:03b5121a232e 3536 memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
pcercuei 0:03b5121a232e 3537 if (val != NULL) {
pcercuei 0:03b5121a232e 3538 ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
pcercuei 0:03b5121a232e 3539 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3540 if (ret->nodeTab == NULL) {
pcercuei 0:03b5121a232e 3541 xmlXPathErrMemory(NULL, "creating nodeset\n");
pcercuei 0:03b5121a232e 3542 xmlFree(ret);
pcercuei 0:03b5121a232e 3543 return(NULL);
pcercuei 0:03b5121a232e 3544 }
pcercuei 0:03b5121a232e 3545 memset(ret->nodeTab, 0 ,
pcercuei 0:03b5121a232e 3546 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3547 ret->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 3548 if (val->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 3549 xmlNsPtr ns = (xmlNsPtr) val;
pcercuei 0:03b5121a232e 3550
pcercuei 0:03b5121a232e 3551 ret->nodeTab[ret->nodeNr++] =
pcercuei 0:03b5121a232e 3552 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
pcercuei 0:03b5121a232e 3553 } else
pcercuei 0:03b5121a232e 3554 ret->nodeTab[ret->nodeNr++] = val;
pcercuei 0:03b5121a232e 3555 }
pcercuei 0:03b5121a232e 3556 return(ret);
pcercuei 0:03b5121a232e 3557 }
pcercuei 0:03b5121a232e 3558
pcercuei 0:03b5121a232e 3559 /**
pcercuei 0:03b5121a232e 3560 * xmlXPathNodeSetCreateSize:
pcercuei 0:03b5121a232e 3561 * @size: the initial size of the set
pcercuei 0:03b5121a232e 3562 *
pcercuei 0:03b5121a232e 3563 * Create a new xmlNodeSetPtr of type double and of value @val
pcercuei 0:03b5121a232e 3564 *
pcercuei 0:03b5121a232e 3565 * Returns the newly created object.
pcercuei 0:03b5121a232e 3566 */
pcercuei 0:03b5121a232e 3567 static xmlNodeSetPtr
pcercuei 0:03b5121a232e 3568 xmlXPathNodeSetCreateSize(int size) {
pcercuei 0:03b5121a232e 3569 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 3570
pcercuei 0:03b5121a232e 3571 ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
pcercuei 0:03b5121a232e 3572 if (ret == NULL) {
pcercuei 0:03b5121a232e 3573 xmlXPathErrMemory(NULL, "creating nodeset\n");
pcercuei 0:03b5121a232e 3574 return(NULL);
pcercuei 0:03b5121a232e 3575 }
pcercuei 0:03b5121a232e 3576 memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
pcercuei 0:03b5121a232e 3577 if (size < XML_NODESET_DEFAULT)
pcercuei 0:03b5121a232e 3578 size = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 3579 ret->nodeTab = (xmlNodePtr *) xmlMalloc(size * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3580 if (ret->nodeTab == NULL) {
pcercuei 0:03b5121a232e 3581 xmlXPathErrMemory(NULL, "creating nodeset\n");
pcercuei 0:03b5121a232e 3582 xmlFree(ret);
pcercuei 0:03b5121a232e 3583 return(NULL);
pcercuei 0:03b5121a232e 3584 }
pcercuei 0:03b5121a232e 3585 memset(ret->nodeTab, 0 , size * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3586 ret->nodeMax = size;
pcercuei 0:03b5121a232e 3587 return(ret);
pcercuei 0:03b5121a232e 3588 }
pcercuei 0:03b5121a232e 3589
pcercuei 0:03b5121a232e 3590 /**
pcercuei 0:03b5121a232e 3591 * xmlXPathNodeSetContains:
pcercuei 0:03b5121a232e 3592 * @cur: the node-set
pcercuei 0:03b5121a232e 3593 * @val: the node
pcercuei 0:03b5121a232e 3594 *
pcercuei 0:03b5121a232e 3595 * checks whether @cur contains @val
pcercuei 0:03b5121a232e 3596 *
pcercuei 0:03b5121a232e 3597 * Returns true (1) if @cur contains @val, false (0) otherwise
pcercuei 0:03b5121a232e 3598 */
pcercuei 0:03b5121a232e 3599 int
pcercuei 0:03b5121a232e 3600 xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
pcercuei 0:03b5121a232e 3601 int i;
pcercuei 0:03b5121a232e 3602
pcercuei 0:03b5121a232e 3603 if ((cur == NULL) || (val == NULL)) return(0);
pcercuei 0:03b5121a232e 3604 if (val->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 3605 for (i = 0; i < cur->nodeNr; i++) {
pcercuei 0:03b5121a232e 3606 if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 3607 xmlNsPtr ns1, ns2;
pcercuei 0:03b5121a232e 3608
pcercuei 0:03b5121a232e 3609 ns1 = (xmlNsPtr) val;
pcercuei 0:03b5121a232e 3610 ns2 = (xmlNsPtr) cur->nodeTab[i];
pcercuei 0:03b5121a232e 3611 if (ns1 == ns2)
pcercuei 0:03b5121a232e 3612 return(1);
pcercuei 0:03b5121a232e 3613 if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
pcercuei 0:03b5121a232e 3614 (xmlStrEqual(ns1->prefix, ns2->prefix)))
pcercuei 0:03b5121a232e 3615 return(1);
pcercuei 0:03b5121a232e 3616 }
pcercuei 0:03b5121a232e 3617 }
pcercuei 0:03b5121a232e 3618 } else {
pcercuei 0:03b5121a232e 3619 for (i = 0; i < cur->nodeNr; i++) {
pcercuei 0:03b5121a232e 3620 if (cur->nodeTab[i] == val)
pcercuei 0:03b5121a232e 3621 return(1);
pcercuei 0:03b5121a232e 3622 }
pcercuei 0:03b5121a232e 3623 }
pcercuei 0:03b5121a232e 3624 return(0);
pcercuei 0:03b5121a232e 3625 }
pcercuei 0:03b5121a232e 3626
pcercuei 0:03b5121a232e 3627 /**
pcercuei 0:03b5121a232e 3628 * xmlXPathNodeSetAddNs:
pcercuei 0:03b5121a232e 3629 * @cur: the initial node set
pcercuei 0:03b5121a232e 3630 * @node: the hosting node
pcercuei 0:03b5121a232e 3631 * @ns: a the namespace node
pcercuei 0:03b5121a232e 3632 *
pcercuei 0:03b5121a232e 3633 * add a new namespace node to an existing NodeSet
pcercuei 0:03b5121a232e 3634 *
pcercuei 0:03b5121a232e 3635 * Returns 0 in case of success and -1 in case of error
pcercuei 0:03b5121a232e 3636 */
pcercuei 0:03b5121a232e 3637 int
pcercuei 0:03b5121a232e 3638 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
pcercuei 0:03b5121a232e 3639 int i;
pcercuei 0:03b5121a232e 3640
pcercuei 0:03b5121a232e 3641
pcercuei 0:03b5121a232e 3642 if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
pcercuei 0:03b5121a232e 3643 (ns->type != XML_NAMESPACE_DECL) ||
pcercuei 0:03b5121a232e 3644 (node->type != XML_ELEMENT_NODE))
pcercuei 0:03b5121a232e 3645 return(-1);
pcercuei 0:03b5121a232e 3646
pcercuei 0:03b5121a232e 3647 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
pcercuei 0:03b5121a232e 3648 /*
pcercuei 0:03b5121a232e 3649 * prevent duplicates
pcercuei 0:03b5121a232e 3650 */
pcercuei 0:03b5121a232e 3651 for (i = 0;i < cur->nodeNr;i++) {
pcercuei 0:03b5121a232e 3652 if ((cur->nodeTab[i] != NULL) &&
pcercuei 0:03b5121a232e 3653 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 3654 (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
pcercuei 0:03b5121a232e 3655 (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
pcercuei 0:03b5121a232e 3656 return(0);
pcercuei 0:03b5121a232e 3657 }
pcercuei 0:03b5121a232e 3658
pcercuei 0:03b5121a232e 3659 /*
pcercuei 0:03b5121a232e 3660 * grow the nodeTab if needed
pcercuei 0:03b5121a232e 3661 */
pcercuei 0:03b5121a232e 3662 if (cur->nodeMax == 0) {
pcercuei 0:03b5121a232e 3663 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
pcercuei 0:03b5121a232e 3664 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3665 if (cur->nodeTab == NULL) {
pcercuei 0:03b5121a232e 3666 xmlXPathErrMemory(NULL, "growing nodeset\n");
pcercuei 0:03b5121a232e 3667 return(-1);
pcercuei 0:03b5121a232e 3668 }
pcercuei 0:03b5121a232e 3669 memset(cur->nodeTab, 0 ,
pcercuei 0:03b5121a232e 3670 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3671 cur->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 3672 } else if (cur->nodeNr == cur->nodeMax) {
pcercuei 0:03b5121a232e 3673 xmlNodePtr *temp;
pcercuei 0:03b5121a232e 3674
pcercuei 0:03b5121a232e 3675 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
pcercuei 0:03b5121a232e 3676 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
pcercuei 0:03b5121a232e 3677 return(-1);
pcercuei 0:03b5121a232e 3678 }
pcercuei 0:03b5121a232e 3679 temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
pcercuei 0:03b5121a232e 3680 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3681 if (temp == NULL) {
pcercuei 0:03b5121a232e 3682 xmlXPathErrMemory(NULL, "growing nodeset\n");
pcercuei 0:03b5121a232e 3683 return(-1);
pcercuei 0:03b5121a232e 3684 }
pcercuei 0:03b5121a232e 3685 cur->nodeMax *= 2;
pcercuei 0:03b5121a232e 3686 cur->nodeTab = temp;
pcercuei 0:03b5121a232e 3687 }
pcercuei 0:03b5121a232e 3688 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
pcercuei 0:03b5121a232e 3689 return(0);
pcercuei 0:03b5121a232e 3690 }
pcercuei 0:03b5121a232e 3691
pcercuei 0:03b5121a232e 3692 /**
pcercuei 0:03b5121a232e 3693 * xmlXPathNodeSetAdd:
pcercuei 0:03b5121a232e 3694 * @cur: the initial node set
pcercuei 0:03b5121a232e 3695 * @val: a new xmlNodePtr
pcercuei 0:03b5121a232e 3696 *
pcercuei 0:03b5121a232e 3697 * add a new xmlNodePtr to an existing NodeSet
pcercuei 0:03b5121a232e 3698 *
pcercuei 0:03b5121a232e 3699 * Returns 0 in case of success, and -1 in case of error
pcercuei 0:03b5121a232e 3700 */
pcercuei 0:03b5121a232e 3701 int
pcercuei 0:03b5121a232e 3702 xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
pcercuei 0:03b5121a232e 3703 int i;
pcercuei 0:03b5121a232e 3704
pcercuei 0:03b5121a232e 3705 if ((cur == NULL) || (val == NULL)) return(-1);
pcercuei 0:03b5121a232e 3706
pcercuei 0:03b5121a232e 3707 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
pcercuei 0:03b5121a232e 3708 /*
pcercuei 0:03b5121a232e 3709 * prevent duplcates
pcercuei 0:03b5121a232e 3710 */
pcercuei 0:03b5121a232e 3711 for (i = 0;i < cur->nodeNr;i++)
pcercuei 0:03b5121a232e 3712 if (cur->nodeTab[i] == val) return(0);
pcercuei 0:03b5121a232e 3713
pcercuei 0:03b5121a232e 3714 /*
pcercuei 0:03b5121a232e 3715 * grow the nodeTab if needed
pcercuei 0:03b5121a232e 3716 */
pcercuei 0:03b5121a232e 3717 if (cur->nodeMax == 0) {
pcercuei 0:03b5121a232e 3718 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
pcercuei 0:03b5121a232e 3719 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3720 if (cur->nodeTab == NULL) {
pcercuei 0:03b5121a232e 3721 xmlXPathErrMemory(NULL, "growing nodeset\n");
pcercuei 0:03b5121a232e 3722 return(-1);
pcercuei 0:03b5121a232e 3723 }
pcercuei 0:03b5121a232e 3724 memset(cur->nodeTab, 0 ,
pcercuei 0:03b5121a232e 3725 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3726 cur->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 3727 } else if (cur->nodeNr == cur->nodeMax) {
pcercuei 0:03b5121a232e 3728 xmlNodePtr *temp;
pcercuei 0:03b5121a232e 3729
pcercuei 0:03b5121a232e 3730 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
pcercuei 0:03b5121a232e 3731 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
pcercuei 0:03b5121a232e 3732 return(-1);
pcercuei 0:03b5121a232e 3733 }
pcercuei 0:03b5121a232e 3734 temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
pcercuei 0:03b5121a232e 3735 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3736 if (temp == NULL) {
pcercuei 0:03b5121a232e 3737 xmlXPathErrMemory(NULL, "growing nodeset\n");
pcercuei 0:03b5121a232e 3738 return(-1);
pcercuei 0:03b5121a232e 3739 }
pcercuei 0:03b5121a232e 3740 cur->nodeMax *= 2;
pcercuei 0:03b5121a232e 3741 cur->nodeTab = temp;
pcercuei 0:03b5121a232e 3742 }
pcercuei 0:03b5121a232e 3743 if (val->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 3744 xmlNsPtr ns = (xmlNsPtr) val;
pcercuei 0:03b5121a232e 3745
pcercuei 0:03b5121a232e 3746 cur->nodeTab[cur->nodeNr++] =
pcercuei 0:03b5121a232e 3747 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
pcercuei 0:03b5121a232e 3748 } else
pcercuei 0:03b5121a232e 3749 cur->nodeTab[cur->nodeNr++] = val;
pcercuei 0:03b5121a232e 3750 return(0);
pcercuei 0:03b5121a232e 3751 }
pcercuei 0:03b5121a232e 3752
pcercuei 0:03b5121a232e 3753 /**
pcercuei 0:03b5121a232e 3754 * xmlXPathNodeSetAddUnique:
pcercuei 0:03b5121a232e 3755 * @cur: the initial node set
pcercuei 0:03b5121a232e 3756 * @val: a new xmlNodePtr
pcercuei 0:03b5121a232e 3757 *
pcercuei 0:03b5121a232e 3758 * add a new xmlNodePtr to an existing NodeSet, optimized version
pcercuei 0:03b5121a232e 3759 * when we are sure the node is not already in the set.
pcercuei 0:03b5121a232e 3760 *
pcercuei 0:03b5121a232e 3761 * Returns 0 in case of success and -1 in case of failure
pcercuei 0:03b5121a232e 3762 */
pcercuei 0:03b5121a232e 3763 int
pcercuei 0:03b5121a232e 3764 xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
pcercuei 0:03b5121a232e 3765 if ((cur == NULL) || (val == NULL)) return(-1);
pcercuei 0:03b5121a232e 3766
pcercuei 0:03b5121a232e 3767 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
pcercuei 0:03b5121a232e 3768 /*
pcercuei 0:03b5121a232e 3769 * grow the nodeTab if needed
pcercuei 0:03b5121a232e 3770 */
pcercuei 0:03b5121a232e 3771 if (cur->nodeMax == 0) {
pcercuei 0:03b5121a232e 3772 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
pcercuei 0:03b5121a232e 3773 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3774 if (cur->nodeTab == NULL) {
pcercuei 0:03b5121a232e 3775 xmlXPathErrMemory(NULL, "growing nodeset\n");
pcercuei 0:03b5121a232e 3776 return(-1);
pcercuei 0:03b5121a232e 3777 }
pcercuei 0:03b5121a232e 3778 memset(cur->nodeTab, 0 ,
pcercuei 0:03b5121a232e 3779 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3780 cur->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 3781 } else if (cur->nodeNr == cur->nodeMax) {
pcercuei 0:03b5121a232e 3782 xmlNodePtr *temp;
pcercuei 0:03b5121a232e 3783
pcercuei 0:03b5121a232e 3784 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
pcercuei 0:03b5121a232e 3785 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
pcercuei 0:03b5121a232e 3786 return(-1);
pcercuei 0:03b5121a232e 3787 }
pcercuei 0:03b5121a232e 3788 temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
pcercuei 0:03b5121a232e 3789 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3790 if (temp == NULL) {
pcercuei 0:03b5121a232e 3791 xmlXPathErrMemory(NULL, "growing nodeset\n");
pcercuei 0:03b5121a232e 3792 return(-1);
pcercuei 0:03b5121a232e 3793 }
pcercuei 0:03b5121a232e 3794 cur->nodeTab = temp;
pcercuei 0:03b5121a232e 3795 cur->nodeMax *= 2;
pcercuei 0:03b5121a232e 3796 }
pcercuei 0:03b5121a232e 3797 if (val->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 3798 xmlNsPtr ns = (xmlNsPtr) val;
pcercuei 0:03b5121a232e 3799
pcercuei 0:03b5121a232e 3800 cur->nodeTab[cur->nodeNr++] =
pcercuei 0:03b5121a232e 3801 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
pcercuei 0:03b5121a232e 3802 } else
pcercuei 0:03b5121a232e 3803 cur->nodeTab[cur->nodeNr++] = val;
pcercuei 0:03b5121a232e 3804 return(0);
pcercuei 0:03b5121a232e 3805 }
pcercuei 0:03b5121a232e 3806
pcercuei 0:03b5121a232e 3807 /**
pcercuei 0:03b5121a232e 3808 * xmlXPathNodeSetMerge:
pcercuei 0:03b5121a232e 3809 * @val1: the first NodeSet or NULL
pcercuei 0:03b5121a232e 3810 * @val2: the second NodeSet
pcercuei 0:03b5121a232e 3811 *
pcercuei 0:03b5121a232e 3812 * Merges two nodesets, all nodes from @val2 are added to @val1
pcercuei 0:03b5121a232e 3813 * if @val1 is NULL, a new set is created and copied from @val2
pcercuei 0:03b5121a232e 3814 *
pcercuei 0:03b5121a232e 3815 * Returns @val1 once extended or NULL in case of error.
pcercuei 0:03b5121a232e 3816 */
pcercuei 0:03b5121a232e 3817 xmlNodeSetPtr
pcercuei 0:03b5121a232e 3818 xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
pcercuei 0:03b5121a232e 3819 int i, j, initNr, skip;
pcercuei 0:03b5121a232e 3820 xmlNodePtr n1, n2;
pcercuei 0:03b5121a232e 3821
pcercuei 0:03b5121a232e 3822 if (val2 == NULL) return(val1);
pcercuei 0:03b5121a232e 3823 if (val1 == NULL) {
pcercuei 0:03b5121a232e 3824 val1 = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 3825 if (val1 == NULL)
pcercuei 0:03b5121a232e 3826 return (NULL);
pcercuei 0:03b5121a232e 3827 #if 0
pcercuei 0:03b5121a232e 3828 /*
pcercuei 0:03b5121a232e 3829 * TODO: The optimization won't work in every case, since
pcercuei 0:03b5121a232e 3830 * those nasty namespace nodes need to be added with
pcercuei 0:03b5121a232e 3831 * xmlXPathNodeSetDupNs() to the set; thus a pure
pcercuei 0:03b5121a232e 3832 * memcpy is not possible.
pcercuei 0:03b5121a232e 3833 * If there was a flag on the nodesetval, indicating that
pcercuei 0:03b5121a232e 3834 * some temporary nodes are in, that would be helpfull.
pcercuei 0:03b5121a232e 3835 */
pcercuei 0:03b5121a232e 3836 /*
pcercuei 0:03b5121a232e 3837 * Optimization: Create an equally sized node-set
pcercuei 0:03b5121a232e 3838 * and memcpy the content.
pcercuei 0:03b5121a232e 3839 */
pcercuei 0:03b5121a232e 3840 val1 = xmlXPathNodeSetCreateSize(val2->nodeNr);
pcercuei 0:03b5121a232e 3841 if (val1 == NULL)
pcercuei 0:03b5121a232e 3842 return(NULL);
pcercuei 0:03b5121a232e 3843 if (val2->nodeNr != 0) {
pcercuei 0:03b5121a232e 3844 if (val2->nodeNr == 1)
pcercuei 0:03b5121a232e 3845 *(val1->nodeTab) = *(val2->nodeTab);
pcercuei 0:03b5121a232e 3846 else {
pcercuei 0:03b5121a232e 3847 memcpy(val1->nodeTab, val2->nodeTab,
pcercuei 0:03b5121a232e 3848 val2->nodeNr * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3849 }
pcercuei 0:03b5121a232e 3850 val1->nodeNr = val2->nodeNr;
pcercuei 0:03b5121a232e 3851 }
pcercuei 0:03b5121a232e 3852 return(val1);
pcercuei 0:03b5121a232e 3853 #endif
pcercuei 0:03b5121a232e 3854 }
pcercuei 0:03b5121a232e 3855
pcercuei 0:03b5121a232e 3856 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
pcercuei 0:03b5121a232e 3857 initNr = val1->nodeNr;
pcercuei 0:03b5121a232e 3858
pcercuei 0:03b5121a232e 3859 for (i = 0;i < val2->nodeNr;i++) {
pcercuei 0:03b5121a232e 3860 n2 = val2->nodeTab[i];
pcercuei 0:03b5121a232e 3861 /*
pcercuei 0:03b5121a232e 3862 * check against duplicates
pcercuei 0:03b5121a232e 3863 */
pcercuei 0:03b5121a232e 3864 skip = 0;
pcercuei 0:03b5121a232e 3865 for (j = 0; j < initNr; j++) {
pcercuei 0:03b5121a232e 3866 n1 = val1->nodeTab[j];
pcercuei 0:03b5121a232e 3867 if (n1 == n2) {
pcercuei 0:03b5121a232e 3868 skip = 1;
pcercuei 0:03b5121a232e 3869 break;
pcercuei 0:03b5121a232e 3870 } else if ((n1->type == XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 3871 (n2->type == XML_NAMESPACE_DECL)) {
pcercuei 0:03b5121a232e 3872 if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
pcercuei 0:03b5121a232e 3873 (xmlStrEqual(((xmlNsPtr) n1)->prefix,
pcercuei 0:03b5121a232e 3874 ((xmlNsPtr) n2)->prefix)))
pcercuei 0:03b5121a232e 3875 {
pcercuei 0:03b5121a232e 3876 skip = 1;
pcercuei 0:03b5121a232e 3877 break;
pcercuei 0:03b5121a232e 3878 }
pcercuei 0:03b5121a232e 3879 }
pcercuei 0:03b5121a232e 3880 }
pcercuei 0:03b5121a232e 3881 if (skip)
pcercuei 0:03b5121a232e 3882 continue;
pcercuei 0:03b5121a232e 3883
pcercuei 0:03b5121a232e 3884 /*
pcercuei 0:03b5121a232e 3885 * grow the nodeTab if needed
pcercuei 0:03b5121a232e 3886 */
pcercuei 0:03b5121a232e 3887 if (val1->nodeMax == 0) {
pcercuei 0:03b5121a232e 3888 val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
pcercuei 0:03b5121a232e 3889 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3890 if (val1->nodeTab == NULL) {
pcercuei 0:03b5121a232e 3891 xmlXPathErrMemory(NULL, "merging nodeset\n");
pcercuei 0:03b5121a232e 3892 return(NULL);
pcercuei 0:03b5121a232e 3893 }
pcercuei 0:03b5121a232e 3894 memset(val1->nodeTab, 0 ,
pcercuei 0:03b5121a232e 3895 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3896 val1->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 3897 } else if (val1->nodeNr == val1->nodeMax) {
pcercuei 0:03b5121a232e 3898 xmlNodePtr *temp;
pcercuei 0:03b5121a232e 3899
pcercuei 0:03b5121a232e 3900 if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
pcercuei 0:03b5121a232e 3901 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
pcercuei 0:03b5121a232e 3902 return(NULL);
pcercuei 0:03b5121a232e 3903 }
pcercuei 0:03b5121a232e 3904 temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
pcercuei 0:03b5121a232e 3905 sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3906 if (temp == NULL) {
pcercuei 0:03b5121a232e 3907 xmlXPathErrMemory(NULL, "merging nodeset\n");
pcercuei 0:03b5121a232e 3908 return(NULL);
pcercuei 0:03b5121a232e 3909 }
pcercuei 0:03b5121a232e 3910 val1->nodeTab = temp;
pcercuei 0:03b5121a232e 3911 val1->nodeMax *= 2;
pcercuei 0:03b5121a232e 3912 }
pcercuei 0:03b5121a232e 3913 if (n2->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 3914 xmlNsPtr ns = (xmlNsPtr) n2;
pcercuei 0:03b5121a232e 3915
pcercuei 0:03b5121a232e 3916 val1->nodeTab[val1->nodeNr++] =
pcercuei 0:03b5121a232e 3917 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
pcercuei 0:03b5121a232e 3918 } else
pcercuei 0:03b5121a232e 3919 val1->nodeTab[val1->nodeNr++] = n2;
pcercuei 0:03b5121a232e 3920 }
pcercuei 0:03b5121a232e 3921
pcercuei 0:03b5121a232e 3922 return(val1);
pcercuei 0:03b5121a232e 3923 }
pcercuei 0:03b5121a232e 3924
pcercuei 0:03b5121a232e 3925
pcercuei 0:03b5121a232e 3926 /**
pcercuei 0:03b5121a232e 3927 * xmlXPathNodeSetMergeAndClear:
pcercuei 0:03b5121a232e 3928 * @set1: the first NodeSet or NULL
pcercuei 0:03b5121a232e 3929 * @set2: the second NodeSet
pcercuei 0:03b5121a232e 3930 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes
pcercuei 0:03b5121a232e 3931 *
pcercuei 0:03b5121a232e 3932 * Merges two nodesets, all nodes from @set2 are added to @set1
pcercuei 0:03b5121a232e 3933 * if @set1 is NULL, a new set is created and copied from @set2.
pcercuei 0:03b5121a232e 3934 * Checks for duplicate nodes. Clears set2.
pcercuei 0:03b5121a232e 3935 *
pcercuei 0:03b5121a232e 3936 * Returns @set1 once extended or NULL in case of error.
pcercuei 0:03b5121a232e 3937 */
pcercuei 0:03b5121a232e 3938 static xmlNodeSetPtr
pcercuei 0:03b5121a232e 3939 xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
pcercuei 0:03b5121a232e 3940 int hasNullEntries)
pcercuei 0:03b5121a232e 3941 {
pcercuei 0:03b5121a232e 3942 if ((set1 == NULL) && (hasNullEntries == 0)) {
pcercuei 0:03b5121a232e 3943 /*
pcercuei 0:03b5121a232e 3944 * Note that doing a memcpy of the list, namespace nodes are
pcercuei 0:03b5121a232e 3945 * just assigned to set1, since set2 is cleared anyway.
pcercuei 0:03b5121a232e 3946 */
pcercuei 0:03b5121a232e 3947 set1 = xmlXPathNodeSetCreateSize(set2->nodeNr);
pcercuei 0:03b5121a232e 3948 if (set1 == NULL)
pcercuei 0:03b5121a232e 3949 return(NULL);
pcercuei 0:03b5121a232e 3950 if (set2->nodeNr != 0) {
pcercuei 0:03b5121a232e 3951 memcpy(set1->nodeTab, set2->nodeTab,
pcercuei 0:03b5121a232e 3952 set2->nodeNr * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 3953 set1->nodeNr = set2->nodeNr;
pcercuei 0:03b5121a232e 3954 }
pcercuei 0:03b5121a232e 3955 } else {
pcercuei 0:03b5121a232e 3956 int i, j, initNbSet1;
pcercuei 0:03b5121a232e 3957 xmlNodePtr n1, n2;
pcercuei 0:03b5121a232e 3958
pcercuei 0:03b5121a232e 3959 if (set1 == NULL)
pcercuei 0:03b5121a232e 3960 set1 = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 3961 if (set1 == NULL)
pcercuei 0:03b5121a232e 3962 return (NULL);
pcercuei 0:03b5121a232e 3963
pcercuei 0:03b5121a232e 3964 initNbSet1 = set1->nodeNr;
pcercuei 0:03b5121a232e 3965 for (i = 0;i < set2->nodeNr;i++) {
pcercuei 0:03b5121a232e 3966 n2 = set2->nodeTab[i];
pcercuei 0:03b5121a232e 3967 /*
pcercuei 0:03b5121a232e 3968 * Skip NULLed entries.
pcercuei 0:03b5121a232e 3969 */
pcercuei 0:03b5121a232e 3970 if (n2 == NULL)
pcercuei 0:03b5121a232e 3971 continue;
pcercuei 0:03b5121a232e 3972 /*
pcercuei 0:03b5121a232e 3973 * Skip duplicates.
pcercuei 0:03b5121a232e 3974 */
pcercuei 0:03b5121a232e 3975 for (j = 0; j < initNbSet1; j++) {
pcercuei 0:03b5121a232e 3976 n1 = set1->nodeTab[j];
pcercuei 0:03b5121a232e 3977 if (n1 == n2) {
pcercuei 0:03b5121a232e 3978 goto skip_node;
pcercuei 0:03b5121a232e 3979 } else if ((n1->type == XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 3980 (n2->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 3981 {
pcercuei 0:03b5121a232e 3982 if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
pcercuei 0:03b5121a232e 3983 (xmlStrEqual(((xmlNsPtr) n1)->prefix,
pcercuei 0:03b5121a232e 3984 ((xmlNsPtr) n2)->prefix)))
pcercuei 0:03b5121a232e 3985 {
pcercuei 0:03b5121a232e 3986 /*
pcercuei 0:03b5121a232e 3987 * Free the namespace node.
pcercuei 0:03b5121a232e 3988 */
pcercuei 0:03b5121a232e 3989 set2->nodeTab[i] = NULL;
pcercuei 0:03b5121a232e 3990 xmlXPathNodeSetFreeNs((xmlNsPtr) n2);
pcercuei 0:03b5121a232e 3991 goto skip_node;
pcercuei 0:03b5121a232e 3992 }
pcercuei 0:03b5121a232e 3993 }
pcercuei 0:03b5121a232e 3994 }
pcercuei 0:03b5121a232e 3995 /*
pcercuei 0:03b5121a232e 3996 * grow the nodeTab if needed
pcercuei 0:03b5121a232e 3997 */
pcercuei 0:03b5121a232e 3998 if (set1->nodeMax == 0) {
pcercuei 0:03b5121a232e 3999 set1->nodeTab = (xmlNodePtr *) xmlMalloc(
pcercuei 0:03b5121a232e 4000 XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4001 if (set1->nodeTab == NULL) {
pcercuei 0:03b5121a232e 4002 xmlXPathErrMemory(NULL, "merging nodeset\n");
pcercuei 0:03b5121a232e 4003 return(NULL);
pcercuei 0:03b5121a232e 4004 }
pcercuei 0:03b5121a232e 4005 memset(set1->nodeTab, 0,
pcercuei 0:03b5121a232e 4006 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4007 set1->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 4008 } else if (set1->nodeNr >= set1->nodeMax) {
pcercuei 0:03b5121a232e 4009 xmlNodePtr *temp;
pcercuei 0:03b5121a232e 4010
pcercuei 0:03b5121a232e 4011 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
pcercuei 0:03b5121a232e 4012 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
pcercuei 0:03b5121a232e 4013 return(NULL);
pcercuei 0:03b5121a232e 4014 }
pcercuei 0:03b5121a232e 4015 temp = (xmlNodePtr *) xmlRealloc(
pcercuei 0:03b5121a232e 4016 set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4017 if (temp == NULL) {
pcercuei 0:03b5121a232e 4018 xmlXPathErrMemory(NULL, "merging nodeset\n");
pcercuei 0:03b5121a232e 4019 return(NULL);
pcercuei 0:03b5121a232e 4020 }
pcercuei 0:03b5121a232e 4021 set1->nodeTab = temp;
pcercuei 0:03b5121a232e 4022 set1->nodeMax *= 2;
pcercuei 0:03b5121a232e 4023 }
pcercuei 0:03b5121a232e 4024 if (n2->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 4025 xmlNsPtr ns = (xmlNsPtr) n2;
pcercuei 0:03b5121a232e 4026
pcercuei 0:03b5121a232e 4027 set1->nodeTab[set1->nodeNr++] =
pcercuei 0:03b5121a232e 4028 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
pcercuei 0:03b5121a232e 4029 } else
pcercuei 0:03b5121a232e 4030 set1->nodeTab[set1->nodeNr++] = n2;
pcercuei 0:03b5121a232e 4031 skip_node:
pcercuei 0:03b5121a232e 4032 {}
pcercuei 0:03b5121a232e 4033 }
pcercuei 0:03b5121a232e 4034 }
pcercuei 0:03b5121a232e 4035 set2->nodeNr = 0;
pcercuei 0:03b5121a232e 4036 return(set1);
pcercuei 0:03b5121a232e 4037 }
pcercuei 0:03b5121a232e 4038
pcercuei 0:03b5121a232e 4039 /**
pcercuei 0:03b5121a232e 4040 * xmlXPathNodeSetMergeAndClearNoDupls:
pcercuei 0:03b5121a232e 4041 * @set1: the first NodeSet or NULL
pcercuei 0:03b5121a232e 4042 * @set2: the second NodeSet
pcercuei 0:03b5121a232e 4043 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes
pcercuei 0:03b5121a232e 4044 *
pcercuei 0:03b5121a232e 4045 * Merges two nodesets, all nodes from @set2 are added to @set1
pcercuei 0:03b5121a232e 4046 * if @set1 is NULL, a new set is created and copied from @set2.
pcercuei 0:03b5121a232e 4047 * Doesn't chack for duplicate nodes. Clears set2.
pcercuei 0:03b5121a232e 4048 *
pcercuei 0:03b5121a232e 4049 * Returns @set1 once extended or NULL in case of error.
pcercuei 0:03b5121a232e 4050 */
pcercuei 0:03b5121a232e 4051 static xmlNodeSetPtr
pcercuei 0:03b5121a232e 4052 xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
pcercuei 0:03b5121a232e 4053 int hasNullEntries)
pcercuei 0:03b5121a232e 4054 {
pcercuei 0:03b5121a232e 4055 if (set2 == NULL)
pcercuei 0:03b5121a232e 4056 return(set1);
pcercuei 0:03b5121a232e 4057 if ((set1 == NULL) && (hasNullEntries == 0)) {
pcercuei 0:03b5121a232e 4058 /*
pcercuei 0:03b5121a232e 4059 * Note that doing a memcpy of the list, namespace nodes are
pcercuei 0:03b5121a232e 4060 * just assigned to set1, since set2 is cleared anyway.
pcercuei 0:03b5121a232e 4061 */
pcercuei 0:03b5121a232e 4062 set1 = xmlXPathNodeSetCreateSize(set2->nodeNr);
pcercuei 0:03b5121a232e 4063 if (set1 == NULL)
pcercuei 0:03b5121a232e 4064 return(NULL);
pcercuei 0:03b5121a232e 4065 if (set2->nodeNr != 0) {
pcercuei 0:03b5121a232e 4066 memcpy(set1->nodeTab, set2->nodeTab,
pcercuei 0:03b5121a232e 4067 set2->nodeNr * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4068 set1->nodeNr = set2->nodeNr;
pcercuei 0:03b5121a232e 4069 }
pcercuei 0:03b5121a232e 4070 } else {
pcercuei 0:03b5121a232e 4071 int i;
pcercuei 0:03b5121a232e 4072 xmlNodePtr n2;
pcercuei 0:03b5121a232e 4073
pcercuei 0:03b5121a232e 4074 if (set1 == NULL)
pcercuei 0:03b5121a232e 4075 set1 = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 4076 if (set1 == NULL)
pcercuei 0:03b5121a232e 4077 return (NULL);
pcercuei 0:03b5121a232e 4078
pcercuei 0:03b5121a232e 4079 for (i = 0;i < set2->nodeNr;i++) {
pcercuei 0:03b5121a232e 4080 n2 = set2->nodeTab[i];
pcercuei 0:03b5121a232e 4081 /*
pcercuei 0:03b5121a232e 4082 * Skip NULLed entries.
pcercuei 0:03b5121a232e 4083 */
pcercuei 0:03b5121a232e 4084 if (n2 == NULL)
pcercuei 0:03b5121a232e 4085 continue;
pcercuei 0:03b5121a232e 4086 if (set1->nodeMax == 0) {
pcercuei 0:03b5121a232e 4087 set1->nodeTab = (xmlNodePtr *) xmlMalloc(
pcercuei 0:03b5121a232e 4088 XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4089 if (set1->nodeTab == NULL) {
pcercuei 0:03b5121a232e 4090 xmlXPathErrMemory(NULL, "merging nodeset\n");
pcercuei 0:03b5121a232e 4091 return(NULL);
pcercuei 0:03b5121a232e 4092 }
pcercuei 0:03b5121a232e 4093 memset(set1->nodeTab, 0,
pcercuei 0:03b5121a232e 4094 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4095 set1->nodeMax = XML_NODESET_DEFAULT;
pcercuei 0:03b5121a232e 4096 } else if (set1->nodeNr >= set1->nodeMax) {
pcercuei 0:03b5121a232e 4097 xmlNodePtr *temp;
pcercuei 0:03b5121a232e 4098
pcercuei 0:03b5121a232e 4099 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
pcercuei 0:03b5121a232e 4100 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
pcercuei 0:03b5121a232e 4101 return(NULL);
pcercuei 0:03b5121a232e 4102 }
pcercuei 0:03b5121a232e 4103 temp = (xmlNodePtr *) xmlRealloc(
pcercuei 0:03b5121a232e 4104 set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
pcercuei 0:03b5121a232e 4105 if (temp == NULL) {
pcercuei 0:03b5121a232e 4106 xmlXPathErrMemory(NULL, "merging nodeset\n");
pcercuei 0:03b5121a232e 4107 return(NULL);
pcercuei 0:03b5121a232e 4108 }
pcercuei 0:03b5121a232e 4109 set1->nodeTab = temp;
pcercuei 0:03b5121a232e 4110 set1->nodeMax *= 2;
pcercuei 0:03b5121a232e 4111 }
pcercuei 0:03b5121a232e 4112 set1->nodeTab[set1->nodeNr++] = n2;
pcercuei 0:03b5121a232e 4113 }
pcercuei 0:03b5121a232e 4114 }
pcercuei 0:03b5121a232e 4115 set2->nodeNr = 0;
pcercuei 0:03b5121a232e 4116 return(set1);
pcercuei 0:03b5121a232e 4117 }
pcercuei 0:03b5121a232e 4118
pcercuei 0:03b5121a232e 4119 /**
pcercuei 0:03b5121a232e 4120 * xmlXPathNodeSetDel:
pcercuei 0:03b5121a232e 4121 * @cur: the initial node set
pcercuei 0:03b5121a232e 4122 * @val: an xmlNodePtr
pcercuei 0:03b5121a232e 4123 *
pcercuei 0:03b5121a232e 4124 * Removes an xmlNodePtr from an existing NodeSet
pcercuei 0:03b5121a232e 4125 */
pcercuei 0:03b5121a232e 4126 void
pcercuei 0:03b5121a232e 4127 xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
pcercuei 0:03b5121a232e 4128 int i;
pcercuei 0:03b5121a232e 4129
pcercuei 0:03b5121a232e 4130 if (cur == NULL) return;
pcercuei 0:03b5121a232e 4131 if (val == NULL) return;
pcercuei 0:03b5121a232e 4132
pcercuei 0:03b5121a232e 4133 /*
pcercuei 0:03b5121a232e 4134 * find node in nodeTab
pcercuei 0:03b5121a232e 4135 */
pcercuei 0:03b5121a232e 4136 for (i = 0;i < cur->nodeNr;i++)
pcercuei 0:03b5121a232e 4137 if (cur->nodeTab[i] == val) break;
pcercuei 0:03b5121a232e 4138
pcercuei 0:03b5121a232e 4139 if (i >= cur->nodeNr) { /* not found */
pcercuei 0:03b5121a232e 4140 #ifdef DEBUG
pcercuei 0:03b5121a232e 4141 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 4142 "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
pcercuei 0:03b5121a232e 4143 val->name);
pcercuei 0:03b5121a232e 4144 #endif
pcercuei 0:03b5121a232e 4145 return;
pcercuei 0:03b5121a232e 4146 }
pcercuei 0:03b5121a232e 4147 if ((cur->nodeTab[i] != NULL) &&
pcercuei 0:03b5121a232e 4148 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 4149 xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
pcercuei 0:03b5121a232e 4150 cur->nodeNr--;
pcercuei 0:03b5121a232e 4151 for (;i < cur->nodeNr;i++)
pcercuei 0:03b5121a232e 4152 cur->nodeTab[i] = cur->nodeTab[i + 1];
pcercuei 0:03b5121a232e 4153 cur->nodeTab[cur->nodeNr] = NULL;
pcercuei 0:03b5121a232e 4154 }
pcercuei 0:03b5121a232e 4155
pcercuei 0:03b5121a232e 4156 /**
pcercuei 0:03b5121a232e 4157 * xmlXPathNodeSetRemove:
pcercuei 0:03b5121a232e 4158 * @cur: the initial node set
pcercuei 0:03b5121a232e 4159 * @val: the index to remove
pcercuei 0:03b5121a232e 4160 *
pcercuei 0:03b5121a232e 4161 * Removes an entry from an existing NodeSet list.
pcercuei 0:03b5121a232e 4162 */
pcercuei 0:03b5121a232e 4163 void
pcercuei 0:03b5121a232e 4164 xmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
pcercuei 0:03b5121a232e 4165 if (cur == NULL) return;
pcercuei 0:03b5121a232e 4166 if (val >= cur->nodeNr) return;
pcercuei 0:03b5121a232e 4167 if ((cur->nodeTab[val] != NULL) &&
pcercuei 0:03b5121a232e 4168 (cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 4169 xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
pcercuei 0:03b5121a232e 4170 cur->nodeNr--;
pcercuei 0:03b5121a232e 4171 for (;val < cur->nodeNr;val++)
pcercuei 0:03b5121a232e 4172 cur->nodeTab[val] = cur->nodeTab[val + 1];
pcercuei 0:03b5121a232e 4173 cur->nodeTab[cur->nodeNr] = NULL;
pcercuei 0:03b5121a232e 4174 }
pcercuei 0:03b5121a232e 4175
pcercuei 0:03b5121a232e 4176 /**
pcercuei 0:03b5121a232e 4177 * xmlXPathFreeNodeSet:
pcercuei 0:03b5121a232e 4178 * @obj: the xmlNodeSetPtr to free
pcercuei 0:03b5121a232e 4179 *
pcercuei 0:03b5121a232e 4180 * Free the NodeSet compound (not the actual nodes !).
pcercuei 0:03b5121a232e 4181 */
pcercuei 0:03b5121a232e 4182 void
pcercuei 0:03b5121a232e 4183 xmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
pcercuei 0:03b5121a232e 4184 if (obj == NULL) return;
pcercuei 0:03b5121a232e 4185 if (obj->nodeTab != NULL) {
pcercuei 0:03b5121a232e 4186 int i;
pcercuei 0:03b5121a232e 4187
pcercuei 0:03b5121a232e 4188 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
pcercuei 0:03b5121a232e 4189 for (i = 0;i < obj->nodeNr;i++)
pcercuei 0:03b5121a232e 4190 if ((obj->nodeTab[i] != NULL) &&
pcercuei 0:03b5121a232e 4191 (obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 4192 xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
pcercuei 0:03b5121a232e 4193 xmlFree(obj->nodeTab);
pcercuei 0:03b5121a232e 4194 }
pcercuei 0:03b5121a232e 4195 xmlFree(obj);
pcercuei 0:03b5121a232e 4196 }
pcercuei 0:03b5121a232e 4197
pcercuei 0:03b5121a232e 4198 /**
pcercuei 0:03b5121a232e 4199 * xmlXPathNodeSetClear:
pcercuei 0:03b5121a232e 4200 * @set: the node set to clear
pcercuei 0:03b5121a232e 4201 *
pcercuei 0:03b5121a232e 4202 * Clears the list from all temporary XPath objects (e.g. namespace nodes
pcercuei 0:03b5121a232e 4203 * are feed), but does *not* free the list itself. Sets the length of the
pcercuei 0:03b5121a232e 4204 * list to 0.
pcercuei 0:03b5121a232e 4205 */
pcercuei 0:03b5121a232e 4206 static void
pcercuei 0:03b5121a232e 4207 xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes)
pcercuei 0:03b5121a232e 4208 {
pcercuei 0:03b5121a232e 4209 if ((set == NULL) || (set->nodeNr <= 0))
pcercuei 0:03b5121a232e 4210 return;
pcercuei 0:03b5121a232e 4211 else if (hasNsNodes) {
pcercuei 0:03b5121a232e 4212 int i;
pcercuei 0:03b5121a232e 4213 xmlNodePtr node;
pcercuei 0:03b5121a232e 4214
pcercuei 0:03b5121a232e 4215 for (i = 0; i < set->nodeNr; i++) {
pcercuei 0:03b5121a232e 4216 node = set->nodeTab[i];
pcercuei 0:03b5121a232e 4217 if ((node != NULL) &&
pcercuei 0:03b5121a232e 4218 (node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 4219 xmlXPathNodeSetFreeNs((xmlNsPtr) node);
pcercuei 0:03b5121a232e 4220 }
pcercuei 0:03b5121a232e 4221 }
pcercuei 0:03b5121a232e 4222 set->nodeNr = 0;
pcercuei 0:03b5121a232e 4223 }
pcercuei 0:03b5121a232e 4224
pcercuei 0:03b5121a232e 4225 /**
pcercuei 0:03b5121a232e 4226 * xmlXPathNodeSetClearFromPos:
pcercuei 0:03b5121a232e 4227 * @set: the node set to be cleared
pcercuei 0:03b5121a232e 4228 * @pos: the start position to clear from
pcercuei 0:03b5121a232e 4229 *
pcercuei 0:03b5121a232e 4230 * Clears the list from temporary XPath objects (e.g. namespace nodes
pcercuei 0:03b5121a232e 4231 * are feed) starting with the entry at @pos, but does *not* free the list
pcercuei 0:03b5121a232e 4232 * itself. Sets the length of the list to @pos.
pcercuei 0:03b5121a232e 4233 */
pcercuei 0:03b5121a232e 4234 static void
pcercuei 0:03b5121a232e 4235 xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes)
pcercuei 0:03b5121a232e 4236 {
pcercuei 0:03b5121a232e 4237 if ((set == NULL) || (set->nodeNr <= 0) || (pos >= set->nodeNr))
pcercuei 0:03b5121a232e 4238 return;
pcercuei 0:03b5121a232e 4239 else if ((hasNsNodes)) {
pcercuei 0:03b5121a232e 4240 int i;
pcercuei 0:03b5121a232e 4241 xmlNodePtr node;
pcercuei 0:03b5121a232e 4242
pcercuei 0:03b5121a232e 4243 for (i = pos; i < set->nodeNr; i++) {
pcercuei 0:03b5121a232e 4244 node = set->nodeTab[i];
pcercuei 0:03b5121a232e 4245 if ((node != NULL) &&
pcercuei 0:03b5121a232e 4246 (node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 4247 xmlXPathNodeSetFreeNs((xmlNsPtr) node);
pcercuei 0:03b5121a232e 4248 }
pcercuei 0:03b5121a232e 4249 }
pcercuei 0:03b5121a232e 4250 set->nodeNr = pos;
pcercuei 0:03b5121a232e 4251 }
pcercuei 0:03b5121a232e 4252
pcercuei 0:03b5121a232e 4253 /**
pcercuei 0:03b5121a232e 4254 * xmlXPathFreeValueTree:
pcercuei 0:03b5121a232e 4255 * @obj: the xmlNodeSetPtr to free
pcercuei 0:03b5121a232e 4256 *
pcercuei 0:03b5121a232e 4257 * Free the NodeSet compound and the actual tree, this is different
pcercuei 0:03b5121a232e 4258 * from xmlXPathFreeNodeSet()
pcercuei 0:03b5121a232e 4259 */
pcercuei 0:03b5121a232e 4260 static void
pcercuei 0:03b5121a232e 4261 xmlXPathFreeValueTree(xmlNodeSetPtr obj) {
pcercuei 0:03b5121a232e 4262 int i;
pcercuei 0:03b5121a232e 4263
pcercuei 0:03b5121a232e 4264 if (obj == NULL) return;
pcercuei 0:03b5121a232e 4265
pcercuei 0:03b5121a232e 4266 if (obj->nodeTab != NULL) {
pcercuei 0:03b5121a232e 4267 for (i = 0;i < obj->nodeNr;i++) {
pcercuei 0:03b5121a232e 4268 if (obj->nodeTab[i] != NULL) {
pcercuei 0:03b5121a232e 4269 if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 4270 xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
pcercuei 0:03b5121a232e 4271 } else {
pcercuei 0:03b5121a232e 4272 xmlFreeNodeList(obj->nodeTab[i]);
pcercuei 0:03b5121a232e 4273 }
pcercuei 0:03b5121a232e 4274 }
pcercuei 0:03b5121a232e 4275 }
pcercuei 0:03b5121a232e 4276 xmlFree(obj->nodeTab);
pcercuei 0:03b5121a232e 4277 }
pcercuei 0:03b5121a232e 4278 xmlFree(obj);
pcercuei 0:03b5121a232e 4279 }
pcercuei 0:03b5121a232e 4280
pcercuei 0:03b5121a232e 4281 #if defined(DEBUG) || defined(DEBUG_STEP)
pcercuei 0:03b5121a232e 4282 /**
pcercuei 0:03b5121a232e 4283 * xmlGenericErrorContextNodeSet:
pcercuei 0:03b5121a232e 4284 * @output: a FILE * for the output
pcercuei 0:03b5121a232e 4285 * @obj: the xmlNodeSetPtr to display
pcercuei 0:03b5121a232e 4286 *
pcercuei 0:03b5121a232e 4287 * Quick display of a NodeSet
pcercuei 0:03b5121a232e 4288 */
pcercuei 0:03b5121a232e 4289 void
pcercuei 0:03b5121a232e 4290 xmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
pcercuei 0:03b5121a232e 4291 int i;
pcercuei 0:03b5121a232e 4292
pcercuei 0:03b5121a232e 4293 if (output == NULL) output = xmlGenericErrorContext;
pcercuei 0:03b5121a232e 4294 if (obj == NULL) {
pcercuei 0:03b5121a232e 4295 fprintf(output, "NodeSet == NULL !\n");
pcercuei 0:03b5121a232e 4296 return;
pcercuei 0:03b5121a232e 4297 }
pcercuei 0:03b5121a232e 4298 if (obj->nodeNr == 0) {
pcercuei 0:03b5121a232e 4299 fprintf(output, "NodeSet is empty\n");
pcercuei 0:03b5121a232e 4300 return;
pcercuei 0:03b5121a232e 4301 }
pcercuei 0:03b5121a232e 4302 if (obj->nodeTab == NULL) {
pcercuei 0:03b5121a232e 4303 fprintf(output, " nodeTab == NULL !\n");
pcercuei 0:03b5121a232e 4304 return;
pcercuei 0:03b5121a232e 4305 }
pcercuei 0:03b5121a232e 4306 for (i = 0; i < obj->nodeNr; i++) {
pcercuei 0:03b5121a232e 4307 if (obj->nodeTab[i] == NULL) {
pcercuei 0:03b5121a232e 4308 fprintf(output, " NULL !\n");
pcercuei 0:03b5121a232e 4309 return;
pcercuei 0:03b5121a232e 4310 }
pcercuei 0:03b5121a232e 4311 if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 4312 (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
pcercuei 0:03b5121a232e 4313 fprintf(output, " /");
pcercuei 0:03b5121a232e 4314 else if (obj->nodeTab[i]->name == NULL)
pcercuei 0:03b5121a232e 4315 fprintf(output, " noname!");
pcercuei 0:03b5121a232e 4316 else fprintf(output, " %s", obj->nodeTab[i]->name);
pcercuei 0:03b5121a232e 4317 }
pcercuei 0:03b5121a232e 4318 fprintf(output, "\n");
pcercuei 0:03b5121a232e 4319 }
pcercuei 0:03b5121a232e 4320 #endif
pcercuei 0:03b5121a232e 4321
pcercuei 0:03b5121a232e 4322 /**
pcercuei 0:03b5121a232e 4323 * xmlXPathNewNodeSet:
pcercuei 0:03b5121a232e 4324 * @val: the NodePtr value
pcercuei 0:03b5121a232e 4325 *
pcercuei 0:03b5121a232e 4326 * Create a new xmlXPathObjectPtr of type NodeSet and initialize
pcercuei 0:03b5121a232e 4327 * it with the single Node @val
pcercuei 0:03b5121a232e 4328 *
pcercuei 0:03b5121a232e 4329 * Returns the newly created object.
pcercuei 0:03b5121a232e 4330 */
pcercuei 0:03b5121a232e 4331 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 4332 xmlXPathNewNodeSet(xmlNodePtr val) {
pcercuei 0:03b5121a232e 4333 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 4334
pcercuei 0:03b5121a232e 4335 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 4336 if (ret == NULL) {
pcercuei 0:03b5121a232e 4337 xmlXPathErrMemory(NULL, "creating nodeset\n");
pcercuei 0:03b5121a232e 4338 return(NULL);
pcercuei 0:03b5121a232e 4339 }
pcercuei 0:03b5121a232e 4340 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 4341 ret->type = XPATH_NODESET;
pcercuei 0:03b5121a232e 4342 ret->boolval = 0;
pcercuei 0:03b5121a232e 4343 ret->nodesetval = xmlXPathNodeSetCreate(val);
pcercuei 0:03b5121a232e 4344 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
pcercuei 0:03b5121a232e 4345 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 4346 xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET);
pcercuei 0:03b5121a232e 4347 #endif
pcercuei 0:03b5121a232e 4348 return(ret);
pcercuei 0:03b5121a232e 4349 }
pcercuei 0:03b5121a232e 4350
pcercuei 0:03b5121a232e 4351 /**
pcercuei 0:03b5121a232e 4352 * xmlXPathNewValueTree:
pcercuei 0:03b5121a232e 4353 * @val: the NodePtr value
pcercuei 0:03b5121a232e 4354 *
pcercuei 0:03b5121a232e 4355 * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
pcercuei 0:03b5121a232e 4356 * it with the tree root @val
pcercuei 0:03b5121a232e 4357 *
pcercuei 0:03b5121a232e 4358 * Returns the newly created object.
pcercuei 0:03b5121a232e 4359 */
pcercuei 0:03b5121a232e 4360 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 4361 xmlXPathNewValueTree(xmlNodePtr val) {
pcercuei 0:03b5121a232e 4362 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 4363
pcercuei 0:03b5121a232e 4364 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 4365 if (ret == NULL) {
pcercuei 0:03b5121a232e 4366 xmlXPathErrMemory(NULL, "creating result value tree\n");
pcercuei 0:03b5121a232e 4367 return(NULL);
pcercuei 0:03b5121a232e 4368 }
pcercuei 0:03b5121a232e 4369 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 4370 ret->type = XPATH_XSLT_TREE;
pcercuei 0:03b5121a232e 4371 ret->boolval = 1;
pcercuei 0:03b5121a232e 4372 ret->user = (void *) val;
pcercuei 0:03b5121a232e 4373 ret->nodesetval = xmlXPathNodeSetCreate(val);
pcercuei 0:03b5121a232e 4374 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 4375 xmlXPathDebugObjUsageRequested(NULL, XPATH_XSLT_TREE);
pcercuei 0:03b5121a232e 4376 #endif
pcercuei 0:03b5121a232e 4377 return(ret);
pcercuei 0:03b5121a232e 4378 }
pcercuei 0:03b5121a232e 4379
pcercuei 0:03b5121a232e 4380 /**
pcercuei 0:03b5121a232e 4381 * xmlXPathNewNodeSetList:
pcercuei 0:03b5121a232e 4382 * @val: an existing NodeSet
pcercuei 0:03b5121a232e 4383 *
pcercuei 0:03b5121a232e 4384 * Create a new xmlXPathObjectPtr of type NodeSet and initialize
pcercuei 0:03b5121a232e 4385 * it with the Nodeset @val
pcercuei 0:03b5121a232e 4386 *
pcercuei 0:03b5121a232e 4387 * Returns the newly created object.
pcercuei 0:03b5121a232e 4388 */
pcercuei 0:03b5121a232e 4389 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 4390 xmlXPathNewNodeSetList(xmlNodeSetPtr val)
pcercuei 0:03b5121a232e 4391 {
pcercuei 0:03b5121a232e 4392 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 4393 int i;
pcercuei 0:03b5121a232e 4394
pcercuei 0:03b5121a232e 4395 if (val == NULL)
pcercuei 0:03b5121a232e 4396 ret = NULL;
pcercuei 0:03b5121a232e 4397 else if (val->nodeTab == NULL)
pcercuei 0:03b5121a232e 4398 ret = xmlXPathNewNodeSet(NULL);
pcercuei 0:03b5121a232e 4399 else {
pcercuei 0:03b5121a232e 4400 ret = xmlXPathNewNodeSet(val->nodeTab[0]);
pcercuei 0:03b5121a232e 4401 if (ret) {
pcercuei 0:03b5121a232e 4402 for (i = 1; i < val->nodeNr; ++i) {
pcercuei 0:03b5121a232e 4403 if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
pcercuei 0:03b5121a232e 4404 < 0) break;
pcercuei 0:03b5121a232e 4405 }
pcercuei 0:03b5121a232e 4406 }
pcercuei 0:03b5121a232e 4407 }
pcercuei 0:03b5121a232e 4408
pcercuei 0:03b5121a232e 4409 return (ret);
pcercuei 0:03b5121a232e 4410 }
pcercuei 0:03b5121a232e 4411
pcercuei 0:03b5121a232e 4412 /**
pcercuei 0:03b5121a232e 4413 * xmlXPathWrapNodeSet:
pcercuei 0:03b5121a232e 4414 * @val: the NodePtr value
pcercuei 0:03b5121a232e 4415 *
pcercuei 0:03b5121a232e 4416 * Wrap the Nodeset @val in a new xmlXPathObjectPtr
pcercuei 0:03b5121a232e 4417 *
pcercuei 0:03b5121a232e 4418 * Returns the newly created object.
pcercuei 0:03b5121a232e 4419 */
pcercuei 0:03b5121a232e 4420 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 4421 xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
pcercuei 0:03b5121a232e 4422 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 4423
pcercuei 0:03b5121a232e 4424 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 4425 if (ret == NULL) {
pcercuei 0:03b5121a232e 4426 xmlXPathErrMemory(NULL, "creating node set object\n");
pcercuei 0:03b5121a232e 4427 return(NULL);
pcercuei 0:03b5121a232e 4428 }
pcercuei 0:03b5121a232e 4429 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 4430 ret->type = XPATH_NODESET;
pcercuei 0:03b5121a232e 4431 ret->nodesetval = val;
pcercuei 0:03b5121a232e 4432 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 4433 xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET);
pcercuei 0:03b5121a232e 4434 #endif
pcercuei 0:03b5121a232e 4435 return(ret);
pcercuei 0:03b5121a232e 4436 }
pcercuei 0:03b5121a232e 4437
pcercuei 0:03b5121a232e 4438 /**
pcercuei 0:03b5121a232e 4439 * xmlXPathFreeNodeSetList:
pcercuei 0:03b5121a232e 4440 * @obj: an existing NodeSetList object
pcercuei 0:03b5121a232e 4441 *
pcercuei 0:03b5121a232e 4442 * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
pcercuei 0:03b5121a232e 4443 * the list contrary to xmlXPathFreeObject().
pcercuei 0:03b5121a232e 4444 */
pcercuei 0:03b5121a232e 4445 void
pcercuei 0:03b5121a232e 4446 xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
pcercuei 0:03b5121a232e 4447 if (obj == NULL) return;
pcercuei 0:03b5121a232e 4448 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 4449 xmlXPathDebugObjUsageReleased(NULL, obj->type);
pcercuei 0:03b5121a232e 4450 #endif
pcercuei 0:03b5121a232e 4451 xmlFree(obj);
pcercuei 0:03b5121a232e 4452 }
pcercuei 0:03b5121a232e 4453
pcercuei 0:03b5121a232e 4454 /**
pcercuei 0:03b5121a232e 4455 * xmlXPathDifference:
pcercuei 0:03b5121a232e 4456 * @nodes1: a node-set
pcercuei 0:03b5121a232e 4457 * @nodes2: a node-set
pcercuei 0:03b5121a232e 4458 *
pcercuei 0:03b5121a232e 4459 * Implements the EXSLT - Sets difference() function:
pcercuei 0:03b5121a232e 4460 * node-set set:difference (node-set, node-set)
pcercuei 0:03b5121a232e 4461 *
pcercuei 0:03b5121a232e 4462 * Returns the difference between the two node sets, or nodes1 if
pcercuei 0:03b5121a232e 4463 * nodes2 is empty
pcercuei 0:03b5121a232e 4464 */
pcercuei 0:03b5121a232e 4465 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4466 xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4467 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 4468 int i, l1;
pcercuei 0:03b5121a232e 4469 xmlNodePtr cur;
pcercuei 0:03b5121a232e 4470
pcercuei 0:03b5121a232e 4471 if (xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4472 return(nodes1);
pcercuei 0:03b5121a232e 4473
pcercuei 0:03b5121a232e 4474 ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 4475 if (xmlXPathNodeSetIsEmpty(nodes1))
pcercuei 0:03b5121a232e 4476 return(ret);
pcercuei 0:03b5121a232e 4477
pcercuei 0:03b5121a232e 4478 l1 = xmlXPathNodeSetGetLength(nodes1);
pcercuei 0:03b5121a232e 4479
pcercuei 0:03b5121a232e 4480 for (i = 0; i < l1; i++) {
pcercuei 0:03b5121a232e 4481 cur = xmlXPathNodeSetItem(nodes1, i);
pcercuei 0:03b5121a232e 4482 if (!xmlXPathNodeSetContains(nodes2, cur)) {
pcercuei 0:03b5121a232e 4483 if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
pcercuei 0:03b5121a232e 4484 break;
pcercuei 0:03b5121a232e 4485 }
pcercuei 0:03b5121a232e 4486 }
pcercuei 0:03b5121a232e 4487 return(ret);
pcercuei 0:03b5121a232e 4488 }
pcercuei 0:03b5121a232e 4489
pcercuei 0:03b5121a232e 4490 /**
pcercuei 0:03b5121a232e 4491 * xmlXPathIntersection:
pcercuei 0:03b5121a232e 4492 * @nodes1: a node-set
pcercuei 0:03b5121a232e 4493 * @nodes2: a node-set
pcercuei 0:03b5121a232e 4494 *
pcercuei 0:03b5121a232e 4495 * Implements the EXSLT - Sets intersection() function:
pcercuei 0:03b5121a232e 4496 * node-set set:intersection (node-set, node-set)
pcercuei 0:03b5121a232e 4497 *
pcercuei 0:03b5121a232e 4498 * Returns a node set comprising the nodes that are within both the
pcercuei 0:03b5121a232e 4499 * node sets passed as arguments
pcercuei 0:03b5121a232e 4500 */
pcercuei 0:03b5121a232e 4501 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4502 xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4503 xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 4504 int i, l1;
pcercuei 0:03b5121a232e 4505 xmlNodePtr cur;
pcercuei 0:03b5121a232e 4506
pcercuei 0:03b5121a232e 4507 if (ret == NULL)
pcercuei 0:03b5121a232e 4508 return(ret);
pcercuei 0:03b5121a232e 4509 if (xmlXPathNodeSetIsEmpty(nodes1))
pcercuei 0:03b5121a232e 4510 return(ret);
pcercuei 0:03b5121a232e 4511 if (xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4512 return(ret);
pcercuei 0:03b5121a232e 4513
pcercuei 0:03b5121a232e 4514 l1 = xmlXPathNodeSetGetLength(nodes1);
pcercuei 0:03b5121a232e 4515
pcercuei 0:03b5121a232e 4516 for (i = 0; i < l1; i++) {
pcercuei 0:03b5121a232e 4517 cur = xmlXPathNodeSetItem(nodes1, i);
pcercuei 0:03b5121a232e 4518 if (xmlXPathNodeSetContains(nodes2, cur)) {
pcercuei 0:03b5121a232e 4519 if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
pcercuei 0:03b5121a232e 4520 break;
pcercuei 0:03b5121a232e 4521 }
pcercuei 0:03b5121a232e 4522 }
pcercuei 0:03b5121a232e 4523 return(ret);
pcercuei 0:03b5121a232e 4524 }
pcercuei 0:03b5121a232e 4525
pcercuei 0:03b5121a232e 4526 /**
pcercuei 0:03b5121a232e 4527 * xmlXPathDistinctSorted:
pcercuei 0:03b5121a232e 4528 * @nodes: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4529 *
pcercuei 0:03b5121a232e 4530 * Implements the EXSLT - Sets distinct() function:
pcercuei 0:03b5121a232e 4531 * node-set set:distinct (node-set)
pcercuei 0:03b5121a232e 4532 *
pcercuei 0:03b5121a232e 4533 * Returns a subset of the nodes contained in @nodes, or @nodes if
pcercuei 0:03b5121a232e 4534 * it is empty
pcercuei 0:03b5121a232e 4535 */
pcercuei 0:03b5121a232e 4536 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4537 xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
pcercuei 0:03b5121a232e 4538 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 4539 xmlHashTablePtr hash;
pcercuei 0:03b5121a232e 4540 int i, l;
pcercuei 0:03b5121a232e 4541 xmlChar * strval;
pcercuei 0:03b5121a232e 4542 xmlNodePtr cur;
pcercuei 0:03b5121a232e 4543
pcercuei 0:03b5121a232e 4544 if (xmlXPathNodeSetIsEmpty(nodes))
pcercuei 0:03b5121a232e 4545 return(nodes);
pcercuei 0:03b5121a232e 4546
pcercuei 0:03b5121a232e 4547 ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 4548 if (ret == NULL)
pcercuei 0:03b5121a232e 4549 return(ret);
pcercuei 0:03b5121a232e 4550 l = xmlXPathNodeSetGetLength(nodes);
pcercuei 0:03b5121a232e 4551 hash = xmlHashCreate (l);
pcercuei 0:03b5121a232e 4552 for (i = 0; i < l; i++) {
pcercuei 0:03b5121a232e 4553 cur = xmlXPathNodeSetItem(nodes, i);
pcercuei 0:03b5121a232e 4554 strval = xmlXPathCastNodeToString(cur);
pcercuei 0:03b5121a232e 4555 if (xmlHashLookup(hash, strval) == NULL) {
pcercuei 0:03b5121a232e 4556 xmlHashAddEntry(hash, strval, strval);
pcercuei 0:03b5121a232e 4557 if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
pcercuei 0:03b5121a232e 4558 break;
pcercuei 0:03b5121a232e 4559 } else {
pcercuei 0:03b5121a232e 4560 xmlFree(strval);
pcercuei 0:03b5121a232e 4561 }
pcercuei 0:03b5121a232e 4562 }
pcercuei 0:03b5121a232e 4563 xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
pcercuei 0:03b5121a232e 4564 return(ret);
pcercuei 0:03b5121a232e 4565 }
pcercuei 0:03b5121a232e 4566
pcercuei 0:03b5121a232e 4567 /**
pcercuei 0:03b5121a232e 4568 * xmlXPathDistinct:
pcercuei 0:03b5121a232e 4569 * @nodes: a node-set
pcercuei 0:03b5121a232e 4570 *
pcercuei 0:03b5121a232e 4571 * Implements the EXSLT - Sets distinct() function:
pcercuei 0:03b5121a232e 4572 * node-set set:distinct (node-set)
pcercuei 0:03b5121a232e 4573 * @nodes is sorted by document order, then #exslSetsDistinctSorted
pcercuei 0:03b5121a232e 4574 * is called with the sorted node-set
pcercuei 0:03b5121a232e 4575 *
pcercuei 0:03b5121a232e 4576 * Returns a subset of the nodes contained in @nodes, or @nodes if
pcercuei 0:03b5121a232e 4577 * it is empty
pcercuei 0:03b5121a232e 4578 */
pcercuei 0:03b5121a232e 4579 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4580 xmlXPathDistinct (xmlNodeSetPtr nodes) {
pcercuei 0:03b5121a232e 4581 if (xmlXPathNodeSetIsEmpty(nodes))
pcercuei 0:03b5121a232e 4582 return(nodes);
pcercuei 0:03b5121a232e 4583
pcercuei 0:03b5121a232e 4584 xmlXPathNodeSetSort(nodes);
pcercuei 0:03b5121a232e 4585 return(xmlXPathDistinctSorted(nodes));
pcercuei 0:03b5121a232e 4586 }
pcercuei 0:03b5121a232e 4587
pcercuei 0:03b5121a232e 4588 /**
pcercuei 0:03b5121a232e 4589 * xmlXPathHasSameNodes:
pcercuei 0:03b5121a232e 4590 * @nodes1: a node-set
pcercuei 0:03b5121a232e 4591 * @nodes2: a node-set
pcercuei 0:03b5121a232e 4592 *
pcercuei 0:03b5121a232e 4593 * Implements the EXSLT - Sets has-same-nodes function:
pcercuei 0:03b5121a232e 4594 * boolean set:has-same-node(node-set, node-set)
pcercuei 0:03b5121a232e 4595 *
pcercuei 0:03b5121a232e 4596 * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
pcercuei 0:03b5121a232e 4597 * otherwise
pcercuei 0:03b5121a232e 4598 */
pcercuei 0:03b5121a232e 4599 int
pcercuei 0:03b5121a232e 4600 xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4601 int i, l;
pcercuei 0:03b5121a232e 4602 xmlNodePtr cur;
pcercuei 0:03b5121a232e 4603
pcercuei 0:03b5121a232e 4604 if (xmlXPathNodeSetIsEmpty(nodes1) ||
pcercuei 0:03b5121a232e 4605 xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4606 return(0);
pcercuei 0:03b5121a232e 4607
pcercuei 0:03b5121a232e 4608 l = xmlXPathNodeSetGetLength(nodes1);
pcercuei 0:03b5121a232e 4609 for (i = 0; i < l; i++) {
pcercuei 0:03b5121a232e 4610 cur = xmlXPathNodeSetItem(nodes1, i);
pcercuei 0:03b5121a232e 4611 if (xmlXPathNodeSetContains(nodes2, cur))
pcercuei 0:03b5121a232e 4612 return(1);
pcercuei 0:03b5121a232e 4613 }
pcercuei 0:03b5121a232e 4614 return(0);
pcercuei 0:03b5121a232e 4615 }
pcercuei 0:03b5121a232e 4616
pcercuei 0:03b5121a232e 4617 /**
pcercuei 0:03b5121a232e 4618 * xmlXPathNodeLeadingSorted:
pcercuei 0:03b5121a232e 4619 * @nodes: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4620 * @node: a node
pcercuei 0:03b5121a232e 4621 *
pcercuei 0:03b5121a232e 4622 * Implements the EXSLT - Sets leading() function:
pcercuei 0:03b5121a232e 4623 * node-set set:leading (node-set, node-set)
pcercuei 0:03b5121a232e 4624 *
pcercuei 0:03b5121a232e 4625 * Returns the nodes in @nodes that precede @node in document order,
pcercuei 0:03b5121a232e 4626 * @nodes if @node is NULL or an empty node-set if @nodes
pcercuei 0:03b5121a232e 4627 * doesn't contain @node
pcercuei 0:03b5121a232e 4628 */
pcercuei 0:03b5121a232e 4629 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4630 xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
pcercuei 0:03b5121a232e 4631 int i, l;
pcercuei 0:03b5121a232e 4632 xmlNodePtr cur;
pcercuei 0:03b5121a232e 4633 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 4634
pcercuei 0:03b5121a232e 4635 if (node == NULL)
pcercuei 0:03b5121a232e 4636 return(nodes);
pcercuei 0:03b5121a232e 4637
pcercuei 0:03b5121a232e 4638 ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 4639 if (ret == NULL)
pcercuei 0:03b5121a232e 4640 return(ret);
pcercuei 0:03b5121a232e 4641 if (xmlXPathNodeSetIsEmpty(nodes) ||
pcercuei 0:03b5121a232e 4642 (!xmlXPathNodeSetContains(nodes, node)))
pcercuei 0:03b5121a232e 4643 return(ret);
pcercuei 0:03b5121a232e 4644
pcercuei 0:03b5121a232e 4645 l = xmlXPathNodeSetGetLength(nodes);
pcercuei 0:03b5121a232e 4646 for (i = 0; i < l; i++) {
pcercuei 0:03b5121a232e 4647 cur = xmlXPathNodeSetItem(nodes, i);
pcercuei 0:03b5121a232e 4648 if (cur == node)
pcercuei 0:03b5121a232e 4649 break;
pcercuei 0:03b5121a232e 4650 if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
pcercuei 0:03b5121a232e 4651 break;
pcercuei 0:03b5121a232e 4652 }
pcercuei 0:03b5121a232e 4653 return(ret);
pcercuei 0:03b5121a232e 4654 }
pcercuei 0:03b5121a232e 4655
pcercuei 0:03b5121a232e 4656 /**
pcercuei 0:03b5121a232e 4657 * xmlXPathNodeLeading:
pcercuei 0:03b5121a232e 4658 * @nodes: a node-set
pcercuei 0:03b5121a232e 4659 * @node: a node
pcercuei 0:03b5121a232e 4660 *
pcercuei 0:03b5121a232e 4661 * Implements the EXSLT - Sets leading() function:
pcercuei 0:03b5121a232e 4662 * node-set set:leading (node-set, node-set)
pcercuei 0:03b5121a232e 4663 * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
pcercuei 0:03b5121a232e 4664 * is called.
pcercuei 0:03b5121a232e 4665 *
pcercuei 0:03b5121a232e 4666 * Returns the nodes in @nodes that precede @node in document order,
pcercuei 0:03b5121a232e 4667 * @nodes if @node is NULL or an empty node-set if @nodes
pcercuei 0:03b5121a232e 4668 * doesn't contain @node
pcercuei 0:03b5121a232e 4669 */
pcercuei 0:03b5121a232e 4670 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4671 xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
pcercuei 0:03b5121a232e 4672 xmlXPathNodeSetSort(nodes);
pcercuei 0:03b5121a232e 4673 return(xmlXPathNodeLeadingSorted(nodes, node));
pcercuei 0:03b5121a232e 4674 }
pcercuei 0:03b5121a232e 4675
pcercuei 0:03b5121a232e 4676 /**
pcercuei 0:03b5121a232e 4677 * xmlXPathLeadingSorted:
pcercuei 0:03b5121a232e 4678 * @nodes1: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4679 * @nodes2: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4680 *
pcercuei 0:03b5121a232e 4681 * Implements the EXSLT - Sets leading() function:
pcercuei 0:03b5121a232e 4682 * node-set set:leading (node-set, node-set)
pcercuei 0:03b5121a232e 4683 *
pcercuei 0:03b5121a232e 4684 * Returns the nodes in @nodes1 that precede the first node in @nodes2
pcercuei 0:03b5121a232e 4685 * in document order, @nodes1 if @nodes2 is NULL or empty or
pcercuei 0:03b5121a232e 4686 * an empty node-set if @nodes1 doesn't contain @nodes2
pcercuei 0:03b5121a232e 4687 */
pcercuei 0:03b5121a232e 4688 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4689 xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4690 if (xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4691 return(nodes1);
pcercuei 0:03b5121a232e 4692 return(xmlXPathNodeLeadingSorted(nodes1,
pcercuei 0:03b5121a232e 4693 xmlXPathNodeSetItem(nodes2, 1)));
pcercuei 0:03b5121a232e 4694 }
pcercuei 0:03b5121a232e 4695
pcercuei 0:03b5121a232e 4696 /**
pcercuei 0:03b5121a232e 4697 * xmlXPathLeading:
pcercuei 0:03b5121a232e 4698 * @nodes1: a node-set
pcercuei 0:03b5121a232e 4699 * @nodes2: a node-set
pcercuei 0:03b5121a232e 4700 *
pcercuei 0:03b5121a232e 4701 * Implements the EXSLT - Sets leading() function:
pcercuei 0:03b5121a232e 4702 * node-set set:leading (node-set, node-set)
pcercuei 0:03b5121a232e 4703 * @nodes1 and @nodes2 are sorted by document order, then
pcercuei 0:03b5121a232e 4704 * #exslSetsLeadingSorted is called.
pcercuei 0:03b5121a232e 4705 *
pcercuei 0:03b5121a232e 4706 * Returns the nodes in @nodes1 that precede the first node in @nodes2
pcercuei 0:03b5121a232e 4707 * in document order, @nodes1 if @nodes2 is NULL or empty or
pcercuei 0:03b5121a232e 4708 * an empty node-set if @nodes1 doesn't contain @nodes2
pcercuei 0:03b5121a232e 4709 */
pcercuei 0:03b5121a232e 4710 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4711 xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4712 if (xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4713 return(nodes1);
pcercuei 0:03b5121a232e 4714 if (xmlXPathNodeSetIsEmpty(nodes1))
pcercuei 0:03b5121a232e 4715 return(xmlXPathNodeSetCreate(NULL));
pcercuei 0:03b5121a232e 4716 xmlXPathNodeSetSort(nodes1);
pcercuei 0:03b5121a232e 4717 xmlXPathNodeSetSort(nodes2);
pcercuei 0:03b5121a232e 4718 return(xmlXPathNodeLeadingSorted(nodes1,
pcercuei 0:03b5121a232e 4719 xmlXPathNodeSetItem(nodes2, 1)));
pcercuei 0:03b5121a232e 4720 }
pcercuei 0:03b5121a232e 4721
pcercuei 0:03b5121a232e 4722 /**
pcercuei 0:03b5121a232e 4723 * xmlXPathNodeTrailingSorted:
pcercuei 0:03b5121a232e 4724 * @nodes: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4725 * @node: a node
pcercuei 0:03b5121a232e 4726 *
pcercuei 0:03b5121a232e 4727 * Implements the EXSLT - Sets trailing() function:
pcercuei 0:03b5121a232e 4728 * node-set set:trailing (node-set, node-set)
pcercuei 0:03b5121a232e 4729 *
pcercuei 0:03b5121a232e 4730 * Returns the nodes in @nodes that follow @node in document order,
pcercuei 0:03b5121a232e 4731 * @nodes if @node is NULL or an empty node-set if @nodes
pcercuei 0:03b5121a232e 4732 * doesn't contain @node
pcercuei 0:03b5121a232e 4733 */
pcercuei 0:03b5121a232e 4734 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4735 xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
pcercuei 0:03b5121a232e 4736 int i, l;
pcercuei 0:03b5121a232e 4737 xmlNodePtr cur;
pcercuei 0:03b5121a232e 4738 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 4739
pcercuei 0:03b5121a232e 4740 if (node == NULL)
pcercuei 0:03b5121a232e 4741 return(nodes);
pcercuei 0:03b5121a232e 4742
pcercuei 0:03b5121a232e 4743 ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 4744 if (ret == NULL)
pcercuei 0:03b5121a232e 4745 return(ret);
pcercuei 0:03b5121a232e 4746 if (xmlXPathNodeSetIsEmpty(nodes) ||
pcercuei 0:03b5121a232e 4747 (!xmlXPathNodeSetContains(nodes, node)))
pcercuei 0:03b5121a232e 4748 return(ret);
pcercuei 0:03b5121a232e 4749
pcercuei 0:03b5121a232e 4750 l = xmlXPathNodeSetGetLength(nodes);
pcercuei 0:03b5121a232e 4751 for (i = l - 1; i >= 0; i--) {
pcercuei 0:03b5121a232e 4752 cur = xmlXPathNodeSetItem(nodes, i);
pcercuei 0:03b5121a232e 4753 if (cur == node)
pcercuei 0:03b5121a232e 4754 break;
pcercuei 0:03b5121a232e 4755 if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
pcercuei 0:03b5121a232e 4756 break;
pcercuei 0:03b5121a232e 4757 }
pcercuei 0:03b5121a232e 4758 xmlXPathNodeSetSort(ret); /* bug 413451 */
pcercuei 0:03b5121a232e 4759 return(ret);
pcercuei 0:03b5121a232e 4760 }
pcercuei 0:03b5121a232e 4761
pcercuei 0:03b5121a232e 4762 /**
pcercuei 0:03b5121a232e 4763 * xmlXPathNodeTrailing:
pcercuei 0:03b5121a232e 4764 * @nodes: a node-set
pcercuei 0:03b5121a232e 4765 * @node: a node
pcercuei 0:03b5121a232e 4766 *
pcercuei 0:03b5121a232e 4767 * Implements the EXSLT - Sets trailing() function:
pcercuei 0:03b5121a232e 4768 * node-set set:trailing (node-set, node-set)
pcercuei 0:03b5121a232e 4769 * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
pcercuei 0:03b5121a232e 4770 * is called.
pcercuei 0:03b5121a232e 4771 *
pcercuei 0:03b5121a232e 4772 * Returns the nodes in @nodes that follow @node in document order,
pcercuei 0:03b5121a232e 4773 * @nodes if @node is NULL or an empty node-set if @nodes
pcercuei 0:03b5121a232e 4774 * doesn't contain @node
pcercuei 0:03b5121a232e 4775 */
pcercuei 0:03b5121a232e 4776 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4777 xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
pcercuei 0:03b5121a232e 4778 xmlXPathNodeSetSort(nodes);
pcercuei 0:03b5121a232e 4779 return(xmlXPathNodeTrailingSorted(nodes, node));
pcercuei 0:03b5121a232e 4780 }
pcercuei 0:03b5121a232e 4781
pcercuei 0:03b5121a232e 4782 /**
pcercuei 0:03b5121a232e 4783 * xmlXPathTrailingSorted:
pcercuei 0:03b5121a232e 4784 * @nodes1: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4785 * @nodes2: a node-set, sorted by document order
pcercuei 0:03b5121a232e 4786 *
pcercuei 0:03b5121a232e 4787 * Implements the EXSLT - Sets trailing() function:
pcercuei 0:03b5121a232e 4788 * node-set set:trailing (node-set, node-set)
pcercuei 0:03b5121a232e 4789 *
pcercuei 0:03b5121a232e 4790 * Returns the nodes in @nodes1 that follow the first node in @nodes2
pcercuei 0:03b5121a232e 4791 * in document order, @nodes1 if @nodes2 is NULL or empty or
pcercuei 0:03b5121a232e 4792 * an empty node-set if @nodes1 doesn't contain @nodes2
pcercuei 0:03b5121a232e 4793 */
pcercuei 0:03b5121a232e 4794 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4795 xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4796 if (xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4797 return(nodes1);
pcercuei 0:03b5121a232e 4798 return(xmlXPathNodeTrailingSorted(nodes1,
pcercuei 0:03b5121a232e 4799 xmlXPathNodeSetItem(nodes2, 0)));
pcercuei 0:03b5121a232e 4800 }
pcercuei 0:03b5121a232e 4801
pcercuei 0:03b5121a232e 4802 /**
pcercuei 0:03b5121a232e 4803 * xmlXPathTrailing:
pcercuei 0:03b5121a232e 4804 * @nodes1: a node-set
pcercuei 0:03b5121a232e 4805 * @nodes2: a node-set
pcercuei 0:03b5121a232e 4806 *
pcercuei 0:03b5121a232e 4807 * Implements the EXSLT - Sets trailing() function:
pcercuei 0:03b5121a232e 4808 * node-set set:trailing (node-set, node-set)
pcercuei 0:03b5121a232e 4809 * @nodes1 and @nodes2 are sorted by document order, then
pcercuei 0:03b5121a232e 4810 * #xmlXPathTrailingSorted is called.
pcercuei 0:03b5121a232e 4811 *
pcercuei 0:03b5121a232e 4812 * Returns the nodes in @nodes1 that follow the first node in @nodes2
pcercuei 0:03b5121a232e 4813 * in document order, @nodes1 if @nodes2 is NULL or empty or
pcercuei 0:03b5121a232e 4814 * an empty node-set if @nodes1 doesn't contain @nodes2
pcercuei 0:03b5121a232e 4815 */
pcercuei 0:03b5121a232e 4816 xmlNodeSetPtr
pcercuei 0:03b5121a232e 4817 xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
pcercuei 0:03b5121a232e 4818 if (xmlXPathNodeSetIsEmpty(nodes2))
pcercuei 0:03b5121a232e 4819 return(nodes1);
pcercuei 0:03b5121a232e 4820 if (xmlXPathNodeSetIsEmpty(nodes1))
pcercuei 0:03b5121a232e 4821 return(xmlXPathNodeSetCreate(NULL));
pcercuei 0:03b5121a232e 4822 xmlXPathNodeSetSort(nodes1);
pcercuei 0:03b5121a232e 4823 xmlXPathNodeSetSort(nodes2);
pcercuei 0:03b5121a232e 4824 return(xmlXPathNodeTrailingSorted(nodes1,
pcercuei 0:03b5121a232e 4825 xmlXPathNodeSetItem(nodes2, 0)));
pcercuei 0:03b5121a232e 4826 }
pcercuei 0:03b5121a232e 4827
pcercuei 0:03b5121a232e 4828 /************************************************************************
pcercuei 0:03b5121a232e 4829 * *
pcercuei 0:03b5121a232e 4830 * Routines to handle extra functions *
pcercuei 0:03b5121a232e 4831 * *
pcercuei 0:03b5121a232e 4832 ************************************************************************/
pcercuei 0:03b5121a232e 4833
pcercuei 0:03b5121a232e 4834 /**
pcercuei 0:03b5121a232e 4835 * xmlXPathRegisterFunc:
pcercuei 0:03b5121a232e 4836 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4837 * @name: the function name
pcercuei 0:03b5121a232e 4838 * @f: the function implementation or NULL
pcercuei 0:03b5121a232e 4839 *
pcercuei 0:03b5121a232e 4840 * Register a new function. If @f is NULL it unregisters the function
pcercuei 0:03b5121a232e 4841 *
pcercuei 0:03b5121a232e 4842 * Returns 0 in case of success, -1 in case of error
pcercuei 0:03b5121a232e 4843 */
pcercuei 0:03b5121a232e 4844 int
pcercuei 0:03b5121a232e 4845 xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
pcercuei 0:03b5121a232e 4846 xmlXPathFunction f) {
pcercuei 0:03b5121a232e 4847 return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
pcercuei 0:03b5121a232e 4848 }
pcercuei 0:03b5121a232e 4849
pcercuei 0:03b5121a232e 4850 /**
pcercuei 0:03b5121a232e 4851 * xmlXPathRegisterFuncNS:
pcercuei 0:03b5121a232e 4852 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4853 * @name: the function name
pcercuei 0:03b5121a232e 4854 * @ns_uri: the function namespace URI
pcercuei 0:03b5121a232e 4855 * @f: the function implementation or NULL
pcercuei 0:03b5121a232e 4856 *
pcercuei 0:03b5121a232e 4857 * Register a new function. If @f is NULL it unregisters the function
pcercuei 0:03b5121a232e 4858 *
pcercuei 0:03b5121a232e 4859 * Returns 0 in case of success, -1 in case of error
pcercuei 0:03b5121a232e 4860 */
pcercuei 0:03b5121a232e 4861 int
pcercuei 0:03b5121a232e 4862 xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
pcercuei 0:03b5121a232e 4863 const xmlChar *ns_uri, xmlXPathFunction f) {
pcercuei 0:03b5121a232e 4864 if (ctxt == NULL)
pcercuei 0:03b5121a232e 4865 return(-1);
pcercuei 0:03b5121a232e 4866 if (name == NULL)
pcercuei 0:03b5121a232e 4867 return(-1);
pcercuei 0:03b5121a232e 4868
pcercuei 0:03b5121a232e 4869 if (ctxt->funcHash == NULL)
pcercuei 0:03b5121a232e 4870 ctxt->funcHash = xmlHashCreate(0);
pcercuei 0:03b5121a232e 4871 if (ctxt->funcHash == NULL)
pcercuei 0:03b5121a232e 4872 return(-1);
pcercuei 0:03b5121a232e 4873 if (f == NULL)
pcercuei 0:03b5121a232e 4874 return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
pcercuei 0:03b5121a232e 4875 return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, XML_CAST_FPTR(f)));
pcercuei 0:03b5121a232e 4876 }
pcercuei 0:03b5121a232e 4877
pcercuei 0:03b5121a232e 4878 /**
pcercuei 0:03b5121a232e 4879 * xmlXPathRegisterFuncLookup:
pcercuei 0:03b5121a232e 4880 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4881 * @f: the lookup function
pcercuei 0:03b5121a232e 4882 * @funcCtxt: the lookup data
pcercuei 0:03b5121a232e 4883 *
pcercuei 0:03b5121a232e 4884 * Registers an external mechanism to do function lookup.
pcercuei 0:03b5121a232e 4885 */
pcercuei 0:03b5121a232e 4886 void
pcercuei 0:03b5121a232e 4887 xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
pcercuei 0:03b5121a232e 4888 xmlXPathFuncLookupFunc f,
pcercuei 0:03b5121a232e 4889 void *funcCtxt) {
pcercuei 0:03b5121a232e 4890 if (ctxt == NULL)
pcercuei 0:03b5121a232e 4891 return;
pcercuei 0:03b5121a232e 4892 ctxt->funcLookupFunc = f;
pcercuei 0:03b5121a232e 4893 ctxt->funcLookupData = funcCtxt;
pcercuei 0:03b5121a232e 4894 }
pcercuei 0:03b5121a232e 4895
pcercuei 0:03b5121a232e 4896 /**
pcercuei 0:03b5121a232e 4897 * xmlXPathFunctionLookup:
pcercuei 0:03b5121a232e 4898 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4899 * @name: the function name
pcercuei 0:03b5121a232e 4900 *
pcercuei 0:03b5121a232e 4901 * Search in the Function array of the context for the given
pcercuei 0:03b5121a232e 4902 * function.
pcercuei 0:03b5121a232e 4903 *
pcercuei 0:03b5121a232e 4904 * Returns the xmlXPathFunction or NULL if not found
pcercuei 0:03b5121a232e 4905 */
pcercuei 0:03b5121a232e 4906 xmlXPathFunction
pcercuei 0:03b5121a232e 4907 xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
pcercuei 0:03b5121a232e 4908 if (ctxt == NULL)
pcercuei 0:03b5121a232e 4909 return (NULL);
pcercuei 0:03b5121a232e 4910
pcercuei 0:03b5121a232e 4911 if (ctxt->funcLookupFunc != NULL) {
pcercuei 0:03b5121a232e 4912 xmlXPathFunction ret;
pcercuei 0:03b5121a232e 4913 xmlXPathFuncLookupFunc f;
pcercuei 0:03b5121a232e 4914
pcercuei 0:03b5121a232e 4915 f = ctxt->funcLookupFunc;
pcercuei 0:03b5121a232e 4916 ret = f(ctxt->funcLookupData, name, NULL);
pcercuei 0:03b5121a232e 4917 if (ret != NULL)
pcercuei 0:03b5121a232e 4918 return(ret);
pcercuei 0:03b5121a232e 4919 }
pcercuei 0:03b5121a232e 4920 return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
pcercuei 0:03b5121a232e 4921 }
pcercuei 0:03b5121a232e 4922
pcercuei 0:03b5121a232e 4923 /**
pcercuei 0:03b5121a232e 4924 * xmlXPathFunctionLookupNS:
pcercuei 0:03b5121a232e 4925 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4926 * @name: the function name
pcercuei 0:03b5121a232e 4927 * @ns_uri: the function namespace URI
pcercuei 0:03b5121a232e 4928 *
pcercuei 0:03b5121a232e 4929 * Search in the Function array of the context for the given
pcercuei 0:03b5121a232e 4930 * function.
pcercuei 0:03b5121a232e 4931 *
pcercuei 0:03b5121a232e 4932 * Returns the xmlXPathFunction or NULL if not found
pcercuei 0:03b5121a232e 4933 */
pcercuei 0:03b5121a232e 4934 xmlXPathFunction
pcercuei 0:03b5121a232e 4935 xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
pcercuei 0:03b5121a232e 4936 const xmlChar *ns_uri) {
pcercuei 0:03b5121a232e 4937 xmlXPathFunction ret;
pcercuei 0:03b5121a232e 4938
pcercuei 0:03b5121a232e 4939 if (ctxt == NULL)
pcercuei 0:03b5121a232e 4940 return(NULL);
pcercuei 0:03b5121a232e 4941 if (name == NULL)
pcercuei 0:03b5121a232e 4942 return(NULL);
pcercuei 0:03b5121a232e 4943
pcercuei 0:03b5121a232e 4944 if (ctxt->funcLookupFunc != NULL) {
pcercuei 0:03b5121a232e 4945 xmlXPathFuncLookupFunc f;
pcercuei 0:03b5121a232e 4946
pcercuei 0:03b5121a232e 4947 f = ctxt->funcLookupFunc;
pcercuei 0:03b5121a232e 4948 ret = f(ctxt->funcLookupData, name, ns_uri);
pcercuei 0:03b5121a232e 4949 if (ret != NULL)
pcercuei 0:03b5121a232e 4950 return(ret);
pcercuei 0:03b5121a232e 4951 }
pcercuei 0:03b5121a232e 4952
pcercuei 0:03b5121a232e 4953 if (ctxt->funcHash == NULL)
pcercuei 0:03b5121a232e 4954 return(NULL);
pcercuei 0:03b5121a232e 4955
pcercuei 0:03b5121a232e 4956 XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
pcercuei 0:03b5121a232e 4957 return(ret);
pcercuei 0:03b5121a232e 4958 }
pcercuei 0:03b5121a232e 4959
pcercuei 0:03b5121a232e 4960 /**
pcercuei 0:03b5121a232e 4961 * xmlXPathRegisteredFuncsCleanup:
pcercuei 0:03b5121a232e 4962 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4963 *
pcercuei 0:03b5121a232e 4964 * Cleanup the XPath context data associated to registered functions
pcercuei 0:03b5121a232e 4965 */
pcercuei 0:03b5121a232e 4966 void
pcercuei 0:03b5121a232e 4967 xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 4968 if (ctxt == NULL)
pcercuei 0:03b5121a232e 4969 return;
pcercuei 0:03b5121a232e 4970
pcercuei 0:03b5121a232e 4971 xmlHashFree(ctxt->funcHash, NULL);
pcercuei 0:03b5121a232e 4972 ctxt->funcHash = NULL;
pcercuei 0:03b5121a232e 4973 }
pcercuei 0:03b5121a232e 4974
pcercuei 0:03b5121a232e 4975 /************************************************************************
pcercuei 0:03b5121a232e 4976 * *
pcercuei 0:03b5121a232e 4977 * Routines to handle Variables *
pcercuei 0:03b5121a232e 4978 * *
pcercuei 0:03b5121a232e 4979 ************************************************************************/
pcercuei 0:03b5121a232e 4980
pcercuei 0:03b5121a232e 4981 /**
pcercuei 0:03b5121a232e 4982 * xmlXPathRegisterVariable:
pcercuei 0:03b5121a232e 4983 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 4984 * @name: the variable name
pcercuei 0:03b5121a232e 4985 * @value: the variable value or NULL
pcercuei 0:03b5121a232e 4986 *
pcercuei 0:03b5121a232e 4987 * Register a new variable value. If @value is NULL it unregisters
pcercuei 0:03b5121a232e 4988 * the variable
pcercuei 0:03b5121a232e 4989 *
pcercuei 0:03b5121a232e 4990 * Returns 0 in case of success, -1 in case of error
pcercuei 0:03b5121a232e 4991 */
pcercuei 0:03b5121a232e 4992 int
pcercuei 0:03b5121a232e 4993 xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
pcercuei 0:03b5121a232e 4994 xmlXPathObjectPtr value) {
pcercuei 0:03b5121a232e 4995 return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
pcercuei 0:03b5121a232e 4996 }
pcercuei 0:03b5121a232e 4997
pcercuei 0:03b5121a232e 4998 /**
pcercuei 0:03b5121a232e 4999 * xmlXPathRegisterVariableNS:
pcercuei 0:03b5121a232e 5000 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5001 * @name: the variable name
pcercuei 0:03b5121a232e 5002 * @ns_uri: the variable namespace URI
pcercuei 0:03b5121a232e 5003 * @value: the variable value or NULL
pcercuei 0:03b5121a232e 5004 *
pcercuei 0:03b5121a232e 5005 * Register a new variable value. If @value is NULL it unregisters
pcercuei 0:03b5121a232e 5006 * the variable
pcercuei 0:03b5121a232e 5007 *
pcercuei 0:03b5121a232e 5008 * Returns 0 in case of success, -1 in case of error
pcercuei 0:03b5121a232e 5009 */
pcercuei 0:03b5121a232e 5010 int
pcercuei 0:03b5121a232e 5011 xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
pcercuei 0:03b5121a232e 5012 const xmlChar *ns_uri,
pcercuei 0:03b5121a232e 5013 xmlXPathObjectPtr value) {
pcercuei 0:03b5121a232e 5014 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5015 return(-1);
pcercuei 0:03b5121a232e 5016 if (name == NULL)
pcercuei 0:03b5121a232e 5017 return(-1);
pcercuei 0:03b5121a232e 5018
pcercuei 0:03b5121a232e 5019 if (ctxt->varHash == NULL)
pcercuei 0:03b5121a232e 5020 ctxt->varHash = xmlHashCreate(0);
pcercuei 0:03b5121a232e 5021 if (ctxt->varHash == NULL)
pcercuei 0:03b5121a232e 5022 return(-1);
pcercuei 0:03b5121a232e 5023 if (value == NULL)
pcercuei 0:03b5121a232e 5024 return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
pcercuei 0:03b5121a232e 5025 (xmlHashDeallocator)xmlXPathFreeObject));
pcercuei 0:03b5121a232e 5026 return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
pcercuei 0:03b5121a232e 5027 (void *) value,
pcercuei 0:03b5121a232e 5028 (xmlHashDeallocator)xmlXPathFreeObject));
pcercuei 0:03b5121a232e 5029 }
pcercuei 0:03b5121a232e 5030
pcercuei 0:03b5121a232e 5031 /**
pcercuei 0:03b5121a232e 5032 * xmlXPathRegisterVariableLookup:
pcercuei 0:03b5121a232e 5033 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5034 * @f: the lookup function
pcercuei 0:03b5121a232e 5035 * @data: the lookup data
pcercuei 0:03b5121a232e 5036 *
pcercuei 0:03b5121a232e 5037 * register an external mechanism to do variable lookup
pcercuei 0:03b5121a232e 5038 */
pcercuei 0:03b5121a232e 5039 void
pcercuei 0:03b5121a232e 5040 xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
pcercuei 0:03b5121a232e 5041 xmlXPathVariableLookupFunc f, void *data) {
pcercuei 0:03b5121a232e 5042 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5043 return;
pcercuei 0:03b5121a232e 5044 ctxt->varLookupFunc = f;
pcercuei 0:03b5121a232e 5045 ctxt->varLookupData = data;
pcercuei 0:03b5121a232e 5046 }
pcercuei 0:03b5121a232e 5047
pcercuei 0:03b5121a232e 5048 /**
pcercuei 0:03b5121a232e 5049 * xmlXPathVariableLookup:
pcercuei 0:03b5121a232e 5050 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5051 * @name: the variable name
pcercuei 0:03b5121a232e 5052 *
pcercuei 0:03b5121a232e 5053 * Search in the Variable array of the context for the given
pcercuei 0:03b5121a232e 5054 * variable value.
pcercuei 0:03b5121a232e 5055 *
pcercuei 0:03b5121a232e 5056 * Returns a copy of the value or NULL if not found
pcercuei 0:03b5121a232e 5057 */
pcercuei 0:03b5121a232e 5058 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5059 xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
pcercuei 0:03b5121a232e 5060 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5061 return(NULL);
pcercuei 0:03b5121a232e 5062
pcercuei 0:03b5121a232e 5063 if (ctxt->varLookupFunc != NULL) {
pcercuei 0:03b5121a232e 5064 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5065
pcercuei 0:03b5121a232e 5066 ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
pcercuei 0:03b5121a232e 5067 (ctxt->varLookupData, name, NULL);
pcercuei 0:03b5121a232e 5068 return(ret);
pcercuei 0:03b5121a232e 5069 }
pcercuei 0:03b5121a232e 5070 return(xmlXPathVariableLookupNS(ctxt, name, NULL));
pcercuei 0:03b5121a232e 5071 }
pcercuei 0:03b5121a232e 5072
pcercuei 0:03b5121a232e 5073 /**
pcercuei 0:03b5121a232e 5074 * xmlXPathVariableLookupNS:
pcercuei 0:03b5121a232e 5075 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5076 * @name: the variable name
pcercuei 0:03b5121a232e 5077 * @ns_uri: the variable namespace URI
pcercuei 0:03b5121a232e 5078 *
pcercuei 0:03b5121a232e 5079 * Search in the Variable array of the context for the given
pcercuei 0:03b5121a232e 5080 * variable value.
pcercuei 0:03b5121a232e 5081 *
pcercuei 0:03b5121a232e 5082 * Returns the a copy of the value or NULL if not found
pcercuei 0:03b5121a232e 5083 */
pcercuei 0:03b5121a232e 5084 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5085 xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
pcercuei 0:03b5121a232e 5086 const xmlChar *ns_uri) {
pcercuei 0:03b5121a232e 5087 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5088 return(NULL);
pcercuei 0:03b5121a232e 5089
pcercuei 0:03b5121a232e 5090 if (ctxt->varLookupFunc != NULL) {
pcercuei 0:03b5121a232e 5091 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5092
pcercuei 0:03b5121a232e 5093 ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
pcercuei 0:03b5121a232e 5094 (ctxt->varLookupData, name, ns_uri);
pcercuei 0:03b5121a232e 5095 if (ret != NULL) return(ret);
pcercuei 0:03b5121a232e 5096 }
pcercuei 0:03b5121a232e 5097
pcercuei 0:03b5121a232e 5098 if (ctxt->varHash == NULL)
pcercuei 0:03b5121a232e 5099 return(NULL);
pcercuei 0:03b5121a232e 5100 if (name == NULL)
pcercuei 0:03b5121a232e 5101 return(NULL);
pcercuei 0:03b5121a232e 5102
pcercuei 0:03b5121a232e 5103 return(xmlXPathCacheObjectCopy(ctxt, (xmlXPathObjectPtr)
pcercuei 0:03b5121a232e 5104 xmlHashLookup2(ctxt->varHash, name, ns_uri)));
pcercuei 0:03b5121a232e 5105 }
pcercuei 0:03b5121a232e 5106
pcercuei 0:03b5121a232e 5107 /**
pcercuei 0:03b5121a232e 5108 * xmlXPathRegisteredVariablesCleanup:
pcercuei 0:03b5121a232e 5109 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5110 *
pcercuei 0:03b5121a232e 5111 * Cleanup the XPath context data associated to registered variables
pcercuei 0:03b5121a232e 5112 */
pcercuei 0:03b5121a232e 5113 void
pcercuei 0:03b5121a232e 5114 xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 5115 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5116 return;
pcercuei 0:03b5121a232e 5117
pcercuei 0:03b5121a232e 5118 xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject);
pcercuei 0:03b5121a232e 5119 ctxt->varHash = NULL;
pcercuei 0:03b5121a232e 5120 }
pcercuei 0:03b5121a232e 5121
pcercuei 0:03b5121a232e 5122 /**
pcercuei 0:03b5121a232e 5123 * xmlXPathRegisterNs:
pcercuei 0:03b5121a232e 5124 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5125 * @prefix: the namespace prefix cannot be NULL or empty string
pcercuei 0:03b5121a232e 5126 * @ns_uri: the namespace name
pcercuei 0:03b5121a232e 5127 *
pcercuei 0:03b5121a232e 5128 * Register a new namespace. If @ns_uri is NULL it unregisters
pcercuei 0:03b5121a232e 5129 * the namespace
pcercuei 0:03b5121a232e 5130 *
pcercuei 0:03b5121a232e 5131 * Returns 0 in case of success, -1 in case of error
pcercuei 0:03b5121a232e 5132 */
pcercuei 0:03b5121a232e 5133 int
pcercuei 0:03b5121a232e 5134 xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
pcercuei 0:03b5121a232e 5135 const xmlChar *ns_uri) {
pcercuei 0:03b5121a232e 5136 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5137 return(-1);
pcercuei 0:03b5121a232e 5138 if (prefix == NULL)
pcercuei 0:03b5121a232e 5139 return(-1);
pcercuei 0:03b5121a232e 5140 if (prefix[0] == 0)
pcercuei 0:03b5121a232e 5141 return(-1);
pcercuei 0:03b5121a232e 5142
pcercuei 0:03b5121a232e 5143 if (ctxt->nsHash == NULL)
pcercuei 0:03b5121a232e 5144 ctxt->nsHash = xmlHashCreate(10);
pcercuei 0:03b5121a232e 5145 if (ctxt->nsHash == NULL)
pcercuei 0:03b5121a232e 5146 return(-1);
pcercuei 0:03b5121a232e 5147 if (ns_uri == NULL)
pcercuei 0:03b5121a232e 5148 return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
pcercuei 0:03b5121a232e 5149 (xmlHashDeallocator)xmlFree));
pcercuei 0:03b5121a232e 5150 return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri),
pcercuei 0:03b5121a232e 5151 (xmlHashDeallocator)xmlFree));
pcercuei 0:03b5121a232e 5152 }
pcercuei 0:03b5121a232e 5153
pcercuei 0:03b5121a232e 5154 /**
pcercuei 0:03b5121a232e 5155 * xmlXPathNsLookup:
pcercuei 0:03b5121a232e 5156 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5157 * @prefix: the namespace prefix value
pcercuei 0:03b5121a232e 5158 *
pcercuei 0:03b5121a232e 5159 * Search in the namespace declaration array of the context for the given
pcercuei 0:03b5121a232e 5160 * namespace name associated to the given prefix
pcercuei 0:03b5121a232e 5161 *
pcercuei 0:03b5121a232e 5162 * Returns the value or NULL if not found
pcercuei 0:03b5121a232e 5163 */
pcercuei 0:03b5121a232e 5164 const xmlChar *
pcercuei 0:03b5121a232e 5165 xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
pcercuei 0:03b5121a232e 5166 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5167 return(NULL);
pcercuei 0:03b5121a232e 5168 if (prefix == NULL)
pcercuei 0:03b5121a232e 5169 return(NULL);
pcercuei 0:03b5121a232e 5170
pcercuei 0:03b5121a232e 5171 #ifdef XML_XML_NAMESPACE
pcercuei 0:03b5121a232e 5172 if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
pcercuei 0:03b5121a232e 5173 return(XML_XML_NAMESPACE);
pcercuei 0:03b5121a232e 5174 #endif
pcercuei 0:03b5121a232e 5175
pcercuei 0:03b5121a232e 5176 if (ctxt->namespaces != NULL) {
pcercuei 0:03b5121a232e 5177 int i;
pcercuei 0:03b5121a232e 5178
pcercuei 0:03b5121a232e 5179 for (i = 0;i < ctxt->nsNr;i++) {
pcercuei 0:03b5121a232e 5180 if ((ctxt->namespaces[i] != NULL) &&
pcercuei 0:03b5121a232e 5181 (xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
pcercuei 0:03b5121a232e 5182 return(ctxt->namespaces[i]->href);
pcercuei 0:03b5121a232e 5183 }
pcercuei 0:03b5121a232e 5184 }
pcercuei 0:03b5121a232e 5185
pcercuei 0:03b5121a232e 5186 return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
pcercuei 0:03b5121a232e 5187 }
pcercuei 0:03b5121a232e 5188
pcercuei 0:03b5121a232e 5189 /**
pcercuei 0:03b5121a232e 5190 * xmlXPathRegisteredNsCleanup:
pcercuei 0:03b5121a232e 5191 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 5192 *
pcercuei 0:03b5121a232e 5193 * Cleanup the XPath context data associated to registered variables
pcercuei 0:03b5121a232e 5194 */
pcercuei 0:03b5121a232e 5195 void
pcercuei 0:03b5121a232e 5196 xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 5197 if (ctxt == NULL)
pcercuei 0:03b5121a232e 5198 return;
pcercuei 0:03b5121a232e 5199
pcercuei 0:03b5121a232e 5200 xmlHashFree(ctxt->nsHash, (xmlHashDeallocator)xmlFree);
pcercuei 0:03b5121a232e 5201 ctxt->nsHash = NULL;
pcercuei 0:03b5121a232e 5202 }
pcercuei 0:03b5121a232e 5203
pcercuei 0:03b5121a232e 5204 /************************************************************************
pcercuei 0:03b5121a232e 5205 * *
pcercuei 0:03b5121a232e 5206 * Routines to handle Values *
pcercuei 0:03b5121a232e 5207 * *
pcercuei 0:03b5121a232e 5208 ************************************************************************/
pcercuei 0:03b5121a232e 5209
pcercuei 0:03b5121a232e 5210 /* Allocations are terrible, one needs to optimize all this !!! */
pcercuei 0:03b5121a232e 5211
pcercuei 0:03b5121a232e 5212 /**
pcercuei 0:03b5121a232e 5213 * xmlXPathNewFloat:
pcercuei 0:03b5121a232e 5214 * @val: the double value
pcercuei 0:03b5121a232e 5215 *
pcercuei 0:03b5121a232e 5216 * Create a new xmlXPathObjectPtr of type double and of value @val
pcercuei 0:03b5121a232e 5217 *
pcercuei 0:03b5121a232e 5218 * Returns the newly created object.
pcercuei 0:03b5121a232e 5219 */
pcercuei 0:03b5121a232e 5220 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5221 xmlXPathNewFloat(double val) {
pcercuei 0:03b5121a232e 5222 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5223
pcercuei 0:03b5121a232e 5224 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5225 if (ret == NULL) {
pcercuei 0:03b5121a232e 5226 xmlXPathErrMemory(NULL, "creating float object\n");
pcercuei 0:03b5121a232e 5227 return(NULL);
pcercuei 0:03b5121a232e 5228 }
pcercuei 0:03b5121a232e 5229 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5230 ret->type = XPATH_NUMBER;
pcercuei 0:03b5121a232e 5231 ret->floatval = val;
pcercuei 0:03b5121a232e 5232 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5233 xmlXPathDebugObjUsageRequested(NULL, XPATH_NUMBER);
pcercuei 0:03b5121a232e 5234 #endif
pcercuei 0:03b5121a232e 5235 return(ret);
pcercuei 0:03b5121a232e 5236 }
pcercuei 0:03b5121a232e 5237
pcercuei 0:03b5121a232e 5238 /**
pcercuei 0:03b5121a232e 5239 * xmlXPathNewBoolean:
pcercuei 0:03b5121a232e 5240 * @val: the boolean value
pcercuei 0:03b5121a232e 5241 *
pcercuei 0:03b5121a232e 5242 * Create a new xmlXPathObjectPtr of type boolean and of value @val
pcercuei 0:03b5121a232e 5243 *
pcercuei 0:03b5121a232e 5244 * Returns the newly created object.
pcercuei 0:03b5121a232e 5245 */
pcercuei 0:03b5121a232e 5246 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5247 xmlXPathNewBoolean(int val) {
pcercuei 0:03b5121a232e 5248 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5249
pcercuei 0:03b5121a232e 5250 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5251 if (ret == NULL) {
pcercuei 0:03b5121a232e 5252 xmlXPathErrMemory(NULL, "creating boolean object\n");
pcercuei 0:03b5121a232e 5253 return(NULL);
pcercuei 0:03b5121a232e 5254 }
pcercuei 0:03b5121a232e 5255 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5256 ret->type = XPATH_BOOLEAN;
pcercuei 0:03b5121a232e 5257 ret->boolval = (val != 0);
pcercuei 0:03b5121a232e 5258 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5259 xmlXPathDebugObjUsageRequested(NULL, XPATH_BOOLEAN);
pcercuei 0:03b5121a232e 5260 #endif
pcercuei 0:03b5121a232e 5261 return(ret);
pcercuei 0:03b5121a232e 5262 }
pcercuei 0:03b5121a232e 5263
pcercuei 0:03b5121a232e 5264 /**
pcercuei 0:03b5121a232e 5265 * xmlXPathNewString:
pcercuei 0:03b5121a232e 5266 * @val: the xmlChar * value
pcercuei 0:03b5121a232e 5267 *
pcercuei 0:03b5121a232e 5268 * Create a new xmlXPathObjectPtr of type string and of value @val
pcercuei 0:03b5121a232e 5269 *
pcercuei 0:03b5121a232e 5270 * Returns the newly created object.
pcercuei 0:03b5121a232e 5271 */
pcercuei 0:03b5121a232e 5272 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5273 xmlXPathNewString(const xmlChar *val) {
pcercuei 0:03b5121a232e 5274 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5275
pcercuei 0:03b5121a232e 5276 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5277 if (ret == NULL) {
pcercuei 0:03b5121a232e 5278 xmlXPathErrMemory(NULL, "creating string object\n");
pcercuei 0:03b5121a232e 5279 return(NULL);
pcercuei 0:03b5121a232e 5280 }
pcercuei 0:03b5121a232e 5281 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5282 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 5283 if (val != NULL)
pcercuei 0:03b5121a232e 5284 ret->stringval = xmlStrdup(val);
pcercuei 0:03b5121a232e 5285 else
pcercuei 0:03b5121a232e 5286 ret->stringval = xmlStrdup((const xmlChar *)"");
pcercuei 0:03b5121a232e 5287 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5288 xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
pcercuei 0:03b5121a232e 5289 #endif
pcercuei 0:03b5121a232e 5290 return(ret);
pcercuei 0:03b5121a232e 5291 }
pcercuei 0:03b5121a232e 5292
pcercuei 0:03b5121a232e 5293 /**
pcercuei 0:03b5121a232e 5294 * xmlXPathWrapString:
pcercuei 0:03b5121a232e 5295 * @val: the xmlChar * value
pcercuei 0:03b5121a232e 5296 *
pcercuei 0:03b5121a232e 5297 * Wraps the @val string into an XPath object.
pcercuei 0:03b5121a232e 5298 *
pcercuei 0:03b5121a232e 5299 * Returns the newly created object.
pcercuei 0:03b5121a232e 5300 */
pcercuei 0:03b5121a232e 5301 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5302 xmlXPathWrapString (xmlChar *val) {
pcercuei 0:03b5121a232e 5303 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5304
pcercuei 0:03b5121a232e 5305 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5306 if (ret == NULL) {
pcercuei 0:03b5121a232e 5307 xmlXPathErrMemory(NULL, "creating string object\n");
pcercuei 0:03b5121a232e 5308 return(NULL);
pcercuei 0:03b5121a232e 5309 }
pcercuei 0:03b5121a232e 5310 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5311 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 5312 ret->stringval = val;
pcercuei 0:03b5121a232e 5313 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5314 xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
pcercuei 0:03b5121a232e 5315 #endif
pcercuei 0:03b5121a232e 5316 return(ret);
pcercuei 0:03b5121a232e 5317 }
pcercuei 0:03b5121a232e 5318
pcercuei 0:03b5121a232e 5319 /**
pcercuei 0:03b5121a232e 5320 * xmlXPathNewCString:
pcercuei 0:03b5121a232e 5321 * @val: the char * value
pcercuei 0:03b5121a232e 5322 *
pcercuei 0:03b5121a232e 5323 * Create a new xmlXPathObjectPtr of type string and of value @val
pcercuei 0:03b5121a232e 5324 *
pcercuei 0:03b5121a232e 5325 * Returns the newly created object.
pcercuei 0:03b5121a232e 5326 */
pcercuei 0:03b5121a232e 5327 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5328 xmlXPathNewCString(const char *val) {
pcercuei 0:03b5121a232e 5329 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5330
pcercuei 0:03b5121a232e 5331 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5332 if (ret == NULL) {
pcercuei 0:03b5121a232e 5333 xmlXPathErrMemory(NULL, "creating string object\n");
pcercuei 0:03b5121a232e 5334 return(NULL);
pcercuei 0:03b5121a232e 5335 }
pcercuei 0:03b5121a232e 5336 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5337 ret->type = XPATH_STRING;
pcercuei 0:03b5121a232e 5338 ret->stringval = xmlStrdup(BAD_CAST val);
pcercuei 0:03b5121a232e 5339 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5340 xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING);
pcercuei 0:03b5121a232e 5341 #endif
pcercuei 0:03b5121a232e 5342 return(ret);
pcercuei 0:03b5121a232e 5343 }
pcercuei 0:03b5121a232e 5344
pcercuei 0:03b5121a232e 5345 /**
pcercuei 0:03b5121a232e 5346 * xmlXPathWrapCString:
pcercuei 0:03b5121a232e 5347 * @val: the char * value
pcercuei 0:03b5121a232e 5348 *
pcercuei 0:03b5121a232e 5349 * Wraps a string into an XPath object.
pcercuei 0:03b5121a232e 5350 *
pcercuei 0:03b5121a232e 5351 * Returns the newly created object.
pcercuei 0:03b5121a232e 5352 */
pcercuei 0:03b5121a232e 5353 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5354 xmlXPathWrapCString (char * val) {
pcercuei 0:03b5121a232e 5355 return(xmlXPathWrapString((xmlChar *)(val)));
pcercuei 0:03b5121a232e 5356 }
pcercuei 0:03b5121a232e 5357
pcercuei 0:03b5121a232e 5358 /**
pcercuei 0:03b5121a232e 5359 * xmlXPathWrapExternal:
pcercuei 0:03b5121a232e 5360 * @val: the user data
pcercuei 0:03b5121a232e 5361 *
pcercuei 0:03b5121a232e 5362 * Wraps the @val data into an XPath object.
pcercuei 0:03b5121a232e 5363 *
pcercuei 0:03b5121a232e 5364 * Returns the newly created object.
pcercuei 0:03b5121a232e 5365 */
pcercuei 0:03b5121a232e 5366 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5367 xmlXPathWrapExternal (void *val) {
pcercuei 0:03b5121a232e 5368 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5369
pcercuei 0:03b5121a232e 5370 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5371 if (ret == NULL) {
pcercuei 0:03b5121a232e 5372 xmlXPathErrMemory(NULL, "creating user object\n");
pcercuei 0:03b5121a232e 5373 return(NULL);
pcercuei 0:03b5121a232e 5374 }
pcercuei 0:03b5121a232e 5375 memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5376 ret->type = XPATH_USERS;
pcercuei 0:03b5121a232e 5377 ret->user = val;
pcercuei 0:03b5121a232e 5378 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5379 xmlXPathDebugObjUsageRequested(NULL, XPATH_USERS);
pcercuei 0:03b5121a232e 5380 #endif
pcercuei 0:03b5121a232e 5381 return(ret);
pcercuei 0:03b5121a232e 5382 }
pcercuei 0:03b5121a232e 5383
pcercuei 0:03b5121a232e 5384 /**
pcercuei 0:03b5121a232e 5385 * xmlXPathObjectCopy:
pcercuei 0:03b5121a232e 5386 * @val: the original object
pcercuei 0:03b5121a232e 5387 *
pcercuei 0:03b5121a232e 5388 * allocate a new copy of a given object
pcercuei 0:03b5121a232e 5389 *
pcercuei 0:03b5121a232e 5390 * Returns the newly created object.
pcercuei 0:03b5121a232e 5391 */
pcercuei 0:03b5121a232e 5392 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5393 xmlXPathObjectCopy(xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 5394 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5395
pcercuei 0:03b5121a232e 5396 if (val == NULL)
pcercuei 0:03b5121a232e 5397 return(NULL);
pcercuei 0:03b5121a232e 5398
pcercuei 0:03b5121a232e 5399 ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5400 if (ret == NULL) {
pcercuei 0:03b5121a232e 5401 xmlXPathErrMemory(NULL, "copying object\n");
pcercuei 0:03b5121a232e 5402 return(NULL);
pcercuei 0:03b5121a232e 5403 }
pcercuei 0:03b5121a232e 5404 memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5405 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5406 xmlXPathDebugObjUsageRequested(NULL, val->type);
pcercuei 0:03b5121a232e 5407 #endif
pcercuei 0:03b5121a232e 5408 switch (val->type) {
pcercuei 0:03b5121a232e 5409 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 5410 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 5411 case XPATH_POINT:
pcercuei 0:03b5121a232e 5412 case XPATH_RANGE:
pcercuei 0:03b5121a232e 5413 break;
pcercuei 0:03b5121a232e 5414 case XPATH_STRING:
pcercuei 0:03b5121a232e 5415 ret->stringval = xmlStrdup(val->stringval);
pcercuei 0:03b5121a232e 5416 break;
pcercuei 0:03b5121a232e 5417 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 5418 #if 0
pcercuei 0:03b5121a232e 5419 /*
pcercuei 0:03b5121a232e 5420 Removed 11 July 2004 - the current handling of xslt tmpRVT nodes means that
pcercuei 0:03b5121a232e 5421 this previous handling is no longer correct, and can cause some serious
pcercuei 0:03b5121a232e 5422 problems (ref. bug 145547)
pcercuei 0:03b5121a232e 5423 */
pcercuei 0:03b5121a232e 5424 if ((val->nodesetval != NULL) &&
pcercuei 0:03b5121a232e 5425 (val->nodesetval->nodeTab != NULL)) {
pcercuei 0:03b5121a232e 5426 xmlNodePtr cur, tmp;
pcercuei 0:03b5121a232e 5427 xmlDocPtr top;
pcercuei 0:03b5121a232e 5428
pcercuei 0:03b5121a232e 5429 ret->boolval = 1;
pcercuei 0:03b5121a232e 5430 top = xmlNewDoc(NULL);
pcercuei 0:03b5121a232e 5431 top->name = (char *)
pcercuei 0:03b5121a232e 5432 xmlStrdup(val->nodesetval->nodeTab[0]->name);
pcercuei 0:03b5121a232e 5433 ret->user = top;
pcercuei 0:03b5121a232e 5434 if (top != NULL) {
pcercuei 0:03b5121a232e 5435 top->doc = top;
pcercuei 0:03b5121a232e 5436 cur = val->nodesetval->nodeTab[0]->children;
pcercuei 0:03b5121a232e 5437 while (cur != NULL) {
pcercuei 0:03b5121a232e 5438 tmp = xmlDocCopyNode(cur, top, 1);
pcercuei 0:03b5121a232e 5439 xmlAddChild((xmlNodePtr) top, tmp);
pcercuei 0:03b5121a232e 5440 cur = cur->next;
pcercuei 0:03b5121a232e 5441 }
pcercuei 0:03b5121a232e 5442 }
pcercuei 0:03b5121a232e 5443
pcercuei 0:03b5121a232e 5444 ret->nodesetval = xmlXPathNodeSetCreate((xmlNodePtr) top);
pcercuei 0:03b5121a232e 5445 } else
pcercuei 0:03b5121a232e 5446 ret->nodesetval = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 5447 /* Deallocate the copied tree value */
pcercuei 0:03b5121a232e 5448 break;
pcercuei 0:03b5121a232e 5449 #endif
pcercuei 0:03b5121a232e 5450 case XPATH_NODESET:
pcercuei 0:03b5121a232e 5451 ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
pcercuei 0:03b5121a232e 5452 /* Do not deallocate the copied tree value */
pcercuei 0:03b5121a232e 5453 ret->boolval = 0;
pcercuei 0:03b5121a232e 5454 break;
pcercuei 0:03b5121a232e 5455 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 5456 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 5457 {
pcercuei 0:03b5121a232e 5458 xmlLocationSetPtr loc = val->user;
pcercuei 0:03b5121a232e 5459 ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
pcercuei 0:03b5121a232e 5460 break;
pcercuei 0:03b5121a232e 5461 }
pcercuei 0:03b5121a232e 5462 #endif
pcercuei 0:03b5121a232e 5463 case XPATH_USERS:
pcercuei 0:03b5121a232e 5464 ret->user = val->user;
pcercuei 0:03b5121a232e 5465 break;
pcercuei 0:03b5121a232e 5466 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 5467 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 5468 "xmlXPathObjectCopy: unsupported type %d\n",
pcercuei 0:03b5121a232e 5469 val->type);
pcercuei 0:03b5121a232e 5470 break;
pcercuei 0:03b5121a232e 5471 }
pcercuei 0:03b5121a232e 5472 return(ret);
pcercuei 0:03b5121a232e 5473 }
pcercuei 0:03b5121a232e 5474
pcercuei 0:03b5121a232e 5475 /**
pcercuei 0:03b5121a232e 5476 * xmlXPathFreeObject:
pcercuei 0:03b5121a232e 5477 * @obj: the object to free
pcercuei 0:03b5121a232e 5478 *
pcercuei 0:03b5121a232e 5479 * Free up an xmlXPathObjectPtr object.
pcercuei 0:03b5121a232e 5480 */
pcercuei 0:03b5121a232e 5481 void
pcercuei 0:03b5121a232e 5482 xmlXPathFreeObject(xmlXPathObjectPtr obj) {
pcercuei 0:03b5121a232e 5483 if (obj == NULL) return;
pcercuei 0:03b5121a232e 5484 if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 5485 if (obj->boolval) {
pcercuei 0:03b5121a232e 5486 #if 0
pcercuei 0:03b5121a232e 5487 if (obj->user != NULL) {
pcercuei 0:03b5121a232e 5488 xmlXPathFreeNodeSet(obj->nodesetval);
pcercuei 0:03b5121a232e 5489 xmlFreeNodeList((xmlNodePtr) obj->user);
pcercuei 0:03b5121a232e 5490 } else
pcercuei 0:03b5121a232e 5491 #endif
pcercuei 0:03b5121a232e 5492 obj->type = XPATH_XSLT_TREE; /* TODO: Just for debugging. */
pcercuei 0:03b5121a232e 5493 if (obj->nodesetval != NULL)
pcercuei 0:03b5121a232e 5494 xmlXPathFreeValueTree(obj->nodesetval);
pcercuei 0:03b5121a232e 5495 } else {
pcercuei 0:03b5121a232e 5496 if (obj->nodesetval != NULL)
pcercuei 0:03b5121a232e 5497 xmlXPathFreeNodeSet(obj->nodesetval);
pcercuei 0:03b5121a232e 5498 }
pcercuei 0:03b5121a232e 5499 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 5500 } else if (obj->type == XPATH_LOCATIONSET) {
pcercuei 0:03b5121a232e 5501 if (obj->user != NULL)
pcercuei 0:03b5121a232e 5502 xmlXPtrFreeLocationSet(obj->user);
pcercuei 0:03b5121a232e 5503 #endif
pcercuei 0:03b5121a232e 5504 } else if (obj->type == XPATH_STRING) {
pcercuei 0:03b5121a232e 5505 if (obj->stringval != NULL)
pcercuei 0:03b5121a232e 5506 xmlFree(obj->stringval);
pcercuei 0:03b5121a232e 5507 }
pcercuei 0:03b5121a232e 5508 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5509 xmlXPathDebugObjUsageReleased(NULL, obj->type);
pcercuei 0:03b5121a232e 5510 #endif
pcercuei 0:03b5121a232e 5511 xmlFree(obj);
pcercuei 0:03b5121a232e 5512 }
pcercuei 0:03b5121a232e 5513
pcercuei 0:03b5121a232e 5514 /**
pcercuei 0:03b5121a232e 5515 * xmlXPathReleaseObject:
pcercuei 0:03b5121a232e 5516 * @obj: the xmlXPathObjectPtr to free or to cache
pcercuei 0:03b5121a232e 5517 *
pcercuei 0:03b5121a232e 5518 * Depending on the state of the cache this frees the given
pcercuei 0:03b5121a232e 5519 * XPath object or stores it in the cache.
pcercuei 0:03b5121a232e 5520 */
pcercuei 0:03b5121a232e 5521 static void
pcercuei 0:03b5121a232e 5522 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
pcercuei 0:03b5121a232e 5523 {
pcercuei 0:03b5121a232e 5524 #define XP_CACHE_ADD(sl, o) if (sl == NULL) { \
pcercuei 0:03b5121a232e 5525 sl = xmlPointerListCreate(10); if (sl == NULL) goto free_obj; } \
pcercuei 0:03b5121a232e 5526 if (xmlPointerListAddSize(sl, obj, 0) == -1) goto free_obj;
pcercuei 0:03b5121a232e 5527
pcercuei 0:03b5121a232e 5528 #define XP_CACHE_WANTS(sl, n) ((sl == NULL) || ((sl)->number < n))
pcercuei 0:03b5121a232e 5529
pcercuei 0:03b5121a232e 5530 if (obj == NULL)
pcercuei 0:03b5121a232e 5531 return;
pcercuei 0:03b5121a232e 5532 if ((ctxt == NULL) || (ctxt->cache == NULL)) {
pcercuei 0:03b5121a232e 5533 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 5534 } else {
pcercuei 0:03b5121a232e 5535 xmlXPathContextCachePtr cache =
pcercuei 0:03b5121a232e 5536 (xmlXPathContextCachePtr) ctxt->cache;
pcercuei 0:03b5121a232e 5537
pcercuei 0:03b5121a232e 5538 switch (obj->type) {
pcercuei 0:03b5121a232e 5539 case XPATH_NODESET:
pcercuei 0:03b5121a232e 5540 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 5541 if (obj->nodesetval != NULL) {
pcercuei 0:03b5121a232e 5542 if (obj->boolval) {
pcercuei 0:03b5121a232e 5543 /*
pcercuei 0:03b5121a232e 5544 * It looks like the @boolval is used for
pcercuei 0:03b5121a232e 5545 * evaluation if this an XSLT Result Tree Fragment.
pcercuei 0:03b5121a232e 5546 * TODO: Check if this assumption is correct.
pcercuei 0:03b5121a232e 5547 */
pcercuei 0:03b5121a232e 5548 obj->type = XPATH_XSLT_TREE; /* just for debugging */
pcercuei 0:03b5121a232e 5549 xmlXPathFreeValueTree(obj->nodesetval);
pcercuei 0:03b5121a232e 5550 obj->nodesetval = NULL;
pcercuei 0:03b5121a232e 5551 } else if ((obj->nodesetval->nodeMax <= 40) &&
pcercuei 0:03b5121a232e 5552 (XP_CACHE_WANTS(cache->nodesetObjs,
pcercuei 0:03b5121a232e 5553 cache->maxNodeset)))
pcercuei 0:03b5121a232e 5554 {
pcercuei 0:03b5121a232e 5555 XP_CACHE_ADD(cache->nodesetObjs, obj);
pcercuei 0:03b5121a232e 5556 goto obj_cached;
pcercuei 0:03b5121a232e 5557 } else {
pcercuei 0:03b5121a232e 5558 xmlXPathFreeNodeSet(obj->nodesetval);
pcercuei 0:03b5121a232e 5559 obj->nodesetval = NULL;
pcercuei 0:03b5121a232e 5560 }
pcercuei 0:03b5121a232e 5561 }
pcercuei 0:03b5121a232e 5562 break;
pcercuei 0:03b5121a232e 5563 case XPATH_STRING:
pcercuei 0:03b5121a232e 5564 if (obj->stringval != NULL)
pcercuei 0:03b5121a232e 5565 xmlFree(obj->stringval);
pcercuei 0:03b5121a232e 5566
pcercuei 0:03b5121a232e 5567 if (XP_CACHE_WANTS(cache->stringObjs, cache->maxString)) {
pcercuei 0:03b5121a232e 5568 XP_CACHE_ADD(cache->stringObjs, obj);
pcercuei 0:03b5121a232e 5569 goto obj_cached;
pcercuei 0:03b5121a232e 5570 }
pcercuei 0:03b5121a232e 5571 break;
pcercuei 0:03b5121a232e 5572 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 5573 if (XP_CACHE_WANTS(cache->booleanObjs, cache->maxBoolean)) {
pcercuei 0:03b5121a232e 5574 XP_CACHE_ADD(cache->booleanObjs, obj);
pcercuei 0:03b5121a232e 5575 goto obj_cached;
pcercuei 0:03b5121a232e 5576 }
pcercuei 0:03b5121a232e 5577 break;
pcercuei 0:03b5121a232e 5578 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 5579 if (XP_CACHE_WANTS(cache->numberObjs, cache->maxNumber)) {
pcercuei 0:03b5121a232e 5580 XP_CACHE_ADD(cache->numberObjs, obj);
pcercuei 0:03b5121a232e 5581 goto obj_cached;
pcercuei 0:03b5121a232e 5582 }
pcercuei 0:03b5121a232e 5583 break;
pcercuei 0:03b5121a232e 5584 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 5585 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 5586 if (obj->user != NULL) {
pcercuei 0:03b5121a232e 5587 xmlXPtrFreeLocationSet(obj->user);
pcercuei 0:03b5121a232e 5588 }
pcercuei 0:03b5121a232e 5589 goto free_obj;
pcercuei 0:03b5121a232e 5590 #endif
pcercuei 0:03b5121a232e 5591 default:
pcercuei 0:03b5121a232e 5592 goto free_obj;
pcercuei 0:03b5121a232e 5593 }
pcercuei 0:03b5121a232e 5594
pcercuei 0:03b5121a232e 5595 /*
pcercuei 0:03b5121a232e 5596 * Fallback to adding to the misc-objects slot.
pcercuei 0:03b5121a232e 5597 */
pcercuei 0:03b5121a232e 5598 if (XP_CACHE_WANTS(cache->miscObjs, cache->maxMisc)) {
pcercuei 0:03b5121a232e 5599 XP_CACHE_ADD(cache->miscObjs, obj);
pcercuei 0:03b5121a232e 5600 } else
pcercuei 0:03b5121a232e 5601 goto free_obj;
pcercuei 0:03b5121a232e 5602
pcercuei 0:03b5121a232e 5603 obj_cached:
pcercuei 0:03b5121a232e 5604
pcercuei 0:03b5121a232e 5605 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5606 xmlXPathDebugObjUsageReleased(ctxt, obj->type);
pcercuei 0:03b5121a232e 5607 #endif
pcercuei 0:03b5121a232e 5608
pcercuei 0:03b5121a232e 5609 if (obj->nodesetval != NULL) {
pcercuei 0:03b5121a232e 5610 xmlNodeSetPtr tmpset = obj->nodesetval;
pcercuei 0:03b5121a232e 5611
pcercuei 0:03b5121a232e 5612 /*
pcercuei 0:03b5121a232e 5613 * TODO: Due to those nasty ns-nodes, we need to traverse
pcercuei 0:03b5121a232e 5614 * the list and free the ns-nodes.
pcercuei 0:03b5121a232e 5615 * URGENT TODO: Check if it's actually slowing things down.
pcercuei 0:03b5121a232e 5616 * Maybe we shouldn't try to preserve the list.
pcercuei 0:03b5121a232e 5617 */
pcercuei 0:03b5121a232e 5618 if (tmpset->nodeNr > 1) {
pcercuei 0:03b5121a232e 5619 int i;
pcercuei 0:03b5121a232e 5620 xmlNodePtr node;
pcercuei 0:03b5121a232e 5621
pcercuei 0:03b5121a232e 5622 for (i = 0; i < tmpset->nodeNr; i++) {
pcercuei 0:03b5121a232e 5623 node = tmpset->nodeTab[i];
pcercuei 0:03b5121a232e 5624 if ((node != NULL) &&
pcercuei 0:03b5121a232e 5625 (node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 5626 {
pcercuei 0:03b5121a232e 5627 xmlXPathNodeSetFreeNs((xmlNsPtr) node);
pcercuei 0:03b5121a232e 5628 }
pcercuei 0:03b5121a232e 5629 }
pcercuei 0:03b5121a232e 5630 } else if (tmpset->nodeNr == 1) {
pcercuei 0:03b5121a232e 5631 if ((tmpset->nodeTab[0] != NULL) &&
pcercuei 0:03b5121a232e 5632 (tmpset->nodeTab[0]->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 5633 xmlXPathNodeSetFreeNs((xmlNsPtr) tmpset->nodeTab[0]);
pcercuei 0:03b5121a232e 5634 }
pcercuei 0:03b5121a232e 5635 tmpset->nodeNr = 0;
pcercuei 0:03b5121a232e 5636 memset(obj, 0, sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5637 obj->nodesetval = tmpset;
pcercuei 0:03b5121a232e 5638 } else
pcercuei 0:03b5121a232e 5639 memset(obj, 0, sizeof(xmlXPathObject));
pcercuei 0:03b5121a232e 5640
pcercuei 0:03b5121a232e 5641 return;
pcercuei 0:03b5121a232e 5642
pcercuei 0:03b5121a232e 5643 free_obj:
pcercuei 0:03b5121a232e 5644 /*
pcercuei 0:03b5121a232e 5645 * Cache is full; free the object.
pcercuei 0:03b5121a232e 5646 */
pcercuei 0:03b5121a232e 5647 if (obj->nodesetval != NULL)
pcercuei 0:03b5121a232e 5648 xmlXPathFreeNodeSet(obj->nodesetval);
pcercuei 0:03b5121a232e 5649 #ifdef XP_DEBUG_OBJ_USAGE
pcercuei 0:03b5121a232e 5650 xmlXPathDebugObjUsageReleased(NULL, obj->type);
pcercuei 0:03b5121a232e 5651 #endif
pcercuei 0:03b5121a232e 5652 xmlFree(obj);
pcercuei 0:03b5121a232e 5653 }
pcercuei 0:03b5121a232e 5654 return;
pcercuei 0:03b5121a232e 5655 }
pcercuei 0:03b5121a232e 5656
pcercuei 0:03b5121a232e 5657
pcercuei 0:03b5121a232e 5658 /************************************************************************
pcercuei 0:03b5121a232e 5659 * *
pcercuei 0:03b5121a232e 5660 * Type Casting Routines *
pcercuei 0:03b5121a232e 5661 * *
pcercuei 0:03b5121a232e 5662 ************************************************************************/
pcercuei 0:03b5121a232e 5663
pcercuei 0:03b5121a232e 5664 /**
pcercuei 0:03b5121a232e 5665 * xmlXPathCastBooleanToString:
pcercuei 0:03b5121a232e 5666 * @val: a boolean
pcercuei 0:03b5121a232e 5667 *
pcercuei 0:03b5121a232e 5668 * Converts a boolean to its string value.
pcercuei 0:03b5121a232e 5669 *
pcercuei 0:03b5121a232e 5670 * Returns a newly allocated string.
pcercuei 0:03b5121a232e 5671 */
pcercuei 0:03b5121a232e 5672 xmlChar *
pcercuei 0:03b5121a232e 5673 xmlXPathCastBooleanToString (int val) {
pcercuei 0:03b5121a232e 5674 xmlChar *ret;
pcercuei 0:03b5121a232e 5675 if (val)
pcercuei 0:03b5121a232e 5676 ret = xmlStrdup((const xmlChar *) "true");
pcercuei 0:03b5121a232e 5677 else
pcercuei 0:03b5121a232e 5678 ret = xmlStrdup((const xmlChar *) "false");
pcercuei 0:03b5121a232e 5679 return(ret);
pcercuei 0:03b5121a232e 5680 }
pcercuei 0:03b5121a232e 5681
pcercuei 0:03b5121a232e 5682 /**
pcercuei 0:03b5121a232e 5683 * xmlXPathCastNumberToString:
pcercuei 0:03b5121a232e 5684 * @val: a number
pcercuei 0:03b5121a232e 5685 *
pcercuei 0:03b5121a232e 5686 * Converts a number to its string value.
pcercuei 0:03b5121a232e 5687 *
pcercuei 0:03b5121a232e 5688 * Returns a newly allocated string.
pcercuei 0:03b5121a232e 5689 */
pcercuei 0:03b5121a232e 5690 xmlChar *
pcercuei 0:03b5121a232e 5691 xmlXPathCastNumberToString (double val) {
pcercuei 0:03b5121a232e 5692 xmlChar *ret;
pcercuei 0:03b5121a232e 5693 switch (xmlXPathIsInf(val)) {
pcercuei 0:03b5121a232e 5694 case 1:
pcercuei 0:03b5121a232e 5695 ret = xmlStrdup((const xmlChar *) "Infinity");
pcercuei 0:03b5121a232e 5696 break;
pcercuei 0:03b5121a232e 5697 case -1:
pcercuei 0:03b5121a232e 5698 ret = xmlStrdup((const xmlChar *) "-Infinity");
pcercuei 0:03b5121a232e 5699 break;
pcercuei 0:03b5121a232e 5700 default:
pcercuei 0:03b5121a232e 5701 if (xmlXPathIsNaN(val)) {
pcercuei 0:03b5121a232e 5702 ret = xmlStrdup((const xmlChar *) "NaN");
pcercuei 0:03b5121a232e 5703 } else if (val == 0 && xmlXPathGetSign(val) != 0) {
pcercuei 0:03b5121a232e 5704 ret = xmlStrdup((const xmlChar *) "0");
pcercuei 0:03b5121a232e 5705 } else {
pcercuei 0:03b5121a232e 5706 /* could be improved */
pcercuei 0:03b5121a232e 5707 char buf[100];
pcercuei 0:03b5121a232e 5708 xmlXPathFormatNumber(val, buf, 99);
pcercuei 0:03b5121a232e 5709 buf[99] = 0;
pcercuei 0:03b5121a232e 5710 ret = xmlStrdup((const xmlChar *) buf);
pcercuei 0:03b5121a232e 5711 }
pcercuei 0:03b5121a232e 5712 }
pcercuei 0:03b5121a232e 5713 return(ret);
pcercuei 0:03b5121a232e 5714 }
pcercuei 0:03b5121a232e 5715
pcercuei 0:03b5121a232e 5716 /**
pcercuei 0:03b5121a232e 5717 * xmlXPathCastNodeToString:
pcercuei 0:03b5121a232e 5718 * @node: a node
pcercuei 0:03b5121a232e 5719 *
pcercuei 0:03b5121a232e 5720 * Converts a node to its string value.
pcercuei 0:03b5121a232e 5721 *
pcercuei 0:03b5121a232e 5722 * Returns a newly allocated string.
pcercuei 0:03b5121a232e 5723 */
pcercuei 0:03b5121a232e 5724 xmlChar *
pcercuei 0:03b5121a232e 5725 xmlXPathCastNodeToString (xmlNodePtr node) {
pcercuei 0:03b5121a232e 5726 xmlChar *ret;
pcercuei 0:03b5121a232e 5727 if ((ret = xmlNodeGetContent(node)) == NULL)
pcercuei 0:03b5121a232e 5728 ret = xmlStrdup((const xmlChar *) "");
pcercuei 0:03b5121a232e 5729 return(ret);
pcercuei 0:03b5121a232e 5730 }
pcercuei 0:03b5121a232e 5731
pcercuei 0:03b5121a232e 5732 /**
pcercuei 0:03b5121a232e 5733 * xmlXPathCastNodeSetToString:
pcercuei 0:03b5121a232e 5734 * @ns: a node-set
pcercuei 0:03b5121a232e 5735 *
pcercuei 0:03b5121a232e 5736 * Converts a node-set to its string value.
pcercuei 0:03b5121a232e 5737 *
pcercuei 0:03b5121a232e 5738 * Returns a newly allocated string.
pcercuei 0:03b5121a232e 5739 */
pcercuei 0:03b5121a232e 5740 xmlChar *
pcercuei 0:03b5121a232e 5741 xmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
pcercuei 0:03b5121a232e 5742 if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
pcercuei 0:03b5121a232e 5743 return(xmlStrdup((const xmlChar *) ""));
pcercuei 0:03b5121a232e 5744
pcercuei 0:03b5121a232e 5745 if (ns->nodeNr > 1)
pcercuei 0:03b5121a232e 5746 xmlXPathNodeSetSort(ns);
pcercuei 0:03b5121a232e 5747 return(xmlXPathCastNodeToString(ns->nodeTab[0]));
pcercuei 0:03b5121a232e 5748 }
pcercuei 0:03b5121a232e 5749
pcercuei 0:03b5121a232e 5750 /**
pcercuei 0:03b5121a232e 5751 * xmlXPathCastToString:
pcercuei 0:03b5121a232e 5752 * @val: an XPath object
pcercuei 0:03b5121a232e 5753 *
pcercuei 0:03b5121a232e 5754 * Converts an existing object to its string() equivalent
pcercuei 0:03b5121a232e 5755 *
pcercuei 0:03b5121a232e 5756 * Returns the allocated string value of the object, NULL in case of error.
pcercuei 0:03b5121a232e 5757 * It's up to the caller to free the string memory with xmlFree().
pcercuei 0:03b5121a232e 5758 */
pcercuei 0:03b5121a232e 5759 xmlChar *
pcercuei 0:03b5121a232e 5760 xmlXPathCastToString(xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 5761 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 5762
pcercuei 0:03b5121a232e 5763 if (val == NULL)
pcercuei 0:03b5121a232e 5764 return(xmlStrdup((const xmlChar *) ""));
pcercuei 0:03b5121a232e 5765 switch (val->type) {
pcercuei 0:03b5121a232e 5766 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 5767 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 5768 xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
pcercuei 0:03b5121a232e 5769 #endif
pcercuei 0:03b5121a232e 5770 ret = xmlStrdup((const xmlChar *) "");
pcercuei 0:03b5121a232e 5771 break;
pcercuei 0:03b5121a232e 5772 case XPATH_NODESET:
pcercuei 0:03b5121a232e 5773 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 5774 ret = xmlXPathCastNodeSetToString(val->nodesetval);
pcercuei 0:03b5121a232e 5775 break;
pcercuei 0:03b5121a232e 5776 case XPATH_STRING:
pcercuei 0:03b5121a232e 5777 return(xmlStrdup(val->stringval));
pcercuei 0:03b5121a232e 5778 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 5779 ret = xmlXPathCastBooleanToString(val->boolval);
pcercuei 0:03b5121a232e 5780 break;
pcercuei 0:03b5121a232e 5781 case XPATH_NUMBER: {
pcercuei 0:03b5121a232e 5782 ret = xmlXPathCastNumberToString(val->floatval);
pcercuei 0:03b5121a232e 5783 break;
pcercuei 0:03b5121a232e 5784 }
pcercuei 0:03b5121a232e 5785 case XPATH_USERS:
pcercuei 0:03b5121a232e 5786 case XPATH_POINT:
pcercuei 0:03b5121a232e 5787 case XPATH_RANGE:
pcercuei 0:03b5121a232e 5788 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 5789 TODO
pcercuei 0:03b5121a232e 5790 ret = xmlStrdup((const xmlChar *) "");
pcercuei 0:03b5121a232e 5791 break;
pcercuei 0:03b5121a232e 5792 }
pcercuei 0:03b5121a232e 5793 return(ret);
pcercuei 0:03b5121a232e 5794 }
pcercuei 0:03b5121a232e 5795
pcercuei 0:03b5121a232e 5796 /**
pcercuei 0:03b5121a232e 5797 * xmlXPathConvertString:
pcercuei 0:03b5121a232e 5798 * @val: an XPath object
pcercuei 0:03b5121a232e 5799 *
pcercuei 0:03b5121a232e 5800 * Converts an existing object to its string() equivalent
pcercuei 0:03b5121a232e 5801 *
pcercuei 0:03b5121a232e 5802 * Returns the new object, the old one is freed (or the operation
pcercuei 0:03b5121a232e 5803 * is done directly on @val)
pcercuei 0:03b5121a232e 5804 */
pcercuei 0:03b5121a232e 5805 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5806 xmlXPathConvertString(xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 5807 xmlChar *res = NULL;
pcercuei 0:03b5121a232e 5808
pcercuei 0:03b5121a232e 5809 if (val == NULL)
pcercuei 0:03b5121a232e 5810 return(xmlXPathNewCString(""));
pcercuei 0:03b5121a232e 5811
pcercuei 0:03b5121a232e 5812 switch (val->type) {
pcercuei 0:03b5121a232e 5813 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 5814 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 5815 xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
pcercuei 0:03b5121a232e 5816 #endif
pcercuei 0:03b5121a232e 5817 break;
pcercuei 0:03b5121a232e 5818 case XPATH_NODESET:
pcercuei 0:03b5121a232e 5819 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 5820 res = xmlXPathCastNodeSetToString(val->nodesetval);
pcercuei 0:03b5121a232e 5821 break;
pcercuei 0:03b5121a232e 5822 case XPATH_STRING:
pcercuei 0:03b5121a232e 5823 return(val);
pcercuei 0:03b5121a232e 5824 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 5825 res = xmlXPathCastBooleanToString(val->boolval);
pcercuei 0:03b5121a232e 5826 break;
pcercuei 0:03b5121a232e 5827 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 5828 res = xmlXPathCastNumberToString(val->floatval);
pcercuei 0:03b5121a232e 5829 break;
pcercuei 0:03b5121a232e 5830 case XPATH_USERS:
pcercuei 0:03b5121a232e 5831 case XPATH_POINT:
pcercuei 0:03b5121a232e 5832 case XPATH_RANGE:
pcercuei 0:03b5121a232e 5833 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 5834 TODO;
pcercuei 0:03b5121a232e 5835 break;
pcercuei 0:03b5121a232e 5836 }
pcercuei 0:03b5121a232e 5837 xmlXPathFreeObject(val);
pcercuei 0:03b5121a232e 5838 if (res == NULL)
pcercuei 0:03b5121a232e 5839 return(xmlXPathNewCString(""));
pcercuei 0:03b5121a232e 5840 return(xmlXPathWrapString(res));
pcercuei 0:03b5121a232e 5841 }
pcercuei 0:03b5121a232e 5842
pcercuei 0:03b5121a232e 5843 /**
pcercuei 0:03b5121a232e 5844 * xmlXPathCastBooleanToNumber:
pcercuei 0:03b5121a232e 5845 * @val: a boolean
pcercuei 0:03b5121a232e 5846 *
pcercuei 0:03b5121a232e 5847 * Converts a boolean to its number value
pcercuei 0:03b5121a232e 5848 *
pcercuei 0:03b5121a232e 5849 * Returns the number value
pcercuei 0:03b5121a232e 5850 */
pcercuei 0:03b5121a232e 5851 double
pcercuei 0:03b5121a232e 5852 xmlXPathCastBooleanToNumber(int val) {
pcercuei 0:03b5121a232e 5853 if (val)
pcercuei 0:03b5121a232e 5854 return(1.0);
pcercuei 0:03b5121a232e 5855 return(0.0);
pcercuei 0:03b5121a232e 5856 }
pcercuei 0:03b5121a232e 5857
pcercuei 0:03b5121a232e 5858 /**
pcercuei 0:03b5121a232e 5859 * xmlXPathCastStringToNumber:
pcercuei 0:03b5121a232e 5860 * @val: a string
pcercuei 0:03b5121a232e 5861 *
pcercuei 0:03b5121a232e 5862 * Converts a string to its number value
pcercuei 0:03b5121a232e 5863 *
pcercuei 0:03b5121a232e 5864 * Returns the number value
pcercuei 0:03b5121a232e 5865 */
pcercuei 0:03b5121a232e 5866 double
pcercuei 0:03b5121a232e 5867 xmlXPathCastStringToNumber(const xmlChar * val) {
pcercuei 0:03b5121a232e 5868 return(xmlXPathStringEvalNumber(val));
pcercuei 0:03b5121a232e 5869 }
pcercuei 0:03b5121a232e 5870
pcercuei 0:03b5121a232e 5871 /**
pcercuei 0:03b5121a232e 5872 * xmlXPathCastNodeToNumber:
pcercuei 0:03b5121a232e 5873 * @node: a node
pcercuei 0:03b5121a232e 5874 *
pcercuei 0:03b5121a232e 5875 * Converts a node to its number value
pcercuei 0:03b5121a232e 5876 *
pcercuei 0:03b5121a232e 5877 * Returns the number value
pcercuei 0:03b5121a232e 5878 */
pcercuei 0:03b5121a232e 5879 double
pcercuei 0:03b5121a232e 5880 xmlXPathCastNodeToNumber (xmlNodePtr node) {
pcercuei 0:03b5121a232e 5881 xmlChar *strval;
pcercuei 0:03b5121a232e 5882 double ret;
pcercuei 0:03b5121a232e 5883
pcercuei 0:03b5121a232e 5884 if (node == NULL)
pcercuei 0:03b5121a232e 5885 return(xmlXPathNAN);
pcercuei 0:03b5121a232e 5886 strval = xmlXPathCastNodeToString(node);
pcercuei 0:03b5121a232e 5887 if (strval == NULL)
pcercuei 0:03b5121a232e 5888 return(xmlXPathNAN);
pcercuei 0:03b5121a232e 5889 ret = xmlXPathCastStringToNumber(strval);
pcercuei 0:03b5121a232e 5890 xmlFree(strval);
pcercuei 0:03b5121a232e 5891
pcercuei 0:03b5121a232e 5892 return(ret);
pcercuei 0:03b5121a232e 5893 }
pcercuei 0:03b5121a232e 5894
pcercuei 0:03b5121a232e 5895 /**
pcercuei 0:03b5121a232e 5896 * xmlXPathCastNodeSetToNumber:
pcercuei 0:03b5121a232e 5897 * @ns: a node-set
pcercuei 0:03b5121a232e 5898 *
pcercuei 0:03b5121a232e 5899 * Converts a node-set to its number value
pcercuei 0:03b5121a232e 5900 *
pcercuei 0:03b5121a232e 5901 * Returns the number value
pcercuei 0:03b5121a232e 5902 */
pcercuei 0:03b5121a232e 5903 double
pcercuei 0:03b5121a232e 5904 xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
pcercuei 0:03b5121a232e 5905 xmlChar *str;
pcercuei 0:03b5121a232e 5906 double ret;
pcercuei 0:03b5121a232e 5907
pcercuei 0:03b5121a232e 5908 if (ns == NULL)
pcercuei 0:03b5121a232e 5909 return(xmlXPathNAN);
pcercuei 0:03b5121a232e 5910 str = xmlXPathCastNodeSetToString(ns);
pcercuei 0:03b5121a232e 5911 ret = xmlXPathCastStringToNumber(str);
pcercuei 0:03b5121a232e 5912 xmlFree(str);
pcercuei 0:03b5121a232e 5913 return(ret);
pcercuei 0:03b5121a232e 5914 }
pcercuei 0:03b5121a232e 5915
pcercuei 0:03b5121a232e 5916 /**
pcercuei 0:03b5121a232e 5917 * xmlXPathCastToNumber:
pcercuei 0:03b5121a232e 5918 * @val: an XPath object
pcercuei 0:03b5121a232e 5919 *
pcercuei 0:03b5121a232e 5920 * Converts an XPath object to its number value
pcercuei 0:03b5121a232e 5921 *
pcercuei 0:03b5121a232e 5922 * Returns the number value
pcercuei 0:03b5121a232e 5923 */
pcercuei 0:03b5121a232e 5924 double
pcercuei 0:03b5121a232e 5925 xmlXPathCastToNumber(xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 5926 double ret = 0.0;
pcercuei 0:03b5121a232e 5927
pcercuei 0:03b5121a232e 5928 if (val == NULL)
pcercuei 0:03b5121a232e 5929 return(xmlXPathNAN);
pcercuei 0:03b5121a232e 5930 switch (val->type) {
pcercuei 0:03b5121a232e 5931 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 5932 #ifdef DEGUB_EXPR
pcercuei 0:03b5121a232e 5933 xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
pcercuei 0:03b5121a232e 5934 #endif
pcercuei 0:03b5121a232e 5935 ret = xmlXPathNAN;
pcercuei 0:03b5121a232e 5936 break;
pcercuei 0:03b5121a232e 5937 case XPATH_NODESET:
pcercuei 0:03b5121a232e 5938 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 5939 ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
pcercuei 0:03b5121a232e 5940 break;
pcercuei 0:03b5121a232e 5941 case XPATH_STRING:
pcercuei 0:03b5121a232e 5942 ret = xmlXPathCastStringToNumber(val->stringval);
pcercuei 0:03b5121a232e 5943 break;
pcercuei 0:03b5121a232e 5944 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 5945 ret = val->floatval;
pcercuei 0:03b5121a232e 5946 break;
pcercuei 0:03b5121a232e 5947 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 5948 ret = xmlXPathCastBooleanToNumber(val->boolval);
pcercuei 0:03b5121a232e 5949 break;
pcercuei 0:03b5121a232e 5950 case XPATH_USERS:
pcercuei 0:03b5121a232e 5951 case XPATH_POINT:
pcercuei 0:03b5121a232e 5952 case XPATH_RANGE:
pcercuei 0:03b5121a232e 5953 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 5954 TODO;
pcercuei 0:03b5121a232e 5955 ret = xmlXPathNAN;
pcercuei 0:03b5121a232e 5956 break;
pcercuei 0:03b5121a232e 5957 }
pcercuei 0:03b5121a232e 5958 return(ret);
pcercuei 0:03b5121a232e 5959 }
pcercuei 0:03b5121a232e 5960
pcercuei 0:03b5121a232e 5961 /**
pcercuei 0:03b5121a232e 5962 * xmlXPathConvertNumber:
pcercuei 0:03b5121a232e 5963 * @val: an XPath object
pcercuei 0:03b5121a232e 5964 *
pcercuei 0:03b5121a232e 5965 * Converts an existing object to its number() equivalent
pcercuei 0:03b5121a232e 5966 *
pcercuei 0:03b5121a232e 5967 * Returns the new object, the old one is freed (or the operation
pcercuei 0:03b5121a232e 5968 * is done directly on @val)
pcercuei 0:03b5121a232e 5969 */
pcercuei 0:03b5121a232e 5970 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 5971 xmlXPathConvertNumber(xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 5972 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 5973
pcercuei 0:03b5121a232e 5974 if (val == NULL)
pcercuei 0:03b5121a232e 5975 return(xmlXPathNewFloat(0.0));
pcercuei 0:03b5121a232e 5976 if (val->type == XPATH_NUMBER)
pcercuei 0:03b5121a232e 5977 return(val);
pcercuei 0:03b5121a232e 5978 ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
pcercuei 0:03b5121a232e 5979 xmlXPathFreeObject(val);
pcercuei 0:03b5121a232e 5980 return(ret);
pcercuei 0:03b5121a232e 5981 }
pcercuei 0:03b5121a232e 5982
pcercuei 0:03b5121a232e 5983 /**
pcercuei 0:03b5121a232e 5984 * xmlXPathCastNumberToBoolean:
pcercuei 0:03b5121a232e 5985 * @val: a number
pcercuei 0:03b5121a232e 5986 *
pcercuei 0:03b5121a232e 5987 * Converts a number to its boolean value
pcercuei 0:03b5121a232e 5988 *
pcercuei 0:03b5121a232e 5989 * Returns the boolean value
pcercuei 0:03b5121a232e 5990 */
pcercuei 0:03b5121a232e 5991 int
pcercuei 0:03b5121a232e 5992 xmlXPathCastNumberToBoolean (double val) {
pcercuei 0:03b5121a232e 5993 if (xmlXPathIsNaN(val) || (val == 0.0))
pcercuei 0:03b5121a232e 5994 return(0);
pcercuei 0:03b5121a232e 5995 return(1);
pcercuei 0:03b5121a232e 5996 }
pcercuei 0:03b5121a232e 5997
pcercuei 0:03b5121a232e 5998 /**
pcercuei 0:03b5121a232e 5999 * xmlXPathCastStringToBoolean:
pcercuei 0:03b5121a232e 6000 * @val: a string
pcercuei 0:03b5121a232e 6001 *
pcercuei 0:03b5121a232e 6002 * Converts a string to its boolean value
pcercuei 0:03b5121a232e 6003 *
pcercuei 0:03b5121a232e 6004 * Returns the boolean value
pcercuei 0:03b5121a232e 6005 */
pcercuei 0:03b5121a232e 6006 int
pcercuei 0:03b5121a232e 6007 xmlXPathCastStringToBoolean (const xmlChar *val) {
pcercuei 0:03b5121a232e 6008 if ((val == NULL) || (xmlStrlen(val) == 0))
pcercuei 0:03b5121a232e 6009 return(0);
pcercuei 0:03b5121a232e 6010 return(1);
pcercuei 0:03b5121a232e 6011 }
pcercuei 0:03b5121a232e 6012
pcercuei 0:03b5121a232e 6013 /**
pcercuei 0:03b5121a232e 6014 * xmlXPathCastNodeSetToBoolean:
pcercuei 0:03b5121a232e 6015 * @ns: a node-set
pcercuei 0:03b5121a232e 6016 *
pcercuei 0:03b5121a232e 6017 * Converts a node-set to its boolean value
pcercuei 0:03b5121a232e 6018 *
pcercuei 0:03b5121a232e 6019 * Returns the boolean value
pcercuei 0:03b5121a232e 6020 */
pcercuei 0:03b5121a232e 6021 int
pcercuei 0:03b5121a232e 6022 xmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
pcercuei 0:03b5121a232e 6023 if ((ns == NULL) || (ns->nodeNr == 0))
pcercuei 0:03b5121a232e 6024 return(0);
pcercuei 0:03b5121a232e 6025 return(1);
pcercuei 0:03b5121a232e 6026 }
pcercuei 0:03b5121a232e 6027
pcercuei 0:03b5121a232e 6028 /**
pcercuei 0:03b5121a232e 6029 * xmlXPathCastToBoolean:
pcercuei 0:03b5121a232e 6030 * @val: an XPath object
pcercuei 0:03b5121a232e 6031 *
pcercuei 0:03b5121a232e 6032 * Converts an XPath object to its boolean value
pcercuei 0:03b5121a232e 6033 *
pcercuei 0:03b5121a232e 6034 * Returns the boolean value
pcercuei 0:03b5121a232e 6035 */
pcercuei 0:03b5121a232e 6036 int
pcercuei 0:03b5121a232e 6037 xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 6038 int ret = 0;
pcercuei 0:03b5121a232e 6039
pcercuei 0:03b5121a232e 6040 if (val == NULL)
pcercuei 0:03b5121a232e 6041 return(0);
pcercuei 0:03b5121a232e 6042 switch (val->type) {
pcercuei 0:03b5121a232e 6043 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 6044 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 6045 xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
pcercuei 0:03b5121a232e 6046 #endif
pcercuei 0:03b5121a232e 6047 ret = 0;
pcercuei 0:03b5121a232e 6048 break;
pcercuei 0:03b5121a232e 6049 case XPATH_NODESET:
pcercuei 0:03b5121a232e 6050 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 6051 ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
pcercuei 0:03b5121a232e 6052 break;
pcercuei 0:03b5121a232e 6053 case XPATH_STRING:
pcercuei 0:03b5121a232e 6054 ret = xmlXPathCastStringToBoolean(val->stringval);
pcercuei 0:03b5121a232e 6055 break;
pcercuei 0:03b5121a232e 6056 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 6057 ret = xmlXPathCastNumberToBoolean(val->floatval);
pcercuei 0:03b5121a232e 6058 break;
pcercuei 0:03b5121a232e 6059 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 6060 ret = val->boolval;
pcercuei 0:03b5121a232e 6061 break;
pcercuei 0:03b5121a232e 6062 case XPATH_USERS:
pcercuei 0:03b5121a232e 6063 case XPATH_POINT:
pcercuei 0:03b5121a232e 6064 case XPATH_RANGE:
pcercuei 0:03b5121a232e 6065 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 6066 TODO;
pcercuei 0:03b5121a232e 6067 ret = 0;
pcercuei 0:03b5121a232e 6068 break;
pcercuei 0:03b5121a232e 6069 }
pcercuei 0:03b5121a232e 6070 return(ret);
pcercuei 0:03b5121a232e 6071 }
pcercuei 0:03b5121a232e 6072
pcercuei 0:03b5121a232e 6073
pcercuei 0:03b5121a232e 6074 /**
pcercuei 0:03b5121a232e 6075 * xmlXPathConvertBoolean:
pcercuei 0:03b5121a232e 6076 * @val: an XPath object
pcercuei 0:03b5121a232e 6077 *
pcercuei 0:03b5121a232e 6078 * Converts an existing object to its boolean() equivalent
pcercuei 0:03b5121a232e 6079 *
pcercuei 0:03b5121a232e 6080 * Returns the new object, the old one is freed (or the operation
pcercuei 0:03b5121a232e 6081 * is done directly on @val)
pcercuei 0:03b5121a232e 6082 */
pcercuei 0:03b5121a232e 6083 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 6084 xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 6085 xmlXPathObjectPtr ret;
pcercuei 0:03b5121a232e 6086
pcercuei 0:03b5121a232e 6087 if (val == NULL)
pcercuei 0:03b5121a232e 6088 return(xmlXPathNewBoolean(0));
pcercuei 0:03b5121a232e 6089 if (val->type == XPATH_BOOLEAN)
pcercuei 0:03b5121a232e 6090 return(val);
pcercuei 0:03b5121a232e 6091 ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
pcercuei 0:03b5121a232e 6092 xmlXPathFreeObject(val);
pcercuei 0:03b5121a232e 6093 return(ret);
pcercuei 0:03b5121a232e 6094 }
pcercuei 0:03b5121a232e 6095
pcercuei 0:03b5121a232e 6096 /************************************************************************
pcercuei 0:03b5121a232e 6097 * *
pcercuei 0:03b5121a232e 6098 * Routines to handle XPath contexts *
pcercuei 0:03b5121a232e 6099 * *
pcercuei 0:03b5121a232e 6100 ************************************************************************/
pcercuei 0:03b5121a232e 6101
pcercuei 0:03b5121a232e 6102 /**
pcercuei 0:03b5121a232e 6103 * xmlXPathNewContext:
pcercuei 0:03b5121a232e 6104 * @doc: the XML document
pcercuei 0:03b5121a232e 6105 *
pcercuei 0:03b5121a232e 6106 * Create a new xmlXPathContext
pcercuei 0:03b5121a232e 6107 *
pcercuei 0:03b5121a232e 6108 * Returns the xmlXPathContext just allocated. The caller will need to free it.
pcercuei 0:03b5121a232e 6109 */
pcercuei 0:03b5121a232e 6110 xmlXPathContextPtr
pcercuei 0:03b5121a232e 6111 xmlXPathNewContext(xmlDocPtr doc) {
pcercuei 0:03b5121a232e 6112 xmlXPathContextPtr ret;
pcercuei 0:03b5121a232e 6113
pcercuei 0:03b5121a232e 6114 ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
pcercuei 0:03b5121a232e 6115 if (ret == NULL) {
pcercuei 0:03b5121a232e 6116 xmlXPathErrMemory(NULL, "creating context\n");
pcercuei 0:03b5121a232e 6117 return(NULL);
pcercuei 0:03b5121a232e 6118 }
pcercuei 0:03b5121a232e 6119 memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
pcercuei 0:03b5121a232e 6120 ret->doc = doc;
pcercuei 0:03b5121a232e 6121 ret->node = NULL;
pcercuei 0:03b5121a232e 6122
pcercuei 0:03b5121a232e 6123 ret->varHash = NULL;
pcercuei 0:03b5121a232e 6124
pcercuei 0:03b5121a232e 6125 ret->nb_types = 0;
pcercuei 0:03b5121a232e 6126 ret->max_types = 0;
pcercuei 0:03b5121a232e 6127 ret->types = NULL;
pcercuei 0:03b5121a232e 6128
pcercuei 0:03b5121a232e 6129 ret->funcHash = xmlHashCreate(0);
pcercuei 0:03b5121a232e 6130
pcercuei 0:03b5121a232e 6131 ret->nb_axis = 0;
pcercuei 0:03b5121a232e 6132 ret->max_axis = 0;
pcercuei 0:03b5121a232e 6133 ret->axis = NULL;
pcercuei 0:03b5121a232e 6134
pcercuei 0:03b5121a232e 6135 ret->nsHash = NULL;
pcercuei 0:03b5121a232e 6136 ret->user = NULL;
pcercuei 0:03b5121a232e 6137
pcercuei 0:03b5121a232e 6138 ret->contextSize = -1;
pcercuei 0:03b5121a232e 6139 ret->proximityPosition = -1;
pcercuei 0:03b5121a232e 6140
pcercuei 0:03b5121a232e 6141 #ifdef XP_DEFAULT_CACHE_ON
pcercuei 0:03b5121a232e 6142 if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
pcercuei 0:03b5121a232e 6143 xmlXPathFreeContext(ret);
pcercuei 0:03b5121a232e 6144 return(NULL);
pcercuei 0:03b5121a232e 6145 }
pcercuei 0:03b5121a232e 6146 #endif
pcercuei 0:03b5121a232e 6147
pcercuei 0:03b5121a232e 6148 xmlXPathRegisterAllFunctions(ret);
pcercuei 0:03b5121a232e 6149
pcercuei 0:03b5121a232e 6150 return(ret);
pcercuei 0:03b5121a232e 6151 }
pcercuei 0:03b5121a232e 6152
pcercuei 0:03b5121a232e 6153 /**
pcercuei 0:03b5121a232e 6154 * xmlXPathFreeContext:
pcercuei 0:03b5121a232e 6155 * @ctxt: the context to free
pcercuei 0:03b5121a232e 6156 *
pcercuei 0:03b5121a232e 6157 * Free up an xmlXPathContext
pcercuei 0:03b5121a232e 6158 */
pcercuei 0:03b5121a232e 6159 void
pcercuei 0:03b5121a232e 6160 xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 6161 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 6162
pcercuei 0:03b5121a232e 6163 if (ctxt->cache != NULL)
pcercuei 0:03b5121a232e 6164 xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
pcercuei 0:03b5121a232e 6165 xmlXPathRegisteredNsCleanup(ctxt);
pcercuei 0:03b5121a232e 6166 xmlXPathRegisteredFuncsCleanup(ctxt);
pcercuei 0:03b5121a232e 6167 xmlXPathRegisteredVariablesCleanup(ctxt);
pcercuei 0:03b5121a232e 6168 xmlResetError(&ctxt->lastError);
pcercuei 0:03b5121a232e 6169 xmlFree(ctxt);
pcercuei 0:03b5121a232e 6170 }
pcercuei 0:03b5121a232e 6171
pcercuei 0:03b5121a232e 6172 /************************************************************************
pcercuei 0:03b5121a232e 6173 * *
pcercuei 0:03b5121a232e 6174 * Routines to handle XPath parser contexts *
pcercuei 0:03b5121a232e 6175 * *
pcercuei 0:03b5121a232e 6176 ************************************************************************/
pcercuei 0:03b5121a232e 6177
pcercuei 0:03b5121a232e 6178 #define CHECK_CTXT(ctxt) \
pcercuei 0:03b5121a232e 6179 if (ctxt == NULL) { \
pcercuei 0:03b5121a232e 6180 __xmlRaiseError(NULL, NULL, NULL, \
pcercuei 0:03b5121a232e 6181 NULL, NULL, XML_FROM_XPATH, \
pcercuei 0:03b5121a232e 6182 XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \
pcercuei 0:03b5121a232e 6183 __FILE__, __LINE__, \
pcercuei 0:03b5121a232e 6184 NULL, NULL, NULL, 0, 0, \
pcercuei 0:03b5121a232e 6185 "NULL context pointer\n"); \
pcercuei 0:03b5121a232e 6186 return(NULL); \
pcercuei 0:03b5121a232e 6187 } \
pcercuei 0:03b5121a232e 6188
pcercuei 0:03b5121a232e 6189 #define CHECK_CTXT_NEG(ctxt) \
pcercuei 0:03b5121a232e 6190 if (ctxt == NULL) { \
pcercuei 0:03b5121a232e 6191 __xmlRaiseError(NULL, NULL, NULL, \
pcercuei 0:03b5121a232e 6192 NULL, NULL, XML_FROM_XPATH, \
pcercuei 0:03b5121a232e 6193 XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \
pcercuei 0:03b5121a232e 6194 __FILE__, __LINE__, \
pcercuei 0:03b5121a232e 6195 NULL, NULL, NULL, 0, 0, \
pcercuei 0:03b5121a232e 6196 "NULL context pointer\n"); \
pcercuei 0:03b5121a232e 6197 return(-1); \
pcercuei 0:03b5121a232e 6198 } \
pcercuei 0:03b5121a232e 6199
pcercuei 0:03b5121a232e 6200
pcercuei 0:03b5121a232e 6201 #define CHECK_CONTEXT(ctxt) \
pcercuei 0:03b5121a232e 6202 if ((ctxt == NULL) || (ctxt->doc == NULL) || \
pcercuei 0:03b5121a232e 6203 (ctxt->doc->children == NULL)) { \
pcercuei 0:03b5121a232e 6204 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT); \
pcercuei 0:03b5121a232e 6205 return(NULL); \
pcercuei 0:03b5121a232e 6206 }
pcercuei 0:03b5121a232e 6207
pcercuei 0:03b5121a232e 6208
pcercuei 0:03b5121a232e 6209 /**
pcercuei 0:03b5121a232e 6210 * xmlXPathNewParserContext:
pcercuei 0:03b5121a232e 6211 * @str: the XPath expression
pcercuei 0:03b5121a232e 6212 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 6213 *
pcercuei 0:03b5121a232e 6214 * Create a new xmlXPathParserContext
pcercuei 0:03b5121a232e 6215 *
pcercuei 0:03b5121a232e 6216 * Returns the xmlXPathParserContext just allocated.
pcercuei 0:03b5121a232e 6217 */
pcercuei 0:03b5121a232e 6218 xmlXPathParserContextPtr
pcercuei 0:03b5121a232e 6219 xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 6220 xmlXPathParserContextPtr ret;
pcercuei 0:03b5121a232e 6221
pcercuei 0:03b5121a232e 6222 ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
pcercuei 0:03b5121a232e 6223 if (ret == NULL) {
pcercuei 0:03b5121a232e 6224 xmlXPathErrMemory(ctxt, "creating parser context\n");
pcercuei 0:03b5121a232e 6225 return(NULL);
pcercuei 0:03b5121a232e 6226 }
pcercuei 0:03b5121a232e 6227 memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
pcercuei 0:03b5121a232e 6228 ret->cur = ret->base = str;
pcercuei 0:03b5121a232e 6229 ret->context = ctxt;
pcercuei 0:03b5121a232e 6230
pcercuei 0:03b5121a232e 6231 ret->comp = xmlXPathNewCompExpr();
pcercuei 0:03b5121a232e 6232 if (ret->comp == NULL) {
pcercuei 0:03b5121a232e 6233 xmlFree(ret->valueTab);
pcercuei 0:03b5121a232e 6234 xmlFree(ret);
pcercuei 0:03b5121a232e 6235 return(NULL);
pcercuei 0:03b5121a232e 6236 }
pcercuei 0:03b5121a232e 6237 if ((ctxt != NULL) && (ctxt->dict != NULL)) {
pcercuei 0:03b5121a232e 6238 ret->comp->dict = ctxt->dict;
pcercuei 0:03b5121a232e 6239 xmlDictReference(ret->comp->dict);
pcercuei 0:03b5121a232e 6240 }
pcercuei 0:03b5121a232e 6241
pcercuei 0:03b5121a232e 6242 return(ret);
pcercuei 0:03b5121a232e 6243 }
pcercuei 0:03b5121a232e 6244
pcercuei 0:03b5121a232e 6245 /**
pcercuei 0:03b5121a232e 6246 * xmlXPathCompParserContext:
pcercuei 0:03b5121a232e 6247 * @comp: the XPath compiled expression
pcercuei 0:03b5121a232e 6248 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 6249 *
pcercuei 0:03b5121a232e 6250 * Create a new xmlXPathParserContext when processing a compiled expression
pcercuei 0:03b5121a232e 6251 *
pcercuei 0:03b5121a232e 6252 * Returns the xmlXPathParserContext just allocated.
pcercuei 0:03b5121a232e 6253 */
pcercuei 0:03b5121a232e 6254 static xmlXPathParserContextPtr
pcercuei 0:03b5121a232e 6255 xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 6256 xmlXPathParserContextPtr ret;
pcercuei 0:03b5121a232e 6257
pcercuei 0:03b5121a232e 6258 ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
pcercuei 0:03b5121a232e 6259 if (ret == NULL) {
pcercuei 0:03b5121a232e 6260 xmlXPathErrMemory(ctxt, "creating evaluation context\n");
pcercuei 0:03b5121a232e 6261 return(NULL);
pcercuei 0:03b5121a232e 6262 }
pcercuei 0:03b5121a232e 6263 memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
pcercuei 0:03b5121a232e 6264
pcercuei 0:03b5121a232e 6265 /* Allocate the value stack */
pcercuei 0:03b5121a232e 6266 ret->valueTab = (xmlXPathObjectPtr *)
pcercuei 0:03b5121a232e 6267 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
pcercuei 0:03b5121a232e 6268 if (ret->valueTab == NULL) {
pcercuei 0:03b5121a232e 6269 xmlFree(ret);
pcercuei 0:03b5121a232e 6270 xmlXPathErrMemory(ctxt, "creating evaluation context\n");
pcercuei 0:03b5121a232e 6271 return(NULL);
pcercuei 0:03b5121a232e 6272 }
pcercuei 0:03b5121a232e 6273 ret->valueNr = 0;
pcercuei 0:03b5121a232e 6274 ret->valueMax = 10;
pcercuei 0:03b5121a232e 6275 ret->value = NULL;
pcercuei 0:03b5121a232e 6276 ret->valueFrame = 0;
pcercuei 0:03b5121a232e 6277
pcercuei 0:03b5121a232e 6278 ret->context = ctxt;
pcercuei 0:03b5121a232e 6279 ret->comp = comp;
pcercuei 0:03b5121a232e 6280
pcercuei 0:03b5121a232e 6281 return(ret);
pcercuei 0:03b5121a232e 6282 }
pcercuei 0:03b5121a232e 6283
pcercuei 0:03b5121a232e 6284 /**
pcercuei 0:03b5121a232e 6285 * xmlXPathFreeParserContext:
pcercuei 0:03b5121a232e 6286 * @ctxt: the context to free
pcercuei 0:03b5121a232e 6287 *
pcercuei 0:03b5121a232e 6288 * Free up an xmlXPathParserContext
pcercuei 0:03b5121a232e 6289 */
pcercuei 0:03b5121a232e 6290 void
pcercuei 0:03b5121a232e 6291 xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 6292 if (ctxt->valueTab != NULL) {
pcercuei 0:03b5121a232e 6293 xmlFree(ctxt->valueTab);
pcercuei 0:03b5121a232e 6294 }
pcercuei 0:03b5121a232e 6295 if (ctxt->comp != NULL) {
pcercuei 0:03b5121a232e 6296 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 6297 if (ctxt->comp->stream != NULL) {
pcercuei 0:03b5121a232e 6298 xmlFreePatternList(ctxt->comp->stream);
pcercuei 0:03b5121a232e 6299 ctxt->comp->stream = NULL;
pcercuei 0:03b5121a232e 6300 }
pcercuei 0:03b5121a232e 6301 #endif
pcercuei 0:03b5121a232e 6302 xmlXPathFreeCompExpr(ctxt->comp);
pcercuei 0:03b5121a232e 6303 }
pcercuei 0:03b5121a232e 6304 xmlFree(ctxt);
pcercuei 0:03b5121a232e 6305 }
pcercuei 0:03b5121a232e 6306
pcercuei 0:03b5121a232e 6307 /************************************************************************
pcercuei 0:03b5121a232e 6308 * *
pcercuei 0:03b5121a232e 6309 * The implicit core function library *
pcercuei 0:03b5121a232e 6310 * *
pcercuei 0:03b5121a232e 6311 ************************************************************************/
pcercuei 0:03b5121a232e 6312
pcercuei 0:03b5121a232e 6313 /**
pcercuei 0:03b5121a232e 6314 * xmlXPathNodeValHash:
pcercuei 0:03b5121a232e 6315 * @node: a node pointer
pcercuei 0:03b5121a232e 6316 *
pcercuei 0:03b5121a232e 6317 * Function computing the beginning of the string value of the node,
pcercuei 0:03b5121a232e 6318 * used to speed up comparisons
pcercuei 0:03b5121a232e 6319 *
pcercuei 0:03b5121a232e 6320 * Returns an int usable as a hash
pcercuei 0:03b5121a232e 6321 */
pcercuei 0:03b5121a232e 6322 static unsigned int
pcercuei 0:03b5121a232e 6323 xmlXPathNodeValHash(xmlNodePtr node) {
pcercuei 0:03b5121a232e 6324 int len = 2;
pcercuei 0:03b5121a232e 6325 const xmlChar * string = NULL;
pcercuei 0:03b5121a232e 6326 xmlNodePtr tmp = NULL;
pcercuei 0:03b5121a232e 6327 unsigned int ret = 0;
pcercuei 0:03b5121a232e 6328
pcercuei 0:03b5121a232e 6329 if (node == NULL)
pcercuei 0:03b5121a232e 6330 return(0);
pcercuei 0:03b5121a232e 6331
pcercuei 0:03b5121a232e 6332 if (node->type == XML_DOCUMENT_NODE) {
pcercuei 0:03b5121a232e 6333 tmp = xmlDocGetRootElement((xmlDocPtr) node);
pcercuei 0:03b5121a232e 6334 if (tmp == NULL)
pcercuei 0:03b5121a232e 6335 node = node->children;
pcercuei 0:03b5121a232e 6336 else
pcercuei 0:03b5121a232e 6337 node = tmp;
pcercuei 0:03b5121a232e 6338
pcercuei 0:03b5121a232e 6339 if (node == NULL)
pcercuei 0:03b5121a232e 6340 return(0);
pcercuei 0:03b5121a232e 6341 }
pcercuei 0:03b5121a232e 6342
pcercuei 0:03b5121a232e 6343 switch (node->type) {
pcercuei 0:03b5121a232e 6344 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 6345 case XML_PI_NODE:
pcercuei 0:03b5121a232e 6346 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 6347 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 6348 string = node->content;
pcercuei 0:03b5121a232e 6349 if (string == NULL)
pcercuei 0:03b5121a232e 6350 return(0);
pcercuei 0:03b5121a232e 6351 if (string[0] == 0)
pcercuei 0:03b5121a232e 6352 return(0);
pcercuei 0:03b5121a232e 6353 return(((unsigned int) string[0]) +
pcercuei 0:03b5121a232e 6354 (((unsigned int) string[1]) << 8));
pcercuei 0:03b5121a232e 6355 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 6356 string = ((xmlNsPtr)node)->href;
pcercuei 0:03b5121a232e 6357 if (string == NULL)
pcercuei 0:03b5121a232e 6358 return(0);
pcercuei 0:03b5121a232e 6359 if (string[0] == 0)
pcercuei 0:03b5121a232e 6360 return(0);
pcercuei 0:03b5121a232e 6361 return(((unsigned int) string[0]) +
pcercuei 0:03b5121a232e 6362 (((unsigned int) string[1]) << 8));
pcercuei 0:03b5121a232e 6363 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 6364 tmp = ((xmlAttrPtr) node)->children;
pcercuei 0:03b5121a232e 6365 break;
pcercuei 0:03b5121a232e 6366 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 6367 tmp = node->children;
pcercuei 0:03b5121a232e 6368 break;
pcercuei 0:03b5121a232e 6369 default:
pcercuei 0:03b5121a232e 6370 return(0);
pcercuei 0:03b5121a232e 6371 }
pcercuei 0:03b5121a232e 6372 while (tmp != NULL) {
pcercuei 0:03b5121a232e 6373 switch (tmp->type) {
pcercuei 0:03b5121a232e 6374 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 6375 case XML_PI_NODE:
pcercuei 0:03b5121a232e 6376 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 6377 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 6378 string = tmp->content;
pcercuei 0:03b5121a232e 6379 break;
pcercuei 0:03b5121a232e 6380 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 6381 string = ((xmlNsPtr)tmp)->href;
pcercuei 0:03b5121a232e 6382 break;
pcercuei 0:03b5121a232e 6383 default:
pcercuei 0:03b5121a232e 6384 break;
pcercuei 0:03b5121a232e 6385 }
pcercuei 0:03b5121a232e 6386 if ((string != NULL) && (string[0] != 0)) {
pcercuei 0:03b5121a232e 6387 if (len == 1) {
pcercuei 0:03b5121a232e 6388 return(ret + (((unsigned int) string[0]) << 8));
pcercuei 0:03b5121a232e 6389 }
pcercuei 0:03b5121a232e 6390 if (string[1] == 0) {
pcercuei 0:03b5121a232e 6391 len = 1;
pcercuei 0:03b5121a232e 6392 ret = (unsigned int) string[0];
pcercuei 0:03b5121a232e 6393 } else {
pcercuei 0:03b5121a232e 6394 return(((unsigned int) string[0]) +
pcercuei 0:03b5121a232e 6395 (((unsigned int) string[1]) << 8));
pcercuei 0:03b5121a232e 6396 }
pcercuei 0:03b5121a232e 6397 }
pcercuei 0:03b5121a232e 6398 /*
pcercuei 0:03b5121a232e 6399 * Skip to next node
pcercuei 0:03b5121a232e 6400 */
pcercuei 0:03b5121a232e 6401 if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) {
pcercuei 0:03b5121a232e 6402 if (tmp->children->type != XML_ENTITY_DECL) {
pcercuei 0:03b5121a232e 6403 tmp = tmp->children;
pcercuei 0:03b5121a232e 6404 continue;
pcercuei 0:03b5121a232e 6405 }
pcercuei 0:03b5121a232e 6406 }
pcercuei 0:03b5121a232e 6407 if (tmp == node)
pcercuei 0:03b5121a232e 6408 break;
pcercuei 0:03b5121a232e 6409
pcercuei 0:03b5121a232e 6410 if (tmp->next != NULL) {
pcercuei 0:03b5121a232e 6411 tmp = tmp->next;
pcercuei 0:03b5121a232e 6412 continue;
pcercuei 0:03b5121a232e 6413 }
pcercuei 0:03b5121a232e 6414
pcercuei 0:03b5121a232e 6415 do {
pcercuei 0:03b5121a232e 6416 tmp = tmp->parent;
pcercuei 0:03b5121a232e 6417 if (tmp == NULL)
pcercuei 0:03b5121a232e 6418 break;
pcercuei 0:03b5121a232e 6419 if (tmp == node) {
pcercuei 0:03b5121a232e 6420 tmp = NULL;
pcercuei 0:03b5121a232e 6421 break;
pcercuei 0:03b5121a232e 6422 }
pcercuei 0:03b5121a232e 6423 if (tmp->next != NULL) {
pcercuei 0:03b5121a232e 6424 tmp = tmp->next;
pcercuei 0:03b5121a232e 6425 break;
pcercuei 0:03b5121a232e 6426 }
pcercuei 0:03b5121a232e 6427 } while (tmp != NULL);
pcercuei 0:03b5121a232e 6428 }
pcercuei 0:03b5121a232e 6429 return(ret);
pcercuei 0:03b5121a232e 6430 }
pcercuei 0:03b5121a232e 6431
pcercuei 0:03b5121a232e 6432 /**
pcercuei 0:03b5121a232e 6433 * xmlXPathStringHash:
pcercuei 0:03b5121a232e 6434 * @string: a string
pcercuei 0:03b5121a232e 6435 *
pcercuei 0:03b5121a232e 6436 * Function computing the beginning of the string value of the node,
pcercuei 0:03b5121a232e 6437 * used to speed up comparisons
pcercuei 0:03b5121a232e 6438 *
pcercuei 0:03b5121a232e 6439 * Returns an int usable as a hash
pcercuei 0:03b5121a232e 6440 */
pcercuei 0:03b5121a232e 6441 static unsigned int
pcercuei 0:03b5121a232e 6442 xmlXPathStringHash(const xmlChar * string) {
pcercuei 0:03b5121a232e 6443 if (string == NULL)
pcercuei 0:03b5121a232e 6444 return((unsigned int) 0);
pcercuei 0:03b5121a232e 6445 if (string[0] == 0)
pcercuei 0:03b5121a232e 6446 return(0);
pcercuei 0:03b5121a232e 6447 return(((unsigned int) string[0]) +
pcercuei 0:03b5121a232e 6448 (((unsigned int) string[1]) << 8));
pcercuei 0:03b5121a232e 6449 }
pcercuei 0:03b5121a232e 6450
pcercuei 0:03b5121a232e 6451 /**
pcercuei 0:03b5121a232e 6452 * xmlXPathCompareNodeSetFloat:
pcercuei 0:03b5121a232e 6453 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 6454 * @inf: less than (1) or greater than (0)
pcercuei 0:03b5121a232e 6455 * @strict: is the comparison strict
pcercuei 0:03b5121a232e 6456 * @arg: the node set
pcercuei 0:03b5121a232e 6457 * @f: the value
pcercuei 0:03b5121a232e 6458 *
pcercuei 0:03b5121a232e 6459 * Implement the compare operation between a nodeset and a number
pcercuei 0:03b5121a232e 6460 * @ns < @val (1, 1, ...
pcercuei 0:03b5121a232e 6461 * @ns <= @val (1, 0, ...
pcercuei 0:03b5121a232e 6462 * @ns > @val (0, 1, ...
pcercuei 0:03b5121a232e 6463 * @ns >= @val (0, 0, ...
pcercuei 0:03b5121a232e 6464 *
pcercuei 0:03b5121a232e 6465 * If one object to be compared is a node-set and the other is a number,
pcercuei 0:03b5121a232e 6466 * then the comparison will be true if and only if there is a node in the
pcercuei 0:03b5121a232e 6467 * node-set such that the result of performing the comparison on the number
pcercuei 0:03b5121a232e 6468 * to be compared and on the result of converting the string-value of that
pcercuei 0:03b5121a232e 6469 * node to a number using the number function is true.
pcercuei 0:03b5121a232e 6470 *
pcercuei 0:03b5121a232e 6471 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 6472 */
pcercuei 0:03b5121a232e 6473 static int
pcercuei 0:03b5121a232e 6474 xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
pcercuei 0:03b5121a232e 6475 xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
pcercuei 0:03b5121a232e 6476 int i, ret = 0;
pcercuei 0:03b5121a232e 6477 xmlNodeSetPtr ns;
pcercuei 0:03b5121a232e 6478 xmlChar *str2;
pcercuei 0:03b5121a232e 6479
pcercuei 0:03b5121a232e 6480 if ((f == NULL) || (arg == NULL) ||
pcercuei 0:03b5121a232e 6481 ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
pcercuei 0:03b5121a232e 6482 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 6483 xmlXPathReleaseObject(ctxt->context, f);
pcercuei 0:03b5121a232e 6484 return(0);
pcercuei 0:03b5121a232e 6485 }
pcercuei 0:03b5121a232e 6486 ns = arg->nodesetval;
pcercuei 0:03b5121a232e 6487 if (ns != NULL) {
pcercuei 0:03b5121a232e 6488 for (i = 0;i < ns->nodeNr;i++) {
pcercuei 0:03b5121a232e 6489 str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
pcercuei 0:03b5121a232e 6490 if (str2 != NULL) {
pcercuei 0:03b5121a232e 6491 valuePush(ctxt,
pcercuei 0:03b5121a232e 6492 xmlXPathCacheNewString(ctxt->context, str2));
pcercuei 0:03b5121a232e 6493 xmlFree(str2);
pcercuei 0:03b5121a232e 6494 xmlXPathNumberFunction(ctxt, 1);
pcercuei 0:03b5121a232e 6495 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, f));
pcercuei 0:03b5121a232e 6496 ret = xmlXPathCompareValues(ctxt, inf, strict);
pcercuei 0:03b5121a232e 6497 if (ret)
pcercuei 0:03b5121a232e 6498 break;
pcercuei 0:03b5121a232e 6499 }
pcercuei 0:03b5121a232e 6500 }
pcercuei 0:03b5121a232e 6501 }
pcercuei 0:03b5121a232e 6502 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 6503 xmlXPathReleaseObject(ctxt->context, f);
pcercuei 0:03b5121a232e 6504 return(ret);
pcercuei 0:03b5121a232e 6505 }
pcercuei 0:03b5121a232e 6506
pcercuei 0:03b5121a232e 6507 /**
pcercuei 0:03b5121a232e 6508 * xmlXPathCompareNodeSetString:
pcercuei 0:03b5121a232e 6509 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 6510 * @inf: less than (1) or greater than (0)
pcercuei 0:03b5121a232e 6511 * @strict: is the comparison strict
pcercuei 0:03b5121a232e 6512 * @arg: the node set
pcercuei 0:03b5121a232e 6513 * @s: the value
pcercuei 0:03b5121a232e 6514 *
pcercuei 0:03b5121a232e 6515 * Implement the compare operation between a nodeset and a string
pcercuei 0:03b5121a232e 6516 * @ns < @val (1, 1, ...
pcercuei 0:03b5121a232e 6517 * @ns <= @val (1, 0, ...
pcercuei 0:03b5121a232e 6518 * @ns > @val (0, 1, ...
pcercuei 0:03b5121a232e 6519 * @ns >= @val (0, 0, ...
pcercuei 0:03b5121a232e 6520 *
pcercuei 0:03b5121a232e 6521 * If one object to be compared is a node-set and the other is a string,
pcercuei 0:03b5121a232e 6522 * then the comparison will be true if and only if there is a node in
pcercuei 0:03b5121a232e 6523 * the node-set such that the result of performing the comparison on the
pcercuei 0:03b5121a232e 6524 * string-value of the node and the other string is true.
pcercuei 0:03b5121a232e 6525 *
pcercuei 0:03b5121a232e 6526 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 6527 */
pcercuei 0:03b5121a232e 6528 static int
pcercuei 0:03b5121a232e 6529 xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
pcercuei 0:03b5121a232e 6530 xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
pcercuei 0:03b5121a232e 6531 int i, ret = 0;
pcercuei 0:03b5121a232e 6532 xmlNodeSetPtr ns;
pcercuei 0:03b5121a232e 6533 xmlChar *str2;
pcercuei 0:03b5121a232e 6534
pcercuei 0:03b5121a232e 6535 if ((s == NULL) || (arg == NULL) ||
pcercuei 0:03b5121a232e 6536 ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
pcercuei 0:03b5121a232e 6537 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 6538 xmlXPathReleaseObject(ctxt->context, s);
pcercuei 0:03b5121a232e 6539 return(0);
pcercuei 0:03b5121a232e 6540 }
pcercuei 0:03b5121a232e 6541 ns = arg->nodesetval;
pcercuei 0:03b5121a232e 6542 if (ns != NULL) {
pcercuei 0:03b5121a232e 6543 for (i = 0;i < ns->nodeNr;i++) {
pcercuei 0:03b5121a232e 6544 str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
pcercuei 0:03b5121a232e 6545 if (str2 != NULL) {
pcercuei 0:03b5121a232e 6546 valuePush(ctxt,
pcercuei 0:03b5121a232e 6547 xmlXPathCacheNewString(ctxt->context, str2));
pcercuei 0:03b5121a232e 6548 xmlFree(str2);
pcercuei 0:03b5121a232e 6549 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt->context, s));
pcercuei 0:03b5121a232e 6550 ret = xmlXPathCompareValues(ctxt, inf, strict);
pcercuei 0:03b5121a232e 6551 if (ret)
pcercuei 0:03b5121a232e 6552 break;
pcercuei 0:03b5121a232e 6553 }
pcercuei 0:03b5121a232e 6554 }
pcercuei 0:03b5121a232e 6555 }
pcercuei 0:03b5121a232e 6556 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 6557 xmlXPathReleaseObject(ctxt->context, s);
pcercuei 0:03b5121a232e 6558 return(ret);
pcercuei 0:03b5121a232e 6559 }
pcercuei 0:03b5121a232e 6560
pcercuei 0:03b5121a232e 6561 /**
pcercuei 0:03b5121a232e 6562 * xmlXPathCompareNodeSets:
pcercuei 0:03b5121a232e 6563 * @inf: less than (1) or greater than (0)
pcercuei 0:03b5121a232e 6564 * @strict: is the comparison strict
pcercuei 0:03b5121a232e 6565 * @arg1: the first node set object
pcercuei 0:03b5121a232e 6566 * @arg2: the second node set object
pcercuei 0:03b5121a232e 6567 *
pcercuei 0:03b5121a232e 6568 * Implement the compare operation on nodesets:
pcercuei 0:03b5121a232e 6569 *
pcercuei 0:03b5121a232e 6570 * If both objects to be compared are node-sets, then the comparison
pcercuei 0:03b5121a232e 6571 * will be true if and only if there is a node in the first node-set
pcercuei 0:03b5121a232e 6572 * and a node in the second node-set such that the result of performing
pcercuei 0:03b5121a232e 6573 * the comparison on the string-values of the two nodes is true.
pcercuei 0:03b5121a232e 6574 * ....
pcercuei 0:03b5121a232e 6575 * When neither object to be compared is a node-set and the operator
pcercuei 0:03b5121a232e 6576 * is <=, <, >= or >, then the objects are compared by converting both
pcercuei 0:03b5121a232e 6577 * objects to numbers and comparing the numbers according to IEEE 754.
pcercuei 0:03b5121a232e 6578 * ....
pcercuei 0:03b5121a232e 6579 * The number function converts its argument to a number as follows:
pcercuei 0:03b5121a232e 6580 * - a string that consists of optional whitespace followed by an
pcercuei 0:03b5121a232e 6581 * optional minus sign followed by a Number followed by whitespace
pcercuei 0:03b5121a232e 6582 * is converted to the IEEE 754 number that is nearest (according
pcercuei 0:03b5121a232e 6583 * to the IEEE 754 round-to-nearest rule) to the mathematical value
pcercuei 0:03b5121a232e 6584 * represented by the string; any other string is converted to NaN
pcercuei 0:03b5121a232e 6585 *
pcercuei 0:03b5121a232e 6586 * Conclusion all nodes need to be converted first to their string value
pcercuei 0:03b5121a232e 6587 * and then the comparison must be done when possible
pcercuei 0:03b5121a232e 6588 */
pcercuei 0:03b5121a232e 6589 static int
pcercuei 0:03b5121a232e 6590 xmlXPathCompareNodeSets(int inf, int strict,
pcercuei 0:03b5121a232e 6591 xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
pcercuei 0:03b5121a232e 6592 int i, j, init = 0;
pcercuei 0:03b5121a232e 6593 double val1;
pcercuei 0:03b5121a232e 6594 double *values2;
pcercuei 0:03b5121a232e 6595 int ret = 0;
pcercuei 0:03b5121a232e 6596 xmlNodeSetPtr ns1;
pcercuei 0:03b5121a232e 6597 xmlNodeSetPtr ns2;
pcercuei 0:03b5121a232e 6598
pcercuei 0:03b5121a232e 6599 if ((arg1 == NULL) ||
pcercuei 0:03b5121a232e 6600 ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
pcercuei 0:03b5121a232e 6601 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 6602 return(0);
pcercuei 0:03b5121a232e 6603 }
pcercuei 0:03b5121a232e 6604 if ((arg2 == NULL) ||
pcercuei 0:03b5121a232e 6605 ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
pcercuei 0:03b5121a232e 6606 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 6607 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 6608 return(0);
pcercuei 0:03b5121a232e 6609 }
pcercuei 0:03b5121a232e 6610
pcercuei 0:03b5121a232e 6611 ns1 = arg1->nodesetval;
pcercuei 0:03b5121a232e 6612 ns2 = arg2->nodesetval;
pcercuei 0:03b5121a232e 6613
pcercuei 0:03b5121a232e 6614 if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
pcercuei 0:03b5121a232e 6615 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 6616 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 6617 return(0);
pcercuei 0:03b5121a232e 6618 }
pcercuei 0:03b5121a232e 6619 if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
pcercuei 0:03b5121a232e 6620 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 6621 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 6622 return(0);
pcercuei 0:03b5121a232e 6623 }
pcercuei 0:03b5121a232e 6624
pcercuei 0:03b5121a232e 6625 values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
pcercuei 0:03b5121a232e 6626 if (values2 == NULL) {
pcercuei 0:03b5121a232e 6627 xmlXPathErrMemory(NULL, "comparing nodesets\n");
pcercuei 0:03b5121a232e 6628 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 6629 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 6630 return(0);
pcercuei 0:03b5121a232e 6631 }
pcercuei 0:03b5121a232e 6632 for (i = 0;i < ns1->nodeNr;i++) {
pcercuei 0:03b5121a232e 6633 val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
pcercuei 0:03b5121a232e 6634 if (xmlXPathIsNaN(val1))
pcercuei 0:03b5121a232e 6635 continue;
pcercuei 0:03b5121a232e 6636 for (j = 0;j < ns2->nodeNr;j++) {
pcercuei 0:03b5121a232e 6637 if (init == 0) {
pcercuei 0:03b5121a232e 6638 values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
pcercuei 0:03b5121a232e 6639 }
pcercuei 0:03b5121a232e 6640 if (xmlXPathIsNaN(values2[j]))
pcercuei 0:03b5121a232e 6641 continue;
pcercuei 0:03b5121a232e 6642 if (inf && strict)
pcercuei 0:03b5121a232e 6643 ret = (val1 < values2[j]);
pcercuei 0:03b5121a232e 6644 else if (inf && !strict)
pcercuei 0:03b5121a232e 6645 ret = (val1 <= values2[j]);
pcercuei 0:03b5121a232e 6646 else if (!inf && strict)
pcercuei 0:03b5121a232e 6647 ret = (val1 > values2[j]);
pcercuei 0:03b5121a232e 6648 else if (!inf && !strict)
pcercuei 0:03b5121a232e 6649 ret = (val1 >= values2[j]);
pcercuei 0:03b5121a232e 6650 if (ret)
pcercuei 0:03b5121a232e 6651 break;
pcercuei 0:03b5121a232e 6652 }
pcercuei 0:03b5121a232e 6653 if (ret)
pcercuei 0:03b5121a232e 6654 break;
pcercuei 0:03b5121a232e 6655 init = 1;
pcercuei 0:03b5121a232e 6656 }
pcercuei 0:03b5121a232e 6657 xmlFree(values2);
pcercuei 0:03b5121a232e 6658 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 6659 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 6660 return(ret);
pcercuei 0:03b5121a232e 6661 }
pcercuei 0:03b5121a232e 6662
pcercuei 0:03b5121a232e 6663 /**
pcercuei 0:03b5121a232e 6664 * xmlXPathCompareNodeSetValue:
pcercuei 0:03b5121a232e 6665 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 6666 * @inf: less than (1) or greater than (0)
pcercuei 0:03b5121a232e 6667 * @strict: is the comparison strict
pcercuei 0:03b5121a232e 6668 * @arg: the node set
pcercuei 0:03b5121a232e 6669 * @val: the value
pcercuei 0:03b5121a232e 6670 *
pcercuei 0:03b5121a232e 6671 * Implement the compare operation between a nodeset and a value
pcercuei 0:03b5121a232e 6672 * @ns < @val (1, 1, ...
pcercuei 0:03b5121a232e 6673 * @ns <= @val (1, 0, ...
pcercuei 0:03b5121a232e 6674 * @ns > @val (0, 1, ...
pcercuei 0:03b5121a232e 6675 * @ns >= @val (0, 0, ...
pcercuei 0:03b5121a232e 6676 *
pcercuei 0:03b5121a232e 6677 * If one object to be compared is a node-set and the other is a boolean,
pcercuei 0:03b5121a232e 6678 * then the comparison will be true if and only if the result of performing
pcercuei 0:03b5121a232e 6679 * the comparison on the boolean and on the result of converting
pcercuei 0:03b5121a232e 6680 * the node-set to a boolean using the boolean function is true.
pcercuei 0:03b5121a232e 6681 *
pcercuei 0:03b5121a232e 6682 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 6683 */
pcercuei 0:03b5121a232e 6684 static int
pcercuei 0:03b5121a232e 6685 xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
pcercuei 0:03b5121a232e 6686 xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
pcercuei 0:03b5121a232e 6687 if ((val == NULL) || (arg == NULL) ||
pcercuei 0:03b5121a232e 6688 ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 6689 return(0);
pcercuei 0:03b5121a232e 6690
pcercuei 0:03b5121a232e 6691 switch(val->type) {
pcercuei 0:03b5121a232e 6692 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 6693 return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
pcercuei 0:03b5121a232e 6694 case XPATH_NODESET:
pcercuei 0:03b5121a232e 6695 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 6696 return(xmlXPathCompareNodeSets(inf, strict, arg, val));
pcercuei 0:03b5121a232e 6697 case XPATH_STRING:
pcercuei 0:03b5121a232e 6698 return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
pcercuei 0:03b5121a232e 6699 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 6700 valuePush(ctxt, arg);
pcercuei 0:03b5121a232e 6701 xmlXPathBooleanFunction(ctxt, 1);
pcercuei 0:03b5121a232e 6702 valuePush(ctxt, val);
pcercuei 0:03b5121a232e 6703 return(xmlXPathCompareValues(ctxt, inf, strict));
pcercuei 0:03b5121a232e 6704 default:
pcercuei 0:03b5121a232e 6705 TODO
pcercuei 0:03b5121a232e 6706 }
pcercuei 0:03b5121a232e 6707 return(0);
pcercuei 0:03b5121a232e 6708 }
pcercuei 0:03b5121a232e 6709
pcercuei 0:03b5121a232e 6710 /**
pcercuei 0:03b5121a232e 6711 * xmlXPathEqualNodeSetString:
pcercuei 0:03b5121a232e 6712 * @arg: the nodeset object argument
pcercuei 0:03b5121a232e 6713 * @str: the string to compare to.
pcercuei 0:03b5121a232e 6714 * @neq: flag to show whether for '=' (0) or '!=' (1)
pcercuei 0:03b5121a232e 6715 *
pcercuei 0:03b5121a232e 6716 * Implement the equal operation on XPath objects content: @arg1 == @arg2
pcercuei 0:03b5121a232e 6717 * If one object to be compared is a node-set and the other is a string,
pcercuei 0:03b5121a232e 6718 * then the comparison will be true if and only if there is a node in
pcercuei 0:03b5121a232e 6719 * the node-set such that the result of performing the comparison on the
pcercuei 0:03b5121a232e 6720 * string-value of the node and the other string is true.
pcercuei 0:03b5121a232e 6721 *
pcercuei 0:03b5121a232e 6722 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 6723 */
pcercuei 0:03b5121a232e 6724 static int
pcercuei 0:03b5121a232e 6725 xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq)
pcercuei 0:03b5121a232e 6726 {
pcercuei 0:03b5121a232e 6727 int i;
pcercuei 0:03b5121a232e 6728 xmlNodeSetPtr ns;
pcercuei 0:03b5121a232e 6729 xmlChar *str2;
pcercuei 0:03b5121a232e 6730 unsigned int hash;
pcercuei 0:03b5121a232e 6731
pcercuei 0:03b5121a232e 6732 if ((str == NULL) || (arg == NULL) ||
pcercuei 0:03b5121a232e 6733 ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 6734 return (0);
pcercuei 0:03b5121a232e 6735 ns = arg->nodesetval;
pcercuei 0:03b5121a232e 6736 /*
pcercuei 0:03b5121a232e 6737 * A NULL nodeset compared with a string is always false
pcercuei 0:03b5121a232e 6738 * (since there is no node equal, and no node not equal)
pcercuei 0:03b5121a232e 6739 */
pcercuei 0:03b5121a232e 6740 if ((ns == NULL) || (ns->nodeNr <= 0) )
pcercuei 0:03b5121a232e 6741 return (0);
pcercuei 0:03b5121a232e 6742 hash = xmlXPathStringHash(str);
pcercuei 0:03b5121a232e 6743 for (i = 0; i < ns->nodeNr; i++) {
pcercuei 0:03b5121a232e 6744 if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
pcercuei 0:03b5121a232e 6745 str2 = xmlNodeGetContent(ns->nodeTab[i]);
pcercuei 0:03b5121a232e 6746 if ((str2 != NULL) && (xmlStrEqual(str, str2))) {
pcercuei 0:03b5121a232e 6747 xmlFree(str2);
pcercuei 0:03b5121a232e 6748 if (neq)
pcercuei 0:03b5121a232e 6749 continue;
pcercuei 0:03b5121a232e 6750 return (1);
pcercuei 0:03b5121a232e 6751 } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) {
pcercuei 0:03b5121a232e 6752 if (neq)
pcercuei 0:03b5121a232e 6753 continue;
pcercuei 0:03b5121a232e 6754 return (1);
pcercuei 0:03b5121a232e 6755 } else if (neq) {
pcercuei 0:03b5121a232e 6756 if (str2 != NULL)
pcercuei 0:03b5121a232e 6757 xmlFree(str2);
pcercuei 0:03b5121a232e 6758 return (1);
pcercuei 0:03b5121a232e 6759 }
pcercuei 0:03b5121a232e 6760 if (str2 != NULL)
pcercuei 0:03b5121a232e 6761 xmlFree(str2);
pcercuei 0:03b5121a232e 6762 } else if (neq)
pcercuei 0:03b5121a232e 6763 return (1);
pcercuei 0:03b5121a232e 6764 }
pcercuei 0:03b5121a232e 6765 return (0);
pcercuei 0:03b5121a232e 6766 }
pcercuei 0:03b5121a232e 6767
pcercuei 0:03b5121a232e 6768 /**
pcercuei 0:03b5121a232e 6769 * xmlXPathEqualNodeSetFloat:
pcercuei 0:03b5121a232e 6770 * @arg: the nodeset object argument
pcercuei 0:03b5121a232e 6771 * @f: the float to compare to
pcercuei 0:03b5121a232e 6772 * @neq: flag to show whether to compare '=' (0) or '!=' (1)
pcercuei 0:03b5121a232e 6773 *
pcercuei 0:03b5121a232e 6774 * Implement the equal operation on XPath objects content: @arg1 == @arg2
pcercuei 0:03b5121a232e 6775 * If one object to be compared is a node-set and the other is a number,
pcercuei 0:03b5121a232e 6776 * then the comparison will be true if and only if there is a node in
pcercuei 0:03b5121a232e 6777 * the node-set such that the result of performing the comparison on the
pcercuei 0:03b5121a232e 6778 * number to be compared and on the result of converting the string-value
pcercuei 0:03b5121a232e 6779 * of that node to a number using the number function is true.
pcercuei 0:03b5121a232e 6780 *
pcercuei 0:03b5121a232e 6781 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 6782 */
pcercuei 0:03b5121a232e 6783 static int
pcercuei 0:03b5121a232e 6784 xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 6785 xmlXPathObjectPtr arg, double f, int neq) {
pcercuei 0:03b5121a232e 6786 int i, ret=0;
pcercuei 0:03b5121a232e 6787 xmlNodeSetPtr ns;
pcercuei 0:03b5121a232e 6788 xmlChar *str2;
pcercuei 0:03b5121a232e 6789 xmlXPathObjectPtr val;
pcercuei 0:03b5121a232e 6790 double v;
pcercuei 0:03b5121a232e 6791
pcercuei 0:03b5121a232e 6792 if ((arg == NULL) ||
pcercuei 0:03b5121a232e 6793 ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 6794 return(0);
pcercuei 0:03b5121a232e 6795
pcercuei 0:03b5121a232e 6796 ns = arg->nodesetval;
pcercuei 0:03b5121a232e 6797 if (ns != NULL) {
pcercuei 0:03b5121a232e 6798 for (i=0;i<ns->nodeNr;i++) {
pcercuei 0:03b5121a232e 6799 str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
pcercuei 0:03b5121a232e 6800 if (str2 != NULL) {
pcercuei 0:03b5121a232e 6801 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, str2));
pcercuei 0:03b5121a232e 6802 xmlFree(str2);
pcercuei 0:03b5121a232e 6803 xmlXPathNumberFunction(ctxt, 1);
pcercuei 0:03b5121a232e 6804 val = valuePop(ctxt);
pcercuei 0:03b5121a232e 6805 v = val->floatval;
pcercuei 0:03b5121a232e 6806 xmlXPathReleaseObject(ctxt->context, val);
pcercuei 0:03b5121a232e 6807 if (!xmlXPathIsNaN(v)) {
pcercuei 0:03b5121a232e 6808 if ((!neq) && (v==f)) {
pcercuei 0:03b5121a232e 6809 ret = 1;
pcercuei 0:03b5121a232e 6810 break;
pcercuei 0:03b5121a232e 6811 } else if ((neq) && (v!=f)) {
pcercuei 0:03b5121a232e 6812 ret = 1;
pcercuei 0:03b5121a232e 6813 break;
pcercuei 0:03b5121a232e 6814 }
pcercuei 0:03b5121a232e 6815 } else { /* NaN is unequal to any value */
pcercuei 0:03b5121a232e 6816 if (neq)
pcercuei 0:03b5121a232e 6817 ret = 1;
pcercuei 0:03b5121a232e 6818 }
pcercuei 0:03b5121a232e 6819 }
pcercuei 0:03b5121a232e 6820 }
pcercuei 0:03b5121a232e 6821 }
pcercuei 0:03b5121a232e 6822
pcercuei 0:03b5121a232e 6823 return(ret);
pcercuei 0:03b5121a232e 6824 }
pcercuei 0:03b5121a232e 6825
pcercuei 0:03b5121a232e 6826
pcercuei 0:03b5121a232e 6827 /**
pcercuei 0:03b5121a232e 6828 * xmlXPathEqualNodeSets:
pcercuei 0:03b5121a232e 6829 * @arg1: first nodeset object argument
pcercuei 0:03b5121a232e 6830 * @arg2: second nodeset object argument
pcercuei 0:03b5121a232e 6831 * @neq: flag to show whether to test '=' (0) or '!=' (1)
pcercuei 0:03b5121a232e 6832 *
pcercuei 0:03b5121a232e 6833 * Implement the equal / not equal operation on XPath nodesets:
pcercuei 0:03b5121a232e 6834 * @arg1 == @arg2 or @arg1 != @arg2
pcercuei 0:03b5121a232e 6835 * If both objects to be compared are node-sets, then the comparison
pcercuei 0:03b5121a232e 6836 * will be true if and only if there is a node in the first node-set and
pcercuei 0:03b5121a232e 6837 * a node in the second node-set such that the result of performing the
pcercuei 0:03b5121a232e 6838 * comparison on the string-values of the two nodes is true.
pcercuei 0:03b5121a232e 6839 *
pcercuei 0:03b5121a232e 6840 * (needless to say, this is a costly operation)
pcercuei 0:03b5121a232e 6841 *
pcercuei 0:03b5121a232e 6842 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 6843 */
pcercuei 0:03b5121a232e 6844 static int
pcercuei 0:03b5121a232e 6845 xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
pcercuei 0:03b5121a232e 6846 int i, j;
pcercuei 0:03b5121a232e 6847 unsigned int *hashs1;
pcercuei 0:03b5121a232e 6848 unsigned int *hashs2;
pcercuei 0:03b5121a232e 6849 xmlChar **values1;
pcercuei 0:03b5121a232e 6850 xmlChar **values2;
pcercuei 0:03b5121a232e 6851 int ret = 0;
pcercuei 0:03b5121a232e 6852 xmlNodeSetPtr ns1;
pcercuei 0:03b5121a232e 6853 xmlNodeSetPtr ns2;
pcercuei 0:03b5121a232e 6854
pcercuei 0:03b5121a232e 6855 if ((arg1 == NULL) ||
pcercuei 0:03b5121a232e 6856 ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 6857 return(0);
pcercuei 0:03b5121a232e 6858 if ((arg2 == NULL) ||
pcercuei 0:03b5121a232e 6859 ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 6860 return(0);
pcercuei 0:03b5121a232e 6861
pcercuei 0:03b5121a232e 6862 ns1 = arg1->nodesetval;
pcercuei 0:03b5121a232e 6863 ns2 = arg2->nodesetval;
pcercuei 0:03b5121a232e 6864
pcercuei 0:03b5121a232e 6865 if ((ns1 == NULL) || (ns1->nodeNr <= 0))
pcercuei 0:03b5121a232e 6866 return(0);
pcercuei 0:03b5121a232e 6867 if ((ns2 == NULL) || (ns2->nodeNr <= 0))
pcercuei 0:03b5121a232e 6868 return(0);
pcercuei 0:03b5121a232e 6869
pcercuei 0:03b5121a232e 6870 /*
pcercuei 0:03b5121a232e 6871 * for equal, check if there is a node pertaining to both sets
pcercuei 0:03b5121a232e 6872 */
pcercuei 0:03b5121a232e 6873 if (neq == 0)
pcercuei 0:03b5121a232e 6874 for (i = 0;i < ns1->nodeNr;i++)
pcercuei 0:03b5121a232e 6875 for (j = 0;j < ns2->nodeNr;j++)
pcercuei 0:03b5121a232e 6876 if (ns1->nodeTab[i] == ns2->nodeTab[j])
pcercuei 0:03b5121a232e 6877 return(1);
pcercuei 0:03b5121a232e 6878
pcercuei 0:03b5121a232e 6879 values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
pcercuei 0:03b5121a232e 6880 if (values1 == NULL) {
pcercuei 0:03b5121a232e 6881 xmlXPathErrMemory(NULL, "comparing nodesets\n");
pcercuei 0:03b5121a232e 6882 return(0);
pcercuei 0:03b5121a232e 6883 }
pcercuei 0:03b5121a232e 6884 hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
pcercuei 0:03b5121a232e 6885 if (hashs1 == NULL) {
pcercuei 0:03b5121a232e 6886 xmlXPathErrMemory(NULL, "comparing nodesets\n");
pcercuei 0:03b5121a232e 6887 xmlFree(values1);
pcercuei 0:03b5121a232e 6888 return(0);
pcercuei 0:03b5121a232e 6889 }
pcercuei 0:03b5121a232e 6890 memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
pcercuei 0:03b5121a232e 6891 values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
pcercuei 0:03b5121a232e 6892 if (values2 == NULL) {
pcercuei 0:03b5121a232e 6893 xmlXPathErrMemory(NULL, "comparing nodesets\n");
pcercuei 0:03b5121a232e 6894 xmlFree(hashs1);
pcercuei 0:03b5121a232e 6895 xmlFree(values1);
pcercuei 0:03b5121a232e 6896 return(0);
pcercuei 0:03b5121a232e 6897 }
pcercuei 0:03b5121a232e 6898 hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
pcercuei 0:03b5121a232e 6899 if (hashs2 == NULL) {
pcercuei 0:03b5121a232e 6900 xmlXPathErrMemory(NULL, "comparing nodesets\n");
pcercuei 0:03b5121a232e 6901 xmlFree(hashs1);
pcercuei 0:03b5121a232e 6902 xmlFree(values1);
pcercuei 0:03b5121a232e 6903 xmlFree(values2);
pcercuei 0:03b5121a232e 6904 return(0);
pcercuei 0:03b5121a232e 6905 }
pcercuei 0:03b5121a232e 6906 memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
pcercuei 0:03b5121a232e 6907 for (i = 0;i < ns1->nodeNr;i++) {
pcercuei 0:03b5121a232e 6908 hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
pcercuei 0:03b5121a232e 6909 for (j = 0;j < ns2->nodeNr;j++) {
pcercuei 0:03b5121a232e 6910 if (i == 0)
pcercuei 0:03b5121a232e 6911 hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
pcercuei 0:03b5121a232e 6912 if (hashs1[i] != hashs2[j]) {
pcercuei 0:03b5121a232e 6913 if (neq) {
pcercuei 0:03b5121a232e 6914 ret = 1;
pcercuei 0:03b5121a232e 6915 break;
pcercuei 0:03b5121a232e 6916 }
pcercuei 0:03b5121a232e 6917 }
pcercuei 0:03b5121a232e 6918 else {
pcercuei 0:03b5121a232e 6919 if (values1[i] == NULL)
pcercuei 0:03b5121a232e 6920 values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
pcercuei 0:03b5121a232e 6921 if (values2[j] == NULL)
pcercuei 0:03b5121a232e 6922 values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
pcercuei 0:03b5121a232e 6923 ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
pcercuei 0:03b5121a232e 6924 if (ret)
pcercuei 0:03b5121a232e 6925 break;
pcercuei 0:03b5121a232e 6926 }
pcercuei 0:03b5121a232e 6927 }
pcercuei 0:03b5121a232e 6928 if (ret)
pcercuei 0:03b5121a232e 6929 break;
pcercuei 0:03b5121a232e 6930 }
pcercuei 0:03b5121a232e 6931 for (i = 0;i < ns1->nodeNr;i++)
pcercuei 0:03b5121a232e 6932 if (values1[i] != NULL)
pcercuei 0:03b5121a232e 6933 xmlFree(values1[i]);
pcercuei 0:03b5121a232e 6934 for (j = 0;j < ns2->nodeNr;j++)
pcercuei 0:03b5121a232e 6935 if (values2[j] != NULL)
pcercuei 0:03b5121a232e 6936 xmlFree(values2[j]);
pcercuei 0:03b5121a232e 6937 xmlFree(values1);
pcercuei 0:03b5121a232e 6938 xmlFree(values2);
pcercuei 0:03b5121a232e 6939 xmlFree(hashs1);
pcercuei 0:03b5121a232e 6940 xmlFree(hashs2);
pcercuei 0:03b5121a232e 6941 return(ret);
pcercuei 0:03b5121a232e 6942 }
pcercuei 0:03b5121a232e 6943
pcercuei 0:03b5121a232e 6944 static int
pcercuei 0:03b5121a232e 6945 xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 6946 xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
pcercuei 0:03b5121a232e 6947 int ret = 0;
pcercuei 0:03b5121a232e 6948 /*
pcercuei 0:03b5121a232e 6949 *At this point we are assured neither arg1 nor arg2
pcercuei 0:03b5121a232e 6950 *is a nodeset, so we can just pick the appropriate routine.
pcercuei 0:03b5121a232e 6951 */
pcercuei 0:03b5121a232e 6952 switch (arg1->type) {
pcercuei 0:03b5121a232e 6953 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 6954 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 6955 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 6956 "Equal: undefined\n");
pcercuei 0:03b5121a232e 6957 #endif
pcercuei 0:03b5121a232e 6958 break;
pcercuei 0:03b5121a232e 6959 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 6960 switch (arg2->type) {
pcercuei 0:03b5121a232e 6961 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 6962 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 6963 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 6964 "Equal: undefined\n");
pcercuei 0:03b5121a232e 6965 #endif
pcercuei 0:03b5121a232e 6966 break;
pcercuei 0:03b5121a232e 6967 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 6968 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 6969 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 6970 "Equal: %d boolean %d \n",
pcercuei 0:03b5121a232e 6971 arg1->boolval, arg2->boolval);
pcercuei 0:03b5121a232e 6972 #endif
pcercuei 0:03b5121a232e 6973 ret = (arg1->boolval == arg2->boolval);
pcercuei 0:03b5121a232e 6974 break;
pcercuei 0:03b5121a232e 6975 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 6976 ret = (arg1->boolval ==
pcercuei 0:03b5121a232e 6977 xmlXPathCastNumberToBoolean(arg2->floatval));
pcercuei 0:03b5121a232e 6978 break;
pcercuei 0:03b5121a232e 6979 case XPATH_STRING:
pcercuei 0:03b5121a232e 6980 if ((arg2->stringval == NULL) ||
pcercuei 0:03b5121a232e 6981 (arg2->stringval[0] == 0)) ret = 0;
pcercuei 0:03b5121a232e 6982 else
pcercuei 0:03b5121a232e 6983 ret = 1;
pcercuei 0:03b5121a232e 6984 ret = (arg1->boolval == ret);
pcercuei 0:03b5121a232e 6985 break;
pcercuei 0:03b5121a232e 6986 case XPATH_USERS:
pcercuei 0:03b5121a232e 6987 case XPATH_POINT:
pcercuei 0:03b5121a232e 6988 case XPATH_RANGE:
pcercuei 0:03b5121a232e 6989 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 6990 TODO
pcercuei 0:03b5121a232e 6991 break;
pcercuei 0:03b5121a232e 6992 case XPATH_NODESET:
pcercuei 0:03b5121a232e 6993 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 6994 break;
pcercuei 0:03b5121a232e 6995 }
pcercuei 0:03b5121a232e 6996 break;
pcercuei 0:03b5121a232e 6997 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 6998 switch (arg2->type) {
pcercuei 0:03b5121a232e 6999 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 7000 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 7001 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 7002 "Equal: undefined\n");
pcercuei 0:03b5121a232e 7003 #endif
pcercuei 0:03b5121a232e 7004 break;
pcercuei 0:03b5121a232e 7005 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 7006 ret = (arg2->boolval==
pcercuei 0:03b5121a232e 7007 xmlXPathCastNumberToBoolean(arg1->floatval));
pcercuei 0:03b5121a232e 7008 break;
pcercuei 0:03b5121a232e 7009 case XPATH_STRING:
pcercuei 0:03b5121a232e 7010 valuePush(ctxt, arg2);
pcercuei 0:03b5121a232e 7011 xmlXPathNumberFunction(ctxt, 1);
pcercuei 0:03b5121a232e 7012 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7013 /* no break on purpose */
pcercuei 0:03b5121a232e 7014 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 7015 /* Hand check NaN and Infinity equalities */
pcercuei 0:03b5121a232e 7016 if (xmlXPathIsNaN(arg1->floatval) ||
pcercuei 0:03b5121a232e 7017 xmlXPathIsNaN(arg2->floatval)) {
pcercuei 0:03b5121a232e 7018 ret = 0;
pcercuei 0:03b5121a232e 7019 } else if (xmlXPathIsInf(arg1->floatval) == 1) {
pcercuei 0:03b5121a232e 7020 if (xmlXPathIsInf(arg2->floatval) == 1)
pcercuei 0:03b5121a232e 7021 ret = 1;
pcercuei 0:03b5121a232e 7022 else
pcercuei 0:03b5121a232e 7023 ret = 0;
pcercuei 0:03b5121a232e 7024 } else if (xmlXPathIsInf(arg1->floatval) == -1) {
pcercuei 0:03b5121a232e 7025 if (xmlXPathIsInf(arg2->floatval) == -1)
pcercuei 0:03b5121a232e 7026 ret = 1;
pcercuei 0:03b5121a232e 7027 else
pcercuei 0:03b5121a232e 7028 ret = 0;
pcercuei 0:03b5121a232e 7029 } else if (xmlXPathIsInf(arg2->floatval) == 1) {
pcercuei 0:03b5121a232e 7030 if (xmlXPathIsInf(arg1->floatval) == 1)
pcercuei 0:03b5121a232e 7031 ret = 1;
pcercuei 0:03b5121a232e 7032 else
pcercuei 0:03b5121a232e 7033 ret = 0;
pcercuei 0:03b5121a232e 7034 } else if (xmlXPathIsInf(arg2->floatval) == -1) {
pcercuei 0:03b5121a232e 7035 if (xmlXPathIsInf(arg1->floatval) == -1)
pcercuei 0:03b5121a232e 7036 ret = 1;
pcercuei 0:03b5121a232e 7037 else
pcercuei 0:03b5121a232e 7038 ret = 0;
pcercuei 0:03b5121a232e 7039 } else {
pcercuei 0:03b5121a232e 7040 ret = (arg1->floatval == arg2->floatval);
pcercuei 0:03b5121a232e 7041 }
pcercuei 0:03b5121a232e 7042 break;
pcercuei 0:03b5121a232e 7043 case XPATH_USERS:
pcercuei 0:03b5121a232e 7044 case XPATH_POINT:
pcercuei 0:03b5121a232e 7045 case XPATH_RANGE:
pcercuei 0:03b5121a232e 7046 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 7047 TODO
pcercuei 0:03b5121a232e 7048 break;
pcercuei 0:03b5121a232e 7049 case XPATH_NODESET:
pcercuei 0:03b5121a232e 7050 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 7051 break;
pcercuei 0:03b5121a232e 7052 }
pcercuei 0:03b5121a232e 7053 break;
pcercuei 0:03b5121a232e 7054 case XPATH_STRING:
pcercuei 0:03b5121a232e 7055 switch (arg2->type) {
pcercuei 0:03b5121a232e 7056 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 7057 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 7058 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 7059 "Equal: undefined\n");
pcercuei 0:03b5121a232e 7060 #endif
pcercuei 0:03b5121a232e 7061 break;
pcercuei 0:03b5121a232e 7062 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 7063 if ((arg1->stringval == NULL) ||
pcercuei 0:03b5121a232e 7064 (arg1->stringval[0] == 0)) ret = 0;
pcercuei 0:03b5121a232e 7065 else
pcercuei 0:03b5121a232e 7066 ret = 1;
pcercuei 0:03b5121a232e 7067 ret = (arg2->boolval == ret);
pcercuei 0:03b5121a232e 7068 break;
pcercuei 0:03b5121a232e 7069 case XPATH_STRING:
pcercuei 0:03b5121a232e 7070 ret = xmlStrEqual(arg1->stringval, arg2->stringval);
pcercuei 0:03b5121a232e 7071 break;
pcercuei 0:03b5121a232e 7072 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 7073 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 7074 xmlXPathNumberFunction(ctxt, 1);
pcercuei 0:03b5121a232e 7075 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7076 /* Hand check NaN and Infinity equalities */
pcercuei 0:03b5121a232e 7077 if (xmlXPathIsNaN(arg1->floatval) ||
pcercuei 0:03b5121a232e 7078 xmlXPathIsNaN(arg2->floatval)) {
pcercuei 0:03b5121a232e 7079 ret = 0;
pcercuei 0:03b5121a232e 7080 } else if (xmlXPathIsInf(arg1->floatval) == 1) {
pcercuei 0:03b5121a232e 7081 if (xmlXPathIsInf(arg2->floatval) == 1)
pcercuei 0:03b5121a232e 7082 ret = 1;
pcercuei 0:03b5121a232e 7083 else
pcercuei 0:03b5121a232e 7084 ret = 0;
pcercuei 0:03b5121a232e 7085 } else if (xmlXPathIsInf(arg1->floatval) == -1) {
pcercuei 0:03b5121a232e 7086 if (xmlXPathIsInf(arg2->floatval) == -1)
pcercuei 0:03b5121a232e 7087 ret = 1;
pcercuei 0:03b5121a232e 7088 else
pcercuei 0:03b5121a232e 7089 ret = 0;
pcercuei 0:03b5121a232e 7090 } else if (xmlXPathIsInf(arg2->floatval) == 1) {
pcercuei 0:03b5121a232e 7091 if (xmlXPathIsInf(arg1->floatval) == 1)
pcercuei 0:03b5121a232e 7092 ret = 1;
pcercuei 0:03b5121a232e 7093 else
pcercuei 0:03b5121a232e 7094 ret = 0;
pcercuei 0:03b5121a232e 7095 } else if (xmlXPathIsInf(arg2->floatval) == -1) {
pcercuei 0:03b5121a232e 7096 if (xmlXPathIsInf(arg1->floatval) == -1)
pcercuei 0:03b5121a232e 7097 ret = 1;
pcercuei 0:03b5121a232e 7098 else
pcercuei 0:03b5121a232e 7099 ret = 0;
pcercuei 0:03b5121a232e 7100 } else {
pcercuei 0:03b5121a232e 7101 ret = (arg1->floatval == arg2->floatval);
pcercuei 0:03b5121a232e 7102 }
pcercuei 0:03b5121a232e 7103 break;
pcercuei 0:03b5121a232e 7104 case XPATH_USERS:
pcercuei 0:03b5121a232e 7105 case XPATH_POINT:
pcercuei 0:03b5121a232e 7106 case XPATH_RANGE:
pcercuei 0:03b5121a232e 7107 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 7108 TODO
pcercuei 0:03b5121a232e 7109 break;
pcercuei 0:03b5121a232e 7110 case XPATH_NODESET:
pcercuei 0:03b5121a232e 7111 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 7112 break;
pcercuei 0:03b5121a232e 7113 }
pcercuei 0:03b5121a232e 7114 break;
pcercuei 0:03b5121a232e 7115 case XPATH_USERS:
pcercuei 0:03b5121a232e 7116 case XPATH_POINT:
pcercuei 0:03b5121a232e 7117 case XPATH_RANGE:
pcercuei 0:03b5121a232e 7118 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 7119 TODO
pcercuei 0:03b5121a232e 7120 break;
pcercuei 0:03b5121a232e 7121 case XPATH_NODESET:
pcercuei 0:03b5121a232e 7122 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 7123 break;
pcercuei 0:03b5121a232e 7124 }
pcercuei 0:03b5121a232e 7125 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7126 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7127 return(ret);
pcercuei 0:03b5121a232e 7128 }
pcercuei 0:03b5121a232e 7129
pcercuei 0:03b5121a232e 7130 /**
pcercuei 0:03b5121a232e 7131 * xmlXPathEqualValues:
pcercuei 0:03b5121a232e 7132 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7133 *
pcercuei 0:03b5121a232e 7134 * Implement the equal operation on XPath objects content: @arg1 == @arg2
pcercuei 0:03b5121a232e 7135 *
pcercuei 0:03b5121a232e 7136 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 7137 */
pcercuei 0:03b5121a232e 7138 int
pcercuei 0:03b5121a232e 7139 xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7140 xmlXPathObjectPtr arg1, arg2, argtmp;
pcercuei 0:03b5121a232e 7141 int ret = 0;
pcercuei 0:03b5121a232e 7142
pcercuei 0:03b5121a232e 7143 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
pcercuei 0:03b5121a232e 7144 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7145 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7146 if ((arg1 == NULL) || (arg2 == NULL)) {
pcercuei 0:03b5121a232e 7147 if (arg1 != NULL)
pcercuei 0:03b5121a232e 7148 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7149 else
pcercuei 0:03b5121a232e 7150 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7151 XP_ERROR0(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7152 }
pcercuei 0:03b5121a232e 7153
pcercuei 0:03b5121a232e 7154 if (arg1 == arg2) {
pcercuei 0:03b5121a232e 7155 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 7156 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 7157 "Equal: by pointer\n");
pcercuei 0:03b5121a232e 7158 #endif
pcercuei 0:03b5121a232e 7159 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 7160 return(1);
pcercuei 0:03b5121a232e 7161 }
pcercuei 0:03b5121a232e 7162
pcercuei 0:03b5121a232e 7163 /*
pcercuei 0:03b5121a232e 7164 *If either argument is a nodeset, it's a 'special case'
pcercuei 0:03b5121a232e 7165 */
pcercuei 0:03b5121a232e 7166 if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
pcercuei 0:03b5121a232e 7167 (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 7168 /*
pcercuei 0:03b5121a232e 7169 *Hack it to assure arg1 is the nodeset
pcercuei 0:03b5121a232e 7170 */
pcercuei 0:03b5121a232e 7171 if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 7172 argtmp = arg2;
pcercuei 0:03b5121a232e 7173 arg2 = arg1;
pcercuei 0:03b5121a232e 7174 arg1 = argtmp;
pcercuei 0:03b5121a232e 7175 }
pcercuei 0:03b5121a232e 7176 switch (arg2->type) {
pcercuei 0:03b5121a232e 7177 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 7178 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 7179 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 7180 "Equal: undefined\n");
pcercuei 0:03b5121a232e 7181 #endif
pcercuei 0:03b5121a232e 7182 break;
pcercuei 0:03b5121a232e 7183 case XPATH_NODESET:
pcercuei 0:03b5121a232e 7184 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 7185 ret = xmlXPathEqualNodeSets(arg1, arg2, 0);
pcercuei 0:03b5121a232e 7186 break;
pcercuei 0:03b5121a232e 7187 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 7188 if ((arg1->nodesetval == NULL) ||
pcercuei 0:03b5121a232e 7189 (arg1->nodesetval->nodeNr == 0)) ret = 0;
pcercuei 0:03b5121a232e 7190 else
pcercuei 0:03b5121a232e 7191 ret = 1;
pcercuei 0:03b5121a232e 7192 ret = (ret == arg2->boolval);
pcercuei 0:03b5121a232e 7193 break;
pcercuei 0:03b5121a232e 7194 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 7195 ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
pcercuei 0:03b5121a232e 7196 break;
pcercuei 0:03b5121a232e 7197 case XPATH_STRING:
pcercuei 0:03b5121a232e 7198 ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0);
pcercuei 0:03b5121a232e 7199 break;
pcercuei 0:03b5121a232e 7200 case XPATH_USERS:
pcercuei 0:03b5121a232e 7201 case XPATH_POINT:
pcercuei 0:03b5121a232e 7202 case XPATH_RANGE:
pcercuei 0:03b5121a232e 7203 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 7204 TODO
pcercuei 0:03b5121a232e 7205 break;
pcercuei 0:03b5121a232e 7206 }
pcercuei 0:03b5121a232e 7207 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7208 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7209 return(ret);
pcercuei 0:03b5121a232e 7210 }
pcercuei 0:03b5121a232e 7211
pcercuei 0:03b5121a232e 7212 return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
pcercuei 0:03b5121a232e 7213 }
pcercuei 0:03b5121a232e 7214
pcercuei 0:03b5121a232e 7215 /**
pcercuei 0:03b5121a232e 7216 * xmlXPathNotEqualValues:
pcercuei 0:03b5121a232e 7217 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7218 *
pcercuei 0:03b5121a232e 7219 * Implement the equal operation on XPath objects content: @arg1 == @arg2
pcercuei 0:03b5121a232e 7220 *
pcercuei 0:03b5121a232e 7221 * Returns 0 or 1 depending on the results of the test.
pcercuei 0:03b5121a232e 7222 */
pcercuei 0:03b5121a232e 7223 int
pcercuei 0:03b5121a232e 7224 xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7225 xmlXPathObjectPtr arg1, arg2, argtmp;
pcercuei 0:03b5121a232e 7226 int ret = 0;
pcercuei 0:03b5121a232e 7227
pcercuei 0:03b5121a232e 7228 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
pcercuei 0:03b5121a232e 7229 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7230 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7231 if ((arg1 == NULL) || (arg2 == NULL)) {
pcercuei 0:03b5121a232e 7232 if (arg1 != NULL)
pcercuei 0:03b5121a232e 7233 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7234 else
pcercuei 0:03b5121a232e 7235 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7236 XP_ERROR0(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7237 }
pcercuei 0:03b5121a232e 7238
pcercuei 0:03b5121a232e 7239 if (arg1 == arg2) {
pcercuei 0:03b5121a232e 7240 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 7241 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 7242 "NotEqual: by pointer\n");
pcercuei 0:03b5121a232e 7243 #endif
pcercuei 0:03b5121a232e 7244 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7245 return(0);
pcercuei 0:03b5121a232e 7246 }
pcercuei 0:03b5121a232e 7247
pcercuei 0:03b5121a232e 7248 /*
pcercuei 0:03b5121a232e 7249 *If either argument is a nodeset, it's a 'special case'
pcercuei 0:03b5121a232e 7250 */
pcercuei 0:03b5121a232e 7251 if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
pcercuei 0:03b5121a232e 7252 (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 7253 /*
pcercuei 0:03b5121a232e 7254 *Hack it to assure arg1 is the nodeset
pcercuei 0:03b5121a232e 7255 */
pcercuei 0:03b5121a232e 7256 if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 7257 argtmp = arg2;
pcercuei 0:03b5121a232e 7258 arg2 = arg1;
pcercuei 0:03b5121a232e 7259 arg1 = argtmp;
pcercuei 0:03b5121a232e 7260 }
pcercuei 0:03b5121a232e 7261 switch (arg2->type) {
pcercuei 0:03b5121a232e 7262 case XPATH_UNDEFINED:
pcercuei 0:03b5121a232e 7263 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 7264 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 7265 "NotEqual: undefined\n");
pcercuei 0:03b5121a232e 7266 #endif
pcercuei 0:03b5121a232e 7267 break;
pcercuei 0:03b5121a232e 7268 case XPATH_NODESET:
pcercuei 0:03b5121a232e 7269 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 7270 ret = xmlXPathEqualNodeSets(arg1, arg2, 1);
pcercuei 0:03b5121a232e 7271 break;
pcercuei 0:03b5121a232e 7272 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 7273 if ((arg1->nodesetval == NULL) ||
pcercuei 0:03b5121a232e 7274 (arg1->nodesetval->nodeNr == 0)) ret = 0;
pcercuei 0:03b5121a232e 7275 else
pcercuei 0:03b5121a232e 7276 ret = 1;
pcercuei 0:03b5121a232e 7277 ret = (ret != arg2->boolval);
pcercuei 0:03b5121a232e 7278 break;
pcercuei 0:03b5121a232e 7279 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 7280 ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
pcercuei 0:03b5121a232e 7281 break;
pcercuei 0:03b5121a232e 7282 case XPATH_STRING:
pcercuei 0:03b5121a232e 7283 ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1);
pcercuei 0:03b5121a232e 7284 break;
pcercuei 0:03b5121a232e 7285 case XPATH_USERS:
pcercuei 0:03b5121a232e 7286 case XPATH_POINT:
pcercuei 0:03b5121a232e 7287 case XPATH_RANGE:
pcercuei 0:03b5121a232e 7288 case XPATH_LOCATIONSET:
pcercuei 0:03b5121a232e 7289 TODO
pcercuei 0:03b5121a232e 7290 break;
pcercuei 0:03b5121a232e 7291 }
pcercuei 0:03b5121a232e 7292 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7293 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7294 return(ret);
pcercuei 0:03b5121a232e 7295 }
pcercuei 0:03b5121a232e 7296
pcercuei 0:03b5121a232e 7297 return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
pcercuei 0:03b5121a232e 7298 }
pcercuei 0:03b5121a232e 7299
pcercuei 0:03b5121a232e 7300 /**
pcercuei 0:03b5121a232e 7301 * xmlXPathCompareValues:
pcercuei 0:03b5121a232e 7302 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7303 * @inf: less than (1) or greater than (0)
pcercuei 0:03b5121a232e 7304 * @strict: is the comparison strict
pcercuei 0:03b5121a232e 7305 *
pcercuei 0:03b5121a232e 7306 * Implement the compare operation on XPath objects:
pcercuei 0:03b5121a232e 7307 * @arg1 < @arg2 (1, 1, ...
pcercuei 0:03b5121a232e 7308 * @arg1 <= @arg2 (1, 0, ...
pcercuei 0:03b5121a232e 7309 * @arg1 > @arg2 (0, 1, ...
pcercuei 0:03b5121a232e 7310 * @arg1 >= @arg2 (0, 0, ...
pcercuei 0:03b5121a232e 7311 *
pcercuei 0:03b5121a232e 7312 * When neither object to be compared is a node-set and the operator is
pcercuei 0:03b5121a232e 7313 * <=, <, >=, >, then the objects are compared by converted both objects
pcercuei 0:03b5121a232e 7314 * to numbers and comparing the numbers according to IEEE 754. The <
pcercuei 0:03b5121a232e 7315 * comparison will be true if and only if the first number is less than the
pcercuei 0:03b5121a232e 7316 * second number. The <= comparison will be true if and only if the first
pcercuei 0:03b5121a232e 7317 * number is less than or equal to the second number. The > comparison
pcercuei 0:03b5121a232e 7318 * will be true if and only if the first number is greater than the second
pcercuei 0:03b5121a232e 7319 * number. The >= comparison will be true if and only if the first number
pcercuei 0:03b5121a232e 7320 * is greater than or equal to the second number.
pcercuei 0:03b5121a232e 7321 *
pcercuei 0:03b5121a232e 7322 * Returns 1 if the comparison succeeded, 0 if it failed
pcercuei 0:03b5121a232e 7323 */
pcercuei 0:03b5121a232e 7324 int
pcercuei 0:03b5121a232e 7325 xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
pcercuei 0:03b5121a232e 7326 int ret = 0, arg1i = 0, arg2i = 0;
pcercuei 0:03b5121a232e 7327 xmlXPathObjectPtr arg1, arg2;
pcercuei 0:03b5121a232e 7328
pcercuei 0:03b5121a232e 7329 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
pcercuei 0:03b5121a232e 7330 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7331 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7332 if ((arg1 == NULL) || (arg2 == NULL)) {
pcercuei 0:03b5121a232e 7333 if (arg1 != NULL)
pcercuei 0:03b5121a232e 7334 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7335 else
pcercuei 0:03b5121a232e 7336 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7337 XP_ERROR0(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7338 }
pcercuei 0:03b5121a232e 7339
pcercuei 0:03b5121a232e 7340 if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
pcercuei 0:03b5121a232e 7341 (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 7342 /*
pcercuei 0:03b5121a232e 7343 * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments
pcercuei 0:03b5121a232e 7344 * are not freed from within this routine; they will be freed from the
pcercuei 0:03b5121a232e 7345 * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue
pcercuei 0:03b5121a232e 7346 */
pcercuei 0:03b5121a232e 7347 if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
pcercuei 0:03b5121a232e 7348 ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
pcercuei 0:03b5121a232e 7349 ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2);
pcercuei 0:03b5121a232e 7350 } else {
pcercuei 0:03b5121a232e 7351 if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 7352 ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
pcercuei 0:03b5121a232e 7353 arg1, arg2);
pcercuei 0:03b5121a232e 7354 } else {
pcercuei 0:03b5121a232e 7355 ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
pcercuei 0:03b5121a232e 7356 arg2, arg1);
pcercuei 0:03b5121a232e 7357 }
pcercuei 0:03b5121a232e 7358 }
pcercuei 0:03b5121a232e 7359 return(ret);
pcercuei 0:03b5121a232e 7360 }
pcercuei 0:03b5121a232e 7361
pcercuei 0:03b5121a232e 7362 if (arg1->type != XPATH_NUMBER) {
pcercuei 0:03b5121a232e 7363 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 7364 xmlXPathNumberFunction(ctxt, 1);
pcercuei 0:03b5121a232e 7365 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7366 }
pcercuei 0:03b5121a232e 7367 if (arg1->type != XPATH_NUMBER) {
pcercuei 0:03b5121a232e 7368 xmlXPathFreeObject(arg1);
pcercuei 0:03b5121a232e 7369 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 7370 XP_ERROR0(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7371 }
pcercuei 0:03b5121a232e 7372 if (arg2->type != XPATH_NUMBER) {
pcercuei 0:03b5121a232e 7373 valuePush(ctxt, arg2);
pcercuei 0:03b5121a232e 7374 xmlXPathNumberFunction(ctxt, 1);
pcercuei 0:03b5121a232e 7375 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 7376 }
pcercuei 0:03b5121a232e 7377 if (arg2->type != XPATH_NUMBER) {
pcercuei 0:03b5121a232e 7378 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7379 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7380 XP_ERROR0(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7381 }
pcercuei 0:03b5121a232e 7382 /*
pcercuei 0:03b5121a232e 7383 * Add tests for infinity and nan
pcercuei 0:03b5121a232e 7384 * => feedback on 3.4 for Inf and NaN
pcercuei 0:03b5121a232e 7385 */
pcercuei 0:03b5121a232e 7386 /* Hand check NaN and Infinity comparisons */
pcercuei 0:03b5121a232e 7387 if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
pcercuei 0:03b5121a232e 7388 ret=0;
pcercuei 0:03b5121a232e 7389 } else {
pcercuei 0:03b5121a232e 7390 arg1i=xmlXPathIsInf(arg1->floatval);
pcercuei 0:03b5121a232e 7391 arg2i=xmlXPathIsInf(arg2->floatval);
pcercuei 0:03b5121a232e 7392 if (inf && strict) {
pcercuei 0:03b5121a232e 7393 if ((arg1i == -1 && arg2i != -1) ||
pcercuei 0:03b5121a232e 7394 (arg2i == 1 && arg1i != 1)) {
pcercuei 0:03b5121a232e 7395 ret = 1;
pcercuei 0:03b5121a232e 7396 } else if (arg1i == 0 && arg2i == 0) {
pcercuei 0:03b5121a232e 7397 ret = (arg1->floatval < arg2->floatval);
pcercuei 0:03b5121a232e 7398 } else {
pcercuei 0:03b5121a232e 7399 ret = 0;
pcercuei 0:03b5121a232e 7400 }
pcercuei 0:03b5121a232e 7401 }
pcercuei 0:03b5121a232e 7402 else if (inf && !strict) {
pcercuei 0:03b5121a232e 7403 if (arg1i == -1 || arg2i == 1) {
pcercuei 0:03b5121a232e 7404 ret = 1;
pcercuei 0:03b5121a232e 7405 } else if (arg1i == 0 && arg2i == 0) {
pcercuei 0:03b5121a232e 7406 ret = (arg1->floatval <= arg2->floatval);
pcercuei 0:03b5121a232e 7407 } else {
pcercuei 0:03b5121a232e 7408 ret = 0;
pcercuei 0:03b5121a232e 7409 }
pcercuei 0:03b5121a232e 7410 }
pcercuei 0:03b5121a232e 7411 else if (!inf && strict) {
pcercuei 0:03b5121a232e 7412 if ((arg1i == 1 && arg2i != 1) ||
pcercuei 0:03b5121a232e 7413 (arg2i == -1 && arg1i != -1)) {
pcercuei 0:03b5121a232e 7414 ret = 1;
pcercuei 0:03b5121a232e 7415 } else if (arg1i == 0 && arg2i == 0) {
pcercuei 0:03b5121a232e 7416 ret = (arg1->floatval > arg2->floatval);
pcercuei 0:03b5121a232e 7417 } else {
pcercuei 0:03b5121a232e 7418 ret = 0;
pcercuei 0:03b5121a232e 7419 }
pcercuei 0:03b5121a232e 7420 }
pcercuei 0:03b5121a232e 7421 else if (!inf && !strict) {
pcercuei 0:03b5121a232e 7422 if (arg1i == 1 || arg2i == -1) {
pcercuei 0:03b5121a232e 7423 ret = 1;
pcercuei 0:03b5121a232e 7424 } else if (arg1i == 0 && arg2i == 0) {
pcercuei 0:03b5121a232e 7425 ret = (arg1->floatval >= arg2->floatval);
pcercuei 0:03b5121a232e 7426 } else {
pcercuei 0:03b5121a232e 7427 ret = 0;
pcercuei 0:03b5121a232e 7428 }
pcercuei 0:03b5121a232e 7429 }
pcercuei 0:03b5121a232e 7430 }
pcercuei 0:03b5121a232e 7431 xmlXPathReleaseObject(ctxt->context, arg1);
pcercuei 0:03b5121a232e 7432 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 7433 return(ret);
pcercuei 0:03b5121a232e 7434 }
pcercuei 0:03b5121a232e 7435
pcercuei 0:03b5121a232e 7436 /**
pcercuei 0:03b5121a232e 7437 * xmlXPathValueFlipSign:
pcercuei 0:03b5121a232e 7438 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7439 *
pcercuei 0:03b5121a232e 7440 * Implement the unary - operation on an XPath object
pcercuei 0:03b5121a232e 7441 * The numeric operators convert their operands to numbers as if
pcercuei 0:03b5121a232e 7442 * by calling the number function.
pcercuei 0:03b5121a232e 7443 */
pcercuei 0:03b5121a232e 7444 void
pcercuei 0:03b5121a232e 7445 xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7446 if ((ctxt == NULL) || (ctxt->context == NULL)) return;
pcercuei 0:03b5121a232e 7447 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 7448 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 7449 if (xmlXPathIsNaN(ctxt->value->floatval))
pcercuei 0:03b5121a232e 7450 ctxt->value->floatval=xmlXPathNAN;
pcercuei 0:03b5121a232e 7451 else if (xmlXPathIsInf(ctxt->value->floatval) == 1)
pcercuei 0:03b5121a232e 7452 ctxt->value->floatval=xmlXPathNINF;
pcercuei 0:03b5121a232e 7453 else if (xmlXPathIsInf(ctxt->value->floatval) == -1)
pcercuei 0:03b5121a232e 7454 ctxt->value->floatval=xmlXPathPINF;
pcercuei 0:03b5121a232e 7455 else if (ctxt->value->floatval == 0) {
pcercuei 0:03b5121a232e 7456 if (xmlXPathGetSign(ctxt->value->floatval) == 0)
pcercuei 0:03b5121a232e 7457 ctxt->value->floatval = xmlXPathNZERO;
pcercuei 0:03b5121a232e 7458 else
pcercuei 0:03b5121a232e 7459 ctxt->value->floatval = 0;
pcercuei 0:03b5121a232e 7460 }
pcercuei 0:03b5121a232e 7461 else
pcercuei 0:03b5121a232e 7462 ctxt->value->floatval = - ctxt->value->floatval;
pcercuei 0:03b5121a232e 7463 }
pcercuei 0:03b5121a232e 7464
pcercuei 0:03b5121a232e 7465 /**
pcercuei 0:03b5121a232e 7466 * xmlXPathAddValues:
pcercuei 0:03b5121a232e 7467 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7468 *
pcercuei 0:03b5121a232e 7469 * Implement the add operation on XPath objects:
pcercuei 0:03b5121a232e 7470 * The numeric operators convert their operands to numbers as if
pcercuei 0:03b5121a232e 7471 * by calling the number function.
pcercuei 0:03b5121a232e 7472 */
pcercuei 0:03b5121a232e 7473 void
pcercuei 0:03b5121a232e 7474 xmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7475 xmlXPathObjectPtr arg;
pcercuei 0:03b5121a232e 7476 double val;
pcercuei 0:03b5121a232e 7477
pcercuei 0:03b5121a232e 7478 arg = valuePop(ctxt);
pcercuei 0:03b5121a232e 7479 if (arg == NULL)
pcercuei 0:03b5121a232e 7480 XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7481 val = xmlXPathCastToNumber(arg);
pcercuei 0:03b5121a232e 7482 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 7483 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 7484 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 7485 ctxt->value->floatval += val;
pcercuei 0:03b5121a232e 7486 }
pcercuei 0:03b5121a232e 7487
pcercuei 0:03b5121a232e 7488 /**
pcercuei 0:03b5121a232e 7489 * xmlXPathSubValues:
pcercuei 0:03b5121a232e 7490 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7491 *
pcercuei 0:03b5121a232e 7492 * Implement the subtraction operation on XPath objects:
pcercuei 0:03b5121a232e 7493 * The numeric operators convert their operands to numbers as if
pcercuei 0:03b5121a232e 7494 * by calling the number function.
pcercuei 0:03b5121a232e 7495 */
pcercuei 0:03b5121a232e 7496 void
pcercuei 0:03b5121a232e 7497 xmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7498 xmlXPathObjectPtr arg;
pcercuei 0:03b5121a232e 7499 double val;
pcercuei 0:03b5121a232e 7500
pcercuei 0:03b5121a232e 7501 arg = valuePop(ctxt);
pcercuei 0:03b5121a232e 7502 if (arg == NULL)
pcercuei 0:03b5121a232e 7503 XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7504 val = xmlXPathCastToNumber(arg);
pcercuei 0:03b5121a232e 7505 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 7506 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 7507 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 7508 ctxt->value->floatval -= val;
pcercuei 0:03b5121a232e 7509 }
pcercuei 0:03b5121a232e 7510
pcercuei 0:03b5121a232e 7511 /**
pcercuei 0:03b5121a232e 7512 * xmlXPathMultValues:
pcercuei 0:03b5121a232e 7513 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7514 *
pcercuei 0:03b5121a232e 7515 * Implement the multiply operation on XPath objects:
pcercuei 0:03b5121a232e 7516 * The numeric operators convert their operands to numbers as if
pcercuei 0:03b5121a232e 7517 * by calling the number function.
pcercuei 0:03b5121a232e 7518 */
pcercuei 0:03b5121a232e 7519 void
pcercuei 0:03b5121a232e 7520 xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7521 xmlXPathObjectPtr arg;
pcercuei 0:03b5121a232e 7522 double val;
pcercuei 0:03b5121a232e 7523
pcercuei 0:03b5121a232e 7524 arg = valuePop(ctxt);
pcercuei 0:03b5121a232e 7525 if (arg == NULL)
pcercuei 0:03b5121a232e 7526 XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7527 val = xmlXPathCastToNumber(arg);
pcercuei 0:03b5121a232e 7528 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 7529 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 7530 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 7531 ctxt->value->floatval *= val;
pcercuei 0:03b5121a232e 7532 }
pcercuei 0:03b5121a232e 7533
pcercuei 0:03b5121a232e 7534 /**
pcercuei 0:03b5121a232e 7535 * xmlXPathDivValues:
pcercuei 0:03b5121a232e 7536 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7537 *
pcercuei 0:03b5121a232e 7538 * Implement the div operation on XPath objects @arg1 / @arg2:
pcercuei 0:03b5121a232e 7539 * The numeric operators convert their operands to numbers as if
pcercuei 0:03b5121a232e 7540 * by calling the number function.
pcercuei 0:03b5121a232e 7541 */
pcercuei 0:03b5121a232e 7542 void
pcercuei 0:03b5121a232e 7543 xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7544 xmlXPathObjectPtr arg;
pcercuei 0:03b5121a232e 7545 double val;
pcercuei 0:03b5121a232e 7546
pcercuei 0:03b5121a232e 7547 arg = valuePop(ctxt);
pcercuei 0:03b5121a232e 7548 if (arg == NULL)
pcercuei 0:03b5121a232e 7549 XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7550 val = xmlXPathCastToNumber(arg);
pcercuei 0:03b5121a232e 7551 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 7552 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 7553 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 7554 if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval))
pcercuei 0:03b5121a232e 7555 ctxt->value->floatval = xmlXPathNAN;
pcercuei 0:03b5121a232e 7556 else if (val == 0 && xmlXPathGetSign(val) != 0) {
pcercuei 0:03b5121a232e 7557 if (ctxt->value->floatval == 0)
pcercuei 0:03b5121a232e 7558 ctxt->value->floatval = xmlXPathNAN;
pcercuei 0:03b5121a232e 7559 else if (ctxt->value->floatval > 0)
pcercuei 0:03b5121a232e 7560 ctxt->value->floatval = xmlXPathNINF;
pcercuei 0:03b5121a232e 7561 else if (ctxt->value->floatval < 0)
pcercuei 0:03b5121a232e 7562 ctxt->value->floatval = xmlXPathPINF;
pcercuei 0:03b5121a232e 7563 }
pcercuei 0:03b5121a232e 7564 else if (val == 0) {
pcercuei 0:03b5121a232e 7565 if (ctxt->value->floatval == 0)
pcercuei 0:03b5121a232e 7566 ctxt->value->floatval = xmlXPathNAN;
pcercuei 0:03b5121a232e 7567 else if (ctxt->value->floatval > 0)
pcercuei 0:03b5121a232e 7568 ctxt->value->floatval = xmlXPathPINF;
pcercuei 0:03b5121a232e 7569 else if (ctxt->value->floatval < 0)
pcercuei 0:03b5121a232e 7570 ctxt->value->floatval = xmlXPathNINF;
pcercuei 0:03b5121a232e 7571 } else
pcercuei 0:03b5121a232e 7572 ctxt->value->floatval /= val;
pcercuei 0:03b5121a232e 7573 }
pcercuei 0:03b5121a232e 7574
pcercuei 0:03b5121a232e 7575 /**
pcercuei 0:03b5121a232e 7576 * xmlXPathModValues:
pcercuei 0:03b5121a232e 7577 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7578 *
pcercuei 0:03b5121a232e 7579 * Implement the mod operation on XPath objects: @arg1 / @arg2
pcercuei 0:03b5121a232e 7580 * The numeric operators convert their operands to numbers as if
pcercuei 0:03b5121a232e 7581 * by calling the number function.
pcercuei 0:03b5121a232e 7582 */
pcercuei 0:03b5121a232e 7583 void
pcercuei 0:03b5121a232e 7584 xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 7585 xmlXPathObjectPtr arg;
pcercuei 0:03b5121a232e 7586 double arg1, arg2;
pcercuei 0:03b5121a232e 7587
pcercuei 0:03b5121a232e 7588 arg = valuePop(ctxt);
pcercuei 0:03b5121a232e 7589 if (arg == NULL)
pcercuei 0:03b5121a232e 7590 XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 7591 arg2 = xmlXPathCastToNumber(arg);
pcercuei 0:03b5121a232e 7592 xmlXPathReleaseObject(ctxt->context, arg);
pcercuei 0:03b5121a232e 7593 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 7594 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 7595 arg1 = ctxt->value->floatval;
pcercuei 0:03b5121a232e 7596 if (arg2 == 0)
pcercuei 0:03b5121a232e 7597 ctxt->value->floatval = xmlXPathNAN;
pcercuei 0:03b5121a232e 7598 else {
pcercuei 0:03b5121a232e 7599 ctxt->value->floatval = fmod(arg1, arg2);
pcercuei 0:03b5121a232e 7600 }
pcercuei 0:03b5121a232e 7601 }
pcercuei 0:03b5121a232e 7602
pcercuei 0:03b5121a232e 7603 /************************************************************************
pcercuei 0:03b5121a232e 7604 * *
pcercuei 0:03b5121a232e 7605 * The traversal functions *
pcercuei 0:03b5121a232e 7606 * *
pcercuei 0:03b5121a232e 7607 ************************************************************************/
pcercuei 0:03b5121a232e 7608
pcercuei 0:03b5121a232e 7609 /*
pcercuei 0:03b5121a232e 7610 * A traversal function enumerates nodes along an axis.
pcercuei 0:03b5121a232e 7611 * Initially it must be called with NULL, and it indicates
pcercuei 0:03b5121a232e 7612 * termination on the axis by returning NULL.
pcercuei 0:03b5121a232e 7613 */
pcercuei 0:03b5121a232e 7614 typedef xmlNodePtr (*xmlXPathTraversalFunction)
pcercuei 0:03b5121a232e 7615 (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
pcercuei 0:03b5121a232e 7616
pcercuei 0:03b5121a232e 7617 /*
pcercuei 0:03b5121a232e 7618 * xmlXPathTraversalFunctionExt:
pcercuei 0:03b5121a232e 7619 * A traversal function enumerates nodes along an axis.
pcercuei 0:03b5121a232e 7620 * Initially it must be called with NULL, and it indicates
pcercuei 0:03b5121a232e 7621 * termination on the axis by returning NULL.
pcercuei 0:03b5121a232e 7622 * The context node of the traversal is specified via @contextNode.
pcercuei 0:03b5121a232e 7623 */
pcercuei 0:03b5121a232e 7624 typedef xmlNodePtr (*xmlXPathTraversalFunctionExt)
pcercuei 0:03b5121a232e 7625 (xmlNodePtr cur, xmlNodePtr contextNode);
pcercuei 0:03b5121a232e 7626
pcercuei 0:03b5121a232e 7627 /*
pcercuei 0:03b5121a232e 7628 * xmlXPathNodeSetMergeFunction:
pcercuei 0:03b5121a232e 7629 * Used for merging node sets in xmlXPathCollectAndTest().
pcercuei 0:03b5121a232e 7630 */
pcercuei 0:03b5121a232e 7631 typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction)
pcercuei 0:03b5121a232e 7632 (xmlNodeSetPtr, xmlNodeSetPtr, int);
pcercuei 0:03b5121a232e 7633
pcercuei 0:03b5121a232e 7634
pcercuei 0:03b5121a232e 7635 /**
pcercuei 0:03b5121a232e 7636 * xmlXPathNextSelf:
pcercuei 0:03b5121a232e 7637 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7638 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7639 *
pcercuei 0:03b5121a232e 7640 * Traversal function for the "self" direction
pcercuei 0:03b5121a232e 7641 * The self axis contains just the context node itself
pcercuei 0:03b5121a232e 7642 *
pcercuei 0:03b5121a232e 7643 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7644 */
pcercuei 0:03b5121a232e 7645 xmlNodePtr
pcercuei 0:03b5121a232e 7646 xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 7647 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 7648 if (cur == NULL)
pcercuei 0:03b5121a232e 7649 return(ctxt->context->node);
pcercuei 0:03b5121a232e 7650 return(NULL);
pcercuei 0:03b5121a232e 7651 }
pcercuei 0:03b5121a232e 7652
pcercuei 0:03b5121a232e 7653 /**
pcercuei 0:03b5121a232e 7654 * xmlXPathNextChild:
pcercuei 0:03b5121a232e 7655 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7656 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7657 *
pcercuei 0:03b5121a232e 7658 * Traversal function for the "child" direction
pcercuei 0:03b5121a232e 7659 * The child axis contains the children of the context node in document order.
pcercuei 0:03b5121a232e 7660 *
pcercuei 0:03b5121a232e 7661 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7662 */
pcercuei 0:03b5121a232e 7663 xmlNodePtr
pcercuei 0:03b5121a232e 7664 xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 7665 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 7666 if (cur == NULL) {
pcercuei 0:03b5121a232e 7667 if (ctxt->context->node == NULL) return(NULL);
pcercuei 0:03b5121a232e 7668 switch (ctxt->context->node->type) {
pcercuei 0:03b5121a232e 7669 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 7670 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 7671 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 7672 case XML_ENTITY_REF_NODE:
pcercuei 0:03b5121a232e 7673 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 7674 case XML_PI_NODE:
pcercuei 0:03b5121a232e 7675 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 7676 case XML_NOTATION_NODE:
pcercuei 0:03b5121a232e 7677 case XML_DTD_NODE:
pcercuei 0:03b5121a232e 7678 return(ctxt->context->node->children);
pcercuei 0:03b5121a232e 7679 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7680 case XML_DOCUMENT_TYPE_NODE:
pcercuei 0:03b5121a232e 7681 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 7682 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7683 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 7684 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7685 #endif
pcercuei 0:03b5121a232e 7686 return(((xmlDocPtr) ctxt->context->node)->children);
pcercuei 0:03b5121a232e 7687 case XML_ELEMENT_DECL:
pcercuei 0:03b5121a232e 7688 case XML_ATTRIBUTE_DECL:
pcercuei 0:03b5121a232e 7689 case XML_ENTITY_DECL:
pcercuei 0:03b5121a232e 7690 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 7691 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 7692 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 7693 case XML_XINCLUDE_END:
pcercuei 0:03b5121a232e 7694 return(NULL);
pcercuei 0:03b5121a232e 7695 }
pcercuei 0:03b5121a232e 7696 return(NULL);
pcercuei 0:03b5121a232e 7697 }
pcercuei 0:03b5121a232e 7698 if ((cur->type == XML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 7699 (cur->type == XML_HTML_DOCUMENT_NODE))
pcercuei 0:03b5121a232e 7700 return(NULL);
pcercuei 0:03b5121a232e 7701 return(cur->next);
pcercuei 0:03b5121a232e 7702 }
pcercuei 0:03b5121a232e 7703
pcercuei 0:03b5121a232e 7704 /**
pcercuei 0:03b5121a232e 7705 * xmlXPathNextChildElement:
pcercuei 0:03b5121a232e 7706 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7707 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7708 *
pcercuei 0:03b5121a232e 7709 * Traversal function for the "child" direction and nodes of type element.
pcercuei 0:03b5121a232e 7710 * The child axis contains the children of the context node in document order.
pcercuei 0:03b5121a232e 7711 *
pcercuei 0:03b5121a232e 7712 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7713 */
pcercuei 0:03b5121a232e 7714 static xmlNodePtr
pcercuei 0:03b5121a232e 7715 xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 7716 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 7717 if (cur == NULL) {
pcercuei 0:03b5121a232e 7718 cur = ctxt->context->node;
pcercuei 0:03b5121a232e 7719 if (cur == NULL) return(NULL);
pcercuei 0:03b5121a232e 7720 /*
pcercuei 0:03b5121a232e 7721 * Get the first element child.
pcercuei 0:03b5121a232e 7722 */
pcercuei 0:03b5121a232e 7723 switch (cur->type) {
pcercuei 0:03b5121a232e 7724 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 7725 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 7726 case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */
pcercuei 0:03b5121a232e 7727 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 7728 cur = cur->children;
pcercuei 0:03b5121a232e 7729 if (cur != NULL) {
pcercuei 0:03b5121a232e 7730 if (cur->type == XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 7731 return(cur);
pcercuei 0:03b5121a232e 7732 do {
pcercuei 0:03b5121a232e 7733 cur = cur->next;
pcercuei 0:03b5121a232e 7734 } while ((cur != NULL) &&
pcercuei 0:03b5121a232e 7735 (cur->type != XML_ELEMENT_NODE));
pcercuei 0:03b5121a232e 7736 return(cur);
pcercuei 0:03b5121a232e 7737 }
pcercuei 0:03b5121a232e 7738 return(NULL);
pcercuei 0:03b5121a232e 7739 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7740 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7741 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 7742 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7743 #endif
pcercuei 0:03b5121a232e 7744 return(xmlDocGetRootElement((xmlDocPtr) cur));
pcercuei 0:03b5121a232e 7745 default:
pcercuei 0:03b5121a232e 7746 return(NULL);
pcercuei 0:03b5121a232e 7747 }
pcercuei 0:03b5121a232e 7748 return(NULL);
pcercuei 0:03b5121a232e 7749 }
pcercuei 0:03b5121a232e 7750 /*
pcercuei 0:03b5121a232e 7751 * Get the next sibling element node.
pcercuei 0:03b5121a232e 7752 */
pcercuei 0:03b5121a232e 7753 switch (cur->type) {
pcercuei 0:03b5121a232e 7754 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 7755 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 7756 case XML_ENTITY_REF_NODE:
pcercuei 0:03b5121a232e 7757 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 7758 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 7759 case XML_PI_NODE:
pcercuei 0:03b5121a232e 7760 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 7761 case XML_XINCLUDE_END:
pcercuei 0:03b5121a232e 7762 break;
pcercuei 0:03b5121a232e 7763 /* case XML_DTD_NODE: */ /* URGENT TODO: DTD-node as well? */
pcercuei 0:03b5121a232e 7764 default:
pcercuei 0:03b5121a232e 7765 return(NULL);
pcercuei 0:03b5121a232e 7766 }
pcercuei 0:03b5121a232e 7767 if (cur->next != NULL) {
pcercuei 0:03b5121a232e 7768 if (cur->next->type == XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 7769 return(cur->next);
pcercuei 0:03b5121a232e 7770 cur = cur->next;
pcercuei 0:03b5121a232e 7771 do {
pcercuei 0:03b5121a232e 7772 cur = cur->next;
pcercuei 0:03b5121a232e 7773 } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE));
pcercuei 0:03b5121a232e 7774 return(cur);
pcercuei 0:03b5121a232e 7775 }
pcercuei 0:03b5121a232e 7776 return(NULL);
pcercuei 0:03b5121a232e 7777 }
pcercuei 0:03b5121a232e 7778
pcercuei 0:03b5121a232e 7779 #if 0
pcercuei 0:03b5121a232e 7780 /**
pcercuei 0:03b5121a232e 7781 * xmlXPathNextDescendantOrSelfElemParent:
pcercuei 0:03b5121a232e 7782 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7783 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7784 *
pcercuei 0:03b5121a232e 7785 * Traversal function for the "descendant-or-self" axis.
pcercuei 0:03b5121a232e 7786 * Additionally it returns only nodes which can be parents of
pcercuei 0:03b5121a232e 7787 * element nodes.
pcercuei 0:03b5121a232e 7788 *
pcercuei 0:03b5121a232e 7789 *
pcercuei 0:03b5121a232e 7790 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7791 */
pcercuei 0:03b5121a232e 7792 static xmlNodePtr
pcercuei 0:03b5121a232e 7793 xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur,
pcercuei 0:03b5121a232e 7794 xmlNodePtr contextNode)
pcercuei 0:03b5121a232e 7795 {
pcercuei 0:03b5121a232e 7796 if (cur == NULL) {
pcercuei 0:03b5121a232e 7797 if (contextNode == NULL)
pcercuei 0:03b5121a232e 7798 return(NULL);
pcercuei 0:03b5121a232e 7799 switch (contextNode->type) {
pcercuei 0:03b5121a232e 7800 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 7801 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 7802 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 7803 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7804 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 7805 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7806 #endif
pcercuei 0:03b5121a232e 7807 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7808 return(contextNode);
pcercuei 0:03b5121a232e 7809 default:
pcercuei 0:03b5121a232e 7810 return(NULL);
pcercuei 0:03b5121a232e 7811 }
pcercuei 0:03b5121a232e 7812 return(NULL);
pcercuei 0:03b5121a232e 7813 } else {
pcercuei 0:03b5121a232e 7814 xmlNodePtr start = cur;
pcercuei 0:03b5121a232e 7815
pcercuei 0:03b5121a232e 7816 while (cur != NULL) {
pcercuei 0:03b5121a232e 7817 switch (cur->type) {
pcercuei 0:03b5121a232e 7818 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 7819 /* TODO: OK to have XInclude here? */
pcercuei 0:03b5121a232e 7820 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 7821 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 7822 if (cur != start)
pcercuei 0:03b5121a232e 7823 return(cur);
pcercuei 0:03b5121a232e 7824 if (cur->children != NULL) {
pcercuei 0:03b5121a232e 7825 cur = cur->children;
pcercuei 0:03b5121a232e 7826 continue;
pcercuei 0:03b5121a232e 7827 }
pcercuei 0:03b5121a232e 7828 break;
pcercuei 0:03b5121a232e 7829 /* Not sure if we need those here. */
pcercuei 0:03b5121a232e 7830 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7831 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 7832 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7833 #endif
pcercuei 0:03b5121a232e 7834 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7835 if (cur != start)
pcercuei 0:03b5121a232e 7836 return(cur);
pcercuei 0:03b5121a232e 7837 return(xmlDocGetRootElement((xmlDocPtr) cur));
pcercuei 0:03b5121a232e 7838 default:
pcercuei 0:03b5121a232e 7839 break;
pcercuei 0:03b5121a232e 7840 }
pcercuei 0:03b5121a232e 7841
pcercuei 0:03b5121a232e 7842 next_sibling:
pcercuei 0:03b5121a232e 7843 if ((cur == NULL) || (cur == contextNode))
pcercuei 0:03b5121a232e 7844 return(NULL);
pcercuei 0:03b5121a232e 7845 if (cur->next != NULL) {
pcercuei 0:03b5121a232e 7846 cur = cur->next;
pcercuei 0:03b5121a232e 7847 } else {
pcercuei 0:03b5121a232e 7848 cur = cur->parent;
pcercuei 0:03b5121a232e 7849 goto next_sibling;
pcercuei 0:03b5121a232e 7850 }
pcercuei 0:03b5121a232e 7851 }
pcercuei 0:03b5121a232e 7852 }
pcercuei 0:03b5121a232e 7853 return(NULL);
pcercuei 0:03b5121a232e 7854 }
pcercuei 0:03b5121a232e 7855 #endif
pcercuei 0:03b5121a232e 7856
pcercuei 0:03b5121a232e 7857 /**
pcercuei 0:03b5121a232e 7858 * xmlXPathNextDescendant:
pcercuei 0:03b5121a232e 7859 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7860 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7861 *
pcercuei 0:03b5121a232e 7862 * Traversal function for the "descendant" direction
pcercuei 0:03b5121a232e 7863 * the descendant axis contains the descendants of the context node in document
pcercuei 0:03b5121a232e 7864 * order; a descendant is a child or a child of a child and so on.
pcercuei 0:03b5121a232e 7865 *
pcercuei 0:03b5121a232e 7866 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7867 */
pcercuei 0:03b5121a232e 7868 xmlNodePtr
pcercuei 0:03b5121a232e 7869 xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 7870 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 7871 if (cur == NULL) {
pcercuei 0:03b5121a232e 7872 if (ctxt->context->node == NULL)
pcercuei 0:03b5121a232e 7873 return(NULL);
pcercuei 0:03b5121a232e 7874 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
pcercuei 0:03b5121a232e 7875 (ctxt->context->node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 7876 return(NULL);
pcercuei 0:03b5121a232e 7877
pcercuei 0:03b5121a232e 7878 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
pcercuei 0:03b5121a232e 7879 return(ctxt->context->doc->children);
pcercuei 0:03b5121a232e 7880 return(ctxt->context->node->children);
pcercuei 0:03b5121a232e 7881 }
pcercuei 0:03b5121a232e 7882
pcercuei 0:03b5121a232e 7883 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 7884 return(NULL);
pcercuei 0:03b5121a232e 7885 if (cur->children != NULL) {
pcercuei 0:03b5121a232e 7886 /*
pcercuei 0:03b5121a232e 7887 * Do not descend on entities declarations
pcercuei 0:03b5121a232e 7888 */
pcercuei 0:03b5121a232e 7889 if (cur->children->type != XML_ENTITY_DECL) {
pcercuei 0:03b5121a232e 7890 cur = cur->children;
pcercuei 0:03b5121a232e 7891 /*
pcercuei 0:03b5121a232e 7892 * Skip DTDs
pcercuei 0:03b5121a232e 7893 */
pcercuei 0:03b5121a232e 7894 if (cur->type != XML_DTD_NODE)
pcercuei 0:03b5121a232e 7895 return(cur);
pcercuei 0:03b5121a232e 7896 }
pcercuei 0:03b5121a232e 7897 }
pcercuei 0:03b5121a232e 7898
pcercuei 0:03b5121a232e 7899 if (cur == ctxt->context->node) return(NULL);
pcercuei 0:03b5121a232e 7900
pcercuei 0:03b5121a232e 7901 while (cur->next != NULL) {
pcercuei 0:03b5121a232e 7902 cur = cur->next;
pcercuei 0:03b5121a232e 7903 if ((cur->type != XML_ENTITY_DECL) &&
pcercuei 0:03b5121a232e 7904 (cur->type != XML_DTD_NODE))
pcercuei 0:03b5121a232e 7905 return(cur);
pcercuei 0:03b5121a232e 7906 }
pcercuei 0:03b5121a232e 7907
pcercuei 0:03b5121a232e 7908 do {
pcercuei 0:03b5121a232e 7909 cur = cur->parent;
pcercuei 0:03b5121a232e 7910 if (cur == NULL) break;
pcercuei 0:03b5121a232e 7911 if (cur == ctxt->context->node) return(NULL);
pcercuei 0:03b5121a232e 7912 if (cur->next != NULL) {
pcercuei 0:03b5121a232e 7913 cur = cur->next;
pcercuei 0:03b5121a232e 7914 return(cur);
pcercuei 0:03b5121a232e 7915 }
pcercuei 0:03b5121a232e 7916 } while (cur != NULL);
pcercuei 0:03b5121a232e 7917 return(cur);
pcercuei 0:03b5121a232e 7918 }
pcercuei 0:03b5121a232e 7919
pcercuei 0:03b5121a232e 7920 /**
pcercuei 0:03b5121a232e 7921 * xmlXPathNextDescendantOrSelf:
pcercuei 0:03b5121a232e 7922 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7923 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7924 *
pcercuei 0:03b5121a232e 7925 * Traversal function for the "descendant-or-self" direction
pcercuei 0:03b5121a232e 7926 * the descendant-or-self axis contains the context node and the descendants
pcercuei 0:03b5121a232e 7927 * of the context node in document order; thus the context node is the first
pcercuei 0:03b5121a232e 7928 * node on the axis, and the first child of the context node is the second node
pcercuei 0:03b5121a232e 7929 * on the axis
pcercuei 0:03b5121a232e 7930 *
pcercuei 0:03b5121a232e 7931 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7932 */
pcercuei 0:03b5121a232e 7933 xmlNodePtr
pcercuei 0:03b5121a232e 7934 xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 7935 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 7936 if (cur == NULL)
pcercuei 0:03b5121a232e 7937 return(ctxt->context->node);
pcercuei 0:03b5121a232e 7938
pcercuei 0:03b5121a232e 7939 if (ctxt->context->node == NULL)
pcercuei 0:03b5121a232e 7940 return(NULL);
pcercuei 0:03b5121a232e 7941 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
pcercuei 0:03b5121a232e 7942 (ctxt->context->node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 7943 return(NULL);
pcercuei 0:03b5121a232e 7944
pcercuei 0:03b5121a232e 7945 return(xmlXPathNextDescendant(ctxt, cur));
pcercuei 0:03b5121a232e 7946 }
pcercuei 0:03b5121a232e 7947
pcercuei 0:03b5121a232e 7948 /**
pcercuei 0:03b5121a232e 7949 * xmlXPathNextParent:
pcercuei 0:03b5121a232e 7950 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 7951 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 7952 *
pcercuei 0:03b5121a232e 7953 * Traversal function for the "parent" direction
pcercuei 0:03b5121a232e 7954 * The parent axis contains the parent of the context node, if there is one.
pcercuei 0:03b5121a232e 7955 *
pcercuei 0:03b5121a232e 7956 * Returns the next element following that axis
pcercuei 0:03b5121a232e 7957 */
pcercuei 0:03b5121a232e 7958 xmlNodePtr
pcercuei 0:03b5121a232e 7959 xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 7960 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 7961 /*
pcercuei 0:03b5121a232e 7962 * the parent of an attribute or namespace node is the element
pcercuei 0:03b5121a232e 7963 * to which the attribute or namespace node is attached
pcercuei 0:03b5121a232e 7964 * Namespace handling !!!
pcercuei 0:03b5121a232e 7965 */
pcercuei 0:03b5121a232e 7966 if (cur == NULL) {
pcercuei 0:03b5121a232e 7967 if (ctxt->context->node == NULL) return(NULL);
pcercuei 0:03b5121a232e 7968 switch (ctxt->context->node->type) {
pcercuei 0:03b5121a232e 7969 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 7970 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 7971 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 7972 case XML_ENTITY_REF_NODE:
pcercuei 0:03b5121a232e 7973 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 7974 case XML_PI_NODE:
pcercuei 0:03b5121a232e 7975 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 7976 case XML_NOTATION_NODE:
pcercuei 0:03b5121a232e 7977 case XML_DTD_NODE:
pcercuei 0:03b5121a232e 7978 case XML_ELEMENT_DECL:
pcercuei 0:03b5121a232e 7979 case XML_ATTRIBUTE_DECL:
pcercuei 0:03b5121a232e 7980 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 7981 case XML_XINCLUDE_END:
pcercuei 0:03b5121a232e 7982 case XML_ENTITY_DECL:
pcercuei 0:03b5121a232e 7983 if (ctxt->context->node->parent == NULL)
pcercuei 0:03b5121a232e 7984 return((xmlNodePtr) ctxt->context->doc);
pcercuei 0:03b5121a232e 7985 if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 7986 ((ctxt->context->node->parent->name[0] == ' ') ||
pcercuei 0:03b5121a232e 7987 (xmlStrEqual(ctxt->context->node->parent->name,
pcercuei 0:03b5121a232e 7988 BAD_CAST "fake node libxslt"))))
pcercuei 0:03b5121a232e 7989 return(NULL);
pcercuei 0:03b5121a232e 7990 return(ctxt->context->node->parent);
pcercuei 0:03b5121a232e 7991 case XML_ATTRIBUTE_NODE: {
pcercuei 0:03b5121a232e 7992 xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
pcercuei 0:03b5121a232e 7993
pcercuei 0:03b5121a232e 7994 return(att->parent);
pcercuei 0:03b5121a232e 7995 }
pcercuei 0:03b5121a232e 7996 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 7997 case XML_DOCUMENT_TYPE_NODE:
pcercuei 0:03b5121a232e 7998 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 7999 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8000 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 8001 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8002 #endif
pcercuei 0:03b5121a232e 8003 return(NULL);
pcercuei 0:03b5121a232e 8004 case XML_NAMESPACE_DECL: {
pcercuei 0:03b5121a232e 8005 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
pcercuei 0:03b5121a232e 8006
pcercuei 0:03b5121a232e 8007 if ((ns->next != NULL) &&
pcercuei 0:03b5121a232e 8008 (ns->next->type != XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 8009 return((xmlNodePtr) ns->next);
pcercuei 0:03b5121a232e 8010 return(NULL);
pcercuei 0:03b5121a232e 8011 }
pcercuei 0:03b5121a232e 8012 }
pcercuei 0:03b5121a232e 8013 }
pcercuei 0:03b5121a232e 8014 return(NULL);
pcercuei 0:03b5121a232e 8015 }
pcercuei 0:03b5121a232e 8016
pcercuei 0:03b5121a232e 8017 /**
pcercuei 0:03b5121a232e 8018 * xmlXPathNextAncestor:
pcercuei 0:03b5121a232e 8019 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8020 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8021 *
pcercuei 0:03b5121a232e 8022 * Traversal function for the "ancestor" direction
pcercuei 0:03b5121a232e 8023 * the ancestor axis contains the ancestors of the context node; the ancestors
pcercuei 0:03b5121a232e 8024 * of the context node consist of the parent of context node and the parent's
pcercuei 0:03b5121a232e 8025 * parent and so on; the nodes are ordered in reverse document order; thus the
pcercuei 0:03b5121a232e 8026 * parent is the first node on the axis, and the parent's parent is the second
pcercuei 0:03b5121a232e 8027 * node on the axis
pcercuei 0:03b5121a232e 8028 *
pcercuei 0:03b5121a232e 8029 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8030 */
pcercuei 0:03b5121a232e 8031 xmlNodePtr
pcercuei 0:03b5121a232e 8032 xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8033 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8034 /*
pcercuei 0:03b5121a232e 8035 * the parent of an attribute or namespace node is the element
pcercuei 0:03b5121a232e 8036 * to which the attribute or namespace node is attached
pcercuei 0:03b5121a232e 8037 * !!!!!!!!!!!!!
pcercuei 0:03b5121a232e 8038 */
pcercuei 0:03b5121a232e 8039 if (cur == NULL) {
pcercuei 0:03b5121a232e 8040 if (ctxt->context->node == NULL) return(NULL);
pcercuei 0:03b5121a232e 8041 switch (ctxt->context->node->type) {
pcercuei 0:03b5121a232e 8042 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 8043 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 8044 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 8045 case XML_ENTITY_REF_NODE:
pcercuei 0:03b5121a232e 8046 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 8047 case XML_PI_NODE:
pcercuei 0:03b5121a232e 8048 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 8049 case XML_DTD_NODE:
pcercuei 0:03b5121a232e 8050 case XML_ELEMENT_DECL:
pcercuei 0:03b5121a232e 8051 case XML_ATTRIBUTE_DECL:
pcercuei 0:03b5121a232e 8052 case XML_ENTITY_DECL:
pcercuei 0:03b5121a232e 8053 case XML_NOTATION_NODE:
pcercuei 0:03b5121a232e 8054 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 8055 case XML_XINCLUDE_END:
pcercuei 0:03b5121a232e 8056 if (ctxt->context->node->parent == NULL)
pcercuei 0:03b5121a232e 8057 return((xmlNodePtr) ctxt->context->doc);
pcercuei 0:03b5121a232e 8058 if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 8059 ((ctxt->context->node->parent->name[0] == ' ') ||
pcercuei 0:03b5121a232e 8060 (xmlStrEqual(ctxt->context->node->parent->name,
pcercuei 0:03b5121a232e 8061 BAD_CAST "fake node libxslt"))))
pcercuei 0:03b5121a232e 8062 return(NULL);
pcercuei 0:03b5121a232e 8063 return(ctxt->context->node->parent);
pcercuei 0:03b5121a232e 8064 case XML_ATTRIBUTE_NODE: {
pcercuei 0:03b5121a232e 8065 xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
pcercuei 0:03b5121a232e 8066
pcercuei 0:03b5121a232e 8067 return(tmp->parent);
pcercuei 0:03b5121a232e 8068 }
pcercuei 0:03b5121a232e 8069 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8070 case XML_DOCUMENT_TYPE_NODE:
pcercuei 0:03b5121a232e 8071 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 8072 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8073 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 8074 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8075 #endif
pcercuei 0:03b5121a232e 8076 return(NULL);
pcercuei 0:03b5121a232e 8077 case XML_NAMESPACE_DECL: {
pcercuei 0:03b5121a232e 8078 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
pcercuei 0:03b5121a232e 8079
pcercuei 0:03b5121a232e 8080 if ((ns->next != NULL) &&
pcercuei 0:03b5121a232e 8081 (ns->next->type != XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 8082 return((xmlNodePtr) ns->next);
pcercuei 0:03b5121a232e 8083 /* Bad, how did that namespace end up here ? */
pcercuei 0:03b5121a232e 8084 return(NULL);
pcercuei 0:03b5121a232e 8085 }
pcercuei 0:03b5121a232e 8086 }
pcercuei 0:03b5121a232e 8087 return(NULL);
pcercuei 0:03b5121a232e 8088 }
pcercuei 0:03b5121a232e 8089 if (cur == ctxt->context->doc->children)
pcercuei 0:03b5121a232e 8090 return((xmlNodePtr) ctxt->context->doc);
pcercuei 0:03b5121a232e 8091 if (cur == (xmlNodePtr) ctxt->context->doc)
pcercuei 0:03b5121a232e 8092 return(NULL);
pcercuei 0:03b5121a232e 8093 switch (cur->type) {
pcercuei 0:03b5121a232e 8094 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 8095 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 8096 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 8097 case XML_ENTITY_REF_NODE:
pcercuei 0:03b5121a232e 8098 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 8099 case XML_PI_NODE:
pcercuei 0:03b5121a232e 8100 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 8101 case XML_NOTATION_NODE:
pcercuei 0:03b5121a232e 8102 case XML_DTD_NODE:
pcercuei 0:03b5121a232e 8103 case XML_ELEMENT_DECL:
pcercuei 0:03b5121a232e 8104 case XML_ATTRIBUTE_DECL:
pcercuei 0:03b5121a232e 8105 case XML_ENTITY_DECL:
pcercuei 0:03b5121a232e 8106 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 8107 case XML_XINCLUDE_END:
pcercuei 0:03b5121a232e 8108 if (cur->parent == NULL)
pcercuei 0:03b5121a232e 8109 return(NULL);
pcercuei 0:03b5121a232e 8110 if ((cur->parent->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 8111 ((cur->parent->name[0] == ' ') ||
pcercuei 0:03b5121a232e 8112 (xmlStrEqual(cur->parent->name,
pcercuei 0:03b5121a232e 8113 BAD_CAST "fake node libxslt"))))
pcercuei 0:03b5121a232e 8114 return(NULL);
pcercuei 0:03b5121a232e 8115 return(cur->parent);
pcercuei 0:03b5121a232e 8116 case XML_ATTRIBUTE_NODE: {
pcercuei 0:03b5121a232e 8117 xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
pcercuei 0:03b5121a232e 8118
pcercuei 0:03b5121a232e 8119 return(att->parent);
pcercuei 0:03b5121a232e 8120 }
pcercuei 0:03b5121a232e 8121 case XML_NAMESPACE_DECL: {
pcercuei 0:03b5121a232e 8122 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
pcercuei 0:03b5121a232e 8123
pcercuei 0:03b5121a232e 8124 if ((ns->next != NULL) &&
pcercuei 0:03b5121a232e 8125 (ns->next->type != XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 8126 return((xmlNodePtr) ns->next);
pcercuei 0:03b5121a232e 8127 /* Bad, how did that namespace end up here ? */
pcercuei 0:03b5121a232e 8128 return(NULL);
pcercuei 0:03b5121a232e 8129 }
pcercuei 0:03b5121a232e 8130 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8131 case XML_DOCUMENT_TYPE_NODE:
pcercuei 0:03b5121a232e 8132 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 8133 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8134 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 8135 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 8136 #endif
pcercuei 0:03b5121a232e 8137 return(NULL);
pcercuei 0:03b5121a232e 8138 }
pcercuei 0:03b5121a232e 8139 return(NULL);
pcercuei 0:03b5121a232e 8140 }
pcercuei 0:03b5121a232e 8141
pcercuei 0:03b5121a232e 8142 /**
pcercuei 0:03b5121a232e 8143 * xmlXPathNextAncestorOrSelf:
pcercuei 0:03b5121a232e 8144 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8145 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8146 *
pcercuei 0:03b5121a232e 8147 * Traversal function for the "ancestor-or-self" direction
pcercuei 0:03b5121a232e 8148 * he ancestor-or-self axis contains the context node and ancestors of
pcercuei 0:03b5121a232e 8149 * the context node in reverse document order; thus the context node is
pcercuei 0:03b5121a232e 8150 * the first node on the axis, and the context node's parent the second;
pcercuei 0:03b5121a232e 8151 * parent here is defined the same as with the parent axis.
pcercuei 0:03b5121a232e 8152 *
pcercuei 0:03b5121a232e 8153 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8154 */
pcercuei 0:03b5121a232e 8155 xmlNodePtr
pcercuei 0:03b5121a232e 8156 xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8157 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8158 if (cur == NULL)
pcercuei 0:03b5121a232e 8159 return(ctxt->context->node);
pcercuei 0:03b5121a232e 8160 return(xmlXPathNextAncestor(ctxt, cur));
pcercuei 0:03b5121a232e 8161 }
pcercuei 0:03b5121a232e 8162
pcercuei 0:03b5121a232e 8163 /**
pcercuei 0:03b5121a232e 8164 * xmlXPathNextFollowingSibling:
pcercuei 0:03b5121a232e 8165 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8166 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8167 *
pcercuei 0:03b5121a232e 8168 * Traversal function for the "following-sibling" direction
pcercuei 0:03b5121a232e 8169 * The following-sibling axis contains the following siblings of the context
pcercuei 0:03b5121a232e 8170 * node in document order.
pcercuei 0:03b5121a232e 8171 *
pcercuei 0:03b5121a232e 8172 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8173 */
pcercuei 0:03b5121a232e 8174 xmlNodePtr
pcercuei 0:03b5121a232e 8175 xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8176 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8177 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
pcercuei 0:03b5121a232e 8178 (ctxt->context->node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 8179 return(NULL);
pcercuei 0:03b5121a232e 8180 if (cur == (xmlNodePtr) ctxt->context->doc)
pcercuei 0:03b5121a232e 8181 return(NULL);
pcercuei 0:03b5121a232e 8182 if (cur == NULL)
pcercuei 0:03b5121a232e 8183 return(ctxt->context->node->next);
pcercuei 0:03b5121a232e 8184 return(cur->next);
pcercuei 0:03b5121a232e 8185 }
pcercuei 0:03b5121a232e 8186
pcercuei 0:03b5121a232e 8187 /**
pcercuei 0:03b5121a232e 8188 * xmlXPathNextPrecedingSibling:
pcercuei 0:03b5121a232e 8189 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8190 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8191 *
pcercuei 0:03b5121a232e 8192 * Traversal function for the "preceding-sibling" direction
pcercuei 0:03b5121a232e 8193 * The preceding-sibling axis contains the preceding siblings of the context
pcercuei 0:03b5121a232e 8194 * node in reverse document order; the first preceding sibling is first on the
pcercuei 0:03b5121a232e 8195 * axis; the sibling preceding that node is the second on the axis and so on.
pcercuei 0:03b5121a232e 8196 *
pcercuei 0:03b5121a232e 8197 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8198 */
pcercuei 0:03b5121a232e 8199 xmlNodePtr
pcercuei 0:03b5121a232e 8200 xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8201 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8202 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
pcercuei 0:03b5121a232e 8203 (ctxt->context->node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 8204 return(NULL);
pcercuei 0:03b5121a232e 8205 if (cur == (xmlNodePtr) ctxt->context->doc)
pcercuei 0:03b5121a232e 8206 return(NULL);
pcercuei 0:03b5121a232e 8207 if (cur == NULL)
pcercuei 0:03b5121a232e 8208 return(ctxt->context->node->prev);
pcercuei 0:03b5121a232e 8209 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
pcercuei 0:03b5121a232e 8210 cur = cur->prev;
pcercuei 0:03b5121a232e 8211 if (cur == NULL)
pcercuei 0:03b5121a232e 8212 return(ctxt->context->node->prev);
pcercuei 0:03b5121a232e 8213 }
pcercuei 0:03b5121a232e 8214 return(cur->prev);
pcercuei 0:03b5121a232e 8215 }
pcercuei 0:03b5121a232e 8216
pcercuei 0:03b5121a232e 8217 /**
pcercuei 0:03b5121a232e 8218 * xmlXPathNextFollowing:
pcercuei 0:03b5121a232e 8219 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8220 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8221 *
pcercuei 0:03b5121a232e 8222 * Traversal function for the "following" direction
pcercuei 0:03b5121a232e 8223 * The following axis contains all nodes in the same document as the context
pcercuei 0:03b5121a232e 8224 * node that are after the context node in document order, excluding any
pcercuei 0:03b5121a232e 8225 * descendants and excluding attribute nodes and namespace nodes; the nodes
pcercuei 0:03b5121a232e 8226 * are ordered in document order
pcercuei 0:03b5121a232e 8227 *
pcercuei 0:03b5121a232e 8228 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8229 */
pcercuei 0:03b5121a232e 8230 xmlNodePtr
pcercuei 0:03b5121a232e 8231 xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8232 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8233 if ((cur != NULL) && (cur->type != XML_ATTRIBUTE_NODE) &&
pcercuei 0:03b5121a232e 8234 (cur->type != XML_NAMESPACE_DECL) && (cur->children != NULL))
pcercuei 0:03b5121a232e 8235 return(cur->children);
pcercuei 0:03b5121a232e 8236
pcercuei 0:03b5121a232e 8237 if (cur == NULL) {
pcercuei 0:03b5121a232e 8238 cur = ctxt->context->node;
pcercuei 0:03b5121a232e 8239 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 8240 return(NULL);
pcercuei 0:03b5121a232e 8241 if (cur->type == XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 8242 cur = cur->parent;
pcercuei 0:03b5121a232e 8243 }
pcercuei 0:03b5121a232e 8244 if (cur == NULL) return(NULL) ; /* ERROR */
pcercuei 0:03b5121a232e 8245 if (cur->next != NULL) return(cur->next) ;
pcercuei 0:03b5121a232e 8246 do {
pcercuei 0:03b5121a232e 8247 cur = cur->parent;
pcercuei 0:03b5121a232e 8248 if (cur == NULL) break;
pcercuei 0:03b5121a232e 8249 if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
pcercuei 0:03b5121a232e 8250 if (cur->next != NULL) return(cur->next);
pcercuei 0:03b5121a232e 8251 } while (cur != NULL);
pcercuei 0:03b5121a232e 8252 return(cur);
pcercuei 0:03b5121a232e 8253 }
pcercuei 0:03b5121a232e 8254
pcercuei 0:03b5121a232e 8255 /*
pcercuei 0:03b5121a232e 8256 * xmlXPathIsAncestor:
pcercuei 0:03b5121a232e 8257 * @ancestor: the ancestor node
pcercuei 0:03b5121a232e 8258 * @node: the current node
pcercuei 0:03b5121a232e 8259 *
pcercuei 0:03b5121a232e 8260 * Check that @ancestor is a @node's ancestor
pcercuei 0:03b5121a232e 8261 *
pcercuei 0:03b5121a232e 8262 * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
pcercuei 0:03b5121a232e 8263 */
pcercuei 0:03b5121a232e 8264 static int
pcercuei 0:03b5121a232e 8265 xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
pcercuei 0:03b5121a232e 8266 if ((ancestor == NULL) || (node == NULL)) return(0);
pcercuei 0:03b5121a232e 8267 if (node->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 8268 return(0);
pcercuei 0:03b5121a232e 8269 if (ancestor->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 8270 return(0);
pcercuei 0:03b5121a232e 8271 /* nodes need to be in the same document */
pcercuei 0:03b5121a232e 8272 if (ancestor->doc != node->doc) return(0);
pcercuei 0:03b5121a232e 8273 /* avoid searching if ancestor or node is the root node */
pcercuei 0:03b5121a232e 8274 if (ancestor == (xmlNodePtr) node->doc) return(1);
pcercuei 0:03b5121a232e 8275 if (node == (xmlNodePtr) ancestor->doc) return(0);
pcercuei 0:03b5121a232e 8276 while (node->parent != NULL) {
pcercuei 0:03b5121a232e 8277 if (node->parent == ancestor)
pcercuei 0:03b5121a232e 8278 return(1);
pcercuei 0:03b5121a232e 8279 node = node->parent;
pcercuei 0:03b5121a232e 8280 }
pcercuei 0:03b5121a232e 8281 return(0);
pcercuei 0:03b5121a232e 8282 }
pcercuei 0:03b5121a232e 8283
pcercuei 0:03b5121a232e 8284 /**
pcercuei 0:03b5121a232e 8285 * xmlXPathNextPreceding:
pcercuei 0:03b5121a232e 8286 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8287 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8288 *
pcercuei 0:03b5121a232e 8289 * Traversal function for the "preceding" direction
pcercuei 0:03b5121a232e 8290 * the preceding axis contains all nodes in the same document as the context
pcercuei 0:03b5121a232e 8291 * node that are before the context node in document order, excluding any
pcercuei 0:03b5121a232e 8292 * ancestors and excluding attribute nodes and namespace nodes; the nodes are
pcercuei 0:03b5121a232e 8293 * ordered in reverse document order
pcercuei 0:03b5121a232e 8294 *
pcercuei 0:03b5121a232e 8295 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8296 */
pcercuei 0:03b5121a232e 8297 xmlNodePtr
pcercuei 0:03b5121a232e 8298 xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
pcercuei 0:03b5121a232e 8299 {
pcercuei 0:03b5121a232e 8300 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8301 if (cur == NULL) {
pcercuei 0:03b5121a232e 8302 cur = ctxt->context->node;
pcercuei 0:03b5121a232e 8303 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 8304 return(NULL);
pcercuei 0:03b5121a232e 8305 if (cur->type == XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 8306 return(cur->parent);
pcercuei 0:03b5121a232e 8307 }
pcercuei 0:03b5121a232e 8308 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 8309 return (NULL);
pcercuei 0:03b5121a232e 8310 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
pcercuei 0:03b5121a232e 8311 cur = cur->prev;
pcercuei 0:03b5121a232e 8312 do {
pcercuei 0:03b5121a232e 8313 if (cur->prev != NULL) {
pcercuei 0:03b5121a232e 8314 for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
pcercuei 0:03b5121a232e 8315 return (cur);
pcercuei 0:03b5121a232e 8316 }
pcercuei 0:03b5121a232e 8317
pcercuei 0:03b5121a232e 8318 cur = cur->parent;
pcercuei 0:03b5121a232e 8319 if (cur == NULL)
pcercuei 0:03b5121a232e 8320 return (NULL);
pcercuei 0:03b5121a232e 8321 if (cur == ctxt->context->doc->children)
pcercuei 0:03b5121a232e 8322 return (NULL);
pcercuei 0:03b5121a232e 8323 } while (xmlXPathIsAncestor(cur, ctxt->context->node));
pcercuei 0:03b5121a232e 8324 return (cur);
pcercuei 0:03b5121a232e 8325 }
pcercuei 0:03b5121a232e 8326
pcercuei 0:03b5121a232e 8327 /**
pcercuei 0:03b5121a232e 8328 * xmlXPathNextPrecedingInternal:
pcercuei 0:03b5121a232e 8329 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8330 * @cur: the current node in the traversal
pcercuei 0:03b5121a232e 8331 *
pcercuei 0:03b5121a232e 8332 * Traversal function for the "preceding" direction
pcercuei 0:03b5121a232e 8333 * the preceding axis contains all nodes in the same document as the context
pcercuei 0:03b5121a232e 8334 * node that are before the context node in document order, excluding any
pcercuei 0:03b5121a232e 8335 * ancestors and excluding attribute nodes and namespace nodes; the nodes are
pcercuei 0:03b5121a232e 8336 * ordered in reverse document order
pcercuei 0:03b5121a232e 8337 * This is a faster implementation but internal only since it requires a
pcercuei 0:03b5121a232e 8338 * state kept in the parser context: ctxt->ancestor.
pcercuei 0:03b5121a232e 8339 *
pcercuei 0:03b5121a232e 8340 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8341 */
pcercuei 0:03b5121a232e 8342 static xmlNodePtr
pcercuei 0:03b5121a232e 8343 xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 8344 xmlNodePtr cur)
pcercuei 0:03b5121a232e 8345 {
pcercuei 0:03b5121a232e 8346 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8347 if (cur == NULL) {
pcercuei 0:03b5121a232e 8348 cur = ctxt->context->node;
pcercuei 0:03b5121a232e 8349 if (cur == NULL)
pcercuei 0:03b5121a232e 8350 return (NULL);
pcercuei 0:03b5121a232e 8351 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 8352 return (NULL);
pcercuei 0:03b5121a232e 8353 ctxt->ancestor = cur->parent;
pcercuei 0:03b5121a232e 8354 }
pcercuei 0:03b5121a232e 8355 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 8356 return(NULL);
pcercuei 0:03b5121a232e 8357 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
pcercuei 0:03b5121a232e 8358 cur = cur->prev;
pcercuei 0:03b5121a232e 8359 while (cur->prev == NULL) {
pcercuei 0:03b5121a232e 8360 cur = cur->parent;
pcercuei 0:03b5121a232e 8361 if (cur == NULL)
pcercuei 0:03b5121a232e 8362 return (NULL);
pcercuei 0:03b5121a232e 8363 if (cur == ctxt->context->doc->children)
pcercuei 0:03b5121a232e 8364 return (NULL);
pcercuei 0:03b5121a232e 8365 if (cur != ctxt->ancestor)
pcercuei 0:03b5121a232e 8366 return (cur);
pcercuei 0:03b5121a232e 8367 ctxt->ancestor = cur->parent;
pcercuei 0:03b5121a232e 8368 }
pcercuei 0:03b5121a232e 8369 cur = cur->prev;
pcercuei 0:03b5121a232e 8370 while (cur->last != NULL)
pcercuei 0:03b5121a232e 8371 cur = cur->last;
pcercuei 0:03b5121a232e 8372 return (cur);
pcercuei 0:03b5121a232e 8373 }
pcercuei 0:03b5121a232e 8374
pcercuei 0:03b5121a232e 8375 /**
pcercuei 0:03b5121a232e 8376 * xmlXPathNextNamespace:
pcercuei 0:03b5121a232e 8377 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8378 * @cur: the current attribute in the traversal
pcercuei 0:03b5121a232e 8379 *
pcercuei 0:03b5121a232e 8380 * Traversal function for the "namespace" direction
pcercuei 0:03b5121a232e 8381 * the namespace axis contains the namespace nodes of the context node;
pcercuei 0:03b5121a232e 8382 * the order of nodes on this axis is implementation-defined; the axis will
pcercuei 0:03b5121a232e 8383 * be empty unless the context node is an element
pcercuei 0:03b5121a232e 8384 *
pcercuei 0:03b5121a232e 8385 * We keep the XML namespace node at the end of the list.
pcercuei 0:03b5121a232e 8386 *
pcercuei 0:03b5121a232e 8387 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8388 */
pcercuei 0:03b5121a232e 8389 xmlNodePtr
pcercuei 0:03b5121a232e 8390 xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8391 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8392 if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
pcercuei 0:03b5121a232e 8393 if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
pcercuei 0:03b5121a232e 8394 if (ctxt->context->tmpNsList != NULL)
pcercuei 0:03b5121a232e 8395 xmlFree(ctxt->context->tmpNsList);
pcercuei 0:03b5121a232e 8396 ctxt->context->tmpNsList =
pcercuei 0:03b5121a232e 8397 xmlGetNsList(ctxt->context->doc, ctxt->context->node);
pcercuei 0:03b5121a232e 8398 ctxt->context->tmpNsNr = 0;
pcercuei 0:03b5121a232e 8399 if (ctxt->context->tmpNsList != NULL) {
pcercuei 0:03b5121a232e 8400 while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
pcercuei 0:03b5121a232e 8401 ctxt->context->tmpNsNr++;
pcercuei 0:03b5121a232e 8402 }
pcercuei 0:03b5121a232e 8403 }
pcercuei 0:03b5121a232e 8404 return((xmlNodePtr) xmlXPathXMLNamespace);
pcercuei 0:03b5121a232e 8405 }
pcercuei 0:03b5121a232e 8406 if (ctxt->context->tmpNsNr > 0) {
pcercuei 0:03b5121a232e 8407 return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
pcercuei 0:03b5121a232e 8408 } else {
pcercuei 0:03b5121a232e 8409 if (ctxt->context->tmpNsList != NULL)
pcercuei 0:03b5121a232e 8410 xmlFree(ctxt->context->tmpNsList);
pcercuei 0:03b5121a232e 8411 ctxt->context->tmpNsList = NULL;
pcercuei 0:03b5121a232e 8412 return(NULL);
pcercuei 0:03b5121a232e 8413 }
pcercuei 0:03b5121a232e 8414 }
pcercuei 0:03b5121a232e 8415
pcercuei 0:03b5121a232e 8416 /**
pcercuei 0:03b5121a232e 8417 * xmlXPathNextAttribute:
pcercuei 0:03b5121a232e 8418 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8419 * @cur: the current attribute in the traversal
pcercuei 0:03b5121a232e 8420 *
pcercuei 0:03b5121a232e 8421 * Traversal function for the "attribute" direction
pcercuei 0:03b5121a232e 8422 * TODO: support DTD inherited default attributes
pcercuei 0:03b5121a232e 8423 *
pcercuei 0:03b5121a232e 8424 * Returns the next element following that axis
pcercuei 0:03b5121a232e 8425 */
pcercuei 0:03b5121a232e 8426 xmlNodePtr
pcercuei 0:03b5121a232e 8427 xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
pcercuei 0:03b5121a232e 8428 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
pcercuei 0:03b5121a232e 8429 if (ctxt->context->node == NULL)
pcercuei 0:03b5121a232e 8430 return(NULL);
pcercuei 0:03b5121a232e 8431 if (ctxt->context->node->type != XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 8432 return(NULL);
pcercuei 0:03b5121a232e 8433 if (cur == NULL) {
pcercuei 0:03b5121a232e 8434 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
pcercuei 0:03b5121a232e 8435 return(NULL);
pcercuei 0:03b5121a232e 8436 return((xmlNodePtr)ctxt->context->node->properties);
pcercuei 0:03b5121a232e 8437 }
pcercuei 0:03b5121a232e 8438 return((xmlNodePtr)cur->next);
pcercuei 0:03b5121a232e 8439 }
pcercuei 0:03b5121a232e 8440
pcercuei 0:03b5121a232e 8441 /************************************************************************
pcercuei 0:03b5121a232e 8442 * *
pcercuei 0:03b5121a232e 8443 * NodeTest Functions *
pcercuei 0:03b5121a232e 8444 * *
pcercuei 0:03b5121a232e 8445 ************************************************************************/
pcercuei 0:03b5121a232e 8446
pcercuei 0:03b5121a232e 8447 #define IS_FUNCTION 200
pcercuei 0:03b5121a232e 8448
pcercuei 0:03b5121a232e 8449
pcercuei 0:03b5121a232e 8450 /************************************************************************
pcercuei 0:03b5121a232e 8451 * *
pcercuei 0:03b5121a232e 8452 * Implicit tree core function library *
pcercuei 0:03b5121a232e 8453 * *
pcercuei 0:03b5121a232e 8454 ************************************************************************/
pcercuei 0:03b5121a232e 8455
pcercuei 0:03b5121a232e 8456 /**
pcercuei 0:03b5121a232e 8457 * xmlXPathRoot:
pcercuei 0:03b5121a232e 8458 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8459 *
pcercuei 0:03b5121a232e 8460 * Initialize the context to the root of the document
pcercuei 0:03b5121a232e 8461 */
pcercuei 0:03b5121a232e 8462 void
pcercuei 0:03b5121a232e 8463 xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 8464 if ((ctxt == NULL) || (ctxt->context == NULL))
pcercuei 0:03b5121a232e 8465 return;
pcercuei 0:03b5121a232e 8466 ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
pcercuei 0:03b5121a232e 8467 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 8468 ctxt->context->node));
pcercuei 0:03b5121a232e 8469 }
pcercuei 0:03b5121a232e 8470
pcercuei 0:03b5121a232e 8471 /************************************************************************
pcercuei 0:03b5121a232e 8472 * *
pcercuei 0:03b5121a232e 8473 * The explicit core function library *
pcercuei 0:03b5121a232e 8474 *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib *
pcercuei 0:03b5121a232e 8475 * *
pcercuei 0:03b5121a232e 8476 ************************************************************************/
pcercuei 0:03b5121a232e 8477
pcercuei 0:03b5121a232e 8478
pcercuei 0:03b5121a232e 8479 /**
pcercuei 0:03b5121a232e 8480 * xmlXPathLastFunction:
pcercuei 0:03b5121a232e 8481 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8482 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8483 *
pcercuei 0:03b5121a232e 8484 * Implement the last() XPath function
pcercuei 0:03b5121a232e 8485 * number last()
pcercuei 0:03b5121a232e 8486 * The last function returns the number of nodes in the context node list.
pcercuei 0:03b5121a232e 8487 */
pcercuei 0:03b5121a232e 8488 void
pcercuei 0:03b5121a232e 8489 xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8490 CHECK_ARITY(0);
pcercuei 0:03b5121a232e 8491 if (ctxt->context->contextSize >= 0) {
pcercuei 0:03b5121a232e 8492 valuePush(ctxt,
pcercuei 0:03b5121a232e 8493 xmlXPathCacheNewFloat(ctxt->context,
pcercuei 0:03b5121a232e 8494 (double) ctxt->context->contextSize));
pcercuei 0:03b5121a232e 8495 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 8496 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 8497 "last() : %d\n", ctxt->context->contextSize);
pcercuei 0:03b5121a232e 8498 #endif
pcercuei 0:03b5121a232e 8499 } else {
pcercuei 0:03b5121a232e 8500 XP_ERROR(XPATH_INVALID_CTXT_SIZE);
pcercuei 0:03b5121a232e 8501 }
pcercuei 0:03b5121a232e 8502 }
pcercuei 0:03b5121a232e 8503
pcercuei 0:03b5121a232e 8504 /**
pcercuei 0:03b5121a232e 8505 * xmlXPathPositionFunction:
pcercuei 0:03b5121a232e 8506 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8507 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8508 *
pcercuei 0:03b5121a232e 8509 * Implement the position() XPath function
pcercuei 0:03b5121a232e 8510 * number position()
pcercuei 0:03b5121a232e 8511 * The position function returns the position of the context node in the
pcercuei 0:03b5121a232e 8512 * context node list. The first position is 1, and so the last position
pcercuei 0:03b5121a232e 8513 * will be equal to last().
pcercuei 0:03b5121a232e 8514 */
pcercuei 0:03b5121a232e 8515 void
pcercuei 0:03b5121a232e 8516 xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8517 CHECK_ARITY(0);
pcercuei 0:03b5121a232e 8518 if (ctxt->context->proximityPosition >= 0) {
pcercuei 0:03b5121a232e 8519 valuePush(ctxt,
pcercuei 0:03b5121a232e 8520 xmlXPathCacheNewFloat(ctxt->context,
pcercuei 0:03b5121a232e 8521 (double) ctxt->context->proximityPosition));
pcercuei 0:03b5121a232e 8522 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 8523 xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
pcercuei 0:03b5121a232e 8524 ctxt->context->proximityPosition);
pcercuei 0:03b5121a232e 8525 #endif
pcercuei 0:03b5121a232e 8526 } else {
pcercuei 0:03b5121a232e 8527 XP_ERROR(XPATH_INVALID_CTXT_POSITION);
pcercuei 0:03b5121a232e 8528 }
pcercuei 0:03b5121a232e 8529 }
pcercuei 0:03b5121a232e 8530
pcercuei 0:03b5121a232e 8531 /**
pcercuei 0:03b5121a232e 8532 * xmlXPathCountFunction:
pcercuei 0:03b5121a232e 8533 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8534 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8535 *
pcercuei 0:03b5121a232e 8536 * Implement the count() XPath function
pcercuei 0:03b5121a232e 8537 * number count(node-set)
pcercuei 0:03b5121a232e 8538 */
pcercuei 0:03b5121a232e 8539 void
pcercuei 0:03b5121a232e 8540 xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8541 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 8542
pcercuei 0:03b5121a232e 8543 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8544 if ((ctxt->value == NULL) ||
pcercuei 0:03b5121a232e 8545 ((ctxt->value->type != XPATH_NODESET) &&
pcercuei 0:03b5121a232e 8546 (ctxt->value->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 8547 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 8548 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 8549
pcercuei 0:03b5121a232e 8550 if ((cur == NULL) || (cur->nodesetval == NULL))
pcercuei 0:03b5121a232e 8551 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0));
pcercuei 0:03b5121a232e 8552 else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 8553 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context,
pcercuei 0:03b5121a232e 8554 (double) cur->nodesetval->nodeNr));
pcercuei 0:03b5121a232e 8555 } else {
pcercuei 0:03b5121a232e 8556 if ((cur->nodesetval->nodeNr != 1) ||
pcercuei 0:03b5121a232e 8557 (cur->nodesetval->nodeTab == NULL)) {
pcercuei 0:03b5121a232e 8558 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0));
pcercuei 0:03b5121a232e 8559 } else {
pcercuei 0:03b5121a232e 8560 xmlNodePtr tmp;
pcercuei 0:03b5121a232e 8561 int i = 0;
pcercuei 0:03b5121a232e 8562
pcercuei 0:03b5121a232e 8563 tmp = cur->nodesetval->nodeTab[0];
pcercuei 0:03b5121a232e 8564 if ((tmp != NULL) && (tmp->type != XML_NAMESPACE_DECL)) {
pcercuei 0:03b5121a232e 8565 tmp = tmp->children;
pcercuei 0:03b5121a232e 8566 while (tmp != NULL) {
pcercuei 0:03b5121a232e 8567 tmp = tmp->next;
pcercuei 0:03b5121a232e 8568 i++;
pcercuei 0:03b5121a232e 8569 }
pcercuei 0:03b5121a232e 8570 }
pcercuei 0:03b5121a232e 8571 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) i));
pcercuei 0:03b5121a232e 8572 }
pcercuei 0:03b5121a232e 8573 }
pcercuei 0:03b5121a232e 8574 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 8575 }
pcercuei 0:03b5121a232e 8576
pcercuei 0:03b5121a232e 8577 /**
pcercuei 0:03b5121a232e 8578 * xmlXPathGetElementsByIds:
pcercuei 0:03b5121a232e 8579 * @doc: the document
pcercuei 0:03b5121a232e 8580 * @ids: a whitespace separated list of IDs
pcercuei 0:03b5121a232e 8581 *
pcercuei 0:03b5121a232e 8582 * Selects elements by their unique ID.
pcercuei 0:03b5121a232e 8583 *
pcercuei 0:03b5121a232e 8584 * Returns a node-set of selected elements.
pcercuei 0:03b5121a232e 8585 */
pcercuei 0:03b5121a232e 8586 static xmlNodeSetPtr
pcercuei 0:03b5121a232e 8587 xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
pcercuei 0:03b5121a232e 8588 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 8589 const xmlChar *cur = ids;
pcercuei 0:03b5121a232e 8590 xmlChar *ID;
pcercuei 0:03b5121a232e 8591 xmlAttrPtr attr;
pcercuei 0:03b5121a232e 8592 xmlNodePtr elem = NULL;
pcercuei 0:03b5121a232e 8593
pcercuei 0:03b5121a232e 8594 if (ids == NULL) return(NULL);
pcercuei 0:03b5121a232e 8595
pcercuei 0:03b5121a232e 8596 ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 8597 if (ret == NULL)
pcercuei 0:03b5121a232e 8598 return(ret);
pcercuei 0:03b5121a232e 8599
pcercuei 0:03b5121a232e 8600 while (IS_BLANK_CH(*cur)) cur++;
pcercuei 0:03b5121a232e 8601 while (*cur != 0) {
pcercuei 0:03b5121a232e 8602 while ((!IS_BLANK_CH(*cur)) && (*cur != 0))
pcercuei 0:03b5121a232e 8603 cur++;
pcercuei 0:03b5121a232e 8604
pcercuei 0:03b5121a232e 8605 ID = xmlStrndup(ids, cur - ids);
pcercuei 0:03b5121a232e 8606 if (ID != NULL) {
pcercuei 0:03b5121a232e 8607 /*
pcercuei 0:03b5121a232e 8608 * We used to check the fact that the value passed
pcercuei 0:03b5121a232e 8609 * was an NCName, but this generated much troubles for
pcercuei 0:03b5121a232e 8610 * me and Aleksey Sanin, people blatantly violated that
pcercuei 0:03b5121a232e 8611 * constaint, like Visa3D spec.
pcercuei 0:03b5121a232e 8612 * if (xmlValidateNCName(ID, 1) == 0)
pcercuei 0:03b5121a232e 8613 */
pcercuei 0:03b5121a232e 8614 attr = xmlGetID(doc, ID);
pcercuei 0:03b5121a232e 8615 if (attr != NULL) {
pcercuei 0:03b5121a232e 8616 if (attr->type == XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 8617 elem = attr->parent;
pcercuei 0:03b5121a232e 8618 else if (attr->type == XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 8619 elem = (xmlNodePtr) attr;
pcercuei 0:03b5121a232e 8620 else
pcercuei 0:03b5121a232e 8621 elem = NULL;
pcercuei 0:03b5121a232e 8622 if (elem != NULL)
pcercuei 0:03b5121a232e 8623 xmlXPathNodeSetAdd(ret, elem);
pcercuei 0:03b5121a232e 8624 }
pcercuei 0:03b5121a232e 8625 xmlFree(ID);
pcercuei 0:03b5121a232e 8626 }
pcercuei 0:03b5121a232e 8627
pcercuei 0:03b5121a232e 8628 while (IS_BLANK_CH(*cur)) cur++;
pcercuei 0:03b5121a232e 8629 ids = cur;
pcercuei 0:03b5121a232e 8630 }
pcercuei 0:03b5121a232e 8631 return(ret);
pcercuei 0:03b5121a232e 8632 }
pcercuei 0:03b5121a232e 8633
pcercuei 0:03b5121a232e 8634 /**
pcercuei 0:03b5121a232e 8635 * xmlXPathIdFunction:
pcercuei 0:03b5121a232e 8636 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8637 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8638 *
pcercuei 0:03b5121a232e 8639 * Implement the id() XPath function
pcercuei 0:03b5121a232e 8640 * node-set id(object)
pcercuei 0:03b5121a232e 8641 * The id function selects elements by their unique ID
pcercuei 0:03b5121a232e 8642 * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
pcercuei 0:03b5121a232e 8643 * then the result is the union of the result of applying id to the
pcercuei 0:03b5121a232e 8644 * string value of each of the nodes in the argument node-set. When the
pcercuei 0:03b5121a232e 8645 * argument to id is of any other type, the argument is converted to a
pcercuei 0:03b5121a232e 8646 * string as if by a call to the string function; the string is split
pcercuei 0:03b5121a232e 8647 * into a whitespace-separated list of tokens (whitespace is any sequence
pcercuei 0:03b5121a232e 8648 * of characters matching the production S); the result is a node-set
pcercuei 0:03b5121a232e 8649 * containing the elements in the same document as the context node that
pcercuei 0:03b5121a232e 8650 * have a unique ID equal to any of the tokens in the list.
pcercuei 0:03b5121a232e 8651 */
pcercuei 0:03b5121a232e 8652 void
pcercuei 0:03b5121a232e 8653 xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8654 xmlChar *tokens;
pcercuei 0:03b5121a232e 8655 xmlNodeSetPtr ret;
pcercuei 0:03b5121a232e 8656 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 8657
pcercuei 0:03b5121a232e 8658 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8659 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 8660 if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 8661 if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
pcercuei 0:03b5121a232e 8662 xmlNodeSetPtr ns;
pcercuei 0:03b5121a232e 8663 int i;
pcercuei 0:03b5121a232e 8664
pcercuei 0:03b5121a232e 8665 ret = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 8666 /*
pcercuei 0:03b5121a232e 8667 * FIXME -- in an out-of-memory condition this will behave badly.
pcercuei 0:03b5121a232e 8668 * The solution is not clear -- we already popped an item from
pcercuei 0:03b5121a232e 8669 * ctxt, so the object is in a corrupt state.
pcercuei 0:03b5121a232e 8670 */
pcercuei 0:03b5121a232e 8671
pcercuei 0:03b5121a232e 8672 if (obj->nodesetval != NULL) {
pcercuei 0:03b5121a232e 8673 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
pcercuei 0:03b5121a232e 8674 tokens =
pcercuei 0:03b5121a232e 8675 xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
pcercuei 0:03b5121a232e 8676 ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
pcercuei 0:03b5121a232e 8677 ret = xmlXPathNodeSetMerge(ret, ns);
pcercuei 0:03b5121a232e 8678 xmlXPathFreeNodeSet(ns);
pcercuei 0:03b5121a232e 8679 if (tokens != NULL)
pcercuei 0:03b5121a232e 8680 xmlFree(tokens);
pcercuei 0:03b5121a232e 8681 }
pcercuei 0:03b5121a232e 8682 }
pcercuei 0:03b5121a232e 8683 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 8684 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret));
pcercuei 0:03b5121a232e 8685 return;
pcercuei 0:03b5121a232e 8686 }
pcercuei 0:03b5121a232e 8687 obj = xmlXPathCacheConvertString(ctxt->context, obj);
pcercuei 0:03b5121a232e 8688 ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval);
pcercuei 0:03b5121a232e 8689 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret));
pcercuei 0:03b5121a232e 8690 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 8691 return;
pcercuei 0:03b5121a232e 8692 }
pcercuei 0:03b5121a232e 8693
pcercuei 0:03b5121a232e 8694 /**
pcercuei 0:03b5121a232e 8695 * xmlXPathLocalNameFunction:
pcercuei 0:03b5121a232e 8696 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8697 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8698 *
pcercuei 0:03b5121a232e 8699 * Implement the local-name() XPath function
pcercuei 0:03b5121a232e 8700 * string local-name(node-set?)
pcercuei 0:03b5121a232e 8701 * The local-name function returns a string containing the local part
pcercuei 0:03b5121a232e 8702 * of the name of the node in the argument node-set that is first in
pcercuei 0:03b5121a232e 8703 * document order. If the node-set is empty or the first node has no
pcercuei 0:03b5121a232e 8704 * name, an empty string is returned. If the argument is omitted it
pcercuei 0:03b5121a232e 8705 * defaults to the context node.
pcercuei 0:03b5121a232e 8706 */
pcercuei 0:03b5121a232e 8707 void
pcercuei 0:03b5121a232e 8708 xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8709 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 8710
pcercuei 0:03b5121a232e 8711 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 8712
pcercuei 0:03b5121a232e 8713 if (nargs == 0) {
pcercuei 0:03b5121a232e 8714 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 8715 ctxt->context->node));
pcercuei 0:03b5121a232e 8716 nargs = 1;
pcercuei 0:03b5121a232e 8717 }
pcercuei 0:03b5121a232e 8718
pcercuei 0:03b5121a232e 8719 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8720 if ((ctxt->value == NULL) ||
pcercuei 0:03b5121a232e 8721 ((ctxt->value->type != XPATH_NODESET) &&
pcercuei 0:03b5121a232e 8722 (ctxt->value->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 8723 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 8724 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 8725
pcercuei 0:03b5121a232e 8726 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
pcercuei 0:03b5121a232e 8727 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8728 } else {
pcercuei 0:03b5121a232e 8729 int i = 0; /* Should be first in document order !!!!! */
pcercuei 0:03b5121a232e 8730 switch (cur->nodesetval->nodeTab[i]->type) {
pcercuei 0:03b5121a232e 8731 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 8732 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 8733 case XML_PI_NODE:
pcercuei 0:03b5121a232e 8734 if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
pcercuei 0:03b5121a232e 8735 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8736 else
pcercuei 0:03b5121a232e 8737 valuePush(ctxt,
pcercuei 0:03b5121a232e 8738 xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 8739 cur->nodesetval->nodeTab[i]->name));
pcercuei 0:03b5121a232e 8740 break;
pcercuei 0:03b5121a232e 8741 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 8742 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 8743 ((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
pcercuei 0:03b5121a232e 8744 break;
pcercuei 0:03b5121a232e 8745 default:
pcercuei 0:03b5121a232e 8746 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8747 }
pcercuei 0:03b5121a232e 8748 }
pcercuei 0:03b5121a232e 8749 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 8750 }
pcercuei 0:03b5121a232e 8751
pcercuei 0:03b5121a232e 8752 /**
pcercuei 0:03b5121a232e 8753 * xmlXPathNamespaceURIFunction:
pcercuei 0:03b5121a232e 8754 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8755 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8756 *
pcercuei 0:03b5121a232e 8757 * Implement the namespace-uri() XPath function
pcercuei 0:03b5121a232e 8758 * string namespace-uri(node-set?)
pcercuei 0:03b5121a232e 8759 * The namespace-uri function returns a string containing the
pcercuei 0:03b5121a232e 8760 * namespace URI of the expanded name of the node in the argument
pcercuei 0:03b5121a232e 8761 * node-set that is first in document order. If the node-set is empty,
pcercuei 0:03b5121a232e 8762 * the first node has no name, or the expanded name has no namespace
pcercuei 0:03b5121a232e 8763 * URI, an empty string is returned. If the argument is omitted it
pcercuei 0:03b5121a232e 8764 * defaults to the context node.
pcercuei 0:03b5121a232e 8765 */
pcercuei 0:03b5121a232e 8766 void
pcercuei 0:03b5121a232e 8767 xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8768 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 8769
pcercuei 0:03b5121a232e 8770 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 8771
pcercuei 0:03b5121a232e 8772 if (nargs == 0) {
pcercuei 0:03b5121a232e 8773 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 8774 ctxt->context->node));
pcercuei 0:03b5121a232e 8775 nargs = 1;
pcercuei 0:03b5121a232e 8776 }
pcercuei 0:03b5121a232e 8777 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8778 if ((ctxt->value == NULL) ||
pcercuei 0:03b5121a232e 8779 ((ctxt->value->type != XPATH_NODESET) &&
pcercuei 0:03b5121a232e 8780 (ctxt->value->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 8781 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 8782 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 8783
pcercuei 0:03b5121a232e 8784 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
pcercuei 0:03b5121a232e 8785 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8786 } else {
pcercuei 0:03b5121a232e 8787 int i = 0; /* Should be first in document order !!!!! */
pcercuei 0:03b5121a232e 8788 switch (cur->nodesetval->nodeTab[i]->type) {
pcercuei 0:03b5121a232e 8789 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 8790 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 8791 if (cur->nodesetval->nodeTab[i]->ns == NULL)
pcercuei 0:03b5121a232e 8792 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8793 else
pcercuei 0:03b5121a232e 8794 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 8795 cur->nodesetval->nodeTab[i]->ns->href));
pcercuei 0:03b5121a232e 8796 break;
pcercuei 0:03b5121a232e 8797 default:
pcercuei 0:03b5121a232e 8798 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8799 }
pcercuei 0:03b5121a232e 8800 }
pcercuei 0:03b5121a232e 8801 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 8802 }
pcercuei 0:03b5121a232e 8803
pcercuei 0:03b5121a232e 8804 /**
pcercuei 0:03b5121a232e 8805 * xmlXPathNameFunction:
pcercuei 0:03b5121a232e 8806 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8807 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8808 *
pcercuei 0:03b5121a232e 8809 * Implement the name() XPath function
pcercuei 0:03b5121a232e 8810 * string name(node-set?)
pcercuei 0:03b5121a232e 8811 * The name function returns a string containing a QName representing
pcercuei 0:03b5121a232e 8812 * the name of the node in the argument node-set that is first in document
pcercuei 0:03b5121a232e 8813 * order. The QName must represent the name with respect to the namespace
pcercuei 0:03b5121a232e 8814 * declarations in effect on the node whose name is being represented.
pcercuei 0:03b5121a232e 8815 * Typically, this will be the form in which the name occurred in the XML
pcercuei 0:03b5121a232e 8816 * source. This need not be the case if there are namespace declarations
pcercuei 0:03b5121a232e 8817 * in effect on the node that associate multiple prefixes with the same
pcercuei 0:03b5121a232e 8818 * namespace. However, an implementation may include information about
pcercuei 0:03b5121a232e 8819 * the original prefix in its representation of nodes; in this case, an
pcercuei 0:03b5121a232e 8820 * implementation can ensure that the returned string is always the same
pcercuei 0:03b5121a232e 8821 * as the QName used in the XML source. If the argument it omitted it
pcercuei 0:03b5121a232e 8822 * defaults to the context node.
pcercuei 0:03b5121a232e 8823 * Libxml keep the original prefix so the "real qualified name" used is
pcercuei 0:03b5121a232e 8824 * returned.
pcercuei 0:03b5121a232e 8825 */
pcercuei 0:03b5121a232e 8826 static void
pcercuei 0:03b5121a232e 8827 xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
pcercuei 0:03b5121a232e 8828 {
pcercuei 0:03b5121a232e 8829 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 8830
pcercuei 0:03b5121a232e 8831 if (nargs == 0) {
pcercuei 0:03b5121a232e 8832 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 8833 ctxt->context->node));
pcercuei 0:03b5121a232e 8834 nargs = 1;
pcercuei 0:03b5121a232e 8835 }
pcercuei 0:03b5121a232e 8836
pcercuei 0:03b5121a232e 8837 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8838 if ((ctxt->value == NULL) ||
pcercuei 0:03b5121a232e 8839 ((ctxt->value->type != XPATH_NODESET) &&
pcercuei 0:03b5121a232e 8840 (ctxt->value->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 8841 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 8842 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 8843
pcercuei 0:03b5121a232e 8844 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
pcercuei 0:03b5121a232e 8845 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8846 } else {
pcercuei 0:03b5121a232e 8847 int i = 0; /* Should be first in document order !!!!! */
pcercuei 0:03b5121a232e 8848
pcercuei 0:03b5121a232e 8849 switch (cur->nodesetval->nodeTab[i]->type) {
pcercuei 0:03b5121a232e 8850 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 8851 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 8852 if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
pcercuei 0:03b5121a232e 8853 valuePush(ctxt,
pcercuei 0:03b5121a232e 8854 xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 8855 else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
pcercuei 0:03b5121a232e 8856 (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
pcercuei 0:03b5121a232e 8857 valuePush(ctxt,
pcercuei 0:03b5121a232e 8858 xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 8859 cur->nodesetval->nodeTab[i]->name));
pcercuei 0:03b5121a232e 8860 } else {
pcercuei 0:03b5121a232e 8861 xmlChar *fullname;
pcercuei 0:03b5121a232e 8862
pcercuei 0:03b5121a232e 8863 fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
pcercuei 0:03b5121a232e 8864 cur->nodesetval->nodeTab[i]->ns->prefix,
pcercuei 0:03b5121a232e 8865 NULL, 0);
pcercuei 0:03b5121a232e 8866 if (fullname == cur->nodesetval->nodeTab[i]->name)
pcercuei 0:03b5121a232e 8867 fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
pcercuei 0:03b5121a232e 8868 if (fullname == NULL) {
pcercuei 0:03b5121a232e 8869 XP_ERROR(XPATH_MEMORY_ERROR);
pcercuei 0:03b5121a232e 8870 }
pcercuei 0:03b5121a232e 8871 valuePush(ctxt, xmlXPathCacheWrapString(
pcercuei 0:03b5121a232e 8872 ctxt->context, fullname));
pcercuei 0:03b5121a232e 8873 }
pcercuei 0:03b5121a232e 8874 break;
pcercuei 0:03b5121a232e 8875 default:
pcercuei 0:03b5121a232e 8876 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 8877 cur->nodesetval->nodeTab[i]));
pcercuei 0:03b5121a232e 8878 xmlXPathLocalNameFunction(ctxt, 1);
pcercuei 0:03b5121a232e 8879 }
pcercuei 0:03b5121a232e 8880 }
pcercuei 0:03b5121a232e 8881 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 8882 }
pcercuei 0:03b5121a232e 8883
pcercuei 0:03b5121a232e 8884
pcercuei 0:03b5121a232e 8885 /**
pcercuei 0:03b5121a232e 8886 * xmlXPathStringFunction:
pcercuei 0:03b5121a232e 8887 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8888 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8889 *
pcercuei 0:03b5121a232e 8890 * Implement the string() XPath function
pcercuei 0:03b5121a232e 8891 * string string(object?)
pcercuei 0:03b5121a232e 8892 * The string function converts an object to a string as follows:
pcercuei 0:03b5121a232e 8893 * - A node-set is converted to a string by returning the value of
pcercuei 0:03b5121a232e 8894 * the node in the node-set that is first in document order.
pcercuei 0:03b5121a232e 8895 * If the node-set is empty, an empty string is returned.
pcercuei 0:03b5121a232e 8896 * - A number is converted to a string as follows
pcercuei 0:03b5121a232e 8897 * + NaN is converted to the string NaN
pcercuei 0:03b5121a232e 8898 * + positive zero is converted to the string 0
pcercuei 0:03b5121a232e 8899 * + negative zero is converted to the string 0
pcercuei 0:03b5121a232e 8900 * + positive infinity is converted to the string Infinity
pcercuei 0:03b5121a232e 8901 * + negative infinity is converted to the string -Infinity
pcercuei 0:03b5121a232e 8902 * + if the number is an integer, the number is represented in
pcercuei 0:03b5121a232e 8903 * decimal form as a Number with no decimal point and no leading
pcercuei 0:03b5121a232e 8904 * zeros, preceded by a minus sign (-) if the number is negative
pcercuei 0:03b5121a232e 8905 * + otherwise, the number is represented in decimal form as a
pcercuei 0:03b5121a232e 8906 * Number including a decimal point with at least one digit
pcercuei 0:03b5121a232e 8907 * before the decimal point and at least one digit after the
pcercuei 0:03b5121a232e 8908 * decimal point, preceded by a minus sign (-) if the number
pcercuei 0:03b5121a232e 8909 * is negative; there must be no leading zeros before the decimal
pcercuei 0:03b5121a232e 8910 * point apart possibly from the one required digit immediately
pcercuei 0:03b5121a232e 8911 * before the decimal point; beyond the one required digit
pcercuei 0:03b5121a232e 8912 * after the decimal point there must be as many, but only as
pcercuei 0:03b5121a232e 8913 * many, more digits as are needed to uniquely distinguish the
pcercuei 0:03b5121a232e 8914 * number from all other IEEE 754 numeric values.
pcercuei 0:03b5121a232e 8915 * - The boolean false value is converted to the string false.
pcercuei 0:03b5121a232e 8916 * The boolean true value is converted to the string true.
pcercuei 0:03b5121a232e 8917 *
pcercuei 0:03b5121a232e 8918 * If the argument is omitted, it defaults to a node-set with the
pcercuei 0:03b5121a232e 8919 * context node as its only member.
pcercuei 0:03b5121a232e 8920 */
pcercuei 0:03b5121a232e 8921 void
pcercuei 0:03b5121a232e 8922 xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8923 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 8924
pcercuei 0:03b5121a232e 8925 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 8926 if (nargs == 0) {
pcercuei 0:03b5121a232e 8927 valuePush(ctxt,
pcercuei 0:03b5121a232e 8928 xmlXPathCacheWrapString(ctxt->context,
pcercuei 0:03b5121a232e 8929 xmlXPathCastNodeToString(ctxt->context->node)));
pcercuei 0:03b5121a232e 8930 return;
pcercuei 0:03b5121a232e 8931 }
pcercuei 0:03b5121a232e 8932
pcercuei 0:03b5121a232e 8933 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8934 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 8935 if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 8936 valuePush(ctxt, xmlXPathCacheConvertString(ctxt->context, cur));
pcercuei 0:03b5121a232e 8937 }
pcercuei 0:03b5121a232e 8938
pcercuei 0:03b5121a232e 8939 /**
pcercuei 0:03b5121a232e 8940 * xmlXPathStringLengthFunction:
pcercuei 0:03b5121a232e 8941 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8942 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8943 *
pcercuei 0:03b5121a232e 8944 * Implement the string-length() XPath function
pcercuei 0:03b5121a232e 8945 * number string-length(string?)
pcercuei 0:03b5121a232e 8946 * The string-length returns the number of characters in the string
pcercuei 0:03b5121a232e 8947 * (see [3.6 Strings]). If the argument is omitted, it defaults to
pcercuei 0:03b5121a232e 8948 * the context node converted to a string, in other words the value
pcercuei 0:03b5121a232e 8949 * of the context node.
pcercuei 0:03b5121a232e 8950 */
pcercuei 0:03b5121a232e 8951 void
pcercuei 0:03b5121a232e 8952 xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8953 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 8954
pcercuei 0:03b5121a232e 8955 if (nargs == 0) {
pcercuei 0:03b5121a232e 8956 if ((ctxt == NULL) || (ctxt->context == NULL))
pcercuei 0:03b5121a232e 8957 return;
pcercuei 0:03b5121a232e 8958 if (ctxt->context->node == NULL) {
pcercuei 0:03b5121a232e 8959 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0));
pcercuei 0:03b5121a232e 8960 } else {
pcercuei 0:03b5121a232e 8961 xmlChar *content;
pcercuei 0:03b5121a232e 8962
pcercuei 0:03b5121a232e 8963 content = xmlXPathCastNodeToString(ctxt->context->node);
pcercuei 0:03b5121a232e 8964 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context,
pcercuei 0:03b5121a232e 8965 xmlUTF8Strlen(content)));
pcercuei 0:03b5121a232e 8966 xmlFree(content);
pcercuei 0:03b5121a232e 8967 }
pcercuei 0:03b5121a232e 8968 return;
pcercuei 0:03b5121a232e 8969 }
pcercuei 0:03b5121a232e 8970 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 8971 CAST_TO_STRING;
pcercuei 0:03b5121a232e 8972 CHECK_TYPE(XPATH_STRING);
pcercuei 0:03b5121a232e 8973 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 8974 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context,
pcercuei 0:03b5121a232e 8975 xmlUTF8Strlen(cur->stringval)));
pcercuei 0:03b5121a232e 8976 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 8977 }
pcercuei 0:03b5121a232e 8978
pcercuei 0:03b5121a232e 8979 /**
pcercuei 0:03b5121a232e 8980 * xmlXPathConcatFunction:
pcercuei 0:03b5121a232e 8981 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 8982 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 8983 *
pcercuei 0:03b5121a232e 8984 * Implement the concat() XPath function
pcercuei 0:03b5121a232e 8985 * string concat(string, string, string*)
pcercuei 0:03b5121a232e 8986 * The concat function returns the concatenation of its arguments.
pcercuei 0:03b5121a232e 8987 */
pcercuei 0:03b5121a232e 8988 void
pcercuei 0:03b5121a232e 8989 xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 8990 xmlXPathObjectPtr cur, newobj;
pcercuei 0:03b5121a232e 8991 xmlChar *tmp;
pcercuei 0:03b5121a232e 8992
pcercuei 0:03b5121a232e 8993 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 8994 if (nargs < 2) {
pcercuei 0:03b5121a232e 8995 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 8996 }
pcercuei 0:03b5121a232e 8997
pcercuei 0:03b5121a232e 8998 CAST_TO_STRING;
pcercuei 0:03b5121a232e 8999 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 9000 if ((cur == NULL) || (cur->type != XPATH_STRING)) {
pcercuei 0:03b5121a232e 9001 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 9002 return;
pcercuei 0:03b5121a232e 9003 }
pcercuei 0:03b5121a232e 9004 nargs--;
pcercuei 0:03b5121a232e 9005
pcercuei 0:03b5121a232e 9006 while (nargs > 0) {
pcercuei 0:03b5121a232e 9007 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9008 newobj = valuePop(ctxt);
pcercuei 0:03b5121a232e 9009 if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
pcercuei 0:03b5121a232e 9010 xmlXPathReleaseObject(ctxt->context, newobj);
pcercuei 0:03b5121a232e 9011 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 9012 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 9013 }
pcercuei 0:03b5121a232e 9014 tmp = xmlStrcat(newobj->stringval, cur->stringval);
pcercuei 0:03b5121a232e 9015 newobj->stringval = cur->stringval;
pcercuei 0:03b5121a232e 9016 cur->stringval = tmp;
pcercuei 0:03b5121a232e 9017 xmlXPathReleaseObject(ctxt->context, newobj);
pcercuei 0:03b5121a232e 9018 nargs--;
pcercuei 0:03b5121a232e 9019 }
pcercuei 0:03b5121a232e 9020 valuePush(ctxt, cur);
pcercuei 0:03b5121a232e 9021 }
pcercuei 0:03b5121a232e 9022
pcercuei 0:03b5121a232e 9023 /**
pcercuei 0:03b5121a232e 9024 * xmlXPathContainsFunction:
pcercuei 0:03b5121a232e 9025 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9026 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9027 *
pcercuei 0:03b5121a232e 9028 * Implement the contains() XPath function
pcercuei 0:03b5121a232e 9029 * boolean contains(string, string)
pcercuei 0:03b5121a232e 9030 * The contains function returns true if the first argument string
pcercuei 0:03b5121a232e 9031 * contains the second argument string, and otherwise returns false.
pcercuei 0:03b5121a232e 9032 */
pcercuei 0:03b5121a232e 9033 void
pcercuei 0:03b5121a232e 9034 xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9035 xmlXPathObjectPtr hay, needle;
pcercuei 0:03b5121a232e 9036
pcercuei 0:03b5121a232e 9037 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 9038 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9039 CHECK_TYPE(XPATH_STRING);
pcercuei 0:03b5121a232e 9040 needle = valuePop(ctxt);
pcercuei 0:03b5121a232e 9041 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9042 hay = valuePop(ctxt);
pcercuei 0:03b5121a232e 9043
pcercuei 0:03b5121a232e 9044 if ((hay == NULL) || (hay->type != XPATH_STRING)) {
pcercuei 0:03b5121a232e 9045 xmlXPathReleaseObject(ctxt->context, hay);
pcercuei 0:03b5121a232e 9046 xmlXPathReleaseObject(ctxt->context, needle);
pcercuei 0:03b5121a232e 9047 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 9048 }
pcercuei 0:03b5121a232e 9049 if (xmlStrstr(hay->stringval, needle->stringval))
pcercuei 0:03b5121a232e 9050 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1));
pcercuei 0:03b5121a232e 9051 else
pcercuei 0:03b5121a232e 9052 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0));
pcercuei 0:03b5121a232e 9053 xmlXPathReleaseObject(ctxt->context, hay);
pcercuei 0:03b5121a232e 9054 xmlXPathReleaseObject(ctxt->context, needle);
pcercuei 0:03b5121a232e 9055 }
pcercuei 0:03b5121a232e 9056
pcercuei 0:03b5121a232e 9057 /**
pcercuei 0:03b5121a232e 9058 * xmlXPathStartsWithFunction:
pcercuei 0:03b5121a232e 9059 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9060 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9061 *
pcercuei 0:03b5121a232e 9062 * Implement the starts-with() XPath function
pcercuei 0:03b5121a232e 9063 * boolean starts-with(string, string)
pcercuei 0:03b5121a232e 9064 * The starts-with function returns true if the first argument string
pcercuei 0:03b5121a232e 9065 * starts with the second argument string, and otherwise returns false.
pcercuei 0:03b5121a232e 9066 */
pcercuei 0:03b5121a232e 9067 void
pcercuei 0:03b5121a232e 9068 xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9069 xmlXPathObjectPtr hay, needle;
pcercuei 0:03b5121a232e 9070 int n;
pcercuei 0:03b5121a232e 9071
pcercuei 0:03b5121a232e 9072 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 9073 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9074 CHECK_TYPE(XPATH_STRING);
pcercuei 0:03b5121a232e 9075 needle = valuePop(ctxt);
pcercuei 0:03b5121a232e 9076 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9077 hay = valuePop(ctxt);
pcercuei 0:03b5121a232e 9078
pcercuei 0:03b5121a232e 9079 if ((hay == NULL) || (hay->type != XPATH_STRING)) {
pcercuei 0:03b5121a232e 9080 xmlXPathReleaseObject(ctxt->context, hay);
pcercuei 0:03b5121a232e 9081 xmlXPathReleaseObject(ctxt->context, needle);
pcercuei 0:03b5121a232e 9082 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 9083 }
pcercuei 0:03b5121a232e 9084 n = xmlStrlen(needle->stringval);
pcercuei 0:03b5121a232e 9085 if (xmlStrncmp(hay->stringval, needle->stringval, n))
pcercuei 0:03b5121a232e 9086 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0));
pcercuei 0:03b5121a232e 9087 else
pcercuei 0:03b5121a232e 9088 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1));
pcercuei 0:03b5121a232e 9089 xmlXPathReleaseObject(ctxt->context, hay);
pcercuei 0:03b5121a232e 9090 xmlXPathReleaseObject(ctxt->context, needle);
pcercuei 0:03b5121a232e 9091 }
pcercuei 0:03b5121a232e 9092
pcercuei 0:03b5121a232e 9093 /**
pcercuei 0:03b5121a232e 9094 * xmlXPathSubstringFunction:
pcercuei 0:03b5121a232e 9095 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9096 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9097 *
pcercuei 0:03b5121a232e 9098 * Implement the substring() XPath function
pcercuei 0:03b5121a232e 9099 * string substring(string, number, number?)
pcercuei 0:03b5121a232e 9100 * The substring function returns the substring of the first argument
pcercuei 0:03b5121a232e 9101 * starting at the position specified in the second argument with
pcercuei 0:03b5121a232e 9102 * length specified in the third argument. For example,
pcercuei 0:03b5121a232e 9103 * substring("12345",2,3) returns "234". If the third argument is not
pcercuei 0:03b5121a232e 9104 * specified, it returns the substring starting at the position specified
pcercuei 0:03b5121a232e 9105 * in the second argument and continuing to the end of the string. For
pcercuei 0:03b5121a232e 9106 * example, substring("12345",2) returns "2345". More precisely, each
pcercuei 0:03b5121a232e 9107 * character in the string (see [3.6 Strings]) is considered to have a
pcercuei 0:03b5121a232e 9108 * numeric position: the position of the first character is 1, the position
pcercuei 0:03b5121a232e 9109 * of the second character is 2 and so on. The returned substring contains
pcercuei 0:03b5121a232e 9110 * those characters for which the position of the character is greater than
pcercuei 0:03b5121a232e 9111 * or equal to the second argument and, if the third argument is specified,
pcercuei 0:03b5121a232e 9112 * less than the sum of the second and third arguments; the comparisons
pcercuei 0:03b5121a232e 9113 * and addition used for the above follow the standard IEEE 754 rules. Thus:
pcercuei 0:03b5121a232e 9114 * - substring("12345", 1.5, 2.6) returns "234"
pcercuei 0:03b5121a232e 9115 * - substring("12345", 0, 3) returns "12"
pcercuei 0:03b5121a232e 9116 * - substring("12345", 0 div 0, 3) returns ""
pcercuei 0:03b5121a232e 9117 * - substring("12345", 1, 0 div 0) returns ""
pcercuei 0:03b5121a232e 9118 * - substring("12345", -42, 1 div 0) returns "12345"
pcercuei 0:03b5121a232e 9119 * - substring("12345", -1 div 0, 1 div 0) returns ""
pcercuei 0:03b5121a232e 9120 */
pcercuei 0:03b5121a232e 9121 void
pcercuei 0:03b5121a232e 9122 xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9123 xmlXPathObjectPtr str, start, len;
pcercuei 0:03b5121a232e 9124 double le=0, in;
pcercuei 0:03b5121a232e 9125 int i, l, m;
pcercuei 0:03b5121a232e 9126 xmlChar *ret;
pcercuei 0:03b5121a232e 9127
pcercuei 0:03b5121a232e 9128 if (nargs < 2) {
pcercuei 0:03b5121a232e 9129 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 9130 }
pcercuei 0:03b5121a232e 9131 if (nargs > 3) {
pcercuei 0:03b5121a232e 9132 CHECK_ARITY(3);
pcercuei 0:03b5121a232e 9133 }
pcercuei 0:03b5121a232e 9134 /*
pcercuei 0:03b5121a232e 9135 * take care of possible last (position) argument
pcercuei 0:03b5121a232e 9136 */
pcercuei 0:03b5121a232e 9137 if (nargs == 3) {
pcercuei 0:03b5121a232e 9138 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 9139 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 9140 len = valuePop(ctxt);
pcercuei 0:03b5121a232e 9141 le = len->floatval;
pcercuei 0:03b5121a232e 9142 xmlXPathReleaseObject(ctxt->context, len);
pcercuei 0:03b5121a232e 9143 }
pcercuei 0:03b5121a232e 9144
pcercuei 0:03b5121a232e 9145 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 9146 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 9147 start = valuePop(ctxt);
pcercuei 0:03b5121a232e 9148 in = start->floatval;
pcercuei 0:03b5121a232e 9149 xmlXPathReleaseObject(ctxt->context, start);
pcercuei 0:03b5121a232e 9150 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9151 CHECK_TYPE(XPATH_STRING);
pcercuei 0:03b5121a232e 9152 str = valuePop(ctxt);
pcercuei 0:03b5121a232e 9153 m = xmlUTF8Strlen((const unsigned char *)str->stringval);
pcercuei 0:03b5121a232e 9154
pcercuei 0:03b5121a232e 9155 /*
pcercuei 0:03b5121a232e 9156 * If last pos not present, calculate last position
pcercuei 0:03b5121a232e 9157 */
pcercuei 0:03b5121a232e 9158 if (nargs != 3) {
pcercuei 0:03b5121a232e 9159 le = (double)m;
pcercuei 0:03b5121a232e 9160 if (in < 1.0)
pcercuei 0:03b5121a232e 9161 in = 1.0;
pcercuei 0:03b5121a232e 9162 }
pcercuei 0:03b5121a232e 9163
pcercuei 0:03b5121a232e 9164 /* Need to check for the special cases where either
pcercuei 0:03b5121a232e 9165 * the index is NaN, the length is NaN, or both
pcercuei 0:03b5121a232e 9166 * arguments are infinity (relying on Inf + -Inf = NaN)
pcercuei 0:03b5121a232e 9167 */
pcercuei 0:03b5121a232e 9168 if (!xmlXPathIsInf(in) && !xmlXPathIsNaN(in + le)) {
pcercuei 0:03b5121a232e 9169 /*
pcercuei 0:03b5121a232e 9170 * To meet the requirements of the spec, the arguments
pcercuei 0:03b5121a232e 9171 * must be converted to integer format before
pcercuei 0:03b5121a232e 9172 * initial index calculations are done
pcercuei 0:03b5121a232e 9173 *
pcercuei 0:03b5121a232e 9174 * First we go to integer form, rounding up
pcercuei 0:03b5121a232e 9175 * and checking for special cases
pcercuei 0:03b5121a232e 9176 */
pcercuei 0:03b5121a232e 9177 i = (int) in;
pcercuei 0:03b5121a232e 9178 if (((double)i)+0.5 <= in) i++;
pcercuei 0:03b5121a232e 9179
pcercuei 0:03b5121a232e 9180 if (xmlXPathIsInf(le) == 1) {
pcercuei 0:03b5121a232e 9181 l = m;
pcercuei 0:03b5121a232e 9182 if (i < 1)
pcercuei 0:03b5121a232e 9183 i = 1;
pcercuei 0:03b5121a232e 9184 }
pcercuei 0:03b5121a232e 9185 else if (xmlXPathIsInf(le) == -1 || le < 0.0)
pcercuei 0:03b5121a232e 9186 l = 0;
pcercuei 0:03b5121a232e 9187 else {
pcercuei 0:03b5121a232e 9188 l = (int) le;
pcercuei 0:03b5121a232e 9189 if (((double)l)+0.5 <= le) l++;
pcercuei 0:03b5121a232e 9190 }
pcercuei 0:03b5121a232e 9191
pcercuei 0:03b5121a232e 9192 /* Now we normalize inidices */
pcercuei 0:03b5121a232e 9193 i -= 1;
pcercuei 0:03b5121a232e 9194 l += i;
pcercuei 0:03b5121a232e 9195 if (i < 0)
pcercuei 0:03b5121a232e 9196 i = 0;
pcercuei 0:03b5121a232e 9197 if (l > m)
pcercuei 0:03b5121a232e 9198 l = m;
pcercuei 0:03b5121a232e 9199
pcercuei 0:03b5121a232e 9200 /* number of chars to copy */
pcercuei 0:03b5121a232e 9201 l -= i;
pcercuei 0:03b5121a232e 9202
pcercuei 0:03b5121a232e 9203 ret = xmlUTF8Strsub(str->stringval, i, l);
pcercuei 0:03b5121a232e 9204 }
pcercuei 0:03b5121a232e 9205 else {
pcercuei 0:03b5121a232e 9206 ret = NULL;
pcercuei 0:03b5121a232e 9207 }
pcercuei 0:03b5121a232e 9208 if (ret == NULL)
pcercuei 0:03b5121a232e 9209 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, ""));
pcercuei 0:03b5121a232e 9210 else {
pcercuei 0:03b5121a232e 9211 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, ret));
pcercuei 0:03b5121a232e 9212 xmlFree(ret);
pcercuei 0:03b5121a232e 9213 }
pcercuei 0:03b5121a232e 9214 xmlXPathReleaseObject(ctxt->context, str);
pcercuei 0:03b5121a232e 9215 }
pcercuei 0:03b5121a232e 9216
pcercuei 0:03b5121a232e 9217 /**
pcercuei 0:03b5121a232e 9218 * xmlXPathSubstringBeforeFunction:
pcercuei 0:03b5121a232e 9219 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9220 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9221 *
pcercuei 0:03b5121a232e 9222 * Implement the substring-before() XPath function
pcercuei 0:03b5121a232e 9223 * string substring-before(string, string)
pcercuei 0:03b5121a232e 9224 * The substring-before function returns the substring of the first
pcercuei 0:03b5121a232e 9225 * argument string that precedes the first occurrence of the second
pcercuei 0:03b5121a232e 9226 * argument string in the first argument string, or the empty string
pcercuei 0:03b5121a232e 9227 * if the first argument string does not contain the second argument
pcercuei 0:03b5121a232e 9228 * string. For example, substring-before("1999/04/01","/") returns 1999.
pcercuei 0:03b5121a232e 9229 */
pcercuei 0:03b5121a232e 9230 void
pcercuei 0:03b5121a232e 9231 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9232 xmlXPathObjectPtr str;
pcercuei 0:03b5121a232e 9233 xmlXPathObjectPtr find;
pcercuei 0:03b5121a232e 9234 xmlBufPtr target;
pcercuei 0:03b5121a232e 9235 const xmlChar *point;
pcercuei 0:03b5121a232e 9236 int offset;
pcercuei 0:03b5121a232e 9237
pcercuei 0:03b5121a232e 9238 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 9239 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9240 find = valuePop(ctxt);
pcercuei 0:03b5121a232e 9241 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9242 str = valuePop(ctxt);
pcercuei 0:03b5121a232e 9243
pcercuei 0:03b5121a232e 9244 target = xmlBufCreate();
pcercuei 0:03b5121a232e 9245 if (target) {
pcercuei 0:03b5121a232e 9246 point = xmlStrstr(str->stringval, find->stringval);
pcercuei 0:03b5121a232e 9247 if (point) {
pcercuei 0:03b5121a232e 9248 offset = (int)(point - str->stringval);
pcercuei 0:03b5121a232e 9249 xmlBufAdd(target, str->stringval, offset);
pcercuei 0:03b5121a232e 9250 }
pcercuei 0:03b5121a232e 9251 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 9252 xmlBufContent(target)));
pcercuei 0:03b5121a232e 9253 xmlBufFree(target);
pcercuei 0:03b5121a232e 9254 }
pcercuei 0:03b5121a232e 9255 xmlXPathReleaseObject(ctxt->context, str);
pcercuei 0:03b5121a232e 9256 xmlXPathReleaseObject(ctxt->context, find);
pcercuei 0:03b5121a232e 9257 }
pcercuei 0:03b5121a232e 9258
pcercuei 0:03b5121a232e 9259 /**
pcercuei 0:03b5121a232e 9260 * xmlXPathSubstringAfterFunction:
pcercuei 0:03b5121a232e 9261 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9262 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9263 *
pcercuei 0:03b5121a232e 9264 * Implement the substring-after() XPath function
pcercuei 0:03b5121a232e 9265 * string substring-after(string, string)
pcercuei 0:03b5121a232e 9266 * The substring-after function returns the substring of the first
pcercuei 0:03b5121a232e 9267 * argument string that follows the first occurrence of the second
pcercuei 0:03b5121a232e 9268 * argument string in the first argument string, or the empty stringi
pcercuei 0:03b5121a232e 9269 * if the first argument string does not contain the second argument
pcercuei 0:03b5121a232e 9270 * string. For example, substring-after("1999/04/01","/") returns 04/01,
pcercuei 0:03b5121a232e 9271 * and substring-after("1999/04/01","19") returns 99/04/01.
pcercuei 0:03b5121a232e 9272 */
pcercuei 0:03b5121a232e 9273 void
pcercuei 0:03b5121a232e 9274 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9275 xmlXPathObjectPtr str;
pcercuei 0:03b5121a232e 9276 xmlXPathObjectPtr find;
pcercuei 0:03b5121a232e 9277 xmlBufPtr target;
pcercuei 0:03b5121a232e 9278 const xmlChar *point;
pcercuei 0:03b5121a232e 9279 int offset;
pcercuei 0:03b5121a232e 9280
pcercuei 0:03b5121a232e 9281 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 9282 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9283 find = valuePop(ctxt);
pcercuei 0:03b5121a232e 9284 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9285 str = valuePop(ctxt);
pcercuei 0:03b5121a232e 9286
pcercuei 0:03b5121a232e 9287 target = xmlBufCreate();
pcercuei 0:03b5121a232e 9288 if (target) {
pcercuei 0:03b5121a232e 9289 point = xmlStrstr(str->stringval, find->stringval);
pcercuei 0:03b5121a232e 9290 if (point) {
pcercuei 0:03b5121a232e 9291 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
pcercuei 0:03b5121a232e 9292 xmlBufAdd(target, &str->stringval[offset],
pcercuei 0:03b5121a232e 9293 xmlStrlen(str->stringval) - offset);
pcercuei 0:03b5121a232e 9294 }
pcercuei 0:03b5121a232e 9295 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 9296 xmlBufContent(target)));
pcercuei 0:03b5121a232e 9297 xmlBufFree(target);
pcercuei 0:03b5121a232e 9298 }
pcercuei 0:03b5121a232e 9299 xmlXPathReleaseObject(ctxt->context, str);
pcercuei 0:03b5121a232e 9300 xmlXPathReleaseObject(ctxt->context, find);
pcercuei 0:03b5121a232e 9301 }
pcercuei 0:03b5121a232e 9302
pcercuei 0:03b5121a232e 9303 /**
pcercuei 0:03b5121a232e 9304 * xmlXPathNormalizeFunction:
pcercuei 0:03b5121a232e 9305 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9306 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9307 *
pcercuei 0:03b5121a232e 9308 * Implement the normalize-space() XPath function
pcercuei 0:03b5121a232e 9309 * string normalize-space(string?)
pcercuei 0:03b5121a232e 9310 * The normalize-space function returns the argument string with white
pcercuei 0:03b5121a232e 9311 * space normalized by stripping leading and trailing whitespace
pcercuei 0:03b5121a232e 9312 * and replacing sequences of whitespace characters by a single
pcercuei 0:03b5121a232e 9313 * space. Whitespace characters are the same allowed by the S production
pcercuei 0:03b5121a232e 9314 * in XML. If the argument is omitted, it defaults to the context
pcercuei 0:03b5121a232e 9315 * node converted to a string, in other words the value of the context node.
pcercuei 0:03b5121a232e 9316 */
pcercuei 0:03b5121a232e 9317 void
pcercuei 0:03b5121a232e 9318 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9319 xmlXPathObjectPtr obj = NULL;
pcercuei 0:03b5121a232e 9320 xmlChar *source = NULL;
pcercuei 0:03b5121a232e 9321 xmlBufPtr target;
pcercuei 0:03b5121a232e 9322 xmlChar blank;
pcercuei 0:03b5121a232e 9323
pcercuei 0:03b5121a232e 9324 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 9325 if (nargs == 0) {
pcercuei 0:03b5121a232e 9326 /* Use current context node */
pcercuei 0:03b5121a232e 9327 valuePush(ctxt,
pcercuei 0:03b5121a232e 9328 xmlXPathCacheWrapString(ctxt->context,
pcercuei 0:03b5121a232e 9329 xmlXPathCastNodeToString(ctxt->context->node)));
pcercuei 0:03b5121a232e 9330 nargs = 1;
pcercuei 0:03b5121a232e 9331 }
pcercuei 0:03b5121a232e 9332
pcercuei 0:03b5121a232e 9333 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9334 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9335 CHECK_TYPE(XPATH_STRING);
pcercuei 0:03b5121a232e 9336 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 9337 source = obj->stringval;
pcercuei 0:03b5121a232e 9338
pcercuei 0:03b5121a232e 9339 target = xmlBufCreate();
pcercuei 0:03b5121a232e 9340 if (target && source) {
pcercuei 0:03b5121a232e 9341
pcercuei 0:03b5121a232e 9342 /* Skip leading whitespaces */
pcercuei 0:03b5121a232e 9343 while (IS_BLANK_CH(*source))
pcercuei 0:03b5121a232e 9344 source++;
pcercuei 0:03b5121a232e 9345
pcercuei 0:03b5121a232e 9346 /* Collapse intermediate whitespaces, and skip trailing whitespaces */
pcercuei 0:03b5121a232e 9347 blank = 0;
pcercuei 0:03b5121a232e 9348 while (*source) {
pcercuei 0:03b5121a232e 9349 if (IS_BLANK_CH(*source)) {
pcercuei 0:03b5121a232e 9350 blank = 0x20;
pcercuei 0:03b5121a232e 9351 } else {
pcercuei 0:03b5121a232e 9352 if (blank) {
pcercuei 0:03b5121a232e 9353 xmlBufAdd(target, &blank, 1);
pcercuei 0:03b5121a232e 9354 blank = 0;
pcercuei 0:03b5121a232e 9355 }
pcercuei 0:03b5121a232e 9356 xmlBufAdd(target, source, 1);
pcercuei 0:03b5121a232e 9357 }
pcercuei 0:03b5121a232e 9358 source++;
pcercuei 0:03b5121a232e 9359 }
pcercuei 0:03b5121a232e 9360 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 9361 xmlBufContent(target)));
pcercuei 0:03b5121a232e 9362 xmlBufFree(target);
pcercuei 0:03b5121a232e 9363 }
pcercuei 0:03b5121a232e 9364 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 9365 }
pcercuei 0:03b5121a232e 9366
pcercuei 0:03b5121a232e 9367 /**
pcercuei 0:03b5121a232e 9368 * xmlXPathTranslateFunction:
pcercuei 0:03b5121a232e 9369 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9370 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9371 *
pcercuei 0:03b5121a232e 9372 * Implement the translate() XPath function
pcercuei 0:03b5121a232e 9373 * string translate(string, string, string)
pcercuei 0:03b5121a232e 9374 * The translate function returns the first argument string with
pcercuei 0:03b5121a232e 9375 * occurrences of characters in the second argument string replaced
pcercuei 0:03b5121a232e 9376 * by the character at the corresponding position in the third argument
pcercuei 0:03b5121a232e 9377 * string. For example, translate("bar","abc","ABC") returns the string
pcercuei 0:03b5121a232e 9378 * BAr. If there is a character in the second argument string with no
pcercuei 0:03b5121a232e 9379 * character at a corresponding position in the third argument string
pcercuei 0:03b5121a232e 9380 * (because the second argument string is longer than the third argument
pcercuei 0:03b5121a232e 9381 * string), then occurrences of that character in the first argument
pcercuei 0:03b5121a232e 9382 * string are removed. For example, translate("--aaa--","abc-","ABC")
pcercuei 0:03b5121a232e 9383 * returns "AAA". If a character occurs more than once in second
pcercuei 0:03b5121a232e 9384 * argument string, then the first occurrence determines the replacement
pcercuei 0:03b5121a232e 9385 * character. If the third argument string is longer than the second
pcercuei 0:03b5121a232e 9386 * argument string, then excess characters are ignored.
pcercuei 0:03b5121a232e 9387 */
pcercuei 0:03b5121a232e 9388 void
pcercuei 0:03b5121a232e 9389 xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9390 xmlXPathObjectPtr str;
pcercuei 0:03b5121a232e 9391 xmlXPathObjectPtr from;
pcercuei 0:03b5121a232e 9392 xmlXPathObjectPtr to;
pcercuei 0:03b5121a232e 9393 xmlBufPtr target;
pcercuei 0:03b5121a232e 9394 int offset, max;
pcercuei 0:03b5121a232e 9395 xmlChar ch;
pcercuei 0:03b5121a232e 9396 const xmlChar *point;
pcercuei 0:03b5121a232e 9397 xmlChar *cptr;
pcercuei 0:03b5121a232e 9398
pcercuei 0:03b5121a232e 9399 CHECK_ARITY(3);
pcercuei 0:03b5121a232e 9400
pcercuei 0:03b5121a232e 9401 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9402 to = valuePop(ctxt);
pcercuei 0:03b5121a232e 9403 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9404 from = valuePop(ctxt);
pcercuei 0:03b5121a232e 9405 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9406 str = valuePop(ctxt);
pcercuei 0:03b5121a232e 9407
pcercuei 0:03b5121a232e 9408 target = xmlBufCreate();
pcercuei 0:03b5121a232e 9409 if (target) {
pcercuei 0:03b5121a232e 9410 max = xmlUTF8Strlen(to->stringval);
pcercuei 0:03b5121a232e 9411 for (cptr = str->stringval; (ch=*cptr); ) {
pcercuei 0:03b5121a232e 9412 offset = xmlUTF8Strloc(from->stringval, cptr);
pcercuei 0:03b5121a232e 9413 if (offset >= 0) {
pcercuei 0:03b5121a232e 9414 if (offset < max) {
pcercuei 0:03b5121a232e 9415 point = xmlUTF8Strpos(to->stringval, offset);
pcercuei 0:03b5121a232e 9416 if (point)
pcercuei 0:03b5121a232e 9417 xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
pcercuei 0:03b5121a232e 9418 }
pcercuei 0:03b5121a232e 9419 } else
pcercuei 0:03b5121a232e 9420 xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
pcercuei 0:03b5121a232e 9421
pcercuei 0:03b5121a232e 9422 /* Step to next character in input */
pcercuei 0:03b5121a232e 9423 cptr++;
pcercuei 0:03b5121a232e 9424 if ( ch & 0x80 ) {
pcercuei 0:03b5121a232e 9425 /* if not simple ascii, verify proper format */
pcercuei 0:03b5121a232e 9426 if ( (ch & 0xc0) != 0xc0 ) {
pcercuei 0:03b5121a232e 9427 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 9428 "xmlXPathTranslateFunction: Invalid UTF8 string\n");
pcercuei 0:03b5121a232e 9429 /* not asserting an XPath error is probably better */
pcercuei 0:03b5121a232e 9430 break;
pcercuei 0:03b5121a232e 9431 }
pcercuei 0:03b5121a232e 9432 /* then skip over remaining bytes for this char */
pcercuei 0:03b5121a232e 9433 while ( (ch <<= 1) & 0x80 )
pcercuei 0:03b5121a232e 9434 if ( (*cptr++ & 0xc0) != 0x80 ) {
pcercuei 0:03b5121a232e 9435 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 9436 "xmlXPathTranslateFunction: Invalid UTF8 string\n");
pcercuei 0:03b5121a232e 9437 /* not asserting an XPath error is probably better */
pcercuei 0:03b5121a232e 9438 break;
pcercuei 0:03b5121a232e 9439 }
pcercuei 0:03b5121a232e 9440 if (ch & 0x80) /* must have had error encountered */
pcercuei 0:03b5121a232e 9441 break;
pcercuei 0:03b5121a232e 9442 }
pcercuei 0:03b5121a232e 9443 }
pcercuei 0:03b5121a232e 9444 }
pcercuei 0:03b5121a232e 9445 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 9446 xmlBufContent(target)));
pcercuei 0:03b5121a232e 9447 xmlBufFree(target);
pcercuei 0:03b5121a232e 9448 xmlXPathReleaseObject(ctxt->context, str);
pcercuei 0:03b5121a232e 9449 xmlXPathReleaseObject(ctxt->context, from);
pcercuei 0:03b5121a232e 9450 xmlXPathReleaseObject(ctxt->context, to);
pcercuei 0:03b5121a232e 9451 }
pcercuei 0:03b5121a232e 9452
pcercuei 0:03b5121a232e 9453 /**
pcercuei 0:03b5121a232e 9454 * xmlXPathBooleanFunction:
pcercuei 0:03b5121a232e 9455 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9456 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9457 *
pcercuei 0:03b5121a232e 9458 * Implement the boolean() XPath function
pcercuei 0:03b5121a232e 9459 * boolean boolean(object)
pcercuei 0:03b5121a232e 9460 * The boolean function converts its argument to a boolean as follows:
pcercuei 0:03b5121a232e 9461 * - a number is true if and only if it is neither positive or
pcercuei 0:03b5121a232e 9462 * negative zero nor NaN
pcercuei 0:03b5121a232e 9463 * - a node-set is true if and only if it is non-empty
pcercuei 0:03b5121a232e 9464 * - a string is true if and only if its length is non-zero
pcercuei 0:03b5121a232e 9465 */
pcercuei 0:03b5121a232e 9466 void
pcercuei 0:03b5121a232e 9467 xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9468 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 9469
pcercuei 0:03b5121a232e 9470 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9471 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 9472 if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
pcercuei 0:03b5121a232e 9473 cur = xmlXPathCacheConvertBoolean(ctxt->context, cur);
pcercuei 0:03b5121a232e 9474 valuePush(ctxt, cur);
pcercuei 0:03b5121a232e 9475 }
pcercuei 0:03b5121a232e 9476
pcercuei 0:03b5121a232e 9477 /**
pcercuei 0:03b5121a232e 9478 * xmlXPathNotFunction:
pcercuei 0:03b5121a232e 9479 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9480 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9481 *
pcercuei 0:03b5121a232e 9482 * Implement the not() XPath function
pcercuei 0:03b5121a232e 9483 * boolean not(boolean)
pcercuei 0:03b5121a232e 9484 * The not function returns true if its argument is false,
pcercuei 0:03b5121a232e 9485 * and false otherwise.
pcercuei 0:03b5121a232e 9486 */
pcercuei 0:03b5121a232e 9487 void
pcercuei 0:03b5121a232e 9488 xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9489 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9490 CAST_TO_BOOLEAN;
pcercuei 0:03b5121a232e 9491 CHECK_TYPE(XPATH_BOOLEAN);
pcercuei 0:03b5121a232e 9492 ctxt->value->boolval = ! ctxt->value->boolval;
pcercuei 0:03b5121a232e 9493 }
pcercuei 0:03b5121a232e 9494
pcercuei 0:03b5121a232e 9495 /**
pcercuei 0:03b5121a232e 9496 * xmlXPathTrueFunction:
pcercuei 0:03b5121a232e 9497 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9498 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9499 *
pcercuei 0:03b5121a232e 9500 * Implement the true() XPath function
pcercuei 0:03b5121a232e 9501 * boolean true()
pcercuei 0:03b5121a232e 9502 */
pcercuei 0:03b5121a232e 9503 void
pcercuei 0:03b5121a232e 9504 xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9505 CHECK_ARITY(0);
pcercuei 0:03b5121a232e 9506 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1));
pcercuei 0:03b5121a232e 9507 }
pcercuei 0:03b5121a232e 9508
pcercuei 0:03b5121a232e 9509 /**
pcercuei 0:03b5121a232e 9510 * xmlXPathFalseFunction:
pcercuei 0:03b5121a232e 9511 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9512 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9513 *
pcercuei 0:03b5121a232e 9514 * Implement the false() XPath function
pcercuei 0:03b5121a232e 9515 * boolean false()
pcercuei 0:03b5121a232e 9516 */
pcercuei 0:03b5121a232e 9517 void
pcercuei 0:03b5121a232e 9518 xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9519 CHECK_ARITY(0);
pcercuei 0:03b5121a232e 9520 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0));
pcercuei 0:03b5121a232e 9521 }
pcercuei 0:03b5121a232e 9522
pcercuei 0:03b5121a232e 9523 /**
pcercuei 0:03b5121a232e 9524 * xmlXPathLangFunction:
pcercuei 0:03b5121a232e 9525 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9526 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9527 *
pcercuei 0:03b5121a232e 9528 * Implement the lang() XPath function
pcercuei 0:03b5121a232e 9529 * boolean lang(string)
pcercuei 0:03b5121a232e 9530 * The lang function returns true or false depending on whether the
pcercuei 0:03b5121a232e 9531 * language of the context node as specified by xml:lang attributes
pcercuei 0:03b5121a232e 9532 * is the same as or is a sublanguage of the language specified by
pcercuei 0:03b5121a232e 9533 * the argument string. The language of the context node is determined
pcercuei 0:03b5121a232e 9534 * by the value of the xml:lang attribute on the context node, or, if
pcercuei 0:03b5121a232e 9535 * the context node has no xml:lang attribute, by the value of the
pcercuei 0:03b5121a232e 9536 * xml:lang attribute on the nearest ancestor of the context node that
pcercuei 0:03b5121a232e 9537 * has an xml:lang attribute. If there is no such attribute, then lang
pcercuei 0:03b5121a232e 9538 * returns false. If there is such an attribute, then lang returns
pcercuei 0:03b5121a232e 9539 * true if the attribute value is equal to the argument ignoring case,
pcercuei 0:03b5121a232e 9540 * or if there is some suffix starting with - such that the attribute
pcercuei 0:03b5121a232e 9541 * value is equal to the argument ignoring that suffix of the attribute
pcercuei 0:03b5121a232e 9542 * value and ignoring case.
pcercuei 0:03b5121a232e 9543 */
pcercuei 0:03b5121a232e 9544 void
pcercuei 0:03b5121a232e 9545 xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9546 xmlXPathObjectPtr val = NULL;
pcercuei 0:03b5121a232e 9547 const xmlChar *theLang = NULL;
pcercuei 0:03b5121a232e 9548 const xmlChar *lang;
pcercuei 0:03b5121a232e 9549 int ret = 0;
pcercuei 0:03b5121a232e 9550 int i;
pcercuei 0:03b5121a232e 9551
pcercuei 0:03b5121a232e 9552 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9553 CAST_TO_STRING;
pcercuei 0:03b5121a232e 9554 CHECK_TYPE(XPATH_STRING);
pcercuei 0:03b5121a232e 9555 val = valuePop(ctxt);
pcercuei 0:03b5121a232e 9556 lang = val->stringval;
pcercuei 0:03b5121a232e 9557 theLang = xmlNodeGetLang(ctxt->context->node);
pcercuei 0:03b5121a232e 9558 if ((theLang != NULL) && (lang != NULL)) {
pcercuei 0:03b5121a232e 9559 for (i = 0;lang[i] != 0;i++)
pcercuei 0:03b5121a232e 9560 if (toupper(lang[i]) != toupper(theLang[i]))
pcercuei 0:03b5121a232e 9561 goto not_equal;
pcercuei 0:03b5121a232e 9562 if ((theLang[i] == 0) || (theLang[i] == '-'))
pcercuei 0:03b5121a232e 9563 ret = 1;
pcercuei 0:03b5121a232e 9564 }
pcercuei 0:03b5121a232e 9565 not_equal:
pcercuei 0:03b5121a232e 9566 if (theLang != NULL)
pcercuei 0:03b5121a232e 9567 xmlFree((void *)theLang);
pcercuei 0:03b5121a232e 9568
pcercuei 0:03b5121a232e 9569 xmlXPathReleaseObject(ctxt->context, val);
pcercuei 0:03b5121a232e 9570 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
pcercuei 0:03b5121a232e 9571 }
pcercuei 0:03b5121a232e 9572
pcercuei 0:03b5121a232e 9573 /**
pcercuei 0:03b5121a232e 9574 * xmlXPathNumberFunction:
pcercuei 0:03b5121a232e 9575 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9576 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9577 *
pcercuei 0:03b5121a232e 9578 * Implement the number() XPath function
pcercuei 0:03b5121a232e 9579 * number number(object?)
pcercuei 0:03b5121a232e 9580 */
pcercuei 0:03b5121a232e 9581 void
pcercuei 0:03b5121a232e 9582 xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9583 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 9584 double res;
pcercuei 0:03b5121a232e 9585
pcercuei 0:03b5121a232e 9586 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 9587 if (nargs == 0) {
pcercuei 0:03b5121a232e 9588 if (ctxt->context->node == NULL) {
pcercuei 0:03b5121a232e 9589 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, 0.0));
pcercuei 0:03b5121a232e 9590 } else {
pcercuei 0:03b5121a232e 9591 xmlChar* content = xmlNodeGetContent(ctxt->context->node);
pcercuei 0:03b5121a232e 9592
pcercuei 0:03b5121a232e 9593 res = xmlXPathStringEvalNumber(content);
pcercuei 0:03b5121a232e 9594 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res));
pcercuei 0:03b5121a232e 9595 xmlFree(content);
pcercuei 0:03b5121a232e 9596 }
pcercuei 0:03b5121a232e 9597 return;
pcercuei 0:03b5121a232e 9598 }
pcercuei 0:03b5121a232e 9599
pcercuei 0:03b5121a232e 9600 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9601 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 9602 valuePush(ctxt, xmlXPathCacheConvertNumber(ctxt->context, cur));
pcercuei 0:03b5121a232e 9603 }
pcercuei 0:03b5121a232e 9604
pcercuei 0:03b5121a232e 9605 /**
pcercuei 0:03b5121a232e 9606 * xmlXPathSumFunction:
pcercuei 0:03b5121a232e 9607 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9608 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9609 *
pcercuei 0:03b5121a232e 9610 * Implement the sum() XPath function
pcercuei 0:03b5121a232e 9611 * number sum(node-set)
pcercuei 0:03b5121a232e 9612 * The sum function returns the sum of the values of the nodes in
pcercuei 0:03b5121a232e 9613 * the argument node-set.
pcercuei 0:03b5121a232e 9614 */
pcercuei 0:03b5121a232e 9615 void
pcercuei 0:03b5121a232e 9616 xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9617 xmlXPathObjectPtr cur;
pcercuei 0:03b5121a232e 9618 int i;
pcercuei 0:03b5121a232e 9619 double res = 0.0;
pcercuei 0:03b5121a232e 9620
pcercuei 0:03b5121a232e 9621 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9622 if ((ctxt->value == NULL) ||
pcercuei 0:03b5121a232e 9623 ((ctxt->value->type != XPATH_NODESET) &&
pcercuei 0:03b5121a232e 9624 (ctxt->value->type != XPATH_XSLT_TREE)))
pcercuei 0:03b5121a232e 9625 XP_ERROR(XPATH_INVALID_TYPE);
pcercuei 0:03b5121a232e 9626 cur = valuePop(ctxt);
pcercuei 0:03b5121a232e 9627
pcercuei 0:03b5121a232e 9628 if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
pcercuei 0:03b5121a232e 9629 for (i = 0; i < cur->nodesetval->nodeNr; i++) {
pcercuei 0:03b5121a232e 9630 res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
pcercuei 0:03b5121a232e 9631 }
pcercuei 0:03b5121a232e 9632 }
pcercuei 0:03b5121a232e 9633 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, res));
pcercuei 0:03b5121a232e 9634 xmlXPathReleaseObject(ctxt->context, cur);
pcercuei 0:03b5121a232e 9635 }
pcercuei 0:03b5121a232e 9636
pcercuei 0:03b5121a232e 9637 /*
pcercuei 0:03b5121a232e 9638 * To assure working code on multiple platforms, we want to only depend
pcercuei 0:03b5121a232e 9639 * upon the characteristic truncation of converting a floating point value
pcercuei 0:03b5121a232e 9640 * to an integer. Unfortunately, because of the different storage sizes
pcercuei 0:03b5121a232e 9641 * of our internal floating point value (double) and integer (int), we
pcercuei 0:03b5121a232e 9642 * can't directly convert (see bug 301162). This macro is a messy
pcercuei 0:03b5121a232e 9643 * 'workaround'
pcercuei 0:03b5121a232e 9644 */
pcercuei 0:03b5121a232e 9645 #define XTRUNC(f, v) \
pcercuei 0:03b5121a232e 9646 f = fmod((v), INT_MAX); \
pcercuei 0:03b5121a232e 9647 f = (v) - (f) + (double)((int)(f));
pcercuei 0:03b5121a232e 9648
pcercuei 0:03b5121a232e 9649 /**
pcercuei 0:03b5121a232e 9650 * xmlXPathFloorFunction:
pcercuei 0:03b5121a232e 9651 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9652 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9653 *
pcercuei 0:03b5121a232e 9654 * Implement the floor() XPath function
pcercuei 0:03b5121a232e 9655 * number floor(number)
pcercuei 0:03b5121a232e 9656 * The floor function returns the largest (closest to positive infinity)
pcercuei 0:03b5121a232e 9657 * number that is not greater than the argument and that is an integer.
pcercuei 0:03b5121a232e 9658 */
pcercuei 0:03b5121a232e 9659 void
pcercuei 0:03b5121a232e 9660 xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9661 double f;
pcercuei 0:03b5121a232e 9662
pcercuei 0:03b5121a232e 9663 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9664 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 9665 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 9666
pcercuei 0:03b5121a232e 9667 XTRUNC(f, ctxt->value->floatval);
pcercuei 0:03b5121a232e 9668 if (f != ctxt->value->floatval) {
pcercuei 0:03b5121a232e 9669 if (ctxt->value->floatval > 0)
pcercuei 0:03b5121a232e 9670 ctxt->value->floatval = f;
pcercuei 0:03b5121a232e 9671 else
pcercuei 0:03b5121a232e 9672 ctxt->value->floatval = f - 1;
pcercuei 0:03b5121a232e 9673 }
pcercuei 0:03b5121a232e 9674 }
pcercuei 0:03b5121a232e 9675
pcercuei 0:03b5121a232e 9676 /**
pcercuei 0:03b5121a232e 9677 * xmlXPathCeilingFunction:
pcercuei 0:03b5121a232e 9678 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9679 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9680 *
pcercuei 0:03b5121a232e 9681 * Implement the ceiling() XPath function
pcercuei 0:03b5121a232e 9682 * number ceiling(number)
pcercuei 0:03b5121a232e 9683 * The ceiling function returns the smallest (closest to negative infinity)
pcercuei 0:03b5121a232e 9684 * number that is not less than the argument and that is an integer.
pcercuei 0:03b5121a232e 9685 */
pcercuei 0:03b5121a232e 9686 void
pcercuei 0:03b5121a232e 9687 xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9688 double f;
pcercuei 0:03b5121a232e 9689
pcercuei 0:03b5121a232e 9690 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9691 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 9692 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 9693
pcercuei 0:03b5121a232e 9694 #if 0
pcercuei 0:03b5121a232e 9695 ctxt->value->floatval = ceil(ctxt->value->floatval);
pcercuei 0:03b5121a232e 9696 #else
pcercuei 0:03b5121a232e 9697 XTRUNC(f, ctxt->value->floatval);
pcercuei 0:03b5121a232e 9698 if (f != ctxt->value->floatval) {
pcercuei 0:03b5121a232e 9699 if (ctxt->value->floatval > 0)
pcercuei 0:03b5121a232e 9700 ctxt->value->floatval = f + 1;
pcercuei 0:03b5121a232e 9701 else {
pcercuei 0:03b5121a232e 9702 if (ctxt->value->floatval < 0 && f == 0)
pcercuei 0:03b5121a232e 9703 ctxt->value->floatval = xmlXPathNZERO;
pcercuei 0:03b5121a232e 9704 else
pcercuei 0:03b5121a232e 9705 ctxt->value->floatval = f;
pcercuei 0:03b5121a232e 9706 }
pcercuei 0:03b5121a232e 9707
pcercuei 0:03b5121a232e 9708 }
pcercuei 0:03b5121a232e 9709 #endif
pcercuei 0:03b5121a232e 9710 }
pcercuei 0:03b5121a232e 9711
pcercuei 0:03b5121a232e 9712 /**
pcercuei 0:03b5121a232e 9713 * xmlXPathRoundFunction:
pcercuei 0:03b5121a232e 9714 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9715 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 9716 *
pcercuei 0:03b5121a232e 9717 * Implement the round() XPath function
pcercuei 0:03b5121a232e 9718 * number round(number)
pcercuei 0:03b5121a232e 9719 * The round function returns the number that is closest to the
pcercuei 0:03b5121a232e 9720 * argument and that is an integer. If there are two such numbers,
pcercuei 0:03b5121a232e 9721 * then the one that is even is returned.
pcercuei 0:03b5121a232e 9722 */
pcercuei 0:03b5121a232e 9723 void
pcercuei 0:03b5121a232e 9724 xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 9725 double f;
pcercuei 0:03b5121a232e 9726
pcercuei 0:03b5121a232e 9727 CHECK_ARITY(1);
pcercuei 0:03b5121a232e 9728 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 9729 CHECK_TYPE(XPATH_NUMBER);
pcercuei 0:03b5121a232e 9730
pcercuei 0:03b5121a232e 9731 if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
pcercuei 0:03b5121a232e 9732 (xmlXPathIsInf(ctxt->value->floatval) == 1) ||
pcercuei 0:03b5121a232e 9733 (xmlXPathIsInf(ctxt->value->floatval) == -1) ||
pcercuei 0:03b5121a232e 9734 (ctxt->value->floatval == 0.0))
pcercuei 0:03b5121a232e 9735 return;
pcercuei 0:03b5121a232e 9736
pcercuei 0:03b5121a232e 9737 XTRUNC(f, ctxt->value->floatval);
pcercuei 0:03b5121a232e 9738 if (ctxt->value->floatval < 0) {
pcercuei 0:03b5121a232e 9739 if (ctxt->value->floatval < f - 0.5)
pcercuei 0:03b5121a232e 9740 ctxt->value->floatval = f - 1;
pcercuei 0:03b5121a232e 9741 else
pcercuei 0:03b5121a232e 9742 ctxt->value->floatval = f;
pcercuei 0:03b5121a232e 9743 if (ctxt->value->floatval == 0)
pcercuei 0:03b5121a232e 9744 ctxt->value->floatval = xmlXPathNZERO;
pcercuei 0:03b5121a232e 9745 } else {
pcercuei 0:03b5121a232e 9746 if (ctxt->value->floatval < f + 0.5)
pcercuei 0:03b5121a232e 9747 ctxt->value->floatval = f;
pcercuei 0:03b5121a232e 9748 else
pcercuei 0:03b5121a232e 9749 ctxt->value->floatval = f + 1;
pcercuei 0:03b5121a232e 9750 }
pcercuei 0:03b5121a232e 9751 }
pcercuei 0:03b5121a232e 9752
pcercuei 0:03b5121a232e 9753 /************************************************************************
pcercuei 0:03b5121a232e 9754 * *
pcercuei 0:03b5121a232e 9755 * The Parser *
pcercuei 0:03b5121a232e 9756 * *
pcercuei 0:03b5121a232e 9757 ************************************************************************/
pcercuei 0:03b5121a232e 9758
pcercuei 0:03b5121a232e 9759 /*
pcercuei 0:03b5121a232e 9760 * a few forward declarations since we use a recursive call based
pcercuei 0:03b5121a232e 9761 * implementation.
pcercuei 0:03b5121a232e 9762 */
pcercuei 0:03b5121a232e 9763 static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort);
pcercuei 0:03b5121a232e 9764 static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
pcercuei 0:03b5121a232e 9765 static void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
pcercuei 0:03b5121a232e 9766 static void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
pcercuei 0:03b5121a232e 9767 static xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 9768 int qualified);
pcercuei 0:03b5121a232e 9769
pcercuei 0:03b5121a232e 9770 /**
pcercuei 0:03b5121a232e 9771 * xmlXPathCurrentChar:
pcercuei 0:03b5121a232e 9772 * @ctxt: the XPath parser context
pcercuei 0:03b5121a232e 9773 * @cur: pointer to the beginning of the char
pcercuei 0:03b5121a232e 9774 * @len: pointer to the length of the char read
pcercuei 0:03b5121a232e 9775 *
pcercuei 0:03b5121a232e 9776 * The current char value, if using UTF-8 this may actually span multiple
pcercuei 0:03b5121a232e 9777 * bytes in the input buffer.
pcercuei 0:03b5121a232e 9778 *
pcercuei 0:03b5121a232e 9779 * Returns the current char value and its length
pcercuei 0:03b5121a232e 9780 */
pcercuei 0:03b5121a232e 9781
pcercuei 0:03b5121a232e 9782 static int
pcercuei 0:03b5121a232e 9783 xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
pcercuei 0:03b5121a232e 9784 unsigned char c;
pcercuei 0:03b5121a232e 9785 unsigned int val;
pcercuei 0:03b5121a232e 9786 const xmlChar *cur;
pcercuei 0:03b5121a232e 9787
pcercuei 0:03b5121a232e 9788 if (ctxt == NULL)
pcercuei 0:03b5121a232e 9789 return(0);
pcercuei 0:03b5121a232e 9790 cur = ctxt->cur;
pcercuei 0:03b5121a232e 9791
pcercuei 0:03b5121a232e 9792 /*
pcercuei 0:03b5121a232e 9793 * We are supposed to handle UTF8, check it's valid
pcercuei 0:03b5121a232e 9794 * From rfc2044: encoding of the Unicode values on UTF-8:
pcercuei 0:03b5121a232e 9795 *
pcercuei 0:03b5121a232e 9796 * UCS-4 range (hex.) UTF-8 octet sequence (binary)
pcercuei 0:03b5121a232e 9797 * 0000 0000-0000 007F 0xxxxxxx
pcercuei 0:03b5121a232e 9798 * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
pcercuei 0:03b5121a232e 9799 * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
pcercuei 0:03b5121a232e 9800 *
pcercuei 0:03b5121a232e 9801 * Check for the 0x110000 limit too
pcercuei 0:03b5121a232e 9802 */
pcercuei 0:03b5121a232e 9803 c = *cur;
pcercuei 0:03b5121a232e 9804 if (c & 0x80) {
pcercuei 0:03b5121a232e 9805 if ((cur[1] & 0xc0) != 0x80)
pcercuei 0:03b5121a232e 9806 goto encoding_error;
pcercuei 0:03b5121a232e 9807 if ((c & 0xe0) == 0xe0) {
pcercuei 0:03b5121a232e 9808
pcercuei 0:03b5121a232e 9809 if ((cur[2] & 0xc0) != 0x80)
pcercuei 0:03b5121a232e 9810 goto encoding_error;
pcercuei 0:03b5121a232e 9811 if ((c & 0xf0) == 0xf0) {
pcercuei 0:03b5121a232e 9812 if (((c & 0xf8) != 0xf0) ||
pcercuei 0:03b5121a232e 9813 ((cur[3] & 0xc0) != 0x80))
pcercuei 0:03b5121a232e 9814 goto encoding_error;
pcercuei 0:03b5121a232e 9815 /* 4-byte code */
pcercuei 0:03b5121a232e 9816 *len = 4;
pcercuei 0:03b5121a232e 9817 val = (cur[0] & 0x7) << 18;
pcercuei 0:03b5121a232e 9818 val |= (cur[1] & 0x3f) << 12;
pcercuei 0:03b5121a232e 9819 val |= (cur[2] & 0x3f) << 6;
pcercuei 0:03b5121a232e 9820 val |= cur[3] & 0x3f;
pcercuei 0:03b5121a232e 9821 } else {
pcercuei 0:03b5121a232e 9822 /* 3-byte code */
pcercuei 0:03b5121a232e 9823 *len = 3;
pcercuei 0:03b5121a232e 9824 val = (cur[0] & 0xf) << 12;
pcercuei 0:03b5121a232e 9825 val |= (cur[1] & 0x3f) << 6;
pcercuei 0:03b5121a232e 9826 val |= cur[2] & 0x3f;
pcercuei 0:03b5121a232e 9827 }
pcercuei 0:03b5121a232e 9828 } else {
pcercuei 0:03b5121a232e 9829 /* 2-byte code */
pcercuei 0:03b5121a232e 9830 *len = 2;
pcercuei 0:03b5121a232e 9831 val = (cur[0] & 0x1f) << 6;
pcercuei 0:03b5121a232e 9832 val |= cur[1] & 0x3f;
pcercuei 0:03b5121a232e 9833 }
pcercuei 0:03b5121a232e 9834 if (!IS_CHAR(val)) {
pcercuei 0:03b5121a232e 9835 XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
pcercuei 0:03b5121a232e 9836 }
pcercuei 0:03b5121a232e 9837 return(val);
pcercuei 0:03b5121a232e 9838 } else {
pcercuei 0:03b5121a232e 9839 /* 1-byte code */
pcercuei 0:03b5121a232e 9840 *len = 1;
pcercuei 0:03b5121a232e 9841 return((int) *cur);
pcercuei 0:03b5121a232e 9842 }
pcercuei 0:03b5121a232e 9843 encoding_error:
pcercuei 0:03b5121a232e 9844 /*
pcercuei 0:03b5121a232e 9845 * If we detect an UTF8 error that probably means that the
pcercuei 0:03b5121a232e 9846 * input encoding didn't get properly advertised in the
pcercuei 0:03b5121a232e 9847 * declaration header. Report the error and switch the encoding
pcercuei 0:03b5121a232e 9848 * to ISO-Latin-1 (if you don't like this policy, just declare the
pcercuei 0:03b5121a232e 9849 * encoding !)
pcercuei 0:03b5121a232e 9850 */
pcercuei 0:03b5121a232e 9851 *len = 0;
pcercuei 0:03b5121a232e 9852 XP_ERROR0(XPATH_ENCODING_ERROR);
pcercuei 0:03b5121a232e 9853 }
pcercuei 0:03b5121a232e 9854
pcercuei 0:03b5121a232e 9855 /**
pcercuei 0:03b5121a232e 9856 * xmlXPathParseNCName:
pcercuei 0:03b5121a232e 9857 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9858 *
pcercuei 0:03b5121a232e 9859 * parse an XML namespace non qualified name.
pcercuei 0:03b5121a232e 9860 *
pcercuei 0:03b5121a232e 9861 * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
pcercuei 0:03b5121a232e 9862 *
pcercuei 0:03b5121a232e 9863 * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
pcercuei 0:03b5121a232e 9864 * CombiningChar | Extender
pcercuei 0:03b5121a232e 9865 *
pcercuei 0:03b5121a232e 9866 * Returns the namespace name or NULL
pcercuei 0:03b5121a232e 9867 */
pcercuei 0:03b5121a232e 9868
pcercuei 0:03b5121a232e 9869 xmlChar *
pcercuei 0:03b5121a232e 9870 xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 9871 const xmlChar *in;
pcercuei 0:03b5121a232e 9872 xmlChar *ret;
pcercuei 0:03b5121a232e 9873 int count = 0;
pcercuei 0:03b5121a232e 9874
pcercuei 0:03b5121a232e 9875 if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
pcercuei 0:03b5121a232e 9876 /*
pcercuei 0:03b5121a232e 9877 * Accelerator for simple ASCII names
pcercuei 0:03b5121a232e 9878 */
pcercuei 0:03b5121a232e 9879 in = ctxt->cur;
pcercuei 0:03b5121a232e 9880 if (((*in >= 0x61) && (*in <= 0x7A)) ||
pcercuei 0:03b5121a232e 9881 ((*in >= 0x41) && (*in <= 0x5A)) ||
pcercuei 0:03b5121a232e 9882 (*in == '_')) {
pcercuei 0:03b5121a232e 9883 in++;
pcercuei 0:03b5121a232e 9884 while (((*in >= 0x61) && (*in <= 0x7A)) ||
pcercuei 0:03b5121a232e 9885 ((*in >= 0x41) && (*in <= 0x5A)) ||
pcercuei 0:03b5121a232e 9886 ((*in >= 0x30) && (*in <= 0x39)) ||
pcercuei 0:03b5121a232e 9887 (*in == '_') || (*in == '.') ||
pcercuei 0:03b5121a232e 9888 (*in == '-'))
pcercuei 0:03b5121a232e 9889 in++;
pcercuei 0:03b5121a232e 9890 if ((*in == ' ') || (*in == '>') || (*in == '/') ||
pcercuei 0:03b5121a232e 9891 (*in == '[') || (*in == ']') || (*in == ':') ||
pcercuei 0:03b5121a232e 9892 (*in == '@') || (*in == '*')) {
pcercuei 0:03b5121a232e 9893 count = in - ctxt->cur;
pcercuei 0:03b5121a232e 9894 if (count == 0)
pcercuei 0:03b5121a232e 9895 return(NULL);
pcercuei 0:03b5121a232e 9896 ret = xmlStrndup(ctxt->cur, count);
pcercuei 0:03b5121a232e 9897 ctxt->cur = in;
pcercuei 0:03b5121a232e 9898 return(ret);
pcercuei 0:03b5121a232e 9899 }
pcercuei 0:03b5121a232e 9900 }
pcercuei 0:03b5121a232e 9901 return(xmlXPathParseNameComplex(ctxt, 0));
pcercuei 0:03b5121a232e 9902 }
pcercuei 0:03b5121a232e 9903
pcercuei 0:03b5121a232e 9904
pcercuei 0:03b5121a232e 9905 /**
pcercuei 0:03b5121a232e 9906 * xmlXPathParseQName:
pcercuei 0:03b5121a232e 9907 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9908 * @prefix: a xmlChar **
pcercuei 0:03b5121a232e 9909 *
pcercuei 0:03b5121a232e 9910 * parse an XML qualified name
pcercuei 0:03b5121a232e 9911 *
pcercuei 0:03b5121a232e 9912 * [NS 5] QName ::= (Prefix ':')? LocalPart
pcercuei 0:03b5121a232e 9913 *
pcercuei 0:03b5121a232e 9914 * [NS 6] Prefix ::= NCName
pcercuei 0:03b5121a232e 9915 *
pcercuei 0:03b5121a232e 9916 * [NS 7] LocalPart ::= NCName
pcercuei 0:03b5121a232e 9917 *
pcercuei 0:03b5121a232e 9918 * Returns the function returns the local part, and prefix is updated
pcercuei 0:03b5121a232e 9919 * to get the Prefix if any.
pcercuei 0:03b5121a232e 9920 */
pcercuei 0:03b5121a232e 9921
pcercuei 0:03b5121a232e 9922 static xmlChar *
pcercuei 0:03b5121a232e 9923 xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
pcercuei 0:03b5121a232e 9924 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 9925
pcercuei 0:03b5121a232e 9926 *prefix = NULL;
pcercuei 0:03b5121a232e 9927 ret = xmlXPathParseNCName(ctxt);
pcercuei 0:03b5121a232e 9928 if (ret && CUR == ':') {
pcercuei 0:03b5121a232e 9929 *prefix = ret;
pcercuei 0:03b5121a232e 9930 NEXT;
pcercuei 0:03b5121a232e 9931 ret = xmlXPathParseNCName(ctxt);
pcercuei 0:03b5121a232e 9932 }
pcercuei 0:03b5121a232e 9933 return(ret);
pcercuei 0:03b5121a232e 9934 }
pcercuei 0:03b5121a232e 9935
pcercuei 0:03b5121a232e 9936 /**
pcercuei 0:03b5121a232e 9937 * xmlXPathParseName:
pcercuei 0:03b5121a232e 9938 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 9939 *
pcercuei 0:03b5121a232e 9940 * parse an XML name
pcercuei 0:03b5121a232e 9941 *
pcercuei 0:03b5121a232e 9942 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
pcercuei 0:03b5121a232e 9943 * CombiningChar | Extender
pcercuei 0:03b5121a232e 9944 *
pcercuei 0:03b5121a232e 9945 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
pcercuei 0:03b5121a232e 9946 *
pcercuei 0:03b5121a232e 9947 * Returns the namespace name or NULL
pcercuei 0:03b5121a232e 9948 */
pcercuei 0:03b5121a232e 9949
pcercuei 0:03b5121a232e 9950 xmlChar *
pcercuei 0:03b5121a232e 9951 xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 9952 const xmlChar *in;
pcercuei 0:03b5121a232e 9953 xmlChar *ret;
pcercuei 0:03b5121a232e 9954 size_t count = 0;
pcercuei 0:03b5121a232e 9955
pcercuei 0:03b5121a232e 9956 if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
pcercuei 0:03b5121a232e 9957 /*
pcercuei 0:03b5121a232e 9958 * Accelerator for simple ASCII names
pcercuei 0:03b5121a232e 9959 */
pcercuei 0:03b5121a232e 9960 in = ctxt->cur;
pcercuei 0:03b5121a232e 9961 if (((*in >= 0x61) && (*in <= 0x7A)) ||
pcercuei 0:03b5121a232e 9962 ((*in >= 0x41) && (*in <= 0x5A)) ||
pcercuei 0:03b5121a232e 9963 (*in == '_') || (*in == ':')) {
pcercuei 0:03b5121a232e 9964 in++;
pcercuei 0:03b5121a232e 9965 while (((*in >= 0x61) && (*in <= 0x7A)) ||
pcercuei 0:03b5121a232e 9966 ((*in >= 0x41) && (*in <= 0x5A)) ||
pcercuei 0:03b5121a232e 9967 ((*in >= 0x30) && (*in <= 0x39)) ||
pcercuei 0:03b5121a232e 9968 (*in == '_') || (*in == '-') ||
pcercuei 0:03b5121a232e 9969 (*in == ':') || (*in == '.'))
pcercuei 0:03b5121a232e 9970 in++;
pcercuei 0:03b5121a232e 9971 if ((*in > 0) && (*in < 0x80)) {
pcercuei 0:03b5121a232e 9972 count = in - ctxt->cur;
pcercuei 0:03b5121a232e 9973 if (count > XML_MAX_NAME_LENGTH) {
pcercuei 0:03b5121a232e 9974 ctxt->cur = in;
pcercuei 0:03b5121a232e 9975 XP_ERRORNULL(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 9976 }
pcercuei 0:03b5121a232e 9977 ret = xmlStrndup(ctxt->cur, count);
pcercuei 0:03b5121a232e 9978 ctxt->cur = in;
pcercuei 0:03b5121a232e 9979 return(ret);
pcercuei 0:03b5121a232e 9980 }
pcercuei 0:03b5121a232e 9981 }
pcercuei 0:03b5121a232e 9982 return(xmlXPathParseNameComplex(ctxt, 1));
pcercuei 0:03b5121a232e 9983 }
pcercuei 0:03b5121a232e 9984
pcercuei 0:03b5121a232e 9985 static xmlChar *
pcercuei 0:03b5121a232e 9986 xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
pcercuei 0:03b5121a232e 9987 xmlChar buf[XML_MAX_NAMELEN + 5];
pcercuei 0:03b5121a232e 9988 int len = 0, l;
pcercuei 0:03b5121a232e 9989 int c;
pcercuei 0:03b5121a232e 9990
pcercuei 0:03b5121a232e 9991 /*
pcercuei 0:03b5121a232e 9992 * Handler for more complex cases
pcercuei 0:03b5121a232e 9993 */
pcercuei 0:03b5121a232e 9994 c = CUR_CHAR(l);
pcercuei 0:03b5121a232e 9995 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
pcercuei 0:03b5121a232e 9996 (c == '[') || (c == ']') || (c == '@') || /* accelerators */
pcercuei 0:03b5121a232e 9997 (c == '*') || /* accelerators */
pcercuei 0:03b5121a232e 9998 (!IS_LETTER(c) && (c != '_') &&
pcercuei 0:03b5121a232e 9999 ((qualified) && (c != ':')))) {
pcercuei 0:03b5121a232e 10000 return(NULL);
pcercuei 0:03b5121a232e 10001 }
pcercuei 0:03b5121a232e 10002
pcercuei 0:03b5121a232e 10003 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
pcercuei 0:03b5121a232e 10004 ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
pcercuei 0:03b5121a232e 10005 (c == '.') || (c == '-') ||
pcercuei 0:03b5121a232e 10006 (c == '_') || ((qualified) && (c == ':')) ||
pcercuei 0:03b5121a232e 10007 (IS_COMBINING(c)) ||
pcercuei 0:03b5121a232e 10008 (IS_EXTENDER(c)))) {
pcercuei 0:03b5121a232e 10009 COPY_BUF(l,buf,len,c);
pcercuei 0:03b5121a232e 10010 NEXTL(l);
pcercuei 0:03b5121a232e 10011 c = CUR_CHAR(l);
pcercuei 0:03b5121a232e 10012 if (len >= XML_MAX_NAMELEN) {
pcercuei 0:03b5121a232e 10013 /*
pcercuei 0:03b5121a232e 10014 * Okay someone managed to make a huge name, so he's ready to pay
pcercuei 0:03b5121a232e 10015 * for the processing speed.
pcercuei 0:03b5121a232e 10016 */
pcercuei 0:03b5121a232e 10017 xmlChar *buffer;
pcercuei 0:03b5121a232e 10018 int max = len * 2;
pcercuei 0:03b5121a232e 10019
pcercuei 0:03b5121a232e 10020 if (len > XML_MAX_NAME_LENGTH) {
pcercuei 0:03b5121a232e 10021 XP_ERRORNULL(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10022 }
pcercuei 0:03b5121a232e 10023 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
pcercuei 0:03b5121a232e 10024 if (buffer == NULL) {
pcercuei 0:03b5121a232e 10025 XP_ERRORNULL(XPATH_MEMORY_ERROR);
pcercuei 0:03b5121a232e 10026 }
pcercuei 0:03b5121a232e 10027 memcpy(buffer, buf, len);
pcercuei 0:03b5121a232e 10028 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
pcercuei 0:03b5121a232e 10029 (c == '.') || (c == '-') ||
pcercuei 0:03b5121a232e 10030 (c == '_') || ((qualified) && (c == ':')) ||
pcercuei 0:03b5121a232e 10031 (IS_COMBINING(c)) ||
pcercuei 0:03b5121a232e 10032 (IS_EXTENDER(c))) {
pcercuei 0:03b5121a232e 10033 if (len + 10 > max) {
pcercuei 0:03b5121a232e 10034 if (max > XML_MAX_NAME_LENGTH) {
pcercuei 0:03b5121a232e 10035 XP_ERRORNULL(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10036 }
pcercuei 0:03b5121a232e 10037 max *= 2;
pcercuei 0:03b5121a232e 10038 buffer = (xmlChar *) xmlRealloc(buffer,
pcercuei 0:03b5121a232e 10039 max * sizeof(xmlChar));
pcercuei 0:03b5121a232e 10040 if (buffer == NULL) {
pcercuei 0:03b5121a232e 10041 XP_ERRORNULL(XPATH_MEMORY_ERROR);
pcercuei 0:03b5121a232e 10042 }
pcercuei 0:03b5121a232e 10043 }
pcercuei 0:03b5121a232e 10044 COPY_BUF(l,buffer,len,c);
pcercuei 0:03b5121a232e 10045 NEXTL(l);
pcercuei 0:03b5121a232e 10046 c = CUR_CHAR(l);
pcercuei 0:03b5121a232e 10047 }
pcercuei 0:03b5121a232e 10048 buffer[len] = 0;
pcercuei 0:03b5121a232e 10049 return(buffer);
pcercuei 0:03b5121a232e 10050 }
pcercuei 0:03b5121a232e 10051 }
pcercuei 0:03b5121a232e 10052 if (len == 0)
pcercuei 0:03b5121a232e 10053 return(NULL);
pcercuei 0:03b5121a232e 10054 return(xmlStrndup(buf, len));
pcercuei 0:03b5121a232e 10055 }
pcercuei 0:03b5121a232e 10056
pcercuei 0:03b5121a232e 10057 #define MAX_FRAC 20
pcercuei 0:03b5121a232e 10058
pcercuei 0:03b5121a232e 10059 /*
pcercuei 0:03b5121a232e 10060 * These are used as divisors for the fractional part of a number.
pcercuei 0:03b5121a232e 10061 * Since the table includes 1.0 (representing '0' fractional digits),
pcercuei 0:03b5121a232e 10062 * it must be dimensioned at MAX_FRAC+1 (bug 133921)
pcercuei 0:03b5121a232e 10063 */
pcercuei 0:03b5121a232e 10064 static double my_pow10[MAX_FRAC+1] = {
pcercuei 0:03b5121a232e 10065 1.0, 10.0, 100.0, 1000.0, 10000.0,
pcercuei 0:03b5121a232e 10066 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
pcercuei 0:03b5121a232e 10067 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
pcercuei 0:03b5121a232e 10068 100000000000000.0,
pcercuei 0:03b5121a232e 10069 1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
pcercuei 0:03b5121a232e 10070 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0
pcercuei 0:03b5121a232e 10071 };
pcercuei 0:03b5121a232e 10072
pcercuei 0:03b5121a232e 10073 /**
pcercuei 0:03b5121a232e 10074 * xmlXPathStringEvalNumber:
pcercuei 0:03b5121a232e 10075 * @str: A string to scan
pcercuei 0:03b5121a232e 10076 *
pcercuei 0:03b5121a232e 10077 * [30a] Float ::= Number ('e' Digits?)?
pcercuei 0:03b5121a232e 10078 *
pcercuei 0:03b5121a232e 10079 * [30] Number ::= Digits ('.' Digits?)?
pcercuei 0:03b5121a232e 10080 * | '.' Digits
pcercuei 0:03b5121a232e 10081 * [31] Digits ::= [0-9]+
pcercuei 0:03b5121a232e 10082 *
pcercuei 0:03b5121a232e 10083 * Compile a Number in the string
pcercuei 0:03b5121a232e 10084 * In complement of the Number expression, this function also handles
pcercuei 0:03b5121a232e 10085 * negative values : '-' Number.
pcercuei 0:03b5121a232e 10086 *
pcercuei 0:03b5121a232e 10087 * Returns the double value.
pcercuei 0:03b5121a232e 10088 */
pcercuei 0:03b5121a232e 10089 double
pcercuei 0:03b5121a232e 10090 xmlXPathStringEvalNumber(const xmlChar *str) {
pcercuei 0:03b5121a232e 10091 const xmlChar *cur = str;
pcercuei 0:03b5121a232e 10092 double ret;
pcercuei 0:03b5121a232e 10093 int ok = 0;
pcercuei 0:03b5121a232e 10094 int isneg = 0;
pcercuei 0:03b5121a232e 10095 int exponent = 0;
pcercuei 0:03b5121a232e 10096 int is_exponent_negative = 0;
pcercuei 0:03b5121a232e 10097 #ifdef __GNUC__
pcercuei 0:03b5121a232e 10098 unsigned long tmp = 0;
pcercuei 0:03b5121a232e 10099 double temp;
pcercuei 0:03b5121a232e 10100 #endif
pcercuei 0:03b5121a232e 10101 if (cur == NULL) return(0);
pcercuei 0:03b5121a232e 10102 while (IS_BLANK_CH(*cur)) cur++;
pcercuei 0:03b5121a232e 10103 if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
pcercuei 0:03b5121a232e 10104 return(xmlXPathNAN);
pcercuei 0:03b5121a232e 10105 }
pcercuei 0:03b5121a232e 10106 if (*cur == '-') {
pcercuei 0:03b5121a232e 10107 isneg = 1;
pcercuei 0:03b5121a232e 10108 cur++;
pcercuei 0:03b5121a232e 10109 }
pcercuei 0:03b5121a232e 10110
pcercuei 0:03b5121a232e 10111 #ifdef __GNUC__
pcercuei 0:03b5121a232e 10112 /*
pcercuei 0:03b5121a232e 10113 * tmp/temp is a workaround against a gcc compiler bug
pcercuei 0:03b5121a232e 10114 * http://veillard.com/gcc.bug
pcercuei 0:03b5121a232e 10115 */
pcercuei 0:03b5121a232e 10116 ret = 0;
pcercuei 0:03b5121a232e 10117 while ((*cur >= '0') && (*cur <= '9')) {
pcercuei 0:03b5121a232e 10118 ret = ret * 10;
pcercuei 0:03b5121a232e 10119 tmp = (*cur - '0');
pcercuei 0:03b5121a232e 10120 ok = 1;
pcercuei 0:03b5121a232e 10121 cur++;
pcercuei 0:03b5121a232e 10122 temp = (double) tmp;
pcercuei 0:03b5121a232e 10123 ret = ret + temp;
pcercuei 0:03b5121a232e 10124 }
pcercuei 0:03b5121a232e 10125 #else
pcercuei 0:03b5121a232e 10126 ret = 0;
pcercuei 0:03b5121a232e 10127 while ((*cur >= '0') && (*cur <= '9')) {
pcercuei 0:03b5121a232e 10128 ret = ret * 10 + (*cur - '0');
pcercuei 0:03b5121a232e 10129 ok = 1;
pcercuei 0:03b5121a232e 10130 cur++;
pcercuei 0:03b5121a232e 10131 }
pcercuei 0:03b5121a232e 10132 #endif
pcercuei 0:03b5121a232e 10133
pcercuei 0:03b5121a232e 10134 if (*cur == '.') {
pcercuei 0:03b5121a232e 10135 int v, frac = 0;
pcercuei 0:03b5121a232e 10136 double fraction = 0;
pcercuei 0:03b5121a232e 10137
pcercuei 0:03b5121a232e 10138 cur++;
pcercuei 0:03b5121a232e 10139 if (((*cur < '0') || (*cur > '9')) && (!ok)) {
pcercuei 0:03b5121a232e 10140 return(xmlXPathNAN);
pcercuei 0:03b5121a232e 10141 }
pcercuei 0:03b5121a232e 10142 while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
pcercuei 0:03b5121a232e 10143 v = (*cur - '0');
pcercuei 0:03b5121a232e 10144 fraction = fraction * 10 + v;
pcercuei 0:03b5121a232e 10145 frac = frac + 1;
pcercuei 0:03b5121a232e 10146 cur++;
pcercuei 0:03b5121a232e 10147 }
pcercuei 0:03b5121a232e 10148 fraction /= my_pow10[frac];
pcercuei 0:03b5121a232e 10149 ret = ret + fraction;
pcercuei 0:03b5121a232e 10150 while ((*cur >= '0') && (*cur <= '9'))
pcercuei 0:03b5121a232e 10151 cur++;
pcercuei 0:03b5121a232e 10152 }
pcercuei 0:03b5121a232e 10153 if ((*cur == 'e') || (*cur == 'E')) {
pcercuei 0:03b5121a232e 10154 cur++;
pcercuei 0:03b5121a232e 10155 if (*cur == '-') {
pcercuei 0:03b5121a232e 10156 is_exponent_negative = 1;
pcercuei 0:03b5121a232e 10157 cur++;
pcercuei 0:03b5121a232e 10158 } else if (*cur == '+') {
pcercuei 0:03b5121a232e 10159 cur++;
pcercuei 0:03b5121a232e 10160 }
pcercuei 0:03b5121a232e 10161 while ((*cur >= '0') && (*cur <= '9')) {
pcercuei 0:03b5121a232e 10162 exponent = exponent * 10 + (*cur - '0');
pcercuei 0:03b5121a232e 10163 cur++;
pcercuei 0:03b5121a232e 10164 }
pcercuei 0:03b5121a232e 10165 }
pcercuei 0:03b5121a232e 10166 while (IS_BLANK_CH(*cur)) cur++;
pcercuei 0:03b5121a232e 10167 if (*cur != 0) return(xmlXPathNAN);
pcercuei 0:03b5121a232e 10168 if (isneg) ret = -ret;
pcercuei 0:03b5121a232e 10169 if (is_exponent_negative) exponent = -exponent;
pcercuei 0:03b5121a232e 10170 ret *= pow(10.0, (double)exponent);
pcercuei 0:03b5121a232e 10171 return(ret);
pcercuei 0:03b5121a232e 10172 }
pcercuei 0:03b5121a232e 10173
pcercuei 0:03b5121a232e 10174 /**
pcercuei 0:03b5121a232e 10175 * xmlXPathCompNumber:
pcercuei 0:03b5121a232e 10176 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10177 *
pcercuei 0:03b5121a232e 10178 * [30] Number ::= Digits ('.' Digits?)?
pcercuei 0:03b5121a232e 10179 * | '.' Digits
pcercuei 0:03b5121a232e 10180 * [31] Digits ::= [0-9]+
pcercuei 0:03b5121a232e 10181 *
pcercuei 0:03b5121a232e 10182 * Compile a Number, then push it on the stack
pcercuei 0:03b5121a232e 10183 *
pcercuei 0:03b5121a232e 10184 */
pcercuei 0:03b5121a232e 10185 static void
pcercuei 0:03b5121a232e 10186 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
pcercuei 0:03b5121a232e 10187 {
pcercuei 0:03b5121a232e 10188 double ret = 0.0;
pcercuei 0:03b5121a232e 10189 int ok = 0;
pcercuei 0:03b5121a232e 10190 int exponent = 0;
pcercuei 0:03b5121a232e 10191 int is_exponent_negative = 0;
pcercuei 0:03b5121a232e 10192 #ifdef __GNUC__
pcercuei 0:03b5121a232e 10193 unsigned long tmp = 0;
pcercuei 0:03b5121a232e 10194 double temp;
pcercuei 0:03b5121a232e 10195 #endif
pcercuei 0:03b5121a232e 10196
pcercuei 0:03b5121a232e 10197 CHECK_ERROR;
pcercuei 0:03b5121a232e 10198 if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
pcercuei 0:03b5121a232e 10199 XP_ERROR(XPATH_NUMBER_ERROR);
pcercuei 0:03b5121a232e 10200 }
pcercuei 0:03b5121a232e 10201 #ifdef __GNUC__
pcercuei 0:03b5121a232e 10202 /*
pcercuei 0:03b5121a232e 10203 * tmp/temp is a workaround against a gcc compiler bug
pcercuei 0:03b5121a232e 10204 * http://veillard.com/gcc.bug
pcercuei 0:03b5121a232e 10205 */
pcercuei 0:03b5121a232e 10206 ret = 0;
pcercuei 0:03b5121a232e 10207 while ((CUR >= '0') && (CUR <= '9')) {
pcercuei 0:03b5121a232e 10208 ret = ret * 10;
pcercuei 0:03b5121a232e 10209 tmp = (CUR - '0');
pcercuei 0:03b5121a232e 10210 ok = 1;
pcercuei 0:03b5121a232e 10211 NEXT;
pcercuei 0:03b5121a232e 10212 temp = (double) tmp;
pcercuei 0:03b5121a232e 10213 ret = ret + temp;
pcercuei 0:03b5121a232e 10214 }
pcercuei 0:03b5121a232e 10215 #else
pcercuei 0:03b5121a232e 10216 ret = 0;
pcercuei 0:03b5121a232e 10217 while ((CUR >= '0') && (CUR <= '9')) {
pcercuei 0:03b5121a232e 10218 ret = ret * 10 + (CUR - '0');
pcercuei 0:03b5121a232e 10219 ok = 1;
pcercuei 0:03b5121a232e 10220 NEXT;
pcercuei 0:03b5121a232e 10221 }
pcercuei 0:03b5121a232e 10222 #endif
pcercuei 0:03b5121a232e 10223 if (CUR == '.') {
pcercuei 0:03b5121a232e 10224 int v, frac = 0;
pcercuei 0:03b5121a232e 10225 double fraction = 0;
pcercuei 0:03b5121a232e 10226
pcercuei 0:03b5121a232e 10227 NEXT;
pcercuei 0:03b5121a232e 10228 if (((CUR < '0') || (CUR > '9')) && (!ok)) {
pcercuei 0:03b5121a232e 10229 XP_ERROR(XPATH_NUMBER_ERROR);
pcercuei 0:03b5121a232e 10230 }
pcercuei 0:03b5121a232e 10231 while ((CUR >= '0') && (CUR <= '9') && (frac < MAX_FRAC)) {
pcercuei 0:03b5121a232e 10232 v = (CUR - '0');
pcercuei 0:03b5121a232e 10233 fraction = fraction * 10 + v;
pcercuei 0:03b5121a232e 10234 frac = frac + 1;
pcercuei 0:03b5121a232e 10235 NEXT;
pcercuei 0:03b5121a232e 10236 }
pcercuei 0:03b5121a232e 10237 fraction /= my_pow10[frac];
pcercuei 0:03b5121a232e 10238 ret = ret + fraction;
pcercuei 0:03b5121a232e 10239 while ((CUR >= '0') && (CUR <= '9'))
pcercuei 0:03b5121a232e 10240 NEXT;
pcercuei 0:03b5121a232e 10241 }
pcercuei 0:03b5121a232e 10242 if ((CUR == 'e') || (CUR == 'E')) {
pcercuei 0:03b5121a232e 10243 NEXT;
pcercuei 0:03b5121a232e 10244 if (CUR == '-') {
pcercuei 0:03b5121a232e 10245 is_exponent_negative = 1;
pcercuei 0:03b5121a232e 10246 NEXT;
pcercuei 0:03b5121a232e 10247 } else if (CUR == '+') {
pcercuei 0:03b5121a232e 10248 NEXT;
pcercuei 0:03b5121a232e 10249 }
pcercuei 0:03b5121a232e 10250 while ((CUR >= '0') && (CUR <= '9')) {
pcercuei 0:03b5121a232e 10251 exponent = exponent * 10 + (CUR - '0');
pcercuei 0:03b5121a232e 10252 NEXT;
pcercuei 0:03b5121a232e 10253 }
pcercuei 0:03b5121a232e 10254 if (is_exponent_negative)
pcercuei 0:03b5121a232e 10255 exponent = -exponent;
pcercuei 0:03b5121a232e 10256 ret *= pow(10.0, (double) exponent);
pcercuei 0:03b5121a232e 10257 }
pcercuei 0:03b5121a232e 10258 PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
pcercuei 0:03b5121a232e 10259 xmlXPathCacheNewFloat(ctxt->context, ret), NULL);
pcercuei 0:03b5121a232e 10260 }
pcercuei 0:03b5121a232e 10261
pcercuei 0:03b5121a232e 10262 /**
pcercuei 0:03b5121a232e 10263 * xmlXPathParseLiteral:
pcercuei 0:03b5121a232e 10264 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10265 *
pcercuei 0:03b5121a232e 10266 * Parse a Literal
pcercuei 0:03b5121a232e 10267 *
pcercuei 0:03b5121a232e 10268 * [29] Literal ::= '"' [^"]* '"'
pcercuei 0:03b5121a232e 10269 * | "'" [^']* "'"
pcercuei 0:03b5121a232e 10270 *
pcercuei 0:03b5121a232e 10271 * Returns the value found or NULL in case of error
pcercuei 0:03b5121a232e 10272 */
pcercuei 0:03b5121a232e 10273 static xmlChar *
pcercuei 0:03b5121a232e 10274 xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10275 const xmlChar *q;
pcercuei 0:03b5121a232e 10276 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 10277
pcercuei 0:03b5121a232e 10278 if (CUR == '"') {
pcercuei 0:03b5121a232e 10279 NEXT;
pcercuei 0:03b5121a232e 10280 q = CUR_PTR;
pcercuei 0:03b5121a232e 10281 while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
pcercuei 0:03b5121a232e 10282 NEXT;
pcercuei 0:03b5121a232e 10283 if (!IS_CHAR_CH(CUR)) {
pcercuei 0:03b5121a232e 10284 XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
pcercuei 0:03b5121a232e 10285 } else {
pcercuei 0:03b5121a232e 10286 ret = xmlStrndup(q, CUR_PTR - q);
pcercuei 0:03b5121a232e 10287 NEXT;
pcercuei 0:03b5121a232e 10288 }
pcercuei 0:03b5121a232e 10289 } else if (CUR == '\'') {
pcercuei 0:03b5121a232e 10290 NEXT;
pcercuei 0:03b5121a232e 10291 q = CUR_PTR;
pcercuei 0:03b5121a232e 10292 while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
pcercuei 0:03b5121a232e 10293 NEXT;
pcercuei 0:03b5121a232e 10294 if (!IS_CHAR_CH(CUR)) {
pcercuei 0:03b5121a232e 10295 XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
pcercuei 0:03b5121a232e 10296 } else {
pcercuei 0:03b5121a232e 10297 ret = xmlStrndup(q, CUR_PTR - q);
pcercuei 0:03b5121a232e 10298 NEXT;
pcercuei 0:03b5121a232e 10299 }
pcercuei 0:03b5121a232e 10300 } else {
pcercuei 0:03b5121a232e 10301 XP_ERRORNULL(XPATH_START_LITERAL_ERROR);
pcercuei 0:03b5121a232e 10302 }
pcercuei 0:03b5121a232e 10303 return(ret);
pcercuei 0:03b5121a232e 10304 }
pcercuei 0:03b5121a232e 10305
pcercuei 0:03b5121a232e 10306 /**
pcercuei 0:03b5121a232e 10307 * xmlXPathCompLiteral:
pcercuei 0:03b5121a232e 10308 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10309 *
pcercuei 0:03b5121a232e 10310 * Parse a Literal and push it on the stack.
pcercuei 0:03b5121a232e 10311 *
pcercuei 0:03b5121a232e 10312 * [29] Literal ::= '"' [^"]* '"'
pcercuei 0:03b5121a232e 10313 * | "'" [^']* "'"
pcercuei 0:03b5121a232e 10314 *
pcercuei 0:03b5121a232e 10315 * TODO: xmlXPathCompLiteral memory allocation could be improved.
pcercuei 0:03b5121a232e 10316 */
pcercuei 0:03b5121a232e 10317 static void
pcercuei 0:03b5121a232e 10318 xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10319 const xmlChar *q;
pcercuei 0:03b5121a232e 10320 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 10321
pcercuei 0:03b5121a232e 10322 if (CUR == '"') {
pcercuei 0:03b5121a232e 10323 NEXT;
pcercuei 0:03b5121a232e 10324 q = CUR_PTR;
pcercuei 0:03b5121a232e 10325 while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
pcercuei 0:03b5121a232e 10326 NEXT;
pcercuei 0:03b5121a232e 10327 if (!IS_CHAR_CH(CUR)) {
pcercuei 0:03b5121a232e 10328 XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
pcercuei 0:03b5121a232e 10329 } else {
pcercuei 0:03b5121a232e 10330 ret = xmlStrndup(q, CUR_PTR - q);
pcercuei 0:03b5121a232e 10331 NEXT;
pcercuei 0:03b5121a232e 10332 }
pcercuei 0:03b5121a232e 10333 } else if (CUR == '\'') {
pcercuei 0:03b5121a232e 10334 NEXT;
pcercuei 0:03b5121a232e 10335 q = CUR_PTR;
pcercuei 0:03b5121a232e 10336 while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
pcercuei 0:03b5121a232e 10337 NEXT;
pcercuei 0:03b5121a232e 10338 if (!IS_CHAR_CH(CUR)) {
pcercuei 0:03b5121a232e 10339 XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
pcercuei 0:03b5121a232e 10340 } else {
pcercuei 0:03b5121a232e 10341 ret = xmlStrndup(q, CUR_PTR - q);
pcercuei 0:03b5121a232e 10342 NEXT;
pcercuei 0:03b5121a232e 10343 }
pcercuei 0:03b5121a232e 10344 } else {
pcercuei 0:03b5121a232e 10345 XP_ERROR(XPATH_START_LITERAL_ERROR);
pcercuei 0:03b5121a232e 10346 }
pcercuei 0:03b5121a232e 10347 if (ret == NULL) return;
pcercuei 0:03b5121a232e 10348 PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
pcercuei 0:03b5121a232e 10349 xmlXPathCacheNewString(ctxt->context, ret), NULL);
pcercuei 0:03b5121a232e 10350 xmlFree(ret);
pcercuei 0:03b5121a232e 10351 }
pcercuei 0:03b5121a232e 10352
pcercuei 0:03b5121a232e 10353 /**
pcercuei 0:03b5121a232e 10354 * xmlXPathCompVariableReference:
pcercuei 0:03b5121a232e 10355 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10356 *
pcercuei 0:03b5121a232e 10357 * Parse a VariableReference, evaluate it and push it on the stack.
pcercuei 0:03b5121a232e 10358 *
pcercuei 0:03b5121a232e 10359 * The variable bindings consist of a mapping from variable names
pcercuei 0:03b5121a232e 10360 * to variable values. The value of a variable is an object, which can be
pcercuei 0:03b5121a232e 10361 * of any of the types that are possible for the value of an expression,
pcercuei 0:03b5121a232e 10362 * and may also be of additional types not specified here.
pcercuei 0:03b5121a232e 10363 *
pcercuei 0:03b5121a232e 10364 * Early evaluation is possible since:
pcercuei 0:03b5121a232e 10365 * The variable bindings [...] used to evaluate a subexpression are
pcercuei 0:03b5121a232e 10366 * always the same as those used to evaluate the containing expression.
pcercuei 0:03b5121a232e 10367 *
pcercuei 0:03b5121a232e 10368 * [36] VariableReference ::= '$' QName
pcercuei 0:03b5121a232e 10369 */
pcercuei 0:03b5121a232e 10370 static void
pcercuei 0:03b5121a232e 10371 xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10372 xmlChar *name;
pcercuei 0:03b5121a232e 10373 xmlChar *prefix;
pcercuei 0:03b5121a232e 10374
pcercuei 0:03b5121a232e 10375 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10376 if (CUR != '$') {
pcercuei 0:03b5121a232e 10377 XP_ERROR(XPATH_VARIABLE_REF_ERROR);
pcercuei 0:03b5121a232e 10378 }
pcercuei 0:03b5121a232e 10379 NEXT;
pcercuei 0:03b5121a232e 10380 name = xmlXPathParseQName(ctxt, &prefix);
pcercuei 0:03b5121a232e 10381 if (name == NULL) {
pcercuei 0:03b5121a232e 10382 XP_ERROR(XPATH_VARIABLE_REF_ERROR);
pcercuei 0:03b5121a232e 10383 }
pcercuei 0:03b5121a232e 10384 ctxt->comp->last = -1;
pcercuei 0:03b5121a232e 10385 PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
pcercuei 0:03b5121a232e 10386 name, prefix);
pcercuei 0:03b5121a232e 10387 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10388 if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
pcercuei 0:03b5121a232e 10389 XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
pcercuei 0:03b5121a232e 10390 }
pcercuei 0:03b5121a232e 10391 }
pcercuei 0:03b5121a232e 10392
pcercuei 0:03b5121a232e 10393 /**
pcercuei 0:03b5121a232e 10394 * xmlXPathIsNodeType:
pcercuei 0:03b5121a232e 10395 * @name: a name string
pcercuei 0:03b5121a232e 10396 *
pcercuei 0:03b5121a232e 10397 * Is the name given a NodeType one.
pcercuei 0:03b5121a232e 10398 *
pcercuei 0:03b5121a232e 10399 * [38] NodeType ::= 'comment'
pcercuei 0:03b5121a232e 10400 * | 'text'
pcercuei 0:03b5121a232e 10401 * | 'processing-instruction'
pcercuei 0:03b5121a232e 10402 * | 'node'
pcercuei 0:03b5121a232e 10403 *
pcercuei 0:03b5121a232e 10404 * Returns 1 if true 0 otherwise
pcercuei 0:03b5121a232e 10405 */
pcercuei 0:03b5121a232e 10406 int
pcercuei 0:03b5121a232e 10407 xmlXPathIsNodeType(const xmlChar *name) {
pcercuei 0:03b5121a232e 10408 if (name == NULL)
pcercuei 0:03b5121a232e 10409 return(0);
pcercuei 0:03b5121a232e 10410
pcercuei 0:03b5121a232e 10411 if (xmlStrEqual(name, BAD_CAST "node"))
pcercuei 0:03b5121a232e 10412 return(1);
pcercuei 0:03b5121a232e 10413 if (xmlStrEqual(name, BAD_CAST "text"))
pcercuei 0:03b5121a232e 10414 return(1);
pcercuei 0:03b5121a232e 10415 if (xmlStrEqual(name, BAD_CAST "comment"))
pcercuei 0:03b5121a232e 10416 return(1);
pcercuei 0:03b5121a232e 10417 if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
pcercuei 0:03b5121a232e 10418 return(1);
pcercuei 0:03b5121a232e 10419 return(0);
pcercuei 0:03b5121a232e 10420 }
pcercuei 0:03b5121a232e 10421
pcercuei 0:03b5121a232e 10422 /**
pcercuei 0:03b5121a232e 10423 * xmlXPathCompFunctionCall:
pcercuei 0:03b5121a232e 10424 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10425 *
pcercuei 0:03b5121a232e 10426 * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')'
pcercuei 0:03b5121a232e 10427 * [17] Argument ::= Expr
pcercuei 0:03b5121a232e 10428 *
pcercuei 0:03b5121a232e 10429 * Compile a function call, the evaluation of all arguments are
pcercuei 0:03b5121a232e 10430 * pushed on the stack
pcercuei 0:03b5121a232e 10431 */
pcercuei 0:03b5121a232e 10432 static void
pcercuei 0:03b5121a232e 10433 xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10434 xmlChar *name;
pcercuei 0:03b5121a232e 10435 xmlChar *prefix;
pcercuei 0:03b5121a232e 10436 int nbargs = 0;
pcercuei 0:03b5121a232e 10437 int sort = 1;
pcercuei 0:03b5121a232e 10438
pcercuei 0:03b5121a232e 10439 name = xmlXPathParseQName(ctxt, &prefix);
pcercuei 0:03b5121a232e 10440 if (name == NULL) {
pcercuei 0:03b5121a232e 10441 xmlFree(prefix);
pcercuei 0:03b5121a232e 10442 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10443 }
pcercuei 0:03b5121a232e 10444 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10445 #ifdef DEBUG_EXPR
pcercuei 0:03b5121a232e 10446 if (prefix == NULL)
pcercuei 0:03b5121a232e 10447 xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
pcercuei 0:03b5121a232e 10448 name);
pcercuei 0:03b5121a232e 10449 else
pcercuei 0:03b5121a232e 10450 xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
pcercuei 0:03b5121a232e 10451 prefix, name);
pcercuei 0:03b5121a232e 10452 #endif
pcercuei 0:03b5121a232e 10453
pcercuei 0:03b5121a232e 10454 if (CUR != '(') {
pcercuei 0:03b5121a232e 10455 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10456 }
pcercuei 0:03b5121a232e 10457 NEXT;
pcercuei 0:03b5121a232e 10458 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10459
pcercuei 0:03b5121a232e 10460 /*
pcercuei 0:03b5121a232e 10461 * Optimization for count(): we don't need the node-set to be sorted.
pcercuei 0:03b5121a232e 10462 */
pcercuei 0:03b5121a232e 10463 if ((prefix == NULL) && (name[0] == 'c') &&
pcercuei 0:03b5121a232e 10464 xmlStrEqual(name, BAD_CAST "count"))
pcercuei 0:03b5121a232e 10465 {
pcercuei 0:03b5121a232e 10466 sort = 0;
pcercuei 0:03b5121a232e 10467 }
pcercuei 0:03b5121a232e 10468 ctxt->comp->last = -1;
pcercuei 0:03b5121a232e 10469 if (CUR != ')') {
pcercuei 0:03b5121a232e 10470 while (CUR != 0) {
pcercuei 0:03b5121a232e 10471 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 10472 ctxt->comp->last = -1;
pcercuei 0:03b5121a232e 10473 xmlXPathCompileExpr(ctxt, sort);
pcercuei 0:03b5121a232e 10474 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 10475 xmlFree(name);
pcercuei 0:03b5121a232e 10476 xmlFree(prefix);
pcercuei 0:03b5121a232e 10477 return;
pcercuei 0:03b5121a232e 10478 }
pcercuei 0:03b5121a232e 10479 PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
pcercuei 0:03b5121a232e 10480 nbargs++;
pcercuei 0:03b5121a232e 10481 if (CUR == ')') break;
pcercuei 0:03b5121a232e 10482 if (CUR != ',') {
pcercuei 0:03b5121a232e 10483 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10484 }
pcercuei 0:03b5121a232e 10485 NEXT;
pcercuei 0:03b5121a232e 10486 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10487 }
pcercuei 0:03b5121a232e 10488 }
pcercuei 0:03b5121a232e 10489 PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
pcercuei 0:03b5121a232e 10490 name, prefix);
pcercuei 0:03b5121a232e 10491 NEXT;
pcercuei 0:03b5121a232e 10492 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10493 }
pcercuei 0:03b5121a232e 10494
pcercuei 0:03b5121a232e 10495 /**
pcercuei 0:03b5121a232e 10496 * xmlXPathCompPrimaryExpr:
pcercuei 0:03b5121a232e 10497 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10498 *
pcercuei 0:03b5121a232e 10499 * [15] PrimaryExpr ::= VariableReference
pcercuei 0:03b5121a232e 10500 * | '(' Expr ')'
pcercuei 0:03b5121a232e 10501 * | Literal
pcercuei 0:03b5121a232e 10502 * | Number
pcercuei 0:03b5121a232e 10503 * | FunctionCall
pcercuei 0:03b5121a232e 10504 *
pcercuei 0:03b5121a232e 10505 * Compile a primary expression.
pcercuei 0:03b5121a232e 10506 */
pcercuei 0:03b5121a232e 10507 static void
pcercuei 0:03b5121a232e 10508 xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10509 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10510 if (CUR == '$') xmlXPathCompVariableReference(ctxt);
pcercuei 0:03b5121a232e 10511 else if (CUR == '(') {
pcercuei 0:03b5121a232e 10512 NEXT;
pcercuei 0:03b5121a232e 10513 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10514 xmlXPathCompileExpr(ctxt, 1);
pcercuei 0:03b5121a232e 10515 CHECK_ERROR;
pcercuei 0:03b5121a232e 10516 if (CUR != ')') {
pcercuei 0:03b5121a232e 10517 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10518 }
pcercuei 0:03b5121a232e 10519 NEXT;
pcercuei 0:03b5121a232e 10520 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10521 } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
pcercuei 0:03b5121a232e 10522 xmlXPathCompNumber(ctxt);
pcercuei 0:03b5121a232e 10523 } else if ((CUR == '\'') || (CUR == '"')) {
pcercuei 0:03b5121a232e 10524 xmlXPathCompLiteral(ctxt);
pcercuei 0:03b5121a232e 10525 } else {
pcercuei 0:03b5121a232e 10526 xmlXPathCompFunctionCall(ctxt);
pcercuei 0:03b5121a232e 10527 }
pcercuei 0:03b5121a232e 10528 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10529 }
pcercuei 0:03b5121a232e 10530
pcercuei 0:03b5121a232e 10531 /**
pcercuei 0:03b5121a232e 10532 * xmlXPathCompFilterExpr:
pcercuei 0:03b5121a232e 10533 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10534 *
pcercuei 0:03b5121a232e 10535 * [20] FilterExpr ::= PrimaryExpr
pcercuei 0:03b5121a232e 10536 * | FilterExpr Predicate
pcercuei 0:03b5121a232e 10537 *
pcercuei 0:03b5121a232e 10538 * Compile a filter expression.
pcercuei 0:03b5121a232e 10539 * Square brackets are used to filter expressions in the same way that
pcercuei 0:03b5121a232e 10540 * they are used in location paths. It is an error if the expression to
pcercuei 0:03b5121a232e 10541 * be filtered does not evaluate to a node-set. The context node list
pcercuei 0:03b5121a232e 10542 * used for evaluating the expression in square brackets is the node-set
pcercuei 0:03b5121a232e 10543 * to be filtered listed in document order.
pcercuei 0:03b5121a232e 10544 */
pcercuei 0:03b5121a232e 10545
pcercuei 0:03b5121a232e 10546 static void
pcercuei 0:03b5121a232e 10547 xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10548 xmlXPathCompPrimaryExpr(ctxt);
pcercuei 0:03b5121a232e 10549 CHECK_ERROR;
pcercuei 0:03b5121a232e 10550 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10551
pcercuei 0:03b5121a232e 10552 while (CUR == '[') {
pcercuei 0:03b5121a232e 10553 xmlXPathCompPredicate(ctxt, 1);
pcercuei 0:03b5121a232e 10554 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10555 }
pcercuei 0:03b5121a232e 10556
pcercuei 0:03b5121a232e 10557
pcercuei 0:03b5121a232e 10558 }
pcercuei 0:03b5121a232e 10559
pcercuei 0:03b5121a232e 10560 /**
pcercuei 0:03b5121a232e 10561 * xmlXPathScanName:
pcercuei 0:03b5121a232e 10562 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10563 *
pcercuei 0:03b5121a232e 10564 * Trickery: parse an XML name but without consuming the input flow
pcercuei 0:03b5121a232e 10565 * Needed to avoid insanity in the parser state.
pcercuei 0:03b5121a232e 10566 *
pcercuei 0:03b5121a232e 10567 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
pcercuei 0:03b5121a232e 10568 * CombiningChar | Extender
pcercuei 0:03b5121a232e 10569 *
pcercuei 0:03b5121a232e 10570 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
pcercuei 0:03b5121a232e 10571 *
pcercuei 0:03b5121a232e 10572 * [6] Names ::= Name (S Name)*
pcercuei 0:03b5121a232e 10573 *
pcercuei 0:03b5121a232e 10574 * Returns the Name parsed or NULL
pcercuei 0:03b5121a232e 10575 */
pcercuei 0:03b5121a232e 10576
pcercuei 0:03b5121a232e 10577 static xmlChar *
pcercuei 0:03b5121a232e 10578 xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10579 int len = 0, l;
pcercuei 0:03b5121a232e 10580 int c;
pcercuei 0:03b5121a232e 10581 const xmlChar *cur;
pcercuei 0:03b5121a232e 10582 xmlChar *ret;
pcercuei 0:03b5121a232e 10583
pcercuei 0:03b5121a232e 10584 cur = ctxt->cur;
pcercuei 0:03b5121a232e 10585
pcercuei 0:03b5121a232e 10586 c = CUR_CHAR(l);
pcercuei 0:03b5121a232e 10587 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
pcercuei 0:03b5121a232e 10588 (!IS_LETTER(c) && (c != '_') &&
pcercuei 0:03b5121a232e 10589 (c != ':'))) {
pcercuei 0:03b5121a232e 10590 return(NULL);
pcercuei 0:03b5121a232e 10591 }
pcercuei 0:03b5121a232e 10592
pcercuei 0:03b5121a232e 10593 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
pcercuei 0:03b5121a232e 10594 ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
pcercuei 0:03b5121a232e 10595 (c == '.') || (c == '-') ||
pcercuei 0:03b5121a232e 10596 (c == '_') || (c == ':') ||
pcercuei 0:03b5121a232e 10597 (IS_COMBINING(c)) ||
pcercuei 0:03b5121a232e 10598 (IS_EXTENDER(c)))) {
pcercuei 0:03b5121a232e 10599 len += l;
pcercuei 0:03b5121a232e 10600 NEXTL(l);
pcercuei 0:03b5121a232e 10601 c = CUR_CHAR(l);
pcercuei 0:03b5121a232e 10602 }
pcercuei 0:03b5121a232e 10603 ret = xmlStrndup(cur, ctxt->cur - cur);
pcercuei 0:03b5121a232e 10604 ctxt->cur = cur;
pcercuei 0:03b5121a232e 10605 return(ret);
pcercuei 0:03b5121a232e 10606 }
pcercuei 0:03b5121a232e 10607
pcercuei 0:03b5121a232e 10608 /**
pcercuei 0:03b5121a232e 10609 * xmlXPathCompPathExpr:
pcercuei 0:03b5121a232e 10610 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10611 *
pcercuei 0:03b5121a232e 10612 * [19] PathExpr ::= LocationPath
pcercuei 0:03b5121a232e 10613 * | FilterExpr
pcercuei 0:03b5121a232e 10614 * | FilterExpr '/' RelativeLocationPath
pcercuei 0:03b5121a232e 10615 * | FilterExpr '//' RelativeLocationPath
pcercuei 0:03b5121a232e 10616 *
pcercuei 0:03b5121a232e 10617 * Compile a path expression.
pcercuei 0:03b5121a232e 10618 * The / operator and // operators combine an arbitrary expression
pcercuei 0:03b5121a232e 10619 * and a relative location path. It is an error if the expression
pcercuei 0:03b5121a232e 10620 * does not evaluate to a node-set.
pcercuei 0:03b5121a232e 10621 * The / operator does composition in the same way as when / is
pcercuei 0:03b5121a232e 10622 * used in a location path. As in location paths, // is short for
pcercuei 0:03b5121a232e 10623 * /descendant-or-self::node()/.
pcercuei 0:03b5121a232e 10624 */
pcercuei 0:03b5121a232e 10625
pcercuei 0:03b5121a232e 10626 static void
pcercuei 0:03b5121a232e 10627 xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10628 int lc = 1; /* Should we branch to LocationPath ? */
pcercuei 0:03b5121a232e 10629 xmlChar *name = NULL; /* we may have to preparse a name to find out */
pcercuei 0:03b5121a232e 10630
pcercuei 0:03b5121a232e 10631 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10632 if ((CUR == '$') || (CUR == '(') ||
pcercuei 0:03b5121a232e 10633 (IS_ASCII_DIGIT(CUR)) ||
pcercuei 0:03b5121a232e 10634 (CUR == '\'') || (CUR == '"') ||
pcercuei 0:03b5121a232e 10635 (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
pcercuei 0:03b5121a232e 10636 lc = 0;
pcercuei 0:03b5121a232e 10637 } else if (CUR == '*') {
pcercuei 0:03b5121a232e 10638 /* relative or absolute location path */
pcercuei 0:03b5121a232e 10639 lc = 1;
pcercuei 0:03b5121a232e 10640 } else if (CUR == '/') {
pcercuei 0:03b5121a232e 10641 /* relative or absolute location path */
pcercuei 0:03b5121a232e 10642 lc = 1;
pcercuei 0:03b5121a232e 10643 } else if (CUR == '@') {
pcercuei 0:03b5121a232e 10644 /* relative abbreviated attribute location path */
pcercuei 0:03b5121a232e 10645 lc = 1;
pcercuei 0:03b5121a232e 10646 } else if (CUR == '.') {
pcercuei 0:03b5121a232e 10647 /* relative abbreviated attribute location path */
pcercuei 0:03b5121a232e 10648 lc = 1;
pcercuei 0:03b5121a232e 10649 } else {
pcercuei 0:03b5121a232e 10650 /*
pcercuei 0:03b5121a232e 10651 * Problem is finding if we have a name here whether it's:
pcercuei 0:03b5121a232e 10652 * - a nodetype
pcercuei 0:03b5121a232e 10653 * - a function call in which case it's followed by '('
pcercuei 0:03b5121a232e 10654 * - an axis in which case it's followed by ':'
pcercuei 0:03b5121a232e 10655 * - a element name
pcercuei 0:03b5121a232e 10656 * We do an a priori analysis here rather than having to
pcercuei 0:03b5121a232e 10657 * maintain parsed token content through the recursive function
pcercuei 0:03b5121a232e 10658 * calls. This looks uglier but makes the code easier to
pcercuei 0:03b5121a232e 10659 * read/write/debug.
pcercuei 0:03b5121a232e 10660 */
pcercuei 0:03b5121a232e 10661 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10662 name = xmlXPathScanName(ctxt);
pcercuei 0:03b5121a232e 10663 if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
pcercuei 0:03b5121a232e 10664 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10665 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10666 "PathExpr: Axis\n");
pcercuei 0:03b5121a232e 10667 #endif
pcercuei 0:03b5121a232e 10668 lc = 1;
pcercuei 0:03b5121a232e 10669 xmlFree(name);
pcercuei 0:03b5121a232e 10670 } else if (name != NULL) {
pcercuei 0:03b5121a232e 10671 int len =xmlStrlen(name);
pcercuei 0:03b5121a232e 10672
pcercuei 0:03b5121a232e 10673
pcercuei 0:03b5121a232e 10674 while (NXT(len) != 0) {
pcercuei 0:03b5121a232e 10675 if (NXT(len) == '/') {
pcercuei 0:03b5121a232e 10676 /* element name */
pcercuei 0:03b5121a232e 10677 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10678 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10679 "PathExpr: AbbrRelLocation\n");
pcercuei 0:03b5121a232e 10680 #endif
pcercuei 0:03b5121a232e 10681 lc = 1;
pcercuei 0:03b5121a232e 10682 break;
pcercuei 0:03b5121a232e 10683 } else if (IS_BLANK_CH(NXT(len))) {
pcercuei 0:03b5121a232e 10684 /* ignore blanks */
pcercuei 0:03b5121a232e 10685 ;
pcercuei 0:03b5121a232e 10686 } else if (NXT(len) == ':') {
pcercuei 0:03b5121a232e 10687 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10688 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10689 "PathExpr: AbbrRelLocation\n");
pcercuei 0:03b5121a232e 10690 #endif
pcercuei 0:03b5121a232e 10691 lc = 1;
pcercuei 0:03b5121a232e 10692 break;
pcercuei 0:03b5121a232e 10693 } else if ((NXT(len) == '(')) {
pcercuei 0:03b5121a232e 10694 /* Note Type or Function */
pcercuei 0:03b5121a232e 10695 if (xmlXPathIsNodeType(name)) {
pcercuei 0:03b5121a232e 10696 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10697 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10698 "PathExpr: Type search\n");
pcercuei 0:03b5121a232e 10699 #endif
pcercuei 0:03b5121a232e 10700 lc = 1;
pcercuei 0:03b5121a232e 10701 } else {
pcercuei 0:03b5121a232e 10702 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10703 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10704 "PathExpr: function call\n");
pcercuei 0:03b5121a232e 10705 #endif
pcercuei 0:03b5121a232e 10706 lc = 0;
pcercuei 0:03b5121a232e 10707 }
pcercuei 0:03b5121a232e 10708 break;
pcercuei 0:03b5121a232e 10709 } else if ((NXT(len) == '[')) {
pcercuei 0:03b5121a232e 10710 /* element name */
pcercuei 0:03b5121a232e 10711 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10712 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10713 "PathExpr: AbbrRelLocation\n");
pcercuei 0:03b5121a232e 10714 #endif
pcercuei 0:03b5121a232e 10715 lc = 1;
pcercuei 0:03b5121a232e 10716 break;
pcercuei 0:03b5121a232e 10717 } else if ((NXT(len) == '<') || (NXT(len) == '>') ||
pcercuei 0:03b5121a232e 10718 (NXT(len) == '=')) {
pcercuei 0:03b5121a232e 10719 lc = 1;
pcercuei 0:03b5121a232e 10720 break;
pcercuei 0:03b5121a232e 10721 } else {
pcercuei 0:03b5121a232e 10722 lc = 1;
pcercuei 0:03b5121a232e 10723 break;
pcercuei 0:03b5121a232e 10724 }
pcercuei 0:03b5121a232e 10725 len++;
pcercuei 0:03b5121a232e 10726 }
pcercuei 0:03b5121a232e 10727 if (NXT(len) == 0) {
pcercuei 0:03b5121a232e 10728 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 10729 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 10730 "PathExpr: AbbrRelLocation\n");
pcercuei 0:03b5121a232e 10731 #endif
pcercuei 0:03b5121a232e 10732 /* element name */
pcercuei 0:03b5121a232e 10733 lc = 1;
pcercuei 0:03b5121a232e 10734 }
pcercuei 0:03b5121a232e 10735 xmlFree(name);
pcercuei 0:03b5121a232e 10736 } else {
pcercuei 0:03b5121a232e 10737 /* make sure all cases are covered explicitly */
pcercuei 0:03b5121a232e 10738 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 10739 }
pcercuei 0:03b5121a232e 10740 }
pcercuei 0:03b5121a232e 10741
pcercuei 0:03b5121a232e 10742 if (lc) {
pcercuei 0:03b5121a232e 10743 if (CUR == '/') {
pcercuei 0:03b5121a232e 10744 PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
pcercuei 0:03b5121a232e 10745 } else {
pcercuei 0:03b5121a232e 10746 PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
pcercuei 0:03b5121a232e 10747 }
pcercuei 0:03b5121a232e 10748 xmlXPathCompLocationPath(ctxt);
pcercuei 0:03b5121a232e 10749 } else {
pcercuei 0:03b5121a232e 10750 xmlXPathCompFilterExpr(ctxt);
pcercuei 0:03b5121a232e 10751 CHECK_ERROR;
pcercuei 0:03b5121a232e 10752 if ((CUR == '/') && (NXT(1) == '/')) {
pcercuei 0:03b5121a232e 10753 SKIP(2);
pcercuei 0:03b5121a232e 10754 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10755
pcercuei 0:03b5121a232e 10756 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
pcercuei 0:03b5121a232e 10757 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
pcercuei 0:03b5121a232e 10758 PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
pcercuei 0:03b5121a232e 10759
pcercuei 0:03b5121a232e 10760 xmlXPathCompRelativeLocationPath(ctxt);
pcercuei 0:03b5121a232e 10761 } else if (CUR == '/') {
pcercuei 0:03b5121a232e 10762 xmlXPathCompRelativeLocationPath(ctxt);
pcercuei 0:03b5121a232e 10763 }
pcercuei 0:03b5121a232e 10764 }
pcercuei 0:03b5121a232e 10765 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10766 }
pcercuei 0:03b5121a232e 10767
pcercuei 0:03b5121a232e 10768 /**
pcercuei 0:03b5121a232e 10769 * xmlXPathCompUnionExpr:
pcercuei 0:03b5121a232e 10770 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10771 *
pcercuei 0:03b5121a232e 10772 * [18] UnionExpr ::= PathExpr
pcercuei 0:03b5121a232e 10773 * | UnionExpr '|' PathExpr
pcercuei 0:03b5121a232e 10774 *
pcercuei 0:03b5121a232e 10775 * Compile an union expression.
pcercuei 0:03b5121a232e 10776 */
pcercuei 0:03b5121a232e 10777
pcercuei 0:03b5121a232e 10778 static void
pcercuei 0:03b5121a232e 10779 xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10780 xmlXPathCompPathExpr(ctxt);
pcercuei 0:03b5121a232e 10781 CHECK_ERROR;
pcercuei 0:03b5121a232e 10782 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10783 while (CUR == '|') {
pcercuei 0:03b5121a232e 10784 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 10785 PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
pcercuei 0:03b5121a232e 10786
pcercuei 0:03b5121a232e 10787 NEXT;
pcercuei 0:03b5121a232e 10788 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10789 xmlXPathCompPathExpr(ctxt);
pcercuei 0:03b5121a232e 10790
pcercuei 0:03b5121a232e 10791 PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
pcercuei 0:03b5121a232e 10792
pcercuei 0:03b5121a232e 10793 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10794 }
pcercuei 0:03b5121a232e 10795 }
pcercuei 0:03b5121a232e 10796
pcercuei 0:03b5121a232e 10797 /**
pcercuei 0:03b5121a232e 10798 * xmlXPathCompUnaryExpr:
pcercuei 0:03b5121a232e 10799 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10800 *
pcercuei 0:03b5121a232e 10801 * [27] UnaryExpr ::= UnionExpr
pcercuei 0:03b5121a232e 10802 * | '-' UnaryExpr
pcercuei 0:03b5121a232e 10803 *
pcercuei 0:03b5121a232e 10804 * Compile an unary expression.
pcercuei 0:03b5121a232e 10805 */
pcercuei 0:03b5121a232e 10806
pcercuei 0:03b5121a232e 10807 static void
pcercuei 0:03b5121a232e 10808 xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10809 int minus = 0;
pcercuei 0:03b5121a232e 10810 int found = 0;
pcercuei 0:03b5121a232e 10811
pcercuei 0:03b5121a232e 10812 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10813 while (CUR == '-') {
pcercuei 0:03b5121a232e 10814 minus = 1 - minus;
pcercuei 0:03b5121a232e 10815 found = 1;
pcercuei 0:03b5121a232e 10816 NEXT;
pcercuei 0:03b5121a232e 10817 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10818 }
pcercuei 0:03b5121a232e 10819
pcercuei 0:03b5121a232e 10820 xmlXPathCompUnionExpr(ctxt);
pcercuei 0:03b5121a232e 10821 CHECK_ERROR;
pcercuei 0:03b5121a232e 10822 if (found) {
pcercuei 0:03b5121a232e 10823 if (minus)
pcercuei 0:03b5121a232e 10824 PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
pcercuei 0:03b5121a232e 10825 else
pcercuei 0:03b5121a232e 10826 PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
pcercuei 0:03b5121a232e 10827 }
pcercuei 0:03b5121a232e 10828 }
pcercuei 0:03b5121a232e 10829
pcercuei 0:03b5121a232e 10830 /**
pcercuei 0:03b5121a232e 10831 * xmlXPathCompMultiplicativeExpr:
pcercuei 0:03b5121a232e 10832 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10833 *
pcercuei 0:03b5121a232e 10834 * [26] MultiplicativeExpr ::= UnaryExpr
pcercuei 0:03b5121a232e 10835 * | MultiplicativeExpr MultiplyOperator UnaryExpr
pcercuei 0:03b5121a232e 10836 * | MultiplicativeExpr 'div' UnaryExpr
pcercuei 0:03b5121a232e 10837 * | MultiplicativeExpr 'mod' UnaryExpr
pcercuei 0:03b5121a232e 10838 * [34] MultiplyOperator ::= '*'
pcercuei 0:03b5121a232e 10839 *
pcercuei 0:03b5121a232e 10840 * Compile an Additive expression.
pcercuei 0:03b5121a232e 10841 */
pcercuei 0:03b5121a232e 10842
pcercuei 0:03b5121a232e 10843 static void
pcercuei 0:03b5121a232e 10844 xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10845 xmlXPathCompUnaryExpr(ctxt);
pcercuei 0:03b5121a232e 10846 CHECK_ERROR;
pcercuei 0:03b5121a232e 10847 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10848 while ((CUR == '*') ||
pcercuei 0:03b5121a232e 10849 ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
pcercuei 0:03b5121a232e 10850 ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
pcercuei 0:03b5121a232e 10851 int op = -1;
pcercuei 0:03b5121a232e 10852 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 10853
pcercuei 0:03b5121a232e 10854 if (CUR == '*') {
pcercuei 0:03b5121a232e 10855 op = 0;
pcercuei 0:03b5121a232e 10856 NEXT;
pcercuei 0:03b5121a232e 10857 } else if (CUR == 'd') {
pcercuei 0:03b5121a232e 10858 op = 1;
pcercuei 0:03b5121a232e 10859 SKIP(3);
pcercuei 0:03b5121a232e 10860 } else if (CUR == 'm') {
pcercuei 0:03b5121a232e 10861 op = 2;
pcercuei 0:03b5121a232e 10862 SKIP(3);
pcercuei 0:03b5121a232e 10863 }
pcercuei 0:03b5121a232e 10864 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10865 xmlXPathCompUnaryExpr(ctxt);
pcercuei 0:03b5121a232e 10866 CHECK_ERROR;
pcercuei 0:03b5121a232e 10867 PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
pcercuei 0:03b5121a232e 10868 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10869 }
pcercuei 0:03b5121a232e 10870 }
pcercuei 0:03b5121a232e 10871
pcercuei 0:03b5121a232e 10872 /**
pcercuei 0:03b5121a232e 10873 * xmlXPathCompAdditiveExpr:
pcercuei 0:03b5121a232e 10874 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10875 *
pcercuei 0:03b5121a232e 10876 * [25] AdditiveExpr ::= MultiplicativeExpr
pcercuei 0:03b5121a232e 10877 * | AdditiveExpr '+' MultiplicativeExpr
pcercuei 0:03b5121a232e 10878 * | AdditiveExpr '-' MultiplicativeExpr
pcercuei 0:03b5121a232e 10879 *
pcercuei 0:03b5121a232e 10880 * Compile an Additive expression.
pcercuei 0:03b5121a232e 10881 */
pcercuei 0:03b5121a232e 10882
pcercuei 0:03b5121a232e 10883 static void
pcercuei 0:03b5121a232e 10884 xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10885
pcercuei 0:03b5121a232e 10886 xmlXPathCompMultiplicativeExpr(ctxt);
pcercuei 0:03b5121a232e 10887 CHECK_ERROR;
pcercuei 0:03b5121a232e 10888 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10889 while ((CUR == '+') || (CUR == '-')) {
pcercuei 0:03b5121a232e 10890 int plus;
pcercuei 0:03b5121a232e 10891 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 10892
pcercuei 0:03b5121a232e 10893 if (CUR == '+') plus = 1;
pcercuei 0:03b5121a232e 10894 else plus = 0;
pcercuei 0:03b5121a232e 10895 NEXT;
pcercuei 0:03b5121a232e 10896 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10897 xmlXPathCompMultiplicativeExpr(ctxt);
pcercuei 0:03b5121a232e 10898 CHECK_ERROR;
pcercuei 0:03b5121a232e 10899 PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
pcercuei 0:03b5121a232e 10900 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10901 }
pcercuei 0:03b5121a232e 10902 }
pcercuei 0:03b5121a232e 10903
pcercuei 0:03b5121a232e 10904 /**
pcercuei 0:03b5121a232e 10905 * xmlXPathCompRelationalExpr:
pcercuei 0:03b5121a232e 10906 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10907 *
pcercuei 0:03b5121a232e 10908 * [24] RelationalExpr ::= AdditiveExpr
pcercuei 0:03b5121a232e 10909 * | RelationalExpr '<' AdditiveExpr
pcercuei 0:03b5121a232e 10910 * | RelationalExpr '>' AdditiveExpr
pcercuei 0:03b5121a232e 10911 * | RelationalExpr '<=' AdditiveExpr
pcercuei 0:03b5121a232e 10912 * | RelationalExpr '>=' AdditiveExpr
pcercuei 0:03b5121a232e 10913 *
pcercuei 0:03b5121a232e 10914 * A <= B > C is allowed ? Answer from James, yes with
pcercuei 0:03b5121a232e 10915 * (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
pcercuei 0:03b5121a232e 10916 * which is basically what got implemented.
pcercuei 0:03b5121a232e 10917 *
pcercuei 0:03b5121a232e 10918 * Compile a Relational expression, then push the result
pcercuei 0:03b5121a232e 10919 * on the stack
pcercuei 0:03b5121a232e 10920 */
pcercuei 0:03b5121a232e 10921
pcercuei 0:03b5121a232e 10922 static void
pcercuei 0:03b5121a232e 10923 xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10924 xmlXPathCompAdditiveExpr(ctxt);
pcercuei 0:03b5121a232e 10925 CHECK_ERROR;
pcercuei 0:03b5121a232e 10926 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10927 while ((CUR == '<') ||
pcercuei 0:03b5121a232e 10928 (CUR == '>') ||
pcercuei 0:03b5121a232e 10929 ((CUR == '<') && (NXT(1) == '=')) ||
pcercuei 0:03b5121a232e 10930 ((CUR == '>') && (NXT(1) == '='))) {
pcercuei 0:03b5121a232e 10931 int inf, strict;
pcercuei 0:03b5121a232e 10932 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 10933
pcercuei 0:03b5121a232e 10934 if (CUR == '<') inf = 1;
pcercuei 0:03b5121a232e 10935 else inf = 0;
pcercuei 0:03b5121a232e 10936 if (NXT(1) == '=') strict = 0;
pcercuei 0:03b5121a232e 10937 else strict = 1;
pcercuei 0:03b5121a232e 10938 NEXT;
pcercuei 0:03b5121a232e 10939 if (!strict) NEXT;
pcercuei 0:03b5121a232e 10940 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10941 xmlXPathCompAdditiveExpr(ctxt);
pcercuei 0:03b5121a232e 10942 CHECK_ERROR;
pcercuei 0:03b5121a232e 10943 PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
pcercuei 0:03b5121a232e 10944 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10945 }
pcercuei 0:03b5121a232e 10946 }
pcercuei 0:03b5121a232e 10947
pcercuei 0:03b5121a232e 10948 /**
pcercuei 0:03b5121a232e 10949 * xmlXPathCompEqualityExpr:
pcercuei 0:03b5121a232e 10950 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10951 *
pcercuei 0:03b5121a232e 10952 * [23] EqualityExpr ::= RelationalExpr
pcercuei 0:03b5121a232e 10953 * | EqualityExpr '=' RelationalExpr
pcercuei 0:03b5121a232e 10954 * | EqualityExpr '!=' RelationalExpr
pcercuei 0:03b5121a232e 10955 *
pcercuei 0:03b5121a232e 10956 * A != B != C is allowed ? Answer from James, yes with
pcercuei 0:03b5121a232e 10957 * (RelationalExpr = RelationalExpr) = RelationalExpr
pcercuei 0:03b5121a232e 10958 * (RelationalExpr != RelationalExpr) != RelationalExpr
pcercuei 0:03b5121a232e 10959 * which is basically what got implemented.
pcercuei 0:03b5121a232e 10960 *
pcercuei 0:03b5121a232e 10961 * Compile an Equality expression.
pcercuei 0:03b5121a232e 10962 *
pcercuei 0:03b5121a232e 10963 */
pcercuei 0:03b5121a232e 10964 static void
pcercuei 0:03b5121a232e 10965 xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10966 xmlXPathCompRelationalExpr(ctxt);
pcercuei 0:03b5121a232e 10967 CHECK_ERROR;
pcercuei 0:03b5121a232e 10968 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10969 while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
pcercuei 0:03b5121a232e 10970 int eq;
pcercuei 0:03b5121a232e 10971 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 10972
pcercuei 0:03b5121a232e 10973 if (CUR == '=') eq = 1;
pcercuei 0:03b5121a232e 10974 else eq = 0;
pcercuei 0:03b5121a232e 10975 NEXT;
pcercuei 0:03b5121a232e 10976 if (!eq) NEXT;
pcercuei 0:03b5121a232e 10977 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10978 xmlXPathCompRelationalExpr(ctxt);
pcercuei 0:03b5121a232e 10979 CHECK_ERROR;
pcercuei 0:03b5121a232e 10980 PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
pcercuei 0:03b5121a232e 10981 SKIP_BLANKS;
pcercuei 0:03b5121a232e 10982 }
pcercuei 0:03b5121a232e 10983 }
pcercuei 0:03b5121a232e 10984
pcercuei 0:03b5121a232e 10985 /**
pcercuei 0:03b5121a232e 10986 * xmlXPathCompAndExpr:
pcercuei 0:03b5121a232e 10987 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 10988 *
pcercuei 0:03b5121a232e 10989 * [22] AndExpr ::= EqualityExpr
pcercuei 0:03b5121a232e 10990 * | AndExpr 'and' EqualityExpr
pcercuei 0:03b5121a232e 10991 *
pcercuei 0:03b5121a232e 10992 * Compile an AND expression.
pcercuei 0:03b5121a232e 10993 *
pcercuei 0:03b5121a232e 10994 */
pcercuei 0:03b5121a232e 10995 static void
pcercuei 0:03b5121a232e 10996 xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 10997 xmlXPathCompEqualityExpr(ctxt);
pcercuei 0:03b5121a232e 10998 CHECK_ERROR;
pcercuei 0:03b5121a232e 10999 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11000 while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
pcercuei 0:03b5121a232e 11001 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 11002 SKIP(3);
pcercuei 0:03b5121a232e 11003 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11004 xmlXPathCompEqualityExpr(ctxt);
pcercuei 0:03b5121a232e 11005 CHECK_ERROR;
pcercuei 0:03b5121a232e 11006 PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
pcercuei 0:03b5121a232e 11007 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11008 }
pcercuei 0:03b5121a232e 11009 }
pcercuei 0:03b5121a232e 11010
pcercuei 0:03b5121a232e 11011 /**
pcercuei 0:03b5121a232e 11012 * xmlXPathCompileExpr:
pcercuei 0:03b5121a232e 11013 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 11014 *
pcercuei 0:03b5121a232e 11015 * [14] Expr ::= OrExpr
pcercuei 0:03b5121a232e 11016 * [21] OrExpr ::= AndExpr
pcercuei 0:03b5121a232e 11017 * | OrExpr 'or' AndExpr
pcercuei 0:03b5121a232e 11018 *
pcercuei 0:03b5121a232e 11019 * Parse and compile an expression
pcercuei 0:03b5121a232e 11020 */
pcercuei 0:03b5121a232e 11021 static void
pcercuei 0:03b5121a232e 11022 xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
pcercuei 0:03b5121a232e 11023 xmlXPathCompAndExpr(ctxt);
pcercuei 0:03b5121a232e 11024 CHECK_ERROR;
pcercuei 0:03b5121a232e 11025 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11026 while ((CUR == 'o') && (NXT(1) == 'r')) {
pcercuei 0:03b5121a232e 11027 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 11028 SKIP(2);
pcercuei 0:03b5121a232e 11029 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11030 xmlXPathCompAndExpr(ctxt);
pcercuei 0:03b5121a232e 11031 CHECK_ERROR;
pcercuei 0:03b5121a232e 11032 PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
pcercuei 0:03b5121a232e 11033 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11034 }
pcercuei 0:03b5121a232e 11035 if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) {
pcercuei 0:03b5121a232e 11036 /* more ops could be optimized too */
pcercuei 0:03b5121a232e 11037 /*
pcercuei 0:03b5121a232e 11038 * This is the main place to eliminate sorting for
pcercuei 0:03b5121a232e 11039 * operations which don't require a sorted node-set.
pcercuei 0:03b5121a232e 11040 * E.g. count().
pcercuei 0:03b5121a232e 11041 */
pcercuei 0:03b5121a232e 11042 PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
pcercuei 0:03b5121a232e 11043 }
pcercuei 0:03b5121a232e 11044 }
pcercuei 0:03b5121a232e 11045
pcercuei 0:03b5121a232e 11046 /**
pcercuei 0:03b5121a232e 11047 * xmlXPathCompPredicate:
pcercuei 0:03b5121a232e 11048 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 11049 * @filter: act as a filter
pcercuei 0:03b5121a232e 11050 *
pcercuei 0:03b5121a232e 11051 * [8] Predicate ::= '[' PredicateExpr ']'
pcercuei 0:03b5121a232e 11052 * [9] PredicateExpr ::= Expr
pcercuei 0:03b5121a232e 11053 *
pcercuei 0:03b5121a232e 11054 * Compile a predicate expression
pcercuei 0:03b5121a232e 11055 */
pcercuei 0:03b5121a232e 11056 static void
pcercuei 0:03b5121a232e 11057 xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
pcercuei 0:03b5121a232e 11058 int op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 11059
pcercuei 0:03b5121a232e 11060 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11061 if (CUR != '[') {
pcercuei 0:03b5121a232e 11062 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
pcercuei 0:03b5121a232e 11063 }
pcercuei 0:03b5121a232e 11064 NEXT;
pcercuei 0:03b5121a232e 11065 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11066
pcercuei 0:03b5121a232e 11067 ctxt->comp->last = -1;
pcercuei 0:03b5121a232e 11068 /*
pcercuei 0:03b5121a232e 11069 * This call to xmlXPathCompileExpr() will deactivate sorting
pcercuei 0:03b5121a232e 11070 * of the predicate result.
pcercuei 0:03b5121a232e 11071 * TODO: Sorting is still activated for filters, since I'm not
pcercuei 0:03b5121a232e 11072 * sure if needed. Normally sorting should not be needed, since
pcercuei 0:03b5121a232e 11073 * a filter can only diminish the number of items in a sequence,
pcercuei 0:03b5121a232e 11074 * but won't change its order; so if the initial sequence is sorted,
pcercuei 0:03b5121a232e 11075 * subsequent sorting is not needed.
pcercuei 0:03b5121a232e 11076 */
pcercuei 0:03b5121a232e 11077 if (! filter)
pcercuei 0:03b5121a232e 11078 xmlXPathCompileExpr(ctxt, 0);
pcercuei 0:03b5121a232e 11079 else
pcercuei 0:03b5121a232e 11080 xmlXPathCompileExpr(ctxt, 1);
pcercuei 0:03b5121a232e 11081 CHECK_ERROR;
pcercuei 0:03b5121a232e 11082
pcercuei 0:03b5121a232e 11083 if (CUR != ']') {
pcercuei 0:03b5121a232e 11084 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
pcercuei 0:03b5121a232e 11085 }
pcercuei 0:03b5121a232e 11086
pcercuei 0:03b5121a232e 11087 if (filter)
pcercuei 0:03b5121a232e 11088 PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
pcercuei 0:03b5121a232e 11089 else
pcercuei 0:03b5121a232e 11090 PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
pcercuei 0:03b5121a232e 11091
pcercuei 0:03b5121a232e 11092 NEXT;
pcercuei 0:03b5121a232e 11093 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11094 }
pcercuei 0:03b5121a232e 11095
pcercuei 0:03b5121a232e 11096 /**
pcercuei 0:03b5121a232e 11097 * xmlXPathCompNodeTest:
pcercuei 0:03b5121a232e 11098 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 11099 * @test: pointer to a xmlXPathTestVal
pcercuei 0:03b5121a232e 11100 * @type: pointer to a xmlXPathTypeVal
pcercuei 0:03b5121a232e 11101 * @prefix: placeholder for a possible name prefix
pcercuei 0:03b5121a232e 11102 *
pcercuei 0:03b5121a232e 11103 * [7] NodeTest ::= NameTest
pcercuei 0:03b5121a232e 11104 * | NodeType '(' ')'
pcercuei 0:03b5121a232e 11105 * | 'processing-instruction' '(' Literal ')'
pcercuei 0:03b5121a232e 11106 *
pcercuei 0:03b5121a232e 11107 * [37] NameTest ::= '*'
pcercuei 0:03b5121a232e 11108 * | NCName ':' '*'
pcercuei 0:03b5121a232e 11109 * | QName
pcercuei 0:03b5121a232e 11110 * [38] NodeType ::= 'comment'
pcercuei 0:03b5121a232e 11111 * | 'text'
pcercuei 0:03b5121a232e 11112 * | 'processing-instruction'
pcercuei 0:03b5121a232e 11113 * | 'node'
pcercuei 0:03b5121a232e 11114 *
pcercuei 0:03b5121a232e 11115 * Returns the name found and updates @test, @type and @prefix appropriately
pcercuei 0:03b5121a232e 11116 */
pcercuei 0:03b5121a232e 11117 static xmlChar *
pcercuei 0:03b5121a232e 11118 xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
pcercuei 0:03b5121a232e 11119 xmlXPathTypeVal *type, const xmlChar **prefix,
pcercuei 0:03b5121a232e 11120 xmlChar *name) {
pcercuei 0:03b5121a232e 11121 int blanks;
pcercuei 0:03b5121a232e 11122
pcercuei 0:03b5121a232e 11123 if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
pcercuei 0:03b5121a232e 11124 STRANGE;
pcercuei 0:03b5121a232e 11125 return(NULL);
pcercuei 0:03b5121a232e 11126 }
pcercuei 0:03b5121a232e 11127 *type = (xmlXPathTypeVal) 0;
pcercuei 0:03b5121a232e 11128 *test = (xmlXPathTestVal) 0;
pcercuei 0:03b5121a232e 11129 *prefix = NULL;
pcercuei 0:03b5121a232e 11130 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11131
pcercuei 0:03b5121a232e 11132 if ((name == NULL) && (CUR == '*')) {
pcercuei 0:03b5121a232e 11133 /*
pcercuei 0:03b5121a232e 11134 * All elements
pcercuei 0:03b5121a232e 11135 */
pcercuei 0:03b5121a232e 11136 NEXT;
pcercuei 0:03b5121a232e 11137 *test = NODE_TEST_ALL;
pcercuei 0:03b5121a232e 11138 return(NULL);
pcercuei 0:03b5121a232e 11139 }
pcercuei 0:03b5121a232e 11140
pcercuei 0:03b5121a232e 11141 if (name == NULL)
pcercuei 0:03b5121a232e 11142 name = xmlXPathParseNCName(ctxt);
pcercuei 0:03b5121a232e 11143 if (name == NULL) {
pcercuei 0:03b5121a232e 11144 XP_ERRORNULL(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 11145 }
pcercuei 0:03b5121a232e 11146
pcercuei 0:03b5121a232e 11147 blanks = IS_BLANK_CH(CUR);
pcercuei 0:03b5121a232e 11148 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11149 if (CUR == '(') {
pcercuei 0:03b5121a232e 11150 NEXT;
pcercuei 0:03b5121a232e 11151 /*
pcercuei 0:03b5121a232e 11152 * NodeType or PI search
pcercuei 0:03b5121a232e 11153 */
pcercuei 0:03b5121a232e 11154 if (xmlStrEqual(name, BAD_CAST "comment"))
pcercuei 0:03b5121a232e 11155 *type = NODE_TYPE_COMMENT;
pcercuei 0:03b5121a232e 11156 else if (xmlStrEqual(name, BAD_CAST "node"))
pcercuei 0:03b5121a232e 11157 *type = NODE_TYPE_NODE;
pcercuei 0:03b5121a232e 11158 else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
pcercuei 0:03b5121a232e 11159 *type = NODE_TYPE_PI;
pcercuei 0:03b5121a232e 11160 else if (xmlStrEqual(name, BAD_CAST "text"))
pcercuei 0:03b5121a232e 11161 *type = NODE_TYPE_TEXT;
pcercuei 0:03b5121a232e 11162 else {
pcercuei 0:03b5121a232e 11163 if (name != NULL)
pcercuei 0:03b5121a232e 11164 xmlFree(name);
pcercuei 0:03b5121a232e 11165 XP_ERRORNULL(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 11166 }
pcercuei 0:03b5121a232e 11167
pcercuei 0:03b5121a232e 11168 *test = NODE_TEST_TYPE;
pcercuei 0:03b5121a232e 11169
pcercuei 0:03b5121a232e 11170 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11171 if (*type == NODE_TYPE_PI) {
pcercuei 0:03b5121a232e 11172 /*
pcercuei 0:03b5121a232e 11173 * Specific case: search a PI by name.
pcercuei 0:03b5121a232e 11174 */
pcercuei 0:03b5121a232e 11175 if (name != NULL)
pcercuei 0:03b5121a232e 11176 xmlFree(name);
pcercuei 0:03b5121a232e 11177 name = NULL;
pcercuei 0:03b5121a232e 11178 if (CUR != ')') {
pcercuei 0:03b5121a232e 11179 name = xmlXPathParseLiteral(ctxt);
pcercuei 0:03b5121a232e 11180 CHECK_ERROR NULL;
pcercuei 0:03b5121a232e 11181 *test = NODE_TEST_PI;
pcercuei 0:03b5121a232e 11182 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11183 }
pcercuei 0:03b5121a232e 11184 }
pcercuei 0:03b5121a232e 11185 if (CUR != ')') {
pcercuei 0:03b5121a232e 11186 if (name != NULL)
pcercuei 0:03b5121a232e 11187 xmlFree(name);
pcercuei 0:03b5121a232e 11188 XP_ERRORNULL(XPATH_UNCLOSED_ERROR);
pcercuei 0:03b5121a232e 11189 }
pcercuei 0:03b5121a232e 11190 NEXT;
pcercuei 0:03b5121a232e 11191 return(name);
pcercuei 0:03b5121a232e 11192 }
pcercuei 0:03b5121a232e 11193 *test = NODE_TEST_NAME;
pcercuei 0:03b5121a232e 11194 if ((!blanks) && (CUR == ':')) {
pcercuei 0:03b5121a232e 11195 NEXT;
pcercuei 0:03b5121a232e 11196
pcercuei 0:03b5121a232e 11197 /*
pcercuei 0:03b5121a232e 11198 * Since currently the parser context don't have a
pcercuei 0:03b5121a232e 11199 * namespace list associated:
pcercuei 0:03b5121a232e 11200 * The namespace name for this prefix can be computed
pcercuei 0:03b5121a232e 11201 * only at evaluation time. The compilation is done
pcercuei 0:03b5121a232e 11202 * outside of any context.
pcercuei 0:03b5121a232e 11203 */
pcercuei 0:03b5121a232e 11204 #if 0
pcercuei 0:03b5121a232e 11205 *prefix = xmlXPathNsLookup(ctxt->context, name);
pcercuei 0:03b5121a232e 11206 if (name != NULL)
pcercuei 0:03b5121a232e 11207 xmlFree(name);
pcercuei 0:03b5121a232e 11208 if (*prefix == NULL) {
pcercuei 0:03b5121a232e 11209 XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
pcercuei 0:03b5121a232e 11210 }
pcercuei 0:03b5121a232e 11211 #else
pcercuei 0:03b5121a232e 11212 *prefix = name;
pcercuei 0:03b5121a232e 11213 #endif
pcercuei 0:03b5121a232e 11214
pcercuei 0:03b5121a232e 11215 if (CUR == '*') {
pcercuei 0:03b5121a232e 11216 /*
pcercuei 0:03b5121a232e 11217 * All elements
pcercuei 0:03b5121a232e 11218 */
pcercuei 0:03b5121a232e 11219 NEXT;
pcercuei 0:03b5121a232e 11220 *test = NODE_TEST_ALL;
pcercuei 0:03b5121a232e 11221 return(NULL);
pcercuei 0:03b5121a232e 11222 }
pcercuei 0:03b5121a232e 11223
pcercuei 0:03b5121a232e 11224 name = xmlXPathParseNCName(ctxt);
pcercuei 0:03b5121a232e 11225 if (name == NULL) {
pcercuei 0:03b5121a232e 11226 XP_ERRORNULL(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 11227 }
pcercuei 0:03b5121a232e 11228 }
pcercuei 0:03b5121a232e 11229 return(name);
pcercuei 0:03b5121a232e 11230 }
pcercuei 0:03b5121a232e 11231
pcercuei 0:03b5121a232e 11232 /**
pcercuei 0:03b5121a232e 11233 * xmlXPathIsAxisName:
pcercuei 0:03b5121a232e 11234 * @name: a preparsed name token
pcercuei 0:03b5121a232e 11235 *
pcercuei 0:03b5121a232e 11236 * [6] AxisName ::= 'ancestor'
pcercuei 0:03b5121a232e 11237 * | 'ancestor-or-self'
pcercuei 0:03b5121a232e 11238 * | 'attribute'
pcercuei 0:03b5121a232e 11239 * | 'child'
pcercuei 0:03b5121a232e 11240 * | 'descendant'
pcercuei 0:03b5121a232e 11241 * | 'descendant-or-self'
pcercuei 0:03b5121a232e 11242 * | 'following'
pcercuei 0:03b5121a232e 11243 * | 'following-sibling'
pcercuei 0:03b5121a232e 11244 * | 'namespace'
pcercuei 0:03b5121a232e 11245 * | 'parent'
pcercuei 0:03b5121a232e 11246 * | 'preceding'
pcercuei 0:03b5121a232e 11247 * | 'preceding-sibling'
pcercuei 0:03b5121a232e 11248 * | 'self'
pcercuei 0:03b5121a232e 11249 *
pcercuei 0:03b5121a232e 11250 * Returns the axis or 0
pcercuei 0:03b5121a232e 11251 */
pcercuei 0:03b5121a232e 11252 static xmlXPathAxisVal
pcercuei 0:03b5121a232e 11253 xmlXPathIsAxisName(const xmlChar *name) {
pcercuei 0:03b5121a232e 11254 xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
pcercuei 0:03b5121a232e 11255 switch (name[0]) {
pcercuei 0:03b5121a232e 11256 case 'a':
pcercuei 0:03b5121a232e 11257 if (xmlStrEqual(name, BAD_CAST "ancestor"))
pcercuei 0:03b5121a232e 11258 ret = AXIS_ANCESTOR;
pcercuei 0:03b5121a232e 11259 if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
pcercuei 0:03b5121a232e 11260 ret = AXIS_ANCESTOR_OR_SELF;
pcercuei 0:03b5121a232e 11261 if (xmlStrEqual(name, BAD_CAST "attribute"))
pcercuei 0:03b5121a232e 11262 ret = AXIS_ATTRIBUTE;
pcercuei 0:03b5121a232e 11263 break;
pcercuei 0:03b5121a232e 11264 case 'c':
pcercuei 0:03b5121a232e 11265 if (xmlStrEqual(name, BAD_CAST "child"))
pcercuei 0:03b5121a232e 11266 ret = AXIS_CHILD;
pcercuei 0:03b5121a232e 11267 break;
pcercuei 0:03b5121a232e 11268 case 'd':
pcercuei 0:03b5121a232e 11269 if (xmlStrEqual(name, BAD_CAST "descendant"))
pcercuei 0:03b5121a232e 11270 ret = AXIS_DESCENDANT;
pcercuei 0:03b5121a232e 11271 if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
pcercuei 0:03b5121a232e 11272 ret = AXIS_DESCENDANT_OR_SELF;
pcercuei 0:03b5121a232e 11273 break;
pcercuei 0:03b5121a232e 11274 case 'f':
pcercuei 0:03b5121a232e 11275 if (xmlStrEqual(name, BAD_CAST "following"))
pcercuei 0:03b5121a232e 11276 ret = AXIS_FOLLOWING;
pcercuei 0:03b5121a232e 11277 if (xmlStrEqual(name, BAD_CAST "following-sibling"))
pcercuei 0:03b5121a232e 11278 ret = AXIS_FOLLOWING_SIBLING;
pcercuei 0:03b5121a232e 11279 break;
pcercuei 0:03b5121a232e 11280 case 'n':
pcercuei 0:03b5121a232e 11281 if (xmlStrEqual(name, BAD_CAST "namespace"))
pcercuei 0:03b5121a232e 11282 ret = AXIS_NAMESPACE;
pcercuei 0:03b5121a232e 11283 break;
pcercuei 0:03b5121a232e 11284 case 'p':
pcercuei 0:03b5121a232e 11285 if (xmlStrEqual(name, BAD_CAST "parent"))
pcercuei 0:03b5121a232e 11286 ret = AXIS_PARENT;
pcercuei 0:03b5121a232e 11287 if (xmlStrEqual(name, BAD_CAST "preceding"))
pcercuei 0:03b5121a232e 11288 ret = AXIS_PRECEDING;
pcercuei 0:03b5121a232e 11289 if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
pcercuei 0:03b5121a232e 11290 ret = AXIS_PRECEDING_SIBLING;
pcercuei 0:03b5121a232e 11291 break;
pcercuei 0:03b5121a232e 11292 case 's':
pcercuei 0:03b5121a232e 11293 if (xmlStrEqual(name, BAD_CAST "self"))
pcercuei 0:03b5121a232e 11294 ret = AXIS_SELF;
pcercuei 0:03b5121a232e 11295 break;
pcercuei 0:03b5121a232e 11296 }
pcercuei 0:03b5121a232e 11297 return(ret);
pcercuei 0:03b5121a232e 11298 }
pcercuei 0:03b5121a232e 11299
pcercuei 0:03b5121a232e 11300 /**
pcercuei 0:03b5121a232e 11301 * xmlXPathCompStep:
pcercuei 0:03b5121a232e 11302 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 11303 *
pcercuei 0:03b5121a232e 11304 * [4] Step ::= AxisSpecifier NodeTest Predicate*
pcercuei 0:03b5121a232e 11305 * | AbbreviatedStep
pcercuei 0:03b5121a232e 11306 *
pcercuei 0:03b5121a232e 11307 * [12] AbbreviatedStep ::= '.' | '..'
pcercuei 0:03b5121a232e 11308 *
pcercuei 0:03b5121a232e 11309 * [5] AxisSpecifier ::= AxisName '::'
pcercuei 0:03b5121a232e 11310 * | AbbreviatedAxisSpecifier
pcercuei 0:03b5121a232e 11311 *
pcercuei 0:03b5121a232e 11312 * [13] AbbreviatedAxisSpecifier ::= '@'?
pcercuei 0:03b5121a232e 11313 *
pcercuei 0:03b5121a232e 11314 * Modified for XPtr range support as:
pcercuei 0:03b5121a232e 11315 *
pcercuei 0:03b5121a232e 11316 * [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
pcercuei 0:03b5121a232e 11317 * | AbbreviatedStep
pcercuei 0:03b5121a232e 11318 * | 'range-to' '(' Expr ')' Predicate*
pcercuei 0:03b5121a232e 11319 *
pcercuei 0:03b5121a232e 11320 * Compile one step in a Location Path
pcercuei 0:03b5121a232e 11321 * A location step of . is short for self::node(). This is
pcercuei 0:03b5121a232e 11322 * particularly useful in conjunction with //. For example, the
pcercuei 0:03b5121a232e 11323 * location path .//para is short for
pcercuei 0:03b5121a232e 11324 * self::node()/descendant-or-self::node()/child::para
pcercuei 0:03b5121a232e 11325 * and so will select all para descendant elements of the context
pcercuei 0:03b5121a232e 11326 * node.
pcercuei 0:03b5121a232e 11327 * Similarly, a location step of .. is short for parent::node().
pcercuei 0:03b5121a232e 11328 * For example, ../title is short for parent::node()/child::title
pcercuei 0:03b5121a232e 11329 * and so will select the title children of the parent of the context
pcercuei 0:03b5121a232e 11330 * node.
pcercuei 0:03b5121a232e 11331 */
pcercuei 0:03b5121a232e 11332 static void
pcercuei 0:03b5121a232e 11333 xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 11334 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 11335 int rangeto = 0;
pcercuei 0:03b5121a232e 11336 int op2 = -1;
pcercuei 0:03b5121a232e 11337 #endif
pcercuei 0:03b5121a232e 11338
pcercuei 0:03b5121a232e 11339 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11340 if ((CUR == '.') && (NXT(1) == '.')) {
pcercuei 0:03b5121a232e 11341 SKIP(2);
pcercuei 0:03b5121a232e 11342 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11343 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
pcercuei 0:03b5121a232e 11344 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
pcercuei 0:03b5121a232e 11345 } else if (CUR == '.') {
pcercuei 0:03b5121a232e 11346 NEXT;
pcercuei 0:03b5121a232e 11347 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11348 } else {
pcercuei 0:03b5121a232e 11349 xmlChar *name = NULL;
pcercuei 0:03b5121a232e 11350 const xmlChar *prefix = NULL;
pcercuei 0:03b5121a232e 11351 xmlXPathTestVal test = (xmlXPathTestVal) 0;
pcercuei 0:03b5121a232e 11352 xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
pcercuei 0:03b5121a232e 11353 xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
pcercuei 0:03b5121a232e 11354 int op1;
pcercuei 0:03b5121a232e 11355
pcercuei 0:03b5121a232e 11356 /*
pcercuei 0:03b5121a232e 11357 * The modification needed for XPointer change to the production
pcercuei 0:03b5121a232e 11358 */
pcercuei 0:03b5121a232e 11359 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 11360 if (ctxt->xptr) {
pcercuei 0:03b5121a232e 11361 name = xmlXPathParseNCName(ctxt);
pcercuei 0:03b5121a232e 11362 if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
pcercuei 0:03b5121a232e 11363 op2 = ctxt->comp->last;
pcercuei 0:03b5121a232e 11364 xmlFree(name);
pcercuei 0:03b5121a232e 11365 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11366 if (CUR != '(') {
pcercuei 0:03b5121a232e 11367 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 11368 }
pcercuei 0:03b5121a232e 11369 NEXT;
pcercuei 0:03b5121a232e 11370 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11371
pcercuei 0:03b5121a232e 11372 xmlXPathCompileExpr(ctxt, 1);
pcercuei 0:03b5121a232e 11373 /* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */
pcercuei 0:03b5121a232e 11374 CHECK_ERROR;
pcercuei 0:03b5121a232e 11375
pcercuei 0:03b5121a232e 11376 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11377 if (CUR != ')') {
pcercuei 0:03b5121a232e 11378 XP_ERROR(XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 11379 }
pcercuei 0:03b5121a232e 11380 NEXT;
pcercuei 0:03b5121a232e 11381 rangeto = 1;
pcercuei 0:03b5121a232e 11382 goto eval_predicates;
pcercuei 0:03b5121a232e 11383 }
pcercuei 0:03b5121a232e 11384 }
pcercuei 0:03b5121a232e 11385 #endif
pcercuei 0:03b5121a232e 11386 if (CUR == '*') {
pcercuei 0:03b5121a232e 11387 axis = AXIS_CHILD;
pcercuei 0:03b5121a232e 11388 } else {
pcercuei 0:03b5121a232e 11389 if (name == NULL)
pcercuei 0:03b5121a232e 11390 name = xmlXPathParseNCName(ctxt);
pcercuei 0:03b5121a232e 11391 if (name != NULL) {
pcercuei 0:03b5121a232e 11392 axis = xmlXPathIsAxisName(name);
pcercuei 0:03b5121a232e 11393 if (axis != 0) {
pcercuei 0:03b5121a232e 11394 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11395 if ((CUR == ':') && (NXT(1) == ':')) {
pcercuei 0:03b5121a232e 11396 SKIP(2);
pcercuei 0:03b5121a232e 11397 xmlFree(name);
pcercuei 0:03b5121a232e 11398 name = NULL;
pcercuei 0:03b5121a232e 11399 } else {
pcercuei 0:03b5121a232e 11400 /* an element name can conflict with an axis one :-\ */
pcercuei 0:03b5121a232e 11401 axis = AXIS_CHILD;
pcercuei 0:03b5121a232e 11402 }
pcercuei 0:03b5121a232e 11403 } else {
pcercuei 0:03b5121a232e 11404 axis = AXIS_CHILD;
pcercuei 0:03b5121a232e 11405 }
pcercuei 0:03b5121a232e 11406 } else if (CUR == '@') {
pcercuei 0:03b5121a232e 11407 NEXT;
pcercuei 0:03b5121a232e 11408 axis = AXIS_ATTRIBUTE;
pcercuei 0:03b5121a232e 11409 } else {
pcercuei 0:03b5121a232e 11410 axis = AXIS_CHILD;
pcercuei 0:03b5121a232e 11411 }
pcercuei 0:03b5121a232e 11412 }
pcercuei 0:03b5121a232e 11413
pcercuei 0:03b5121a232e 11414 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 11415 xmlFree(name);
pcercuei 0:03b5121a232e 11416 return;
pcercuei 0:03b5121a232e 11417 }
pcercuei 0:03b5121a232e 11418
pcercuei 0:03b5121a232e 11419 name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
pcercuei 0:03b5121a232e 11420 if (test == 0)
pcercuei 0:03b5121a232e 11421 return;
pcercuei 0:03b5121a232e 11422
pcercuei 0:03b5121a232e 11423 if ((prefix != NULL) && (ctxt->context != NULL) &&
pcercuei 0:03b5121a232e 11424 (ctxt->context->flags & XML_XPATH_CHECKNS)) {
pcercuei 0:03b5121a232e 11425 if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) {
pcercuei 0:03b5121a232e 11426 xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
pcercuei 0:03b5121a232e 11427 }
pcercuei 0:03b5121a232e 11428 }
pcercuei 0:03b5121a232e 11429 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 11430 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11431 "Basis : computing new set\n");
pcercuei 0:03b5121a232e 11432 #endif
pcercuei 0:03b5121a232e 11433
pcercuei 0:03b5121a232e 11434 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 11435 xmlGenericError(xmlGenericErrorContext, "Basis : ");
pcercuei 0:03b5121a232e 11436 if (ctxt->value == NULL)
pcercuei 0:03b5121a232e 11437 xmlGenericError(xmlGenericErrorContext, "no value\n");
pcercuei 0:03b5121a232e 11438 else if (ctxt->value->nodesetval == NULL)
pcercuei 0:03b5121a232e 11439 xmlGenericError(xmlGenericErrorContext, "Empty\n");
pcercuei 0:03b5121a232e 11440 else
pcercuei 0:03b5121a232e 11441 xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 11442 #endif
pcercuei 0:03b5121a232e 11443
pcercuei 0:03b5121a232e 11444 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 11445 eval_predicates:
pcercuei 0:03b5121a232e 11446 #endif
pcercuei 0:03b5121a232e 11447 op1 = ctxt->comp->last;
pcercuei 0:03b5121a232e 11448 ctxt->comp->last = -1;
pcercuei 0:03b5121a232e 11449
pcercuei 0:03b5121a232e 11450 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11451 while (CUR == '[') {
pcercuei 0:03b5121a232e 11452 xmlXPathCompPredicate(ctxt, 0);
pcercuei 0:03b5121a232e 11453 }
pcercuei 0:03b5121a232e 11454
pcercuei 0:03b5121a232e 11455 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 11456 if (rangeto) {
pcercuei 0:03b5121a232e 11457 PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
pcercuei 0:03b5121a232e 11458 } else
pcercuei 0:03b5121a232e 11459 #endif
pcercuei 0:03b5121a232e 11460 PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
pcercuei 0:03b5121a232e 11461 test, type, (void *)prefix, (void *)name);
pcercuei 0:03b5121a232e 11462
pcercuei 0:03b5121a232e 11463 }
pcercuei 0:03b5121a232e 11464 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 11465 xmlGenericError(xmlGenericErrorContext, "Step : ");
pcercuei 0:03b5121a232e 11466 if (ctxt->value == NULL)
pcercuei 0:03b5121a232e 11467 xmlGenericError(xmlGenericErrorContext, "no value\n");
pcercuei 0:03b5121a232e 11468 else if (ctxt->value->nodesetval == NULL)
pcercuei 0:03b5121a232e 11469 xmlGenericError(xmlGenericErrorContext, "Empty\n");
pcercuei 0:03b5121a232e 11470 else
pcercuei 0:03b5121a232e 11471 xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11472 ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 11473 #endif
pcercuei 0:03b5121a232e 11474 }
pcercuei 0:03b5121a232e 11475
pcercuei 0:03b5121a232e 11476 /**
pcercuei 0:03b5121a232e 11477 * xmlXPathCompRelativeLocationPath:
pcercuei 0:03b5121a232e 11478 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 11479 *
pcercuei 0:03b5121a232e 11480 * [3] RelativeLocationPath ::= Step
pcercuei 0:03b5121a232e 11481 * | RelativeLocationPath '/' Step
pcercuei 0:03b5121a232e 11482 * | AbbreviatedRelativeLocationPath
pcercuei 0:03b5121a232e 11483 * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
pcercuei 0:03b5121a232e 11484 *
pcercuei 0:03b5121a232e 11485 * Compile a relative location path.
pcercuei 0:03b5121a232e 11486 */
pcercuei 0:03b5121a232e 11487 static void
pcercuei 0:03b5121a232e 11488 xmlXPathCompRelativeLocationPath
pcercuei 0:03b5121a232e 11489 (xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 11490 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11491 if ((CUR == '/') && (NXT(1) == '/')) {
pcercuei 0:03b5121a232e 11492 SKIP(2);
pcercuei 0:03b5121a232e 11493 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11494 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
pcercuei 0:03b5121a232e 11495 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
pcercuei 0:03b5121a232e 11496 } else if (CUR == '/') {
pcercuei 0:03b5121a232e 11497 NEXT;
pcercuei 0:03b5121a232e 11498 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11499 }
pcercuei 0:03b5121a232e 11500 xmlXPathCompStep(ctxt);
pcercuei 0:03b5121a232e 11501 CHECK_ERROR;
pcercuei 0:03b5121a232e 11502 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11503 while (CUR == '/') {
pcercuei 0:03b5121a232e 11504 if ((CUR == '/') && (NXT(1) == '/')) {
pcercuei 0:03b5121a232e 11505 SKIP(2);
pcercuei 0:03b5121a232e 11506 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11507 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
pcercuei 0:03b5121a232e 11508 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
pcercuei 0:03b5121a232e 11509 xmlXPathCompStep(ctxt);
pcercuei 0:03b5121a232e 11510 } else if (CUR == '/') {
pcercuei 0:03b5121a232e 11511 NEXT;
pcercuei 0:03b5121a232e 11512 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11513 xmlXPathCompStep(ctxt);
pcercuei 0:03b5121a232e 11514 }
pcercuei 0:03b5121a232e 11515 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11516 }
pcercuei 0:03b5121a232e 11517 }
pcercuei 0:03b5121a232e 11518
pcercuei 0:03b5121a232e 11519 /**
pcercuei 0:03b5121a232e 11520 * xmlXPathCompLocationPath:
pcercuei 0:03b5121a232e 11521 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 11522 *
pcercuei 0:03b5121a232e 11523 * [1] LocationPath ::= RelativeLocationPath
pcercuei 0:03b5121a232e 11524 * | AbsoluteLocationPath
pcercuei 0:03b5121a232e 11525 * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
pcercuei 0:03b5121a232e 11526 * | AbbreviatedAbsoluteLocationPath
pcercuei 0:03b5121a232e 11527 * [10] AbbreviatedAbsoluteLocationPath ::=
pcercuei 0:03b5121a232e 11528 * '//' RelativeLocationPath
pcercuei 0:03b5121a232e 11529 *
pcercuei 0:03b5121a232e 11530 * Compile a location path
pcercuei 0:03b5121a232e 11531 *
pcercuei 0:03b5121a232e 11532 * // is short for /descendant-or-self::node()/. For example,
pcercuei 0:03b5121a232e 11533 * //para is short for /descendant-or-self::node()/child::para and
pcercuei 0:03b5121a232e 11534 * so will select any para element in the document (even a para element
pcercuei 0:03b5121a232e 11535 * that is a document element will be selected by //para since the
pcercuei 0:03b5121a232e 11536 * document element node is a child of the root node); div//para is
pcercuei 0:03b5121a232e 11537 * short for div/descendant-or-self::node()/child::para and so will
pcercuei 0:03b5121a232e 11538 * select all para descendants of div children.
pcercuei 0:03b5121a232e 11539 */
pcercuei 0:03b5121a232e 11540 static void
pcercuei 0:03b5121a232e 11541 xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 11542 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11543 if (CUR != '/') {
pcercuei 0:03b5121a232e 11544 xmlXPathCompRelativeLocationPath(ctxt);
pcercuei 0:03b5121a232e 11545 } else {
pcercuei 0:03b5121a232e 11546 while (CUR == '/') {
pcercuei 0:03b5121a232e 11547 if ((CUR == '/') && (NXT(1) == '/')) {
pcercuei 0:03b5121a232e 11548 SKIP(2);
pcercuei 0:03b5121a232e 11549 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11550 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
pcercuei 0:03b5121a232e 11551 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
pcercuei 0:03b5121a232e 11552 xmlXPathCompRelativeLocationPath(ctxt);
pcercuei 0:03b5121a232e 11553 } else if (CUR == '/') {
pcercuei 0:03b5121a232e 11554 NEXT;
pcercuei 0:03b5121a232e 11555 SKIP_BLANKS;
pcercuei 0:03b5121a232e 11556 if ((CUR != 0 ) &&
pcercuei 0:03b5121a232e 11557 ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
pcercuei 0:03b5121a232e 11558 (CUR == '@') || (CUR == '*')))
pcercuei 0:03b5121a232e 11559 xmlXPathCompRelativeLocationPath(ctxt);
pcercuei 0:03b5121a232e 11560 }
pcercuei 0:03b5121a232e 11561 CHECK_ERROR;
pcercuei 0:03b5121a232e 11562 }
pcercuei 0:03b5121a232e 11563 }
pcercuei 0:03b5121a232e 11564 }
pcercuei 0:03b5121a232e 11565
pcercuei 0:03b5121a232e 11566 /************************************************************************
pcercuei 0:03b5121a232e 11567 * *
pcercuei 0:03b5121a232e 11568 * XPath precompiled expression evaluation *
pcercuei 0:03b5121a232e 11569 * *
pcercuei 0:03b5121a232e 11570 ************************************************************************/
pcercuei 0:03b5121a232e 11571
pcercuei 0:03b5121a232e 11572 static int
pcercuei 0:03b5121a232e 11573 xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
pcercuei 0:03b5121a232e 11574
pcercuei 0:03b5121a232e 11575 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 11576 static void
pcercuei 0:03b5121a232e 11577 xmlXPathDebugDumpStepAxis(xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 11578 int nbNodes)
pcercuei 0:03b5121a232e 11579 {
pcercuei 0:03b5121a232e 11580 xmlGenericError(xmlGenericErrorContext, "new step : ");
pcercuei 0:03b5121a232e 11581 switch (op->value) {
pcercuei 0:03b5121a232e 11582 case AXIS_ANCESTOR:
pcercuei 0:03b5121a232e 11583 xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
pcercuei 0:03b5121a232e 11584 break;
pcercuei 0:03b5121a232e 11585 case AXIS_ANCESTOR_OR_SELF:
pcercuei 0:03b5121a232e 11586 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11587 "axis 'ancestors-or-self' ");
pcercuei 0:03b5121a232e 11588 break;
pcercuei 0:03b5121a232e 11589 case AXIS_ATTRIBUTE:
pcercuei 0:03b5121a232e 11590 xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
pcercuei 0:03b5121a232e 11591 break;
pcercuei 0:03b5121a232e 11592 case AXIS_CHILD:
pcercuei 0:03b5121a232e 11593 xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
pcercuei 0:03b5121a232e 11594 break;
pcercuei 0:03b5121a232e 11595 case AXIS_DESCENDANT:
pcercuei 0:03b5121a232e 11596 xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
pcercuei 0:03b5121a232e 11597 break;
pcercuei 0:03b5121a232e 11598 case AXIS_DESCENDANT_OR_SELF:
pcercuei 0:03b5121a232e 11599 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11600 "axis 'descendant-or-self' ");
pcercuei 0:03b5121a232e 11601 break;
pcercuei 0:03b5121a232e 11602 case AXIS_FOLLOWING:
pcercuei 0:03b5121a232e 11603 xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
pcercuei 0:03b5121a232e 11604 break;
pcercuei 0:03b5121a232e 11605 case AXIS_FOLLOWING_SIBLING:
pcercuei 0:03b5121a232e 11606 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11607 "axis 'following-siblings' ");
pcercuei 0:03b5121a232e 11608 break;
pcercuei 0:03b5121a232e 11609 case AXIS_NAMESPACE:
pcercuei 0:03b5121a232e 11610 xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
pcercuei 0:03b5121a232e 11611 break;
pcercuei 0:03b5121a232e 11612 case AXIS_PARENT:
pcercuei 0:03b5121a232e 11613 xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
pcercuei 0:03b5121a232e 11614 break;
pcercuei 0:03b5121a232e 11615 case AXIS_PRECEDING:
pcercuei 0:03b5121a232e 11616 xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
pcercuei 0:03b5121a232e 11617 break;
pcercuei 0:03b5121a232e 11618 case AXIS_PRECEDING_SIBLING:
pcercuei 0:03b5121a232e 11619 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11620 "axis 'preceding-sibling' ");
pcercuei 0:03b5121a232e 11621 break;
pcercuei 0:03b5121a232e 11622 case AXIS_SELF:
pcercuei 0:03b5121a232e 11623 xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
pcercuei 0:03b5121a232e 11624 break;
pcercuei 0:03b5121a232e 11625 }
pcercuei 0:03b5121a232e 11626 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11627 " context contains %d nodes\n", nbNodes);
pcercuei 0:03b5121a232e 11628 switch (op->value2) {
pcercuei 0:03b5121a232e 11629 case NODE_TEST_NONE:
pcercuei 0:03b5121a232e 11630 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11631 " searching for none !!!\n");
pcercuei 0:03b5121a232e 11632 break;
pcercuei 0:03b5121a232e 11633 case NODE_TEST_TYPE:
pcercuei 0:03b5121a232e 11634 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11635 " searching for type %d\n", op->value3);
pcercuei 0:03b5121a232e 11636 break;
pcercuei 0:03b5121a232e 11637 case NODE_TEST_PI:
pcercuei 0:03b5121a232e 11638 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11639 " searching for PI !!!\n");
pcercuei 0:03b5121a232e 11640 break;
pcercuei 0:03b5121a232e 11641 case NODE_TEST_ALL:
pcercuei 0:03b5121a232e 11642 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11643 " searching for *\n");
pcercuei 0:03b5121a232e 11644 break;
pcercuei 0:03b5121a232e 11645 case NODE_TEST_NS:
pcercuei 0:03b5121a232e 11646 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11647 " searching for namespace %s\n",
pcercuei 0:03b5121a232e 11648 op->value5);
pcercuei 0:03b5121a232e 11649 break;
pcercuei 0:03b5121a232e 11650 case NODE_TEST_NAME:
pcercuei 0:03b5121a232e 11651 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11652 " searching for name %s\n", op->value5);
pcercuei 0:03b5121a232e 11653 if (op->value4)
pcercuei 0:03b5121a232e 11654 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 11655 " with namespace %s\n", op->value4);
pcercuei 0:03b5121a232e 11656 break;
pcercuei 0:03b5121a232e 11657 }
pcercuei 0:03b5121a232e 11658 xmlGenericError(xmlGenericErrorContext, "Testing : ");
pcercuei 0:03b5121a232e 11659 }
pcercuei 0:03b5121a232e 11660 #endif /* DEBUG_STEP */
pcercuei 0:03b5121a232e 11661
pcercuei 0:03b5121a232e 11662 static int
pcercuei 0:03b5121a232e 11663 xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 11664 xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 11665 xmlNodeSetPtr set,
pcercuei 0:03b5121a232e 11666 int contextSize,
pcercuei 0:03b5121a232e 11667 int hasNsNodes)
pcercuei 0:03b5121a232e 11668 {
pcercuei 0:03b5121a232e 11669 if (op->ch1 != -1) {
pcercuei 0:03b5121a232e 11670 xmlXPathCompExprPtr comp = ctxt->comp;
pcercuei 0:03b5121a232e 11671 /*
pcercuei 0:03b5121a232e 11672 * Process inner predicates first.
pcercuei 0:03b5121a232e 11673 */
pcercuei 0:03b5121a232e 11674 if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) {
pcercuei 0:03b5121a232e 11675 /*
pcercuei 0:03b5121a232e 11676 * TODO: raise an internal error.
pcercuei 0:03b5121a232e 11677 */
pcercuei 0:03b5121a232e 11678 }
pcercuei 0:03b5121a232e 11679 contextSize = xmlXPathCompOpEvalPredicate(ctxt,
pcercuei 0:03b5121a232e 11680 &comp->steps[op->ch1], set, contextSize, hasNsNodes);
pcercuei 0:03b5121a232e 11681 CHECK_ERROR0;
pcercuei 0:03b5121a232e 11682 if (contextSize <= 0)
pcercuei 0:03b5121a232e 11683 return(0);
pcercuei 0:03b5121a232e 11684 }
pcercuei 0:03b5121a232e 11685 if (op->ch2 != -1) {
pcercuei 0:03b5121a232e 11686 xmlXPathContextPtr xpctxt = ctxt->context;
pcercuei 0:03b5121a232e 11687 xmlNodePtr contextNode, oldContextNode;
pcercuei 0:03b5121a232e 11688 xmlDocPtr oldContextDoc;
pcercuei 0:03b5121a232e 11689 int i, res, contextPos = 0, newContextSize;
pcercuei 0:03b5121a232e 11690 xmlXPathStepOpPtr exprOp;
pcercuei 0:03b5121a232e 11691 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
pcercuei 0:03b5121a232e 11692
pcercuei 0:03b5121a232e 11693 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 11694 /*
pcercuei 0:03b5121a232e 11695 * URGENT TODO: Check the following:
pcercuei 0:03b5121a232e 11696 * We don't expect location sets if evaluating prediates, right?
pcercuei 0:03b5121a232e 11697 * Only filters should expect location sets, right?
pcercuei 0:03b5121a232e 11698 */
pcercuei 0:03b5121a232e 11699 #endif
pcercuei 0:03b5121a232e 11700 /*
pcercuei 0:03b5121a232e 11701 * SPEC XPath 1.0:
pcercuei 0:03b5121a232e 11702 * "For each node in the node-set to be filtered, the
pcercuei 0:03b5121a232e 11703 * PredicateExpr is evaluated with that node as the
pcercuei 0:03b5121a232e 11704 * context node, with the number of nodes in the
pcercuei 0:03b5121a232e 11705 * node-set as the context size, and with the proximity
pcercuei 0:03b5121a232e 11706 * position of the node in the node-set with respect to
pcercuei 0:03b5121a232e 11707 * the axis as the context position;"
pcercuei 0:03b5121a232e 11708 * @oldset is the node-set" to be filtered.
pcercuei 0:03b5121a232e 11709 *
pcercuei 0:03b5121a232e 11710 * SPEC XPath 1.0:
pcercuei 0:03b5121a232e 11711 * "only predicates change the context position and
pcercuei 0:03b5121a232e 11712 * context size (see [2.4 Predicates])."
pcercuei 0:03b5121a232e 11713 * Example:
pcercuei 0:03b5121a232e 11714 * node-set context pos
pcercuei 0:03b5121a232e 11715 * nA 1
pcercuei 0:03b5121a232e 11716 * nB 2
pcercuei 0:03b5121a232e 11717 * nC 3
pcercuei 0:03b5121a232e 11718 * After applying predicate [position() > 1] :
pcercuei 0:03b5121a232e 11719 * node-set context pos
pcercuei 0:03b5121a232e 11720 * nB 1
pcercuei 0:03b5121a232e 11721 * nC 2
pcercuei 0:03b5121a232e 11722 */
pcercuei 0:03b5121a232e 11723 oldContextNode = xpctxt->node;
pcercuei 0:03b5121a232e 11724 oldContextDoc = xpctxt->doc;
pcercuei 0:03b5121a232e 11725 /*
pcercuei 0:03b5121a232e 11726 * Get the expression of this predicate.
pcercuei 0:03b5121a232e 11727 */
pcercuei 0:03b5121a232e 11728 exprOp = &ctxt->comp->steps[op->ch2];
pcercuei 0:03b5121a232e 11729 newContextSize = 0;
pcercuei 0:03b5121a232e 11730 for (i = 0; i < set->nodeNr; i++) {
pcercuei 0:03b5121a232e 11731 if (set->nodeTab[i] == NULL)
pcercuei 0:03b5121a232e 11732 continue;
pcercuei 0:03b5121a232e 11733
pcercuei 0:03b5121a232e 11734 contextNode = set->nodeTab[i];
pcercuei 0:03b5121a232e 11735 xpctxt->node = contextNode;
pcercuei 0:03b5121a232e 11736 xpctxt->contextSize = contextSize;
pcercuei 0:03b5121a232e 11737 xpctxt->proximityPosition = ++contextPos;
pcercuei 0:03b5121a232e 11738
pcercuei 0:03b5121a232e 11739 /*
pcercuei 0:03b5121a232e 11740 * Also set the xpath document in case things like
pcercuei 0:03b5121a232e 11741 * key() are evaluated in the predicate.
pcercuei 0:03b5121a232e 11742 */
pcercuei 0:03b5121a232e 11743 if ((contextNode->type != XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 11744 (contextNode->doc != NULL))
pcercuei 0:03b5121a232e 11745 xpctxt->doc = contextNode->doc;
pcercuei 0:03b5121a232e 11746 /*
pcercuei 0:03b5121a232e 11747 * Evaluate the predicate expression with 1 context node
pcercuei 0:03b5121a232e 11748 * at a time; this node is packaged into a node set; this
pcercuei 0:03b5121a232e 11749 * node set is handed over to the evaluation mechanism.
pcercuei 0:03b5121a232e 11750 */
pcercuei 0:03b5121a232e 11751 if (contextObj == NULL)
pcercuei 0:03b5121a232e 11752 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
pcercuei 0:03b5121a232e 11753 else {
pcercuei 0:03b5121a232e 11754 if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
pcercuei 0:03b5121a232e 11755 contextNode) < 0) {
pcercuei 0:03b5121a232e 11756 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 11757 goto evaluation_exit;
pcercuei 0:03b5121a232e 11758 }
pcercuei 0:03b5121a232e 11759 }
pcercuei 0:03b5121a232e 11760
pcercuei 0:03b5121a232e 11761 valuePush(ctxt, contextObj);
pcercuei 0:03b5121a232e 11762
pcercuei 0:03b5121a232e 11763 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
pcercuei 0:03b5121a232e 11764
pcercuei 0:03b5121a232e 11765 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
pcercuei 0:03b5121a232e 11766 xmlXPathNodeSetClear(set, hasNsNodes);
pcercuei 0:03b5121a232e 11767 newContextSize = 0;
pcercuei 0:03b5121a232e 11768 goto evaluation_exit;
pcercuei 0:03b5121a232e 11769 }
pcercuei 0:03b5121a232e 11770
pcercuei 0:03b5121a232e 11771 if (res != 0) {
pcercuei 0:03b5121a232e 11772 newContextSize++;
pcercuei 0:03b5121a232e 11773 } else {
pcercuei 0:03b5121a232e 11774 /*
pcercuei 0:03b5121a232e 11775 * Remove the entry from the initial node set.
pcercuei 0:03b5121a232e 11776 */
pcercuei 0:03b5121a232e 11777 set->nodeTab[i] = NULL;
pcercuei 0:03b5121a232e 11778 if (contextNode->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 11779 xmlXPathNodeSetFreeNs((xmlNsPtr) contextNode);
pcercuei 0:03b5121a232e 11780 }
pcercuei 0:03b5121a232e 11781 if (ctxt->value == contextObj) {
pcercuei 0:03b5121a232e 11782 /*
pcercuei 0:03b5121a232e 11783 * Don't free the temporary XPath object holding the
pcercuei 0:03b5121a232e 11784 * context node, in order to avoid massive recreation
pcercuei 0:03b5121a232e 11785 * inside this loop.
pcercuei 0:03b5121a232e 11786 */
pcercuei 0:03b5121a232e 11787 valuePop(ctxt);
pcercuei 0:03b5121a232e 11788 xmlXPathNodeSetClear(contextObj->nodesetval, hasNsNodes);
pcercuei 0:03b5121a232e 11789 } else {
pcercuei 0:03b5121a232e 11790 /*
pcercuei 0:03b5121a232e 11791 * TODO: The object was lost in the evaluation machinery.
pcercuei 0:03b5121a232e 11792 * Can this happen? Maybe in internal-error cases.
pcercuei 0:03b5121a232e 11793 */
pcercuei 0:03b5121a232e 11794 contextObj = NULL;
pcercuei 0:03b5121a232e 11795 }
pcercuei 0:03b5121a232e 11796 }
pcercuei 0:03b5121a232e 11797
pcercuei 0:03b5121a232e 11798 if (contextObj != NULL) {
pcercuei 0:03b5121a232e 11799 if (ctxt->value == contextObj)
pcercuei 0:03b5121a232e 11800 valuePop(ctxt);
pcercuei 0:03b5121a232e 11801 xmlXPathReleaseObject(xpctxt, contextObj);
pcercuei 0:03b5121a232e 11802 }
pcercuei 0:03b5121a232e 11803 evaluation_exit:
pcercuei 0:03b5121a232e 11804 if (exprRes != NULL)
pcercuei 0:03b5121a232e 11805 xmlXPathReleaseObject(ctxt->context, exprRes);
pcercuei 0:03b5121a232e 11806 /*
pcercuei 0:03b5121a232e 11807 * Reset/invalidate the context.
pcercuei 0:03b5121a232e 11808 */
pcercuei 0:03b5121a232e 11809 xpctxt->node = oldContextNode;
pcercuei 0:03b5121a232e 11810 xpctxt->doc = oldContextDoc;
pcercuei 0:03b5121a232e 11811 xpctxt->contextSize = -1;
pcercuei 0:03b5121a232e 11812 xpctxt->proximityPosition = -1;
pcercuei 0:03b5121a232e 11813 return(newContextSize);
pcercuei 0:03b5121a232e 11814 }
pcercuei 0:03b5121a232e 11815 return(contextSize);
pcercuei 0:03b5121a232e 11816 }
pcercuei 0:03b5121a232e 11817
pcercuei 0:03b5121a232e 11818 static int
pcercuei 0:03b5121a232e 11819 xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 11820 xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 11821 xmlNodeSetPtr set,
pcercuei 0:03b5121a232e 11822 int contextSize,
pcercuei 0:03b5121a232e 11823 int minPos,
pcercuei 0:03b5121a232e 11824 int maxPos,
pcercuei 0:03b5121a232e 11825 int hasNsNodes)
pcercuei 0:03b5121a232e 11826 {
pcercuei 0:03b5121a232e 11827 if (op->ch1 != -1) {
pcercuei 0:03b5121a232e 11828 xmlXPathCompExprPtr comp = ctxt->comp;
pcercuei 0:03b5121a232e 11829 if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) {
pcercuei 0:03b5121a232e 11830 /*
pcercuei 0:03b5121a232e 11831 * TODO: raise an internal error.
pcercuei 0:03b5121a232e 11832 */
pcercuei 0:03b5121a232e 11833 }
pcercuei 0:03b5121a232e 11834 contextSize = xmlXPathCompOpEvalPredicate(ctxt,
pcercuei 0:03b5121a232e 11835 &comp->steps[op->ch1], set, contextSize, hasNsNodes);
pcercuei 0:03b5121a232e 11836 CHECK_ERROR0;
pcercuei 0:03b5121a232e 11837 if (contextSize <= 0)
pcercuei 0:03b5121a232e 11838 return(0);
pcercuei 0:03b5121a232e 11839 }
pcercuei 0:03b5121a232e 11840 /*
pcercuei 0:03b5121a232e 11841 * Check if the node set contains a sufficient number of nodes for
pcercuei 0:03b5121a232e 11842 * the requested range.
pcercuei 0:03b5121a232e 11843 */
pcercuei 0:03b5121a232e 11844 if (contextSize < minPos) {
pcercuei 0:03b5121a232e 11845 xmlXPathNodeSetClear(set, hasNsNodes);
pcercuei 0:03b5121a232e 11846 return(0);
pcercuei 0:03b5121a232e 11847 }
pcercuei 0:03b5121a232e 11848 if (op->ch2 == -1) {
pcercuei 0:03b5121a232e 11849 /*
pcercuei 0:03b5121a232e 11850 * TODO: Can this ever happen?
pcercuei 0:03b5121a232e 11851 */
pcercuei 0:03b5121a232e 11852 return (contextSize);
pcercuei 0:03b5121a232e 11853 } else {
pcercuei 0:03b5121a232e 11854 xmlDocPtr oldContextDoc;
pcercuei 0:03b5121a232e 11855 int i, pos = 0, newContextSize = 0, contextPos = 0, res;
pcercuei 0:03b5121a232e 11856 xmlXPathStepOpPtr exprOp;
pcercuei 0:03b5121a232e 11857 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
pcercuei 0:03b5121a232e 11858 xmlNodePtr oldContextNode, contextNode = NULL;
pcercuei 0:03b5121a232e 11859 xmlXPathContextPtr xpctxt = ctxt->context;
pcercuei 0:03b5121a232e 11860 int frame;
pcercuei 0:03b5121a232e 11861
pcercuei 0:03b5121a232e 11862 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 11863 /*
pcercuei 0:03b5121a232e 11864 * URGENT TODO: Check the following:
pcercuei 0:03b5121a232e 11865 * We don't expect location sets if evaluating prediates, right?
pcercuei 0:03b5121a232e 11866 * Only filters should expect location sets, right?
pcercuei 0:03b5121a232e 11867 */
pcercuei 0:03b5121a232e 11868 #endif /* LIBXML_XPTR_ENABLED */
pcercuei 0:03b5121a232e 11869
pcercuei 0:03b5121a232e 11870 /*
pcercuei 0:03b5121a232e 11871 * Save old context.
pcercuei 0:03b5121a232e 11872 */
pcercuei 0:03b5121a232e 11873 oldContextNode = xpctxt->node;
pcercuei 0:03b5121a232e 11874 oldContextDoc = xpctxt->doc;
pcercuei 0:03b5121a232e 11875 /*
pcercuei 0:03b5121a232e 11876 * Get the expression of this predicate.
pcercuei 0:03b5121a232e 11877 */
pcercuei 0:03b5121a232e 11878 exprOp = &ctxt->comp->steps[op->ch2];
pcercuei 0:03b5121a232e 11879 for (i = 0; i < set->nodeNr; i++) {
pcercuei 0:03b5121a232e 11880 xmlXPathObjectPtr tmp;
pcercuei 0:03b5121a232e 11881
pcercuei 0:03b5121a232e 11882 if (set->nodeTab[i] == NULL)
pcercuei 0:03b5121a232e 11883 continue;
pcercuei 0:03b5121a232e 11884
pcercuei 0:03b5121a232e 11885 contextNode = set->nodeTab[i];
pcercuei 0:03b5121a232e 11886 xpctxt->node = contextNode;
pcercuei 0:03b5121a232e 11887 xpctxt->contextSize = contextSize;
pcercuei 0:03b5121a232e 11888 xpctxt->proximityPosition = ++contextPos;
pcercuei 0:03b5121a232e 11889
pcercuei 0:03b5121a232e 11890 /*
pcercuei 0:03b5121a232e 11891 * Initialize the new set.
pcercuei 0:03b5121a232e 11892 * Also set the xpath document in case things like
pcercuei 0:03b5121a232e 11893 * key() evaluation are attempted on the predicate
pcercuei 0:03b5121a232e 11894 */
pcercuei 0:03b5121a232e 11895 if ((contextNode->type != XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 11896 (contextNode->doc != NULL))
pcercuei 0:03b5121a232e 11897 xpctxt->doc = contextNode->doc;
pcercuei 0:03b5121a232e 11898 /*
pcercuei 0:03b5121a232e 11899 * Evaluate the predicate expression with 1 context node
pcercuei 0:03b5121a232e 11900 * at a time; this node is packaged into a node set; this
pcercuei 0:03b5121a232e 11901 * node set is handed over to the evaluation mechanism.
pcercuei 0:03b5121a232e 11902 */
pcercuei 0:03b5121a232e 11903 if (contextObj == NULL)
pcercuei 0:03b5121a232e 11904 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
pcercuei 0:03b5121a232e 11905 else {
pcercuei 0:03b5121a232e 11906 if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
pcercuei 0:03b5121a232e 11907 contextNode) < 0) {
pcercuei 0:03b5121a232e 11908 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 11909 goto evaluation_exit;
pcercuei 0:03b5121a232e 11910 }
pcercuei 0:03b5121a232e 11911 }
pcercuei 0:03b5121a232e 11912
pcercuei 0:03b5121a232e 11913 frame = xmlXPathSetFrame(ctxt);
pcercuei 0:03b5121a232e 11914 valuePush(ctxt, contextObj);
pcercuei 0:03b5121a232e 11915 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
pcercuei 0:03b5121a232e 11916 tmp = valuePop(ctxt);
pcercuei 0:03b5121a232e 11917 xmlXPathPopFrame(ctxt, frame);
pcercuei 0:03b5121a232e 11918
pcercuei 0:03b5121a232e 11919 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
pcercuei 0:03b5121a232e 11920 while (tmp != contextObj) {
pcercuei 0:03b5121a232e 11921 /*
pcercuei 0:03b5121a232e 11922 * Free up the result
pcercuei 0:03b5121a232e 11923 * then pop off contextObj, which will be freed later
pcercuei 0:03b5121a232e 11924 */
pcercuei 0:03b5121a232e 11925 xmlXPathReleaseObject(xpctxt, tmp);
pcercuei 0:03b5121a232e 11926 tmp = valuePop(ctxt);
pcercuei 0:03b5121a232e 11927 }
pcercuei 0:03b5121a232e 11928 goto evaluation_error;
pcercuei 0:03b5121a232e 11929 }
pcercuei 0:03b5121a232e 11930 /* push the result back onto the stack */
pcercuei 0:03b5121a232e 11931 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 11932
pcercuei 0:03b5121a232e 11933 if (res)
pcercuei 0:03b5121a232e 11934 pos++;
pcercuei 0:03b5121a232e 11935
pcercuei 0:03b5121a232e 11936 if (res && (pos >= minPos) && (pos <= maxPos)) {
pcercuei 0:03b5121a232e 11937 /*
pcercuei 0:03b5121a232e 11938 * Fits in the requested range.
pcercuei 0:03b5121a232e 11939 */
pcercuei 0:03b5121a232e 11940 newContextSize++;
pcercuei 0:03b5121a232e 11941 if (minPos == maxPos) {
pcercuei 0:03b5121a232e 11942 /*
pcercuei 0:03b5121a232e 11943 * Only 1 node was requested.
pcercuei 0:03b5121a232e 11944 */
pcercuei 0:03b5121a232e 11945 if (contextNode->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 11946 /*
pcercuei 0:03b5121a232e 11947 * As always: take care of those nasty
pcercuei 0:03b5121a232e 11948 * namespace nodes.
pcercuei 0:03b5121a232e 11949 */
pcercuei 0:03b5121a232e 11950 set->nodeTab[i] = NULL;
pcercuei 0:03b5121a232e 11951 }
pcercuei 0:03b5121a232e 11952 xmlXPathNodeSetClear(set, hasNsNodes);
pcercuei 0:03b5121a232e 11953 set->nodeNr = 1;
pcercuei 0:03b5121a232e 11954 set->nodeTab[0] = contextNode;
pcercuei 0:03b5121a232e 11955 goto evaluation_exit;
pcercuei 0:03b5121a232e 11956 }
pcercuei 0:03b5121a232e 11957 if (pos == maxPos) {
pcercuei 0:03b5121a232e 11958 /*
pcercuei 0:03b5121a232e 11959 * We are done.
pcercuei 0:03b5121a232e 11960 */
pcercuei 0:03b5121a232e 11961 xmlXPathNodeSetClearFromPos(set, i +1, hasNsNodes);
pcercuei 0:03b5121a232e 11962 goto evaluation_exit;
pcercuei 0:03b5121a232e 11963 }
pcercuei 0:03b5121a232e 11964 } else {
pcercuei 0:03b5121a232e 11965 /*
pcercuei 0:03b5121a232e 11966 * Remove the entry from the initial node set.
pcercuei 0:03b5121a232e 11967 */
pcercuei 0:03b5121a232e 11968 set->nodeTab[i] = NULL;
pcercuei 0:03b5121a232e 11969 if (contextNode->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 11970 xmlXPathNodeSetFreeNs((xmlNsPtr) contextNode);
pcercuei 0:03b5121a232e 11971 }
pcercuei 0:03b5121a232e 11972 if (exprRes != NULL) {
pcercuei 0:03b5121a232e 11973 xmlXPathReleaseObject(ctxt->context, exprRes);
pcercuei 0:03b5121a232e 11974 exprRes = NULL;
pcercuei 0:03b5121a232e 11975 }
pcercuei 0:03b5121a232e 11976 if (ctxt->value == contextObj) {
pcercuei 0:03b5121a232e 11977 /*
pcercuei 0:03b5121a232e 11978 * Don't free the temporary XPath object holding the
pcercuei 0:03b5121a232e 11979 * context node, in order to avoid massive recreation
pcercuei 0:03b5121a232e 11980 * inside this loop.
pcercuei 0:03b5121a232e 11981 */
pcercuei 0:03b5121a232e 11982 valuePop(ctxt);
pcercuei 0:03b5121a232e 11983 xmlXPathNodeSetClear(contextObj->nodesetval, hasNsNodes);
pcercuei 0:03b5121a232e 11984 } else {
pcercuei 0:03b5121a232e 11985 /*
pcercuei 0:03b5121a232e 11986 * The object was lost in the evaluation machinery.
pcercuei 0:03b5121a232e 11987 * Can this happen? Maybe in case of internal-errors.
pcercuei 0:03b5121a232e 11988 */
pcercuei 0:03b5121a232e 11989 contextObj = NULL;
pcercuei 0:03b5121a232e 11990 }
pcercuei 0:03b5121a232e 11991 }
pcercuei 0:03b5121a232e 11992 goto evaluation_exit;
pcercuei 0:03b5121a232e 11993
pcercuei 0:03b5121a232e 11994 evaluation_error:
pcercuei 0:03b5121a232e 11995 xmlXPathNodeSetClear(set, hasNsNodes);
pcercuei 0:03b5121a232e 11996 newContextSize = 0;
pcercuei 0:03b5121a232e 11997
pcercuei 0:03b5121a232e 11998 evaluation_exit:
pcercuei 0:03b5121a232e 11999 if (contextObj != NULL) {
pcercuei 0:03b5121a232e 12000 if (ctxt->value == contextObj)
pcercuei 0:03b5121a232e 12001 valuePop(ctxt);
pcercuei 0:03b5121a232e 12002 xmlXPathReleaseObject(xpctxt, contextObj);
pcercuei 0:03b5121a232e 12003 }
pcercuei 0:03b5121a232e 12004 if (exprRes != NULL)
pcercuei 0:03b5121a232e 12005 xmlXPathReleaseObject(ctxt->context, exprRes);
pcercuei 0:03b5121a232e 12006 /*
pcercuei 0:03b5121a232e 12007 * Reset/invalidate the context.
pcercuei 0:03b5121a232e 12008 */
pcercuei 0:03b5121a232e 12009 xpctxt->node = oldContextNode;
pcercuei 0:03b5121a232e 12010 xpctxt->doc = oldContextDoc;
pcercuei 0:03b5121a232e 12011 xpctxt->contextSize = -1;
pcercuei 0:03b5121a232e 12012 xpctxt->proximityPosition = -1;
pcercuei 0:03b5121a232e 12013 return(newContextSize);
pcercuei 0:03b5121a232e 12014 }
pcercuei 0:03b5121a232e 12015 return(contextSize);
pcercuei 0:03b5121a232e 12016 }
pcercuei 0:03b5121a232e 12017
pcercuei 0:03b5121a232e 12018 static int
pcercuei 0:03b5121a232e 12019 xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 12020 xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 12021 int *maxPos)
pcercuei 0:03b5121a232e 12022 {
pcercuei 0:03b5121a232e 12023
pcercuei 0:03b5121a232e 12024 xmlXPathStepOpPtr exprOp;
pcercuei 0:03b5121a232e 12025
pcercuei 0:03b5121a232e 12026 /*
pcercuei 0:03b5121a232e 12027 * BIG NOTE: This is not intended for XPATH_OP_FILTER yet!
pcercuei 0:03b5121a232e 12028 */
pcercuei 0:03b5121a232e 12029
pcercuei 0:03b5121a232e 12030 /*
pcercuei 0:03b5121a232e 12031 * If not -1, then ch1 will point to:
pcercuei 0:03b5121a232e 12032 * 1) For predicates (XPATH_OP_PREDICATE):
pcercuei 0:03b5121a232e 12033 * - an inner predicate operator
pcercuei 0:03b5121a232e 12034 * 2) For filters (XPATH_OP_FILTER):
pcercuei 0:03b5121a232e 12035 * - an inner filter operater OR
pcercuei 0:03b5121a232e 12036 * - an expression selecting the node set.
pcercuei 0:03b5121a232e 12037 * E.g. "key('a', 'b')" or "(//foo | //bar)".
pcercuei 0:03b5121a232e 12038 */
pcercuei 0:03b5121a232e 12039 if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER))
pcercuei 0:03b5121a232e 12040 return(0);
pcercuei 0:03b5121a232e 12041
pcercuei 0:03b5121a232e 12042 if (op->ch2 != -1) {
pcercuei 0:03b5121a232e 12043 exprOp = &ctxt->comp->steps[op->ch2];
pcercuei 0:03b5121a232e 12044 } else
pcercuei 0:03b5121a232e 12045 return(0);
pcercuei 0:03b5121a232e 12046
pcercuei 0:03b5121a232e 12047 if ((exprOp != NULL) &&
pcercuei 0:03b5121a232e 12048 (exprOp->op == XPATH_OP_VALUE) &&
pcercuei 0:03b5121a232e 12049 (exprOp->value4 != NULL) &&
pcercuei 0:03b5121a232e 12050 (((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER))
pcercuei 0:03b5121a232e 12051 {
pcercuei 0:03b5121a232e 12052 /*
pcercuei 0:03b5121a232e 12053 * We have a "[n]" predicate here.
pcercuei 0:03b5121a232e 12054 * TODO: Unfortunately this simplistic test here is not
pcercuei 0:03b5121a232e 12055 * able to detect a position() predicate in compound
pcercuei 0:03b5121a232e 12056 * expressions like "[@attr = 'a" and position() = 1],
pcercuei 0:03b5121a232e 12057 * and even not the usage of position() in
pcercuei 0:03b5121a232e 12058 * "[position() = 1]"; thus - obviously - a position-range,
pcercuei 0:03b5121a232e 12059 * like it "[position() < 5]", is also not detected.
pcercuei 0:03b5121a232e 12060 * Maybe we could rewrite the AST to ease the optimization.
pcercuei 0:03b5121a232e 12061 */
pcercuei 0:03b5121a232e 12062 *maxPos = (int) ((xmlXPathObjectPtr) exprOp->value4)->floatval;
pcercuei 0:03b5121a232e 12063
pcercuei 0:03b5121a232e 12064 if (((xmlXPathObjectPtr) exprOp->value4)->floatval ==
pcercuei 0:03b5121a232e 12065 (float) *maxPos)
pcercuei 0:03b5121a232e 12066 {
pcercuei 0:03b5121a232e 12067 return(1);
pcercuei 0:03b5121a232e 12068 }
pcercuei 0:03b5121a232e 12069 }
pcercuei 0:03b5121a232e 12070 return(0);
pcercuei 0:03b5121a232e 12071 }
pcercuei 0:03b5121a232e 12072
pcercuei 0:03b5121a232e 12073 static int
pcercuei 0:03b5121a232e 12074 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 12075 xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 12076 xmlNodePtr * first, xmlNodePtr * last,
pcercuei 0:03b5121a232e 12077 int toBool)
pcercuei 0:03b5121a232e 12078 {
pcercuei 0:03b5121a232e 12079
pcercuei 0:03b5121a232e 12080 #define XP_TEST_HIT \
pcercuei 0:03b5121a232e 12081 if (hasAxisRange != 0) { \
pcercuei 0:03b5121a232e 12082 if (++pos == maxPos) { \
pcercuei 0:03b5121a232e 12083 if (addNode(seq, cur) < 0) \
pcercuei 0:03b5121a232e 12084 ctxt->error = XPATH_MEMORY_ERROR; \
pcercuei 0:03b5121a232e 12085 goto axis_range_end; } \
pcercuei 0:03b5121a232e 12086 } else { \
pcercuei 0:03b5121a232e 12087 if (addNode(seq, cur) < 0) \
pcercuei 0:03b5121a232e 12088 ctxt->error = XPATH_MEMORY_ERROR; \
pcercuei 0:03b5121a232e 12089 if (breakOnFirstHit) goto first_hit; }
pcercuei 0:03b5121a232e 12090
pcercuei 0:03b5121a232e 12091 #define XP_TEST_HIT_NS \
pcercuei 0:03b5121a232e 12092 if (hasAxisRange != 0) { \
pcercuei 0:03b5121a232e 12093 if (++pos == maxPos) { \
pcercuei 0:03b5121a232e 12094 hasNsNodes = 1; \
pcercuei 0:03b5121a232e 12095 if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
pcercuei 0:03b5121a232e 12096 ctxt->error = XPATH_MEMORY_ERROR; \
pcercuei 0:03b5121a232e 12097 goto axis_range_end; } \
pcercuei 0:03b5121a232e 12098 } else { \
pcercuei 0:03b5121a232e 12099 hasNsNodes = 1; \
pcercuei 0:03b5121a232e 12100 if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
pcercuei 0:03b5121a232e 12101 ctxt->error = XPATH_MEMORY_ERROR; \
pcercuei 0:03b5121a232e 12102 if (breakOnFirstHit) goto first_hit; }
pcercuei 0:03b5121a232e 12103
pcercuei 0:03b5121a232e 12104 xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
pcercuei 0:03b5121a232e 12105 xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
pcercuei 0:03b5121a232e 12106 xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
pcercuei 0:03b5121a232e 12107 const xmlChar *prefix = op->value4;
pcercuei 0:03b5121a232e 12108 const xmlChar *name = op->value5;
pcercuei 0:03b5121a232e 12109 const xmlChar *URI = NULL;
pcercuei 0:03b5121a232e 12110
pcercuei 0:03b5121a232e 12111 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 12112 int nbMatches = 0, prevMatches = 0;
pcercuei 0:03b5121a232e 12113 #endif
pcercuei 0:03b5121a232e 12114 int total = 0, hasNsNodes = 0;
pcercuei 0:03b5121a232e 12115 /* The popped object holding the context nodes */
pcercuei 0:03b5121a232e 12116 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 12117 /* The set of context nodes for the node tests */
pcercuei 0:03b5121a232e 12118 xmlNodeSetPtr contextSeq;
pcercuei 0:03b5121a232e 12119 int contextIdx;
pcercuei 0:03b5121a232e 12120 xmlNodePtr contextNode;
pcercuei 0:03b5121a232e 12121 /* The final resulting node set wrt to all context nodes */
pcercuei 0:03b5121a232e 12122 xmlNodeSetPtr outSeq;
pcercuei 0:03b5121a232e 12123 /*
pcercuei 0:03b5121a232e 12124 * The temporary resulting node set wrt 1 context node.
pcercuei 0:03b5121a232e 12125 * Used to feed predicate evaluation.
pcercuei 0:03b5121a232e 12126 */
pcercuei 0:03b5121a232e 12127 xmlNodeSetPtr seq;
pcercuei 0:03b5121a232e 12128 xmlNodePtr cur;
pcercuei 0:03b5121a232e 12129 /* First predicate operator */
pcercuei 0:03b5121a232e 12130 xmlXPathStepOpPtr predOp;
pcercuei 0:03b5121a232e 12131 int maxPos; /* The requested position() (when a "[n]" predicate) */
pcercuei 0:03b5121a232e 12132 int hasPredicateRange, hasAxisRange, pos, size, newSize;
pcercuei 0:03b5121a232e 12133 int breakOnFirstHit;
pcercuei 0:03b5121a232e 12134
pcercuei 0:03b5121a232e 12135 xmlXPathTraversalFunction next = NULL;
pcercuei 0:03b5121a232e 12136 int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
pcercuei 0:03b5121a232e 12137 xmlXPathNodeSetMergeFunction mergeAndClear;
pcercuei 0:03b5121a232e 12138 xmlNodePtr oldContextNode;
pcercuei 0:03b5121a232e 12139 xmlXPathContextPtr xpctxt = ctxt->context;
pcercuei 0:03b5121a232e 12140
pcercuei 0:03b5121a232e 12141
pcercuei 0:03b5121a232e 12142 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 12143 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 12144 /*
pcercuei 0:03b5121a232e 12145 * Setup namespaces.
pcercuei 0:03b5121a232e 12146 */
pcercuei 0:03b5121a232e 12147 if (prefix != NULL) {
pcercuei 0:03b5121a232e 12148 URI = xmlXPathNsLookup(xpctxt, prefix);
pcercuei 0:03b5121a232e 12149 if (URI == NULL) {
pcercuei 0:03b5121a232e 12150 xmlXPathReleaseObject(xpctxt, obj);
pcercuei 0:03b5121a232e 12151 XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
pcercuei 0:03b5121a232e 12152 }
pcercuei 0:03b5121a232e 12153 }
pcercuei 0:03b5121a232e 12154 /*
pcercuei 0:03b5121a232e 12155 * Setup axis.
pcercuei 0:03b5121a232e 12156 *
pcercuei 0:03b5121a232e 12157 * MAYBE FUTURE TODO: merging optimizations:
pcercuei 0:03b5121a232e 12158 * - If the nodes to be traversed wrt to the initial nodes and
pcercuei 0:03b5121a232e 12159 * the current axis cannot overlap, then we could avoid searching
pcercuei 0:03b5121a232e 12160 * for duplicates during the merge.
pcercuei 0:03b5121a232e 12161 * But the question is how/when to evaluate if they cannot overlap.
pcercuei 0:03b5121a232e 12162 * Example: if we know that for two initial nodes, the one is
pcercuei 0:03b5121a232e 12163 * not in the ancestor-or-self axis of the other, then we could safely
pcercuei 0:03b5121a232e 12164 * avoid a duplicate-aware merge, if the axis to be traversed is e.g.
pcercuei 0:03b5121a232e 12165 * the descendant-or-self axis.
pcercuei 0:03b5121a232e 12166 */
pcercuei 0:03b5121a232e 12167 mergeAndClear = xmlXPathNodeSetMergeAndClear;
pcercuei 0:03b5121a232e 12168 switch (axis) {
pcercuei 0:03b5121a232e 12169 case AXIS_ANCESTOR:
pcercuei 0:03b5121a232e 12170 first = NULL;
pcercuei 0:03b5121a232e 12171 next = xmlXPathNextAncestor;
pcercuei 0:03b5121a232e 12172 break;
pcercuei 0:03b5121a232e 12173 case AXIS_ANCESTOR_OR_SELF:
pcercuei 0:03b5121a232e 12174 first = NULL;
pcercuei 0:03b5121a232e 12175 next = xmlXPathNextAncestorOrSelf;
pcercuei 0:03b5121a232e 12176 break;
pcercuei 0:03b5121a232e 12177 case AXIS_ATTRIBUTE:
pcercuei 0:03b5121a232e 12178 first = NULL;
pcercuei 0:03b5121a232e 12179 last = NULL;
pcercuei 0:03b5121a232e 12180 next = xmlXPathNextAttribute;
pcercuei 0:03b5121a232e 12181 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
pcercuei 0:03b5121a232e 12182 break;
pcercuei 0:03b5121a232e 12183 case AXIS_CHILD:
pcercuei 0:03b5121a232e 12184 last = NULL;
pcercuei 0:03b5121a232e 12185 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
pcercuei 0:03b5121a232e 12186 (type == NODE_TYPE_NODE))
pcercuei 0:03b5121a232e 12187 {
pcercuei 0:03b5121a232e 12188 /*
pcercuei 0:03b5121a232e 12189 * Optimization if an element node type is 'element'.
pcercuei 0:03b5121a232e 12190 */
pcercuei 0:03b5121a232e 12191 next = xmlXPathNextChildElement;
pcercuei 0:03b5121a232e 12192 } else
pcercuei 0:03b5121a232e 12193 next = xmlXPathNextChild;
pcercuei 0:03b5121a232e 12194 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
pcercuei 0:03b5121a232e 12195 break;
pcercuei 0:03b5121a232e 12196 case AXIS_DESCENDANT:
pcercuei 0:03b5121a232e 12197 last = NULL;
pcercuei 0:03b5121a232e 12198 next = xmlXPathNextDescendant;
pcercuei 0:03b5121a232e 12199 break;
pcercuei 0:03b5121a232e 12200 case AXIS_DESCENDANT_OR_SELF:
pcercuei 0:03b5121a232e 12201 last = NULL;
pcercuei 0:03b5121a232e 12202 next = xmlXPathNextDescendantOrSelf;
pcercuei 0:03b5121a232e 12203 break;
pcercuei 0:03b5121a232e 12204 case AXIS_FOLLOWING:
pcercuei 0:03b5121a232e 12205 last = NULL;
pcercuei 0:03b5121a232e 12206 next = xmlXPathNextFollowing;
pcercuei 0:03b5121a232e 12207 break;
pcercuei 0:03b5121a232e 12208 case AXIS_FOLLOWING_SIBLING:
pcercuei 0:03b5121a232e 12209 last = NULL;
pcercuei 0:03b5121a232e 12210 next = xmlXPathNextFollowingSibling;
pcercuei 0:03b5121a232e 12211 break;
pcercuei 0:03b5121a232e 12212 case AXIS_NAMESPACE:
pcercuei 0:03b5121a232e 12213 first = NULL;
pcercuei 0:03b5121a232e 12214 last = NULL;
pcercuei 0:03b5121a232e 12215 next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
pcercuei 0:03b5121a232e 12216 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
pcercuei 0:03b5121a232e 12217 break;
pcercuei 0:03b5121a232e 12218 case AXIS_PARENT:
pcercuei 0:03b5121a232e 12219 first = NULL;
pcercuei 0:03b5121a232e 12220 next = xmlXPathNextParent;
pcercuei 0:03b5121a232e 12221 break;
pcercuei 0:03b5121a232e 12222 case AXIS_PRECEDING:
pcercuei 0:03b5121a232e 12223 first = NULL;
pcercuei 0:03b5121a232e 12224 next = xmlXPathNextPrecedingInternal;
pcercuei 0:03b5121a232e 12225 break;
pcercuei 0:03b5121a232e 12226 case AXIS_PRECEDING_SIBLING:
pcercuei 0:03b5121a232e 12227 first = NULL;
pcercuei 0:03b5121a232e 12228 next = xmlXPathNextPrecedingSibling;
pcercuei 0:03b5121a232e 12229 break;
pcercuei 0:03b5121a232e 12230 case AXIS_SELF:
pcercuei 0:03b5121a232e 12231 first = NULL;
pcercuei 0:03b5121a232e 12232 last = NULL;
pcercuei 0:03b5121a232e 12233 next = xmlXPathNextSelf;
pcercuei 0:03b5121a232e 12234 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
pcercuei 0:03b5121a232e 12235 break;
pcercuei 0:03b5121a232e 12236 }
pcercuei 0:03b5121a232e 12237
pcercuei 0:03b5121a232e 12238 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 12239 xmlXPathDebugDumpStepAxis(op,
pcercuei 0:03b5121a232e 12240 (obj->nodesetval != NULL) ? obj->nodesetval->nodeNr : 0);
pcercuei 0:03b5121a232e 12241 #endif
pcercuei 0:03b5121a232e 12242
pcercuei 0:03b5121a232e 12243 if (next == NULL) {
pcercuei 0:03b5121a232e 12244 xmlXPathReleaseObject(xpctxt, obj);
pcercuei 0:03b5121a232e 12245 return(0);
pcercuei 0:03b5121a232e 12246 }
pcercuei 0:03b5121a232e 12247 contextSeq = obj->nodesetval;
pcercuei 0:03b5121a232e 12248 if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) {
pcercuei 0:03b5121a232e 12249 xmlXPathReleaseObject(xpctxt, obj);
pcercuei 0:03b5121a232e 12250 valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, NULL));
pcercuei 0:03b5121a232e 12251 return(0);
pcercuei 0:03b5121a232e 12252 }
pcercuei 0:03b5121a232e 12253 /*
pcercuei 0:03b5121a232e 12254 * Predicate optimization ---------------------------------------------
pcercuei 0:03b5121a232e 12255 * If this step has a last predicate, which contains a position(),
pcercuei 0:03b5121a232e 12256 * then we'll optimize (although not exactly "position()", but only
pcercuei 0:03b5121a232e 12257 * the short-hand form, i.e., "[n]".
pcercuei 0:03b5121a232e 12258 *
pcercuei 0:03b5121a232e 12259 * Example - expression "/foo[parent::bar][1]":
pcercuei 0:03b5121a232e 12260 *
pcercuei 0:03b5121a232e 12261 * COLLECT 'child' 'name' 'node' foo -- op (we are here)
pcercuei 0:03b5121a232e 12262 * ROOT -- op->ch1
pcercuei 0:03b5121a232e 12263 * PREDICATE -- op->ch2 (predOp)
pcercuei 0:03b5121a232e 12264 * PREDICATE -- predOp->ch1 = [parent::bar]
pcercuei 0:03b5121a232e 12265 * SORT
pcercuei 0:03b5121a232e 12266 * COLLECT 'parent' 'name' 'node' bar
pcercuei 0:03b5121a232e 12267 * NODE
pcercuei 0:03b5121a232e 12268 * ELEM Object is a number : 1 -- predOp->ch2 = [1]
pcercuei 0:03b5121a232e 12269 *
pcercuei 0:03b5121a232e 12270 */
pcercuei 0:03b5121a232e 12271 maxPos = 0;
pcercuei 0:03b5121a232e 12272 predOp = NULL;
pcercuei 0:03b5121a232e 12273 hasPredicateRange = 0;
pcercuei 0:03b5121a232e 12274 hasAxisRange = 0;
pcercuei 0:03b5121a232e 12275 if (op->ch2 != -1) {
pcercuei 0:03b5121a232e 12276 /*
pcercuei 0:03b5121a232e 12277 * There's at least one predicate. 16 == XPATH_OP_PREDICATE
pcercuei 0:03b5121a232e 12278 */
pcercuei 0:03b5121a232e 12279 predOp = &ctxt->comp->steps[op->ch2];
pcercuei 0:03b5121a232e 12280 if (xmlXPathIsPositionalPredicate(ctxt, predOp, &maxPos)) {
pcercuei 0:03b5121a232e 12281 if (predOp->ch1 != -1) {
pcercuei 0:03b5121a232e 12282 /*
pcercuei 0:03b5121a232e 12283 * Use the next inner predicate operator.
pcercuei 0:03b5121a232e 12284 */
pcercuei 0:03b5121a232e 12285 predOp = &ctxt->comp->steps[predOp->ch1];
pcercuei 0:03b5121a232e 12286 hasPredicateRange = 1;
pcercuei 0:03b5121a232e 12287 } else {
pcercuei 0:03b5121a232e 12288 /*
pcercuei 0:03b5121a232e 12289 * There's no other predicate than the [n] predicate.
pcercuei 0:03b5121a232e 12290 */
pcercuei 0:03b5121a232e 12291 predOp = NULL;
pcercuei 0:03b5121a232e 12292 hasAxisRange = 1;
pcercuei 0:03b5121a232e 12293 }
pcercuei 0:03b5121a232e 12294 }
pcercuei 0:03b5121a232e 12295 }
pcercuei 0:03b5121a232e 12296 breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0;
pcercuei 0:03b5121a232e 12297 /*
pcercuei 0:03b5121a232e 12298 * Axis traversal -----------------------------------------------------
pcercuei 0:03b5121a232e 12299 */
pcercuei 0:03b5121a232e 12300 /*
pcercuei 0:03b5121a232e 12301 * 2.3 Node Tests
pcercuei 0:03b5121a232e 12302 * - For the attribute axis, the principal node type is attribute.
pcercuei 0:03b5121a232e 12303 * - For the namespace axis, the principal node type is namespace.
pcercuei 0:03b5121a232e 12304 * - For other axes, the principal node type is element.
pcercuei 0:03b5121a232e 12305 *
pcercuei 0:03b5121a232e 12306 * A node test * is true for any node of the
pcercuei 0:03b5121a232e 12307 * principal node type. For example, child::* will
pcercuei 0:03b5121a232e 12308 * select all element children of the context node
pcercuei 0:03b5121a232e 12309 */
pcercuei 0:03b5121a232e 12310 oldContextNode = xpctxt->node;
pcercuei 0:03b5121a232e 12311 addNode = xmlXPathNodeSetAddUnique;
pcercuei 0:03b5121a232e 12312 outSeq = NULL;
pcercuei 0:03b5121a232e 12313 seq = NULL;
pcercuei 0:03b5121a232e 12314 contextNode = NULL;
pcercuei 0:03b5121a232e 12315 contextIdx = 0;
pcercuei 0:03b5121a232e 12316
pcercuei 0:03b5121a232e 12317
pcercuei 0:03b5121a232e 12318 while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
pcercuei 0:03b5121a232e 12319 (ctxt->error == XPATH_EXPRESSION_OK)) {
pcercuei 0:03b5121a232e 12320 xpctxt->node = contextSeq->nodeTab[contextIdx++];
pcercuei 0:03b5121a232e 12321
pcercuei 0:03b5121a232e 12322 if (seq == NULL) {
pcercuei 0:03b5121a232e 12323 seq = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 12324 if (seq == NULL) {
pcercuei 0:03b5121a232e 12325 total = 0;
pcercuei 0:03b5121a232e 12326 goto error;
pcercuei 0:03b5121a232e 12327 }
pcercuei 0:03b5121a232e 12328 }
pcercuei 0:03b5121a232e 12329 /*
pcercuei 0:03b5121a232e 12330 * Traverse the axis and test the nodes.
pcercuei 0:03b5121a232e 12331 */
pcercuei 0:03b5121a232e 12332 pos = 0;
pcercuei 0:03b5121a232e 12333 cur = NULL;
pcercuei 0:03b5121a232e 12334 hasNsNodes = 0;
pcercuei 0:03b5121a232e 12335 do {
pcercuei 0:03b5121a232e 12336 cur = next(ctxt, cur);
pcercuei 0:03b5121a232e 12337 if (cur == NULL)
pcercuei 0:03b5121a232e 12338 break;
pcercuei 0:03b5121a232e 12339
pcercuei 0:03b5121a232e 12340 /*
pcercuei 0:03b5121a232e 12341 * QUESTION TODO: What does the "first" and "last" stuff do?
pcercuei 0:03b5121a232e 12342 */
pcercuei 0:03b5121a232e 12343 if ((first != NULL) && (*first != NULL)) {
pcercuei 0:03b5121a232e 12344 if (*first == cur)
pcercuei 0:03b5121a232e 12345 break;
pcercuei 0:03b5121a232e 12346 if (((total % 256) == 0) &&
pcercuei 0:03b5121a232e 12347 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
pcercuei 0:03b5121a232e 12348 (xmlXPathCmpNodesExt(*first, cur) >= 0))
pcercuei 0:03b5121a232e 12349 #else
pcercuei 0:03b5121a232e 12350 (xmlXPathCmpNodes(*first, cur) >= 0))
pcercuei 0:03b5121a232e 12351 #endif
pcercuei 0:03b5121a232e 12352 {
pcercuei 0:03b5121a232e 12353 break;
pcercuei 0:03b5121a232e 12354 }
pcercuei 0:03b5121a232e 12355 }
pcercuei 0:03b5121a232e 12356 if ((last != NULL) && (*last != NULL)) {
pcercuei 0:03b5121a232e 12357 if (*last == cur)
pcercuei 0:03b5121a232e 12358 break;
pcercuei 0:03b5121a232e 12359 if (((total % 256) == 0) &&
pcercuei 0:03b5121a232e 12360 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
pcercuei 0:03b5121a232e 12361 (xmlXPathCmpNodesExt(cur, *last) >= 0))
pcercuei 0:03b5121a232e 12362 #else
pcercuei 0:03b5121a232e 12363 (xmlXPathCmpNodes(cur, *last) >= 0))
pcercuei 0:03b5121a232e 12364 #endif
pcercuei 0:03b5121a232e 12365 {
pcercuei 0:03b5121a232e 12366 break;
pcercuei 0:03b5121a232e 12367 }
pcercuei 0:03b5121a232e 12368 }
pcercuei 0:03b5121a232e 12369
pcercuei 0:03b5121a232e 12370 total++;
pcercuei 0:03b5121a232e 12371
pcercuei 0:03b5121a232e 12372 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 12373 xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
pcercuei 0:03b5121a232e 12374 #endif
pcercuei 0:03b5121a232e 12375
pcercuei 0:03b5121a232e 12376 switch (test) {
pcercuei 0:03b5121a232e 12377 case NODE_TEST_NONE:
pcercuei 0:03b5121a232e 12378 total = 0;
pcercuei 0:03b5121a232e 12379 STRANGE
pcercuei 0:03b5121a232e 12380 goto error;
pcercuei 0:03b5121a232e 12381 case NODE_TEST_TYPE:
pcercuei 0:03b5121a232e 12382 /*
pcercuei 0:03b5121a232e 12383 * TODO: Don't we need to use
pcercuei 0:03b5121a232e 12384 * xmlXPathNodeSetAddNs() for namespace nodes here?
pcercuei 0:03b5121a232e 12385 * Surprisingly, some c14n tests fail, if we do this.
pcercuei 0:03b5121a232e 12386 */
pcercuei 0:03b5121a232e 12387 if (type == NODE_TYPE_NODE) {
pcercuei 0:03b5121a232e 12388 switch (cur->type) {
pcercuei 0:03b5121a232e 12389 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 12390 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 12391 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 12392 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 12393 #endif
pcercuei 0:03b5121a232e 12394 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 12395 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 12396 case XML_PI_NODE:
pcercuei 0:03b5121a232e 12397 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 12398 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 12399 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 12400 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 12401 XP_TEST_HIT
pcercuei 0:03b5121a232e 12402 break;
pcercuei 0:03b5121a232e 12403 default:
pcercuei 0:03b5121a232e 12404 break;
pcercuei 0:03b5121a232e 12405 }
pcercuei 0:03b5121a232e 12406 } else if (cur->type == type) {
pcercuei 0:03b5121a232e 12407 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 12408 XP_TEST_HIT_NS
pcercuei 0:03b5121a232e 12409 else
pcercuei 0:03b5121a232e 12410 XP_TEST_HIT
pcercuei 0:03b5121a232e 12411 } else if ((type == NODE_TYPE_TEXT) &&
pcercuei 0:03b5121a232e 12412 (cur->type == XML_CDATA_SECTION_NODE))
pcercuei 0:03b5121a232e 12413 {
pcercuei 0:03b5121a232e 12414 XP_TEST_HIT
pcercuei 0:03b5121a232e 12415 }
pcercuei 0:03b5121a232e 12416 break;
pcercuei 0:03b5121a232e 12417 case NODE_TEST_PI:
pcercuei 0:03b5121a232e 12418 if ((cur->type == XML_PI_NODE) &&
pcercuei 0:03b5121a232e 12419 ((name == NULL) || xmlStrEqual(name, cur->name)))
pcercuei 0:03b5121a232e 12420 {
pcercuei 0:03b5121a232e 12421 XP_TEST_HIT
pcercuei 0:03b5121a232e 12422 }
pcercuei 0:03b5121a232e 12423 break;
pcercuei 0:03b5121a232e 12424 case NODE_TEST_ALL:
pcercuei 0:03b5121a232e 12425 if (axis == AXIS_ATTRIBUTE) {
pcercuei 0:03b5121a232e 12426 if (cur->type == XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 12427 {
pcercuei 0:03b5121a232e 12428 if (prefix == NULL)
pcercuei 0:03b5121a232e 12429 {
pcercuei 0:03b5121a232e 12430 XP_TEST_HIT
pcercuei 0:03b5121a232e 12431 } else if ((cur->ns != NULL) &&
pcercuei 0:03b5121a232e 12432 (xmlStrEqual(URI, cur->ns->href)))
pcercuei 0:03b5121a232e 12433 {
pcercuei 0:03b5121a232e 12434 XP_TEST_HIT
pcercuei 0:03b5121a232e 12435 }
pcercuei 0:03b5121a232e 12436 }
pcercuei 0:03b5121a232e 12437 } else if (axis == AXIS_NAMESPACE) {
pcercuei 0:03b5121a232e 12438 if (cur->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 12439 {
pcercuei 0:03b5121a232e 12440 XP_TEST_HIT_NS
pcercuei 0:03b5121a232e 12441 }
pcercuei 0:03b5121a232e 12442 } else {
pcercuei 0:03b5121a232e 12443 if (cur->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 12444 if (prefix == NULL)
pcercuei 0:03b5121a232e 12445 {
pcercuei 0:03b5121a232e 12446 XP_TEST_HIT
pcercuei 0:03b5121a232e 12447
pcercuei 0:03b5121a232e 12448 } else if ((cur->ns != NULL) &&
pcercuei 0:03b5121a232e 12449 (xmlStrEqual(URI, cur->ns->href)))
pcercuei 0:03b5121a232e 12450 {
pcercuei 0:03b5121a232e 12451 XP_TEST_HIT
pcercuei 0:03b5121a232e 12452 }
pcercuei 0:03b5121a232e 12453 }
pcercuei 0:03b5121a232e 12454 }
pcercuei 0:03b5121a232e 12455 break;
pcercuei 0:03b5121a232e 12456 case NODE_TEST_NS:{
pcercuei 0:03b5121a232e 12457 TODO;
pcercuei 0:03b5121a232e 12458 break;
pcercuei 0:03b5121a232e 12459 }
pcercuei 0:03b5121a232e 12460 case NODE_TEST_NAME:
pcercuei 0:03b5121a232e 12461 if (axis == AXIS_ATTRIBUTE) {
pcercuei 0:03b5121a232e 12462 if (cur->type != XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 12463 break;
pcercuei 0:03b5121a232e 12464 } else if (axis == AXIS_NAMESPACE) {
pcercuei 0:03b5121a232e 12465 if (cur->type != XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 12466 break;
pcercuei 0:03b5121a232e 12467 } else {
pcercuei 0:03b5121a232e 12468 if (cur->type != XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 12469 break;
pcercuei 0:03b5121a232e 12470 }
pcercuei 0:03b5121a232e 12471 switch (cur->type) {
pcercuei 0:03b5121a232e 12472 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 12473 if (xmlStrEqual(name, cur->name)) {
pcercuei 0:03b5121a232e 12474 if (prefix == NULL) {
pcercuei 0:03b5121a232e 12475 if (cur->ns == NULL)
pcercuei 0:03b5121a232e 12476 {
pcercuei 0:03b5121a232e 12477 XP_TEST_HIT
pcercuei 0:03b5121a232e 12478 }
pcercuei 0:03b5121a232e 12479 } else {
pcercuei 0:03b5121a232e 12480 if ((cur->ns != NULL) &&
pcercuei 0:03b5121a232e 12481 (xmlStrEqual(URI, cur->ns->href)))
pcercuei 0:03b5121a232e 12482 {
pcercuei 0:03b5121a232e 12483 XP_TEST_HIT
pcercuei 0:03b5121a232e 12484 }
pcercuei 0:03b5121a232e 12485 }
pcercuei 0:03b5121a232e 12486 }
pcercuei 0:03b5121a232e 12487 break;
pcercuei 0:03b5121a232e 12488 case XML_ATTRIBUTE_NODE:{
pcercuei 0:03b5121a232e 12489 xmlAttrPtr attr = (xmlAttrPtr) cur;
pcercuei 0:03b5121a232e 12490
pcercuei 0:03b5121a232e 12491 if (xmlStrEqual(name, attr->name)) {
pcercuei 0:03b5121a232e 12492 if (prefix == NULL) {
pcercuei 0:03b5121a232e 12493 if ((attr->ns == NULL) ||
pcercuei 0:03b5121a232e 12494 (attr->ns->prefix == NULL))
pcercuei 0:03b5121a232e 12495 {
pcercuei 0:03b5121a232e 12496 XP_TEST_HIT
pcercuei 0:03b5121a232e 12497 }
pcercuei 0:03b5121a232e 12498 } else {
pcercuei 0:03b5121a232e 12499 if ((attr->ns != NULL) &&
pcercuei 0:03b5121a232e 12500 (xmlStrEqual(URI,
pcercuei 0:03b5121a232e 12501 attr->ns->href)))
pcercuei 0:03b5121a232e 12502 {
pcercuei 0:03b5121a232e 12503 XP_TEST_HIT
pcercuei 0:03b5121a232e 12504 }
pcercuei 0:03b5121a232e 12505 }
pcercuei 0:03b5121a232e 12506 }
pcercuei 0:03b5121a232e 12507 break;
pcercuei 0:03b5121a232e 12508 }
pcercuei 0:03b5121a232e 12509 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 12510 if (cur->type == XML_NAMESPACE_DECL) {
pcercuei 0:03b5121a232e 12511 xmlNsPtr ns = (xmlNsPtr) cur;
pcercuei 0:03b5121a232e 12512
pcercuei 0:03b5121a232e 12513 if ((ns->prefix != NULL) && (name != NULL)
pcercuei 0:03b5121a232e 12514 && (xmlStrEqual(ns->prefix, name)))
pcercuei 0:03b5121a232e 12515 {
pcercuei 0:03b5121a232e 12516 XP_TEST_HIT_NS
pcercuei 0:03b5121a232e 12517 }
pcercuei 0:03b5121a232e 12518 }
pcercuei 0:03b5121a232e 12519 break;
pcercuei 0:03b5121a232e 12520 default:
pcercuei 0:03b5121a232e 12521 break;
pcercuei 0:03b5121a232e 12522 }
pcercuei 0:03b5121a232e 12523 break;
pcercuei 0:03b5121a232e 12524 } /* switch(test) */
pcercuei 0:03b5121a232e 12525 } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
pcercuei 0:03b5121a232e 12526
pcercuei 0:03b5121a232e 12527 goto apply_predicates;
pcercuei 0:03b5121a232e 12528
pcercuei 0:03b5121a232e 12529 axis_range_end: /* ----------------------------------------------------- */
pcercuei 0:03b5121a232e 12530 /*
pcercuei 0:03b5121a232e 12531 * We have a "/foo[n]", and position() = n was reached.
pcercuei 0:03b5121a232e 12532 * Note that we can have as well "/foo/::parent::foo[1]", so
pcercuei 0:03b5121a232e 12533 * a duplicate-aware merge is still needed.
pcercuei 0:03b5121a232e 12534 * Merge with the result.
pcercuei 0:03b5121a232e 12535 */
pcercuei 0:03b5121a232e 12536 if (outSeq == NULL) {
pcercuei 0:03b5121a232e 12537 outSeq = seq;
pcercuei 0:03b5121a232e 12538 seq = NULL;
pcercuei 0:03b5121a232e 12539 } else
pcercuei 0:03b5121a232e 12540 outSeq = mergeAndClear(outSeq, seq, 0);
pcercuei 0:03b5121a232e 12541 /*
pcercuei 0:03b5121a232e 12542 * Break if only a true/false result was requested.
pcercuei 0:03b5121a232e 12543 */
pcercuei 0:03b5121a232e 12544 if (toBool)
pcercuei 0:03b5121a232e 12545 break;
pcercuei 0:03b5121a232e 12546 continue;
pcercuei 0:03b5121a232e 12547
pcercuei 0:03b5121a232e 12548 first_hit: /* ---------------------------------------------------------- */
pcercuei 0:03b5121a232e 12549 /*
pcercuei 0:03b5121a232e 12550 * Break if only a true/false result was requested and
pcercuei 0:03b5121a232e 12551 * no predicates existed and a node test succeeded.
pcercuei 0:03b5121a232e 12552 */
pcercuei 0:03b5121a232e 12553 if (outSeq == NULL) {
pcercuei 0:03b5121a232e 12554 outSeq = seq;
pcercuei 0:03b5121a232e 12555 seq = NULL;
pcercuei 0:03b5121a232e 12556 } else
pcercuei 0:03b5121a232e 12557 outSeq = mergeAndClear(outSeq, seq, 0);
pcercuei 0:03b5121a232e 12558 break;
pcercuei 0:03b5121a232e 12559
pcercuei 0:03b5121a232e 12560 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 12561 if (seq != NULL)
pcercuei 0:03b5121a232e 12562 nbMatches += seq->nodeNr;
pcercuei 0:03b5121a232e 12563 #endif
pcercuei 0:03b5121a232e 12564
pcercuei 0:03b5121a232e 12565 apply_predicates: /* --------------------------------------------------- */
pcercuei 0:03b5121a232e 12566 if (ctxt->error != XPATH_EXPRESSION_OK)
pcercuei 0:03b5121a232e 12567 goto error;
pcercuei 0:03b5121a232e 12568
pcercuei 0:03b5121a232e 12569 /*
pcercuei 0:03b5121a232e 12570 * Apply predicates.
pcercuei 0:03b5121a232e 12571 */
pcercuei 0:03b5121a232e 12572 if ((predOp != NULL) && (seq->nodeNr > 0)) {
pcercuei 0:03b5121a232e 12573 /*
pcercuei 0:03b5121a232e 12574 * E.g. when we have a "/foo[some expression][n]".
pcercuei 0:03b5121a232e 12575 */
pcercuei 0:03b5121a232e 12576 /*
pcercuei 0:03b5121a232e 12577 * QUESTION TODO: The old predicate evaluation took into
pcercuei 0:03b5121a232e 12578 * account location-sets.
pcercuei 0:03b5121a232e 12579 * (E.g. ctxt->value->type == XPATH_LOCATIONSET)
pcercuei 0:03b5121a232e 12580 * Do we expect such a set here?
pcercuei 0:03b5121a232e 12581 * All what I learned now from the evaluation semantics
pcercuei 0:03b5121a232e 12582 * does not indicate that a location-set will be processed
pcercuei 0:03b5121a232e 12583 * here, so this looks OK.
pcercuei 0:03b5121a232e 12584 */
pcercuei 0:03b5121a232e 12585 /*
pcercuei 0:03b5121a232e 12586 * Iterate over all predicates, starting with the outermost
pcercuei 0:03b5121a232e 12587 * predicate.
pcercuei 0:03b5121a232e 12588 * TODO: Problem: we cannot execute the inner predicates first
pcercuei 0:03b5121a232e 12589 * since we cannot go back *up* the operator tree!
pcercuei 0:03b5121a232e 12590 * Options we have:
pcercuei 0:03b5121a232e 12591 * 1) Use of recursive functions (like is it currently done
pcercuei 0:03b5121a232e 12592 * via xmlXPathCompOpEval())
pcercuei 0:03b5121a232e 12593 * 2) Add a predicate evaluation information stack to the
pcercuei 0:03b5121a232e 12594 * context struct
pcercuei 0:03b5121a232e 12595 * 3) Change the way the operators are linked; we need a
pcercuei 0:03b5121a232e 12596 * "parent" field on xmlXPathStepOp
pcercuei 0:03b5121a232e 12597 *
pcercuei 0:03b5121a232e 12598 * For the moment, I'll try to solve this with a recursive
pcercuei 0:03b5121a232e 12599 * function: xmlXPathCompOpEvalPredicate().
pcercuei 0:03b5121a232e 12600 */
pcercuei 0:03b5121a232e 12601 size = seq->nodeNr;
pcercuei 0:03b5121a232e 12602 if (hasPredicateRange != 0)
pcercuei 0:03b5121a232e 12603 newSize = xmlXPathCompOpEvalPositionalPredicate(ctxt,
pcercuei 0:03b5121a232e 12604 predOp, seq, size, maxPos, maxPos, hasNsNodes);
pcercuei 0:03b5121a232e 12605 else
pcercuei 0:03b5121a232e 12606 newSize = xmlXPathCompOpEvalPredicate(ctxt,
pcercuei 0:03b5121a232e 12607 predOp, seq, size, hasNsNodes);
pcercuei 0:03b5121a232e 12608
pcercuei 0:03b5121a232e 12609 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 12610 total = 0;
pcercuei 0:03b5121a232e 12611 goto error;
pcercuei 0:03b5121a232e 12612 }
pcercuei 0:03b5121a232e 12613 /*
pcercuei 0:03b5121a232e 12614 * Add the filtered set of nodes to the result node set.
pcercuei 0:03b5121a232e 12615 */
pcercuei 0:03b5121a232e 12616 if (newSize == 0) {
pcercuei 0:03b5121a232e 12617 /*
pcercuei 0:03b5121a232e 12618 * The predicates filtered all nodes out.
pcercuei 0:03b5121a232e 12619 */
pcercuei 0:03b5121a232e 12620 xmlXPathNodeSetClear(seq, hasNsNodes);
pcercuei 0:03b5121a232e 12621 } else if (seq->nodeNr > 0) {
pcercuei 0:03b5121a232e 12622 /*
pcercuei 0:03b5121a232e 12623 * Add to result set.
pcercuei 0:03b5121a232e 12624 */
pcercuei 0:03b5121a232e 12625 if (outSeq == NULL) {
pcercuei 0:03b5121a232e 12626 if (size != newSize) {
pcercuei 0:03b5121a232e 12627 /*
pcercuei 0:03b5121a232e 12628 * We need to merge and clear here, since
pcercuei 0:03b5121a232e 12629 * the sequence will contained NULLed entries.
pcercuei 0:03b5121a232e 12630 */
pcercuei 0:03b5121a232e 12631 outSeq = mergeAndClear(NULL, seq, 1);
pcercuei 0:03b5121a232e 12632 } else {
pcercuei 0:03b5121a232e 12633 outSeq = seq;
pcercuei 0:03b5121a232e 12634 seq = NULL;
pcercuei 0:03b5121a232e 12635 }
pcercuei 0:03b5121a232e 12636 } else
pcercuei 0:03b5121a232e 12637 outSeq = mergeAndClear(outSeq, seq,
pcercuei 0:03b5121a232e 12638 (size != newSize) ? 1: 0);
pcercuei 0:03b5121a232e 12639 /*
pcercuei 0:03b5121a232e 12640 * Break if only a true/false result was requested.
pcercuei 0:03b5121a232e 12641 */
pcercuei 0:03b5121a232e 12642 if (toBool)
pcercuei 0:03b5121a232e 12643 break;
pcercuei 0:03b5121a232e 12644 }
pcercuei 0:03b5121a232e 12645 } else if (seq->nodeNr > 0) {
pcercuei 0:03b5121a232e 12646 /*
pcercuei 0:03b5121a232e 12647 * Add to result set.
pcercuei 0:03b5121a232e 12648 */
pcercuei 0:03b5121a232e 12649 if (outSeq == NULL) {
pcercuei 0:03b5121a232e 12650 outSeq = seq;
pcercuei 0:03b5121a232e 12651 seq = NULL;
pcercuei 0:03b5121a232e 12652 } else {
pcercuei 0:03b5121a232e 12653 outSeq = mergeAndClear(outSeq, seq, 0);
pcercuei 0:03b5121a232e 12654 }
pcercuei 0:03b5121a232e 12655 }
pcercuei 0:03b5121a232e 12656 }
pcercuei 0:03b5121a232e 12657
pcercuei 0:03b5121a232e 12658 error:
pcercuei 0:03b5121a232e 12659 if ((obj->boolval) && (obj->user != NULL)) {
pcercuei 0:03b5121a232e 12660 /*
pcercuei 0:03b5121a232e 12661 * QUESTION TODO: What does this do and why?
pcercuei 0:03b5121a232e 12662 * TODO: Do we have to do this also for the "error"
pcercuei 0:03b5121a232e 12663 * cleanup further down?
pcercuei 0:03b5121a232e 12664 */
pcercuei 0:03b5121a232e 12665 ctxt->value->boolval = 1;
pcercuei 0:03b5121a232e 12666 ctxt->value->user = obj->user;
pcercuei 0:03b5121a232e 12667 obj->user = NULL;
pcercuei 0:03b5121a232e 12668 obj->boolval = 0;
pcercuei 0:03b5121a232e 12669 }
pcercuei 0:03b5121a232e 12670 xmlXPathReleaseObject(xpctxt, obj);
pcercuei 0:03b5121a232e 12671
pcercuei 0:03b5121a232e 12672 /*
pcercuei 0:03b5121a232e 12673 * Ensure we return at least an emtpy set.
pcercuei 0:03b5121a232e 12674 */
pcercuei 0:03b5121a232e 12675 if (outSeq == NULL) {
pcercuei 0:03b5121a232e 12676 if ((seq != NULL) && (seq->nodeNr == 0))
pcercuei 0:03b5121a232e 12677 outSeq = seq;
pcercuei 0:03b5121a232e 12678 else
pcercuei 0:03b5121a232e 12679 outSeq = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 12680 /* XXX what if xmlXPathNodeSetCreate returned NULL here? */
pcercuei 0:03b5121a232e 12681 }
pcercuei 0:03b5121a232e 12682 if ((seq != NULL) && (seq != outSeq)) {
pcercuei 0:03b5121a232e 12683 xmlXPathFreeNodeSet(seq);
pcercuei 0:03b5121a232e 12684 }
pcercuei 0:03b5121a232e 12685 /*
pcercuei 0:03b5121a232e 12686 * Hand over the result. Better to push the set also in
pcercuei 0:03b5121a232e 12687 * case of errors.
pcercuei 0:03b5121a232e 12688 */
pcercuei 0:03b5121a232e 12689 valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, outSeq));
pcercuei 0:03b5121a232e 12690 /*
pcercuei 0:03b5121a232e 12691 * Reset the context node.
pcercuei 0:03b5121a232e 12692 */
pcercuei 0:03b5121a232e 12693 xpctxt->node = oldContextNode;
pcercuei 0:03b5121a232e 12694
pcercuei 0:03b5121a232e 12695 #ifdef DEBUG_STEP
pcercuei 0:03b5121a232e 12696 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 12697 "\nExamined %d nodes, found %d nodes at that step\n",
pcercuei 0:03b5121a232e 12698 total, nbMatches);
pcercuei 0:03b5121a232e 12699 #endif
pcercuei 0:03b5121a232e 12700
pcercuei 0:03b5121a232e 12701 return(total);
pcercuei 0:03b5121a232e 12702 }
pcercuei 0:03b5121a232e 12703
pcercuei 0:03b5121a232e 12704 static int
pcercuei 0:03b5121a232e 12705 xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 12706 xmlXPathStepOpPtr op, xmlNodePtr * first);
pcercuei 0:03b5121a232e 12707
pcercuei 0:03b5121a232e 12708 /**
pcercuei 0:03b5121a232e 12709 * xmlXPathCompOpEvalFirst:
pcercuei 0:03b5121a232e 12710 * @ctxt: the XPath parser context with the compiled expression
pcercuei 0:03b5121a232e 12711 * @op: an XPath compiled operation
pcercuei 0:03b5121a232e 12712 * @first: the first elem found so far
pcercuei 0:03b5121a232e 12713 *
pcercuei 0:03b5121a232e 12714 * Evaluate the Precompiled XPath operation searching only the first
pcercuei 0:03b5121a232e 12715 * element in document order
pcercuei 0:03b5121a232e 12716 *
pcercuei 0:03b5121a232e 12717 * Returns the number of examined objects.
pcercuei 0:03b5121a232e 12718 */
pcercuei 0:03b5121a232e 12719 static int
pcercuei 0:03b5121a232e 12720 xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 12721 xmlXPathStepOpPtr op, xmlNodePtr * first)
pcercuei 0:03b5121a232e 12722 {
pcercuei 0:03b5121a232e 12723 int total = 0, cur;
pcercuei 0:03b5121a232e 12724 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 12725 xmlXPathObjectPtr arg1, arg2;
pcercuei 0:03b5121a232e 12726
pcercuei 0:03b5121a232e 12727 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12728 comp = ctxt->comp;
pcercuei 0:03b5121a232e 12729 switch (op->op) {
pcercuei 0:03b5121a232e 12730 case XPATH_OP_END:
pcercuei 0:03b5121a232e 12731 return (0);
pcercuei 0:03b5121a232e 12732 case XPATH_OP_UNION:
pcercuei 0:03b5121a232e 12733 total =
pcercuei 0:03b5121a232e 12734 xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
pcercuei 0:03b5121a232e 12735 first);
pcercuei 0:03b5121a232e 12736 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12737 if ((ctxt->value != NULL)
pcercuei 0:03b5121a232e 12738 && (ctxt->value->type == XPATH_NODESET)
pcercuei 0:03b5121a232e 12739 && (ctxt->value->nodesetval != NULL)
pcercuei 0:03b5121a232e 12740 && (ctxt->value->nodesetval->nodeNr >= 1)) {
pcercuei 0:03b5121a232e 12741 /*
pcercuei 0:03b5121a232e 12742 * limit tree traversing to first node in the result
pcercuei 0:03b5121a232e 12743 */
pcercuei 0:03b5121a232e 12744 /*
pcercuei 0:03b5121a232e 12745 * OPTIMIZE TODO: This implicitely sorts
pcercuei 0:03b5121a232e 12746 * the result, even if not needed. E.g. if the argument
pcercuei 0:03b5121a232e 12747 * of the count() function, no sorting is needed.
pcercuei 0:03b5121a232e 12748 * OPTIMIZE TODO: How do we know if the node-list wasn't
pcercuei 0:03b5121a232e 12749 * aready sorted?
pcercuei 0:03b5121a232e 12750 */
pcercuei 0:03b5121a232e 12751 if (ctxt->value->nodesetval->nodeNr > 1)
pcercuei 0:03b5121a232e 12752 xmlXPathNodeSetSort(ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 12753 *first = ctxt->value->nodesetval->nodeTab[0];
pcercuei 0:03b5121a232e 12754 }
pcercuei 0:03b5121a232e 12755 cur =
pcercuei 0:03b5121a232e 12756 xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
pcercuei 0:03b5121a232e 12757 first);
pcercuei 0:03b5121a232e 12758 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12759 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 12760 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 12761
pcercuei 0:03b5121a232e 12762 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 12763 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 12764
pcercuei 0:03b5121a232e 12765 arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
pcercuei 0:03b5121a232e 12766 arg2->nodesetval);
pcercuei 0:03b5121a232e 12767 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 12768 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 12769 /* optimizer */
pcercuei 0:03b5121a232e 12770 if (total > cur)
pcercuei 0:03b5121a232e 12771 xmlXPathCompSwap(op);
pcercuei 0:03b5121a232e 12772 return (total + cur);
pcercuei 0:03b5121a232e 12773 case XPATH_OP_ROOT:
pcercuei 0:03b5121a232e 12774 xmlXPathRoot(ctxt);
pcercuei 0:03b5121a232e 12775 return (0);
pcercuei 0:03b5121a232e 12776 case XPATH_OP_NODE:
pcercuei 0:03b5121a232e 12777 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 12778 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 12779 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12780 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 12781 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 12782 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12783 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 12784 ctxt->context->node));
pcercuei 0:03b5121a232e 12785 return (total);
pcercuei 0:03b5121a232e 12786 case XPATH_OP_RESET:
pcercuei 0:03b5121a232e 12787 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 12788 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 12789 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12790 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 12791 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 12792 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12793 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 12794 return (total);
pcercuei 0:03b5121a232e 12795 case XPATH_OP_COLLECT:{
pcercuei 0:03b5121a232e 12796 if (op->ch1 == -1)
pcercuei 0:03b5121a232e 12797 return (total);
pcercuei 0:03b5121a232e 12798
pcercuei 0:03b5121a232e 12799 total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 12800 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12801
pcercuei 0:03b5121a232e 12802 total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL, 0);
pcercuei 0:03b5121a232e 12803 return (total);
pcercuei 0:03b5121a232e 12804 }
pcercuei 0:03b5121a232e 12805 case XPATH_OP_VALUE:
pcercuei 0:03b5121a232e 12806 valuePush(ctxt,
pcercuei 0:03b5121a232e 12807 xmlXPathCacheObjectCopy(ctxt->context,
pcercuei 0:03b5121a232e 12808 (xmlXPathObjectPtr) op->value4));
pcercuei 0:03b5121a232e 12809 return (0);
pcercuei 0:03b5121a232e 12810 case XPATH_OP_SORT:
pcercuei 0:03b5121a232e 12811 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 12812 total +=
pcercuei 0:03b5121a232e 12813 xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
pcercuei 0:03b5121a232e 12814 first);
pcercuei 0:03b5121a232e 12815 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12816 if ((ctxt->value != NULL)
pcercuei 0:03b5121a232e 12817 && (ctxt->value->type == XPATH_NODESET)
pcercuei 0:03b5121a232e 12818 && (ctxt->value->nodesetval != NULL)
pcercuei 0:03b5121a232e 12819 && (ctxt->value->nodesetval->nodeNr > 1))
pcercuei 0:03b5121a232e 12820 xmlXPathNodeSetSort(ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 12821 return (total);
pcercuei 0:03b5121a232e 12822 #ifdef XP_OPTIMIZED_FILTER_FIRST
pcercuei 0:03b5121a232e 12823 case XPATH_OP_FILTER:
pcercuei 0:03b5121a232e 12824 total += xmlXPathCompOpEvalFilterFirst(ctxt, op, first);
pcercuei 0:03b5121a232e 12825 return (total);
pcercuei 0:03b5121a232e 12826 #endif
pcercuei 0:03b5121a232e 12827 default:
pcercuei 0:03b5121a232e 12828 return (xmlXPathCompOpEval(ctxt, op));
pcercuei 0:03b5121a232e 12829 }
pcercuei 0:03b5121a232e 12830 }
pcercuei 0:03b5121a232e 12831
pcercuei 0:03b5121a232e 12832 /**
pcercuei 0:03b5121a232e 12833 * xmlXPathCompOpEvalLast:
pcercuei 0:03b5121a232e 12834 * @ctxt: the XPath parser context with the compiled expression
pcercuei 0:03b5121a232e 12835 * @op: an XPath compiled operation
pcercuei 0:03b5121a232e 12836 * @last: the last elem found so far
pcercuei 0:03b5121a232e 12837 *
pcercuei 0:03b5121a232e 12838 * Evaluate the Precompiled XPath operation searching only the last
pcercuei 0:03b5121a232e 12839 * element in document order
pcercuei 0:03b5121a232e 12840 *
pcercuei 0:03b5121a232e 12841 * Returns the number of nodes traversed
pcercuei 0:03b5121a232e 12842 */
pcercuei 0:03b5121a232e 12843 static int
pcercuei 0:03b5121a232e 12844 xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 12845 xmlNodePtr * last)
pcercuei 0:03b5121a232e 12846 {
pcercuei 0:03b5121a232e 12847 int total = 0, cur;
pcercuei 0:03b5121a232e 12848 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 12849 xmlXPathObjectPtr arg1, arg2;
pcercuei 0:03b5121a232e 12850 xmlNodePtr bak;
pcercuei 0:03b5121a232e 12851 xmlDocPtr bakd;
pcercuei 0:03b5121a232e 12852 int pp;
pcercuei 0:03b5121a232e 12853 int cs;
pcercuei 0:03b5121a232e 12854
pcercuei 0:03b5121a232e 12855 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12856 comp = ctxt->comp;
pcercuei 0:03b5121a232e 12857 switch (op->op) {
pcercuei 0:03b5121a232e 12858 case XPATH_OP_END:
pcercuei 0:03b5121a232e 12859 return (0);
pcercuei 0:03b5121a232e 12860 case XPATH_OP_UNION:
pcercuei 0:03b5121a232e 12861 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 12862 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 12863 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 12864 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 12865 total =
pcercuei 0:03b5121a232e 12866 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
pcercuei 0:03b5121a232e 12867 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12868 if ((ctxt->value != NULL)
pcercuei 0:03b5121a232e 12869 && (ctxt->value->type == XPATH_NODESET)
pcercuei 0:03b5121a232e 12870 && (ctxt->value->nodesetval != NULL)
pcercuei 0:03b5121a232e 12871 && (ctxt->value->nodesetval->nodeNr >= 1)) {
pcercuei 0:03b5121a232e 12872 /*
pcercuei 0:03b5121a232e 12873 * limit tree traversing to first node in the result
pcercuei 0:03b5121a232e 12874 */
pcercuei 0:03b5121a232e 12875 if (ctxt->value->nodesetval->nodeNr > 1)
pcercuei 0:03b5121a232e 12876 xmlXPathNodeSetSort(ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 12877 *last =
pcercuei 0:03b5121a232e 12878 ctxt->value->nodesetval->nodeTab[ctxt->value->
pcercuei 0:03b5121a232e 12879 nodesetval->nodeNr -
pcercuei 0:03b5121a232e 12880 1];
pcercuei 0:03b5121a232e 12881 }
pcercuei 0:03b5121a232e 12882 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 12883 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 12884 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 12885 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 12886 cur =
pcercuei 0:03b5121a232e 12887 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
pcercuei 0:03b5121a232e 12888 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12889 if ((ctxt->value != NULL)
pcercuei 0:03b5121a232e 12890 && (ctxt->value->type == XPATH_NODESET)
pcercuei 0:03b5121a232e 12891 && (ctxt->value->nodesetval != NULL)
pcercuei 0:03b5121a232e 12892 && (ctxt->value->nodesetval->nodeNr >= 1)) { /* TODO: NOP ? */
pcercuei 0:03b5121a232e 12893 }
pcercuei 0:03b5121a232e 12894 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 12895 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 12896
pcercuei 0:03b5121a232e 12897 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 12898 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 12899
pcercuei 0:03b5121a232e 12900 arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
pcercuei 0:03b5121a232e 12901 arg2->nodesetval);
pcercuei 0:03b5121a232e 12902 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 12903 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 12904 /* optimizer */
pcercuei 0:03b5121a232e 12905 if (total > cur)
pcercuei 0:03b5121a232e 12906 xmlXPathCompSwap(op);
pcercuei 0:03b5121a232e 12907 return (total + cur);
pcercuei 0:03b5121a232e 12908 case XPATH_OP_ROOT:
pcercuei 0:03b5121a232e 12909 xmlXPathRoot(ctxt);
pcercuei 0:03b5121a232e 12910 return (0);
pcercuei 0:03b5121a232e 12911 case XPATH_OP_NODE:
pcercuei 0:03b5121a232e 12912 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 12913 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 12914 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12915 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 12916 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 12917 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12918 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 12919 ctxt->context->node));
pcercuei 0:03b5121a232e 12920 return (total);
pcercuei 0:03b5121a232e 12921 case XPATH_OP_RESET:
pcercuei 0:03b5121a232e 12922 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 12923 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 12924 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12925 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 12926 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 12927 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12928 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 12929 return (total);
pcercuei 0:03b5121a232e 12930 case XPATH_OP_COLLECT:{
pcercuei 0:03b5121a232e 12931 if (op->ch1 == -1)
pcercuei 0:03b5121a232e 12932 return (0);
pcercuei 0:03b5121a232e 12933
pcercuei 0:03b5121a232e 12934 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 12935 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12936
pcercuei 0:03b5121a232e 12937 total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last, 0);
pcercuei 0:03b5121a232e 12938 return (total);
pcercuei 0:03b5121a232e 12939 }
pcercuei 0:03b5121a232e 12940 case XPATH_OP_VALUE:
pcercuei 0:03b5121a232e 12941 valuePush(ctxt,
pcercuei 0:03b5121a232e 12942 xmlXPathCacheObjectCopy(ctxt->context,
pcercuei 0:03b5121a232e 12943 (xmlXPathObjectPtr) op->value4));
pcercuei 0:03b5121a232e 12944 return (0);
pcercuei 0:03b5121a232e 12945 case XPATH_OP_SORT:
pcercuei 0:03b5121a232e 12946 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 12947 total +=
pcercuei 0:03b5121a232e 12948 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
pcercuei 0:03b5121a232e 12949 last);
pcercuei 0:03b5121a232e 12950 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12951 if ((ctxt->value != NULL)
pcercuei 0:03b5121a232e 12952 && (ctxt->value->type == XPATH_NODESET)
pcercuei 0:03b5121a232e 12953 && (ctxt->value->nodesetval != NULL)
pcercuei 0:03b5121a232e 12954 && (ctxt->value->nodesetval->nodeNr > 1))
pcercuei 0:03b5121a232e 12955 xmlXPathNodeSetSort(ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 12956 return (total);
pcercuei 0:03b5121a232e 12957 default:
pcercuei 0:03b5121a232e 12958 return (xmlXPathCompOpEval(ctxt, op));
pcercuei 0:03b5121a232e 12959 }
pcercuei 0:03b5121a232e 12960 }
pcercuei 0:03b5121a232e 12961
pcercuei 0:03b5121a232e 12962 #ifdef XP_OPTIMIZED_FILTER_FIRST
pcercuei 0:03b5121a232e 12963 static int
pcercuei 0:03b5121a232e 12964 xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 12965 xmlXPathStepOpPtr op, xmlNodePtr * first)
pcercuei 0:03b5121a232e 12966 {
pcercuei 0:03b5121a232e 12967 int total = 0;
pcercuei 0:03b5121a232e 12968 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 12969 xmlXPathObjectPtr res;
pcercuei 0:03b5121a232e 12970 xmlXPathObjectPtr obj;
pcercuei 0:03b5121a232e 12971 xmlNodeSetPtr oldset;
pcercuei 0:03b5121a232e 12972 xmlNodePtr oldnode;
pcercuei 0:03b5121a232e 12973 xmlDocPtr oldDoc;
pcercuei 0:03b5121a232e 12974 int i;
pcercuei 0:03b5121a232e 12975
pcercuei 0:03b5121a232e 12976 CHECK_ERROR0;
pcercuei 0:03b5121a232e 12977 comp = ctxt->comp;
pcercuei 0:03b5121a232e 12978 /*
pcercuei 0:03b5121a232e 12979 * Optimization for ()[last()] selection i.e. the last elem
pcercuei 0:03b5121a232e 12980 */
pcercuei 0:03b5121a232e 12981 if ((op->ch1 != -1) && (op->ch2 != -1) &&
pcercuei 0:03b5121a232e 12982 (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
pcercuei 0:03b5121a232e 12983 (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
pcercuei 0:03b5121a232e 12984 int f = comp->steps[op->ch2].ch1;
pcercuei 0:03b5121a232e 12985
pcercuei 0:03b5121a232e 12986 if ((f != -1) &&
pcercuei 0:03b5121a232e 12987 (comp->steps[f].op == XPATH_OP_FUNCTION) &&
pcercuei 0:03b5121a232e 12988 (comp->steps[f].value5 == NULL) &&
pcercuei 0:03b5121a232e 12989 (comp->steps[f].value == 0) &&
pcercuei 0:03b5121a232e 12990 (comp->steps[f].value4 != NULL) &&
pcercuei 0:03b5121a232e 12991 (xmlStrEqual
pcercuei 0:03b5121a232e 12992 (comp->steps[f].value4, BAD_CAST "last"))) {
pcercuei 0:03b5121a232e 12993 xmlNodePtr last = NULL;
pcercuei 0:03b5121a232e 12994
pcercuei 0:03b5121a232e 12995 total +=
pcercuei 0:03b5121a232e 12996 xmlXPathCompOpEvalLast(ctxt,
pcercuei 0:03b5121a232e 12997 &comp->steps[op->ch1],
pcercuei 0:03b5121a232e 12998 &last);
pcercuei 0:03b5121a232e 12999 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13000 /*
pcercuei 0:03b5121a232e 13001 * The nodeset should be in document order,
pcercuei 0:03b5121a232e 13002 * Keep only the last value
pcercuei 0:03b5121a232e 13003 */
pcercuei 0:03b5121a232e 13004 if ((ctxt->value != NULL) &&
pcercuei 0:03b5121a232e 13005 (ctxt->value->type == XPATH_NODESET) &&
pcercuei 0:03b5121a232e 13006 (ctxt->value->nodesetval != NULL) &&
pcercuei 0:03b5121a232e 13007 (ctxt->value->nodesetval->nodeTab != NULL) &&
pcercuei 0:03b5121a232e 13008 (ctxt->value->nodesetval->nodeNr > 1)) {
pcercuei 0:03b5121a232e 13009 ctxt->value->nodesetval->nodeTab[0] =
pcercuei 0:03b5121a232e 13010 ctxt->value->nodesetval->nodeTab[ctxt->
pcercuei 0:03b5121a232e 13011 value->
pcercuei 0:03b5121a232e 13012 nodesetval->
pcercuei 0:03b5121a232e 13013 nodeNr -
pcercuei 0:03b5121a232e 13014 1];
pcercuei 0:03b5121a232e 13015 ctxt->value->nodesetval->nodeNr = 1;
pcercuei 0:03b5121a232e 13016 *first = *(ctxt->value->nodesetval->nodeTab);
pcercuei 0:03b5121a232e 13017 }
pcercuei 0:03b5121a232e 13018 return (total);
pcercuei 0:03b5121a232e 13019 }
pcercuei 0:03b5121a232e 13020 }
pcercuei 0:03b5121a232e 13021
pcercuei 0:03b5121a232e 13022 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13023 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13024 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13025 if (op->ch2 == -1)
pcercuei 0:03b5121a232e 13026 return (total);
pcercuei 0:03b5121a232e 13027 if (ctxt->value == NULL)
pcercuei 0:03b5121a232e 13028 return (total);
pcercuei 0:03b5121a232e 13029
pcercuei 0:03b5121a232e 13030 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 13031 oldnode = ctxt->context->node;
pcercuei 0:03b5121a232e 13032 /*
pcercuei 0:03b5121a232e 13033 * Hum are we filtering the result of an XPointer expression
pcercuei 0:03b5121a232e 13034 */
pcercuei 0:03b5121a232e 13035 if (ctxt->value->type == XPATH_LOCATIONSET) {
pcercuei 0:03b5121a232e 13036 xmlXPathObjectPtr tmp = NULL;
pcercuei 0:03b5121a232e 13037 xmlLocationSetPtr newlocset = NULL;
pcercuei 0:03b5121a232e 13038 xmlLocationSetPtr oldlocset;
pcercuei 0:03b5121a232e 13039
pcercuei 0:03b5121a232e 13040 /*
pcercuei 0:03b5121a232e 13041 * Extract the old locset, and then evaluate the result of the
pcercuei 0:03b5121a232e 13042 * expression for all the element in the locset. use it to grow
pcercuei 0:03b5121a232e 13043 * up a new locset.
pcercuei 0:03b5121a232e 13044 */
pcercuei 0:03b5121a232e 13045 CHECK_TYPE0(XPATH_LOCATIONSET);
pcercuei 0:03b5121a232e 13046 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 13047 oldlocset = obj->user;
pcercuei 0:03b5121a232e 13048 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13049
pcercuei 0:03b5121a232e 13050 if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
pcercuei 0:03b5121a232e 13051 ctxt->context->contextSize = 0;
pcercuei 0:03b5121a232e 13052 ctxt->context->proximityPosition = 0;
pcercuei 0:03b5121a232e 13053 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13054 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13055 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13056 if (res != NULL) {
pcercuei 0:03b5121a232e 13057 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13058 }
pcercuei 0:03b5121a232e 13059 valuePush(ctxt, obj);
pcercuei 0:03b5121a232e 13060 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13061 return (total);
pcercuei 0:03b5121a232e 13062 }
pcercuei 0:03b5121a232e 13063 newlocset = xmlXPtrLocationSetCreate(NULL);
pcercuei 0:03b5121a232e 13064
pcercuei 0:03b5121a232e 13065 for (i = 0; i < oldlocset->locNr; i++) {
pcercuei 0:03b5121a232e 13066 /*
pcercuei 0:03b5121a232e 13067 * Run the evaluation with a node list made of a
pcercuei 0:03b5121a232e 13068 * single item in the nodelocset.
pcercuei 0:03b5121a232e 13069 */
pcercuei 0:03b5121a232e 13070 ctxt->context->node = oldlocset->locTab[i]->user;
pcercuei 0:03b5121a232e 13071 ctxt->context->contextSize = oldlocset->locNr;
pcercuei 0:03b5121a232e 13072 ctxt->context->proximityPosition = i + 1;
pcercuei 0:03b5121a232e 13073 if (tmp == NULL) {
pcercuei 0:03b5121a232e 13074 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 13075 ctxt->context->node);
pcercuei 0:03b5121a232e 13076 } else {
pcercuei 0:03b5121a232e 13077 if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
pcercuei 0:03b5121a232e 13078 ctxt->context->node) < 0) {
pcercuei 0:03b5121a232e 13079 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 13080 }
pcercuei 0:03b5121a232e 13081 }
pcercuei 0:03b5121a232e 13082 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 13083 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13084 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13085 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 13086 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 13087 return(0);
pcercuei 0:03b5121a232e 13088 }
pcercuei 0:03b5121a232e 13089 /*
pcercuei 0:03b5121a232e 13090 * The result of the evaluation need to be tested to
pcercuei 0:03b5121a232e 13091 * decided whether the filter succeeded or not
pcercuei 0:03b5121a232e 13092 */
pcercuei 0:03b5121a232e 13093 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13094 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
pcercuei 0:03b5121a232e 13095 xmlXPtrLocationSetAdd(newlocset,
pcercuei 0:03b5121a232e 13096 xmlXPathCacheObjectCopy(ctxt->context,
pcercuei 0:03b5121a232e 13097 oldlocset->locTab[i]));
pcercuei 0:03b5121a232e 13098 }
pcercuei 0:03b5121a232e 13099 /*
pcercuei 0:03b5121a232e 13100 * Cleanup
pcercuei 0:03b5121a232e 13101 */
pcercuei 0:03b5121a232e 13102 if (res != NULL) {
pcercuei 0:03b5121a232e 13103 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13104 }
pcercuei 0:03b5121a232e 13105 if (ctxt->value == tmp) {
pcercuei 0:03b5121a232e 13106 valuePop(ctxt);
pcercuei 0:03b5121a232e 13107 xmlXPathNodeSetClear(tmp->nodesetval, 1);
pcercuei 0:03b5121a232e 13108 /*
pcercuei 0:03b5121a232e 13109 * REVISIT TODO: Don't create a temporary nodeset
pcercuei 0:03b5121a232e 13110 * for everly iteration.
pcercuei 0:03b5121a232e 13111 */
pcercuei 0:03b5121a232e 13112 /* OLD: xmlXPathFreeObject(res); */
pcercuei 0:03b5121a232e 13113 } else
pcercuei 0:03b5121a232e 13114 tmp = NULL;
pcercuei 0:03b5121a232e 13115 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13116 /*
pcercuei 0:03b5121a232e 13117 * Only put the first node in the result, then leave.
pcercuei 0:03b5121a232e 13118 */
pcercuei 0:03b5121a232e 13119 if (newlocset->locNr > 0) {
pcercuei 0:03b5121a232e 13120 *first = (xmlNodePtr) oldlocset->locTab[i]->user;
pcercuei 0:03b5121a232e 13121 break;
pcercuei 0:03b5121a232e 13122 }
pcercuei 0:03b5121a232e 13123 }
pcercuei 0:03b5121a232e 13124 if (tmp != NULL) {
pcercuei 0:03b5121a232e 13125 xmlXPathReleaseObject(ctxt->context, tmp);
pcercuei 0:03b5121a232e 13126 }
pcercuei 0:03b5121a232e 13127 /*
pcercuei 0:03b5121a232e 13128 * The result is used as the new evaluation locset.
pcercuei 0:03b5121a232e 13129 */
pcercuei 0:03b5121a232e 13130 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 13131 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13132 ctxt->context->contextSize = -1;
pcercuei 0:03b5121a232e 13133 ctxt->context->proximityPosition = -1;
pcercuei 0:03b5121a232e 13134 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
pcercuei 0:03b5121a232e 13135 ctxt->context->node = oldnode;
pcercuei 0:03b5121a232e 13136 return (total);
pcercuei 0:03b5121a232e 13137 }
pcercuei 0:03b5121a232e 13138 #endif /* LIBXML_XPTR_ENABLED */
pcercuei 0:03b5121a232e 13139
pcercuei 0:03b5121a232e 13140 /*
pcercuei 0:03b5121a232e 13141 * Extract the old set, and then evaluate the result of the
pcercuei 0:03b5121a232e 13142 * expression for all the element in the set. use it to grow
pcercuei 0:03b5121a232e 13143 * up a new set.
pcercuei 0:03b5121a232e 13144 */
pcercuei 0:03b5121a232e 13145 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 13146 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 13147 oldset = obj->nodesetval;
pcercuei 0:03b5121a232e 13148
pcercuei 0:03b5121a232e 13149 oldnode = ctxt->context->node;
pcercuei 0:03b5121a232e 13150 oldDoc = ctxt->context->doc;
pcercuei 0:03b5121a232e 13151 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13152
pcercuei 0:03b5121a232e 13153 if ((oldset == NULL) || (oldset->nodeNr == 0)) {
pcercuei 0:03b5121a232e 13154 ctxt->context->contextSize = 0;
pcercuei 0:03b5121a232e 13155 ctxt->context->proximityPosition = 0;
pcercuei 0:03b5121a232e 13156 /* QUESTION TODO: Why was this code commented out?
pcercuei 0:03b5121a232e 13157 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13158 total +=
pcercuei 0:03b5121a232e 13159 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 13160 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13161 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13162 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13163 if (res != NULL)
pcercuei 0:03b5121a232e 13164 xmlXPathFreeObject(res);
pcercuei 0:03b5121a232e 13165 */
pcercuei 0:03b5121a232e 13166 valuePush(ctxt, obj);
pcercuei 0:03b5121a232e 13167 ctxt->context->node = oldnode;
pcercuei 0:03b5121a232e 13168 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13169 } else {
pcercuei 0:03b5121a232e 13170 xmlNodeSetPtr newset;
pcercuei 0:03b5121a232e 13171 xmlXPathObjectPtr tmp = NULL;
pcercuei 0:03b5121a232e 13172 /*
pcercuei 0:03b5121a232e 13173 * Initialize the new set.
pcercuei 0:03b5121a232e 13174 * Also set the xpath document in case things like
pcercuei 0:03b5121a232e 13175 * key() evaluation are attempted on the predicate
pcercuei 0:03b5121a232e 13176 */
pcercuei 0:03b5121a232e 13177 newset = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 13178 /* XXX what if xmlXPathNodeSetCreate returned NULL? */
pcercuei 0:03b5121a232e 13179
pcercuei 0:03b5121a232e 13180 for (i = 0; i < oldset->nodeNr; i++) {
pcercuei 0:03b5121a232e 13181 /*
pcercuei 0:03b5121a232e 13182 * Run the evaluation with a node list made of
pcercuei 0:03b5121a232e 13183 * a single item in the nodeset.
pcercuei 0:03b5121a232e 13184 */
pcercuei 0:03b5121a232e 13185 ctxt->context->node = oldset->nodeTab[i];
pcercuei 0:03b5121a232e 13186 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 13187 (oldset->nodeTab[i]->doc != NULL))
pcercuei 0:03b5121a232e 13188 ctxt->context->doc = oldset->nodeTab[i]->doc;
pcercuei 0:03b5121a232e 13189 if (tmp == NULL) {
pcercuei 0:03b5121a232e 13190 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 13191 ctxt->context->node);
pcercuei 0:03b5121a232e 13192 } else {
pcercuei 0:03b5121a232e 13193 if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
pcercuei 0:03b5121a232e 13194 ctxt->context->node) < 0) {
pcercuei 0:03b5121a232e 13195 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 13196 }
pcercuei 0:03b5121a232e 13197 }
pcercuei 0:03b5121a232e 13198 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 13199 ctxt->context->contextSize = oldset->nodeNr;
pcercuei 0:03b5121a232e 13200 ctxt->context->proximityPosition = i + 1;
pcercuei 0:03b5121a232e 13201 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13202 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13203 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 13204 xmlXPathFreeNodeSet(newset);
pcercuei 0:03b5121a232e 13205 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 13206 return(0);
pcercuei 0:03b5121a232e 13207 }
pcercuei 0:03b5121a232e 13208 /*
pcercuei 0:03b5121a232e 13209 * The result of the evaluation needs to be tested to
pcercuei 0:03b5121a232e 13210 * decide whether the filter succeeded or not
pcercuei 0:03b5121a232e 13211 */
pcercuei 0:03b5121a232e 13212 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13213 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
pcercuei 0:03b5121a232e 13214 if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) < 0)
pcercuei 0:03b5121a232e 13215 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 13216 }
pcercuei 0:03b5121a232e 13217 /*
pcercuei 0:03b5121a232e 13218 * Cleanup
pcercuei 0:03b5121a232e 13219 */
pcercuei 0:03b5121a232e 13220 if (res != NULL) {
pcercuei 0:03b5121a232e 13221 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13222 }
pcercuei 0:03b5121a232e 13223 if (ctxt->value == tmp) {
pcercuei 0:03b5121a232e 13224 valuePop(ctxt);
pcercuei 0:03b5121a232e 13225 /*
pcercuei 0:03b5121a232e 13226 * Don't free the temporary nodeset
pcercuei 0:03b5121a232e 13227 * in order to avoid massive recreation inside this
pcercuei 0:03b5121a232e 13228 * loop.
pcercuei 0:03b5121a232e 13229 */
pcercuei 0:03b5121a232e 13230 xmlXPathNodeSetClear(tmp->nodesetval, 1);
pcercuei 0:03b5121a232e 13231 } else
pcercuei 0:03b5121a232e 13232 tmp = NULL;
pcercuei 0:03b5121a232e 13233 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13234 /*
pcercuei 0:03b5121a232e 13235 * Only put the first node in the result, then leave.
pcercuei 0:03b5121a232e 13236 */
pcercuei 0:03b5121a232e 13237 if (newset->nodeNr > 0) {
pcercuei 0:03b5121a232e 13238 *first = *(newset->nodeTab);
pcercuei 0:03b5121a232e 13239 break;
pcercuei 0:03b5121a232e 13240 }
pcercuei 0:03b5121a232e 13241 }
pcercuei 0:03b5121a232e 13242 if (tmp != NULL) {
pcercuei 0:03b5121a232e 13243 xmlXPathReleaseObject(ctxt->context, tmp);
pcercuei 0:03b5121a232e 13244 }
pcercuei 0:03b5121a232e 13245 /*
pcercuei 0:03b5121a232e 13246 * The result is used as the new evaluation set.
pcercuei 0:03b5121a232e 13247 */
pcercuei 0:03b5121a232e 13248 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 13249 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13250 ctxt->context->contextSize = -1;
pcercuei 0:03b5121a232e 13251 ctxt->context->proximityPosition = -1;
pcercuei 0:03b5121a232e 13252 /* may want to move this past the '}' later */
pcercuei 0:03b5121a232e 13253 ctxt->context->doc = oldDoc;
pcercuei 0:03b5121a232e 13254 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
pcercuei 0:03b5121a232e 13255 }
pcercuei 0:03b5121a232e 13256 ctxt->context->node = oldnode;
pcercuei 0:03b5121a232e 13257 return(total);
pcercuei 0:03b5121a232e 13258 }
pcercuei 0:03b5121a232e 13259 #endif /* XP_OPTIMIZED_FILTER_FIRST */
pcercuei 0:03b5121a232e 13260
pcercuei 0:03b5121a232e 13261 /**
pcercuei 0:03b5121a232e 13262 * xmlXPathCompOpEval:
pcercuei 0:03b5121a232e 13263 * @ctxt: the XPath parser context with the compiled expression
pcercuei 0:03b5121a232e 13264 * @op: an XPath compiled operation
pcercuei 0:03b5121a232e 13265 *
pcercuei 0:03b5121a232e 13266 * Evaluate the Precompiled XPath operation
pcercuei 0:03b5121a232e 13267 * Returns the number of nodes traversed
pcercuei 0:03b5121a232e 13268 */
pcercuei 0:03b5121a232e 13269 static int
pcercuei 0:03b5121a232e 13270 xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
pcercuei 0:03b5121a232e 13271 {
pcercuei 0:03b5121a232e 13272 int total = 0;
pcercuei 0:03b5121a232e 13273 int equal, ret;
pcercuei 0:03b5121a232e 13274 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 13275 xmlXPathObjectPtr arg1, arg2;
pcercuei 0:03b5121a232e 13276 xmlNodePtr bak;
pcercuei 0:03b5121a232e 13277 xmlDocPtr bakd;
pcercuei 0:03b5121a232e 13278 int pp;
pcercuei 0:03b5121a232e 13279 int cs;
pcercuei 0:03b5121a232e 13280
pcercuei 0:03b5121a232e 13281 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13282 comp = ctxt->comp;
pcercuei 0:03b5121a232e 13283 switch (op->op) {
pcercuei 0:03b5121a232e 13284 case XPATH_OP_END:
pcercuei 0:03b5121a232e 13285 return (0);
pcercuei 0:03b5121a232e 13286 case XPATH_OP_AND:
pcercuei 0:03b5121a232e 13287 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13288 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13289 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13290 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13291 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13292 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13293 xmlXPathBooleanFunction(ctxt, 1);
pcercuei 0:03b5121a232e 13294 if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
pcercuei 0:03b5121a232e 13295 return (total);
pcercuei 0:03b5121a232e 13296 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 13297 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13298 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13299 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13300 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13301 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13302 if (ctxt->error) {
pcercuei 0:03b5121a232e 13303 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 13304 return(0);
pcercuei 0:03b5121a232e 13305 }
pcercuei 0:03b5121a232e 13306 xmlXPathBooleanFunction(ctxt, 1);
pcercuei 0:03b5121a232e 13307 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 13308 arg1->boolval &= arg2->boolval;
pcercuei 0:03b5121a232e 13309 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 13310 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 13311 return (total);
pcercuei 0:03b5121a232e 13312 case XPATH_OP_OR:
pcercuei 0:03b5121a232e 13313 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13314 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13315 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13316 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13317 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13318 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13319 xmlXPathBooleanFunction(ctxt, 1);
pcercuei 0:03b5121a232e 13320 if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
pcercuei 0:03b5121a232e 13321 return (total);
pcercuei 0:03b5121a232e 13322 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 13323 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13324 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13325 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13326 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13327 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13328 if (ctxt->error) {
pcercuei 0:03b5121a232e 13329 xmlXPathFreeObject(arg2);
pcercuei 0:03b5121a232e 13330 return(0);
pcercuei 0:03b5121a232e 13331 }
pcercuei 0:03b5121a232e 13332 xmlXPathBooleanFunction(ctxt, 1);
pcercuei 0:03b5121a232e 13333 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 13334 arg1->boolval |= arg2->boolval;
pcercuei 0:03b5121a232e 13335 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 13336 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 13337 return (total);
pcercuei 0:03b5121a232e 13338 case XPATH_OP_EQUAL:
pcercuei 0:03b5121a232e 13339 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13340 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13341 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13342 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13343 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13344 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13345 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13346 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13347 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13348 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13349 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13350 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13351 if (op->value)
pcercuei 0:03b5121a232e 13352 equal = xmlXPathEqualValues(ctxt);
pcercuei 0:03b5121a232e 13353 else
pcercuei 0:03b5121a232e 13354 equal = xmlXPathNotEqualValues(ctxt);
pcercuei 0:03b5121a232e 13355 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal));
pcercuei 0:03b5121a232e 13356 return (total);
pcercuei 0:03b5121a232e 13357 case XPATH_OP_CMP:
pcercuei 0:03b5121a232e 13358 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13359 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13360 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13361 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13362 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13363 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13364 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13365 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13366 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13367 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13368 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13369 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13370 ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
pcercuei 0:03b5121a232e 13371 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
pcercuei 0:03b5121a232e 13372 return (total);
pcercuei 0:03b5121a232e 13373 case XPATH_OP_PLUS:
pcercuei 0:03b5121a232e 13374 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13375 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13376 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13377 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13378 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13379 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13380 if (op->ch2 != -1) {
pcercuei 0:03b5121a232e 13381 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13382 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13383 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13384 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13385 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13386 }
pcercuei 0:03b5121a232e 13387 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13388 if (op->value == 0)
pcercuei 0:03b5121a232e 13389 xmlXPathSubValues(ctxt);
pcercuei 0:03b5121a232e 13390 else if (op->value == 1)
pcercuei 0:03b5121a232e 13391 xmlXPathAddValues(ctxt);
pcercuei 0:03b5121a232e 13392 else if (op->value == 2)
pcercuei 0:03b5121a232e 13393 xmlXPathValueFlipSign(ctxt);
pcercuei 0:03b5121a232e 13394 else if (op->value == 3) {
pcercuei 0:03b5121a232e 13395 CAST_TO_NUMBER;
pcercuei 0:03b5121a232e 13396 CHECK_TYPE0(XPATH_NUMBER);
pcercuei 0:03b5121a232e 13397 }
pcercuei 0:03b5121a232e 13398 return (total);
pcercuei 0:03b5121a232e 13399 case XPATH_OP_MULT:
pcercuei 0:03b5121a232e 13400 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13401 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13402 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13403 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13404 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13405 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13406 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13407 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13408 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13409 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13410 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13411 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13412 if (op->value == 0)
pcercuei 0:03b5121a232e 13413 xmlXPathMultValues(ctxt);
pcercuei 0:03b5121a232e 13414 else if (op->value == 1)
pcercuei 0:03b5121a232e 13415 xmlXPathDivValues(ctxt);
pcercuei 0:03b5121a232e 13416 else if (op->value == 2)
pcercuei 0:03b5121a232e 13417 xmlXPathModValues(ctxt);
pcercuei 0:03b5121a232e 13418 return (total);
pcercuei 0:03b5121a232e 13419 case XPATH_OP_UNION:
pcercuei 0:03b5121a232e 13420 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13421 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13422 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13423 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13424 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13425 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13426 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13427 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13428 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13429 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13430 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13431 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13432 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 13433 arg2 = valuePop(ctxt);
pcercuei 0:03b5121a232e 13434
pcercuei 0:03b5121a232e 13435 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 13436 arg1 = valuePop(ctxt);
pcercuei 0:03b5121a232e 13437
pcercuei 0:03b5121a232e 13438 if ((arg1->nodesetval == NULL) ||
pcercuei 0:03b5121a232e 13439 ((arg2->nodesetval != NULL) &&
pcercuei 0:03b5121a232e 13440 (arg2->nodesetval->nodeNr != 0)))
pcercuei 0:03b5121a232e 13441 {
pcercuei 0:03b5121a232e 13442 arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
pcercuei 0:03b5121a232e 13443 arg2->nodesetval);
pcercuei 0:03b5121a232e 13444 }
pcercuei 0:03b5121a232e 13445
pcercuei 0:03b5121a232e 13446 valuePush(ctxt, arg1);
pcercuei 0:03b5121a232e 13447 xmlXPathReleaseObject(ctxt->context, arg2);
pcercuei 0:03b5121a232e 13448 return (total);
pcercuei 0:03b5121a232e 13449 case XPATH_OP_ROOT:
pcercuei 0:03b5121a232e 13450 xmlXPathRoot(ctxt);
pcercuei 0:03b5121a232e 13451 return (total);
pcercuei 0:03b5121a232e 13452 case XPATH_OP_NODE:
pcercuei 0:03b5121a232e 13453 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13454 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13455 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13456 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13457 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13458 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13459 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 13460 ctxt->context->node));
pcercuei 0:03b5121a232e 13461 return (total);
pcercuei 0:03b5121a232e 13462 case XPATH_OP_RESET:
pcercuei 0:03b5121a232e 13463 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13464 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13465 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13466 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13467 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13468 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13469 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13470 return (total);
pcercuei 0:03b5121a232e 13471 case XPATH_OP_COLLECT:{
pcercuei 0:03b5121a232e 13472 if (op->ch1 == -1)
pcercuei 0:03b5121a232e 13473 return (total);
pcercuei 0:03b5121a232e 13474
pcercuei 0:03b5121a232e 13475 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13476 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13477
pcercuei 0:03b5121a232e 13478 total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 0);
pcercuei 0:03b5121a232e 13479 return (total);
pcercuei 0:03b5121a232e 13480 }
pcercuei 0:03b5121a232e 13481 case XPATH_OP_VALUE:
pcercuei 0:03b5121a232e 13482 valuePush(ctxt,
pcercuei 0:03b5121a232e 13483 xmlXPathCacheObjectCopy(ctxt->context,
pcercuei 0:03b5121a232e 13484 (xmlXPathObjectPtr) op->value4));
pcercuei 0:03b5121a232e 13485 return (total);
pcercuei 0:03b5121a232e 13486 case XPATH_OP_VARIABLE:{
pcercuei 0:03b5121a232e 13487 xmlXPathObjectPtr val;
pcercuei 0:03b5121a232e 13488
pcercuei 0:03b5121a232e 13489 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13490 total +=
pcercuei 0:03b5121a232e 13491 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13492 if (op->value5 == NULL) {
pcercuei 0:03b5121a232e 13493 val = xmlXPathVariableLookup(ctxt->context, op->value4);
pcercuei 0:03b5121a232e 13494 if (val == NULL) {
pcercuei 0:03b5121a232e 13495 ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
pcercuei 0:03b5121a232e 13496 return(0);
pcercuei 0:03b5121a232e 13497 }
pcercuei 0:03b5121a232e 13498 valuePush(ctxt, val);
pcercuei 0:03b5121a232e 13499 } else {
pcercuei 0:03b5121a232e 13500 const xmlChar *URI;
pcercuei 0:03b5121a232e 13501
pcercuei 0:03b5121a232e 13502 URI = xmlXPathNsLookup(ctxt->context, op->value5);
pcercuei 0:03b5121a232e 13503 if (URI == NULL) {
pcercuei 0:03b5121a232e 13504 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 13505 "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
pcercuei 0:03b5121a232e 13506 (char *) op->value4, (char *)op->value5);
pcercuei 0:03b5121a232e 13507 ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
pcercuei 0:03b5121a232e 13508 return (total);
pcercuei 0:03b5121a232e 13509 }
pcercuei 0:03b5121a232e 13510 val = xmlXPathVariableLookupNS(ctxt->context,
pcercuei 0:03b5121a232e 13511 op->value4, URI);
pcercuei 0:03b5121a232e 13512 if (val == NULL) {
pcercuei 0:03b5121a232e 13513 ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
pcercuei 0:03b5121a232e 13514 return(0);
pcercuei 0:03b5121a232e 13515 }
pcercuei 0:03b5121a232e 13516 valuePush(ctxt, val);
pcercuei 0:03b5121a232e 13517 }
pcercuei 0:03b5121a232e 13518 return (total);
pcercuei 0:03b5121a232e 13519 }
pcercuei 0:03b5121a232e 13520 case XPATH_OP_FUNCTION:{
pcercuei 0:03b5121a232e 13521 xmlXPathFunction func;
pcercuei 0:03b5121a232e 13522 const xmlChar *oldFunc, *oldFuncURI;
pcercuei 0:03b5121a232e 13523 int i;
pcercuei 0:03b5121a232e 13524 int frame;
pcercuei 0:03b5121a232e 13525
pcercuei 0:03b5121a232e 13526 frame = xmlXPathSetFrame(ctxt);
pcercuei 0:03b5121a232e 13527 if (op->ch1 != -1) {
pcercuei 0:03b5121a232e 13528 total +=
pcercuei 0:03b5121a232e 13529 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13530 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 13531 xmlXPathPopFrame(ctxt, frame);
pcercuei 0:03b5121a232e 13532 return (total);
pcercuei 0:03b5121a232e 13533 }
pcercuei 0:03b5121a232e 13534 }
pcercuei 0:03b5121a232e 13535 if (ctxt->valueNr < ctxt->valueFrame + op->value) {
pcercuei 0:03b5121a232e 13536 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 13537 "xmlXPathCompOpEval: parameter error\n");
pcercuei 0:03b5121a232e 13538 ctxt->error = XPATH_INVALID_OPERAND;
pcercuei 0:03b5121a232e 13539 xmlXPathPopFrame(ctxt, frame);
pcercuei 0:03b5121a232e 13540 return (total);
pcercuei 0:03b5121a232e 13541 }
pcercuei 0:03b5121a232e 13542 for (i = 0; i < op->value; i++) {
pcercuei 0:03b5121a232e 13543 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
pcercuei 0:03b5121a232e 13544 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 13545 "xmlXPathCompOpEval: parameter error\n");
pcercuei 0:03b5121a232e 13546 ctxt->error = XPATH_INVALID_OPERAND;
pcercuei 0:03b5121a232e 13547 xmlXPathPopFrame(ctxt, frame);
pcercuei 0:03b5121a232e 13548 return (total);
pcercuei 0:03b5121a232e 13549 }
pcercuei 0:03b5121a232e 13550 }
pcercuei 0:03b5121a232e 13551 if (op->cache != NULL)
pcercuei 0:03b5121a232e 13552 XML_CAST_FPTR(func) = op->cache;
pcercuei 0:03b5121a232e 13553 else {
pcercuei 0:03b5121a232e 13554 const xmlChar *URI = NULL;
pcercuei 0:03b5121a232e 13555
pcercuei 0:03b5121a232e 13556 if (op->value5 == NULL)
pcercuei 0:03b5121a232e 13557 func =
pcercuei 0:03b5121a232e 13558 xmlXPathFunctionLookup(ctxt->context,
pcercuei 0:03b5121a232e 13559 op->value4);
pcercuei 0:03b5121a232e 13560 else {
pcercuei 0:03b5121a232e 13561 URI = xmlXPathNsLookup(ctxt->context, op->value5);
pcercuei 0:03b5121a232e 13562 if (URI == NULL) {
pcercuei 0:03b5121a232e 13563 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 13564 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
pcercuei 0:03b5121a232e 13565 (char *)op->value4, (char *)op->value5);
pcercuei 0:03b5121a232e 13566 xmlXPathPopFrame(ctxt, frame);
pcercuei 0:03b5121a232e 13567 ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
pcercuei 0:03b5121a232e 13568 return (total);
pcercuei 0:03b5121a232e 13569 }
pcercuei 0:03b5121a232e 13570 func = xmlXPathFunctionLookupNS(ctxt->context,
pcercuei 0:03b5121a232e 13571 op->value4, URI);
pcercuei 0:03b5121a232e 13572 }
pcercuei 0:03b5121a232e 13573 if (func == NULL) {
pcercuei 0:03b5121a232e 13574 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 13575 "xmlXPathCompOpEval: function %s not found\n",
pcercuei 0:03b5121a232e 13576 (char *)op->value4);
pcercuei 0:03b5121a232e 13577 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
pcercuei 0:03b5121a232e 13578 }
pcercuei 0:03b5121a232e 13579 op->cache = XML_CAST_FPTR(func);
pcercuei 0:03b5121a232e 13580 op->cacheURI = (void *) URI;
pcercuei 0:03b5121a232e 13581 }
pcercuei 0:03b5121a232e 13582 oldFunc = ctxt->context->function;
pcercuei 0:03b5121a232e 13583 oldFuncURI = ctxt->context->functionURI;
pcercuei 0:03b5121a232e 13584 ctxt->context->function = op->value4;
pcercuei 0:03b5121a232e 13585 ctxt->context->functionURI = op->cacheURI;
pcercuei 0:03b5121a232e 13586 func(ctxt, op->value);
pcercuei 0:03b5121a232e 13587 ctxt->context->function = oldFunc;
pcercuei 0:03b5121a232e 13588 ctxt->context->functionURI = oldFuncURI;
pcercuei 0:03b5121a232e 13589 xmlXPathPopFrame(ctxt, frame);
pcercuei 0:03b5121a232e 13590 return (total);
pcercuei 0:03b5121a232e 13591 }
pcercuei 0:03b5121a232e 13592 case XPATH_OP_ARG:
pcercuei 0:03b5121a232e 13593 bakd = ctxt->context->doc;
pcercuei 0:03b5121a232e 13594 bak = ctxt->context->node;
pcercuei 0:03b5121a232e 13595 pp = ctxt->context->proximityPosition;
pcercuei 0:03b5121a232e 13596 cs = ctxt->context->contextSize;
pcercuei 0:03b5121a232e 13597 if (op->ch1 != -1) {
pcercuei 0:03b5121a232e 13598 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13599 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13600 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13601 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13602 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13603 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13604 }
pcercuei 0:03b5121a232e 13605 if (op->ch2 != -1) {
pcercuei 0:03b5121a232e 13606 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13607 ctxt->context->contextSize = cs;
pcercuei 0:03b5121a232e 13608 ctxt->context->proximityPosition = pp;
pcercuei 0:03b5121a232e 13609 ctxt->context->node = bak;
pcercuei 0:03b5121a232e 13610 ctxt->context->doc = bakd;
pcercuei 0:03b5121a232e 13611 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13612 }
pcercuei 0:03b5121a232e 13613 return (total);
pcercuei 0:03b5121a232e 13614 case XPATH_OP_PREDICATE:
pcercuei 0:03b5121a232e 13615 case XPATH_OP_FILTER:{
pcercuei 0:03b5121a232e 13616 xmlXPathObjectPtr res;
pcercuei 0:03b5121a232e 13617 xmlXPathObjectPtr obj, tmp;
pcercuei 0:03b5121a232e 13618 xmlNodeSetPtr newset = NULL;
pcercuei 0:03b5121a232e 13619 xmlNodeSetPtr oldset;
pcercuei 0:03b5121a232e 13620 xmlNodePtr oldnode;
pcercuei 0:03b5121a232e 13621 xmlDocPtr oldDoc;
pcercuei 0:03b5121a232e 13622 int i;
pcercuei 0:03b5121a232e 13623
pcercuei 0:03b5121a232e 13624 /*
pcercuei 0:03b5121a232e 13625 * Optimization for ()[1] selection i.e. the first elem
pcercuei 0:03b5121a232e 13626 */
pcercuei 0:03b5121a232e 13627 if ((op->ch1 != -1) && (op->ch2 != -1) &&
pcercuei 0:03b5121a232e 13628 #ifdef XP_OPTIMIZED_FILTER_FIRST
pcercuei 0:03b5121a232e 13629 /*
pcercuei 0:03b5121a232e 13630 * FILTER TODO: Can we assume that the inner processing
pcercuei 0:03b5121a232e 13631 * will result in an ordered list if we have an
pcercuei 0:03b5121a232e 13632 * XPATH_OP_FILTER?
pcercuei 0:03b5121a232e 13633 * What about an additional field or flag on
pcercuei 0:03b5121a232e 13634 * xmlXPathObject like @sorted ? This way we wouln'd need
pcercuei 0:03b5121a232e 13635 * to assume anything, so it would be more robust and
pcercuei 0:03b5121a232e 13636 * easier to optimize.
pcercuei 0:03b5121a232e 13637 */
pcercuei 0:03b5121a232e 13638 ((comp->steps[op->ch1].op == XPATH_OP_SORT) || /* 18 */
pcercuei 0:03b5121a232e 13639 (comp->steps[op->ch1].op == XPATH_OP_FILTER)) && /* 17 */
pcercuei 0:03b5121a232e 13640 #else
pcercuei 0:03b5121a232e 13641 (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
pcercuei 0:03b5121a232e 13642 #endif
pcercuei 0:03b5121a232e 13643 (comp->steps[op->ch2].op == XPATH_OP_VALUE)) { /* 12 */
pcercuei 0:03b5121a232e 13644 xmlXPathObjectPtr val;
pcercuei 0:03b5121a232e 13645
pcercuei 0:03b5121a232e 13646 val = comp->steps[op->ch2].value4;
pcercuei 0:03b5121a232e 13647 if ((val != NULL) && (val->type == XPATH_NUMBER) &&
pcercuei 0:03b5121a232e 13648 (val->floatval == 1.0)) {
pcercuei 0:03b5121a232e 13649 xmlNodePtr first = NULL;
pcercuei 0:03b5121a232e 13650
pcercuei 0:03b5121a232e 13651 total +=
pcercuei 0:03b5121a232e 13652 xmlXPathCompOpEvalFirst(ctxt,
pcercuei 0:03b5121a232e 13653 &comp->steps[op->ch1],
pcercuei 0:03b5121a232e 13654 &first);
pcercuei 0:03b5121a232e 13655 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13656 /*
pcercuei 0:03b5121a232e 13657 * The nodeset should be in document order,
pcercuei 0:03b5121a232e 13658 * Keep only the first value
pcercuei 0:03b5121a232e 13659 */
pcercuei 0:03b5121a232e 13660 if ((ctxt->value != NULL) &&
pcercuei 0:03b5121a232e 13661 (ctxt->value->type == XPATH_NODESET) &&
pcercuei 0:03b5121a232e 13662 (ctxt->value->nodesetval != NULL) &&
pcercuei 0:03b5121a232e 13663 (ctxt->value->nodesetval->nodeNr > 1))
pcercuei 0:03b5121a232e 13664 ctxt->value->nodesetval->nodeNr = 1;
pcercuei 0:03b5121a232e 13665 return (total);
pcercuei 0:03b5121a232e 13666 }
pcercuei 0:03b5121a232e 13667 }
pcercuei 0:03b5121a232e 13668 /*
pcercuei 0:03b5121a232e 13669 * Optimization for ()[last()] selection i.e. the last elem
pcercuei 0:03b5121a232e 13670 */
pcercuei 0:03b5121a232e 13671 if ((op->ch1 != -1) && (op->ch2 != -1) &&
pcercuei 0:03b5121a232e 13672 (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
pcercuei 0:03b5121a232e 13673 (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
pcercuei 0:03b5121a232e 13674 int f = comp->steps[op->ch2].ch1;
pcercuei 0:03b5121a232e 13675
pcercuei 0:03b5121a232e 13676 if ((f != -1) &&
pcercuei 0:03b5121a232e 13677 (comp->steps[f].op == XPATH_OP_FUNCTION) &&
pcercuei 0:03b5121a232e 13678 (comp->steps[f].value5 == NULL) &&
pcercuei 0:03b5121a232e 13679 (comp->steps[f].value == 0) &&
pcercuei 0:03b5121a232e 13680 (comp->steps[f].value4 != NULL) &&
pcercuei 0:03b5121a232e 13681 (xmlStrEqual
pcercuei 0:03b5121a232e 13682 (comp->steps[f].value4, BAD_CAST "last"))) {
pcercuei 0:03b5121a232e 13683 xmlNodePtr last = NULL;
pcercuei 0:03b5121a232e 13684
pcercuei 0:03b5121a232e 13685 total +=
pcercuei 0:03b5121a232e 13686 xmlXPathCompOpEvalLast(ctxt,
pcercuei 0:03b5121a232e 13687 &comp->steps[op->ch1],
pcercuei 0:03b5121a232e 13688 &last);
pcercuei 0:03b5121a232e 13689 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13690 /*
pcercuei 0:03b5121a232e 13691 * The nodeset should be in document order,
pcercuei 0:03b5121a232e 13692 * Keep only the last value
pcercuei 0:03b5121a232e 13693 */
pcercuei 0:03b5121a232e 13694 if ((ctxt->value != NULL) &&
pcercuei 0:03b5121a232e 13695 (ctxt->value->type == XPATH_NODESET) &&
pcercuei 0:03b5121a232e 13696 (ctxt->value->nodesetval != NULL) &&
pcercuei 0:03b5121a232e 13697 (ctxt->value->nodesetval->nodeTab != NULL) &&
pcercuei 0:03b5121a232e 13698 (ctxt->value->nodesetval->nodeNr > 1)) {
pcercuei 0:03b5121a232e 13699 ctxt->value->nodesetval->nodeTab[0] =
pcercuei 0:03b5121a232e 13700 ctxt->value->nodesetval->nodeTab[ctxt->
pcercuei 0:03b5121a232e 13701 value->
pcercuei 0:03b5121a232e 13702 nodesetval->
pcercuei 0:03b5121a232e 13703 nodeNr -
pcercuei 0:03b5121a232e 13704 1];
pcercuei 0:03b5121a232e 13705 ctxt->value->nodesetval->nodeNr = 1;
pcercuei 0:03b5121a232e 13706 }
pcercuei 0:03b5121a232e 13707 return (total);
pcercuei 0:03b5121a232e 13708 }
pcercuei 0:03b5121a232e 13709 }
pcercuei 0:03b5121a232e 13710 /*
pcercuei 0:03b5121a232e 13711 * Process inner predicates first.
pcercuei 0:03b5121a232e 13712 * Example "index[parent::book][1]":
pcercuei 0:03b5121a232e 13713 * ...
pcercuei 0:03b5121a232e 13714 * PREDICATE <-- we are here "[1]"
pcercuei 0:03b5121a232e 13715 * PREDICATE <-- process "[parent::book]" first
pcercuei 0:03b5121a232e 13716 * SORT
pcercuei 0:03b5121a232e 13717 * COLLECT 'parent' 'name' 'node' book
pcercuei 0:03b5121a232e 13718 * NODE
pcercuei 0:03b5121a232e 13719 * ELEM Object is a number : 1
pcercuei 0:03b5121a232e 13720 */
pcercuei 0:03b5121a232e 13721 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13722 total +=
pcercuei 0:03b5121a232e 13723 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13724 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13725 if (op->ch2 == -1)
pcercuei 0:03b5121a232e 13726 return (total);
pcercuei 0:03b5121a232e 13727 if (ctxt->value == NULL)
pcercuei 0:03b5121a232e 13728 return (total);
pcercuei 0:03b5121a232e 13729
pcercuei 0:03b5121a232e 13730 oldnode = ctxt->context->node;
pcercuei 0:03b5121a232e 13731
pcercuei 0:03b5121a232e 13732 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 13733 /*
pcercuei 0:03b5121a232e 13734 * Hum are we filtering the result of an XPointer expression
pcercuei 0:03b5121a232e 13735 */
pcercuei 0:03b5121a232e 13736 if (ctxt->value->type == XPATH_LOCATIONSET) {
pcercuei 0:03b5121a232e 13737 xmlLocationSetPtr newlocset = NULL;
pcercuei 0:03b5121a232e 13738 xmlLocationSetPtr oldlocset;
pcercuei 0:03b5121a232e 13739
pcercuei 0:03b5121a232e 13740 /*
pcercuei 0:03b5121a232e 13741 * Extract the old locset, and then evaluate the result of the
pcercuei 0:03b5121a232e 13742 * expression for all the element in the locset. use it to grow
pcercuei 0:03b5121a232e 13743 * up a new locset.
pcercuei 0:03b5121a232e 13744 */
pcercuei 0:03b5121a232e 13745 CHECK_TYPE0(XPATH_LOCATIONSET);
pcercuei 0:03b5121a232e 13746 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 13747 oldlocset = obj->user;
pcercuei 0:03b5121a232e 13748 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13749
pcercuei 0:03b5121a232e 13750 if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
pcercuei 0:03b5121a232e 13751 ctxt->context->contextSize = 0;
pcercuei 0:03b5121a232e 13752 ctxt->context->proximityPosition = 0;
pcercuei 0:03b5121a232e 13753 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13754 total +=
pcercuei 0:03b5121a232e 13755 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 13756 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13757 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13758 if (res != NULL) {
pcercuei 0:03b5121a232e 13759 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13760 }
pcercuei 0:03b5121a232e 13761 valuePush(ctxt, obj);
pcercuei 0:03b5121a232e 13762 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13763 return (total);
pcercuei 0:03b5121a232e 13764 }
pcercuei 0:03b5121a232e 13765 newlocset = xmlXPtrLocationSetCreate(NULL);
pcercuei 0:03b5121a232e 13766
pcercuei 0:03b5121a232e 13767 for (i = 0; i < oldlocset->locNr; i++) {
pcercuei 0:03b5121a232e 13768 /*
pcercuei 0:03b5121a232e 13769 * Run the evaluation with a node list made of a
pcercuei 0:03b5121a232e 13770 * single item in the nodelocset.
pcercuei 0:03b5121a232e 13771 */
pcercuei 0:03b5121a232e 13772 ctxt->context->node = oldlocset->locTab[i]->user;
pcercuei 0:03b5121a232e 13773 ctxt->context->contextSize = oldlocset->locNr;
pcercuei 0:03b5121a232e 13774 ctxt->context->proximityPosition = i + 1;
pcercuei 0:03b5121a232e 13775 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 13776 ctxt->context->node);
pcercuei 0:03b5121a232e 13777 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 13778
pcercuei 0:03b5121a232e 13779 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13780 total +=
pcercuei 0:03b5121a232e 13781 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 13782 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13783 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 13784 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 13785 return(0);
pcercuei 0:03b5121a232e 13786 }
pcercuei 0:03b5121a232e 13787
pcercuei 0:03b5121a232e 13788 /*
pcercuei 0:03b5121a232e 13789 * The result of the evaluation need to be tested to
pcercuei 0:03b5121a232e 13790 * decided whether the filter succeeded or not
pcercuei 0:03b5121a232e 13791 */
pcercuei 0:03b5121a232e 13792 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13793 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
pcercuei 0:03b5121a232e 13794 xmlXPtrLocationSetAdd(newlocset,
pcercuei 0:03b5121a232e 13795 xmlXPathObjectCopy
pcercuei 0:03b5121a232e 13796 (oldlocset->locTab[i]));
pcercuei 0:03b5121a232e 13797 }
pcercuei 0:03b5121a232e 13798
pcercuei 0:03b5121a232e 13799 /*
pcercuei 0:03b5121a232e 13800 * Cleanup
pcercuei 0:03b5121a232e 13801 */
pcercuei 0:03b5121a232e 13802 if (res != NULL) {
pcercuei 0:03b5121a232e 13803 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13804 }
pcercuei 0:03b5121a232e 13805 if (ctxt->value == tmp) {
pcercuei 0:03b5121a232e 13806 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13807 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13808 }
pcercuei 0:03b5121a232e 13809
pcercuei 0:03b5121a232e 13810 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13811 }
pcercuei 0:03b5121a232e 13812
pcercuei 0:03b5121a232e 13813 /*
pcercuei 0:03b5121a232e 13814 * The result is used as the new evaluation locset.
pcercuei 0:03b5121a232e 13815 */
pcercuei 0:03b5121a232e 13816 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 13817 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13818 ctxt->context->contextSize = -1;
pcercuei 0:03b5121a232e 13819 ctxt->context->proximityPosition = -1;
pcercuei 0:03b5121a232e 13820 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
pcercuei 0:03b5121a232e 13821 ctxt->context->node = oldnode;
pcercuei 0:03b5121a232e 13822 return (total);
pcercuei 0:03b5121a232e 13823 }
pcercuei 0:03b5121a232e 13824 #endif /* LIBXML_XPTR_ENABLED */
pcercuei 0:03b5121a232e 13825
pcercuei 0:03b5121a232e 13826 /*
pcercuei 0:03b5121a232e 13827 * Extract the old set, and then evaluate the result of the
pcercuei 0:03b5121a232e 13828 * expression for all the element in the set. use it to grow
pcercuei 0:03b5121a232e 13829 * up a new set.
pcercuei 0:03b5121a232e 13830 */
pcercuei 0:03b5121a232e 13831 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 13832 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 13833 oldset = obj->nodesetval;
pcercuei 0:03b5121a232e 13834
pcercuei 0:03b5121a232e 13835 oldnode = ctxt->context->node;
pcercuei 0:03b5121a232e 13836 oldDoc = ctxt->context->doc;
pcercuei 0:03b5121a232e 13837 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13838
pcercuei 0:03b5121a232e 13839 if ((oldset == NULL) || (oldset->nodeNr == 0)) {
pcercuei 0:03b5121a232e 13840 ctxt->context->contextSize = 0;
pcercuei 0:03b5121a232e 13841 ctxt->context->proximityPosition = 0;
pcercuei 0:03b5121a232e 13842 /*
pcercuei 0:03b5121a232e 13843 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13844 total +=
pcercuei 0:03b5121a232e 13845 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 13846 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13847 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13848 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13849 if (res != NULL)
pcercuei 0:03b5121a232e 13850 xmlXPathFreeObject(res);
pcercuei 0:03b5121a232e 13851 */
pcercuei 0:03b5121a232e 13852 valuePush(ctxt, obj);
pcercuei 0:03b5121a232e 13853 ctxt->context->node = oldnode;
pcercuei 0:03b5121a232e 13854 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13855 } else {
pcercuei 0:03b5121a232e 13856 tmp = NULL;
pcercuei 0:03b5121a232e 13857 /*
pcercuei 0:03b5121a232e 13858 * Initialize the new set.
pcercuei 0:03b5121a232e 13859 * Also set the xpath document in case things like
pcercuei 0:03b5121a232e 13860 * key() evaluation are attempted on the predicate
pcercuei 0:03b5121a232e 13861 */
pcercuei 0:03b5121a232e 13862 newset = xmlXPathNodeSetCreate(NULL);
pcercuei 0:03b5121a232e 13863 /*
pcercuei 0:03b5121a232e 13864 * SPEC XPath 1.0:
pcercuei 0:03b5121a232e 13865 * "For each node in the node-set to be filtered, the
pcercuei 0:03b5121a232e 13866 * PredicateExpr is evaluated with that node as the
pcercuei 0:03b5121a232e 13867 * context node, with the number of nodes in the
pcercuei 0:03b5121a232e 13868 * node-set as the context size, and with the proximity
pcercuei 0:03b5121a232e 13869 * position of the node in the node-set with respect to
pcercuei 0:03b5121a232e 13870 * the axis as the context position;"
pcercuei 0:03b5121a232e 13871 * @oldset is the node-set" to be filtered.
pcercuei 0:03b5121a232e 13872 *
pcercuei 0:03b5121a232e 13873 * SPEC XPath 1.0:
pcercuei 0:03b5121a232e 13874 * "only predicates change the context position and
pcercuei 0:03b5121a232e 13875 * context size (see [2.4 Predicates])."
pcercuei 0:03b5121a232e 13876 * Example:
pcercuei 0:03b5121a232e 13877 * node-set context pos
pcercuei 0:03b5121a232e 13878 * nA 1
pcercuei 0:03b5121a232e 13879 * nB 2
pcercuei 0:03b5121a232e 13880 * nC 3
pcercuei 0:03b5121a232e 13881 * After applying predicate [position() > 1] :
pcercuei 0:03b5121a232e 13882 * node-set context pos
pcercuei 0:03b5121a232e 13883 * nB 1
pcercuei 0:03b5121a232e 13884 * nC 2
pcercuei 0:03b5121a232e 13885 *
pcercuei 0:03b5121a232e 13886 * removed the first node in the node-set, then
pcercuei 0:03b5121a232e 13887 * the context position of the
pcercuei 0:03b5121a232e 13888 */
pcercuei 0:03b5121a232e 13889 for (i = 0; i < oldset->nodeNr; i++) {
pcercuei 0:03b5121a232e 13890 /*
pcercuei 0:03b5121a232e 13891 * Run the evaluation with a node list made of
pcercuei 0:03b5121a232e 13892 * a single item in the nodeset.
pcercuei 0:03b5121a232e 13893 */
pcercuei 0:03b5121a232e 13894 ctxt->context->node = oldset->nodeTab[i];
pcercuei 0:03b5121a232e 13895 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) &&
pcercuei 0:03b5121a232e 13896 (oldset->nodeTab[i]->doc != NULL))
pcercuei 0:03b5121a232e 13897 ctxt->context->doc = oldset->nodeTab[i]->doc;
pcercuei 0:03b5121a232e 13898 if (tmp == NULL) {
pcercuei 0:03b5121a232e 13899 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 13900 ctxt->context->node);
pcercuei 0:03b5121a232e 13901 } else {
pcercuei 0:03b5121a232e 13902 if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
pcercuei 0:03b5121a232e 13903 ctxt->context->node) < 0) {
pcercuei 0:03b5121a232e 13904 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 13905 }
pcercuei 0:03b5121a232e 13906 }
pcercuei 0:03b5121a232e 13907 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 13908 ctxt->context->contextSize = oldset->nodeNr;
pcercuei 0:03b5121a232e 13909 ctxt->context->proximityPosition = i + 1;
pcercuei 0:03b5121a232e 13910 /*
pcercuei 0:03b5121a232e 13911 * Evaluate the predicate against the context node.
pcercuei 0:03b5121a232e 13912 * Can/should we optimize position() predicates
pcercuei 0:03b5121a232e 13913 * here (e.g. "[1]")?
pcercuei 0:03b5121a232e 13914 */
pcercuei 0:03b5121a232e 13915 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 13916 total +=
pcercuei 0:03b5121a232e 13917 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 13918 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 13919 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 13920 xmlXPathFreeNodeSet(newset);
pcercuei 0:03b5121a232e 13921 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 13922 return(0);
pcercuei 0:03b5121a232e 13923 }
pcercuei 0:03b5121a232e 13924
pcercuei 0:03b5121a232e 13925 /*
pcercuei 0:03b5121a232e 13926 * The result of the evaluation needs to be tested to
pcercuei 0:03b5121a232e 13927 * decide whether the filter succeeded or not
pcercuei 0:03b5121a232e 13928 */
pcercuei 0:03b5121a232e 13929 /*
pcercuei 0:03b5121a232e 13930 * OPTIMIZE TODO: Can we use
pcercuei 0:03b5121a232e 13931 * xmlXPathNodeSetAdd*Unique()* instead?
pcercuei 0:03b5121a232e 13932 */
pcercuei 0:03b5121a232e 13933 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 13934 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
pcercuei 0:03b5121a232e 13935 if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i])
pcercuei 0:03b5121a232e 13936 < 0)
pcercuei 0:03b5121a232e 13937 ctxt->error = XPATH_MEMORY_ERROR;
pcercuei 0:03b5121a232e 13938 }
pcercuei 0:03b5121a232e 13939
pcercuei 0:03b5121a232e 13940 /*
pcercuei 0:03b5121a232e 13941 * Cleanup
pcercuei 0:03b5121a232e 13942 */
pcercuei 0:03b5121a232e 13943 if (res != NULL) {
pcercuei 0:03b5121a232e 13944 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 13945 }
pcercuei 0:03b5121a232e 13946 if (ctxt->value == tmp) {
pcercuei 0:03b5121a232e 13947 valuePop(ctxt);
pcercuei 0:03b5121a232e 13948 xmlXPathNodeSetClear(tmp->nodesetval, 1);
pcercuei 0:03b5121a232e 13949 /*
pcercuei 0:03b5121a232e 13950 * Don't free the temporary nodeset
pcercuei 0:03b5121a232e 13951 * in order to avoid massive recreation inside this
pcercuei 0:03b5121a232e 13952 * loop.
pcercuei 0:03b5121a232e 13953 */
pcercuei 0:03b5121a232e 13954 } else
pcercuei 0:03b5121a232e 13955 tmp = NULL;
pcercuei 0:03b5121a232e 13956 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13957 }
pcercuei 0:03b5121a232e 13958 if (tmp != NULL)
pcercuei 0:03b5121a232e 13959 xmlXPathReleaseObject(ctxt->context, tmp);
pcercuei 0:03b5121a232e 13960 /*
pcercuei 0:03b5121a232e 13961 * The result is used as the new evaluation set.
pcercuei 0:03b5121a232e 13962 */
pcercuei 0:03b5121a232e 13963 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 13964 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 13965 ctxt->context->contextSize = -1;
pcercuei 0:03b5121a232e 13966 ctxt->context->proximityPosition = -1;
pcercuei 0:03b5121a232e 13967 /* may want to move this past the '}' later */
pcercuei 0:03b5121a232e 13968 ctxt->context->doc = oldDoc;
pcercuei 0:03b5121a232e 13969 valuePush(ctxt,
pcercuei 0:03b5121a232e 13970 xmlXPathCacheWrapNodeSet(ctxt->context, newset));
pcercuei 0:03b5121a232e 13971 }
pcercuei 0:03b5121a232e 13972 ctxt->context->node = oldnode;
pcercuei 0:03b5121a232e 13973 return (total);
pcercuei 0:03b5121a232e 13974 }
pcercuei 0:03b5121a232e 13975 case XPATH_OP_SORT:
pcercuei 0:03b5121a232e 13976 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13977 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 13978 CHECK_ERROR0;
pcercuei 0:03b5121a232e 13979 if ((ctxt->value != NULL) &&
pcercuei 0:03b5121a232e 13980 (ctxt->value->type == XPATH_NODESET) &&
pcercuei 0:03b5121a232e 13981 (ctxt->value->nodesetval != NULL) &&
pcercuei 0:03b5121a232e 13982 (ctxt->value->nodesetval->nodeNr > 1))
pcercuei 0:03b5121a232e 13983 {
pcercuei 0:03b5121a232e 13984 xmlXPathNodeSetSort(ctxt->value->nodesetval);
pcercuei 0:03b5121a232e 13985 }
pcercuei 0:03b5121a232e 13986 return (total);
pcercuei 0:03b5121a232e 13987 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 13988 case XPATH_OP_RANGETO:{
pcercuei 0:03b5121a232e 13989 xmlXPathObjectPtr range;
pcercuei 0:03b5121a232e 13990 xmlXPathObjectPtr res, obj;
pcercuei 0:03b5121a232e 13991 xmlXPathObjectPtr tmp;
pcercuei 0:03b5121a232e 13992 xmlLocationSetPtr newlocset = NULL;
pcercuei 0:03b5121a232e 13993 xmlLocationSetPtr oldlocset;
pcercuei 0:03b5121a232e 13994 xmlNodeSetPtr oldset;
pcercuei 0:03b5121a232e 13995 int i, j;
pcercuei 0:03b5121a232e 13996
pcercuei 0:03b5121a232e 13997 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 13998 total +=
pcercuei 0:03b5121a232e 13999 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 14000 if (op->ch2 == -1)
pcercuei 0:03b5121a232e 14001 return (total);
pcercuei 0:03b5121a232e 14002
pcercuei 0:03b5121a232e 14003 if (ctxt->value->type == XPATH_LOCATIONSET) {
pcercuei 0:03b5121a232e 14004 /*
pcercuei 0:03b5121a232e 14005 * Extract the old locset, and then evaluate the result of the
pcercuei 0:03b5121a232e 14006 * expression for all the element in the locset. use it to grow
pcercuei 0:03b5121a232e 14007 * up a new locset.
pcercuei 0:03b5121a232e 14008 */
pcercuei 0:03b5121a232e 14009 CHECK_TYPE0(XPATH_LOCATIONSET);
pcercuei 0:03b5121a232e 14010 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 14011 oldlocset = obj->user;
pcercuei 0:03b5121a232e 14012
pcercuei 0:03b5121a232e 14013 if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
pcercuei 0:03b5121a232e 14014 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 14015 ctxt->context->contextSize = 0;
pcercuei 0:03b5121a232e 14016 ctxt->context->proximityPosition = 0;
pcercuei 0:03b5121a232e 14017 total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 14018 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 14019 if (res != NULL) {
pcercuei 0:03b5121a232e 14020 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 14021 }
pcercuei 0:03b5121a232e 14022 valuePush(ctxt, obj);
pcercuei 0:03b5121a232e 14023 CHECK_ERROR0;
pcercuei 0:03b5121a232e 14024 return (total);
pcercuei 0:03b5121a232e 14025 }
pcercuei 0:03b5121a232e 14026 newlocset = xmlXPtrLocationSetCreate(NULL);
pcercuei 0:03b5121a232e 14027
pcercuei 0:03b5121a232e 14028 for (i = 0; i < oldlocset->locNr; i++) {
pcercuei 0:03b5121a232e 14029 /*
pcercuei 0:03b5121a232e 14030 * Run the evaluation with a node list made of a
pcercuei 0:03b5121a232e 14031 * single item in the nodelocset.
pcercuei 0:03b5121a232e 14032 */
pcercuei 0:03b5121a232e 14033 ctxt->context->node = oldlocset->locTab[i]->user;
pcercuei 0:03b5121a232e 14034 ctxt->context->contextSize = oldlocset->locNr;
pcercuei 0:03b5121a232e 14035 ctxt->context->proximityPosition = i + 1;
pcercuei 0:03b5121a232e 14036 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 14037 ctxt->context->node);
pcercuei 0:03b5121a232e 14038 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 14039
pcercuei 0:03b5121a232e 14040 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 14041 total +=
pcercuei 0:03b5121a232e 14042 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 14043 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 14044 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 14045 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 14046 return(0);
pcercuei 0:03b5121a232e 14047 }
pcercuei 0:03b5121a232e 14048
pcercuei 0:03b5121a232e 14049 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 14050 if (res->type == XPATH_LOCATIONSET) {
pcercuei 0:03b5121a232e 14051 xmlLocationSetPtr rloc =
pcercuei 0:03b5121a232e 14052 (xmlLocationSetPtr)res->user;
pcercuei 0:03b5121a232e 14053 for (j=0; j<rloc->locNr; j++) {
pcercuei 0:03b5121a232e 14054 range = xmlXPtrNewRange(
pcercuei 0:03b5121a232e 14055 oldlocset->locTab[i]->user,
pcercuei 0:03b5121a232e 14056 oldlocset->locTab[i]->index,
pcercuei 0:03b5121a232e 14057 rloc->locTab[j]->user2,
pcercuei 0:03b5121a232e 14058 rloc->locTab[j]->index2);
pcercuei 0:03b5121a232e 14059 if (range != NULL) {
pcercuei 0:03b5121a232e 14060 xmlXPtrLocationSetAdd(newlocset, range);
pcercuei 0:03b5121a232e 14061 }
pcercuei 0:03b5121a232e 14062 }
pcercuei 0:03b5121a232e 14063 } else {
pcercuei 0:03b5121a232e 14064 range = xmlXPtrNewRangeNodeObject(
pcercuei 0:03b5121a232e 14065 (xmlNodePtr)oldlocset->locTab[i]->user, res);
pcercuei 0:03b5121a232e 14066 if (range != NULL) {
pcercuei 0:03b5121a232e 14067 xmlXPtrLocationSetAdd(newlocset,range);
pcercuei 0:03b5121a232e 14068 }
pcercuei 0:03b5121a232e 14069 }
pcercuei 0:03b5121a232e 14070
pcercuei 0:03b5121a232e 14071 /*
pcercuei 0:03b5121a232e 14072 * Cleanup
pcercuei 0:03b5121a232e 14073 */
pcercuei 0:03b5121a232e 14074 if (res != NULL) {
pcercuei 0:03b5121a232e 14075 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 14076 }
pcercuei 0:03b5121a232e 14077 if (ctxt->value == tmp) {
pcercuei 0:03b5121a232e 14078 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 14079 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 14080 }
pcercuei 0:03b5121a232e 14081
pcercuei 0:03b5121a232e 14082 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 14083 }
pcercuei 0:03b5121a232e 14084 } else { /* Not a location set */
pcercuei 0:03b5121a232e 14085 CHECK_TYPE0(XPATH_NODESET);
pcercuei 0:03b5121a232e 14086 obj = valuePop(ctxt);
pcercuei 0:03b5121a232e 14087 oldset = obj->nodesetval;
pcercuei 0:03b5121a232e 14088 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 14089
pcercuei 0:03b5121a232e 14090 newlocset = xmlXPtrLocationSetCreate(NULL);
pcercuei 0:03b5121a232e 14091
pcercuei 0:03b5121a232e 14092 if (oldset != NULL) {
pcercuei 0:03b5121a232e 14093 for (i = 0; i < oldset->nodeNr; i++) {
pcercuei 0:03b5121a232e 14094 /*
pcercuei 0:03b5121a232e 14095 * Run the evaluation with a node list made of a single item
pcercuei 0:03b5121a232e 14096 * in the nodeset.
pcercuei 0:03b5121a232e 14097 */
pcercuei 0:03b5121a232e 14098 ctxt->context->node = oldset->nodeTab[i];
pcercuei 0:03b5121a232e 14099 /*
pcercuei 0:03b5121a232e 14100 * OPTIMIZE TODO: Avoid recreation for every iteration.
pcercuei 0:03b5121a232e 14101 */
pcercuei 0:03b5121a232e 14102 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
pcercuei 0:03b5121a232e 14103 ctxt->context->node);
pcercuei 0:03b5121a232e 14104 valuePush(ctxt, tmp);
pcercuei 0:03b5121a232e 14105
pcercuei 0:03b5121a232e 14106 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 14107 total +=
pcercuei 0:03b5121a232e 14108 xmlXPathCompOpEval(ctxt,
pcercuei 0:03b5121a232e 14109 &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 14110 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 14111 xmlXPathFreeObject(obj);
pcercuei 0:03b5121a232e 14112 return(0);
pcercuei 0:03b5121a232e 14113 }
pcercuei 0:03b5121a232e 14114
pcercuei 0:03b5121a232e 14115 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 14116 range =
pcercuei 0:03b5121a232e 14117 xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
pcercuei 0:03b5121a232e 14118 res);
pcercuei 0:03b5121a232e 14119 if (range != NULL) {
pcercuei 0:03b5121a232e 14120 xmlXPtrLocationSetAdd(newlocset, range);
pcercuei 0:03b5121a232e 14121 }
pcercuei 0:03b5121a232e 14122
pcercuei 0:03b5121a232e 14123 /*
pcercuei 0:03b5121a232e 14124 * Cleanup
pcercuei 0:03b5121a232e 14125 */
pcercuei 0:03b5121a232e 14126 if (res != NULL) {
pcercuei 0:03b5121a232e 14127 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 14128 }
pcercuei 0:03b5121a232e 14129 if (ctxt->value == tmp) {
pcercuei 0:03b5121a232e 14130 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 14131 xmlXPathReleaseObject(ctxt->context, res);
pcercuei 0:03b5121a232e 14132 }
pcercuei 0:03b5121a232e 14133
pcercuei 0:03b5121a232e 14134 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 14135 }
pcercuei 0:03b5121a232e 14136 }
pcercuei 0:03b5121a232e 14137 }
pcercuei 0:03b5121a232e 14138
pcercuei 0:03b5121a232e 14139 /*
pcercuei 0:03b5121a232e 14140 * The result is used as the new evaluation set.
pcercuei 0:03b5121a232e 14141 */
pcercuei 0:03b5121a232e 14142 xmlXPathReleaseObject(ctxt->context, obj);
pcercuei 0:03b5121a232e 14143 ctxt->context->node = NULL;
pcercuei 0:03b5121a232e 14144 ctxt->context->contextSize = -1;
pcercuei 0:03b5121a232e 14145 ctxt->context->proximityPosition = -1;
pcercuei 0:03b5121a232e 14146 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
pcercuei 0:03b5121a232e 14147 return (total);
pcercuei 0:03b5121a232e 14148 }
pcercuei 0:03b5121a232e 14149 #endif /* LIBXML_XPTR_ENABLED */
pcercuei 0:03b5121a232e 14150 }
pcercuei 0:03b5121a232e 14151 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 14152 "XPath: unknown precompiled operation %d\n", op->op);
pcercuei 0:03b5121a232e 14153 ctxt->error = XPATH_INVALID_OPERAND;
pcercuei 0:03b5121a232e 14154 return (total);
pcercuei 0:03b5121a232e 14155 }
pcercuei 0:03b5121a232e 14156
pcercuei 0:03b5121a232e 14157 /**
pcercuei 0:03b5121a232e 14158 * xmlXPathCompOpEvalToBoolean:
pcercuei 0:03b5121a232e 14159 * @ctxt: the XPath parser context
pcercuei 0:03b5121a232e 14160 *
pcercuei 0:03b5121a232e 14161 * Evaluates if the expression evaluates to true.
pcercuei 0:03b5121a232e 14162 *
pcercuei 0:03b5121a232e 14163 * Returns 1 if true, 0 if false and -1 on API or internal errors.
pcercuei 0:03b5121a232e 14164 */
pcercuei 0:03b5121a232e 14165 static int
pcercuei 0:03b5121a232e 14166 xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 14167 xmlXPathStepOpPtr op,
pcercuei 0:03b5121a232e 14168 int isPredicate)
pcercuei 0:03b5121a232e 14169 {
pcercuei 0:03b5121a232e 14170 xmlXPathObjectPtr resObj = NULL;
pcercuei 0:03b5121a232e 14171
pcercuei 0:03b5121a232e 14172 start:
pcercuei 0:03b5121a232e 14173 /* comp = ctxt->comp; */
pcercuei 0:03b5121a232e 14174 switch (op->op) {
pcercuei 0:03b5121a232e 14175 case XPATH_OP_END:
pcercuei 0:03b5121a232e 14176 return (0);
pcercuei 0:03b5121a232e 14177 case XPATH_OP_VALUE:
pcercuei 0:03b5121a232e 14178 resObj = (xmlXPathObjectPtr) op->value4;
pcercuei 0:03b5121a232e 14179 if (isPredicate)
pcercuei 0:03b5121a232e 14180 return(xmlXPathEvaluatePredicateResult(ctxt, resObj));
pcercuei 0:03b5121a232e 14181 return(xmlXPathCastToBoolean(resObj));
pcercuei 0:03b5121a232e 14182 case XPATH_OP_SORT:
pcercuei 0:03b5121a232e 14183 /*
pcercuei 0:03b5121a232e 14184 * We don't need sorting for boolean results. Skip this one.
pcercuei 0:03b5121a232e 14185 */
pcercuei 0:03b5121a232e 14186 if (op->ch1 != -1) {
pcercuei 0:03b5121a232e 14187 op = &ctxt->comp->steps[op->ch1];
pcercuei 0:03b5121a232e 14188 goto start;
pcercuei 0:03b5121a232e 14189 }
pcercuei 0:03b5121a232e 14190 return(0);
pcercuei 0:03b5121a232e 14191 case XPATH_OP_COLLECT:
pcercuei 0:03b5121a232e 14192 if (op->ch1 == -1)
pcercuei 0:03b5121a232e 14193 return(0);
pcercuei 0:03b5121a232e 14194
pcercuei 0:03b5121a232e 14195 xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 14196 if (ctxt->error != XPATH_EXPRESSION_OK)
pcercuei 0:03b5121a232e 14197 return(-1);
pcercuei 0:03b5121a232e 14198
pcercuei 0:03b5121a232e 14199 xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 1);
pcercuei 0:03b5121a232e 14200 if (ctxt->error != XPATH_EXPRESSION_OK)
pcercuei 0:03b5121a232e 14201 return(-1);
pcercuei 0:03b5121a232e 14202
pcercuei 0:03b5121a232e 14203 resObj = valuePop(ctxt);
pcercuei 0:03b5121a232e 14204 if (resObj == NULL)
pcercuei 0:03b5121a232e 14205 return(-1);
pcercuei 0:03b5121a232e 14206 break;
pcercuei 0:03b5121a232e 14207 default:
pcercuei 0:03b5121a232e 14208 /*
pcercuei 0:03b5121a232e 14209 * Fallback to call xmlXPathCompOpEval().
pcercuei 0:03b5121a232e 14210 */
pcercuei 0:03b5121a232e 14211 xmlXPathCompOpEval(ctxt, op);
pcercuei 0:03b5121a232e 14212 if (ctxt->error != XPATH_EXPRESSION_OK)
pcercuei 0:03b5121a232e 14213 return(-1);
pcercuei 0:03b5121a232e 14214
pcercuei 0:03b5121a232e 14215 resObj = valuePop(ctxt);
pcercuei 0:03b5121a232e 14216 if (resObj == NULL)
pcercuei 0:03b5121a232e 14217 return(-1);
pcercuei 0:03b5121a232e 14218 break;
pcercuei 0:03b5121a232e 14219 }
pcercuei 0:03b5121a232e 14220
pcercuei 0:03b5121a232e 14221 if (resObj) {
pcercuei 0:03b5121a232e 14222 int res;
pcercuei 0:03b5121a232e 14223
pcercuei 0:03b5121a232e 14224 if (resObj->type == XPATH_BOOLEAN) {
pcercuei 0:03b5121a232e 14225 res = resObj->boolval;
pcercuei 0:03b5121a232e 14226 } else if (isPredicate) {
pcercuei 0:03b5121a232e 14227 /*
pcercuei 0:03b5121a232e 14228 * For predicates a result of type "number" is handled
pcercuei 0:03b5121a232e 14229 * differently:
pcercuei 0:03b5121a232e 14230 * SPEC XPath 1.0:
pcercuei 0:03b5121a232e 14231 * "If the result is a number, the result will be converted
pcercuei 0:03b5121a232e 14232 * to true if the number is equal to the context position
pcercuei 0:03b5121a232e 14233 * and will be converted to false otherwise;"
pcercuei 0:03b5121a232e 14234 */
pcercuei 0:03b5121a232e 14235 res = xmlXPathEvaluatePredicateResult(ctxt, resObj);
pcercuei 0:03b5121a232e 14236 } else {
pcercuei 0:03b5121a232e 14237 res = xmlXPathCastToBoolean(resObj);
pcercuei 0:03b5121a232e 14238 }
pcercuei 0:03b5121a232e 14239 xmlXPathReleaseObject(ctxt->context, resObj);
pcercuei 0:03b5121a232e 14240 return(res);
pcercuei 0:03b5121a232e 14241 }
pcercuei 0:03b5121a232e 14242
pcercuei 0:03b5121a232e 14243 return(0);
pcercuei 0:03b5121a232e 14244 }
pcercuei 0:03b5121a232e 14245
pcercuei 0:03b5121a232e 14246 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 14247 /**
pcercuei 0:03b5121a232e 14248 * xmlXPathRunStreamEval:
pcercuei 0:03b5121a232e 14249 * @ctxt: the XPath parser context with the compiled expression
pcercuei 0:03b5121a232e 14250 *
pcercuei 0:03b5121a232e 14251 * Evaluate the Precompiled Streamable XPath expression in the given context.
pcercuei 0:03b5121a232e 14252 */
pcercuei 0:03b5121a232e 14253 static int
pcercuei 0:03b5121a232e 14254 xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp,
pcercuei 0:03b5121a232e 14255 xmlXPathObjectPtr *resultSeq, int toBool)
pcercuei 0:03b5121a232e 14256 {
pcercuei 0:03b5121a232e 14257 int max_depth, min_depth;
pcercuei 0:03b5121a232e 14258 int from_root;
pcercuei 0:03b5121a232e 14259 int ret, depth;
pcercuei 0:03b5121a232e 14260 int eval_all_nodes;
pcercuei 0:03b5121a232e 14261 xmlNodePtr cur = NULL, limit = NULL;
pcercuei 0:03b5121a232e 14262 xmlStreamCtxtPtr patstream = NULL;
pcercuei 0:03b5121a232e 14263
pcercuei 0:03b5121a232e 14264 int nb_nodes = 0;
pcercuei 0:03b5121a232e 14265
pcercuei 0:03b5121a232e 14266 if ((ctxt == NULL) || (comp == NULL))
pcercuei 0:03b5121a232e 14267 return(-1);
pcercuei 0:03b5121a232e 14268 max_depth = xmlPatternMaxDepth(comp);
pcercuei 0:03b5121a232e 14269 if (max_depth == -1)
pcercuei 0:03b5121a232e 14270 return(-1);
pcercuei 0:03b5121a232e 14271 if (max_depth == -2)
pcercuei 0:03b5121a232e 14272 max_depth = 10000;
pcercuei 0:03b5121a232e 14273 min_depth = xmlPatternMinDepth(comp);
pcercuei 0:03b5121a232e 14274 if (min_depth == -1)
pcercuei 0:03b5121a232e 14275 return(-1);
pcercuei 0:03b5121a232e 14276 from_root = xmlPatternFromRoot(comp);
pcercuei 0:03b5121a232e 14277 if (from_root < 0)
pcercuei 0:03b5121a232e 14278 return(-1);
pcercuei 0:03b5121a232e 14279 #if 0
pcercuei 0:03b5121a232e 14280 printf("stream eval: depth %d from root %d\n", max_depth, from_root);
pcercuei 0:03b5121a232e 14281 #endif
pcercuei 0:03b5121a232e 14282
pcercuei 0:03b5121a232e 14283 if (! toBool) {
pcercuei 0:03b5121a232e 14284 if (resultSeq == NULL)
pcercuei 0:03b5121a232e 14285 return(-1);
pcercuei 0:03b5121a232e 14286 *resultSeq = xmlXPathCacheNewNodeSet(ctxt, NULL);
pcercuei 0:03b5121a232e 14287 if (*resultSeq == NULL)
pcercuei 0:03b5121a232e 14288 return(-1);
pcercuei 0:03b5121a232e 14289 }
pcercuei 0:03b5121a232e 14290
pcercuei 0:03b5121a232e 14291 /*
pcercuei 0:03b5121a232e 14292 * handle the special cases of "/" amd "." being matched
pcercuei 0:03b5121a232e 14293 */
pcercuei 0:03b5121a232e 14294 if (min_depth == 0) {
pcercuei 0:03b5121a232e 14295 if (from_root) {
pcercuei 0:03b5121a232e 14296 /* Select "/" */
pcercuei 0:03b5121a232e 14297 if (toBool)
pcercuei 0:03b5121a232e 14298 return(1);
pcercuei 0:03b5121a232e 14299 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
pcercuei 0:03b5121a232e 14300 (xmlNodePtr) ctxt->doc);
pcercuei 0:03b5121a232e 14301 } else {
pcercuei 0:03b5121a232e 14302 /* Select "self::node()" */
pcercuei 0:03b5121a232e 14303 if (toBool)
pcercuei 0:03b5121a232e 14304 return(1);
pcercuei 0:03b5121a232e 14305 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node);
pcercuei 0:03b5121a232e 14306 }
pcercuei 0:03b5121a232e 14307 }
pcercuei 0:03b5121a232e 14308 if (max_depth == 0) {
pcercuei 0:03b5121a232e 14309 return(0);
pcercuei 0:03b5121a232e 14310 }
pcercuei 0:03b5121a232e 14311
pcercuei 0:03b5121a232e 14312 if (from_root) {
pcercuei 0:03b5121a232e 14313 cur = (xmlNodePtr)ctxt->doc;
pcercuei 0:03b5121a232e 14314 } else if (ctxt->node != NULL) {
pcercuei 0:03b5121a232e 14315 switch (ctxt->node->type) {
pcercuei 0:03b5121a232e 14316 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 14317 case XML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 14318 case XML_DOCUMENT_FRAG_NODE:
pcercuei 0:03b5121a232e 14319 case XML_HTML_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 14320 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 14321 case XML_DOCB_DOCUMENT_NODE:
pcercuei 0:03b5121a232e 14322 #endif
pcercuei 0:03b5121a232e 14323 cur = ctxt->node;
pcercuei 0:03b5121a232e 14324 break;
pcercuei 0:03b5121a232e 14325 case XML_ATTRIBUTE_NODE:
pcercuei 0:03b5121a232e 14326 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 14327 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 14328 case XML_ENTITY_REF_NODE:
pcercuei 0:03b5121a232e 14329 case XML_ENTITY_NODE:
pcercuei 0:03b5121a232e 14330 case XML_PI_NODE:
pcercuei 0:03b5121a232e 14331 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 14332 case XML_NOTATION_NODE:
pcercuei 0:03b5121a232e 14333 case XML_DTD_NODE:
pcercuei 0:03b5121a232e 14334 case XML_DOCUMENT_TYPE_NODE:
pcercuei 0:03b5121a232e 14335 case XML_ELEMENT_DECL:
pcercuei 0:03b5121a232e 14336 case XML_ATTRIBUTE_DECL:
pcercuei 0:03b5121a232e 14337 case XML_ENTITY_DECL:
pcercuei 0:03b5121a232e 14338 case XML_NAMESPACE_DECL:
pcercuei 0:03b5121a232e 14339 case XML_XINCLUDE_START:
pcercuei 0:03b5121a232e 14340 case XML_XINCLUDE_END:
pcercuei 0:03b5121a232e 14341 break;
pcercuei 0:03b5121a232e 14342 }
pcercuei 0:03b5121a232e 14343 limit = cur;
pcercuei 0:03b5121a232e 14344 }
pcercuei 0:03b5121a232e 14345 if (cur == NULL) {
pcercuei 0:03b5121a232e 14346 return(0);
pcercuei 0:03b5121a232e 14347 }
pcercuei 0:03b5121a232e 14348
pcercuei 0:03b5121a232e 14349 patstream = xmlPatternGetStreamCtxt(comp);
pcercuei 0:03b5121a232e 14350 if (patstream == NULL) {
pcercuei 0:03b5121a232e 14351 /*
pcercuei 0:03b5121a232e 14352 * QUESTION TODO: Is this an error?
pcercuei 0:03b5121a232e 14353 */
pcercuei 0:03b5121a232e 14354 return(0);
pcercuei 0:03b5121a232e 14355 }
pcercuei 0:03b5121a232e 14356
pcercuei 0:03b5121a232e 14357 eval_all_nodes = xmlStreamWantsAnyNode(patstream);
pcercuei 0:03b5121a232e 14358
pcercuei 0:03b5121a232e 14359 if (from_root) {
pcercuei 0:03b5121a232e 14360 ret = xmlStreamPush(patstream, NULL, NULL);
pcercuei 0:03b5121a232e 14361 if (ret < 0) {
pcercuei 0:03b5121a232e 14362 } else if (ret == 1) {
pcercuei 0:03b5121a232e 14363 if (toBool)
pcercuei 0:03b5121a232e 14364 goto return_1;
pcercuei 0:03b5121a232e 14365 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur);
pcercuei 0:03b5121a232e 14366 }
pcercuei 0:03b5121a232e 14367 }
pcercuei 0:03b5121a232e 14368 depth = 0;
pcercuei 0:03b5121a232e 14369 goto scan_children;
pcercuei 0:03b5121a232e 14370 next_node:
pcercuei 0:03b5121a232e 14371 do {
pcercuei 0:03b5121a232e 14372 nb_nodes++;
pcercuei 0:03b5121a232e 14373
pcercuei 0:03b5121a232e 14374 switch (cur->type) {
pcercuei 0:03b5121a232e 14375 case XML_ELEMENT_NODE:
pcercuei 0:03b5121a232e 14376 case XML_TEXT_NODE:
pcercuei 0:03b5121a232e 14377 case XML_CDATA_SECTION_NODE:
pcercuei 0:03b5121a232e 14378 case XML_COMMENT_NODE:
pcercuei 0:03b5121a232e 14379 case XML_PI_NODE:
pcercuei 0:03b5121a232e 14380 if (cur->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 14381 ret = xmlStreamPush(patstream, cur->name,
pcercuei 0:03b5121a232e 14382 (cur->ns ? cur->ns->href : NULL));
pcercuei 0:03b5121a232e 14383 } else if (eval_all_nodes)
pcercuei 0:03b5121a232e 14384 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type);
pcercuei 0:03b5121a232e 14385 else
pcercuei 0:03b5121a232e 14386 break;
pcercuei 0:03b5121a232e 14387
pcercuei 0:03b5121a232e 14388 if (ret < 0) {
pcercuei 0:03b5121a232e 14389 /* NOP. */
pcercuei 0:03b5121a232e 14390 } else if (ret == 1) {
pcercuei 0:03b5121a232e 14391 if (toBool)
pcercuei 0:03b5121a232e 14392 goto return_1;
pcercuei 0:03b5121a232e 14393 if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur)
pcercuei 0:03b5121a232e 14394 < 0) {
pcercuei 0:03b5121a232e 14395 ctxt->lastError.domain = XML_FROM_XPATH;
pcercuei 0:03b5121a232e 14396 ctxt->lastError.code = XML_ERR_NO_MEMORY;
pcercuei 0:03b5121a232e 14397 }
pcercuei 0:03b5121a232e 14398 }
pcercuei 0:03b5121a232e 14399 if ((cur->children == NULL) || (depth >= max_depth)) {
pcercuei 0:03b5121a232e 14400 ret = xmlStreamPop(patstream);
pcercuei 0:03b5121a232e 14401 while (cur->next != NULL) {
pcercuei 0:03b5121a232e 14402 cur = cur->next;
pcercuei 0:03b5121a232e 14403 if ((cur->type != XML_ENTITY_DECL) &&
pcercuei 0:03b5121a232e 14404 (cur->type != XML_DTD_NODE))
pcercuei 0:03b5121a232e 14405 goto next_node;
pcercuei 0:03b5121a232e 14406 }
pcercuei 0:03b5121a232e 14407 }
pcercuei 0:03b5121a232e 14408 default:
pcercuei 0:03b5121a232e 14409 break;
pcercuei 0:03b5121a232e 14410 }
pcercuei 0:03b5121a232e 14411
pcercuei 0:03b5121a232e 14412 scan_children:
pcercuei 0:03b5121a232e 14413 if (cur->type == XML_NAMESPACE_DECL) break;
pcercuei 0:03b5121a232e 14414 if ((cur->children != NULL) && (depth < max_depth)) {
pcercuei 0:03b5121a232e 14415 /*
pcercuei 0:03b5121a232e 14416 * Do not descend on entities declarations
pcercuei 0:03b5121a232e 14417 */
pcercuei 0:03b5121a232e 14418 if (cur->children->type != XML_ENTITY_DECL) {
pcercuei 0:03b5121a232e 14419 cur = cur->children;
pcercuei 0:03b5121a232e 14420 depth++;
pcercuei 0:03b5121a232e 14421 /*
pcercuei 0:03b5121a232e 14422 * Skip DTDs
pcercuei 0:03b5121a232e 14423 */
pcercuei 0:03b5121a232e 14424 if (cur->type != XML_DTD_NODE)
pcercuei 0:03b5121a232e 14425 continue;
pcercuei 0:03b5121a232e 14426 }
pcercuei 0:03b5121a232e 14427 }
pcercuei 0:03b5121a232e 14428
pcercuei 0:03b5121a232e 14429 if (cur == limit)
pcercuei 0:03b5121a232e 14430 break;
pcercuei 0:03b5121a232e 14431
pcercuei 0:03b5121a232e 14432 while (cur->next != NULL) {
pcercuei 0:03b5121a232e 14433 cur = cur->next;
pcercuei 0:03b5121a232e 14434 if ((cur->type != XML_ENTITY_DECL) &&
pcercuei 0:03b5121a232e 14435 (cur->type != XML_DTD_NODE))
pcercuei 0:03b5121a232e 14436 goto next_node;
pcercuei 0:03b5121a232e 14437 }
pcercuei 0:03b5121a232e 14438
pcercuei 0:03b5121a232e 14439 do {
pcercuei 0:03b5121a232e 14440 cur = cur->parent;
pcercuei 0:03b5121a232e 14441 depth--;
pcercuei 0:03b5121a232e 14442 if ((cur == NULL) || (cur == limit))
pcercuei 0:03b5121a232e 14443 goto done;
pcercuei 0:03b5121a232e 14444 if (cur->type == XML_ELEMENT_NODE) {
pcercuei 0:03b5121a232e 14445 ret = xmlStreamPop(patstream);
pcercuei 0:03b5121a232e 14446 } else if ((eval_all_nodes) &&
pcercuei 0:03b5121a232e 14447 ((cur->type == XML_TEXT_NODE) ||
pcercuei 0:03b5121a232e 14448 (cur->type == XML_CDATA_SECTION_NODE) ||
pcercuei 0:03b5121a232e 14449 (cur->type == XML_COMMENT_NODE) ||
pcercuei 0:03b5121a232e 14450 (cur->type == XML_PI_NODE)))
pcercuei 0:03b5121a232e 14451 {
pcercuei 0:03b5121a232e 14452 ret = xmlStreamPop(patstream);
pcercuei 0:03b5121a232e 14453 }
pcercuei 0:03b5121a232e 14454 if (cur->next != NULL) {
pcercuei 0:03b5121a232e 14455 cur = cur->next;
pcercuei 0:03b5121a232e 14456 break;
pcercuei 0:03b5121a232e 14457 }
pcercuei 0:03b5121a232e 14458 } while (cur != NULL);
pcercuei 0:03b5121a232e 14459
pcercuei 0:03b5121a232e 14460 } while ((cur != NULL) && (depth >= 0));
pcercuei 0:03b5121a232e 14461
pcercuei 0:03b5121a232e 14462 done:
pcercuei 0:03b5121a232e 14463
pcercuei 0:03b5121a232e 14464 #if 0
pcercuei 0:03b5121a232e 14465 printf("stream eval: checked %d nodes selected %d\n",
pcercuei 0:03b5121a232e 14466 nb_nodes, retObj->nodesetval->nodeNr);
pcercuei 0:03b5121a232e 14467 #endif
pcercuei 0:03b5121a232e 14468
pcercuei 0:03b5121a232e 14469 if (patstream)
pcercuei 0:03b5121a232e 14470 xmlFreeStreamCtxt(patstream);
pcercuei 0:03b5121a232e 14471 return(0);
pcercuei 0:03b5121a232e 14472
pcercuei 0:03b5121a232e 14473 return_1:
pcercuei 0:03b5121a232e 14474 if (patstream)
pcercuei 0:03b5121a232e 14475 xmlFreeStreamCtxt(patstream);
pcercuei 0:03b5121a232e 14476 return(1);
pcercuei 0:03b5121a232e 14477 }
pcercuei 0:03b5121a232e 14478 #endif /* XPATH_STREAMING */
pcercuei 0:03b5121a232e 14479
pcercuei 0:03b5121a232e 14480 /**
pcercuei 0:03b5121a232e 14481 * xmlXPathRunEval:
pcercuei 0:03b5121a232e 14482 * @ctxt: the XPath parser context with the compiled expression
pcercuei 0:03b5121a232e 14483 * @toBool: evaluate to a boolean result
pcercuei 0:03b5121a232e 14484 *
pcercuei 0:03b5121a232e 14485 * Evaluate the Precompiled XPath expression in the given context.
pcercuei 0:03b5121a232e 14486 */
pcercuei 0:03b5121a232e 14487 static int
pcercuei 0:03b5121a232e 14488 xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
pcercuei 0:03b5121a232e 14489 {
pcercuei 0:03b5121a232e 14490 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 14491
pcercuei 0:03b5121a232e 14492 if ((ctxt == NULL) || (ctxt->comp == NULL))
pcercuei 0:03b5121a232e 14493 return(-1);
pcercuei 0:03b5121a232e 14494
pcercuei 0:03b5121a232e 14495 if (ctxt->valueTab == NULL) {
pcercuei 0:03b5121a232e 14496 /* Allocate the value stack */
pcercuei 0:03b5121a232e 14497 ctxt->valueTab = (xmlXPathObjectPtr *)
pcercuei 0:03b5121a232e 14498 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
pcercuei 0:03b5121a232e 14499 if (ctxt->valueTab == NULL) {
pcercuei 0:03b5121a232e 14500 xmlXPathPErrMemory(ctxt, "creating evaluation context\n");
pcercuei 0:03b5121a232e 14501 xmlFree(ctxt);
pcercuei 0:03b5121a232e 14502 }
pcercuei 0:03b5121a232e 14503 ctxt->valueNr = 0;
pcercuei 0:03b5121a232e 14504 ctxt->valueMax = 10;
pcercuei 0:03b5121a232e 14505 ctxt->value = NULL;
pcercuei 0:03b5121a232e 14506 ctxt->valueFrame = 0;
pcercuei 0:03b5121a232e 14507 }
pcercuei 0:03b5121a232e 14508 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 14509 if (ctxt->comp->stream) {
pcercuei 0:03b5121a232e 14510 int res;
pcercuei 0:03b5121a232e 14511
pcercuei 0:03b5121a232e 14512 if (toBool) {
pcercuei 0:03b5121a232e 14513 /*
pcercuei 0:03b5121a232e 14514 * Evaluation to boolean result.
pcercuei 0:03b5121a232e 14515 */
pcercuei 0:03b5121a232e 14516 res = xmlXPathRunStreamEval(ctxt->context,
pcercuei 0:03b5121a232e 14517 ctxt->comp->stream, NULL, 1);
pcercuei 0:03b5121a232e 14518 if (res != -1)
pcercuei 0:03b5121a232e 14519 return(res);
pcercuei 0:03b5121a232e 14520 } else {
pcercuei 0:03b5121a232e 14521 xmlXPathObjectPtr resObj = NULL;
pcercuei 0:03b5121a232e 14522
pcercuei 0:03b5121a232e 14523 /*
pcercuei 0:03b5121a232e 14524 * Evaluation to a sequence.
pcercuei 0:03b5121a232e 14525 */
pcercuei 0:03b5121a232e 14526 res = xmlXPathRunStreamEval(ctxt->context,
pcercuei 0:03b5121a232e 14527 ctxt->comp->stream, &resObj, 0);
pcercuei 0:03b5121a232e 14528
pcercuei 0:03b5121a232e 14529 if ((res != -1) && (resObj != NULL)) {
pcercuei 0:03b5121a232e 14530 valuePush(ctxt, resObj);
pcercuei 0:03b5121a232e 14531 return(0);
pcercuei 0:03b5121a232e 14532 }
pcercuei 0:03b5121a232e 14533 if (resObj != NULL)
pcercuei 0:03b5121a232e 14534 xmlXPathReleaseObject(ctxt->context, resObj);
pcercuei 0:03b5121a232e 14535 }
pcercuei 0:03b5121a232e 14536 /*
pcercuei 0:03b5121a232e 14537 * QUESTION TODO: This falls back to normal XPath evaluation
pcercuei 0:03b5121a232e 14538 * if res == -1. Is this intended?
pcercuei 0:03b5121a232e 14539 */
pcercuei 0:03b5121a232e 14540 }
pcercuei 0:03b5121a232e 14541 #endif
pcercuei 0:03b5121a232e 14542 comp = ctxt->comp;
pcercuei 0:03b5121a232e 14543 if (comp->last < 0) {
pcercuei 0:03b5121a232e 14544 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 14545 "xmlXPathRunEval: last is less than zero\n");
pcercuei 0:03b5121a232e 14546 return(-1);
pcercuei 0:03b5121a232e 14547 }
pcercuei 0:03b5121a232e 14548 if (toBool)
pcercuei 0:03b5121a232e 14549 return(xmlXPathCompOpEvalToBoolean(ctxt,
pcercuei 0:03b5121a232e 14550 &comp->steps[comp->last], 0));
pcercuei 0:03b5121a232e 14551 else
pcercuei 0:03b5121a232e 14552 xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
pcercuei 0:03b5121a232e 14553
pcercuei 0:03b5121a232e 14554 return(0);
pcercuei 0:03b5121a232e 14555 }
pcercuei 0:03b5121a232e 14556
pcercuei 0:03b5121a232e 14557 /************************************************************************
pcercuei 0:03b5121a232e 14558 * *
pcercuei 0:03b5121a232e 14559 * Public interfaces *
pcercuei 0:03b5121a232e 14560 * *
pcercuei 0:03b5121a232e 14561 ************************************************************************/
pcercuei 0:03b5121a232e 14562
pcercuei 0:03b5121a232e 14563 /**
pcercuei 0:03b5121a232e 14564 * xmlXPathEvalPredicate:
pcercuei 0:03b5121a232e 14565 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 14566 * @res: the Predicate Expression evaluation result
pcercuei 0:03b5121a232e 14567 *
pcercuei 0:03b5121a232e 14568 * Evaluate a predicate result for the current node.
pcercuei 0:03b5121a232e 14569 * A PredicateExpr is evaluated by evaluating the Expr and converting
pcercuei 0:03b5121a232e 14570 * the result to a boolean. If the result is a number, the result will
pcercuei 0:03b5121a232e 14571 * be converted to true if the number is equal to the position of the
pcercuei 0:03b5121a232e 14572 * context node in the context node list (as returned by the position
pcercuei 0:03b5121a232e 14573 * function) and will be converted to false otherwise; if the result
pcercuei 0:03b5121a232e 14574 * is not a number, then the result will be converted as if by a call
pcercuei 0:03b5121a232e 14575 * to the boolean function.
pcercuei 0:03b5121a232e 14576 *
pcercuei 0:03b5121a232e 14577 * Returns 1 if predicate is true, 0 otherwise
pcercuei 0:03b5121a232e 14578 */
pcercuei 0:03b5121a232e 14579 int
pcercuei 0:03b5121a232e 14580 xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
pcercuei 0:03b5121a232e 14581 if ((ctxt == NULL) || (res == NULL)) return(0);
pcercuei 0:03b5121a232e 14582 switch (res->type) {
pcercuei 0:03b5121a232e 14583 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 14584 return(res->boolval);
pcercuei 0:03b5121a232e 14585 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 14586 return(res->floatval == ctxt->proximityPosition);
pcercuei 0:03b5121a232e 14587 case XPATH_NODESET:
pcercuei 0:03b5121a232e 14588 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 14589 if (res->nodesetval == NULL)
pcercuei 0:03b5121a232e 14590 return(0);
pcercuei 0:03b5121a232e 14591 return(res->nodesetval->nodeNr != 0);
pcercuei 0:03b5121a232e 14592 case XPATH_STRING:
pcercuei 0:03b5121a232e 14593 return((res->stringval != NULL) &&
pcercuei 0:03b5121a232e 14594 (xmlStrlen(res->stringval) != 0));
pcercuei 0:03b5121a232e 14595 default:
pcercuei 0:03b5121a232e 14596 STRANGE
pcercuei 0:03b5121a232e 14597 }
pcercuei 0:03b5121a232e 14598 return(0);
pcercuei 0:03b5121a232e 14599 }
pcercuei 0:03b5121a232e 14600
pcercuei 0:03b5121a232e 14601 /**
pcercuei 0:03b5121a232e 14602 * xmlXPathEvaluatePredicateResult:
pcercuei 0:03b5121a232e 14603 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 14604 * @res: the Predicate Expression evaluation result
pcercuei 0:03b5121a232e 14605 *
pcercuei 0:03b5121a232e 14606 * Evaluate a predicate result for the current node.
pcercuei 0:03b5121a232e 14607 * A PredicateExpr is evaluated by evaluating the Expr and converting
pcercuei 0:03b5121a232e 14608 * the result to a boolean. If the result is a number, the result will
pcercuei 0:03b5121a232e 14609 * be converted to true if the number is equal to the position of the
pcercuei 0:03b5121a232e 14610 * context node in the context node list (as returned by the position
pcercuei 0:03b5121a232e 14611 * function) and will be converted to false otherwise; if the result
pcercuei 0:03b5121a232e 14612 * is not a number, then the result will be converted as if by a call
pcercuei 0:03b5121a232e 14613 * to the boolean function.
pcercuei 0:03b5121a232e 14614 *
pcercuei 0:03b5121a232e 14615 * Returns 1 if predicate is true, 0 otherwise
pcercuei 0:03b5121a232e 14616 */
pcercuei 0:03b5121a232e 14617 int
pcercuei 0:03b5121a232e 14618 xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
pcercuei 0:03b5121a232e 14619 xmlXPathObjectPtr res) {
pcercuei 0:03b5121a232e 14620 if ((ctxt == NULL) || (res == NULL)) return(0);
pcercuei 0:03b5121a232e 14621 switch (res->type) {
pcercuei 0:03b5121a232e 14622 case XPATH_BOOLEAN:
pcercuei 0:03b5121a232e 14623 return(res->boolval);
pcercuei 0:03b5121a232e 14624 case XPATH_NUMBER:
pcercuei 0:03b5121a232e 14625 #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200))
pcercuei 0:03b5121a232e 14626 return((res->floatval == ctxt->context->proximityPosition) &&
pcercuei 0:03b5121a232e 14627 (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/
pcercuei 0:03b5121a232e 14628 #else
pcercuei 0:03b5121a232e 14629 return(res->floatval == ctxt->context->proximityPosition);
pcercuei 0:03b5121a232e 14630 #endif
pcercuei 0:03b5121a232e 14631 case XPATH_NODESET:
pcercuei 0:03b5121a232e 14632 case XPATH_XSLT_TREE:
pcercuei 0:03b5121a232e 14633 if (res->nodesetval == NULL)
pcercuei 0:03b5121a232e 14634 return(0);
pcercuei 0:03b5121a232e 14635 return(res->nodesetval->nodeNr != 0);
pcercuei 0:03b5121a232e 14636 case XPATH_STRING:
pcercuei 0:03b5121a232e 14637 return((res->stringval != NULL) && (res->stringval[0] != 0));
pcercuei 0:03b5121a232e 14638 #ifdef LIBXML_XPTR_ENABLED
pcercuei 0:03b5121a232e 14639 case XPATH_LOCATIONSET:{
pcercuei 0:03b5121a232e 14640 xmlLocationSetPtr ptr = res->user;
pcercuei 0:03b5121a232e 14641 if (ptr == NULL)
pcercuei 0:03b5121a232e 14642 return(0);
pcercuei 0:03b5121a232e 14643 return (ptr->locNr != 0);
pcercuei 0:03b5121a232e 14644 }
pcercuei 0:03b5121a232e 14645 #endif
pcercuei 0:03b5121a232e 14646 default:
pcercuei 0:03b5121a232e 14647 STRANGE
pcercuei 0:03b5121a232e 14648 }
pcercuei 0:03b5121a232e 14649 return(0);
pcercuei 0:03b5121a232e 14650 }
pcercuei 0:03b5121a232e 14651
pcercuei 0:03b5121a232e 14652 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 14653 /**
pcercuei 0:03b5121a232e 14654 * xmlXPathTryStreamCompile:
pcercuei 0:03b5121a232e 14655 * @ctxt: an XPath context
pcercuei 0:03b5121a232e 14656 * @str: the XPath expression
pcercuei 0:03b5121a232e 14657 *
pcercuei 0:03b5121a232e 14658 * Try to compile the XPath expression as a streamable subset.
pcercuei 0:03b5121a232e 14659 *
pcercuei 0:03b5121a232e 14660 * Returns the compiled expression or NULL if failed to compile.
pcercuei 0:03b5121a232e 14661 */
pcercuei 0:03b5121a232e 14662 static xmlXPathCompExprPtr
pcercuei 0:03b5121a232e 14663 xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
pcercuei 0:03b5121a232e 14664 /*
pcercuei 0:03b5121a232e 14665 * Optimization: use streaming patterns when the XPath expression can
pcercuei 0:03b5121a232e 14666 * be compiled to a stream lookup
pcercuei 0:03b5121a232e 14667 */
pcercuei 0:03b5121a232e 14668 xmlPatternPtr stream;
pcercuei 0:03b5121a232e 14669 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 14670 xmlDictPtr dict = NULL;
pcercuei 0:03b5121a232e 14671 const xmlChar **namespaces = NULL;
pcercuei 0:03b5121a232e 14672 xmlNsPtr ns;
pcercuei 0:03b5121a232e 14673 int i, j;
pcercuei 0:03b5121a232e 14674
pcercuei 0:03b5121a232e 14675 if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
pcercuei 0:03b5121a232e 14676 (!xmlStrchr(str, '@'))) {
pcercuei 0:03b5121a232e 14677 const xmlChar *tmp;
pcercuei 0:03b5121a232e 14678
pcercuei 0:03b5121a232e 14679 /*
pcercuei 0:03b5121a232e 14680 * We don't try to handle expressions using the verbose axis
pcercuei 0:03b5121a232e 14681 * specifiers ("::"), just the simplied form at this point.
pcercuei 0:03b5121a232e 14682 * Additionally, if there is no list of namespaces available and
pcercuei 0:03b5121a232e 14683 * there's a ":" in the expression, indicating a prefixed QName,
pcercuei 0:03b5121a232e 14684 * then we won't try to compile either. xmlPatterncompile() needs
pcercuei 0:03b5121a232e 14685 * to have a list of namespaces at compilation time in order to
pcercuei 0:03b5121a232e 14686 * compile prefixed name tests.
pcercuei 0:03b5121a232e 14687 */
pcercuei 0:03b5121a232e 14688 tmp = xmlStrchr(str, ':');
pcercuei 0:03b5121a232e 14689 if ((tmp != NULL) &&
pcercuei 0:03b5121a232e 14690 ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':')))
pcercuei 0:03b5121a232e 14691 return(NULL);
pcercuei 0:03b5121a232e 14692
pcercuei 0:03b5121a232e 14693 if (ctxt != NULL) {
pcercuei 0:03b5121a232e 14694 dict = ctxt->dict;
pcercuei 0:03b5121a232e 14695 if (ctxt->nsNr > 0) {
pcercuei 0:03b5121a232e 14696 namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
pcercuei 0:03b5121a232e 14697 if (namespaces == NULL) {
pcercuei 0:03b5121a232e 14698 xmlXPathErrMemory(ctxt, "allocating namespaces array\n");
pcercuei 0:03b5121a232e 14699 return(NULL);
pcercuei 0:03b5121a232e 14700 }
pcercuei 0:03b5121a232e 14701 for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
pcercuei 0:03b5121a232e 14702 ns = ctxt->namespaces[j];
pcercuei 0:03b5121a232e 14703 namespaces[i++] = ns->href;
pcercuei 0:03b5121a232e 14704 namespaces[i++] = ns->prefix;
pcercuei 0:03b5121a232e 14705 }
pcercuei 0:03b5121a232e 14706 namespaces[i++] = NULL;
pcercuei 0:03b5121a232e 14707 namespaces[i] = NULL;
pcercuei 0:03b5121a232e 14708 }
pcercuei 0:03b5121a232e 14709 }
pcercuei 0:03b5121a232e 14710
pcercuei 0:03b5121a232e 14711 stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
pcercuei 0:03b5121a232e 14712 &namespaces[0]);
pcercuei 0:03b5121a232e 14713 if (namespaces != NULL) {
pcercuei 0:03b5121a232e 14714 xmlFree((xmlChar **)namespaces);
pcercuei 0:03b5121a232e 14715 }
pcercuei 0:03b5121a232e 14716 if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
pcercuei 0:03b5121a232e 14717 comp = xmlXPathNewCompExpr();
pcercuei 0:03b5121a232e 14718 if (comp == NULL) {
pcercuei 0:03b5121a232e 14719 xmlXPathErrMemory(ctxt, "allocating streamable expression\n");
pcercuei 0:03b5121a232e 14720 return(NULL);
pcercuei 0:03b5121a232e 14721 }
pcercuei 0:03b5121a232e 14722 comp->stream = stream;
pcercuei 0:03b5121a232e 14723 comp->dict = dict;
pcercuei 0:03b5121a232e 14724 if (comp->dict)
pcercuei 0:03b5121a232e 14725 xmlDictReference(comp->dict);
pcercuei 0:03b5121a232e 14726 return(comp);
pcercuei 0:03b5121a232e 14727 }
pcercuei 0:03b5121a232e 14728 xmlFreePattern(stream);
pcercuei 0:03b5121a232e 14729 }
pcercuei 0:03b5121a232e 14730 return(NULL);
pcercuei 0:03b5121a232e 14731 }
pcercuei 0:03b5121a232e 14732 #endif /* XPATH_STREAMING */
pcercuei 0:03b5121a232e 14733
pcercuei 0:03b5121a232e 14734 static void
pcercuei 0:03b5121a232e 14735 xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
pcercuei 0:03b5121a232e 14736 {
pcercuei 0:03b5121a232e 14737 /*
pcercuei 0:03b5121a232e 14738 * Try to rewrite "descendant-or-self::node()/foo" to an optimized
pcercuei 0:03b5121a232e 14739 * internal representation.
pcercuei 0:03b5121a232e 14740 */
pcercuei 0:03b5121a232e 14741
pcercuei 0:03b5121a232e 14742 if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
pcercuei 0:03b5121a232e 14743 (op->ch1 != -1) &&
pcercuei 0:03b5121a232e 14744 (op->ch2 == -1 /* no predicate */))
pcercuei 0:03b5121a232e 14745 {
pcercuei 0:03b5121a232e 14746 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
pcercuei 0:03b5121a232e 14747
pcercuei 0:03b5121a232e 14748 if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
pcercuei 0:03b5121a232e 14749 ((xmlXPathAxisVal) prevop->value ==
pcercuei 0:03b5121a232e 14750 AXIS_DESCENDANT_OR_SELF) &&
pcercuei 0:03b5121a232e 14751 (prevop->ch2 == -1) &&
pcercuei 0:03b5121a232e 14752 ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
pcercuei 0:03b5121a232e 14753 ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
pcercuei 0:03b5121a232e 14754 {
pcercuei 0:03b5121a232e 14755 /*
pcercuei 0:03b5121a232e 14756 * This is a "descendant-or-self::node()" without predicates.
pcercuei 0:03b5121a232e 14757 * Try to eliminate it.
pcercuei 0:03b5121a232e 14758 */
pcercuei 0:03b5121a232e 14759
pcercuei 0:03b5121a232e 14760 switch ((xmlXPathAxisVal) op->value) {
pcercuei 0:03b5121a232e 14761 case AXIS_CHILD:
pcercuei 0:03b5121a232e 14762 case AXIS_DESCENDANT:
pcercuei 0:03b5121a232e 14763 /*
pcercuei 0:03b5121a232e 14764 * Convert "descendant-or-self::node()/child::" or
pcercuei 0:03b5121a232e 14765 * "descendant-or-self::node()/descendant::" to
pcercuei 0:03b5121a232e 14766 * "descendant::"
pcercuei 0:03b5121a232e 14767 */
pcercuei 0:03b5121a232e 14768 op->ch1 = prevop->ch1;
pcercuei 0:03b5121a232e 14769 op->value = AXIS_DESCENDANT;
pcercuei 0:03b5121a232e 14770 break;
pcercuei 0:03b5121a232e 14771 case AXIS_SELF:
pcercuei 0:03b5121a232e 14772 case AXIS_DESCENDANT_OR_SELF:
pcercuei 0:03b5121a232e 14773 /*
pcercuei 0:03b5121a232e 14774 * Convert "descendant-or-self::node()/self::" or
pcercuei 0:03b5121a232e 14775 * "descendant-or-self::node()/descendant-or-self::" to
pcercuei 0:03b5121a232e 14776 * to "descendant-or-self::"
pcercuei 0:03b5121a232e 14777 */
pcercuei 0:03b5121a232e 14778 op->ch1 = prevop->ch1;
pcercuei 0:03b5121a232e 14779 op->value = AXIS_DESCENDANT_OR_SELF;
pcercuei 0:03b5121a232e 14780 break;
pcercuei 0:03b5121a232e 14781 default:
pcercuei 0:03b5121a232e 14782 break;
pcercuei 0:03b5121a232e 14783 }
pcercuei 0:03b5121a232e 14784 }
pcercuei 0:03b5121a232e 14785 }
pcercuei 0:03b5121a232e 14786
pcercuei 0:03b5121a232e 14787 /* Recurse */
pcercuei 0:03b5121a232e 14788 if (op->ch1 != -1)
pcercuei 0:03b5121a232e 14789 xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);
pcercuei 0:03b5121a232e 14790 if (op->ch2 != -1)
pcercuei 0:03b5121a232e 14791 xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]);
pcercuei 0:03b5121a232e 14792 }
pcercuei 0:03b5121a232e 14793
pcercuei 0:03b5121a232e 14794 /**
pcercuei 0:03b5121a232e 14795 * xmlXPathCtxtCompile:
pcercuei 0:03b5121a232e 14796 * @ctxt: an XPath context
pcercuei 0:03b5121a232e 14797 * @str: the XPath expression
pcercuei 0:03b5121a232e 14798 *
pcercuei 0:03b5121a232e 14799 * Compile an XPath expression
pcercuei 0:03b5121a232e 14800 *
pcercuei 0:03b5121a232e 14801 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
pcercuei 0:03b5121a232e 14802 * the caller has to free the object.
pcercuei 0:03b5121a232e 14803 */
pcercuei 0:03b5121a232e 14804 xmlXPathCompExprPtr
pcercuei 0:03b5121a232e 14805 xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
pcercuei 0:03b5121a232e 14806 xmlXPathParserContextPtr pctxt;
pcercuei 0:03b5121a232e 14807 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 14808
pcercuei 0:03b5121a232e 14809 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 14810 comp = xmlXPathTryStreamCompile(ctxt, str);
pcercuei 0:03b5121a232e 14811 if (comp != NULL)
pcercuei 0:03b5121a232e 14812 return(comp);
pcercuei 0:03b5121a232e 14813 #endif
pcercuei 0:03b5121a232e 14814
pcercuei 0:03b5121a232e 14815 xmlXPathInit();
pcercuei 0:03b5121a232e 14816
pcercuei 0:03b5121a232e 14817 pctxt = xmlXPathNewParserContext(str, ctxt);
pcercuei 0:03b5121a232e 14818 if (pctxt == NULL)
pcercuei 0:03b5121a232e 14819 return NULL;
pcercuei 0:03b5121a232e 14820 xmlXPathCompileExpr(pctxt, 1);
pcercuei 0:03b5121a232e 14821
pcercuei 0:03b5121a232e 14822 if( pctxt->error != XPATH_EXPRESSION_OK )
pcercuei 0:03b5121a232e 14823 {
pcercuei 0:03b5121a232e 14824 xmlXPathFreeParserContext(pctxt);
pcercuei 0:03b5121a232e 14825 return(NULL);
pcercuei 0:03b5121a232e 14826 }
pcercuei 0:03b5121a232e 14827
pcercuei 0:03b5121a232e 14828 if (*pctxt->cur != 0) {
pcercuei 0:03b5121a232e 14829 /*
pcercuei 0:03b5121a232e 14830 * aleksey: in some cases this line prints *second* error message
pcercuei 0:03b5121a232e 14831 * (see bug #78858) and probably this should be fixed.
pcercuei 0:03b5121a232e 14832 * However, we are not sure that all error messages are printed
pcercuei 0:03b5121a232e 14833 * out in other places. It's not critical so we leave it as-is for now
pcercuei 0:03b5121a232e 14834 */
pcercuei 0:03b5121a232e 14835 xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 14836 comp = NULL;
pcercuei 0:03b5121a232e 14837 } else {
pcercuei 0:03b5121a232e 14838 comp = pctxt->comp;
pcercuei 0:03b5121a232e 14839 pctxt->comp = NULL;
pcercuei 0:03b5121a232e 14840 }
pcercuei 0:03b5121a232e 14841 xmlXPathFreeParserContext(pctxt);
pcercuei 0:03b5121a232e 14842
pcercuei 0:03b5121a232e 14843 if (comp != NULL) {
pcercuei 0:03b5121a232e 14844 comp->expr = xmlStrdup(str);
pcercuei 0:03b5121a232e 14845 #ifdef DEBUG_EVAL_COUNTS
pcercuei 0:03b5121a232e 14846 comp->string = xmlStrdup(str);
pcercuei 0:03b5121a232e 14847 comp->nb = 0;
pcercuei 0:03b5121a232e 14848 #endif
pcercuei 0:03b5121a232e 14849 if ((comp->nbStep > 1) && (comp->last >= 0)) {
pcercuei 0:03b5121a232e 14850 xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]);
pcercuei 0:03b5121a232e 14851 }
pcercuei 0:03b5121a232e 14852 }
pcercuei 0:03b5121a232e 14853 return(comp);
pcercuei 0:03b5121a232e 14854 }
pcercuei 0:03b5121a232e 14855
pcercuei 0:03b5121a232e 14856 /**
pcercuei 0:03b5121a232e 14857 * xmlXPathCompile:
pcercuei 0:03b5121a232e 14858 * @str: the XPath expression
pcercuei 0:03b5121a232e 14859 *
pcercuei 0:03b5121a232e 14860 * Compile an XPath expression
pcercuei 0:03b5121a232e 14861 *
pcercuei 0:03b5121a232e 14862 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
pcercuei 0:03b5121a232e 14863 * the caller has to free the object.
pcercuei 0:03b5121a232e 14864 */
pcercuei 0:03b5121a232e 14865 xmlXPathCompExprPtr
pcercuei 0:03b5121a232e 14866 xmlXPathCompile(const xmlChar *str) {
pcercuei 0:03b5121a232e 14867 return(xmlXPathCtxtCompile(NULL, str));
pcercuei 0:03b5121a232e 14868 }
pcercuei 0:03b5121a232e 14869
pcercuei 0:03b5121a232e 14870 /**
pcercuei 0:03b5121a232e 14871 * xmlXPathCompiledEvalInternal:
pcercuei 0:03b5121a232e 14872 * @comp: the compiled XPath expression
pcercuei 0:03b5121a232e 14873 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 14874 * @resObj: the resulting XPath object or NULL
pcercuei 0:03b5121a232e 14875 * @toBool: 1 if only a boolean result is requested
pcercuei 0:03b5121a232e 14876 *
pcercuei 0:03b5121a232e 14877 * Evaluate the Precompiled XPath expression in the given context.
pcercuei 0:03b5121a232e 14878 * The caller has to free @resObj.
pcercuei 0:03b5121a232e 14879 *
pcercuei 0:03b5121a232e 14880 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
pcercuei 0:03b5121a232e 14881 * the caller has to free the object.
pcercuei 0:03b5121a232e 14882 */
pcercuei 0:03b5121a232e 14883 static int
pcercuei 0:03b5121a232e 14884 xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
pcercuei 0:03b5121a232e 14885 xmlXPathContextPtr ctxt,
pcercuei 0:03b5121a232e 14886 xmlXPathObjectPtr *resObj,
pcercuei 0:03b5121a232e 14887 int toBool)
pcercuei 0:03b5121a232e 14888 {
pcercuei 0:03b5121a232e 14889 xmlXPathParserContextPtr pctxt;
pcercuei 0:03b5121a232e 14890 #ifndef LIBXML_THREAD_ENABLED
pcercuei 0:03b5121a232e 14891 static int reentance = 0;
pcercuei 0:03b5121a232e 14892 #endif
pcercuei 0:03b5121a232e 14893 int res;
pcercuei 0:03b5121a232e 14894
pcercuei 0:03b5121a232e 14895 CHECK_CTXT_NEG(ctxt)
pcercuei 0:03b5121a232e 14896
pcercuei 0:03b5121a232e 14897 if (comp == NULL)
pcercuei 0:03b5121a232e 14898 return(-1);
pcercuei 0:03b5121a232e 14899 xmlXPathInit();
pcercuei 0:03b5121a232e 14900
pcercuei 0:03b5121a232e 14901 #ifndef LIBXML_THREAD_ENABLED
pcercuei 0:03b5121a232e 14902 reentance++;
pcercuei 0:03b5121a232e 14903 if (reentance > 1)
pcercuei 0:03b5121a232e 14904 xmlXPathDisableOptimizer = 1;
pcercuei 0:03b5121a232e 14905 #endif
pcercuei 0:03b5121a232e 14906
pcercuei 0:03b5121a232e 14907 #ifdef DEBUG_EVAL_COUNTS
pcercuei 0:03b5121a232e 14908 comp->nb++;
pcercuei 0:03b5121a232e 14909 if ((comp->string != NULL) && (comp->nb > 100)) {
pcercuei 0:03b5121a232e 14910 fprintf(stderr, "100 x %s\n", comp->string);
pcercuei 0:03b5121a232e 14911 comp->nb = 0;
pcercuei 0:03b5121a232e 14912 }
pcercuei 0:03b5121a232e 14913 #endif
pcercuei 0:03b5121a232e 14914 pctxt = xmlXPathCompParserContext(comp, ctxt);
pcercuei 0:03b5121a232e 14915 res = xmlXPathRunEval(pctxt, toBool);
pcercuei 0:03b5121a232e 14916
pcercuei 0:03b5121a232e 14917 if (resObj) {
pcercuei 0:03b5121a232e 14918 if (pctxt->value == NULL) {
pcercuei 0:03b5121a232e 14919 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 14920 "xmlXPathCompiledEval: evaluation failed\n");
pcercuei 0:03b5121a232e 14921 *resObj = NULL;
pcercuei 0:03b5121a232e 14922 } else {
pcercuei 0:03b5121a232e 14923 *resObj = valuePop(pctxt);
pcercuei 0:03b5121a232e 14924 }
pcercuei 0:03b5121a232e 14925 }
pcercuei 0:03b5121a232e 14926
pcercuei 0:03b5121a232e 14927 /*
pcercuei 0:03b5121a232e 14928 * Pop all remaining objects from the stack.
pcercuei 0:03b5121a232e 14929 */
pcercuei 0:03b5121a232e 14930 if (pctxt->valueNr > 0) {
pcercuei 0:03b5121a232e 14931 xmlXPathObjectPtr tmp;
pcercuei 0:03b5121a232e 14932 int stack = 0;
pcercuei 0:03b5121a232e 14933
pcercuei 0:03b5121a232e 14934 do {
pcercuei 0:03b5121a232e 14935 tmp = valuePop(pctxt);
pcercuei 0:03b5121a232e 14936 if (tmp != NULL) {
pcercuei 0:03b5121a232e 14937 stack++;
pcercuei 0:03b5121a232e 14938 xmlXPathReleaseObject(ctxt, tmp);
pcercuei 0:03b5121a232e 14939 }
pcercuei 0:03b5121a232e 14940 } while (tmp != NULL);
pcercuei 0:03b5121a232e 14941 if ((stack != 0) &&
pcercuei 0:03b5121a232e 14942 ((toBool) || ((resObj) && (*resObj))))
pcercuei 0:03b5121a232e 14943 {
pcercuei 0:03b5121a232e 14944 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 14945 "xmlXPathCompiledEval: %d objects left on the stack.\n",
pcercuei 0:03b5121a232e 14946 stack);
pcercuei 0:03b5121a232e 14947 }
pcercuei 0:03b5121a232e 14948 }
pcercuei 0:03b5121a232e 14949
pcercuei 0:03b5121a232e 14950 if ((pctxt->error != XPATH_EXPRESSION_OK) && (resObj) && (*resObj)) {
pcercuei 0:03b5121a232e 14951 xmlXPathFreeObject(*resObj);
pcercuei 0:03b5121a232e 14952 *resObj = NULL;
pcercuei 0:03b5121a232e 14953 }
pcercuei 0:03b5121a232e 14954 pctxt->comp = NULL;
pcercuei 0:03b5121a232e 14955 xmlXPathFreeParserContext(pctxt);
pcercuei 0:03b5121a232e 14956 #ifndef LIBXML_THREAD_ENABLED
pcercuei 0:03b5121a232e 14957 reentance--;
pcercuei 0:03b5121a232e 14958 #endif
pcercuei 0:03b5121a232e 14959
pcercuei 0:03b5121a232e 14960 return(res);
pcercuei 0:03b5121a232e 14961 }
pcercuei 0:03b5121a232e 14962
pcercuei 0:03b5121a232e 14963 /**
pcercuei 0:03b5121a232e 14964 * xmlXPathCompiledEval:
pcercuei 0:03b5121a232e 14965 * @comp: the compiled XPath expression
pcercuei 0:03b5121a232e 14966 * @ctx: the XPath context
pcercuei 0:03b5121a232e 14967 *
pcercuei 0:03b5121a232e 14968 * Evaluate the Precompiled XPath expression in the given context.
pcercuei 0:03b5121a232e 14969 *
pcercuei 0:03b5121a232e 14970 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
pcercuei 0:03b5121a232e 14971 * the caller has to free the object.
pcercuei 0:03b5121a232e 14972 */
pcercuei 0:03b5121a232e 14973 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 14974 xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx)
pcercuei 0:03b5121a232e 14975 {
pcercuei 0:03b5121a232e 14976 xmlXPathObjectPtr res = NULL;
pcercuei 0:03b5121a232e 14977
pcercuei 0:03b5121a232e 14978 xmlXPathCompiledEvalInternal(comp, ctx, &res, 0);
pcercuei 0:03b5121a232e 14979 return(res);
pcercuei 0:03b5121a232e 14980 }
pcercuei 0:03b5121a232e 14981
pcercuei 0:03b5121a232e 14982 /**
pcercuei 0:03b5121a232e 14983 * xmlXPathCompiledEvalToBoolean:
pcercuei 0:03b5121a232e 14984 * @comp: the compiled XPath expression
pcercuei 0:03b5121a232e 14985 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 14986 *
pcercuei 0:03b5121a232e 14987 * Applies the XPath boolean() function on the result of the given
pcercuei 0:03b5121a232e 14988 * compiled expression.
pcercuei 0:03b5121a232e 14989 *
pcercuei 0:03b5121a232e 14990 * Returns 1 if the expression evaluated to true, 0 if to false and
pcercuei 0:03b5121a232e 14991 * -1 in API and internal errors.
pcercuei 0:03b5121a232e 14992 */
pcercuei 0:03b5121a232e 14993 int
pcercuei 0:03b5121a232e 14994 xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,
pcercuei 0:03b5121a232e 14995 xmlXPathContextPtr ctxt)
pcercuei 0:03b5121a232e 14996 {
pcercuei 0:03b5121a232e 14997 return(xmlXPathCompiledEvalInternal(comp, ctxt, NULL, 1));
pcercuei 0:03b5121a232e 14998 }
pcercuei 0:03b5121a232e 14999
pcercuei 0:03b5121a232e 15000 /**
pcercuei 0:03b5121a232e 15001 * xmlXPathEvalExpr:
pcercuei 0:03b5121a232e 15002 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 15003 *
pcercuei 0:03b5121a232e 15004 * Parse and evaluate an XPath expression in the given context,
pcercuei 0:03b5121a232e 15005 * then push the result on the context stack
pcercuei 0:03b5121a232e 15006 */
pcercuei 0:03b5121a232e 15007 void
pcercuei 0:03b5121a232e 15008 xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 15009 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 15010 xmlXPathCompExprPtr comp;
pcercuei 0:03b5121a232e 15011 #endif
pcercuei 0:03b5121a232e 15012
pcercuei 0:03b5121a232e 15013 if (ctxt == NULL) return;
pcercuei 0:03b5121a232e 15014
pcercuei 0:03b5121a232e 15015 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 15016 comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
pcercuei 0:03b5121a232e 15017 if (comp != NULL) {
pcercuei 0:03b5121a232e 15018 if (ctxt->comp != NULL)
pcercuei 0:03b5121a232e 15019 xmlXPathFreeCompExpr(ctxt->comp);
pcercuei 0:03b5121a232e 15020 ctxt->comp = comp;
pcercuei 0:03b5121a232e 15021 if (ctxt->cur != NULL)
pcercuei 0:03b5121a232e 15022 while (*ctxt->cur != 0) ctxt->cur++;
pcercuei 0:03b5121a232e 15023 } else
pcercuei 0:03b5121a232e 15024 #endif
pcercuei 0:03b5121a232e 15025 {
pcercuei 0:03b5121a232e 15026 xmlXPathCompileExpr(ctxt, 1);
pcercuei 0:03b5121a232e 15027 if ((ctxt->error == XPATH_EXPRESSION_OK) &&
pcercuei 0:03b5121a232e 15028 (ctxt->comp != NULL) &&
pcercuei 0:03b5121a232e 15029 (ctxt->comp->nbStep > 1) &&
pcercuei 0:03b5121a232e 15030 (ctxt->comp->last >= 0))
pcercuei 0:03b5121a232e 15031 {
pcercuei 0:03b5121a232e 15032 xmlXPathOptimizeExpression(ctxt->comp,
pcercuei 0:03b5121a232e 15033 &ctxt->comp->steps[ctxt->comp->last]);
pcercuei 0:03b5121a232e 15034 }
pcercuei 0:03b5121a232e 15035 }
pcercuei 0:03b5121a232e 15036 CHECK_ERROR;
pcercuei 0:03b5121a232e 15037 xmlXPathRunEval(ctxt, 0);
pcercuei 0:03b5121a232e 15038 }
pcercuei 0:03b5121a232e 15039
pcercuei 0:03b5121a232e 15040 /**
pcercuei 0:03b5121a232e 15041 * xmlXPathEval:
pcercuei 0:03b5121a232e 15042 * @str: the XPath expression
pcercuei 0:03b5121a232e 15043 * @ctx: the XPath context
pcercuei 0:03b5121a232e 15044 *
pcercuei 0:03b5121a232e 15045 * Evaluate the XPath Location Path in the given context.
pcercuei 0:03b5121a232e 15046 *
pcercuei 0:03b5121a232e 15047 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
pcercuei 0:03b5121a232e 15048 * the caller has to free the object.
pcercuei 0:03b5121a232e 15049 */
pcercuei 0:03b5121a232e 15050 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 15051 xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
pcercuei 0:03b5121a232e 15052 xmlXPathParserContextPtr ctxt;
pcercuei 0:03b5121a232e 15053 xmlXPathObjectPtr res, tmp, init = NULL;
pcercuei 0:03b5121a232e 15054 int stack = 0;
pcercuei 0:03b5121a232e 15055
pcercuei 0:03b5121a232e 15056 CHECK_CTXT(ctx)
pcercuei 0:03b5121a232e 15057
pcercuei 0:03b5121a232e 15058 xmlXPathInit();
pcercuei 0:03b5121a232e 15059
pcercuei 0:03b5121a232e 15060 ctxt = xmlXPathNewParserContext(str, ctx);
pcercuei 0:03b5121a232e 15061 if (ctxt == NULL)
pcercuei 0:03b5121a232e 15062 return NULL;
pcercuei 0:03b5121a232e 15063 xmlXPathEvalExpr(ctxt);
pcercuei 0:03b5121a232e 15064
pcercuei 0:03b5121a232e 15065 if (ctxt->value == NULL) {
pcercuei 0:03b5121a232e 15066 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 15067 "xmlXPathEval: evaluation failed\n");
pcercuei 0:03b5121a232e 15068 res = NULL;
pcercuei 0:03b5121a232e 15069 } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL)
pcercuei 0:03b5121a232e 15070 #ifdef XPATH_STREAMING
pcercuei 0:03b5121a232e 15071 && (ctxt->comp->stream == NULL)
pcercuei 0:03b5121a232e 15072 #endif
pcercuei 0:03b5121a232e 15073 ) {
pcercuei 0:03b5121a232e 15074 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 15075 res = NULL;
pcercuei 0:03b5121a232e 15076 } else {
pcercuei 0:03b5121a232e 15077 res = valuePop(ctxt);
pcercuei 0:03b5121a232e 15078 }
pcercuei 0:03b5121a232e 15079
pcercuei 0:03b5121a232e 15080 do {
pcercuei 0:03b5121a232e 15081 tmp = valuePop(ctxt);
pcercuei 0:03b5121a232e 15082 if (tmp != NULL) {
pcercuei 0:03b5121a232e 15083 if (tmp != init)
pcercuei 0:03b5121a232e 15084 stack++;
pcercuei 0:03b5121a232e 15085 xmlXPathReleaseObject(ctx, tmp);
pcercuei 0:03b5121a232e 15086 }
pcercuei 0:03b5121a232e 15087 } while (tmp != NULL);
pcercuei 0:03b5121a232e 15088 if ((stack != 0) && (res != NULL)) {
pcercuei 0:03b5121a232e 15089 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 15090 "xmlXPathEval: %d object left on the stack\n",
pcercuei 0:03b5121a232e 15091 stack);
pcercuei 0:03b5121a232e 15092 }
pcercuei 0:03b5121a232e 15093 if (ctxt->error != XPATH_EXPRESSION_OK) {
pcercuei 0:03b5121a232e 15094 xmlXPathFreeObject(res);
pcercuei 0:03b5121a232e 15095 res = NULL;
pcercuei 0:03b5121a232e 15096 }
pcercuei 0:03b5121a232e 15097
pcercuei 0:03b5121a232e 15098 xmlXPathFreeParserContext(ctxt);
pcercuei 0:03b5121a232e 15099 return(res);
pcercuei 0:03b5121a232e 15100 }
pcercuei 0:03b5121a232e 15101
pcercuei 0:03b5121a232e 15102 /**
pcercuei 0:03b5121a232e 15103 * xmlXPathSetContextNode:
pcercuei 0:03b5121a232e 15104 * @node: the node to to use as the context node
pcercuei 0:03b5121a232e 15105 * @ctx: the XPath context
pcercuei 0:03b5121a232e 15106 *
pcercuei 0:03b5121a232e 15107 * Sets 'node' as the context node. The node must be in the same
pcercuei 0:03b5121a232e 15108 * document as that associated with the context.
pcercuei 0:03b5121a232e 15109 *
pcercuei 0:03b5121a232e 15110 * Returns -1 in case of error or 0 if successful
pcercuei 0:03b5121a232e 15111 */
pcercuei 0:03b5121a232e 15112 int
pcercuei 0:03b5121a232e 15113 xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
pcercuei 0:03b5121a232e 15114 if ((node == NULL) || (ctx == NULL))
pcercuei 0:03b5121a232e 15115 return(-1);
pcercuei 0:03b5121a232e 15116
pcercuei 0:03b5121a232e 15117 if (node->doc == ctx->doc) {
pcercuei 0:03b5121a232e 15118 ctx->node = node;
pcercuei 0:03b5121a232e 15119 return(0);
pcercuei 0:03b5121a232e 15120 }
pcercuei 0:03b5121a232e 15121 return(-1);
pcercuei 0:03b5121a232e 15122 }
pcercuei 0:03b5121a232e 15123
pcercuei 0:03b5121a232e 15124 /**
pcercuei 0:03b5121a232e 15125 * xmlXPathNodeEval:
pcercuei 0:03b5121a232e 15126 * @node: the node to to use as the context node
pcercuei 0:03b5121a232e 15127 * @str: the XPath expression
pcercuei 0:03b5121a232e 15128 * @ctx: the XPath context
pcercuei 0:03b5121a232e 15129 *
pcercuei 0:03b5121a232e 15130 * Evaluate the XPath Location Path in the given context. The node 'node'
pcercuei 0:03b5121a232e 15131 * is set as the context node. The context node is not restored.
pcercuei 0:03b5121a232e 15132 *
pcercuei 0:03b5121a232e 15133 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
pcercuei 0:03b5121a232e 15134 * the caller has to free the object.
pcercuei 0:03b5121a232e 15135 */
pcercuei 0:03b5121a232e 15136 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 15137 xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
pcercuei 0:03b5121a232e 15138 if (str == NULL)
pcercuei 0:03b5121a232e 15139 return(NULL);
pcercuei 0:03b5121a232e 15140 if (xmlXPathSetContextNode(node, ctx) < 0)
pcercuei 0:03b5121a232e 15141 return(NULL);
pcercuei 0:03b5121a232e 15142 return(xmlXPathEval(str, ctx));
pcercuei 0:03b5121a232e 15143 }
pcercuei 0:03b5121a232e 15144
pcercuei 0:03b5121a232e 15145 /**
pcercuei 0:03b5121a232e 15146 * xmlXPathEvalExpression:
pcercuei 0:03b5121a232e 15147 * @str: the XPath expression
pcercuei 0:03b5121a232e 15148 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 15149 *
pcercuei 0:03b5121a232e 15150 * Evaluate the XPath expression in the given context.
pcercuei 0:03b5121a232e 15151 *
pcercuei 0:03b5121a232e 15152 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
pcercuei 0:03b5121a232e 15153 * the caller has to free the object.
pcercuei 0:03b5121a232e 15154 */
pcercuei 0:03b5121a232e 15155 xmlXPathObjectPtr
pcercuei 0:03b5121a232e 15156 xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
pcercuei 0:03b5121a232e 15157 xmlXPathParserContextPtr pctxt;
pcercuei 0:03b5121a232e 15158 xmlXPathObjectPtr res, tmp;
pcercuei 0:03b5121a232e 15159 int stack = 0;
pcercuei 0:03b5121a232e 15160
pcercuei 0:03b5121a232e 15161 CHECK_CTXT(ctxt)
pcercuei 0:03b5121a232e 15162
pcercuei 0:03b5121a232e 15163 xmlXPathInit();
pcercuei 0:03b5121a232e 15164
pcercuei 0:03b5121a232e 15165 pctxt = xmlXPathNewParserContext(str, ctxt);
pcercuei 0:03b5121a232e 15166 if (pctxt == NULL)
pcercuei 0:03b5121a232e 15167 return NULL;
pcercuei 0:03b5121a232e 15168 xmlXPathEvalExpr(pctxt);
pcercuei 0:03b5121a232e 15169
pcercuei 0:03b5121a232e 15170 if ((*pctxt->cur != 0) || (pctxt->error != XPATH_EXPRESSION_OK)) {
pcercuei 0:03b5121a232e 15171 xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
pcercuei 0:03b5121a232e 15172 res = NULL;
pcercuei 0:03b5121a232e 15173 } else {
pcercuei 0:03b5121a232e 15174 res = valuePop(pctxt);
pcercuei 0:03b5121a232e 15175 }
pcercuei 0:03b5121a232e 15176 do {
pcercuei 0:03b5121a232e 15177 tmp = valuePop(pctxt);
pcercuei 0:03b5121a232e 15178 if (tmp != NULL) {
pcercuei 0:03b5121a232e 15179 xmlXPathReleaseObject(ctxt, tmp);
pcercuei 0:03b5121a232e 15180 stack++;
pcercuei 0:03b5121a232e 15181 }
pcercuei 0:03b5121a232e 15182 } while (tmp != NULL);
pcercuei 0:03b5121a232e 15183 if ((stack != 0) && (res != NULL)) {
pcercuei 0:03b5121a232e 15184 xmlGenericError(xmlGenericErrorContext,
pcercuei 0:03b5121a232e 15185 "xmlXPathEvalExpression: %d object left on the stack\n",
pcercuei 0:03b5121a232e 15186 stack);
pcercuei 0:03b5121a232e 15187 }
pcercuei 0:03b5121a232e 15188 xmlXPathFreeParserContext(pctxt);
pcercuei 0:03b5121a232e 15189 return(res);
pcercuei 0:03b5121a232e 15190 }
pcercuei 0:03b5121a232e 15191
pcercuei 0:03b5121a232e 15192 /************************************************************************
pcercuei 0:03b5121a232e 15193 * *
pcercuei 0:03b5121a232e 15194 * Extra functions not pertaining to the XPath spec *
pcercuei 0:03b5121a232e 15195 * *
pcercuei 0:03b5121a232e 15196 ************************************************************************/
pcercuei 0:03b5121a232e 15197 /**
pcercuei 0:03b5121a232e 15198 * xmlXPathEscapeUriFunction:
pcercuei 0:03b5121a232e 15199 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 15200 * @nargs: the number of arguments
pcercuei 0:03b5121a232e 15201 *
pcercuei 0:03b5121a232e 15202 * Implement the escape-uri() XPath function
pcercuei 0:03b5121a232e 15203 * string escape-uri(string $str, bool $escape-reserved)
pcercuei 0:03b5121a232e 15204 *
pcercuei 0:03b5121a232e 15205 * This function applies the URI escaping rules defined in section 2 of [RFC
pcercuei 0:03b5121a232e 15206 * 2396] to the string supplied as $uri-part, which typically represents all
pcercuei 0:03b5121a232e 15207 * or part of a URI. The effect of the function is to replace any special
pcercuei 0:03b5121a232e 15208 * character in the string by an escape sequence of the form %xx%yy...,
pcercuei 0:03b5121a232e 15209 * where xxyy... is the hexadecimal representation of the octets used to
pcercuei 0:03b5121a232e 15210 * represent the character in UTF-8.
pcercuei 0:03b5121a232e 15211 *
pcercuei 0:03b5121a232e 15212 * The set of characters that are escaped depends on the setting of the
pcercuei 0:03b5121a232e 15213 * boolean argument $escape-reserved.
pcercuei 0:03b5121a232e 15214 *
pcercuei 0:03b5121a232e 15215 * If $escape-reserved is true, all characters are escaped other than lower
pcercuei 0:03b5121a232e 15216 * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
pcercuei 0:03b5121a232e 15217 * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
pcercuei 0:03b5121a232e 15218 * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
pcercuei 0:03b5121a232e 15219 * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
pcercuei 0:03b5121a232e 15220 * A-F).
pcercuei 0:03b5121a232e 15221 *
pcercuei 0:03b5121a232e 15222 * If $escape-reserved is false, the behavior differs in that characters
pcercuei 0:03b5121a232e 15223 * referred to in [RFC 2396] as reserved characters are not escaped. These
pcercuei 0:03b5121a232e 15224 * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
pcercuei 0:03b5121a232e 15225 *
pcercuei 0:03b5121a232e 15226 * [RFC 2396] does not define whether escaped URIs should use lower case or
pcercuei 0:03b5121a232e 15227 * upper case for hexadecimal digits. To ensure that escaped URIs can be
pcercuei 0:03b5121a232e 15228 * compared using string comparison functions, this function must always use
pcercuei 0:03b5121a232e 15229 * the upper-case letters A-F.
pcercuei 0:03b5121a232e 15230 *
pcercuei 0:03b5121a232e 15231 * Generally, $escape-reserved should be set to true when escaping a string
pcercuei 0:03b5121a232e 15232 * that is to form a single part of a URI, and to false when escaping an
pcercuei 0:03b5121a232e 15233 * entire URI or URI reference.
pcercuei 0:03b5121a232e 15234 *
pcercuei 0:03b5121a232e 15235 * In the case of non-ascii characters, the string is encoded according to
pcercuei 0:03b5121a232e 15236 * utf-8 and then converted according to RFC 2396.
pcercuei 0:03b5121a232e 15237 *
pcercuei 0:03b5121a232e 15238 * Examples
pcercuei 0:03b5121a232e 15239 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
pcercuei 0:03b5121a232e 15240 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
pcercuei 0:03b5121a232e 15241 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
pcercuei 0:03b5121a232e 15242 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
pcercuei 0:03b5121a232e 15243 *
pcercuei 0:03b5121a232e 15244 */
pcercuei 0:03b5121a232e 15245 static void
pcercuei 0:03b5121a232e 15246 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
pcercuei 0:03b5121a232e 15247 xmlXPathObjectPtr str;
pcercuei 0:03b5121a232e 15248 int escape_reserved;
pcercuei 0:03b5121a232e 15249 xmlBufPtr target;
pcercuei 0:03b5121a232e 15250 xmlChar *cptr;
pcercuei 0:03b5121a232e 15251 xmlChar escape[4];
pcercuei 0:03b5121a232e 15252
pcercuei 0:03b5121a232e 15253 CHECK_ARITY(2);
pcercuei 0:03b5121a232e 15254
pcercuei 0:03b5121a232e 15255 escape_reserved = xmlXPathPopBoolean(ctxt);
pcercuei 0:03b5121a232e 15256
pcercuei 0:03b5121a232e 15257 CAST_TO_STRING;
pcercuei 0:03b5121a232e 15258 str = valuePop(ctxt);
pcercuei 0:03b5121a232e 15259
pcercuei 0:03b5121a232e 15260 target = xmlBufCreate();
pcercuei 0:03b5121a232e 15261
pcercuei 0:03b5121a232e 15262 escape[0] = '%';
pcercuei 0:03b5121a232e 15263 escape[3] = 0;
pcercuei 0:03b5121a232e 15264
pcercuei 0:03b5121a232e 15265 if (target) {
pcercuei 0:03b5121a232e 15266 for (cptr = str->stringval; *cptr; cptr++) {
pcercuei 0:03b5121a232e 15267 if ((*cptr >= 'A' && *cptr <= 'Z') ||
pcercuei 0:03b5121a232e 15268 (*cptr >= 'a' && *cptr <= 'z') ||
pcercuei 0:03b5121a232e 15269 (*cptr >= '0' && *cptr <= '9') ||
pcercuei 0:03b5121a232e 15270 *cptr == '-' || *cptr == '_' || *cptr == '.' ||
pcercuei 0:03b5121a232e 15271 *cptr == '!' || *cptr == '~' || *cptr == '*' ||
pcercuei 0:03b5121a232e 15272 *cptr == '\''|| *cptr == '(' || *cptr == ')' ||
pcercuei 0:03b5121a232e 15273 (*cptr == '%' &&
pcercuei 0:03b5121a232e 15274 ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
pcercuei 0:03b5121a232e 15275 (cptr[1] >= 'a' && cptr[1] <= 'f') ||
pcercuei 0:03b5121a232e 15276 (cptr[1] >= '0' && cptr[1] <= '9')) &&
pcercuei 0:03b5121a232e 15277 ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
pcercuei 0:03b5121a232e 15278 (cptr[2] >= 'a' && cptr[2] <= 'f') ||
pcercuei 0:03b5121a232e 15279 (cptr[2] >= '0' && cptr[2] <= '9'))) ||
pcercuei 0:03b5121a232e 15280 (!escape_reserved &&
pcercuei 0:03b5121a232e 15281 (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
pcercuei 0:03b5121a232e 15282 *cptr == ':' || *cptr == '@' || *cptr == '&' ||
pcercuei 0:03b5121a232e 15283 *cptr == '=' || *cptr == '+' || *cptr == '$' ||
pcercuei 0:03b5121a232e 15284 *cptr == ','))) {
pcercuei 0:03b5121a232e 15285 xmlBufAdd(target, cptr, 1);
pcercuei 0:03b5121a232e 15286 } else {
pcercuei 0:03b5121a232e 15287 if ((*cptr >> 4) < 10)
pcercuei 0:03b5121a232e 15288 escape[1] = '0' + (*cptr >> 4);
pcercuei 0:03b5121a232e 15289 else
pcercuei 0:03b5121a232e 15290 escape[1] = 'A' - 10 + (*cptr >> 4);
pcercuei 0:03b5121a232e 15291 if ((*cptr & 0xF) < 10)
pcercuei 0:03b5121a232e 15292 escape[2] = '0' + (*cptr & 0xF);
pcercuei 0:03b5121a232e 15293 else
pcercuei 0:03b5121a232e 15294 escape[2] = 'A' - 10 + (*cptr & 0xF);
pcercuei 0:03b5121a232e 15295
pcercuei 0:03b5121a232e 15296 xmlBufAdd(target, &escape[0], 3);
pcercuei 0:03b5121a232e 15297 }
pcercuei 0:03b5121a232e 15298 }
pcercuei 0:03b5121a232e 15299 }
pcercuei 0:03b5121a232e 15300 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
pcercuei 0:03b5121a232e 15301 xmlBufContent(target)));
pcercuei 0:03b5121a232e 15302 xmlBufFree(target);
pcercuei 0:03b5121a232e 15303 xmlXPathReleaseObject(ctxt->context, str);
pcercuei 0:03b5121a232e 15304 }
pcercuei 0:03b5121a232e 15305
pcercuei 0:03b5121a232e 15306 /**
pcercuei 0:03b5121a232e 15307 * xmlXPathRegisterAllFunctions:
pcercuei 0:03b5121a232e 15308 * @ctxt: the XPath context
pcercuei 0:03b5121a232e 15309 *
pcercuei 0:03b5121a232e 15310 * Registers all default XPath functions in this context
pcercuei 0:03b5121a232e 15311 */
pcercuei 0:03b5121a232e 15312 void
pcercuei 0:03b5121a232e 15313 xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
pcercuei 0:03b5121a232e 15314 {
pcercuei 0:03b5121a232e 15315 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
pcercuei 0:03b5121a232e 15316 xmlXPathBooleanFunction);
pcercuei 0:03b5121a232e 15317 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
pcercuei 0:03b5121a232e 15318 xmlXPathCeilingFunction);
pcercuei 0:03b5121a232e 15319 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
pcercuei 0:03b5121a232e 15320 xmlXPathCountFunction);
pcercuei 0:03b5121a232e 15321 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
pcercuei 0:03b5121a232e 15322 xmlXPathConcatFunction);
pcercuei 0:03b5121a232e 15323 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
pcercuei 0:03b5121a232e 15324 xmlXPathContainsFunction);
pcercuei 0:03b5121a232e 15325 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
pcercuei 0:03b5121a232e 15326 xmlXPathIdFunction);
pcercuei 0:03b5121a232e 15327 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
pcercuei 0:03b5121a232e 15328 xmlXPathFalseFunction);
pcercuei 0:03b5121a232e 15329 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
pcercuei 0:03b5121a232e 15330 xmlXPathFloorFunction);
pcercuei 0:03b5121a232e 15331 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
pcercuei 0:03b5121a232e 15332 xmlXPathLastFunction);
pcercuei 0:03b5121a232e 15333 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
pcercuei 0:03b5121a232e 15334 xmlXPathLangFunction);
pcercuei 0:03b5121a232e 15335 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
pcercuei 0:03b5121a232e 15336 xmlXPathLocalNameFunction);
pcercuei 0:03b5121a232e 15337 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
pcercuei 0:03b5121a232e 15338 xmlXPathNotFunction);
pcercuei 0:03b5121a232e 15339 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
pcercuei 0:03b5121a232e 15340 xmlXPathNameFunction);
pcercuei 0:03b5121a232e 15341 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
pcercuei 0:03b5121a232e 15342 xmlXPathNamespaceURIFunction);
pcercuei 0:03b5121a232e 15343 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
pcercuei 0:03b5121a232e 15344 xmlXPathNormalizeFunction);
pcercuei 0:03b5121a232e 15345 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
pcercuei 0:03b5121a232e 15346 xmlXPathNumberFunction);
pcercuei 0:03b5121a232e 15347 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
pcercuei 0:03b5121a232e 15348 xmlXPathPositionFunction);
pcercuei 0:03b5121a232e 15349 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
pcercuei 0:03b5121a232e 15350 xmlXPathRoundFunction);
pcercuei 0:03b5121a232e 15351 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
pcercuei 0:03b5121a232e 15352 xmlXPathStringFunction);
pcercuei 0:03b5121a232e 15353 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
pcercuei 0:03b5121a232e 15354 xmlXPathStringLengthFunction);
pcercuei 0:03b5121a232e 15355 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
pcercuei 0:03b5121a232e 15356 xmlXPathStartsWithFunction);
pcercuei 0:03b5121a232e 15357 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
pcercuei 0:03b5121a232e 15358 xmlXPathSubstringFunction);
pcercuei 0:03b5121a232e 15359 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
pcercuei 0:03b5121a232e 15360 xmlXPathSubstringBeforeFunction);
pcercuei 0:03b5121a232e 15361 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
pcercuei 0:03b5121a232e 15362 xmlXPathSubstringAfterFunction);
pcercuei 0:03b5121a232e 15363 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
pcercuei 0:03b5121a232e 15364 xmlXPathSumFunction);
pcercuei 0:03b5121a232e 15365 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
pcercuei 0:03b5121a232e 15366 xmlXPathTrueFunction);
pcercuei 0:03b5121a232e 15367 xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
pcercuei 0:03b5121a232e 15368 xmlXPathTranslateFunction);
pcercuei 0:03b5121a232e 15369
pcercuei 0:03b5121a232e 15370 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
pcercuei 0:03b5121a232e 15371 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
pcercuei 0:03b5121a232e 15372 xmlXPathEscapeUriFunction);
pcercuei 0:03b5121a232e 15373 }
pcercuei 0:03b5121a232e 15374
pcercuei 0:03b5121a232e 15375 #endif /* LIBXML_XPATH_ENABLED */
pcercuei 0:03b5121a232e 15376 #define bottom_xpath
pcercuei 0:03b5121a232e 15377 #include "elfgcchack.h"
pcercuei 0:03b5121a232e 15378