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 |