| OLD | NEW |
| 1 /* | 1 /* |
| 2 * xpath.c: XML Path Language implementation | 2 * xpath.c: XML Path Language implementation |
| 3 * XPath is a language for addressing parts of an XML document, | 3 * XPath is a language for addressing parts of an XML document, |
| 4 * designed to be used by both XSLT and XPointer | 4 * designed to be used by both XSLT and XPointer |
| 5 *f | 5 *f |
| 6 * Reference: W3C Recommendation 16 November 1999 | 6 * Reference: W3C Recommendation 16 November 1999 |
| 7 * http://www.w3.org/TR/1999/REC-xpath-19991116 | 7 * http://www.w3.org/TR/1999/REC-xpath-19991116 |
| 8 * Public reference: | 8 * Public reference: |
| 9 * http://www.w3.org/TR/xpath | 9 * http://www.w3.org/TR/xpath |
| 10 * | 10 * |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #ifdef LIBXML_DEBUG_ENABLED | 48 #ifdef LIBXML_DEBUG_ENABLED |
| 49 #include <libxml/debugXML.h> | 49 #include <libxml/debugXML.h> |
| 50 #endif | 50 #endif |
| 51 #include <libxml/xmlerror.h> | 51 #include <libxml/xmlerror.h> |
| 52 #include <libxml/threads.h> | 52 #include <libxml/threads.h> |
| 53 #include <libxml/globals.h> | 53 #include <libxml/globals.h> |
| 54 #ifdef LIBXML_PATTERN_ENABLED | 54 #ifdef LIBXML_PATTERN_ENABLED |
| 55 #include <libxml/pattern.h> | 55 #include <libxml/pattern.h> |
| 56 #endif | 56 #endif |
| 57 | 57 |
| 58 #include "buf.h" |
| 59 |
| 58 #ifdef LIBXML_PATTERN_ENABLED | 60 #ifdef LIBXML_PATTERN_ENABLED |
| 59 #define XPATH_STREAMING | 61 #define XPATH_STREAMING |
| 60 #endif | 62 #endif |
| 61 | 63 |
| 62 #define TODO \ | 64 #define TODO \ |
| 63 xmlGenericError(xmlGenericErrorContext, \ | 65 xmlGenericError(xmlGenericErrorContext, \ |
| 64 "Unimplemented block at %s:%d\n", \ | 66 "Unimplemented block at %s:%d\n", \ |
| 65 __FILE__, __LINE__); | 67 __FILE__, __LINE__); |
| 66 | 68 |
| 69 /** |
| 70 * WITH_TIM_SORT: |
| 71 * |
| 72 * Use the Timsort algorithm provided in timsort.h to sort |
| 73 * nodeset as this is a great improvement over the old Shell sort |
| 74 * used in xmlXPathNodeSetSort() |
| 75 */ |
| 76 #define WITH_TIM_SORT |
| 77 |
| 67 /* | 78 /* |
| 68 * XP_OPTIMIZED_NON_ELEM_COMPARISON: | 79 * XP_OPTIMIZED_NON_ELEM_COMPARISON: |
| 69 * If defined, this will use xmlXPathCmpNodesExt() instead of | 80 * If defined, this will use xmlXPathCmpNodesExt() instead of |
| 70 * xmlXPathCmpNodes(). The new function is optimized comparison of | 81 * xmlXPathCmpNodes(). The new function is optimized comparison of |
| 71 * non-element nodes; actually it will speed up comparison only if | 82 * non-element nodes; actually it will speed up comparison only if |
| 72 * xmlXPathOrderDocElems() was called in order to index the elements of | 83 * xmlXPathOrderDocElems() was called in order to index the elements of |
| 73 * a tree in document order; Libxslt does such an indexing, thus it will | 84 * a tree in document order; Libxslt does such an indexing, thus it will |
| 74 * benefit from this optimization. | 85 * benefit from this optimization. |
| 75 */ | 86 */ |
| 76 #define XP_OPTIMIZED_NON_ELEM_COMPARISON | 87 #define XP_OPTIMIZED_NON_ELEM_COMPARISON |
| 77 | 88 |
| 78 /* | 89 /* |
| 79 * XP_OPTIMIZED_FILTER_FIRST: | 90 * XP_OPTIMIZED_FILTER_FIRST: |
| 80 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]" | 91 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]" |
| 81 * in a way, that it stop evaluation at the first node. | 92 * in a way, that it stop evaluation at the first node. |
| 82 */ | 93 */ |
| 83 #define XP_OPTIMIZED_FILTER_FIRST | 94 #define XP_OPTIMIZED_FILTER_FIRST |
| 84 | 95 |
| 85 /* | 96 /* |
| 86 * XP_DEBUG_OBJ_USAGE: | 97 * XP_DEBUG_OBJ_USAGE: |
| 87 * Internal flag to enable tracking of how much XPath objects have been | 98 * Internal flag to enable tracking of how much XPath objects have been |
| 88 * created. | 99 * created. |
| 89 */ | 100 */ |
| 90 /* #define XP_DEBUG_OBJ_USAGE */ | 101 /* #define XP_DEBUG_OBJ_USAGE */ |
| 91 | 102 |
| 92 /* | 103 /* |
| 104 * XPATH_MAX_STEPS: |
| 105 * when compiling an XPath expression we arbitrary limit the maximum |
| 106 * number of step operation in the compiled expression. 1000000 is |
| 107 * an insanely large value which should never be reached under normal |
| 108 * circumstances |
| 109 */ |
| 110 #define XPATH_MAX_STEPS 1000000 |
| 111 |
| 112 /* |
| 113 * XPATH_MAX_STACK_DEPTH: |
| 114 * when evaluating an XPath expression we arbitrary limit the maximum |
| 115 * number of object allowed to be pushed on the stack. 1000000 is |
| 116 * an insanely large value which should never be reached under normal |
| 117 * circumstances |
| 118 */ |
| 119 #define XPATH_MAX_STACK_DEPTH 1000000 |
| 120 |
| 121 /* |
| 122 * XPATH_MAX_NODESET_LENGTH: |
| 123 * when evaluating an XPath expression nodesets are created and we |
| 124 * arbitrary limit the maximum length of those node set. 10000000 is |
| 125 * an insanely large value which should never be reached under normal |
| 126 * circumstances, one would first need to construct an in memory tree |
| 127 * with more than 10 millions nodes. |
| 128 */ |
| 129 #define XPATH_MAX_NODESET_LENGTH 10000000 |
| 130 |
| 131 /* |
| 93 * TODO: | 132 * TODO: |
| 94 * There are a few spots where some tests are done which depend upon ascii | 133 * There are a few spots where some tests are done which depend upon ascii |
| 95 * data. These should be enhanced for full UTF8 support (see particularly | 134 * data. These should be enhanced for full UTF8 support (see particularly |
| 96 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT) | 135 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT) |
| 97 */ | 136 */ |
| 98 | 137 |
| 138 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON |
| 139 /** |
| 140 * xmlXPathCmpNodesExt: |
| 141 * @node1: the first node |
| 142 * @node2: the second node |
| 143 * |
| 144 * Compare two nodes w.r.t document order. |
| 145 * This one is optimized for handling of non-element nodes. |
| 146 * |
| 147 * Returns -2 in case of error 1 if first point < second point, 0 if |
| 148 * it's the same node, -1 otherwise |
| 149 */ |
| 150 static int |
| 151 xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) { |
| 152 int depth1, depth2; |
| 153 int misc = 0, precedence1 = 0, precedence2 = 0; |
| 154 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL; |
| 155 xmlNodePtr cur, root; |
| 156 long l1, l2; |
| 157 |
| 158 if ((node1 == NULL) || (node2 == NULL)) |
| 159 return(-2); |
| 160 |
| 161 if (node1 == node2) |
| 162 return(0); |
| 163 |
| 164 /* |
| 165 * a couple of optimizations which will avoid computations in most cases |
| 166 */ |
| 167 switch (node1->type) { |
| 168 case XML_ELEMENT_NODE: |
| 169 if (node2->type == XML_ELEMENT_NODE) { |
| 170 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice
here? */ |
| 171 (0 > (long) node2->content) && |
| 172 (node1->doc == node2->doc)) |
| 173 { |
| 174 l1 = -((long) node1->content); |
| 175 l2 = -((long) node2->content); |
| 176 if (l1 < l2) |
| 177 return(1); |
| 178 if (l1 > l2) |
| 179 return(-1); |
| 180 } else |
| 181 goto turtle_comparison; |
| 182 } |
| 183 break; |
| 184 case XML_ATTRIBUTE_NODE: |
| 185 precedence1 = 1; /* element is owner */ |
| 186 miscNode1 = node1; |
| 187 node1 = node1->parent; |
| 188 misc = 1; |
| 189 break; |
| 190 case XML_TEXT_NODE: |
| 191 case XML_CDATA_SECTION_NODE: |
| 192 case XML_COMMENT_NODE: |
| 193 case XML_PI_NODE: { |
| 194 miscNode1 = node1; |
| 195 /* |
| 196 * Find nearest element node. |
| 197 */ |
| 198 if (node1->prev != NULL) { |
| 199 do { |
| 200 node1 = node1->prev; |
| 201 if (node1->type == XML_ELEMENT_NODE) { |
| 202 precedence1 = 3; /* element in prev-sibl axis */ |
| 203 break; |
| 204 } |
| 205 if (node1->prev == NULL) { |
| 206 precedence1 = 2; /* element is parent */ |
| 207 /* |
| 208 * URGENT TODO: Are there any cases, where the |
| 209 * parent of such a node is not an element node? |
| 210 */ |
| 211 node1 = node1->parent; |
| 212 break; |
| 213 } |
| 214 } while (1); |
| 215 } else { |
| 216 precedence1 = 2; /* element is parent */ |
| 217 node1 = node1->parent; |
| 218 } |
| 219 if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) || |
| 220 (0 <= (long) node1->content)) { |
| 221 /* |
| 222 * Fallback for whatever case. |
| 223 */ |
| 224 node1 = miscNode1; |
| 225 precedence1 = 0; |
| 226 } else |
| 227 misc = 1; |
| 228 } |
| 229 break; |
| 230 case XML_NAMESPACE_DECL: |
| 231 /* |
| 232 * TODO: why do we return 1 for namespace nodes? |
| 233 */ |
| 234 return(1); |
| 235 default: |
| 236 break; |
| 237 } |
| 238 switch (node2->type) { |
| 239 case XML_ELEMENT_NODE: |
| 240 break; |
| 241 case XML_ATTRIBUTE_NODE: |
| 242 precedence2 = 1; /* element is owner */ |
| 243 miscNode2 = node2; |
| 244 node2 = node2->parent; |
| 245 misc = 1; |
| 246 break; |
| 247 case XML_TEXT_NODE: |
| 248 case XML_CDATA_SECTION_NODE: |
| 249 case XML_COMMENT_NODE: |
| 250 case XML_PI_NODE: { |
| 251 miscNode2 = node2; |
| 252 if (node2->prev != NULL) { |
| 253 do { |
| 254 node2 = node2->prev; |
| 255 if (node2->type == XML_ELEMENT_NODE) { |
| 256 precedence2 = 3; /* element in prev-sibl axis */ |
| 257 break; |
| 258 } |
| 259 if (node2->prev == NULL) { |
| 260 precedence2 = 2; /* element is parent */ |
| 261 node2 = node2->parent; |
| 262 break; |
| 263 } |
| 264 } while (1); |
| 265 } else { |
| 266 precedence2 = 2; /* element is parent */ |
| 267 node2 = node2->parent; |
| 268 } |
| 269 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) || |
| 270 (0 <= (long) node2->content)) |
| 271 { |
| 272 node2 = miscNode2; |
| 273 precedence2 = 0; |
| 274 } else |
| 275 misc = 1; |
| 276 } |
| 277 break; |
| 278 case XML_NAMESPACE_DECL: |
| 279 return(1); |
| 280 default: |
| 281 break; |
| 282 } |
| 283 if (misc) { |
| 284 if (node1 == node2) { |
| 285 if (precedence1 == precedence2) { |
| 286 /* |
| 287 * The ugly case; but normally there aren't many |
| 288 * adjacent non-element nodes around. |
| 289 */ |
| 290 cur = miscNode2->prev; |
| 291 while (cur != NULL) { |
| 292 if (cur == miscNode1) |
| 293 return(1); |
| 294 if (cur->type == XML_ELEMENT_NODE) |
| 295 return(-1); |
| 296 cur = cur->prev; |
| 297 } |
| 298 return (-1); |
| 299 } else { |
| 300 /* |
| 301 * Evaluate based on higher precedence wrt to the element. |
| 302 * TODO: This assumes attributes are sorted before content. |
| 303 * Is this 100% correct? |
| 304 */ |
| 305 if (precedence1 < precedence2) |
| 306 return(1); |
| 307 else |
| 308 return(-1); |
| 309 } |
| 310 } |
| 311 /* |
| 312 * Special case: One of the helper-elements is contained by the other. |
| 313 * <foo> |
| 314 * <node2> |
| 315 * <node1>Text-1(precedence1 == 2)</node1> |
| 316 * </node2> |
| 317 * Text-6(precedence2 == 3) |
| 318 * </foo> |
| 319 */ |
| 320 if ((precedence2 == 3) && (precedence1 > 1)) { |
| 321 cur = node1->parent; |
| 322 while (cur) { |
| 323 if (cur == node2) |
| 324 return(1); |
| 325 cur = cur->parent; |
| 326 } |
| 327 } |
| 328 if ((precedence1 == 3) && (precedence2 > 1)) { |
| 329 cur = node2->parent; |
| 330 while (cur) { |
| 331 if (cur == node1) |
| 332 return(-1); |
| 333 cur = cur->parent; |
| 334 } |
| 335 } |
| 336 } |
| 337 |
| 338 /* |
| 339 * Speedup using document order if availble. |
| 340 */ |
| 341 if ((node1->type == XML_ELEMENT_NODE) && |
| 342 (node2->type == XML_ELEMENT_NODE) && |
| 343 (0 > (long) node1->content) && |
| 344 (0 > (long) node2->content) && |
| 345 (node1->doc == node2->doc)) { |
| 346 |
| 347 l1 = -((long) node1->content); |
| 348 l2 = -((long) node2->content); |
| 349 if (l1 < l2) |
| 350 return(1); |
| 351 if (l1 > l2) |
| 352 return(-1); |
| 353 } |
| 354 |
| 355 turtle_comparison: |
| 356 |
| 357 if (node1 == node2->prev) |
| 358 return(1); |
| 359 if (node1 == node2->next) |
| 360 return(-1); |
| 361 /* |
| 362 * compute depth to root |
| 363 */ |
| 364 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { |
| 365 if (cur == node1) |
| 366 return(1); |
| 367 depth2++; |
| 368 } |
| 369 root = cur; |
| 370 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { |
| 371 if (cur == node2) |
| 372 return(-1); |
| 373 depth1++; |
| 374 } |
| 375 /* |
| 376 * Distinct document (or distinct entities :-( ) case. |
| 377 */ |
| 378 if (root != cur) { |
| 379 return(-2); |
| 380 } |
| 381 /* |
| 382 * get the nearest common ancestor. |
| 383 */ |
| 384 while (depth1 > depth2) { |
| 385 depth1--; |
| 386 node1 = node1->parent; |
| 387 } |
| 388 while (depth2 > depth1) { |
| 389 depth2--; |
| 390 node2 = node2->parent; |
| 391 } |
| 392 while (node1->parent != node2->parent) { |
| 393 node1 = node1->parent; |
| 394 node2 = node2->parent; |
| 395 /* should not happen but just in case ... */ |
| 396 if ((node1 == NULL) || (node2 == NULL)) |
| 397 return(-2); |
| 398 } |
| 399 /* |
| 400 * Find who's first. |
| 401 */ |
| 402 if (node1 == node2->prev) |
| 403 return(1); |
| 404 if (node1 == node2->next) |
| 405 return(-1); |
| 406 /* |
| 407 * Speedup using document order if availble. |
| 408 */ |
| 409 if ((node1->type == XML_ELEMENT_NODE) && |
| 410 (node2->type == XML_ELEMENT_NODE) && |
| 411 (0 > (long) node1->content) && |
| 412 (0 > (long) node2->content) && |
| 413 (node1->doc == node2->doc)) { |
| 414 |
| 415 l1 = -((long) node1->content); |
| 416 l2 = -((long) node2->content); |
| 417 if (l1 < l2) |
| 418 return(1); |
| 419 if (l1 > l2) |
| 420 return(-1); |
| 421 } |
| 422 |
| 423 for (cur = node1->next;cur != NULL;cur = cur->next) |
| 424 if (cur == node2) |
| 425 return(1); |
| 426 return(-1); /* assume there is no sibling list corruption */ |
| 427 } |
| 428 #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */ |
| 429 |
| 430 /* |
| 431 * Wrapper for the Timsort argorithm from timsort.h |
| 432 */ |
| 433 #ifdef WITH_TIM_SORT |
| 434 #define SORT_NAME libxml_domnode |
| 435 #define SORT_TYPE xmlNodePtr |
| 436 /** |
| 437 * wrap_cmp: |
| 438 * @x: a node |
| 439 * @y: another node |
| 440 * |
| 441 * Comparison function for the Timsort implementation |
| 442 * |
| 443 * Returns -2 in case of error -1 if first point < second point, 0 if |
| 444 * it's the same node, +1 otherwise |
| 445 */ |
| 446 static |
| 447 int wrap_cmp( xmlNodePtr x, xmlNodePtr y ); |
| 448 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON |
| 449 static int wrap_cmp( xmlNodePtr x, xmlNodePtr y ) |
| 450 { |
| 451 int res = xmlXPathCmpNodesExt(x, y); |
| 452 return res == -2 ? res : -res; |
| 453 } |
| 454 #else |
| 455 static int wrap_cmp( xmlNodePtr x, xmlNodePtr y ) |
| 456 { |
| 457 int res = xmlXPathCmpNodes(x, y); |
| 458 return res == -2 ? res : -res; |
| 459 } |
| 460 #endif |
| 461 #define SORT_CMP(x, y) (wrap_cmp(x, y)) |
| 462 #include "timsort.h" |
| 463 #endif /* WITH_TIM_SORT */ |
| 464 |
| 99 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) | 465 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) |
| 100 | 466 |
| 101 /************************************************************************ | 467 /************************************************************************ |
| 102 * * | 468 * * |
| 103 * Floating point stuff * | 469 * Floating point stuff * |
| 104 * * | 470 * * |
| 105 ************************************************************************/ | 471 ************************************************************************/ |
| 106 | 472 |
| 107 #ifndef TRIO_REPLACE_STDIO | 473 #ifndef TRIO_REPLACE_STDIO |
| 108 #define TRIO_PUBLIC static | 474 #define TRIO_PUBLIC static |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 "Invalid context size\n", | 611 "Invalid context size\n", |
| 246 "Invalid context position\n", | 612 "Invalid context position\n", |
| 247 "Memory allocation error\n", | 613 "Memory allocation error\n", |
| 248 "Syntax error\n", | 614 "Syntax error\n", |
| 249 "Resource error\n", | 615 "Resource error\n", |
| 250 "Sub resource error\n", | 616 "Sub resource error\n", |
| 251 "Undefined namespace prefix\n", | 617 "Undefined namespace prefix\n", |
| 252 "Encoding error\n", | 618 "Encoding error\n", |
| 253 "Char out of XML range\n", | 619 "Char out of XML range\n", |
| 254 "Invalid or incomplete context\n", | 620 "Invalid or incomplete context\n", |
| 621 "Stack usage error\n", |
| 622 "Forbidden variable\n", |
| 255 "?? Unknown error ??\n" /* Must be last in the list! */ | 623 "?? Unknown error ??\n" /* Must be last in the list! */ |
| 256 }; | 624 }; |
| 257 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \ | 625 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \ |
| 258 sizeof(xmlXPathErrorMessages[0])) - 1) | 626 sizeof(xmlXPathErrorMessages[0])) - 1) |
| 259 /** | 627 /** |
| 260 * xmlXPathErrMemory: | 628 * xmlXPathErrMemory: |
| 261 * @ctxt: an XPath context | 629 * @ctxt: an XPath context |
| 262 * @extra: extra informations | 630 * @extra: extra informations |
| 263 * | 631 * |
| 264 * Handle a redefinition of attribute error | 632 * Handle a redefinition of attribute error |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 * and here, we should make the functions public. | 780 * and here, we should make the functions public. |
| 413 */ | 781 */ |
| 414 static int | 782 static int |
| 415 xmlPointerListAddSize(xmlPointerListPtr list, | 783 xmlPointerListAddSize(xmlPointerListPtr list, |
| 416 void *item, | 784 void *item, |
| 417 int initialSize) | 785 int initialSize) |
| 418 { | 786 { |
| 419 if (list->items == NULL) { | 787 if (list->items == NULL) { |
| 420 if (initialSize <= 0) | 788 if (initialSize <= 0) |
| 421 initialSize = 1; | 789 initialSize = 1; |
| 422 » list->items = (void **) xmlMalloc( | 790 » list->items = (void **) xmlMalloc(initialSize * sizeof(void *)); |
| 423 » initialSize * sizeof(void *)); | |
| 424 if (list->items == NULL) { | 791 if (list->items == NULL) { |
| 425 xmlXPathErrMemory(NULL, | 792 xmlXPathErrMemory(NULL, |
| 426 "xmlPointerListCreate: allocating item\n"); | 793 "xmlPointerListCreate: allocating item\n"); |
| 427 return(-1); | 794 return(-1); |
| 428 } | 795 } |
| 429 list->number = 0; | 796 list->number = 0; |
| 430 list->size = initialSize; | 797 list->size = initialSize; |
| 431 } else if (list->size <= list->number) { | 798 } else if (list->size <= list->number) { |
| 799 if (list->size > 50000000) { |
| 800 xmlXPathErrMemory(NULL, |
| 801 "xmlPointerListAddSize: re-allocating item\n"); |
| 802 return(-1); |
| 803 } |
| 432 list->size *= 2; | 804 list->size *= 2; |
| 433 list->items = (void **) xmlRealloc(list->items, | 805 list->items = (void **) xmlRealloc(list->items, |
| 434 list->size * sizeof(void *)); | 806 list->size * sizeof(void *)); |
| 435 if (list->items == NULL) { | 807 if (list->items == NULL) { |
| 436 xmlXPathErrMemory(NULL, | 808 xmlXPathErrMemory(NULL, |
| 437 » » "xmlPointerListCreate: re-allocating item\n"); | 809 » » "xmlPointerListAddSize: re-allocating item\n"); |
| 438 list->size = 0; | 810 list->size = 0; |
| 439 return(-1); | 811 return(-1); |
| 440 } | 812 } |
| 441 } | 813 } |
| 442 list->items[list->number++] = item; | 814 list->items[list->number++] = item; |
| 443 return(0); | 815 return(0); |
| 444 } | 816 } |
| 445 | 817 |
| 446 /** | 818 /** |
| 447 * xsltPointerListCreate: | 819 * xsltPointerListCreate: |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 NODE_TEST_NAME = 5 | 917 NODE_TEST_NAME = 5 |
| 546 } xmlXPathTestVal; | 918 } xmlXPathTestVal; |
| 547 | 919 |
| 548 typedef enum { | 920 typedef enum { |
| 549 NODE_TYPE_NODE = 0, | 921 NODE_TYPE_NODE = 0, |
| 550 NODE_TYPE_COMMENT = XML_COMMENT_NODE, | 922 NODE_TYPE_COMMENT = XML_COMMENT_NODE, |
| 551 NODE_TYPE_TEXT = XML_TEXT_NODE, | 923 NODE_TYPE_TEXT = XML_TEXT_NODE, |
| 552 NODE_TYPE_PI = XML_PI_NODE | 924 NODE_TYPE_PI = XML_PI_NODE |
| 553 } xmlXPathTypeVal; | 925 } xmlXPathTypeVal; |
| 554 | 926 |
| 555 #define XP_REWRITE_DOS_CHILD_ELEM 1 | |
| 556 | |
| 557 typedef struct _xmlXPathStepOp xmlXPathStepOp; | 927 typedef struct _xmlXPathStepOp xmlXPathStepOp; |
| 558 typedef xmlXPathStepOp *xmlXPathStepOpPtr; | 928 typedef xmlXPathStepOp *xmlXPathStepOpPtr; |
| 559 struct _xmlXPathStepOp { | 929 struct _xmlXPathStepOp { |
| 560 xmlXPathOp op; /* The identifier of the operation */ | 930 xmlXPathOp op; /* The identifier of the operation */ |
| 561 int ch1; /* First child */ | 931 int ch1; /* First child */ |
| 562 int ch2; /* Second child */ | 932 int ch2; /* Second child */ |
| 563 int value; | 933 int value; |
| 564 int value2; | 934 int value2; |
| 565 int value3; | 935 int value3; |
| 566 void *value4; | 936 void *value4; |
| 567 void *value5; | 937 void *value5; |
| 568 void *cache; | 938 void *cache; |
| 569 void *cacheURI; | 939 void *cacheURI; |
| 570 int rewriteType; | |
| 571 }; | 940 }; |
| 572 | 941 |
| 573 struct _xmlXPathCompExpr { | 942 struct _xmlXPathCompExpr { |
| 574 int nbStep; /* Number of steps in this expression */ | 943 int nbStep; /* Number of steps in this expression */ |
| 575 int maxStep; /* Maximum number of steps allocated */ | 944 int maxStep; /* Maximum number of steps allocated */ |
| 576 xmlXPathStepOp *steps; /* ops for computation of this expression */ | 945 xmlXPathStepOp *steps; /* ops for computation of this expression */ |
| 577 int last; /* index of last step in expression */ | 946 int last; /* index of last step in expression */ |
| 578 xmlChar *expr; /* the expression being computed */ | 947 xmlChar *expr; /* the expression being computed */ |
| 579 xmlDictPtr dict; /* the dictionnary to use if any */ | 948 xmlDictPtr dict; /* the dictionnary to use if any */ |
| 580 #ifdef DEBUG_EVAL_COUNTS | 949 #ifdef DEBUG_EVAL_COUNTS |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 * | 1084 * |
| 716 * Returns -1 in case of failure, the index otherwise | 1085 * Returns -1 in case of failure, the index otherwise |
| 717 */ | 1086 */ |
| 718 static int | 1087 static int |
| 719 xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2, | 1088 xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2, |
| 720 xmlXPathOp op, int value, | 1089 xmlXPathOp op, int value, |
| 721 int value2, int value3, void *value4, void *value5) { | 1090 int value2, int value3, void *value4, void *value5) { |
| 722 if (comp->nbStep >= comp->maxStep) { | 1091 if (comp->nbStep >= comp->maxStep) { |
| 723 xmlXPathStepOp *real; | 1092 xmlXPathStepOp *real; |
| 724 | 1093 |
| 1094 if (comp->maxStep >= XPATH_MAX_STEPS) { |
| 1095 xmlXPathErrMemory(NULL, "adding step\n"); |
| 1096 return(-1); |
| 1097 } |
| 725 comp->maxStep *= 2; | 1098 comp->maxStep *= 2; |
| 726 real = (xmlXPathStepOp *) xmlRealloc(comp->steps, | 1099 real = (xmlXPathStepOp *) xmlRealloc(comp->steps, |
| 727 comp->maxStep * sizeof(xmlXPathStepOp)); | 1100 comp->maxStep * sizeof(xmlXPathStepOp)); |
| 728 if (real == NULL) { | 1101 if (real == NULL) { |
| 729 comp->maxStep /= 2; | 1102 comp->maxStep /= 2; |
| 730 xmlXPathErrMemory(NULL, "adding step\n"); | 1103 xmlXPathErrMemory(NULL, "adding step\n"); |
| 731 return(-1); | 1104 return(-1); |
| 732 } | 1105 } |
| 733 comp->steps = real; | 1106 comp->steps = real; |
| 734 } | 1107 } |
| 735 comp->last = comp->nbStep; | 1108 comp->last = comp->nbStep; |
| 736 comp->steps[comp->nbStep].rewriteType = 0; | |
| 737 comp->steps[comp->nbStep].ch1 = ch1; | 1109 comp->steps[comp->nbStep].ch1 = ch1; |
| 738 comp->steps[comp->nbStep].ch2 = ch2; | 1110 comp->steps[comp->nbStep].ch2 = ch2; |
| 739 comp->steps[comp->nbStep].op = op; | 1111 comp->steps[comp->nbStep].op = op; |
| 740 comp->steps[comp->nbStep].value = value; | 1112 comp->steps[comp->nbStep].value = value; |
| 741 comp->steps[comp->nbStep].value2 = value2; | 1113 comp->steps[comp->nbStep].value2 = value2; |
| 742 comp->steps[comp->nbStep].value3 = value3; | 1114 comp->steps[comp->nbStep].value3 = value3; |
| 743 if ((comp->dict != NULL) && | 1115 if ((comp->dict != NULL) && |
| 744 ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) || | 1116 ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) || |
| 745 (op == XPATH_OP_COLLECT))) { | 1117 (op == XPATH_OP_COLLECT))) { |
| 746 if (value4 != NULL) { | 1118 if (value4 != NULL) { |
| (...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2044 /* | 2416 /* |
| 2045 * Fallback to misc-cache. | 2417 * Fallback to misc-cache. |
| 2046 */ | 2418 */ |
| 2047 | 2419 |
| 2048 ret = (xmlXPathObjectPtr) | 2420 ret = (xmlXPathObjectPtr) |
| 2049 cache->miscObjs->items[--cache->miscObjs->number]; | 2421 cache->miscObjs->items[--cache->miscObjs->number]; |
| 2050 | 2422 |
| 2051 ret->type = XPATH_NODESET; | 2423 ret->type = XPATH_NODESET; |
| 2052 ret->boolval = 0; | 2424 ret->boolval = 0; |
| 2053 ret->nodesetval = xmlXPathNodeSetCreate(val); | 2425 ret->nodesetval = xmlXPathNodeSetCreate(val); |
| 2426 if (ret->nodesetval == NULL) { |
| 2427 ctxt->lastError.domain = XML_FROM_XPATH; |
| 2428 ctxt->lastError.code = XML_ERR_NO_MEMORY; |
| 2429 return(NULL); |
| 2430 } |
| 2054 #ifdef XP_DEBUG_OBJ_USAGE | 2431 #ifdef XP_DEBUG_OBJ_USAGE |
| 2055 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); | 2432 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); |
| 2056 #endif | 2433 #endif |
| 2057 return(ret); | 2434 return(ret); |
| 2058 } | 2435 } |
| 2059 } | 2436 } |
| 2060 return(xmlXPathNewNodeSet(val)); | 2437 return(xmlXPathNewNodeSet(val)); |
| 2061 } | 2438 } |
| 2062 | 2439 |
| 2063 /** | 2440 /** |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2391 return(ret); | 2768 return(ret); |
| 2392 } | 2769 } |
| 2393 | 2770 |
| 2394 /************************************************************************ | 2771 /************************************************************************ |
| 2395 * * | 2772 * * |
| 2396 * Parser stacks related functions and macros * | 2773 * Parser stacks related functions and macros * |
| 2397 * * | 2774 * * |
| 2398 ************************************************************************/ | 2775 ************************************************************************/ |
| 2399 | 2776 |
| 2400 /** | 2777 /** |
| 2778 * xmlXPathSetFrame: |
| 2779 * @ctxt: an XPath parser context |
| 2780 * |
| 2781 * Set the callee evaluation frame |
| 2782 * |
| 2783 * Returns the previous frame value to be restored once done |
| 2784 */ |
| 2785 static int |
| 2786 xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) { |
| 2787 int ret; |
| 2788 |
| 2789 if (ctxt == NULL) |
| 2790 return(0); |
| 2791 ret = ctxt->valueFrame; |
| 2792 ctxt->valueFrame = ctxt->valueNr; |
| 2793 return(ret); |
| 2794 } |
| 2795 |
| 2796 /** |
| 2797 * xmlXPathPopFrame: |
| 2798 * @ctxt: an XPath parser context |
| 2799 * @frame: the previous frame value |
| 2800 * |
| 2801 * Remove the callee evaluation frame |
| 2802 */ |
| 2803 static void |
| 2804 xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) { |
| 2805 if (ctxt == NULL) |
| 2806 return; |
| 2807 if (ctxt->valueNr < ctxt->valueFrame) { |
| 2808 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR); |
| 2809 } |
| 2810 ctxt->valueFrame = frame; |
| 2811 } |
| 2812 |
| 2813 /** |
| 2401 * valuePop: | 2814 * valuePop: |
| 2402 * @ctxt: an XPath evaluation context | 2815 * @ctxt: an XPath evaluation context |
| 2403 * | 2816 * |
| 2404 * Pops the top XPath object from the value stack | 2817 * Pops the top XPath object from the value stack |
| 2405 * | 2818 * |
| 2406 * Returns the XPath object just removed | 2819 * Returns the XPath object just removed |
| 2407 */ | 2820 */ |
| 2408 xmlXPathObjectPtr | 2821 xmlXPathObjectPtr |
| 2409 valuePop(xmlXPathParserContextPtr ctxt) | 2822 valuePop(xmlXPathParserContextPtr ctxt) |
| 2410 { | 2823 { |
| 2411 xmlXPathObjectPtr ret; | 2824 xmlXPathObjectPtr ret; |
| 2412 | 2825 |
| 2413 if ((ctxt == NULL) || (ctxt->valueNr <= 0)) | 2826 if ((ctxt == NULL) || (ctxt->valueNr <= 0)) |
| 2414 return (NULL); | 2827 return (NULL); |
| 2828 |
| 2829 if (ctxt->valueNr <= ctxt->valueFrame) { |
| 2830 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR); |
| 2831 return (NULL); |
| 2832 } |
| 2833 |
| 2415 ctxt->valueNr--; | 2834 ctxt->valueNr--; |
| 2416 if (ctxt->valueNr > 0) | 2835 if (ctxt->valueNr > 0) |
| 2417 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1]; | 2836 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1]; |
| 2418 else | 2837 else |
| 2419 ctxt->value = NULL; | 2838 ctxt->value = NULL; |
| 2420 ret = ctxt->valueTab[ctxt->valueNr]; | 2839 ret = ctxt->valueTab[ctxt->valueNr]; |
| 2421 ctxt->valueTab[ctxt->valueNr] = NULL; | 2840 ctxt->valueTab[ctxt->valueNr] = NULL; |
| 2422 return (ret); | 2841 return (ret); |
| 2423 } | 2842 } |
| 2424 /** | 2843 /** |
| 2425 * valuePush: | 2844 * valuePush: |
| 2426 * @ctxt: an XPath evaluation context | 2845 * @ctxt: an XPath evaluation context |
| 2427 * @value: the XPath object | 2846 * @value: the XPath object |
| 2428 * | 2847 * |
| 2429 * Pushes a new XPath object on top of the value stack | 2848 * Pushes a new XPath object on top of the value stack |
| 2430 * | 2849 * |
| 2431 * returns the number of items on the value stack | 2850 * returns the number of items on the value stack |
| 2432 */ | 2851 */ |
| 2433 int | 2852 int |
| 2434 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) | 2853 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) |
| 2435 { | 2854 { |
| 2436 if ((ctxt == NULL) || (value == NULL)) return(-1); | 2855 if ((ctxt == NULL) || (value == NULL)) return(-1); |
| 2437 if (ctxt->valueNr >= ctxt->valueMax) { | 2856 if (ctxt->valueNr >= ctxt->valueMax) { |
| 2438 xmlXPathObjectPtr *tmp; | 2857 xmlXPathObjectPtr *tmp; |
| 2439 | 2858 |
| 2859 if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) { |
| 2860 xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n"); |
| 2861 ctxt->error = XPATH_MEMORY_ERROR; |
| 2862 return (0); |
| 2863 } |
| 2440 tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab, | 2864 tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab, |
| 2441 2 * ctxt->valueMax * | 2865 2 * ctxt->valueMax * |
| 2442 sizeof(ctxt->valueTab[0])); | 2866 sizeof(ctxt->valueTab[0])); |
| 2443 if (tmp == NULL) { | 2867 if (tmp == NULL) { |
| 2444 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); | 2868 xmlXPathErrMemory(NULL, "pushing value\n"); |
| 2869 ctxt->error = XPATH_MEMORY_ERROR; |
| 2445 return (0); | 2870 return (0); |
| 2446 } | 2871 } |
| 2447 ctxt->valueMax *= 2; | 2872 ctxt->valueMax *= 2; |
| 2448 ctxt->valueTab = tmp; | 2873 ctxt->valueTab = tmp; |
| 2449 } | 2874 } |
| 2450 ctxt->valueTab[ctxt->valueNr] = value; | 2875 ctxt->valueTab[ctxt->valueNr] = value; |
| 2451 ctxt->value = value; | 2876 ctxt->value = value; |
| 2452 return (ctxt->valueNr++); | 2877 return (ctxt->valueNr++); |
| 2453 } | 2878 } |
| 2454 | 2879 |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2744 fraction_place = DBL_DIG - integer_place - 1; | 3169 fraction_place = DBL_DIG - integer_place - 1; |
| 2745 else | 3170 else |
| 2746 fraction_place = DBL_DIG - integer_place; | 3171 fraction_place = DBL_DIG - integer_place; |
| 2747 } else { | 3172 } else { |
| 2748 fraction_place = 1; | 3173 fraction_place = 1; |
| 2749 } | 3174 } |
| 2750 size = snprintf(work, sizeof(work), "%0.*f", | 3175 size = snprintf(work, sizeof(work), "%0.*f", |
| 2751 fraction_place, number); | 3176 fraction_place, number); |
| 2752 } | 3177 } |
| 2753 | 3178 |
| 3179 /* Remove leading spaces sometimes inserted by snprintf */ |
| 3180 while (work[0] == ' ') { |
| 3181 for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++); |
| 3182 size--; |
| 3183 } |
| 3184 |
| 2754 /* Remove fractional trailing zeroes */ | 3185 /* Remove fractional trailing zeroes */ |
| 2755 after_fraction = work + size; | 3186 after_fraction = work + size; |
| 2756 ptr = after_fraction; | 3187 ptr = after_fraction; |
| 2757 while (*(--ptr) == '0') | 3188 while (*(--ptr) == '0') |
| 2758 ; | 3189 ; |
| 2759 if (*ptr != '.') | 3190 if (*ptr != '.') |
| 2760 ptr++; | 3191 ptr++; |
| 2761 while ((*ptr++ = *after_fraction++) != 0); | 3192 while ((*ptr++ = *after_fraction++) != 0); |
| 2762 | 3193 |
| 2763 /* Finally copy result back to caller */ | 3194 /* Finally copy result back to caller */ |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2884 if ((node1->type == XML_NAMESPACE_DECL) || | 3315 if ((node1->type == XML_NAMESPACE_DECL) || |
| 2885 (node2->type == XML_NAMESPACE_DECL)) | 3316 (node2->type == XML_NAMESPACE_DECL)) |
| 2886 return(1); | 3317 return(1); |
| 2887 if (node1 == node2->prev) | 3318 if (node1 == node2->prev) |
| 2888 return(1); | 3319 return(1); |
| 2889 if (node1 == node2->next) | 3320 if (node1 == node2->next) |
| 2890 return(-1); | 3321 return(-1); |
| 2891 | 3322 |
| 2892 /* | 3323 /* |
| 2893 * Speedup using document order if availble. | 3324 * Speedup using document order if availble. |
| 2894 */ | |
| 2895 if ((node1->type == XML_ELEMENT_NODE) && | |
| 2896 (node2->type == XML_ELEMENT_NODE) && | |
| 2897 (0 > (long) node1->content) && | |
| 2898 (0 > (long) node2->content) && | |
| 2899 (node1->doc == node2->doc)) { | |
| 2900 long l1, l2; | |
| 2901 | |
| 2902 l1 = -((long) node1->content); | |
| 2903 l2 = -((long) node2->content); | |
| 2904 if (l1 < l2) | |
| 2905 return(1); | |
| 2906 if (l1 > l2) | |
| 2907 return(-1); | |
| 2908 } | |
| 2909 | |
| 2910 /* | |
| 2911 * compute depth to root | |
| 2912 */ | |
| 2913 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { | |
| 2914 if (cur == node1) | |
| 2915 return(1); | |
| 2916 depth2++; | |
| 2917 } | |
| 2918 root = cur; | |
| 2919 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { | |
| 2920 if (cur == node2) | |
| 2921 return(-1); | |
| 2922 depth1++; | |
| 2923 } | |
| 2924 /* | |
| 2925 * Distinct document (or distinct entities :-( ) case. | |
| 2926 */ | |
| 2927 if (root != cur) { | |
| 2928 return(-2); | |
| 2929 } | |
| 2930 /* | |
| 2931 * get the nearest common ancestor. | |
| 2932 */ | |
| 2933 while (depth1 > depth2) { | |
| 2934 depth1--; | |
| 2935 node1 = node1->parent; | |
| 2936 } | |
| 2937 while (depth2 > depth1) { | |
| 2938 depth2--; | |
| 2939 node2 = node2->parent; | |
| 2940 } | |
| 2941 while (node1->parent != node2->parent) { | |
| 2942 node1 = node1->parent; | |
| 2943 node2 = node2->parent; | |
| 2944 /* should not happen but just in case ... */ | |
| 2945 if ((node1 == NULL) || (node2 == NULL)) | |
| 2946 return(-2); | |
| 2947 } | |
| 2948 /* | |
| 2949 * Find who's first. | |
| 2950 */ | |
| 2951 if (node1 == node2->prev) | |
| 2952 return(1); | |
| 2953 if (node1 == node2->next) | |
| 2954 return(-1); | |
| 2955 /* | |
| 2956 * Speedup using document order if availble. | |
| 2957 */ | |
| 2958 if ((node1->type == XML_ELEMENT_NODE) && | |
| 2959 (node2->type == XML_ELEMENT_NODE) && | |
| 2960 (0 > (long) node1->content) && | |
| 2961 (0 > (long) node2->content) && | |
| 2962 (node1->doc == node2->doc)) { | |
| 2963 long l1, l2; | |
| 2964 | |
| 2965 l1 = -((long) node1->content); | |
| 2966 l2 = -((long) node2->content); | |
| 2967 if (l1 < l2) | |
| 2968 return(1); | |
| 2969 if (l1 > l2) | |
| 2970 return(-1); | |
| 2971 } | |
| 2972 | |
| 2973 for (cur = node1->next;cur != NULL;cur = cur->next) | |
| 2974 if (cur == node2) | |
| 2975 return(1); | |
| 2976 return(-1); /* assume there is no sibling list corruption */ | |
| 2977 } | |
| 2978 | |
| 2979 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON | |
| 2980 /** | |
| 2981 * xmlXPathCmpNodesExt: | |
| 2982 * @node1: the first node | |
| 2983 * @node2: the second node | |
| 2984 * | |
| 2985 * Compare two nodes w.r.t document order. | |
| 2986 * This one is optimized for handling of non-element nodes. | |
| 2987 * | |
| 2988 * Returns -2 in case of error 1 if first point < second point, 0 if | |
| 2989 * it's the same node, -1 otherwise | |
| 2990 */ | |
| 2991 static int | |
| 2992 xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) { | |
| 2993 int depth1, depth2; | |
| 2994 int misc = 0, precedence1 = 0, precedence2 = 0; | |
| 2995 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL; | |
| 2996 xmlNodePtr cur, root; | |
| 2997 long l1, l2; | |
| 2998 | |
| 2999 if ((node1 == NULL) || (node2 == NULL)) | |
| 3000 return(-2); | |
| 3001 | |
| 3002 if (node1 == node2) | |
| 3003 return(0); | |
| 3004 | |
| 3005 /* | |
| 3006 * a couple of optimizations which will avoid computations in most cases | |
| 3007 */ | |
| 3008 switch (node1->type) { | |
| 3009 case XML_ELEMENT_NODE: | |
| 3010 if (node2->type == XML_ELEMENT_NODE) { | |
| 3011 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice
here? */ | |
| 3012 (0 > (long) node2->content) && | |
| 3013 (node1->doc == node2->doc)) | |
| 3014 { | |
| 3015 l1 = -((long) node1->content); | |
| 3016 l2 = -((long) node2->content); | |
| 3017 if (l1 < l2) | |
| 3018 return(1); | |
| 3019 if (l1 > l2) | |
| 3020 return(-1); | |
| 3021 } else | |
| 3022 goto turtle_comparison; | |
| 3023 } | |
| 3024 break; | |
| 3025 case XML_ATTRIBUTE_NODE: | |
| 3026 precedence1 = 1; /* element is owner */ | |
| 3027 miscNode1 = node1; | |
| 3028 node1 = node1->parent; | |
| 3029 misc = 1; | |
| 3030 break; | |
| 3031 case XML_TEXT_NODE: | |
| 3032 case XML_CDATA_SECTION_NODE: | |
| 3033 case XML_COMMENT_NODE: | |
| 3034 case XML_PI_NODE: { | |
| 3035 miscNode1 = node1; | |
| 3036 /* | |
| 3037 * Find nearest element node. | |
| 3038 */ | |
| 3039 if (node1->prev != NULL) { | |
| 3040 do { | |
| 3041 node1 = node1->prev; | |
| 3042 if (node1->type == XML_ELEMENT_NODE) { | |
| 3043 precedence1 = 3; /* element in prev-sibl axis */ | |
| 3044 break; | |
| 3045 } | |
| 3046 if (node1->prev == NULL) { | |
| 3047 precedence1 = 2; /* element is parent */ | |
| 3048 /* | |
| 3049 * URGENT TODO: Are there any cases, where the | |
| 3050 * parent of such a node is not an element node? | |
| 3051 */ | |
| 3052 node1 = node1->parent; | |
| 3053 break; | |
| 3054 } | |
| 3055 } while (1); | |
| 3056 } else { | |
| 3057 precedence1 = 2; /* element is parent */ | |
| 3058 node1 = node1->parent; | |
| 3059 } | |
| 3060 if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) || | |
| 3061 (0 <= (long) node1->content)) { | |
| 3062 /* | |
| 3063 * Fallback for whatever case. | |
| 3064 */ | |
| 3065 node1 = miscNode1; | |
| 3066 precedence1 = 0; | |
| 3067 } else | |
| 3068 misc = 1; | |
| 3069 } | |
| 3070 break; | |
| 3071 case XML_NAMESPACE_DECL: | |
| 3072 /* | |
| 3073 * TODO: why do we return 1 for namespace nodes? | |
| 3074 */ | |
| 3075 return(1); | |
| 3076 default: | |
| 3077 break; | |
| 3078 } | |
| 3079 switch (node2->type) { | |
| 3080 case XML_ELEMENT_NODE: | |
| 3081 break; | |
| 3082 case XML_ATTRIBUTE_NODE: | |
| 3083 precedence2 = 1; /* element is owner */ | |
| 3084 miscNode2 = node2; | |
| 3085 node2 = node2->parent; | |
| 3086 misc = 1; | |
| 3087 break; | |
| 3088 case XML_TEXT_NODE: | |
| 3089 case XML_CDATA_SECTION_NODE: | |
| 3090 case XML_COMMENT_NODE: | |
| 3091 case XML_PI_NODE: { | |
| 3092 miscNode2 = node2; | |
| 3093 if (node2->prev != NULL) { | |
| 3094 do { | |
| 3095 node2 = node2->prev; | |
| 3096 if (node2->type == XML_ELEMENT_NODE) { | |
| 3097 precedence2 = 3; /* element in prev-sibl axis */ | |
| 3098 break; | |
| 3099 } | |
| 3100 if (node2->prev == NULL) { | |
| 3101 precedence2 = 2; /* element is parent */ | |
| 3102 node2 = node2->parent; | |
| 3103 break; | |
| 3104 } | |
| 3105 } while (1); | |
| 3106 } else { | |
| 3107 precedence2 = 2; /* element is parent */ | |
| 3108 node2 = node2->parent; | |
| 3109 } | |
| 3110 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) || | |
| 3111 (0 <= (long) node1->content)) | |
| 3112 { | |
| 3113 node2 = miscNode2; | |
| 3114 precedence2 = 0; | |
| 3115 } else | |
| 3116 misc = 1; | |
| 3117 } | |
| 3118 break; | |
| 3119 case XML_NAMESPACE_DECL: | |
| 3120 return(1); | |
| 3121 default: | |
| 3122 break; | |
| 3123 } | |
| 3124 if (misc) { | |
| 3125 if (node1 == node2) { | |
| 3126 if (precedence1 == precedence2) { | |
| 3127 /* | |
| 3128 * The ugly case; but normally there aren't many | |
| 3129 * adjacent non-element nodes around. | |
| 3130 */ | |
| 3131 cur = miscNode2->prev; | |
| 3132 while (cur != NULL) { | |
| 3133 if (cur == miscNode1) | |
| 3134 return(1); | |
| 3135 if (cur->type == XML_ELEMENT_NODE) | |
| 3136 return(-1); | |
| 3137 cur = cur->prev; | |
| 3138 } | |
| 3139 return (-1); | |
| 3140 } else { | |
| 3141 /* | |
| 3142 * Evaluate based on higher precedence wrt to the element. | |
| 3143 * TODO: This assumes attributes are sorted before content. | |
| 3144 * Is this 100% correct? | |
| 3145 */ | |
| 3146 if (precedence1 < precedence2) | |
| 3147 return(1); | |
| 3148 else | |
| 3149 return(-1); | |
| 3150 } | |
| 3151 } | |
| 3152 /* | |
| 3153 * Special case: One of the helper-elements is contained by the other. | |
| 3154 * <foo> | |
| 3155 * <node2> | |
| 3156 * <node1>Text-1(precedence1 == 2)</node1> | |
| 3157 * </node2> | |
| 3158 * Text-6(precedence2 == 3) | |
| 3159 * </foo> | |
| 3160 */ | |
| 3161 if ((precedence2 == 3) && (precedence1 > 1)) { | |
| 3162 cur = node1->parent; | |
| 3163 while (cur) { | |
| 3164 if (cur == node2) | |
| 3165 return(1); | |
| 3166 cur = cur->parent; | |
| 3167 } | |
| 3168 } | |
| 3169 if ((precedence1 == 3) && (precedence2 > 1)) { | |
| 3170 cur = node2->parent; | |
| 3171 while (cur) { | |
| 3172 if (cur == node1) | |
| 3173 return(-1); | |
| 3174 cur = cur->parent; | |
| 3175 } | |
| 3176 } | |
| 3177 } | |
| 3178 | |
| 3179 /* | |
| 3180 * Speedup using document order if availble. | |
| 3181 */ | 3325 */ |
| 3182 if ((node1->type == XML_ELEMENT_NODE) && | 3326 if ((node1->type == XML_ELEMENT_NODE) && |
| 3183 (node2->type == XML_ELEMENT_NODE) && | 3327 (node2->type == XML_ELEMENT_NODE) && |
| 3184 (0 > (long) node1->content) && | 3328 (0 > (long) node1->content) && |
| 3185 (0 > (long) node2->content) && | 3329 (0 > (long) node2->content) && |
| 3186 (node1->doc == node2->doc)) { | 3330 (node1->doc == node2->doc)) { |
| 3331 long l1, l2; |
| 3187 | 3332 |
| 3188 l1 = -((long) node1->content); | 3333 l1 = -((long) node1->content); |
| 3189 l2 = -((long) node2->content); | 3334 l2 = -((long) node2->content); |
| 3190 if (l1 < l2) | 3335 if (l1 < l2) |
| 3191 return(1); | 3336 return(1); |
| 3192 if (l1 > l2) | 3337 if (l1 > l2) |
| 3193 return(-1); | 3338 return(-1); |
| 3194 } | 3339 } |
| 3195 | 3340 |
| 3196 turtle_comparison: | |
| 3197 | |
| 3198 if (node1 == node2->prev) | |
| 3199 return(1); | |
| 3200 if (node1 == node2->next) | |
| 3201 return(-1); | |
| 3202 /* | 3341 /* |
| 3203 * compute depth to root | 3342 * compute depth to root |
| 3204 */ | 3343 */ |
| 3205 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { | 3344 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { |
| 3206 if (cur == node1) | 3345 if (cur == node1) |
| 3207 return(1); | 3346 return(1); |
| 3208 depth2++; | 3347 depth2++; |
| 3209 } | 3348 } |
| 3210 root = cur; | 3349 root = cur; |
| 3211 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { | 3350 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3245 if (node1 == node2->next) | 3384 if (node1 == node2->next) |
| 3246 return(-1); | 3385 return(-1); |
| 3247 /* | 3386 /* |
| 3248 * Speedup using document order if availble. | 3387 * Speedup using document order if availble. |
| 3249 */ | 3388 */ |
| 3250 if ((node1->type == XML_ELEMENT_NODE) && | 3389 if ((node1->type == XML_ELEMENT_NODE) && |
| 3251 (node2->type == XML_ELEMENT_NODE) && | 3390 (node2->type == XML_ELEMENT_NODE) && |
| 3252 (0 > (long) node1->content) && | 3391 (0 > (long) node1->content) && |
| 3253 (0 > (long) node2->content) && | 3392 (0 > (long) node2->content) && |
| 3254 (node1->doc == node2->doc)) { | 3393 (node1->doc == node2->doc)) { |
| 3394 long l1, l2; |
| 3255 | 3395 |
| 3256 l1 = -((long) node1->content); | 3396 l1 = -((long) node1->content); |
| 3257 l2 = -((long) node2->content); | 3397 l2 = -((long) node2->content); |
| 3258 if (l1 < l2) | 3398 if (l1 < l2) |
| 3259 return(1); | 3399 return(1); |
| 3260 if (l1 > l2) | 3400 if (l1 > l2) |
| 3261 return(-1); | 3401 return(-1); |
| 3262 } | 3402 } |
| 3263 | 3403 |
| 3264 for (cur = node1->next;cur != NULL;cur = cur->next) | 3404 for (cur = node1->next;cur != NULL;cur = cur->next) |
| 3265 if (cur == node2) | 3405 if (cur == node2) |
| 3266 return(1); | 3406 return(1); |
| 3267 return(-1); /* assume there is no sibling list corruption */ | 3407 return(-1); /* assume there is no sibling list corruption */ |
| 3268 } | 3408 } |
| 3269 #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */ | |
| 3270 | 3409 |
| 3271 /** | 3410 /** |
| 3272 * xmlXPathNodeSetSort: | 3411 * xmlXPathNodeSetSort: |
| 3273 * @set: the node set | 3412 * @set: the node set |
| 3274 * | 3413 * |
| 3275 * Sort the node set in document order | 3414 * Sort the node set in document order |
| 3276 */ | 3415 */ |
| 3277 void | 3416 void |
| 3278 xmlXPathNodeSetSort(xmlNodeSetPtr set) { | 3417 xmlXPathNodeSetSort(xmlNodeSetPtr set) { |
| 3418 #ifndef WITH_TIM_SORT |
| 3279 int i, j, incr, len; | 3419 int i, j, incr, len; |
| 3280 xmlNodePtr tmp; | 3420 xmlNodePtr tmp; |
| 3421 #endif |
| 3281 | 3422 |
| 3282 if (set == NULL) | 3423 if (set == NULL) |
| 3283 return; | 3424 return; |
| 3284 | 3425 |
| 3285 /* Use Shell's sort to sort the node-set */ | 3426 #ifndef WITH_TIM_SORT |
| 3427 /* |
| 3428 * Use the old Shell's sort implementation to sort the node-set |
| 3429 * Timsort ought to be quite faster |
| 3430 */ |
| 3286 len = set->nodeNr; | 3431 len = set->nodeNr; |
| 3287 for (incr = len / 2; incr > 0; incr /= 2) { | 3432 for (incr = len / 2; incr > 0; incr /= 2) { |
| 3288 for (i = incr; i < len; i++) { | 3433 for (i = incr; i < len; i++) { |
| 3289 j = i - incr; | 3434 j = i - incr; |
| 3290 while (j >= 0) { | 3435 while (j >= 0) { |
| 3291 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON | 3436 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON |
| 3292 if (xmlXPathCmpNodesExt(set->nodeTab[j], | 3437 if (xmlXPathCmpNodesExt(set->nodeTab[j], |
| 3293 set->nodeTab[j + incr]) == -1) | 3438 set->nodeTab[j + incr]) == -1) |
| 3294 #else | 3439 #else |
| 3295 if (xmlXPathCmpNodes(set->nodeTab[j], | 3440 if (xmlXPathCmpNodes(set->nodeTab[j], |
| 3296 set->nodeTab[j + incr]) == -1) | 3441 set->nodeTab[j + incr]) == -1) |
| 3297 #endif | 3442 #endif |
| 3298 { | 3443 { |
| 3299 tmp = set->nodeTab[j]; | 3444 tmp = set->nodeTab[j]; |
| 3300 set->nodeTab[j] = set->nodeTab[j + incr]; | 3445 set->nodeTab[j] = set->nodeTab[j + incr]; |
| 3301 set->nodeTab[j + incr] = tmp; | 3446 set->nodeTab[j + incr] = tmp; |
| 3302 j -= incr; | 3447 j -= incr; |
| 3303 } else | 3448 } else |
| 3304 break; | 3449 break; |
| 3305 } | 3450 } |
| 3306 } | 3451 } |
| 3307 } | 3452 } |
| 3453 #else /* WITH_TIM_SORT */ |
| 3454 libxml_domnode_tim_sort(set->nodeTab, set->nodeNr); |
| 3455 #endif /* WITH_TIM_SORT */ |
| 3308 } | 3456 } |
| 3309 | 3457 |
| 3310 #define XML_NODESET_DEFAULT 10 | 3458 #define XML_NODESET_DEFAULT 10 |
| 3311 /** | 3459 /** |
| 3312 * xmlXPathNodeSetDupNs: | 3460 * xmlXPathNodeSetDupNs: |
| 3313 * @node: the parent node of the namespace XPath node | 3461 * @node: the parent node of the namespace XPath node |
| 3314 * @ns: the libxml namespace declaration node. | 3462 * @ns: the libxml namespace declaration node. |
| 3315 * | 3463 * |
| 3316 * Namespace node in libxml don't match the XPath semantic. In a node set | 3464 * Namespace node in libxml don't match the XPath semantic. In a node set |
| 3317 * the namespace nodes are duplicated and the next pointer is set to the | 3465 * the namespace nodes are duplicated and the next pointer is set to the |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3476 return(0); | 3624 return(0); |
| 3477 } | 3625 } |
| 3478 | 3626 |
| 3479 /** | 3627 /** |
| 3480 * xmlXPathNodeSetAddNs: | 3628 * xmlXPathNodeSetAddNs: |
| 3481 * @cur: the initial node set | 3629 * @cur: the initial node set |
| 3482 * @node: the hosting node | 3630 * @node: the hosting node |
| 3483 * @ns: a the namespace node | 3631 * @ns: a the namespace node |
| 3484 * | 3632 * |
| 3485 * add a new namespace node to an existing NodeSet | 3633 * add a new namespace node to an existing NodeSet |
| 3634 * |
| 3635 * Returns 0 in case of success and -1 in case of error |
| 3486 */ | 3636 */ |
| 3487 void | 3637 int |
| 3488 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { | 3638 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { |
| 3489 int i; | 3639 int i; |
| 3490 | 3640 |
| 3491 | 3641 |
| 3492 if ((cur == NULL) || (ns == NULL) || (node == NULL) || | 3642 if ((cur == NULL) || (ns == NULL) || (node == NULL) || |
| 3493 (ns->type != XML_NAMESPACE_DECL) || | 3643 (ns->type != XML_NAMESPACE_DECL) || |
| 3494 (node->type != XML_ELEMENT_NODE)) | 3644 (node->type != XML_ELEMENT_NODE)) |
| 3495 » return; | 3645 » return(-1); |
| 3496 | 3646 |
| 3497 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ | 3647 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ |
| 3498 /* | 3648 /* |
| 3499 * prevent duplicates | 3649 * prevent duplicates |
| 3500 */ | 3650 */ |
| 3501 for (i = 0;i < cur->nodeNr;i++) { | 3651 for (i = 0;i < cur->nodeNr;i++) { |
| 3502 if ((cur->nodeTab[i] != NULL) && | 3652 if ((cur->nodeTab[i] != NULL) && |
| 3503 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) && | 3653 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) && |
| 3504 (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) && | 3654 (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) && |
| 3505 (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix))) | 3655 (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix))) |
| 3506 » return; | 3656 » return(0); |
| 3507 } | 3657 } |
| 3508 | 3658 |
| 3509 /* | 3659 /* |
| 3510 * grow the nodeTab if needed | 3660 * grow the nodeTab if needed |
| 3511 */ | 3661 */ |
| 3512 if (cur->nodeMax == 0) { | 3662 if (cur->nodeMax == 0) { |
| 3513 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * | 3663 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * |
| 3514 sizeof(xmlNodePtr)); | 3664 sizeof(xmlNodePtr)); |
| 3515 if (cur->nodeTab == NULL) { | 3665 if (cur->nodeTab == NULL) { |
| 3516 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3666 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
| 3517 » return; | 3667 » return(-1); |
| 3518 } | 3668 } |
| 3519 memset(cur->nodeTab, 0 , | 3669 memset(cur->nodeTab, 0 , |
| 3520 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 3670 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
| 3521 cur->nodeMax = XML_NODESET_DEFAULT; | 3671 cur->nodeMax = XML_NODESET_DEFAULT; |
| 3522 } else if (cur->nodeNr == cur->nodeMax) { | 3672 } else if (cur->nodeNr == cur->nodeMax) { |
| 3523 xmlNodePtr *temp; | 3673 xmlNodePtr *temp; |
| 3524 | 3674 |
| 3525 cur->nodeMax *= 2; | 3675 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { |
| 3526 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * | 3676 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); |
| 3677 return(-1); |
| 3678 } |
| 3679 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * |
| 3527 sizeof(xmlNodePtr)); | 3680 sizeof(xmlNodePtr)); |
| 3528 if (temp == NULL) { | 3681 if (temp == NULL) { |
| 3529 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3682 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
| 3530 » return; | 3683 » return(-1); |
| 3531 } | 3684 } |
| 3685 cur->nodeMax *= 2; |
| 3532 cur->nodeTab = temp; | 3686 cur->nodeTab = temp; |
| 3533 } | 3687 } |
| 3534 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns); | 3688 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns); |
| 3689 return(0); |
| 3535 } | 3690 } |
| 3536 | 3691 |
| 3537 /** | 3692 /** |
| 3538 * xmlXPathNodeSetAdd: | 3693 * xmlXPathNodeSetAdd: |
| 3539 * @cur: the initial node set | 3694 * @cur: the initial node set |
| 3540 * @val: a new xmlNodePtr | 3695 * @val: a new xmlNodePtr |
| 3541 * | 3696 * |
| 3542 * add a new xmlNodePtr to an existing NodeSet | 3697 * add a new xmlNodePtr to an existing NodeSet |
| 3698 * |
| 3699 * Returns 0 in case of success, and -1 in case of error |
| 3543 */ | 3700 */ |
| 3544 void | 3701 int |
| 3545 xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { | 3702 xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { |
| 3546 int i; | 3703 int i; |
| 3547 | 3704 |
| 3548 if ((cur == NULL) || (val == NULL)) return; | 3705 if ((cur == NULL) || (val == NULL)) return(-1); |
| 3549 | |
| 3550 #if 0 | |
| 3551 if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' ')) | |
| 3552 » return;»/* an XSLT fake node */ | |
| 3553 #endif | |
| 3554 | 3706 |
| 3555 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ | 3707 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ |
| 3556 /* | 3708 /* |
| 3557 * prevent duplcates | 3709 * prevent duplcates |
| 3558 */ | 3710 */ |
| 3559 for (i = 0;i < cur->nodeNr;i++) | 3711 for (i = 0;i < cur->nodeNr;i++) |
| 3560 if (cur->nodeTab[i] == val) return; | 3712 if (cur->nodeTab[i] == val) return(0); |
| 3561 | 3713 |
| 3562 /* | 3714 /* |
| 3563 * grow the nodeTab if needed | 3715 * grow the nodeTab if needed |
| 3564 */ | 3716 */ |
| 3565 if (cur->nodeMax == 0) { | 3717 if (cur->nodeMax == 0) { |
| 3566 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * | 3718 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * |
| 3567 sizeof(xmlNodePtr)); | 3719 sizeof(xmlNodePtr)); |
| 3568 if (cur->nodeTab == NULL) { | 3720 if (cur->nodeTab == NULL) { |
| 3569 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3721 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
| 3570 » return; | 3722 » return(-1); |
| 3571 } | 3723 } |
| 3572 memset(cur->nodeTab, 0 , | 3724 memset(cur->nodeTab, 0 , |
| 3573 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 3725 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
| 3574 cur->nodeMax = XML_NODESET_DEFAULT; | 3726 cur->nodeMax = XML_NODESET_DEFAULT; |
| 3575 } else if (cur->nodeNr == cur->nodeMax) { | 3727 } else if (cur->nodeNr == cur->nodeMax) { |
| 3576 xmlNodePtr *temp; | 3728 xmlNodePtr *temp; |
| 3577 | 3729 |
| 3578 cur->nodeMax *= 2; | 3730 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { |
| 3579 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * | 3731 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); |
| 3732 return(-1); |
| 3733 } |
| 3734 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * |
| 3580 sizeof(xmlNodePtr)); | 3735 sizeof(xmlNodePtr)); |
| 3581 if (temp == NULL) { | 3736 if (temp == NULL) { |
| 3582 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3737 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
| 3583 » return; | 3738 » return(-1); |
| 3584 } | 3739 } |
| 3740 cur->nodeMax *= 2; |
| 3585 cur->nodeTab = temp; | 3741 cur->nodeTab = temp; |
| 3586 } | 3742 } |
| 3587 if (val->type == XML_NAMESPACE_DECL) { | 3743 if (val->type == XML_NAMESPACE_DECL) { |
| 3588 xmlNsPtr ns = (xmlNsPtr) val; | 3744 xmlNsPtr ns = (xmlNsPtr) val; |
| 3589 | 3745 |
| 3590 cur->nodeTab[cur->nodeNr++] = | 3746 cur->nodeTab[cur->nodeNr++] = |
| 3591 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 3747 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
| 3592 } else | 3748 } else |
| 3593 cur->nodeTab[cur->nodeNr++] = val; | 3749 cur->nodeTab[cur->nodeNr++] = val; |
| 3750 return(0); |
| 3594 } | 3751 } |
| 3595 | 3752 |
| 3596 /** | 3753 /** |
| 3597 * xmlXPathNodeSetAddUnique: | 3754 * xmlXPathNodeSetAddUnique: |
| 3598 * @cur: the initial node set | 3755 * @cur: the initial node set |
| 3599 * @val: a new xmlNodePtr | 3756 * @val: a new xmlNodePtr |
| 3600 * | 3757 * |
| 3601 * add a new xmlNodePtr to an existing NodeSet, optimized version | 3758 * add a new xmlNodePtr to an existing NodeSet, optimized version |
| 3602 * when we are sure the node is not already in the set. | 3759 * when we are sure the node is not already in the set. |
| 3760 * |
| 3761 * Returns 0 in case of success and -1 in case of failure |
| 3603 */ | 3762 */ |
| 3604 void | 3763 int |
| 3605 xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { | 3764 xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { |
| 3606 if ((cur == NULL) || (val == NULL)) return; | 3765 if ((cur == NULL) || (val == NULL)) return(-1); |
| 3607 | |
| 3608 #if 0 | |
| 3609 if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' ')) | |
| 3610 » return;»/* an XSLT fake node */ | |
| 3611 #endif | |
| 3612 | 3766 |
| 3613 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ | 3767 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ |
| 3614 /* | 3768 /* |
| 3615 * grow the nodeTab if needed | 3769 * grow the nodeTab if needed |
| 3616 */ | 3770 */ |
| 3617 if (cur->nodeMax == 0) { | 3771 if (cur->nodeMax == 0) { |
| 3618 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * | 3772 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * |
| 3619 sizeof(xmlNodePtr)); | 3773 sizeof(xmlNodePtr)); |
| 3620 if (cur->nodeTab == NULL) { | 3774 if (cur->nodeTab == NULL) { |
| 3621 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3775 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
| 3622 » return; | 3776 » return(-1); |
| 3623 } | 3777 } |
| 3624 memset(cur->nodeTab, 0 , | 3778 memset(cur->nodeTab, 0 , |
| 3625 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 3779 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
| 3626 cur->nodeMax = XML_NODESET_DEFAULT; | 3780 cur->nodeMax = XML_NODESET_DEFAULT; |
| 3627 } else if (cur->nodeNr == cur->nodeMax) { | 3781 } else if (cur->nodeNr == cur->nodeMax) { |
| 3628 xmlNodePtr *temp; | 3782 xmlNodePtr *temp; |
| 3629 | 3783 |
| 3630 cur->nodeMax *= 2; | 3784 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) { |
| 3631 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * | 3785 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n"); |
| 3786 return(-1); |
| 3787 } |
| 3788 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 * |
| 3632 sizeof(xmlNodePtr)); | 3789 sizeof(xmlNodePtr)); |
| 3633 if (temp == NULL) { | 3790 if (temp == NULL) { |
| 3634 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3791 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
| 3635 » return; | 3792 » return(-1); |
| 3636 } | 3793 } |
| 3637 cur->nodeTab = temp; | 3794 cur->nodeTab = temp; |
| 3795 cur->nodeMax *= 2; |
| 3638 } | 3796 } |
| 3639 if (val->type == XML_NAMESPACE_DECL) { | 3797 if (val->type == XML_NAMESPACE_DECL) { |
| 3640 xmlNsPtr ns = (xmlNsPtr) val; | 3798 xmlNsPtr ns = (xmlNsPtr) val; |
| 3641 | 3799 |
| 3642 cur->nodeTab[cur->nodeNr++] = | 3800 cur->nodeTab[cur->nodeNr++] = |
| 3643 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 3801 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
| 3644 } else | 3802 } else |
| 3645 cur->nodeTab[cur->nodeNr++] = val; | 3803 cur->nodeTab[cur->nodeNr++] = val; |
| 3804 return(0); |
| 3646 } | 3805 } |
| 3647 | 3806 |
| 3648 /** | 3807 /** |
| 3649 * xmlXPathNodeSetMerge: | 3808 * xmlXPathNodeSetMerge: |
| 3650 * @val1: the first NodeSet or NULL | 3809 * @val1: the first NodeSet or NULL |
| 3651 * @val2: the second NodeSet | 3810 * @val2: the second NodeSet |
| 3652 * | 3811 * |
| 3653 * Merges two nodesets, all nodes from @val2 are added to @val1 | 3812 * Merges two nodesets, all nodes from @val2 are added to @val1 |
| 3654 * if @val1 is NULL, a new set is created and copied from @val2 | 3813 * if @val1 is NULL, a new set is created and copied from @val2 |
| 3655 * | 3814 * |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3731 if (val1->nodeTab == NULL) { | 3890 if (val1->nodeTab == NULL) { |
| 3732 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 3891 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
| 3733 return(NULL); | 3892 return(NULL); |
| 3734 } | 3893 } |
| 3735 memset(val1->nodeTab, 0 , | 3894 memset(val1->nodeTab, 0 , |
| 3736 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 3895 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
| 3737 val1->nodeMax = XML_NODESET_DEFAULT; | 3896 val1->nodeMax = XML_NODESET_DEFAULT; |
| 3738 } else if (val1->nodeNr == val1->nodeMax) { | 3897 } else if (val1->nodeNr == val1->nodeMax) { |
| 3739 xmlNodePtr *temp; | 3898 xmlNodePtr *temp; |
| 3740 | 3899 |
| 3741 » val1->nodeMax *= 2; | 3900 if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { |
| 3742 » temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * | 3901 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); |
| 3902 return(NULL); |
| 3903 } |
| 3904 » temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 * |
| 3743 sizeof(xmlNodePtr)); | 3905 sizeof(xmlNodePtr)); |
| 3744 if (temp == NULL) { | 3906 if (temp == NULL) { |
| 3745 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 3907 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
| 3746 return(NULL); | 3908 return(NULL); |
| 3747 } | 3909 } |
| 3748 val1->nodeTab = temp; | 3910 val1->nodeTab = temp; |
| 3911 val1->nodeMax *= 2; |
| 3749 } | 3912 } |
| 3750 if (n2->type == XML_NAMESPACE_DECL) { | 3913 if (n2->type == XML_NAMESPACE_DECL) { |
| 3751 xmlNsPtr ns = (xmlNsPtr) n2; | 3914 xmlNsPtr ns = (xmlNsPtr) n2; |
| 3752 | 3915 |
| 3753 val1->nodeTab[val1->nodeNr++] = | 3916 val1->nodeTab[val1->nodeNr++] = |
| 3754 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 3917 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
| 3755 } else | 3918 } else |
| 3756 val1->nodeTab[val1->nodeNr++] = n2; | 3919 val1->nodeTab[val1->nodeNr++] = n2; |
| 3757 } | 3920 } |
| 3758 | 3921 |
| 3759 return(val1); | 3922 return(val1); |
| 3760 } | 3923 } |
| 3761 | 3924 |
| 3762 #if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */ | |
| 3763 /** | |
| 3764 * xmlXPathNodeSetMergeUnique: | |
| 3765 * @val1: the first NodeSet or NULL | |
| 3766 * @val2: the second NodeSet | |
| 3767 * | |
| 3768 * Merges two nodesets, all nodes from @val2 are added to @val1 | |
| 3769 * if @val1 is NULL, a new set is created and copied from @val2 | |
| 3770 * | |
| 3771 * Returns @val1 once extended or NULL in case of error. | |
| 3772 */ | |
| 3773 static xmlNodeSetPtr | |
| 3774 xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { | |
| 3775 int i; | |
| 3776 | |
| 3777 if (val2 == NULL) return(val1); | |
| 3778 if (val1 == NULL) { | |
| 3779 val1 = xmlXPathNodeSetCreate(NULL); | |
| 3780 } | |
| 3781 if (val1 == NULL) | |
| 3782 return (NULL); | |
| 3783 | |
| 3784 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ | |
| 3785 | |
| 3786 for (i = 0;i < val2->nodeNr;i++) { | |
| 3787 /* | |
| 3788 * grow the nodeTab if needed | |
| 3789 */ | |
| 3790 if (val1->nodeMax == 0) { | |
| 3791 val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * | |
| 3792 sizeof(xmlNodePtr)); | |
| 3793 if (val1->nodeTab == NULL) { | |
| 3794 xmlXPathErrMemory(NULL, "merging nodeset\n"); | |
| 3795 return(NULL); | |
| 3796 } | |
| 3797 memset(val1->nodeTab, 0 , | |
| 3798 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | |
| 3799 val1->nodeMax = XML_NODESET_DEFAULT; | |
| 3800 } else if (val1->nodeNr == val1->nodeMax) { | |
| 3801 xmlNodePtr *temp; | |
| 3802 | |
| 3803 val1->nodeMax *= 2; | |
| 3804 temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * | |
| 3805 sizeof(xmlNodePtr)); | |
| 3806 if (temp == NULL) { | |
| 3807 xmlXPathErrMemory(NULL, "merging nodeset\n"); | |
| 3808 return(NULL); | |
| 3809 } | |
| 3810 val1->nodeTab = temp; | |
| 3811 } | |
| 3812 if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) { | |
| 3813 xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i]; | |
| 3814 | |
| 3815 val1->nodeTab[val1->nodeNr++] = | |
| 3816 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | |
| 3817 } else | |
| 3818 val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i]; | |
| 3819 } | |
| 3820 | |
| 3821 return(val1); | |
| 3822 } | |
| 3823 #endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */ | |
| 3824 | 3925 |
| 3825 /** | 3926 /** |
| 3826 * xmlXPathNodeSetMergeAndClear: | 3927 * xmlXPathNodeSetMergeAndClear: |
| 3827 * @set1: the first NodeSet or NULL | 3928 * @set1: the first NodeSet or NULL |
| 3828 * @set2: the second NodeSet | 3929 * @set2: the second NodeSet |
| 3829 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes | 3930 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes |
| 3830 * | 3931 * |
| 3831 * Merges two nodesets, all nodes from @set2 are added to @set1 | 3932 * Merges two nodesets, all nodes from @set2 are added to @set1 |
| 3832 * if @set1 is NULL, a new set is created and copied from @set2. | 3933 * if @set1 is NULL, a new set is created and copied from @set2. |
| 3833 * Checks for duplicate nodes. Clears set2. | 3934 * Checks for duplicate nodes. Clears set2. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3900 if (set1->nodeTab == NULL) { | 4001 if (set1->nodeTab == NULL) { |
| 3901 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 4002 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
| 3902 return(NULL); | 4003 return(NULL); |
| 3903 } | 4004 } |
| 3904 memset(set1->nodeTab, 0, | 4005 memset(set1->nodeTab, 0, |
| 3905 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 4006 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
| 3906 set1->nodeMax = XML_NODESET_DEFAULT; | 4007 set1->nodeMax = XML_NODESET_DEFAULT; |
| 3907 } else if (set1->nodeNr >= set1->nodeMax) { | 4008 } else if (set1->nodeNr >= set1->nodeMax) { |
| 3908 xmlNodePtr *temp; | 4009 xmlNodePtr *temp; |
| 3909 | 4010 |
| 3910 » » set1->nodeMax *= 2; | 4011 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { |
| 4012 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); |
| 4013 return(NULL); |
| 4014 } |
| 3911 temp = (xmlNodePtr *) xmlRealloc( | 4015 temp = (xmlNodePtr *) xmlRealloc( |
| 3912 » » set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); | 4016 » » set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr)); |
| 3913 if (temp == NULL) { | 4017 if (temp == NULL) { |
| 3914 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 4018 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
| 3915 return(NULL); | 4019 return(NULL); |
| 3916 } | 4020 } |
| 3917 set1->nodeTab = temp; | 4021 set1->nodeTab = temp; |
| 4022 set1->nodeMax *= 2; |
| 3918 } | 4023 } |
| 3919 if (n2->type == XML_NAMESPACE_DECL) { | 4024 if (n2->type == XML_NAMESPACE_DECL) { |
| 3920 xmlNsPtr ns = (xmlNsPtr) n2; | 4025 xmlNsPtr ns = (xmlNsPtr) n2; |
| 3921 | 4026 |
| 3922 set1->nodeTab[set1->nodeNr++] = | 4027 set1->nodeTab[set1->nodeNr++] = |
| 3923 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 4028 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
| 3924 } else | 4029 } else |
| 3925 set1->nodeTab[set1->nodeNr++] = n2; | 4030 set1->nodeTab[set1->nodeNr++] = n2; |
| 3926 skip_node: | 4031 skip_node: |
| 3927 {} | 4032 {} |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3984 if (set1->nodeTab == NULL) { | 4089 if (set1->nodeTab == NULL) { |
| 3985 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 4090 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
| 3986 return(NULL); | 4091 return(NULL); |
| 3987 } | 4092 } |
| 3988 memset(set1->nodeTab, 0, | 4093 memset(set1->nodeTab, 0, |
| 3989 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 4094 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
| 3990 set1->nodeMax = XML_NODESET_DEFAULT; | 4095 set1->nodeMax = XML_NODESET_DEFAULT; |
| 3991 } else if (set1->nodeNr >= set1->nodeMax) { | 4096 } else if (set1->nodeNr >= set1->nodeMax) { |
| 3992 xmlNodePtr *temp; | 4097 xmlNodePtr *temp; |
| 3993 | 4098 |
| 3994 » » set1->nodeMax *= 2; | 4099 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) { |
| 4100 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n"); |
| 4101 return(NULL); |
| 4102 } |
| 3995 temp = (xmlNodePtr *) xmlRealloc( | 4103 temp = (xmlNodePtr *) xmlRealloc( |
| 3996 » » set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); | 4104 » » set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr)); |
| 3997 if (temp == NULL) { | 4105 if (temp == NULL) { |
| 3998 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 4106 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
| 3999 return(NULL); | 4107 return(NULL); |
| 4000 } | 4108 } |
| 4001 set1->nodeTab = temp; | 4109 set1->nodeTab = temp; |
| 4110 set1->nodeMax *= 2; |
| 4002 } | 4111 } |
| 4003 set1->nodeTab[set1->nodeNr++] = n2; | 4112 set1->nodeTab[set1->nodeNr++] = n2; |
| 4004 } | 4113 } |
| 4005 } | 4114 } |
| 4006 set2->nodeNr = 0; | 4115 set2->nodeNr = 0; |
| 4007 return(set1); | 4116 return(set1); |
| 4008 } | 4117 } |
| 4009 | 4118 |
| 4010 /** | 4119 /** |
| 4011 * xmlXPathNodeSetDel: | 4120 * xmlXPathNodeSetDel: |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4282 { | 4391 { |
| 4283 xmlXPathObjectPtr ret; | 4392 xmlXPathObjectPtr ret; |
| 4284 int i; | 4393 int i; |
| 4285 | 4394 |
| 4286 if (val == NULL) | 4395 if (val == NULL) |
| 4287 ret = NULL; | 4396 ret = NULL; |
| 4288 else if (val->nodeTab == NULL) | 4397 else if (val->nodeTab == NULL) |
| 4289 ret = xmlXPathNewNodeSet(NULL); | 4398 ret = xmlXPathNewNodeSet(NULL); |
| 4290 else { | 4399 else { |
| 4291 ret = xmlXPathNewNodeSet(val->nodeTab[0]); | 4400 ret = xmlXPathNewNodeSet(val->nodeTab[0]); |
| 4292 if (ret) | 4401 if (ret) { |
| 4293 for (i = 1; i < val->nodeNr; ++i) | 4402 for (i = 1; i < val->nodeNr; ++i) { |
| 4294 xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]); | 4403 if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]) |
| 4404 » » < 0) break; |
| 4405 » } |
| 4406 » } |
| 4295 } | 4407 } |
| 4296 | 4408 |
| 4297 return (ret); | 4409 return (ret); |
| 4298 } | 4410 } |
| 4299 | 4411 |
| 4300 /** | 4412 /** |
| 4301 * xmlXPathWrapNodeSet: | 4413 * xmlXPathWrapNodeSet: |
| 4302 * @val: the NodePtr value | 4414 * @val: the NodePtr value |
| 4303 * | 4415 * |
| 4304 * Wrap the Nodeset @val in a new xmlXPathObjectPtr | 4416 * Wrap the Nodeset @val in a new xmlXPathObjectPtr |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4360 return(nodes1); | 4472 return(nodes1); |
| 4361 | 4473 |
| 4362 ret = xmlXPathNodeSetCreate(NULL); | 4474 ret = xmlXPathNodeSetCreate(NULL); |
| 4363 if (xmlXPathNodeSetIsEmpty(nodes1)) | 4475 if (xmlXPathNodeSetIsEmpty(nodes1)) |
| 4364 return(ret); | 4476 return(ret); |
| 4365 | 4477 |
| 4366 l1 = xmlXPathNodeSetGetLength(nodes1); | 4478 l1 = xmlXPathNodeSetGetLength(nodes1); |
| 4367 | 4479 |
| 4368 for (i = 0; i < l1; i++) { | 4480 for (i = 0; i < l1; i++) { |
| 4369 cur = xmlXPathNodeSetItem(nodes1, i); | 4481 cur = xmlXPathNodeSetItem(nodes1, i); |
| 4370 » if (!xmlXPathNodeSetContains(nodes2, cur)) | 4482 » if (!xmlXPathNodeSetContains(nodes2, cur)) { |
| 4371 » xmlXPathNodeSetAddUnique(ret, cur); | 4483 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0) |
| 4484 » break; |
| 4485 » } |
| 4372 } | 4486 } |
| 4373 return(ret); | 4487 return(ret); |
| 4374 } | 4488 } |
| 4375 | 4489 |
| 4376 /** | 4490 /** |
| 4377 * xmlXPathIntersection: | 4491 * xmlXPathIntersection: |
| 4378 * @nodes1: a node-set | 4492 * @nodes1: a node-set |
| 4379 * @nodes2: a node-set | 4493 * @nodes2: a node-set |
| 4380 * | 4494 * |
| 4381 * Implements the EXSLT - Sets intersection() function: | 4495 * Implements the EXSLT - Sets intersection() function: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4394 return(ret); | 4508 return(ret); |
| 4395 if (xmlXPathNodeSetIsEmpty(nodes1)) | 4509 if (xmlXPathNodeSetIsEmpty(nodes1)) |
| 4396 return(ret); | 4510 return(ret); |
| 4397 if (xmlXPathNodeSetIsEmpty(nodes2)) | 4511 if (xmlXPathNodeSetIsEmpty(nodes2)) |
| 4398 return(ret); | 4512 return(ret); |
| 4399 | 4513 |
| 4400 l1 = xmlXPathNodeSetGetLength(nodes1); | 4514 l1 = xmlXPathNodeSetGetLength(nodes1); |
| 4401 | 4515 |
| 4402 for (i = 0; i < l1; i++) { | 4516 for (i = 0; i < l1; i++) { |
| 4403 cur = xmlXPathNodeSetItem(nodes1, i); | 4517 cur = xmlXPathNodeSetItem(nodes1, i); |
| 4404 » if (xmlXPathNodeSetContains(nodes2, cur)) | 4518 » if (xmlXPathNodeSetContains(nodes2, cur)) { |
| 4405 » xmlXPathNodeSetAddUnique(ret, cur); | 4519 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0) |
| 4520 » break; |
| 4521 » } |
| 4406 } | 4522 } |
| 4407 return(ret); | 4523 return(ret); |
| 4408 } | 4524 } |
| 4409 | 4525 |
| 4410 /** | 4526 /** |
| 4411 * xmlXPathDistinctSorted: | 4527 * xmlXPathDistinctSorted: |
| 4412 * @nodes: a node-set, sorted by document order | 4528 * @nodes: a node-set, sorted by document order |
| 4413 * | 4529 * |
| 4414 * Implements the EXSLT - Sets distinct() function: | 4530 * Implements the EXSLT - Sets distinct() function: |
| 4415 * node-set set:distinct (node-set) | 4531 * node-set set:distinct (node-set) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4431 ret = xmlXPathNodeSetCreate(NULL); | 4547 ret = xmlXPathNodeSetCreate(NULL); |
| 4432 if (ret == NULL) | 4548 if (ret == NULL) |
| 4433 return(ret); | 4549 return(ret); |
| 4434 l = xmlXPathNodeSetGetLength(nodes); | 4550 l = xmlXPathNodeSetGetLength(nodes); |
| 4435 hash = xmlHashCreate (l); | 4551 hash = xmlHashCreate (l); |
| 4436 for (i = 0; i < l; i++) { | 4552 for (i = 0; i < l; i++) { |
| 4437 cur = xmlXPathNodeSetItem(nodes, i); | 4553 cur = xmlXPathNodeSetItem(nodes, i); |
| 4438 strval = xmlXPathCastNodeToString(cur); | 4554 strval = xmlXPathCastNodeToString(cur); |
| 4439 if (xmlHashLookup(hash, strval) == NULL) { | 4555 if (xmlHashLookup(hash, strval) == NULL) { |
| 4440 xmlHashAddEntry(hash, strval, strval); | 4556 xmlHashAddEntry(hash, strval, strval); |
| 4441 » xmlXPathNodeSetAddUnique(ret, cur); | 4557 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0) |
| 4558 » break; |
| 4442 } else { | 4559 } else { |
| 4443 xmlFree(strval); | 4560 xmlFree(strval); |
| 4444 } | 4561 } |
| 4445 } | 4562 } |
| 4446 xmlHashFree(hash, (xmlHashDeallocator) xmlFree); | 4563 xmlHashFree(hash, (xmlHashDeallocator) xmlFree); |
| 4447 return(ret); | 4564 return(ret); |
| 4448 } | 4565 } |
| 4449 | 4566 |
| 4450 /** | 4567 /** |
| 4451 * xmlXPathDistinct: | 4568 * xmlXPathDistinct: |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4523 return(ret); | 4640 return(ret); |
| 4524 if (xmlXPathNodeSetIsEmpty(nodes) || | 4641 if (xmlXPathNodeSetIsEmpty(nodes) || |
| 4525 (!xmlXPathNodeSetContains(nodes, node))) | 4642 (!xmlXPathNodeSetContains(nodes, node))) |
| 4526 return(ret); | 4643 return(ret); |
| 4527 | 4644 |
| 4528 l = xmlXPathNodeSetGetLength(nodes); | 4645 l = xmlXPathNodeSetGetLength(nodes); |
| 4529 for (i = 0; i < l; i++) { | 4646 for (i = 0; i < l; i++) { |
| 4530 cur = xmlXPathNodeSetItem(nodes, i); | 4647 cur = xmlXPathNodeSetItem(nodes, i); |
| 4531 if (cur == node) | 4648 if (cur == node) |
| 4532 break; | 4649 break; |
| 4533 » xmlXPathNodeSetAddUnique(ret, cur); | 4650 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0) |
| 4651 » break; |
| 4534 } | 4652 } |
| 4535 return(ret); | 4653 return(ret); |
| 4536 } | 4654 } |
| 4537 | 4655 |
| 4538 /** | 4656 /** |
| 4539 * xmlXPathNodeLeading: | 4657 * xmlXPathNodeLeading: |
| 4540 * @nodes: a node-set | 4658 * @nodes: a node-set |
| 4541 * @node: a node | 4659 * @node: a node |
| 4542 * | 4660 * |
| 4543 * Implements the EXSLT - Sets leading() function: | 4661 * Implements the EXSLT - Sets leading() function: |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4627 return(ret); | 4745 return(ret); |
| 4628 if (xmlXPathNodeSetIsEmpty(nodes) || | 4746 if (xmlXPathNodeSetIsEmpty(nodes) || |
| 4629 (!xmlXPathNodeSetContains(nodes, node))) | 4747 (!xmlXPathNodeSetContains(nodes, node))) |
| 4630 return(ret); | 4748 return(ret); |
| 4631 | 4749 |
| 4632 l = xmlXPathNodeSetGetLength(nodes); | 4750 l = xmlXPathNodeSetGetLength(nodes); |
| 4633 for (i = l - 1; i >= 0; i--) { | 4751 for (i = l - 1; i >= 0; i--) { |
| 4634 cur = xmlXPathNodeSetItem(nodes, i); | 4752 cur = xmlXPathNodeSetItem(nodes, i); |
| 4635 if (cur == node) | 4753 if (cur == node) |
| 4636 break; | 4754 break; |
| 4637 » xmlXPathNodeSetAddUnique(ret, cur); | 4755 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0) |
| 4756 » break; |
| 4638 } | 4757 } |
| 4639 xmlXPathNodeSetSort(ret); /* bug 413451 */ | 4758 xmlXPathNodeSetSort(ret); /* bug 413451 */ |
| 4640 return(ret); | 4759 return(ret); |
| 4641 } | 4760 } |
| 4642 | 4761 |
| 4643 /** | 4762 /** |
| 4644 * xmlXPathNodeTrailing: | 4763 * xmlXPathNodeTrailing: |
| 4645 * @nodes: a node-set | 4764 * @nodes: a node-set |
| 4646 * @node: a node | 4765 * @node: a node |
| 4647 * | 4766 * |
| (...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6147 ret->valueTab = (xmlXPathObjectPtr *) | 6266 ret->valueTab = (xmlXPathObjectPtr *) |
| 6148 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); | 6267 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); |
| 6149 if (ret->valueTab == NULL) { | 6268 if (ret->valueTab == NULL) { |
| 6150 xmlFree(ret); | 6269 xmlFree(ret); |
| 6151 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); | 6270 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); |
| 6152 return(NULL); | 6271 return(NULL); |
| 6153 } | 6272 } |
| 6154 ret->valueNr = 0; | 6273 ret->valueNr = 0; |
| 6155 ret->valueMax = 10; | 6274 ret->valueMax = 10; |
| 6156 ret->value = NULL; | 6275 ret->value = NULL; |
| 6276 ret->valueFrame = 0; |
| 6157 | 6277 |
| 6158 ret->context = ctxt; | 6278 ret->context = ctxt; |
| 6159 ret->comp = comp; | 6279 ret->comp = comp; |
| 6160 | 6280 |
| 6161 return(ret); | 6281 return(ret); |
| 6162 } | 6282 } |
| 6163 | 6283 |
| 6164 /** | 6284 /** |
| 6165 * xmlXPathFreeParserContext: | 6285 * xmlXPathFreeParserContext: |
| 6166 * @ctxt: the context to free | 6286 * @ctxt: the context to free |
| (...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7649 return(cur->next); | 7769 return(cur->next); |
| 7650 cur = cur->next; | 7770 cur = cur->next; |
| 7651 do { | 7771 do { |
| 7652 cur = cur->next; | 7772 cur = cur->next; |
| 7653 } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE)); | 7773 } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE)); |
| 7654 return(cur); | 7774 return(cur); |
| 7655 } | 7775 } |
| 7656 return(NULL); | 7776 return(NULL); |
| 7657 } | 7777 } |
| 7658 | 7778 |
| 7779 #if 0 |
| 7659 /** | 7780 /** |
| 7660 * xmlXPathNextDescendantOrSelfElemParent: | 7781 * xmlXPathNextDescendantOrSelfElemParent: |
| 7661 * @ctxt: the XPath Parser context | 7782 * @ctxt: the XPath Parser context |
| 7662 * @cur: the current node in the traversal | 7783 * @cur: the current node in the traversal |
| 7663 * | 7784 * |
| 7664 * Traversal function for the "descendant-or-self" axis. | 7785 * Traversal function for the "descendant-or-self" axis. |
| 7665 * Additionally it returns only nodes which can be parents of | 7786 * Additionally it returns only nodes which can be parents of |
| 7666 * element nodes. | 7787 * element nodes. |
| 7667 * | 7788 * |
| 7668 * | 7789 * |
| 7669 * Returns the next element following that axis | 7790 * Returns the next element following that axis |
| 7670 */ | 7791 */ |
| 7671 static xmlNodePtr | 7792 static xmlNodePtr |
| 7672 xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur, | 7793 xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur, |
| 7673 xmlNodePtr contextNode) | 7794 xmlNodePtr contextNode) |
| 7674 { | 7795 { |
| 7675 if (cur == NULL) { | 7796 if (cur == NULL) { |
| 7676 if (contextNode == NULL) | 7797 if (contextNode == NULL) |
| 7677 return(NULL); | 7798 return(NULL); |
| 7678 switch (contextNode->type) { | 7799 switch (contextNode->type) { |
| 7679 case XML_ELEMENT_NODE: | 7800 case XML_ELEMENT_NODE: |
| 7680 case XML_XINCLUDE_START: | 7801 case XML_XINCLUDE_START: |
| 7681 case XML_DOCUMENT_FRAG_NODE: | 7802 case XML_DOCUMENT_FRAG_NODE: |
| 7682 case XML_DOCUMENT_NODE: | 7803 case XML_DOCUMENT_NODE: |
| 7683 #ifdef LIBXML_DOCB_ENABLED | 7804 #ifdef LIBXML_DOCB_ENABLED |
| 7684 case XML_DOCB_DOCUMENT_NODE: | 7805 case XML_DOCB_DOCUMENT_NODE: |
| 7685 #endif | 7806 #endif |
| 7686 » case XML_HTML_DOCUMENT_NODE:» | 7807 » case XML_HTML_DOCUMENT_NODE: |
| 7687 return(contextNode); | 7808 return(contextNode); |
| 7688 default: | 7809 default: |
| 7689 return(NULL); | 7810 return(NULL); |
| 7690 } | 7811 } |
| 7691 return(NULL); | 7812 return(NULL); |
| 7692 } else { | 7813 } else { |
| 7693 xmlNodePtr start = cur; | 7814 xmlNodePtr start = cur; |
| 7694 | 7815 |
| 7695 while (cur != NULL) { | 7816 while (cur != NULL) { |
| 7696 switch (cur->type) { | 7817 switch (cur->type) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 7724 if (cur->next != NULL) { | 7845 if (cur->next != NULL) { |
| 7725 cur = cur->next; | 7846 cur = cur->next; |
| 7726 } else { | 7847 } else { |
| 7727 cur = cur->parent; | 7848 cur = cur->parent; |
| 7728 goto next_sibling; | 7849 goto next_sibling; |
| 7729 } | 7850 } |
| 7730 } | 7851 } |
| 7731 } | 7852 } |
| 7732 return(NULL); | 7853 return(NULL); |
| 7733 } | 7854 } |
| 7855 #endif |
| 7734 | 7856 |
| 7735 /** | 7857 /** |
| 7736 * xmlXPathNextDescendant: | 7858 * xmlXPathNextDescendant: |
| 7737 * @ctxt: the XPath Parser context | 7859 * @ctxt: the XPath Parser context |
| 7738 * @cur: the current node in the traversal | 7860 * @cur: the current node in the traversal |
| 7739 * | 7861 * |
| 7740 * Traversal function for the "descendant" direction | 7862 * Traversal function for the "descendant" direction |
| 7741 * the descendant axis contains the descendants of the context node in document | 7863 * the descendant axis contains the descendants of the context node in document |
| 7742 * order; a descendant is a child or a child of a child and so on. | 7864 * order; a descendant is a child or a child of a child and so on. |
| 7743 * | 7865 * |
| 7744 * Returns the next element following that axis | 7866 * Returns the next element following that axis |
| 7745 */ | 7867 */ |
| 7746 xmlNodePtr | 7868 xmlNodePtr |
| 7747 xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { | 7869 xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { |
| 7748 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); | 7870 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); |
| 7749 if (cur == NULL) { | 7871 if (cur == NULL) { |
| 7750 if (ctxt->context->node == NULL) | 7872 if (ctxt->context->node == NULL) |
| 7751 return(NULL); | 7873 return(NULL); |
| 7752 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || | 7874 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || |
| 7753 (ctxt->context->node->type == XML_NAMESPACE_DECL)) | 7875 (ctxt->context->node->type == XML_NAMESPACE_DECL)) |
| 7754 return(NULL); | 7876 return(NULL); |
| 7755 | 7877 |
| 7756 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) | 7878 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) |
| 7757 return(ctxt->context->doc->children); | 7879 return(ctxt->context->doc->children); |
| 7758 return(ctxt->context->node->children); | 7880 return(ctxt->context->node->children); |
| 7759 } | 7881 } |
| 7760 | 7882 |
| 7883 if (cur->type == XML_NAMESPACE_DECL) |
| 7884 return(NULL); |
| 7761 if (cur->children != NULL) { | 7885 if (cur->children != NULL) { |
| 7762 /* | 7886 /* |
| 7763 * Do not descend on entities declarations | 7887 * Do not descend on entities declarations |
| 7764 */ | 7888 */ |
| 7765 if (cur->children->type != XML_ENTITY_DECL) { | 7889 if (cur->children->type != XML_ENTITY_DECL) { |
| 7766 cur = cur->children; | 7890 cur = cur->children; |
| 7767 /* | 7891 /* |
| 7768 * Skip DTDs | 7892 * Skip DTDs |
| 7769 */ | 7893 */ |
| 7770 if (cur->type != XML_DTD_NODE) | 7894 if (cur->type != XML_DTD_NODE) |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8133 * @ancestor: the ancestor node | 8257 * @ancestor: the ancestor node |
| 8134 * @node: the current node | 8258 * @node: the current node |
| 8135 * | 8259 * |
| 8136 * Check that @ancestor is a @node's ancestor | 8260 * Check that @ancestor is a @node's ancestor |
| 8137 * | 8261 * |
| 8138 * returns 1 if @ancestor is a @node's ancestor, 0 otherwise. | 8262 * returns 1 if @ancestor is a @node's ancestor, 0 otherwise. |
| 8139 */ | 8263 */ |
| 8140 static int | 8264 static int |
| 8141 xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) { | 8265 xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) { |
| 8142 if ((ancestor == NULL) || (node == NULL)) return(0); | 8266 if ((ancestor == NULL) || (node == NULL)) return(0); |
| 8267 if (node->type == XML_NAMESPACE_DECL) |
| 8268 return(0); |
| 8269 if (ancestor->type == XML_NAMESPACE_DECL) |
| 8270 return(0); |
| 8143 /* nodes need to be in the same document */ | 8271 /* nodes need to be in the same document */ |
| 8144 if (ancestor->doc != node->doc) return(0); | 8272 if (ancestor->doc != node->doc) return(0); |
| 8145 /* avoid searching if ancestor or node is the root node */ | 8273 /* avoid searching if ancestor or node is the root node */ |
| 8146 if (ancestor == (xmlNodePtr) node->doc) return(1); | 8274 if (ancestor == (xmlNodePtr) node->doc) return(1); |
| 8147 if (node == (xmlNodePtr) ancestor->doc) return(0); | 8275 if (node == (xmlNodePtr) ancestor->doc) return(0); |
| 8148 while (node->parent != NULL) { | 8276 while (node->parent != NULL) { |
| 8149 if (node->parent == ancestor) | 8277 if (node->parent == ancestor) |
| 8150 return(1); | 8278 return(1); |
| 8151 node = node->parent; | 8279 node = node->parent; |
| 8152 } | 8280 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8170 xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) | 8298 xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) |
| 8171 { | 8299 { |
| 8172 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); | 8300 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); |
| 8173 if (cur == NULL) { | 8301 if (cur == NULL) { |
| 8174 cur = ctxt->context->node; | 8302 cur = ctxt->context->node; |
| 8175 if (cur->type == XML_NAMESPACE_DECL) | 8303 if (cur->type == XML_NAMESPACE_DECL) |
| 8176 return(NULL); | 8304 return(NULL); |
| 8177 if (cur->type == XML_ATTRIBUTE_NODE) | 8305 if (cur->type == XML_ATTRIBUTE_NODE) |
| 8178 return(cur->parent); | 8306 return(cur->parent); |
| 8179 } | 8307 } |
| 8180 if (cur == NULL) | 8308 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) |
| 8181 return (NULL); | 8309 return (NULL); |
| 8182 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) | 8310 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) |
| 8183 cur = cur->prev; | 8311 cur = cur->prev; |
| 8184 do { | 8312 do { |
| 8185 if (cur->prev != NULL) { | 8313 if (cur->prev != NULL) { |
| 8186 for (cur = cur->prev; cur->last != NULL; cur = cur->last) ; | 8314 for (cur = cur->prev; cur->last != NULL; cur = cur->last) ; |
| 8187 return (cur); | 8315 return (cur); |
| 8188 } | 8316 } |
| 8189 | 8317 |
| 8190 cur = cur->parent; | 8318 cur = cur->parent; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 8217 { | 8345 { |
| 8218 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); | 8346 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); |
| 8219 if (cur == NULL) { | 8347 if (cur == NULL) { |
| 8220 cur = ctxt->context->node; | 8348 cur = ctxt->context->node; |
| 8221 if (cur == NULL) | 8349 if (cur == NULL) |
| 8222 return (NULL); | 8350 return (NULL); |
| 8223 if (cur->type == XML_NAMESPACE_DECL) | 8351 if (cur->type == XML_NAMESPACE_DECL) |
| 8224 return (NULL); | 8352 return (NULL); |
| 8225 ctxt->ancestor = cur->parent; | 8353 ctxt->ancestor = cur->parent; |
| 8226 } | 8354 } |
| 8355 if (cur->type == XML_NAMESPACE_DECL) |
| 8356 return(NULL); |
| 8227 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) | 8357 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) |
| 8228 cur = cur->prev; | 8358 cur = cur->prev; |
| 8229 while (cur->prev == NULL) { | 8359 while (cur->prev == NULL) { |
| 8230 cur = cur->parent; | 8360 cur = cur->parent; |
| 8231 if (cur == NULL) | 8361 if (cur == NULL) |
| 8232 return (NULL); | 8362 return (NULL); |
| 8233 if (cur == ctxt->context->doc->children) | 8363 if (cur == ctxt->context->doc->children) |
| 8234 return (NULL); | 8364 return (NULL); |
| 8235 if (cur != ctxt->ancestor) | 8365 if (cur != ctxt->ancestor) |
| 8236 return (cur); | 8366 return (cur); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8424 (double) cur->nodesetval->nodeNr)); | 8554 (double) cur->nodesetval->nodeNr)); |
| 8425 } else { | 8555 } else { |
| 8426 if ((cur->nodesetval->nodeNr != 1) || | 8556 if ((cur->nodesetval->nodeNr != 1) || |
| 8427 (cur->nodesetval->nodeTab == NULL)) { | 8557 (cur->nodesetval->nodeTab == NULL)) { |
| 8428 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); | 8558 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); |
| 8429 } else { | 8559 } else { |
| 8430 xmlNodePtr tmp; | 8560 xmlNodePtr tmp; |
| 8431 int i = 0; | 8561 int i = 0; |
| 8432 | 8562 |
| 8433 tmp = cur->nodesetval->nodeTab[0]; | 8563 tmp = cur->nodesetval->nodeTab[0]; |
| 8434 » if (tmp != NULL) { | 8564 » if ((tmp != NULL) && (tmp->type != XML_NAMESPACE_DECL)) { |
| 8435 tmp = tmp->children; | 8565 tmp = tmp->children; |
| 8436 while (tmp != NULL) { | 8566 while (tmp != NULL) { |
| 8437 tmp = tmp->next; | 8567 tmp = tmp->next; |
| 8438 i++; | 8568 i++; |
| 8439 } | 8569 } |
| 8440 } | 8570 } |
| 8441 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) i)); | 8571 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) i)); |
| 8442 } | 8572 } |
| 8443 } | 8573 } |
| 8444 xmlXPathReleaseObject(ctxt->context, cur); | 8574 xmlXPathReleaseObject(ctxt->context, cur); |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9094 * The substring-before function returns the substring of the first | 9224 * The substring-before function returns the substring of the first |
| 9095 * argument string that precedes the first occurrence of the second | 9225 * argument string that precedes the first occurrence of the second |
| 9096 * argument string in the first argument string, or the empty string | 9226 * argument string in the first argument string, or the empty string |
| 9097 * if the first argument string does not contain the second argument | 9227 * if the first argument string does not contain the second argument |
| 9098 * string. For example, substring-before("1999/04/01","/") returns 1999. | 9228 * string. For example, substring-before("1999/04/01","/") returns 1999. |
| 9099 */ | 9229 */ |
| 9100 void | 9230 void |
| 9101 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9231 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
| 9102 xmlXPathObjectPtr str; | 9232 xmlXPathObjectPtr str; |
| 9103 xmlXPathObjectPtr find; | 9233 xmlXPathObjectPtr find; |
| 9104 xmlBufferPtr target; | 9234 xmlBufPtr target; |
| 9105 const xmlChar *point; | 9235 const xmlChar *point; |
| 9106 int offset; | 9236 int offset; |
| 9107 | 9237 |
| 9108 CHECK_ARITY(2); | 9238 CHECK_ARITY(2); |
| 9109 CAST_TO_STRING; | 9239 CAST_TO_STRING; |
| 9110 find = valuePop(ctxt); | 9240 find = valuePop(ctxt); |
| 9111 CAST_TO_STRING; | 9241 CAST_TO_STRING; |
| 9112 str = valuePop(ctxt); | 9242 str = valuePop(ctxt); |
| 9113 | 9243 |
| 9114 target = xmlBufferCreate(); | 9244 target = xmlBufCreate(); |
| 9115 if (target) { | 9245 if (target) { |
| 9116 point = xmlStrstr(str->stringval, find->stringval); | 9246 point = xmlStrstr(str->stringval, find->stringval); |
| 9117 if (point) { | 9247 if (point) { |
| 9118 offset = (int)(point - str->stringval); | 9248 offset = (int)(point - str->stringval); |
| 9119 xmlBufferAdd(target, str->stringval, offset); | 9249 xmlBufAdd(target, str->stringval, offset); |
| 9120 } | 9250 } |
| 9121 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 9251 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
| 9122 » xmlBufferContent(target))); | 9252 » xmlBufContent(target))); |
| 9123 xmlBufferFree(target); | 9253 xmlBufFree(target); |
| 9124 } | 9254 } |
| 9125 xmlXPathReleaseObject(ctxt->context, str); | 9255 xmlXPathReleaseObject(ctxt->context, str); |
| 9126 xmlXPathReleaseObject(ctxt->context, find); | 9256 xmlXPathReleaseObject(ctxt->context, find); |
| 9127 } | 9257 } |
| 9128 | 9258 |
| 9129 /** | 9259 /** |
| 9130 * xmlXPathSubstringAfterFunction: | 9260 * xmlXPathSubstringAfterFunction: |
| 9131 * @ctxt: the XPath Parser context | 9261 * @ctxt: the XPath Parser context |
| 9132 * @nargs: the number of arguments | 9262 * @nargs: the number of arguments |
| 9133 * | 9263 * |
| 9134 * Implement the substring-after() XPath function | 9264 * Implement the substring-after() XPath function |
| 9135 * string substring-after(string, string) | 9265 * string substring-after(string, string) |
| 9136 * The substring-after function returns the substring of the first | 9266 * The substring-after function returns the substring of the first |
| 9137 * argument string that follows the first occurrence of the second | 9267 * argument string that follows the first occurrence of the second |
| 9138 * argument string in the first argument string, or the empty stringi | 9268 * argument string in the first argument string, or the empty stringi |
| 9139 * if the first argument string does not contain the second argument | 9269 * if the first argument string does not contain the second argument |
| 9140 * string. For example, substring-after("1999/04/01","/") returns 04/01, | 9270 * string. For example, substring-after("1999/04/01","/") returns 04/01, |
| 9141 * and substring-after("1999/04/01","19") returns 99/04/01. | 9271 * and substring-after("1999/04/01","19") returns 99/04/01. |
| 9142 */ | 9272 */ |
| 9143 void | 9273 void |
| 9144 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9274 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
| 9145 xmlXPathObjectPtr str; | 9275 xmlXPathObjectPtr str; |
| 9146 xmlXPathObjectPtr find; | 9276 xmlXPathObjectPtr find; |
| 9147 xmlBufferPtr target; | 9277 xmlBufPtr target; |
| 9148 const xmlChar *point; | 9278 const xmlChar *point; |
| 9149 int offset; | 9279 int offset; |
| 9150 | 9280 |
| 9151 CHECK_ARITY(2); | 9281 CHECK_ARITY(2); |
| 9152 CAST_TO_STRING; | 9282 CAST_TO_STRING; |
| 9153 find = valuePop(ctxt); | 9283 find = valuePop(ctxt); |
| 9154 CAST_TO_STRING; | 9284 CAST_TO_STRING; |
| 9155 str = valuePop(ctxt); | 9285 str = valuePop(ctxt); |
| 9156 | 9286 |
| 9157 target = xmlBufferCreate(); | 9287 target = xmlBufCreate(); |
| 9158 if (target) { | 9288 if (target) { |
| 9159 point = xmlStrstr(str->stringval, find->stringval); | 9289 point = xmlStrstr(str->stringval, find->stringval); |
| 9160 if (point) { | 9290 if (point) { |
| 9161 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval); | 9291 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval); |
| 9162 xmlBufferAdd(target, &str->stringval[offset], | 9292 xmlBufAdd(target, &str->stringval[offset], |
| 9163 xmlStrlen(str->stringval) - offset); | 9293 xmlStrlen(str->stringval) - offset); |
| 9164 } | 9294 } |
| 9165 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 9295 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
| 9166 » xmlBufferContent(target))); | 9296 » xmlBufContent(target))); |
| 9167 xmlBufferFree(target); | 9297 xmlBufFree(target); |
| 9168 } | 9298 } |
| 9169 xmlXPathReleaseObject(ctxt->context, str); | 9299 xmlXPathReleaseObject(ctxt->context, str); |
| 9170 xmlXPathReleaseObject(ctxt->context, find); | 9300 xmlXPathReleaseObject(ctxt->context, find); |
| 9171 } | 9301 } |
| 9172 | 9302 |
| 9173 /** | 9303 /** |
| 9174 * xmlXPathNormalizeFunction: | 9304 * xmlXPathNormalizeFunction: |
| 9175 * @ctxt: the XPath Parser context | 9305 * @ctxt: the XPath Parser context |
| 9176 * @nargs: the number of arguments | 9306 * @nargs: the number of arguments |
| 9177 * | 9307 * |
| 9178 * Implement the normalize-space() XPath function | 9308 * Implement the normalize-space() XPath function |
| 9179 * string normalize-space(string?) | 9309 * string normalize-space(string?) |
| 9180 * The normalize-space function returns the argument string with white | 9310 * The normalize-space function returns the argument string with white |
| 9181 * space normalized by stripping leading and trailing whitespace | 9311 * space normalized by stripping leading and trailing whitespace |
| 9182 * and replacing sequences of whitespace characters by a single | 9312 * and replacing sequences of whitespace characters by a single |
| 9183 * space. Whitespace characters are the same allowed by the S production | 9313 * space. Whitespace characters are the same allowed by the S production |
| 9184 * in XML. If the argument is omitted, it defaults to the context | 9314 * in XML. If the argument is omitted, it defaults to the context |
| 9185 * node converted to a string, in other words the value of the context node. | 9315 * node converted to a string, in other words the value of the context node. |
| 9186 */ | 9316 */ |
| 9187 void | 9317 void |
| 9188 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9318 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
| 9189 xmlXPathObjectPtr obj = NULL; | 9319 xmlXPathObjectPtr obj = NULL; |
| 9190 xmlChar *source = NULL; | 9320 xmlChar *source = NULL; |
| 9191 xmlBufferPtr target; | 9321 xmlBufPtr target; |
| 9192 xmlChar blank; | 9322 xmlChar blank; |
| 9193 | 9323 |
| 9194 if (ctxt == NULL) return; | 9324 if (ctxt == NULL) return; |
| 9195 if (nargs == 0) { | 9325 if (nargs == 0) { |
| 9196 /* Use current context node */ | 9326 /* Use current context node */ |
| 9197 valuePush(ctxt, | 9327 valuePush(ctxt, |
| 9198 xmlXPathCacheWrapString(ctxt->context, | 9328 xmlXPathCacheWrapString(ctxt->context, |
| 9199 xmlXPathCastNodeToString(ctxt->context->node))); | 9329 xmlXPathCastNodeToString(ctxt->context->node))); |
| 9200 nargs = 1; | 9330 nargs = 1; |
| 9201 } | 9331 } |
| 9202 | 9332 |
| 9203 CHECK_ARITY(1); | 9333 CHECK_ARITY(1); |
| 9204 CAST_TO_STRING; | 9334 CAST_TO_STRING; |
| 9205 CHECK_TYPE(XPATH_STRING); | 9335 CHECK_TYPE(XPATH_STRING); |
| 9206 obj = valuePop(ctxt); | 9336 obj = valuePop(ctxt); |
| 9207 source = obj->stringval; | 9337 source = obj->stringval; |
| 9208 | 9338 |
| 9209 target = xmlBufferCreate(); | 9339 target = xmlBufCreate(); |
| 9210 if (target && source) { | 9340 if (target && source) { |
| 9211 | 9341 |
| 9212 /* Skip leading whitespaces */ | 9342 /* Skip leading whitespaces */ |
| 9213 while (IS_BLANK_CH(*source)) | 9343 while (IS_BLANK_CH(*source)) |
| 9214 source++; | 9344 source++; |
| 9215 | 9345 |
| 9216 /* Collapse intermediate whitespaces, and skip trailing whitespaces */ | 9346 /* Collapse intermediate whitespaces, and skip trailing whitespaces */ |
| 9217 blank = 0; | 9347 blank = 0; |
| 9218 while (*source) { | 9348 while (*source) { |
| 9219 if (IS_BLANK_CH(*source)) { | 9349 if (IS_BLANK_CH(*source)) { |
| 9220 blank = 0x20; | 9350 blank = 0x20; |
| 9221 } else { | 9351 } else { |
| 9222 if (blank) { | 9352 if (blank) { |
| 9223 » xmlBufferAdd(target, &blank, 1); | 9353 » xmlBufAdd(target, &blank, 1); |
| 9224 blank = 0; | 9354 blank = 0; |
| 9225 } | 9355 } |
| 9226 » xmlBufferAdd(target, source, 1); | 9356 » xmlBufAdd(target, source, 1); |
| 9227 } | 9357 } |
| 9228 source++; | 9358 source++; |
| 9229 } | 9359 } |
| 9230 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 9360 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
| 9231 » xmlBufferContent(target))); | 9361 » xmlBufContent(target))); |
| 9232 xmlBufferFree(target); | 9362 xmlBufFree(target); |
| 9233 } | 9363 } |
| 9234 xmlXPathReleaseObject(ctxt->context, obj); | 9364 xmlXPathReleaseObject(ctxt->context, obj); |
| 9235 } | 9365 } |
| 9236 | 9366 |
| 9237 /** | 9367 /** |
| 9238 * xmlXPathTranslateFunction: | 9368 * xmlXPathTranslateFunction: |
| 9239 * @ctxt: the XPath Parser context | 9369 * @ctxt: the XPath Parser context |
| 9240 * @nargs: the number of arguments | 9370 * @nargs: the number of arguments |
| 9241 * | 9371 * |
| 9242 * Implement the translate() XPath function | 9372 * Implement the translate() XPath function |
| (...skipping 10 matching lines...) Expand all Loading... |
| 9253 * returns "AAA". If a character occurs more than once in second | 9383 * returns "AAA". If a character occurs more than once in second |
| 9254 * argument string, then the first occurrence determines the replacement | 9384 * argument string, then the first occurrence determines the replacement |
| 9255 * character. If the third argument string is longer than the second | 9385 * character. If the third argument string is longer than the second |
| 9256 * argument string, then excess characters are ignored. | 9386 * argument string, then excess characters are ignored. |
| 9257 */ | 9387 */ |
| 9258 void | 9388 void |
| 9259 xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9389 xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
| 9260 xmlXPathObjectPtr str; | 9390 xmlXPathObjectPtr str; |
| 9261 xmlXPathObjectPtr from; | 9391 xmlXPathObjectPtr from; |
| 9262 xmlXPathObjectPtr to; | 9392 xmlXPathObjectPtr to; |
| 9263 xmlBufferPtr target; | 9393 xmlBufPtr target; |
| 9264 int offset, max; | 9394 int offset, max; |
| 9265 xmlChar ch; | 9395 xmlChar ch; |
| 9266 const xmlChar *point; | 9396 const xmlChar *point; |
| 9267 xmlChar *cptr; | 9397 xmlChar *cptr; |
| 9268 | 9398 |
| 9269 CHECK_ARITY(3); | 9399 CHECK_ARITY(3); |
| 9270 | 9400 |
| 9271 CAST_TO_STRING; | 9401 CAST_TO_STRING; |
| 9272 to = valuePop(ctxt); | 9402 to = valuePop(ctxt); |
| 9273 CAST_TO_STRING; | 9403 CAST_TO_STRING; |
| 9274 from = valuePop(ctxt); | 9404 from = valuePop(ctxt); |
| 9275 CAST_TO_STRING; | 9405 CAST_TO_STRING; |
| 9276 str = valuePop(ctxt); | 9406 str = valuePop(ctxt); |
| 9277 | 9407 |
| 9278 target = xmlBufferCreate(); | 9408 target = xmlBufCreate(); |
| 9279 if (target) { | 9409 if (target) { |
| 9280 max = xmlUTF8Strlen(to->stringval); | 9410 max = xmlUTF8Strlen(to->stringval); |
| 9281 for (cptr = str->stringval; (ch=*cptr); ) { | 9411 for (cptr = str->stringval; (ch=*cptr); ) { |
| 9282 offset = xmlUTF8Strloc(from->stringval, cptr); | 9412 offset = xmlUTF8Strloc(from->stringval, cptr); |
| 9283 if (offset >= 0) { | 9413 if (offset >= 0) { |
| 9284 if (offset < max) { | 9414 if (offset < max) { |
| 9285 point = xmlUTF8Strpos(to->stringval, offset); | 9415 point = xmlUTF8Strpos(to->stringval, offset); |
| 9286 if (point) | 9416 if (point) |
| 9287 » » » xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1)); | 9417 » » » xmlBufAdd(target, point, xmlUTF8Strsize(point, 1)); |
| 9288 } | 9418 } |
| 9289 } else | 9419 } else |
| 9290 » » xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1)); | 9420 » » xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1)); |
| 9291 | 9421 |
| 9292 /* Step to next character in input */ | 9422 /* Step to next character in input */ |
| 9293 cptr++; | 9423 cptr++; |
| 9294 if ( ch & 0x80 ) { | 9424 if ( ch & 0x80 ) { |
| 9295 /* if not simple ascii, verify proper format */ | 9425 /* if not simple ascii, verify proper format */ |
| 9296 if ( (ch & 0xc0) != 0xc0 ) { | 9426 if ( (ch & 0xc0) != 0xc0 ) { |
| 9297 xmlGenericError(xmlGenericErrorContext, | 9427 xmlGenericError(xmlGenericErrorContext, |
| 9298 "xmlXPathTranslateFunction: Invalid UTF8 string\n"); | 9428 "xmlXPathTranslateFunction: Invalid UTF8 string\n"); |
| 9429 /* not asserting an XPath error is probably better */ |
| 9299 break; | 9430 break; |
| 9300 } | 9431 } |
| 9301 /* then skip over remaining bytes for this char */ | 9432 /* then skip over remaining bytes for this char */ |
| 9302 while ( (ch <<= 1) & 0x80 ) | 9433 while ( (ch <<= 1) & 0x80 ) |
| 9303 if ( (*cptr++ & 0xc0) != 0x80 ) { | 9434 if ( (*cptr++ & 0xc0) != 0x80 ) { |
| 9304 xmlGenericError(xmlGenericErrorContext, | 9435 xmlGenericError(xmlGenericErrorContext, |
| 9305 "xmlXPathTranslateFunction: Invalid UTF8 string\n"); | 9436 "xmlXPathTranslateFunction: Invalid UTF8 string\n"); |
| 9437 /* not asserting an XPath error is probably better */ |
| 9306 break; | 9438 break; |
| 9307 } | 9439 } |
| 9308 if (ch & 0x80) /* must have had error encountered */ | 9440 if (ch & 0x80) /* must have had error encountered */ |
| 9309 break; | 9441 break; |
| 9310 } | 9442 } |
| 9311 } | 9443 } |
| 9312 } | 9444 } |
| 9313 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 9445 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
| 9314 » xmlBufferContent(target))); | 9446 » xmlBufContent(target))); |
| 9315 xmlBufferFree(target); | 9447 xmlBufFree(target); |
| 9316 xmlXPathReleaseObject(ctxt->context, str); | 9448 xmlXPathReleaseObject(ctxt->context, str); |
| 9317 xmlXPathReleaseObject(ctxt->context, from); | 9449 xmlXPathReleaseObject(ctxt->context, from); |
| 9318 xmlXPathReleaseObject(ctxt->context, to); | 9450 xmlXPathReleaseObject(ctxt->context, to); |
| 9319 } | 9451 } |
| 9320 | 9452 |
| 9321 /** | 9453 /** |
| 9322 * xmlXPathBooleanFunction: | 9454 * xmlXPathBooleanFunction: |
| 9323 * @ctxt: the XPath Parser context | 9455 * @ctxt: the XPath Parser context |
| 9324 * @nargs: the number of arguments | 9456 * @nargs: the number of arguments |
| 9325 * | 9457 * |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9812 * | 9944 * |
| 9813 * [5] Name ::= (Letter | '_' | ':') (NameChar)* | 9945 * [5] Name ::= (Letter | '_' | ':') (NameChar)* |
| 9814 * | 9946 * |
| 9815 * Returns the namespace name or NULL | 9947 * Returns the namespace name or NULL |
| 9816 */ | 9948 */ |
| 9817 | 9949 |
| 9818 xmlChar * | 9950 xmlChar * |
| 9819 xmlXPathParseName(xmlXPathParserContextPtr ctxt) { | 9951 xmlXPathParseName(xmlXPathParserContextPtr ctxt) { |
| 9820 const xmlChar *in; | 9952 const xmlChar *in; |
| 9821 xmlChar *ret; | 9953 xmlChar *ret; |
| 9822 int count = 0; | 9954 size_t count = 0; |
| 9823 | 9955 |
| 9824 if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL); | 9956 if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL); |
| 9825 /* | 9957 /* |
| 9826 * Accelerator for simple ASCII names | 9958 * Accelerator for simple ASCII names |
| 9827 */ | 9959 */ |
| 9828 in = ctxt->cur; | 9960 in = ctxt->cur; |
| 9829 if (((*in >= 0x61) && (*in <= 0x7A)) || | 9961 if (((*in >= 0x61) && (*in <= 0x7A)) || |
| 9830 ((*in >= 0x41) && (*in <= 0x5A)) || | 9962 ((*in >= 0x41) && (*in <= 0x5A)) || |
| 9831 (*in == '_') || (*in == ':')) { | 9963 (*in == '_') || (*in == ':')) { |
| 9832 in++; | 9964 in++; |
| 9833 while (((*in >= 0x61) && (*in <= 0x7A)) || | 9965 while (((*in >= 0x61) && (*in <= 0x7A)) || |
| 9834 ((*in >= 0x41) && (*in <= 0x5A)) || | 9966 ((*in >= 0x41) && (*in <= 0x5A)) || |
| 9835 ((*in >= 0x30) && (*in <= 0x39)) || | 9967 ((*in >= 0x30) && (*in <= 0x39)) || |
| 9836 (*in == '_') || (*in == '-') || | 9968 (*in == '_') || (*in == '-') || |
| 9837 (*in == ':') || (*in == '.')) | 9969 (*in == ':') || (*in == '.')) |
| 9838 in++; | 9970 in++; |
| 9839 if ((*in > 0) && (*in < 0x80)) { | 9971 if ((*in > 0) && (*in < 0x80)) { |
| 9840 count = in - ctxt->cur; | 9972 count = in - ctxt->cur; |
| 9973 if (count > XML_MAX_NAME_LENGTH) { |
| 9974 ctxt->cur = in; |
| 9975 XP_ERRORNULL(XPATH_EXPR_ERROR); |
| 9976 } |
| 9841 ret = xmlStrndup(ctxt->cur, count); | 9977 ret = xmlStrndup(ctxt->cur, count); |
| 9842 ctxt->cur = in; | 9978 ctxt->cur = in; |
| 9843 return(ret); | 9979 return(ret); |
| 9844 } | 9980 } |
| 9845 } | 9981 } |
| 9846 return(xmlXPathParseNameComplex(ctxt, 1)); | 9982 return(xmlXPathParseNameComplex(ctxt, 1)); |
| 9847 } | 9983 } |
| 9848 | 9984 |
| 9849 static xmlChar * | 9985 static xmlChar * |
| 9850 xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { | 9986 xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 9874 NEXTL(l); | 10010 NEXTL(l); |
| 9875 c = CUR_CHAR(l); | 10011 c = CUR_CHAR(l); |
| 9876 if (len >= XML_MAX_NAMELEN) { | 10012 if (len >= XML_MAX_NAMELEN) { |
| 9877 /* | 10013 /* |
| 9878 * Okay someone managed to make a huge name, so he's ready to pay | 10014 * Okay someone managed to make a huge name, so he's ready to pay |
| 9879 * for the processing speed. | 10015 * for the processing speed. |
| 9880 */ | 10016 */ |
| 9881 xmlChar *buffer; | 10017 xmlChar *buffer; |
| 9882 int max = len * 2; | 10018 int max = len * 2; |
| 9883 | 10019 |
| 10020 if (len > XML_MAX_NAME_LENGTH) { |
| 10021 XP_ERRORNULL(XPATH_EXPR_ERROR); |
| 10022 } |
| 9884 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); | 10023 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); |
| 9885 if (buffer == NULL) { | 10024 if (buffer == NULL) { |
| 9886 XP_ERRORNULL(XPATH_MEMORY_ERROR); | 10025 XP_ERRORNULL(XPATH_MEMORY_ERROR); |
| 9887 } | 10026 } |
| 9888 memcpy(buffer, buf, len); | 10027 memcpy(buffer, buf, len); |
| 9889 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ | 10028 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ |
| 9890 (c == '.') || (c == '-') || | 10029 (c == '.') || (c == '-') || |
| 9891 (c == '_') || ((qualified) && (c == ':')) || | 10030 (c == '_') || ((qualified) && (c == ':')) || |
| 9892 (IS_COMBINING(c)) || | 10031 (IS_COMBINING(c)) || |
| 9893 (IS_EXTENDER(c))) { | 10032 (IS_EXTENDER(c))) { |
| 9894 if (len + 10 > max) { | 10033 if (len + 10 > max) { |
| 10034 if (max > XML_MAX_NAME_LENGTH) { |
| 10035 XP_ERRORNULL(XPATH_EXPR_ERROR); |
| 10036 } |
| 9895 max *= 2; | 10037 max *= 2; |
| 9896 buffer = (xmlChar *) xmlRealloc(buffer, | 10038 buffer = (xmlChar *) xmlRealloc(buffer, |
| 9897 max * sizeof(xmlChar)); | 10039 max * sizeof(xmlChar)); |
| 9898 if (buffer == NULL) { | 10040 if (buffer == NULL) { |
| 9899 XP_ERRORNULL(XPATH_MEMORY_ERROR); | 10041 XP_ERRORNULL(XPATH_MEMORY_ERROR); |
| 9900 } | 10042 } |
| 9901 } | 10043 } |
| 9902 COPY_BUF(l,buffer,len,c); | 10044 COPY_BUF(l,buffer,len,c); |
| 9903 NEXTL(l); | 10045 NEXTL(l); |
| 9904 c = CUR_CHAR(l); | 10046 c = CUR_CHAR(l); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10037 * | '.' Digits | 10179 * | '.' Digits |
| 10038 * [31] Digits ::= [0-9]+ | 10180 * [31] Digits ::= [0-9]+ |
| 10039 * | 10181 * |
| 10040 * Compile a Number, then push it on the stack | 10182 * Compile a Number, then push it on the stack |
| 10041 * | 10183 * |
| 10042 */ | 10184 */ |
| 10043 static void | 10185 static void |
| 10044 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) | 10186 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) |
| 10045 { | 10187 { |
| 10046 double ret = 0.0; | 10188 double ret = 0.0; |
| 10047 double mult = 1; | |
| 10048 int ok = 0; | 10189 int ok = 0; |
| 10049 int exponent = 0; | 10190 int exponent = 0; |
| 10050 int is_exponent_negative = 0; | 10191 int is_exponent_negative = 0; |
| 10051 #ifdef __GNUC__ | 10192 #ifdef __GNUC__ |
| 10052 unsigned long tmp = 0; | 10193 unsigned long tmp = 0; |
| 10053 double temp; | 10194 double temp; |
| 10054 #endif | 10195 #endif |
| 10055 | 10196 |
| 10056 CHECK_ERROR; | 10197 CHECK_ERROR; |
| 10057 if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) { | 10198 if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 10073 } | 10214 } |
| 10074 #else | 10215 #else |
| 10075 ret = 0; | 10216 ret = 0; |
| 10076 while ((CUR >= '0') && (CUR <= '9')) { | 10217 while ((CUR >= '0') && (CUR <= '9')) { |
| 10077 ret = ret * 10 + (CUR - '0'); | 10218 ret = ret * 10 + (CUR - '0'); |
| 10078 ok = 1; | 10219 ok = 1; |
| 10079 NEXT; | 10220 NEXT; |
| 10080 } | 10221 } |
| 10081 #endif | 10222 #endif |
| 10082 if (CUR == '.') { | 10223 if (CUR == '.') { |
| 10224 int v, frac = 0; |
| 10225 double fraction = 0; |
| 10226 |
| 10083 NEXT; | 10227 NEXT; |
| 10084 if (((CUR < '0') || (CUR > '9')) && (!ok)) { | 10228 if (((CUR < '0') || (CUR > '9')) && (!ok)) { |
| 10085 XP_ERROR(XPATH_NUMBER_ERROR); | 10229 XP_ERROR(XPATH_NUMBER_ERROR); |
| 10086 } | 10230 } |
| 10087 while ((CUR >= '0') && (CUR <= '9')) { | 10231 while ((CUR >= '0') && (CUR <= '9') && (frac < MAX_FRAC)) { |
| 10088 mult /= 10; | 10232 » v = (CUR - '0'); |
| 10089 ret = ret + (CUR - '0') * mult; | 10233 » fraction = fraction * 10 + v; |
| 10234 » frac = frac + 1; |
| 10090 NEXT; | 10235 NEXT; |
| 10091 } | 10236 } |
| 10237 fraction /= my_pow10[frac]; |
| 10238 ret = ret + fraction; |
| 10239 while ((CUR >= '0') && (CUR <= '9')) |
| 10240 NEXT; |
| 10092 } | 10241 } |
| 10093 if ((CUR == 'e') || (CUR == 'E')) { | 10242 if ((CUR == 'e') || (CUR == 'E')) { |
| 10094 NEXT; | 10243 NEXT; |
| 10095 if (CUR == '-') { | 10244 if (CUR == '-') { |
| 10096 is_exponent_negative = 1; | 10245 is_exponent_negative = 1; |
| 10097 NEXT; | 10246 NEXT; |
| 10098 } else if (CUR == '+') { | 10247 } else if (CUR == '+') { |
| 10099 NEXT; | 10248 NEXT; |
| 10100 } | 10249 } |
| 10101 while ((CUR >= '0') && (CUR <= '9')) { | 10250 while ((CUR >= '0') && (CUR <= '9')) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10230 NEXT; | 10379 NEXT; |
| 10231 name = xmlXPathParseQName(ctxt, &prefix); | 10380 name = xmlXPathParseQName(ctxt, &prefix); |
| 10232 if (name == NULL) { | 10381 if (name == NULL) { |
| 10233 XP_ERROR(XPATH_VARIABLE_REF_ERROR); | 10382 XP_ERROR(XPATH_VARIABLE_REF_ERROR); |
| 10234 } | 10383 } |
| 10235 ctxt->comp->last = -1; | 10384 ctxt->comp->last = -1; |
| 10236 PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, | 10385 PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, |
| 10237 name, prefix); | 10386 name, prefix); |
| 10238 SKIP_BLANKS; | 10387 SKIP_BLANKS; |
| 10239 if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) { | 10388 if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) { |
| 10240 » XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR); | 10389 » XP_ERROR(XPATH_FORBID_VARIABLE_ERROR); |
| 10241 } | 10390 } |
| 10242 } | 10391 } |
| 10243 | 10392 |
| 10244 /** | 10393 /** |
| 10245 * xmlXPathIsNodeType: | 10394 * xmlXPathIsNodeType: |
| 10246 * @name: a name string | 10395 * @name: a name string |
| 10247 * | 10396 * |
| 10248 * Is the name given a NodeType one. | 10397 * Is the name given a NodeType one. |
| 10249 * | 10398 * |
| 10250 * [38] NodeType ::= 'comment' | 10399 * [38] NodeType ::= 'comment' |
| (...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11255 axis = AXIS_CHILD; | 11404 axis = AXIS_CHILD; |
| 11256 } | 11405 } |
| 11257 } else if (CUR == '@') { | 11406 } else if (CUR == '@') { |
| 11258 NEXT; | 11407 NEXT; |
| 11259 axis = AXIS_ATTRIBUTE; | 11408 axis = AXIS_ATTRIBUTE; |
| 11260 } else { | 11409 } else { |
| 11261 axis = AXIS_CHILD; | 11410 axis = AXIS_CHILD; |
| 11262 } | 11411 } |
| 11263 } | 11412 } |
| 11264 | 11413 |
| 11265 » CHECK_ERROR; | 11414 if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 11415 xmlFree(name); |
| 11416 return; |
| 11417 } |
| 11266 | 11418 |
| 11267 name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name); | 11419 name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name); |
| 11268 if (test == 0) | 11420 if (test == 0) |
| 11269 return; | 11421 return; |
| 11270 | 11422 |
| 11271 if ((prefix != NULL) && (ctxt->context != NULL) && | 11423 if ((prefix != NULL) && (ctxt->context != NULL) && |
| 11272 (ctxt->context->flags & XML_XPATH_CHECKNS)) { | 11424 (ctxt->context->flags & XML_XPATH_CHECKNS)) { |
| 11273 if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) { | 11425 if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) { |
| 11274 xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR); | 11426 xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR); |
| 11275 } | 11427 } |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11591 if ((contextNode->type != XML_NAMESPACE_DECL) && | 11743 if ((contextNode->type != XML_NAMESPACE_DECL) && |
| 11592 (contextNode->doc != NULL)) | 11744 (contextNode->doc != NULL)) |
| 11593 xpctxt->doc = contextNode->doc; | 11745 xpctxt->doc = contextNode->doc; |
| 11594 /* | 11746 /* |
| 11595 * Evaluate the predicate expression with 1 context node | 11747 * Evaluate the predicate expression with 1 context node |
| 11596 * at a time; this node is packaged into a node set; this | 11748 * at a time; this node is packaged into a node set; this |
| 11597 * node set is handed over to the evaluation mechanism. | 11749 * node set is handed over to the evaluation mechanism. |
| 11598 */ | 11750 */ |
| 11599 if (contextObj == NULL) | 11751 if (contextObj == NULL) |
| 11600 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); | 11752 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); |
| 11601 » else | 11753 » else { |
| 11602 » » xmlXPathNodeSetAddUnique(contextObj->nodesetval, | 11754 » » if (xmlXPathNodeSetAddUnique(contextObj->nodesetval, |
| 11603 » » contextNode); | 11755 » » contextNode) < 0) { |
| 11756 » » ctxt->error = XPATH_MEMORY_ERROR; |
| 11757 » » goto evaluation_exit; |
| 11758 » » } |
| 11759 » } |
| 11604 | 11760 |
| 11605 valuePush(ctxt, contextObj); | 11761 valuePush(ctxt, contextObj); |
| 11606 | 11762 |
| 11607 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); | 11763 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); |
| 11608 | 11764 |
| 11609 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { | 11765 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { |
| 11610 xmlXPathNodeSetClear(set, hasNsNodes); | 11766 xmlXPathNodeSetClear(set, hasNsNodes); |
| 11611 newContextSize = 0; | 11767 newContextSize = 0; |
| 11612 goto evaluation_exit; | 11768 goto evaluation_exit; |
| 11613 } | 11769 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11694 * TODO: Can this ever happen? | 11850 * TODO: Can this ever happen? |
| 11695 */ | 11851 */ |
| 11696 return (contextSize); | 11852 return (contextSize); |
| 11697 } else { | 11853 } else { |
| 11698 xmlDocPtr oldContextDoc; | 11854 xmlDocPtr oldContextDoc; |
| 11699 int i, pos = 0, newContextSize = 0, contextPos = 0, res; | 11855 int i, pos = 0, newContextSize = 0, contextPos = 0, res; |
| 11700 xmlXPathStepOpPtr exprOp; | 11856 xmlXPathStepOpPtr exprOp; |
| 11701 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; | 11857 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; |
| 11702 xmlNodePtr oldContextNode, contextNode = NULL; | 11858 xmlNodePtr oldContextNode, contextNode = NULL; |
| 11703 xmlXPathContextPtr xpctxt = ctxt->context; | 11859 xmlXPathContextPtr xpctxt = ctxt->context; |
| 11860 int frame; |
| 11704 | 11861 |
| 11705 #ifdef LIBXML_XPTR_ENABLED | 11862 #ifdef LIBXML_XPTR_ENABLED |
| 11706 /* | 11863 /* |
| 11707 * URGENT TODO: Check the following: | 11864 * URGENT TODO: Check the following: |
| 11708 * We don't expect location sets if evaluating prediates, right? | 11865 * We don't expect location sets if evaluating prediates, right? |
| 11709 * Only filters should expect location sets, right? | 11866 * Only filters should expect location sets, right? |
| 11710 */ | 11867 */ |
| 11711 #endif /* LIBXML_XPTR_ENABLED */ | 11868 #endif /* LIBXML_XPTR_ENABLED */ |
| 11712 | 11869 |
| 11713 /* | 11870 /* |
| 11714 * Save old context. | 11871 * Save old context. |
| 11715 */ | 11872 */ |
| 11716 oldContextNode = xpctxt->node; | 11873 oldContextNode = xpctxt->node; |
| 11717 oldContextDoc = xpctxt->doc; | 11874 oldContextDoc = xpctxt->doc; |
| 11718 /* | 11875 /* |
| 11719 * Get the expression of this predicate. | 11876 * Get the expression of this predicate. |
| 11720 */ | 11877 */ |
| 11721 exprOp = &ctxt->comp->steps[op->ch2]; | 11878 exprOp = &ctxt->comp->steps[op->ch2]; |
| 11722 for (i = 0; i < set->nodeNr; i++) { | 11879 for (i = 0; i < set->nodeNr; i++) { |
| 11880 xmlXPathObjectPtr tmp; |
| 11881 |
| 11723 if (set->nodeTab[i] == NULL) | 11882 if (set->nodeTab[i] == NULL) |
| 11724 continue; | 11883 continue; |
| 11725 | 11884 |
| 11726 contextNode = set->nodeTab[i]; | 11885 contextNode = set->nodeTab[i]; |
| 11727 xpctxt->node = contextNode; | 11886 xpctxt->node = contextNode; |
| 11728 xpctxt->contextSize = contextSize; | 11887 xpctxt->contextSize = contextSize; |
| 11729 xpctxt->proximityPosition = ++contextPos; | 11888 xpctxt->proximityPosition = ++contextPos; |
| 11730 | 11889 |
| 11731 /* | 11890 /* |
| 11732 * Initialize the new set. | 11891 * Initialize the new set. |
| 11733 * Also set the xpath document in case things like | 11892 * Also set the xpath document in case things like |
| 11734 * key() evaluation are attempted on the predicate | 11893 * key() evaluation are attempted on the predicate |
| 11735 */ | 11894 */ |
| 11736 if ((contextNode->type != XML_NAMESPACE_DECL) && | 11895 if ((contextNode->type != XML_NAMESPACE_DECL) && |
| 11737 (contextNode->doc != NULL)) | 11896 (contextNode->doc != NULL)) |
| 11738 xpctxt->doc = contextNode->doc; | 11897 xpctxt->doc = contextNode->doc; |
| 11739 /* | 11898 /* |
| 11740 * Evaluate the predicate expression with 1 context node | 11899 * Evaluate the predicate expression with 1 context node |
| 11741 * at a time; this node is packaged into a node set; this | 11900 * at a time; this node is packaged into a node set; this |
| 11742 * node set is handed over to the evaluation mechanism. | 11901 * node set is handed over to the evaluation mechanism. |
| 11743 */ | 11902 */ |
| 11744 if (contextObj == NULL) | 11903 if (contextObj == NULL) |
| 11745 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); | 11904 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); |
| 11746 » else | 11905 » else { |
| 11747 » » xmlXPathNodeSetAddUnique(contextObj->nodesetval, | 11906 » » if (xmlXPathNodeSetAddUnique(contextObj->nodesetval, |
| 11748 » » contextNode); | 11907 » » contextNode) < 0) { |
| 11908 » » ctxt->error = XPATH_MEMORY_ERROR; |
| 11909 » » goto evaluation_exit; |
| 11910 » » } |
| 11911 » } |
| 11749 | 11912 |
| 11913 frame = xmlXPathSetFrame(ctxt); |
| 11750 valuePush(ctxt, contextObj); | 11914 valuePush(ctxt, contextObj); |
| 11751 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); | 11915 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); |
| 11916 tmp = valuePop(ctxt); |
| 11917 xmlXPathPopFrame(ctxt, frame); |
| 11752 | 11918 |
| 11753 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { | 11919 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { |
| 11754 xmlXPathObjectPtr tmp; | |
| 11755 /* pop the result if any */ | |
| 11756 tmp = valuePop(ctxt); | |
| 11757 while (tmp != contextObj) { | 11920 while (tmp != contextObj) { |
| 11758 /* | 11921 /* |
| 11759 * Free up the result | 11922 * Free up the result |
| 11760 * then pop off contextObj, which will be freed later | 11923 * then pop off contextObj, which will be freed later |
| 11761 */ | 11924 */ |
| 11762 xmlXPathReleaseObject(xpctxt, tmp); | 11925 xmlXPathReleaseObject(xpctxt, tmp); |
| 11763 tmp = valuePop(ctxt); | 11926 tmp = valuePop(ctxt); |
| 11764 } | 11927 } |
| 11765 goto evaluation_error; | 11928 goto evaluation_error; |
| 11766 } | 11929 } |
| 11930 /* push the result back onto the stack */ |
| 11931 valuePush(ctxt, tmp); |
| 11767 | 11932 |
| 11768 if (res) | 11933 if (res) |
| 11769 pos++; | 11934 pos++; |
| 11770 | 11935 |
| 11771 if (res && (pos >= minPos) && (pos <= maxPos)) { | 11936 if (res && (pos >= minPos) && (pos <= maxPos)) { |
| 11772 /* | 11937 /* |
| 11773 * Fits in the requested range. | 11938 * Fits in the requested range. |
| 11774 */ | 11939 */ |
| 11775 newContextSize++; | 11940 newContextSize++; |
| 11776 if (minPos == maxPos) { | 11941 if (minPos == maxPos) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11908 static int | 12073 static int |
| 11909 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, | 12074 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, |
| 11910 xmlXPathStepOpPtr op, | 12075 xmlXPathStepOpPtr op, |
| 11911 xmlNodePtr * first, xmlNodePtr * last, | 12076 xmlNodePtr * first, xmlNodePtr * last, |
| 11912 int toBool) | 12077 int toBool) |
| 11913 { | 12078 { |
| 11914 | 12079 |
| 11915 #define XP_TEST_HIT \ | 12080 #define XP_TEST_HIT \ |
| 11916 if (hasAxisRange != 0) { \ | 12081 if (hasAxisRange != 0) { \ |
| 11917 if (++pos == maxPos) { \ | 12082 if (++pos == maxPos) { \ |
| 11918 » addNode(seq, cur); \ | 12083 » if (addNode(seq, cur) < 0) \ |
| 11919 » goto axis_range_end; } \ | 12084 » ctxt->error = XPATH_MEMORY_ERROR; \ |
| 12085 » goto axis_range_end; } \ |
| 11920 } else { \ | 12086 } else { \ |
| 11921 » addNode(seq, cur); \ | 12087 » if (addNode(seq, cur) < 0) \ |
| 12088 » ctxt->error = XPATH_MEMORY_ERROR; \ |
| 11922 if (breakOnFirstHit) goto first_hit; } | 12089 if (breakOnFirstHit) goto first_hit; } |
| 11923 | 12090 |
| 11924 #define XP_TEST_HIT_NS \ | 12091 #define XP_TEST_HIT_NS \ |
| 11925 if (hasAxisRange != 0) { \ | 12092 if (hasAxisRange != 0) { \ |
| 11926 if (++pos == maxPos) { \ | 12093 if (++pos == maxPos) { \ |
| 11927 hasNsNodes = 1; \ | 12094 hasNsNodes = 1; \ |
| 11928 » xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur); \ | 12095 » if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \ |
| 12096 » ctxt->error = XPATH_MEMORY_ERROR; \ |
| 11929 goto axis_range_end; } \ | 12097 goto axis_range_end; } \ |
| 11930 } else { \ | 12098 } else { \ |
| 11931 hasNsNodes = 1; \ | 12099 hasNsNodes = 1; \ |
| 11932 » xmlXPathNodeSetAddNs(seq, \ | 12100 » if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \ |
| 11933 » xpctxt->node, (xmlNsPtr) cur); \ | 12101 » ctxt->error = XPATH_MEMORY_ERROR; \ |
| 11934 if (breakOnFirstHit) goto first_hit; } | 12102 if (breakOnFirstHit) goto first_hit; } |
| 11935 | 12103 |
| 11936 xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value; | 12104 xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value; |
| 11937 xmlXPathTestVal test = (xmlXPathTestVal) op->value2; | 12105 xmlXPathTestVal test = (xmlXPathTestVal) op->value2; |
| 11938 xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3; | 12106 xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3; |
| 11939 const xmlChar *prefix = op->value4; | 12107 const xmlChar *prefix = op->value4; |
| 11940 const xmlChar *name = op->value5; | 12108 const xmlChar *name = op->value5; |
| 11941 const xmlChar *URI = NULL; | 12109 const xmlChar *URI = NULL; |
| 11942 | 12110 |
| 11943 #ifdef DEBUG_STEP | 12111 #ifdef DEBUG_STEP |
| 11944 int nbMatches = 0, prevMatches = 0; | 12112 int nbMatches = 0, prevMatches = 0; |
| 11945 #endif | 12113 #endif |
| 11946 int total = 0, hasNsNodes = 0; | 12114 int total = 0, hasNsNodes = 0; |
| 11947 /* The popped object holding the context nodes */ | 12115 /* The popped object holding the context nodes */ |
| 11948 xmlXPathObjectPtr obj; | 12116 xmlXPathObjectPtr obj; |
| 11949 /* The set of context nodes for the node tests */ | 12117 /* The set of context nodes for the node tests */ |
| 11950 xmlNodeSetPtr contextSeq; | 12118 xmlNodeSetPtr contextSeq; |
| 11951 int contextIdx; | 12119 int contextIdx; |
| 11952 xmlNodePtr contextNode; | 12120 xmlNodePtr contextNode; |
| 11953 /* The context node for a compound traversal */ | |
| 11954 xmlNodePtr outerContextNode; | |
| 11955 /* The final resulting node set wrt to all context nodes */ | 12121 /* The final resulting node set wrt to all context nodes */ |
| 11956 xmlNodeSetPtr outSeq; | 12122 xmlNodeSetPtr outSeq; |
| 11957 /* | 12123 /* |
| 11958 * The temporary resulting node set wrt 1 context node. | 12124 * The temporary resulting node set wrt 1 context node. |
| 11959 * Used to feed predicate evaluation. | 12125 * Used to feed predicate evaluation. |
| 11960 */ | 12126 */ |
| 11961 xmlNodeSetPtr seq; | 12127 xmlNodeSetPtr seq; |
| 11962 xmlNodePtr cur; | 12128 xmlNodePtr cur; |
| 11963 /* First predicate operator */ | 12129 /* First predicate operator */ |
| 11964 xmlXPathStepOpPtr predOp; | 12130 xmlXPathStepOpPtr predOp; |
| 11965 int maxPos; /* The requested position() (when a "[n]" predicate) */ | 12131 int maxPos; /* The requested position() (when a "[n]" predicate) */ |
| 11966 int hasPredicateRange, hasAxisRange, pos, size, newSize; | 12132 int hasPredicateRange, hasAxisRange, pos, size, newSize; |
| 11967 int breakOnFirstHit; | 12133 int breakOnFirstHit; |
| 11968 | 12134 |
| 11969 xmlXPathTraversalFunction next = NULL; | 12135 xmlXPathTraversalFunction next = NULL; |
| 11970 /* compound axis traversal */ | 12136 int (*addNode) (xmlNodeSetPtr, xmlNodePtr); |
| 11971 xmlXPathTraversalFunctionExt outerNext = NULL; | |
| 11972 void (*addNode) (xmlNodeSetPtr, xmlNodePtr); | |
| 11973 xmlXPathNodeSetMergeFunction mergeAndClear; | 12137 xmlXPathNodeSetMergeFunction mergeAndClear; |
| 11974 xmlNodePtr oldContextNode; | 12138 xmlNodePtr oldContextNode; |
| 11975 xmlXPathContextPtr xpctxt = ctxt->context; | 12139 xmlXPathContextPtr xpctxt = ctxt->context; |
| 11976 | 12140 |
| 11977 | 12141 |
| 11978 CHECK_TYPE0(XPATH_NODESET); | 12142 CHECK_TYPE0(XPATH_NODESET); |
| 11979 obj = valuePop(ctxt); | 12143 obj = valuePop(ctxt); |
| 11980 /* | 12144 /* |
| 11981 * Setup namespaces. | 12145 * Setup namespaces. |
| 11982 */ | 12146 */ |
| (...skipping 28 matching lines...) Expand all Loading... |
| 12011 next = xmlXPathNextAncestorOrSelf; | 12175 next = xmlXPathNextAncestorOrSelf; |
| 12012 break; | 12176 break; |
| 12013 case AXIS_ATTRIBUTE: | 12177 case AXIS_ATTRIBUTE: |
| 12014 first = NULL; | 12178 first = NULL; |
| 12015 last = NULL; | 12179 last = NULL; |
| 12016 next = xmlXPathNextAttribute; | 12180 next = xmlXPathNextAttribute; |
| 12017 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; | 12181 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; |
| 12018 break; | 12182 break; |
| 12019 case AXIS_CHILD: | 12183 case AXIS_CHILD: |
| 12020 last = NULL; | 12184 last = NULL; |
| 12021 if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) { | |
| 12022 /* | |
| 12023 * This iterator will give us only nodes which can | |
| 12024 * hold element nodes. | |
| 12025 */ | |
| 12026 outerNext = xmlXPathNextDescendantOrSelfElemParent; | |
| 12027 } | |
| 12028 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) && | 12185 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) && |
| 12029 (type == NODE_TYPE_NODE)) | 12186 (type == NODE_TYPE_NODE)) |
| 12030 { | 12187 { |
| 12031 /* | 12188 /* |
| 12032 * Optimization if an element node type is 'element'. | 12189 * Optimization if an element node type is 'element'. |
| 12033 */ | 12190 */ |
| 12034 next = xmlXPathNextChildElement; | 12191 next = xmlXPathNextChildElement; |
| 12035 } else | 12192 } else |
| 12036 next = xmlXPathNextChild; | 12193 next = xmlXPathNextChild; |
| 12037 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; | 12194 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12147 * - For other axes, the principal node type is element. | 12304 * - For other axes, the principal node type is element. |
| 12148 * | 12305 * |
| 12149 * A node test * is true for any node of the | 12306 * A node test * is true for any node of the |
| 12150 * principal node type. For example, child::* will | 12307 * principal node type. For example, child::* will |
| 12151 * select all element children of the context node | 12308 * select all element children of the context node |
| 12152 */ | 12309 */ |
| 12153 oldContextNode = xpctxt->node; | 12310 oldContextNode = xpctxt->node; |
| 12154 addNode = xmlXPathNodeSetAddUnique; | 12311 addNode = xmlXPathNodeSetAddUnique; |
| 12155 outSeq = NULL; | 12312 outSeq = NULL; |
| 12156 seq = NULL; | 12313 seq = NULL; |
| 12157 outerContextNode = NULL; | |
| 12158 contextNode = NULL; | 12314 contextNode = NULL; |
| 12159 contextIdx = 0; | 12315 contextIdx = 0; |
| 12160 | 12316 |
| 12161 | 12317 |
| 12162 while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) { | 12318 while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) && |
| 12163 » if (outerNext != NULL) { | 12319 (ctxt->error == XPATH_EXPRESSION_OK)) { |
| 12164 » /* | 12320 » xpctxt->node = contextSeq->nodeTab[contextIdx++]; |
| 12165 » * This is a compound traversal. | |
| 12166 » */ | |
| 12167 » if (contextNode == NULL) { | |
| 12168 » » /* | |
| 12169 » » * Set the context for the outer traversal. | |
| 12170 » » */ | |
| 12171 » » outerContextNode = contextSeq->nodeTab[contextIdx++]; | |
| 12172 » » contextNode = outerNext(NULL, outerContextNode); | |
| 12173 » } else | |
| 12174 » » contextNode = outerNext(contextNode, outerContextNode); | |
| 12175 » if (contextNode == NULL) | |
| 12176 » » continue; | |
| 12177 » /* | |
| 12178 » * Set the context for the main traversal. | |
| 12179 » */ | |
| 12180 » xpctxt->node = contextNode; | |
| 12181 » } else | |
| 12182 » xpctxt->node = contextSeq->nodeTab[contextIdx++]; | |
| 12183 | 12321 |
| 12184 if (seq == NULL) { | 12322 if (seq == NULL) { |
| 12185 seq = xmlXPathNodeSetCreate(NULL); | 12323 seq = xmlXPathNodeSetCreate(NULL); |
| 12186 if (seq == NULL) { | 12324 if (seq == NULL) { |
| 12187 total = 0; | 12325 total = 0; |
| 12188 goto error; | 12326 goto error; |
| 12189 } | 12327 } |
| 12190 } | 12328 } |
| 12191 /* | 12329 /* |
| 12192 * Traverse the axis and test the nodes. | 12330 * Traverse the axis and test the nodes. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12280 if ((cur->type == XML_PI_NODE) && | 12418 if ((cur->type == XML_PI_NODE) && |
| 12281 ((name == NULL) || xmlStrEqual(name, cur->name))) | 12419 ((name == NULL) || xmlStrEqual(name, cur->name))) |
| 12282 { | 12420 { |
| 12283 XP_TEST_HIT | 12421 XP_TEST_HIT |
| 12284 } | 12422 } |
| 12285 break; | 12423 break; |
| 12286 case NODE_TEST_ALL: | 12424 case NODE_TEST_ALL: |
| 12287 if (axis == AXIS_ATTRIBUTE) { | 12425 if (axis == AXIS_ATTRIBUTE) { |
| 12288 if (cur->type == XML_ATTRIBUTE_NODE) | 12426 if (cur->type == XML_ATTRIBUTE_NODE) |
| 12289 { | 12427 { |
| 12290 » » » XP_TEST_HIT | 12428 if (prefix == NULL) |
| 12429 » » » { |
| 12430 » » » » XP_TEST_HIT |
| 12431 } else if ((cur->ns != NULL) && |
| 12432 » » » » (xmlStrEqual(URI, cur->ns->href))) |
| 12433 » » » { |
| 12434 » » » » XP_TEST_HIT |
| 12435 } |
| 12291 } | 12436 } |
| 12292 } else if (axis == AXIS_NAMESPACE) { | 12437 } else if (axis == AXIS_NAMESPACE) { |
| 12293 if (cur->type == XML_NAMESPACE_DECL) | 12438 if (cur->type == XML_NAMESPACE_DECL) |
| 12294 { | 12439 { |
| 12295 XP_TEST_HIT_NS | 12440 XP_TEST_HIT_NS |
| 12296 } | 12441 } |
| 12297 } else { | 12442 } else { |
| 12298 if (cur->type == XML_ELEMENT_NODE) { | 12443 if (cur->type == XML_ELEMENT_NODE) { |
| 12299 if (prefix == NULL) | 12444 if (prefix == NULL) |
| 12300 { | 12445 { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12370 { | 12515 { |
| 12371 XP_TEST_HIT_NS | 12516 XP_TEST_HIT_NS |
| 12372 } | 12517 } |
| 12373 } | 12518 } |
| 12374 break; | 12519 break; |
| 12375 default: | 12520 default: |
| 12376 break; | 12521 break; |
| 12377 } | 12522 } |
| 12378 break; | 12523 break; |
| 12379 } /* switch(test) */ | 12524 } /* switch(test) */ |
| 12380 } while (cur != NULL); | 12525 } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK)); |
| 12381 | 12526 |
| 12382 goto apply_predicates; | 12527 goto apply_predicates; |
| 12383 | 12528 |
| 12384 axis_range_end: /* ----------------------------------------------------- */ | 12529 axis_range_end: /* ----------------------------------------------------- */ |
| 12385 /* | 12530 /* |
| 12386 * We have a "/foo[n]", and position() = n was reached. | 12531 * We have a "/foo[n]", and position() = n was reached. |
| 12387 * Note that we can have as well "/foo/::parent::foo[1]", so | 12532 * Note that we can have as well "/foo/::parent::foo[1]", so |
| 12388 * a duplicate-aware merge is still needed. | 12533 * a duplicate-aware merge is still needed. |
| 12389 * Merge with the result. | 12534 * Merge with the result. |
| 12390 */ | 12535 */ |
| (...skipping 20 matching lines...) Expand all Loading... |
| 12411 } else | 12556 } else |
| 12412 outSeq = mergeAndClear(outSeq, seq, 0); | 12557 outSeq = mergeAndClear(outSeq, seq, 0); |
| 12413 break; | 12558 break; |
| 12414 | 12559 |
| 12415 #ifdef DEBUG_STEP | 12560 #ifdef DEBUG_STEP |
| 12416 if (seq != NULL) | 12561 if (seq != NULL) |
| 12417 nbMatches += seq->nodeNr; | 12562 nbMatches += seq->nodeNr; |
| 12418 #endif | 12563 #endif |
| 12419 | 12564 |
| 12420 apply_predicates: /* --------------------------------------------------- */ | 12565 apply_predicates: /* --------------------------------------------------- */ |
| 12566 if (ctxt->error != XPATH_EXPRESSION_OK) |
| 12567 goto error; |
| 12568 |
| 12421 /* | 12569 /* |
| 12422 * Apply predicates. | 12570 * Apply predicates. |
| 12423 */ | 12571 */ |
| 12424 if ((predOp != NULL) && (seq->nodeNr > 0)) { | 12572 if ((predOp != NULL) && (seq->nodeNr > 0)) { |
| 12425 /* | 12573 /* |
| 12426 * E.g. when we have a "/foo[some expression][n]". | 12574 * E.g. when we have a "/foo[some expression][n]". |
| 12427 » */» | 12575 » */ |
| 12428 /* | 12576 /* |
| 12429 * QUESTION TODO: The old predicate evaluation took into | 12577 * QUESTION TODO: The old predicate evaluation took into |
| 12430 * account location-sets. | 12578 * account location-sets. |
| 12431 * (E.g. ctxt->value->type == XPATH_LOCATIONSET) | 12579 * (E.g. ctxt->value->type == XPATH_LOCATIONSET) |
| 12432 * Do we expect such a set here? | 12580 * Do we expect such a set here? |
| 12433 * All what I learned now from the evaluation semantics | 12581 * All what I learned now from the evaluation semantics |
| 12434 * does not indicate that a location-set will be processed | 12582 * does not indicate that a location-set will be processed |
| 12435 * here, so this looks OK. | 12583 * here, so this looks OK. |
| 12436 » */» | 12584 » */ |
| 12437 /* | 12585 /* |
| 12438 * Iterate over all predicates, starting with the outermost | 12586 * Iterate over all predicates, starting with the outermost |
| 12439 * predicate. | 12587 * predicate. |
| 12440 * TODO: Problem: we cannot execute the inner predicates first | 12588 * TODO: Problem: we cannot execute the inner predicates first |
| 12441 * since we cannot go back *up* the operator tree! | 12589 * since we cannot go back *up* the operator tree! |
| 12442 * Options we have: | 12590 * Options we have: |
| 12443 * 1) Use of recursive functions (like is it currently done | 12591 * 1) Use of recursive functions (like is it currently done |
| 12444 * via xmlXPathCompOpEval()) | 12592 * via xmlXPathCompOpEval()) |
| 12445 * 2) Add a predicate evaluation information stack to the | 12593 * 2) Add a predicate evaluation information stack to the |
| 12446 * context struct | 12594 * context struct |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12919 * Run the evaluation with a node list made of a | 13067 * Run the evaluation with a node list made of a |
| 12920 * single item in the nodelocset. | 13068 * single item in the nodelocset. |
| 12921 */ | 13069 */ |
| 12922 ctxt->context->node = oldlocset->locTab[i]->user; | 13070 ctxt->context->node = oldlocset->locTab[i]->user; |
| 12923 ctxt->context->contextSize = oldlocset->locNr; | 13071 ctxt->context->contextSize = oldlocset->locNr; |
| 12924 ctxt->context->proximityPosition = i + 1; | 13072 ctxt->context->proximityPosition = i + 1; |
| 12925 if (tmp == NULL) { | 13073 if (tmp == NULL) { |
| 12926 tmp = xmlXPathCacheNewNodeSet(ctxt->context, | 13074 tmp = xmlXPathCacheNewNodeSet(ctxt->context, |
| 12927 ctxt->context->node); | 13075 ctxt->context->node); |
| 12928 } else { | 13076 } else { |
| 12929 » » xmlXPathNodeSetAddUnique(tmp->nodesetval, | 13077 » » if (xmlXPathNodeSetAddUnique(tmp->nodesetval, |
| 12930 » » ctxt->context->node); | 13078 » » ctxt->context->node) < 0) { |
| 13079 » » ctxt->error = XPATH_MEMORY_ERROR; |
| 13080 » » } |
| 12931 } | 13081 } |
| 12932 valuePush(ctxt, tmp); | 13082 valuePush(ctxt, tmp); |
| 12933 if (op->ch2 != -1) | 13083 if (op->ch2 != -1) |
| 12934 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 13084 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
| 12935 if (ctxt->error != XPATH_EXPRESSION_OK) { | 13085 if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 12936 xmlXPathFreeObject(obj); | 13086 xmlXPathFreeObject(obj); |
| 12937 return(0); | 13087 return(0); |
| 12938 } | 13088 } |
| 12939 /* | 13089 /* |
| 12940 * The result of the evaluation need to be tested to | 13090 * The result of the evaluation need to be tested to |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13033 * a single item in the nodeset. | 13183 * a single item in the nodeset. |
| 13034 */ | 13184 */ |
| 13035 ctxt->context->node = oldset->nodeTab[i]; | 13185 ctxt->context->node = oldset->nodeTab[i]; |
| 13036 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && | 13186 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && |
| 13037 (oldset->nodeTab[i]->doc != NULL)) | 13187 (oldset->nodeTab[i]->doc != NULL)) |
| 13038 ctxt->context->doc = oldset->nodeTab[i]->doc; | 13188 ctxt->context->doc = oldset->nodeTab[i]->doc; |
| 13039 if (tmp == NULL) { | 13189 if (tmp == NULL) { |
| 13040 tmp = xmlXPathCacheNewNodeSet(ctxt->context, | 13190 tmp = xmlXPathCacheNewNodeSet(ctxt->context, |
| 13041 ctxt->context->node); | 13191 ctxt->context->node); |
| 13042 } else { | 13192 } else { |
| 13043 » » xmlXPathNodeSetAddUnique(tmp->nodesetval, | 13193 » » if (xmlXPathNodeSetAddUnique(tmp->nodesetval, |
| 13044 » » ctxt->context->node); | 13194 » » ctxt->context->node) < 0) { |
| 13195 » » ctxt->error = XPATH_MEMORY_ERROR; |
| 13196 » » } |
| 13045 } | 13197 } |
| 13046 valuePush(ctxt, tmp); | 13198 valuePush(ctxt, tmp); |
| 13047 ctxt->context->contextSize = oldset->nodeNr; | 13199 ctxt->context->contextSize = oldset->nodeNr; |
| 13048 ctxt->context->proximityPosition = i + 1; | 13200 ctxt->context->proximityPosition = i + 1; |
| 13049 if (op->ch2 != -1) | 13201 if (op->ch2 != -1) |
| 13050 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 13202 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
| 13051 if (ctxt->error != XPATH_EXPRESSION_OK) { | 13203 if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 13052 xmlXPathFreeNodeSet(newset); | 13204 xmlXPathFreeNodeSet(newset); |
| 13053 xmlXPathFreeObject(obj); | 13205 xmlXPathFreeObject(obj); |
| 13054 return(0); | 13206 return(0); |
| 13055 } | 13207 } |
| 13056 /* | 13208 /* |
| 13057 * The result of the evaluation needs to be tested to | 13209 * The result of the evaluation needs to be tested to |
| 13058 * decide whether the filter succeeded or not | 13210 * decide whether the filter succeeded or not |
| 13059 */ | 13211 */ |
| 13060 res = valuePop(ctxt); | 13212 res = valuePop(ctxt); |
| 13061 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { | 13213 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { |
| 13062 » » xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); | 13214 » » if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) < 0) |
| 13215 » » ctxt->error = XPATH_MEMORY_ERROR; |
| 13063 } | 13216 } |
| 13064 /* | 13217 /* |
| 13065 * Cleanup | 13218 * Cleanup |
| 13066 */ | 13219 */ |
| 13067 if (res != NULL) { | 13220 if (res != NULL) { |
| 13068 xmlXPathReleaseObject(ctxt->context, res); | 13221 xmlXPathReleaseObject(ctxt->context, res); |
| 13069 } | 13222 } |
| 13070 if (ctxt->value == tmp) { | 13223 if (ctxt->value == tmp) { |
| 13071 valuePop(ctxt); | 13224 valuePop(ctxt); |
| 13072 /* | 13225 /* |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13361 return(0); | 13514 return(0); |
| 13362 } | 13515 } |
| 13363 valuePush(ctxt, val); | 13516 valuePush(ctxt, val); |
| 13364 } | 13517 } |
| 13365 return (total); | 13518 return (total); |
| 13366 } | 13519 } |
| 13367 case XPATH_OP_FUNCTION:{ | 13520 case XPATH_OP_FUNCTION:{ |
| 13368 xmlXPathFunction func; | 13521 xmlXPathFunction func; |
| 13369 const xmlChar *oldFunc, *oldFuncURI; | 13522 const xmlChar *oldFunc, *oldFuncURI; |
| 13370 int i; | 13523 int i; |
| 13524 int frame; |
| 13371 | 13525 |
| 13372 if (op->ch1 != -1) | 13526 frame = xmlXPathSetFrame(ctxt); |
| 13527 if (op->ch1 != -1) { |
| 13373 total += | 13528 total += |
| 13374 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); | 13529 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); |
| 13375 » » if (ctxt->valueNr < op->value) { | 13530 if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 13531 xmlXPathPopFrame(ctxt, frame); |
| 13532 return (total); |
| 13533 } |
| 13534 } |
| 13535 » » if (ctxt->valueNr < ctxt->valueFrame + op->value) { |
| 13376 xmlGenericError(xmlGenericErrorContext, | 13536 xmlGenericError(xmlGenericErrorContext, |
| 13377 "xmlXPathCompOpEval: parameter error\n"); | 13537 "xmlXPathCompOpEval: parameter error\n"); |
| 13378 ctxt->error = XPATH_INVALID_OPERAND; | 13538 ctxt->error = XPATH_INVALID_OPERAND; |
| 13539 xmlXPathPopFrame(ctxt, frame); |
| 13379 return (total); | 13540 return (total); |
| 13380 } | 13541 } |
| 13381 » » for (i = 0; i < op->value; i++) | 13542 » » for (i = 0; i < op->value; i++) { |
| 13382 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { | 13543 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { |
| 13383 xmlGenericError(xmlGenericErrorContext, | 13544 xmlGenericError(xmlGenericErrorContext, |
| 13384 "xmlXPathCompOpEval: parameter error\n"); | 13545 "xmlXPathCompOpEval: parameter error\n"); |
| 13385 ctxt->error = XPATH_INVALID_OPERAND; | 13546 ctxt->error = XPATH_INVALID_OPERAND; |
| 13547 xmlXPathPopFrame(ctxt, frame); |
| 13386 return (total); | 13548 return (total); |
| 13387 } | 13549 } |
| 13550 } |
| 13388 if (op->cache != NULL) | 13551 if (op->cache != NULL) |
| 13389 XML_CAST_FPTR(func) = op->cache; | 13552 XML_CAST_FPTR(func) = op->cache; |
| 13390 else { | 13553 else { |
| 13391 const xmlChar *URI = NULL; | 13554 const xmlChar *URI = NULL; |
| 13392 | 13555 |
| 13393 if (op->value5 == NULL) | 13556 if (op->value5 == NULL) |
| 13394 func = | 13557 func = |
| 13395 xmlXPathFunctionLookup(ctxt->context, | 13558 xmlXPathFunctionLookup(ctxt->context, |
| 13396 op->value4); | 13559 op->value4); |
| 13397 else { | 13560 else { |
| 13398 URI = xmlXPathNsLookup(ctxt->context, op->value5); | 13561 URI = xmlXPathNsLookup(ctxt->context, op->value5); |
| 13399 if (URI == NULL) { | 13562 if (URI == NULL) { |
| 13400 xmlGenericError(xmlGenericErrorContext, | 13563 xmlGenericError(xmlGenericErrorContext, |
| 13401 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", | 13564 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", |
| 13402 (char *)op->value4, (char *)op->value5); | 13565 (char *)op->value4, (char *)op->value5); |
| 13566 xmlXPathPopFrame(ctxt, frame); |
| 13403 ctxt->error = XPATH_UNDEF_PREFIX_ERROR; | 13567 ctxt->error = XPATH_UNDEF_PREFIX_ERROR; |
| 13404 return (total); | 13568 return (total); |
| 13405 } | 13569 } |
| 13406 func = xmlXPathFunctionLookupNS(ctxt->context, | 13570 func = xmlXPathFunctionLookupNS(ctxt->context, |
| 13407 op->value4, URI); | 13571 op->value4, URI); |
| 13408 } | 13572 } |
| 13409 if (func == NULL) { | 13573 if (func == NULL) { |
| 13410 xmlGenericError(xmlGenericErrorContext, | 13574 xmlGenericError(xmlGenericErrorContext, |
| 13411 "xmlXPathCompOpEval: function %s not found\n", | 13575 "xmlXPathCompOpEval: function %s not found\n", |
| 13412 (char *)op->value4); | 13576 (char *)op->value4); |
| 13413 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); | 13577 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); |
| 13414 } | 13578 } |
| 13415 op->cache = XML_CAST_FPTR(func); | 13579 op->cache = XML_CAST_FPTR(func); |
| 13416 op->cacheURI = (void *) URI; | 13580 op->cacheURI = (void *) URI; |
| 13417 } | 13581 } |
| 13418 oldFunc = ctxt->context->function; | 13582 oldFunc = ctxt->context->function; |
| 13419 oldFuncURI = ctxt->context->functionURI; | 13583 oldFuncURI = ctxt->context->functionURI; |
| 13420 ctxt->context->function = op->value4; | 13584 ctxt->context->function = op->value4; |
| 13421 ctxt->context->functionURI = op->cacheURI; | 13585 ctxt->context->functionURI = op->cacheURI; |
| 13422 func(ctxt, op->value); | 13586 func(ctxt, op->value); |
| 13423 ctxt->context->function = oldFunc; | 13587 ctxt->context->function = oldFunc; |
| 13424 ctxt->context->functionURI = oldFuncURI; | 13588 ctxt->context->functionURI = oldFuncURI; |
| 13589 xmlXPathPopFrame(ctxt, frame); |
| 13425 return (total); | 13590 return (total); |
| 13426 } | 13591 } |
| 13427 case XPATH_OP_ARG: | 13592 case XPATH_OP_ARG: |
| 13428 bakd = ctxt->context->doc; | 13593 bakd = ctxt->context->doc; |
| 13429 bak = ctxt->context->node; | 13594 bak = ctxt->context->node; |
| 13430 pp = ctxt->context->proximityPosition; | 13595 pp = ctxt->context->proximityPosition; |
| 13431 cs = ctxt->context->contextSize; | 13596 cs = ctxt->context->contextSize; |
| 13432 if (op->ch1 != -1) | 13597 if (op->ch1 != -1) { |
| 13433 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); | 13598 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); |
| 13434 » ctxt->context->contextSize = cs; | 13599 ctxt->context->contextSize = cs; |
| 13435 » ctxt->context->proximityPosition = pp; | 13600 ctxt->context->proximityPosition = pp; |
| 13436 » ctxt->context->node = bak; | 13601 ctxt->context->node = bak; |
| 13437 » ctxt->context->doc = bakd; | 13602 ctxt->context->doc = bakd; |
| 13438 » CHECK_ERROR0; | 13603 » CHECK_ERROR0; |
| 13604 } |
| 13439 if (op->ch2 != -1) { | 13605 if (op->ch2 != -1) { |
| 13440 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 13606 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
| 13441 » ctxt->context->doc = bakd; | 13607 ctxt->context->contextSize = cs; |
| 13442 » ctxt->context->node = bak; | 13608 ctxt->context->proximityPosition = pp; |
| 13609 ctxt->context->node = bak; |
| 13610 ctxt->context->doc = bakd; |
| 13443 CHECK_ERROR0; | 13611 CHECK_ERROR0; |
| 13444 } | 13612 } |
| 13445 return (total); | 13613 return (total); |
| 13446 case XPATH_OP_PREDICATE: | 13614 case XPATH_OP_PREDICATE: |
| 13447 case XPATH_OP_FILTER:{ | 13615 case XPATH_OP_FILTER:{ |
| 13448 xmlXPathObjectPtr res; | 13616 xmlXPathObjectPtr res; |
| 13449 xmlXPathObjectPtr obj, tmp; | 13617 xmlXPathObjectPtr obj, tmp; |
| 13450 xmlNodeSetPtr newset = NULL; | 13618 xmlNodeSetPtr newset = NULL; |
| 13451 xmlNodeSetPtr oldset; | 13619 xmlNodeSetPtr oldset; |
| 13452 xmlNodePtr oldnode; | 13620 xmlNodePtr oldnode; |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13724 * a single item in the nodeset. | 13892 * a single item in the nodeset. |
| 13725 */ | 13893 */ |
| 13726 ctxt->context->node = oldset->nodeTab[i]; | 13894 ctxt->context->node = oldset->nodeTab[i]; |
| 13727 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && | 13895 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && |
| 13728 (oldset->nodeTab[i]->doc != NULL)) | 13896 (oldset->nodeTab[i]->doc != NULL)) |
| 13729 ctxt->context->doc = oldset->nodeTab[i]->doc; | 13897 ctxt->context->doc = oldset->nodeTab[i]->doc; |
| 13730 if (tmp == NULL) { | 13898 if (tmp == NULL) { |
| 13731 tmp = xmlXPathCacheNewNodeSet(ctxt->context, | 13899 tmp = xmlXPathCacheNewNodeSet(ctxt->context, |
| 13732 ctxt->context->node); | 13900 ctxt->context->node); |
| 13733 } else { | 13901 } else { |
| 13734 » » » xmlXPathNodeSetAddUnique(tmp->nodesetval, | 13902 » » » if (xmlXPathNodeSetAddUnique(tmp->nodesetval, |
| 13735 » » » » ctxt->context->node); | 13903 » » » » ctxt->context->node) < 0) { |
| 13904 » » » » ctxt->error = XPATH_MEMORY_ERROR; |
| 13905 » » » } |
| 13736 } | 13906 } |
| 13737 valuePush(ctxt, tmp); | 13907 valuePush(ctxt, tmp); |
| 13738 ctxt->context->contextSize = oldset->nodeNr; | 13908 ctxt->context->contextSize = oldset->nodeNr; |
| 13739 ctxt->context->proximityPosition = i + 1; | 13909 ctxt->context->proximityPosition = i + 1; |
| 13740 /* | 13910 /* |
| 13741 * Evaluate the predicate against the context node. | 13911 * Evaluate the predicate against the context node. |
| 13742 * Can/should we optimize position() predicates | 13912 * Can/should we optimize position() predicates |
| 13743 * here (e.g. "[1]")? | 13913 * here (e.g. "[1]")? |
| 13744 */ | 13914 */ |
| 13745 if (op->ch2 != -1) | 13915 if (op->ch2 != -1) |
| 13746 total += | 13916 total += |
| 13747 xmlXPathCompOpEval(ctxt, | 13917 xmlXPathCompOpEval(ctxt, |
| 13748 &comp->steps[op->ch2]); | 13918 &comp->steps[op->ch2]); |
| 13749 if (ctxt->error != XPATH_EXPRESSION_OK) { | 13919 if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 13750 xmlXPathFreeNodeSet(newset); | 13920 xmlXPathFreeNodeSet(newset); |
| 13751 xmlXPathFreeObject(obj); | 13921 xmlXPathFreeObject(obj); |
| 13752 return(0); | 13922 return(0); |
| 13753 } | 13923 } |
| 13754 | 13924 |
| 13755 /* | 13925 /* |
| 13756 * The result of the evaluation needs to be tested to | 13926 * The result of the evaluation needs to be tested to |
| 13757 * decide whether the filter succeeded or not | 13927 * decide whether the filter succeeded or not |
| 13758 */ | 13928 */ |
| 13759 /* | 13929 /* |
| 13760 * OPTIMIZE TODO: Can we use | 13930 * OPTIMIZE TODO: Can we use |
| 13761 * xmlXPathNodeSetAdd*Unique()* instead? | 13931 * xmlXPathNodeSetAdd*Unique()* instead? |
| 13762 */ | 13932 */ |
| 13763 res = valuePop(ctxt); | 13933 res = valuePop(ctxt); |
| 13764 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { | 13934 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { |
| 13765 xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); | 13935 if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) |
| 13936 » » » < 0) |
| 13937 » » » » ctxt->error = XPATH_MEMORY_ERROR; |
| 13766 } | 13938 } |
| 13767 | 13939 |
| 13768 /* | 13940 /* |
| 13769 * Cleanup | 13941 * Cleanup |
| 13770 */ | 13942 */ |
| 13771 if (res != NULL) { | 13943 if (res != NULL) { |
| 13772 xmlXPathReleaseObject(ctxt->context, res); | 13944 xmlXPathReleaseObject(ctxt->context, res); |
| 13773 } | 13945 } |
| 13774 if (ctxt->value == tmp) { | 13946 if (ctxt->value == tmp) { |
| 13775 valuePop(ctxt); | 13947 valuePop(ctxt); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13971 ctxt->context->node = NULL; | 14143 ctxt->context->node = NULL; |
| 13972 ctxt->context->contextSize = -1; | 14144 ctxt->context->contextSize = -1; |
| 13973 ctxt->context->proximityPosition = -1; | 14145 ctxt->context->proximityPosition = -1; |
| 13974 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); | 14146 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); |
| 13975 return (total); | 14147 return (total); |
| 13976 } | 14148 } |
| 13977 #endif /* LIBXML_XPTR_ENABLED */ | 14149 #endif /* LIBXML_XPTR_ENABLED */ |
| 13978 } | 14150 } |
| 13979 xmlGenericError(xmlGenericErrorContext, | 14151 xmlGenericError(xmlGenericErrorContext, |
| 13980 "XPath: unknown precompiled operation %d\n", op->op); | 14152 "XPath: unknown precompiled operation %d\n", op->op); |
| 14153 ctxt->error = XPATH_INVALID_OPERAND; |
| 13981 return (total); | 14154 return (total); |
| 13982 } | 14155 } |
| 13983 | 14156 |
| 13984 /** | 14157 /** |
| 13985 * xmlXPathCompOpEvalToBoolean: | 14158 * xmlXPathCompOpEvalToBoolean: |
| 13986 * @ctxt: the XPath parser context | 14159 * @ctxt: the XPath parser context |
| 13987 * | 14160 * |
| 13988 * Evaluates if the expression evaluates to true. | 14161 * Evaluates if the expression evaluates to true. |
| 13989 * | 14162 * |
| 13990 * Returns 1 if true, 0 if false and -1 on API or internal errors. | 14163 * Returns 1 if true, 0 if false and -1 on API or internal errors. |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14117 | 14290 |
| 14118 /* | 14291 /* |
| 14119 * handle the special cases of "/" amd "." being matched | 14292 * handle the special cases of "/" amd "." being matched |
| 14120 */ | 14293 */ |
| 14121 if (min_depth == 0) { | 14294 if (min_depth == 0) { |
| 14122 if (from_root) { | 14295 if (from_root) { |
| 14123 /* Select "/" */ | 14296 /* Select "/" */ |
| 14124 if (toBool) | 14297 if (toBool) |
| 14125 return(1); | 14298 return(1); |
| 14126 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, | 14299 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, |
| 14127 » » (xmlNodePtr) ctxt->doc); | 14300 » » (xmlNodePtr) ctxt->doc); |
| 14128 } else { | 14301 } else { |
| 14129 /* Select "self::node()" */ | 14302 /* Select "self::node()" */ |
| 14130 if (toBool) | 14303 if (toBool) |
| 14131 return(1); | 14304 return(1); |
| 14132 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node); | 14305 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node); |
| 14133 } | 14306 } |
| 14134 } | 14307 } |
| 14135 if (max_depth == 0) { | 14308 if (max_depth == 0) { |
| 14136 return(0); | 14309 return(0); |
| 14137 } | 14310 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14210 } else if (eval_all_nodes) | 14383 } else if (eval_all_nodes) |
| 14211 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type); | 14384 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type); |
| 14212 else | 14385 else |
| 14213 break; | 14386 break; |
| 14214 | 14387 |
| 14215 if (ret < 0) { | 14388 if (ret < 0) { |
| 14216 /* NOP. */ | 14389 /* NOP. */ |
| 14217 } else if (ret == 1) { | 14390 } else if (ret == 1) { |
| 14218 if (toBool) | 14391 if (toBool) |
| 14219 goto return_1; | 14392 goto return_1; |
| 14220 » » xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); | 14393 » » if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) |
| 14394 » » < 0) { |
| 14395 » » » ctxt->lastError.domain = XML_FROM_XPATH; |
| 14396 » » » ctxt->lastError.code = XML_ERR_NO_MEMORY; |
| 14397 » » } |
| 14221 } | 14398 } |
| 14222 if ((cur->children == NULL) || (depth >= max_depth)) { | 14399 if ((cur->children == NULL) || (depth >= max_depth)) { |
| 14223 ret = xmlStreamPop(patstream); | 14400 ret = xmlStreamPop(patstream); |
| 14224 while (cur->next != NULL) { | 14401 while (cur->next != NULL) { |
| 14225 cur = cur->next; | 14402 cur = cur->next; |
| 14226 if ((cur->type != XML_ENTITY_DECL) && | 14403 if ((cur->type != XML_ENTITY_DECL) && |
| 14227 (cur->type != XML_DTD_NODE)) | 14404 (cur->type != XML_DTD_NODE)) |
| 14228 goto next_node; | 14405 goto next_node; |
| 14229 } | 14406 } |
| 14230 } | 14407 } |
| 14231 default: | 14408 default: |
| 14232 break; | 14409 break; |
| 14233 } | 14410 } |
| 14234 | 14411 |
| 14235 scan_children: | 14412 scan_children: |
| 14413 if (cur->type == XML_NAMESPACE_DECL) break; |
| 14236 if ((cur->children != NULL) && (depth < max_depth)) { | 14414 if ((cur->children != NULL) && (depth < max_depth)) { |
| 14237 /* | 14415 /* |
| 14238 * Do not descend on entities declarations | 14416 * Do not descend on entities declarations |
| 14239 */ | 14417 */ |
| 14240 if (cur->children->type != XML_ENTITY_DECL) { | 14418 if (cur->children->type != XML_ENTITY_DECL) { |
| 14241 cur = cur->children; | 14419 cur = cur->children; |
| 14242 depth++; | 14420 depth++; |
| 14243 /* | 14421 /* |
| 14244 * Skip DTDs | 14422 * Skip DTDs |
| 14245 */ | 14423 */ |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14318 /* Allocate the value stack */ | 14496 /* Allocate the value stack */ |
| 14319 ctxt->valueTab = (xmlXPathObjectPtr *) | 14497 ctxt->valueTab = (xmlXPathObjectPtr *) |
| 14320 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); | 14498 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); |
| 14321 if (ctxt->valueTab == NULL) { | 14499 if (ctxt->valueTab == NULL) { |
| 14322 xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); | 14500 xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); |
| 14323 xmlFree(ctxt); | 14501 xmlFree(ctxt); |
| 14324 } | 14502 } |
| 14325 ctxt->valueNr = 0; | 14503 ctxt->valueNr = 0; |
| 14326 ctxt->valueMax = 10; | 14504 ctxt->valueMax = 10; |
| 14327 ctxt->value = NULL; | 14505 ctxt->value = NULL; |
| 14506 ctxt->valueFrame = 0; |
| 14328 } | 14507 } |
| 14329 #ifdef XPATH_STREAMING | 14508 #ifdef XPATH_STREAMING |
| 14330 if (ctxt->comp->stream) { | 14509 if (ctxt->comp->stream) { |
| 14331 int res; | 14510 int res; |
| 14332 | 14511 |
| 14333 if (toBool) { | 14512 if (toBool) { |
| 14334 /* | 14513 /* |
| 14335 * Evaluation to boolean result. | 14514 * Evaluation to boolean result. |
| 14336 */ | 14515 */ |
| 14337 res = xmlXPathRunStreamEval(ctxt->context, | 14516 res = xmlXPathRunStreamEval(ctxt->context, |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14545 if (comp->dict) | 14724 if (comp->dict) |
| 14546 xmlDictReference(comp->dict); | 14725 xmlDictReference(comp->dict); |
| 14547 return(comp); | 14726 return(comp); |
| 14548 } | 14727 } |
| 14549 xmlFreePattern(stream); | 14728 xmlFreePattern(stream); |
| 14550 } | 14729 } |
| 14551 return(NULL); | 14730 return(NULL); |
| 14552 } | 14731 } |
| 14553 #endif /* XPATH_STREAMING */ | 14732 #endif /* XPATH_STREAMING */ |
| 14554 | 14733 |
| 14555 static int | |
| 14556 xmlXPathCanRewriteDosExpression(xmlChar *expr) | |
| 14557 { | |
| 14558 if (expr == NULL) | |
| 14559 return(0); | |
| 14560 do { | |
| 14561 if ((*expr == '/') && (*(++expr) == '/')) | |
| 14562 return(1); | |
| 14563 } while (*expr++); | |
| 14564 return(0); | |
| 14565 } | |
| 14566 static void | 14734 static void |
| 14567 xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) | 14735 xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) |
| 14568 { | 14736 { |
| 14569 /* | 14737 /* |
| 14570 * Try to rewrite "descendant-or-self::node()/foo" to an optimized | 14738 * Try to rewrite "descendant-or-self::node()/foo" to an optimized |
| 14571 * internal representation. | 14739 * internal representation. |
| 14572 */ | 14740 */ |
| 14573 if (op->ch1 != -1) { | |
| 14574 if ((op->op == XPATH_OP_COLLECT /* 11 */) && | |
| 14575 ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) && | |
| 14576 ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) && | |
| 14577 ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */)) | |
| 14578 { | |
| 14579 /* | |
| 14580 * This is a "child::foo" | |
| 14581 */ | |
| 14582 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1]; | |
| 14583 | 14741 |
| 14584 » if ((prevop->op == XPATH_OP_COLLECT /* 11 */) && | 14742 if ((op->op == XPATH_OP_COLLECT /* 11 */) && |
| 14585 » » (prevop->ch1 != -1) && | 14743 (op->ch1 != -1) && |
| 14586 » » ((xmlXPathAxisVal) prevop->value == | 14744 (op->ch2 == -1 /* no predicate */)) |
| 14587 » » AXIS_DESCENDANT_OR_SELF) && | 14745 { |
| 14588 » » (prevop->ch2 == -1) && | 14746 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1]; |
| 14589 » » ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) && | 14747 |
| 14590 » » ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) && | 14748 if ((prevop->op == XPATH_OP_COLLECT /* 11 */) && |
| 14591 » » (comp->steps[prevop->ch1].op == XPATH_OP_ROOT)) | 14749 ((xmlXPathAxisVal) prevop->value == |
| 14592 » { | 14750 AXIS_DESCENDANT_OR_SELF) && |
| 14593 » » /* | 14751 (prevop->ch2 == -1) && |
| 14594 » » * This is a "/descendant-or-self::node()" without predicates. | 14752 ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) && |
| 14595 » » * Eliminate it. | 14753 ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE)) |
| 14596 » » */ | 14754 { |
| 14597 » » op->ch1 = prevop->ch1; | 14755 /* |
| 14598 » » op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM; | 14756 * This is a "descendant-or-self::node()" without predicates. |
| 14599 » } | 14757 * Try to eliminate it. |
| 14758 */ |
| 14759 |
| 14760 switch ((xmlXPathAxisVal) op->value) { |
| 14761 case AXIS_CHILD: |
| 14762 case AXIS_DESCENDANT: |
| 14763 /* |
| 14764 * Convert "descendant-or-self::node()/child::" or |
| 14765 * "descendant-or-self::node()/descendant::" to |
| 14766 * "descendant::" |
| 14767 */ |
| 14768 op->ch1 = prevop->ch1; |
| 14769 op->value = AXIS_DESCENDANT; |
| 14770 break; |
| 14771 case AXIS_SELF: |
| 14772 case AXIS_DESCENDANT_OR_SELF: |
| 14773 /* |
| 14774 * Convert "descendant-or-self::node()/self::" or |
| 14775 * "descendant-or-self::node()/descendant-or-self::" to |
| 14776 * to "descendant-or-self::" |
| 14777 */ |
| 14778 op->ch1 = prevop->ch1; |
| 14779 op->value = AXIS_DESCENDANT_OR_SELF; |
| 14780 break; |
| 14781 default: |
| 14782 break; |
| 14783 } |
| 14600 } | 14784 } |
| 14601 if (op->ch1 != -1) | |
| 14602 xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]); | |
| 14603 } | 14785 } |
| 14786 |
| 14787 /* Recurse */ |
| 14788 if (op->ch1 != -1) |
| 14789 xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]); |
| 14604 if (op->ch2 != -1) | 14790 if (op->ch2 != -1) |
| 14605 » xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]); | 14791 » xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]); |
| 14606 } | 14792 } |
| 14607 | 14793 |
| 14608 /** | 14794 /** |
| 14609 * xmlXPathCtxtCompile: | 14795 * xmlXPathCtxtCompile: |
| 14610 * @ctxt: an XPath context | 14796 * @ctxt: an XPath context |
| 14611 * @str: the XPath expression | 14797 * @str: the XPath expression |
| 14612 * | 14798 * |
| 14613 * Compile an XPath expression | 14799 * Compile an XPath expression |
| 14614 * | 14800 * |
| 14615 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. | 14801 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14653 pctxt->comp = NULL; | 14839 pctxt->comp = NULL; |
| 14654 } | 14840 } |
| 14655 xmlXPathFreeParserContext(pctxt); | 14841 xmlXPathFreeParserContext(pctxt); |
| 14656 | 14842 |
| 14657 if (comp != NULL) { | 14843 if (comp != NULL) { |
| 14658 comp->expr = xmlStrdup(str); | 14844 comp->expr = xmlStrdup(str); |
| 14659 #ifdef DEBUG_EVAL_COUNTS | 14845 #ifdef DEBUG_EVAL_COUNTS |
| 14660 comp->string = xmlStrdup(str); | 14846 comp->string = xmlStrdup(str); |
| 14661 comp->nb = 0; | 14847 comp->nb = 0; |
| 14662 #endif | 14848 #endif |
| 14663 » if ((comp->expr != NULL) && | 14849 » if ((comp->nbStep > 1) && (comp->last >= 0)) { |
| 14664 » (comp->nbStep > 2) && | 14850 » xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]); |
| 14665 » (comp->last >= 0) && | |
| 14666 » (xmlXPathCanRewriteDosExpression(comp->expr) == 1)) | |
| 14667 » { | |
| 14668 » xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]); | |
| 14669 } | 14851 } |
| 14670 } | 14852 } |
| 14671 return(comp); | 14853 return(comp); |
| 14672 } | 14854 } |
| 14673 | 14855 |
| 14674 /** | 14856 /** |
| 14675 * xmlXPathCompile: | 14857 * xmlXPathCompile: |
| 14676 * @str: the XPath expression | 14858 * @str: the XPath expression |
| 14677 * | 14859 * |
| 14678 * Compile an XPath expression | 14860 * Compile an XPath expression |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14835 if (comp != NULL) { | 15017 if (comp != NULL) { |
| 14836 if (ctxt->comp != NULL) | 15018 if (ctxt->comp != NULL) |
| 14837 xmlXPathFreeCompExpr(ctxt->comp); | 15019 xmlXPathFreeCompExpr(ctxt->comp); |
| 14838 ctxt->comp = comp; | 15020 ctxt->comp = comp; |
| 14839 if (ctxt->cur != NULL) | 15021 if (ctxt->cur != NULL) |
| 14840 while (*ctxt->cur != 0) ctxt->cur++; | 15022 while (*ctxt->cur != 0) ctxt->cur++; |
| 14841 } else | 15023 } else |
| 14842 #endif | 15024 #endif |
| 14843 { | 15025 { |
| 14844 xmlXPathCompileExpr(ctxt, 1); | 15026 xmlXPathCompileExpr(ctxt, 1); |
| 14845 /* | |
| 14846 * In this scenario the expression string will sit in ctxt->base. | |
| 14847 */ | |
| 14848 if ((ctxt->error == XPATH_EXPRESSION_OK) && | 15027 if ((ctxt->error == XPATH_EXPRESSION_OK) && |
| 14849 (ctxt->comp != NULL) && | 15028 (ctxt->comp != NULL) && |
| 14850 » (ctxt->base != NULL) && | 15029 » (ctxt->comp->nbStep > 1) && |
| 14851 » (ctxt->comp->nbStep > 2) && | 15030 » (ctxt->comp->last >= 0)) |
| 14852 » (ctxt->comp->last >= 0) && | |
| 14853 » (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1)) | |
| 14854 { | 15031 { |
| 14855 » xmlXPathRewriteDOSExpression(ctxt->comp, | 15032 » xmlXPathOptimizeExpression(ctxt->comp, |
| 14856 &ctxt->comp->steps[ctxt->comp->last]); | 15033 &ctxt->comp->steps[ctxt->comp->last]); |
| 14857 } | 15034 } |
| 14858 } | 15035 } |
| 14859 CHECK_ERROR; | 15036 CHECK_ERROR; |
| 14860 xmlXPathRunEval(ctxt, 0); | 15037 xmlXPathRunEval(ctxt, 0); |
| 14861 } | 15038 } |
| 14862 | 15039 |
| 14863 /** | 15040 /** |
| 14864 * xmlXPathEval: | 15041 * xmlXPathEval: |
| 14865 * @str: the XPath expression | 15042 * @str: the XPath expression |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14916 if (ctxt->error != XPATH_EXPRESSION_OK) { | 15093 if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 14917 xmlXPathFreeObject(res); | 15094 xmlXPathFreeObject(res); |
| 14918 res = NULL; | 15095 res = NULL; |
| 14919 } | 15096 } |
| 14920 | 15097 |
| 14921 xmlXPathFreeParserContext(ctxt); | 15098 xmlXPathFreeParserContext(ctxt); |
| 14922 return(res); | 15099 return(res); |
| 14923 } | 15100 } |
| 14924 | 15101 |
| 14925 /** | 15102 /** |
| 15103 * xmlXPathSetContextNode: |
| 15104 * @node: the node to to use as the context node |
| 15105 * @ctx: the XPath context |
| 15106 * |
| 15107 * Sets 'node' as the context node. The node must be in the same |
| 15108 * document as that associated with the context. |
| 15109 * |
| 15110 * Returns -1 in case of error or 0 if successful |
| 15111 */ |
| 15112 int |
| 15113 xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) { |
| 15114 if ((node == NULL) || (ctx == NULL)) |
| 15115 return(-1); |
| 15116 |
| 15117 if (node->doc == ctx->doc) { |
| 15118 ctx->node = node; |
| 15119 return(0); |
| 15120 } |
| 15121 return(-1); |
| 15122 } |
| 15123 |
| 15124 /** |
| 15125 * xmlXPathNodeEval: |
| 15126 * @node: the node to to use as the context node |
| 15127 * @str: the XPath expression |
| 15128 * @ctx: the XPath context |
| 15129 * |
| 15130 * Evaluate the XPath Location Path in the given context. The node 'node' |
| 15131 * is set as the context node. The context node is not restored. |
| 15132 * |
| 15133 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. |
| 15134 * the caller has to free the object. |
| 15135 */ |
| 15136 xmlXPathObjectPtr |
| 15137 xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) { |
| 15138 if (str == NULL) |
| 15139 return(NULL); |
| 15140 if (xmlXPathSetContextNode(node, ctx) < 0) |
| 15141 return(NULL); |
| 15142 return(xmlXPathEval(str, ctx)); |
| 15143 } |
| 15144 |
| 15145 /** |
| 14926 * xmlXPathEvalExpression: | 15146 * xmlXPathEvalExpression: |
| 14927 * @str: the XPath expression | 15147 * @str: the XPath expression |
| 14928 * @ctxt: the XPath context | 15148 * @ctxt: the XPath context |
| 14929 * | 15149 * |
| 14930 * Evaluate the XPath expression in the given context. | 15150 * Evaluate the XPath expression in the given context. |
| 14931 * | 15151 * |
| 14932 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. | 15152 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. |
| 14933 * the caller has to free the object. | 15153 * the caller has to free the object. |
| 14934 */ | 15154 */ |
| 14935 xmlXPathObjectPtr | 15155 xmlXPathObjectPtr |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15019 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), true()) | 15239 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), true()) |
| 15020 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%
2FLos%20Angeles%23ocean" | 15240 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%
2FLos%20Angeles%23ocean" |
| 15021 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), false()) | 15241 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), false()) |
| 15022 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angele
s%23ocean" | 15242 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angele
s%23ocean" |
| 15023 * | 15243 * |
| 15024 */ | 15244 */ |
| 15025 static void | 15245 static void |
| 15026 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 15246 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
| 15027 xmlXPathObjectPtr str; | 15247 xmlXPathObjectPtr str; |
| 15028 int escape_reserved; | 15248 int escape_reserved; |
| 15029 xmlBufferPtr target; | 15249 xmlBufPtr target; |
| 15030 xmlChar *cptr; | 15250 xmlChar *cptr; |
| 15031 xmlChar escape[4]; | 15251 xmlChar escape[4]; |
| 15032 | 15252 |
| 15033 CHECK_ARITY(2); | 15253 CHECK_ARITY(2); |
| 15034 | 15254 |
| 15035 escape_reserved = xmlXPathPopBoolean(ctxt); | 15255 escape_reserved = xmlXPathPopBoolean(ctxt); |
| 15036 | 15256 |
| 15037 CAST_TO_STRING; | 15257 CAST_TO_STRING; |
| 15038 str = valuePop(ctxt); | 15258 str = valuePop(ctxt); |
| 15039 | 15259 |
| 15040 target = xmlBufferCreate(); | 15260 target = xmlBufCreate(); |
| 15041 | 15261 |
| 15042 escape[0] = '%'; | 15262 escape[0] = '%'; |
| 15043 escape[3] = 0; | 15263 escape[3] = 0; |
| 15044 | 15264 |
| 15045 if (target) { | 15265 if (target) { |
| 15046 for (cptr = str->stringval; *cptr; cptr++) { | 15266 for (cptr = str->stringval; *cptr; cptr++) { |
| 15047 if ((*cptr >= 'A' && *cptr <= 'Z') || | 15267 if ((*cptr >= 'A' && *cptr <= 'Z') || |
| 15048 (*cptr >= 'a' && *cptr <= 'z') || | 15268 (*cptr >= 'a' && *cptr <= 'z') || |
| 15049 (*cptr >= '0' && *cptr <= '9') || | 15269 (*cptr >= '0' && *cptr <= '9') || |
| 15050 *cptr == '-' || *cptr == '_' || *cptr == '.' || | 15270 *cptr == '-' || *cptr == '_' || *cptr == '.' || |
| 15051 *cptr == '!' || *cptr == '~' || *cptr == '*' || | 15271 *cptr == '!' || *cptr == '~' || *cptr == '*' || |
| 15052 *cptr == '\''|| *cptr == '(' || *cptr == ')' || | 15272 *cptr == '\''|| *cptr == '(' || *cptr == ')' || |
| 15053 (*cptr == '%' && | 15273 (*cptr == '%' && |
| 15054 ((cptr[1] >= 'A' && cptr[1] <= 'F') || | 15274 ((cptr[1] >= 'A' && cptr[1] <= 'F') || |
| 15055 (cptr[1] >= 'a' && cptr[1] <= 'f') || | 15275 (cptr[1] >= 'a' && cptr[1] <= 'f') || |
| 15056 (cptr[1] >= '0' && cptr[1] <= '9')) && | 15276 (cptr[1] >= '0' && cptr[1] <= '9')) && |
| 15057 ((cptr[2] >= 'A' && cptr[2] <= 'F') || | 15277 ((cptr[2] >= 'A' && cptr[2] <= 'F') || |
| 15058 (cptr[2] >= 'a' && cptr[2] <= 'f') || | 15278 (cptr[2] >= 'a' && cptr[2] <= 'f') || |
| 15059 (cptr[2] >= '0' && cptr[2] <= '9'))) || | 15279 (cptr[2] >= '0' && cptr[2] <= '9'))) || |
| 15060 (!escape_reserved && | 15280 (!escape_reserved && |
| 15061 (*cptr == ';' || *cptr == '/' || *cptr == '?' || | 15281 (*cptr == ';' || *cptr == '/' || *cptr == '?' || |
| 15062 *cptr == ':' || *cptr == '@' || *cptr == '&' || | 15282 *cptr == ':' || *cptr == '@' || *cptr == '&' || |
| 15063 *cptr == '=' || *cptr == '+' || *cptr == '$' || | 15283 *cptr == '=' || *cptr == '+' || *cptr == '$' || |
| 15064 *cptr == ','))) { | 15284 *cptr == ','))) { |
| 15065 » » xmlBufferAdd(target, cptr, 1); | 15285 » » xmlBufAdd(target, cptr, 1); |
| 15066 } else { | 15286 } else { |
| 15067 if ((*cptr >> 4) < 10) | 15287 if ((*cptr >> 4) < 10) |
| 15068 escape[1] = '0' + (*cptr >> 4); | 15288 escape[1] = '0' + (*cptr >> 4); |
| 15069 else | 15289 else |
| 15070 escape[1] = 'A' - 10 + (*cptr >> 4); | 15290 escape[1] = 'A' - 10 + (*cptr >> 4); |
| 15071 if ((*cptr & 0xF) < 10) | 15291 if ((*cptr & 0xF) < 10) |
| 15072 escape[2] = '0' + (*cptr & 0xF); | 15292 escape[2] = '0' + (*cptr & 0xF); |
| 15073 else | 15293 else |
| 15074 escape[2] = 'A' - 10 + (*cptr & 0xF); | 15294 escape[2] = 'A' - 10 + (*cptr & 0xF); |
| 15075 | 15295 |
| 15076 » » xmlBufferAdd(target, &escape[0], 3); | 15296 » » xmlBufAdd(target, &escape[0], 3); |
| 15077 } | 15297 } |
| 15078 } | 15298 } |
| 15079 } | 15299 } |
| 15080 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 15300 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
| 15081 » xmlBufferContent(target))); | 15301 » xmlBufContent(target))); |
| 15082 xmlBufferFree(target); | 15302 xmlBufFree(target); |
| 15083 xmlXPathReleaseObject(ctxt->context, str); | 15303 xmlXPathReleaseObject(ctxt->context, str); |
| 15084 } | 15304 } |
| 15085 | 15305 |
| 15086 /** | 15306 /** |
| 15087 * xmlXPathRegisterAllFunctions: | 15307 * xmlXPathRegisterAllFunctions: |
| 15088 * @ctxt: the XPath context | 15308 * @ctxt: the XPath context |
| 15089 * | 15309 * |
| 15090 * Registers all default XPath functions in this context | 15310 * Registers all default XPath functions in this context |
| 15091 */ | 15311 */ |
| 15092 void | 15312 void |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15148 xmlXPathTranslateFunction); | 15368 xmlXPathTranslateFunction); |
| 15149 | 15369 |
| 15150 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", | 15370 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", |
| 15151 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", | 15371 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", |
| 15152 xmlXPathEscapeUriFunction); | 15372 xmlXPathEscapeUriFunction); |
| 15153 } | 15373 } |
| 15154 | 15374 |
| 15155 #endif /* LIBXML_XPATH_ENABLED */ | 15375 #endif /* LIBXML_XPATH_ENABLED */ |
| 15156 #define bottom_xpath | 15376 #define bottom_xpath |
| 15157 #include "elfgcchack.h" | 15377 #include "elfgcchack.h" |
| OLD | NEW |