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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 #ifdef LIBXML_PATTERN_ENABLED | 58 #ifdef LIBXML_PATTERN_ENABLED |
59 #define XPATH_STREAMING | 59 #define XPATH_STREAMING |
60 #endif | 60 #endif |
61 | 61 |
62 #define TODO » » » » » » » » \ | 62 #define TODO» » » » » » » » \ |
63 xmlGenericError(xmlGenericErrorContext, \ | 63 xmlGenericError(xmlGenericErrorContext, \ |
64 "Unimplemented block at %s:%d\n", \ | 64 "Unimplemented block at %s:%d\n", \ |
65 __FILE__, __LINE__); | 65 __FILE__, __LINE__); |
66 | 66 |
67 /* | 67 /* |
68 * XP_OPTIMIZED_NON_ELEM_COMPARISON: | 68 * XP_OPTIMIZED_NON_ELEM_COMPARISON: |
69 * If defined, this will use xmlXPathCmpNodesExt() instead of | 69 * If defined, this will use xmlXPathCmpNodesExt() instead of |
70 * xmlXPathCmpNodes(). The new function is optimized comparison of | 70 * xmlXPathCmpNodes(). The new function is optimized comparison of |
71 * non-element nodes; actually it will speed up comparison only if | 71 * non-element nodes; actually it will speed up comparison only if |
72 * xmlXPathOrderDocElems() was called in order to index the elements of | 72 * xmlXPathOrderDocElems() was called in order to index the elements of |
73 * a tree in document order; Libxslt does such an indexing, thus it will | 73 * a tree in document order; Libxslt does such an indexing, thus it will |
74 * benefit from this optimization. | 74 * benefit from this optimization. |
75 */ | 75 */ |
76 #define XP_OPTIMIZED_NON_ELEM_COMPARISON | 76 #define XP_OPTIMIZED_NON_ELEM_COMPARISON |
77 | 77 |
78 /* | 78 /* |
79 * XP_OPTIMIZED_FILTER_FIRST: | 79 * XP_OPTIMIZED_FILTER_FIRST: |
80 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]" | 80 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]" |
81 * in a way, that it stop evaluation at the first node. | 81 * in a way, that it stop evaluation at the first node. |
82 */ | 82 */ |
83 #define XP_OPTIMIZED_FILTER_FIRST | 83 #define XP_OPTIMIZED_FILTER_FIRST |
84 | 84 |
85 /* | 85 /* |
86 * XP_DEBUG_OBJ_USAGE: | 86 * XP_DEBUG_OBJ_USAGE: |
87 * Internal flag to enable tracking of how much XPath objects have been | 87 * Internal flag to enable tracking of how much XPath objects have been |
88 * created. | 88 * created. |
89 */ | 89 */ |
90 /* #define XP_DEBUG_OBJ_USAGE */ | 90 /* #define XP_DEBUG_OBJ_USAGE */ |
91 | 91 |
92 /* | 92 /* |
93 * TODO: | 93 * TODO: |
94 * There are a few spots where some tests are done which depend upon ascii | 94 * 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 | 95 * data. These should be enhanced for full UTF8 support (see particularly |
96 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT) | 96 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT) |
97 */ | 97 */ |
98 | 98 |
99 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) | 99 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) |
100 | 100 |
101 /************************************************************************ | 101 /************************************************************************ |
102 * » » » » » » » » » * | 102 *» » » » » » » » » * |
103 * » » » Floating point stuff» » » » * | 103 *» » » Floating point stuff» » » » * |
104 * » » » » » » » » » * | 104 *» » » » » » » » » * |
105 ************************************************************************/ | 105 ************************************************************************/ |
106 | 106 |
107 #ifndef TRIO_REPLACE_STDIO | 107 #ifndef TRIO_REPLACE_STDIO |
108 #define TRIO_PUBLIC static | 108 #define TRIO_PUBLIC static |
109 #endif | 109 #endif |
110 #include "trionan.c" | 110 #include "trionan.c" |
111 | 111 |
112 /* | 112 /* |
113 * The lack of portability of this section of the libc is annoying ! | 113 * The lack of portability of this section of the libc is annoying ! |
114 */ | 114 */ |
(...skipping 20 matching lines...) Expand all Loading... |
135 xmlXPathInitialized = 1; | 135 xmlXPathInitialized = 1; |
136 } | 136 } |
137 | 137 |
138 /** | 138 /** |
139 * xmlXPathIsNaN: | 139 * xmlXPathIsNaN: |
140 * @val: a double value | 140 * @val: a double value |
141 * | 141 * |
142 * Provides a portable isnan() function to detect whether a double | 142 * Provides a portable isnan() function to detect whether a double |
143 * is a NotaNumber. Based on trio code | 143 * is a NotaNumber. Based on trio code |
144 * http://sourceforge.net/projects/ctrio/ | 144 * http://sourceforge.net/projects/ctrio/ |
145 * | 145 * |
146 * Returns 1 if the value is a NaN, 0 otherwise | 146 * Returns 1 if the value is a NaN, 0 otherwise |
147 */ | 147 */ |
148 int | 148 int |
149 xmlXPathIsNaN(double val) { | 149 xmlXPathIsNaN(double val) { |
150 return(trio_isnan(val)); | 150 return(trio_isnan(val)); |
151 } | 151 } |
152 | 152 |
153 /** | 153 /** |
154 * xmlXPathIsInf: | 154 * xmlXPathIsInf: |
155 * @val: a double value | 155 * @val: a double value |
156 * | 156 * |
157 * Provides a portable isinf() function to detect whether a double | 157 * Provides a portable isinf() function to detect whether a double |
158 * is a +Infinite or -Infinite. Based on trio code | 158 * is a +Infinite or -Infinite. Based on trio code |
159 * http://sourceforge.net/projects/ctrio/ | 159 * http://sourceforge.net/projects/ctrio/ |
160 * | 160 * |
161 * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise | 161 * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise |
162 */ | 162 */ |
163 int | 163 int |
164 xmlXPathIsInf(double val) { | 164 xmlXPathIsInf(double val) { |
165 return(trio_isinf(val)); | 165 return(trio_isinf(val)); |
166 } | 166 } |
167 | 167 |
168 #endif /* SCHEMAS or XPATH */ | 168 #endif /* SCHEMAS or XPATH */ |
169 #ifdef LIBXML_XPATH_ENABLED | 169 #ifdef LIBXML_XPATH_ENABLED |
170 /** | 170 /** |
171 * xmlXPathGetSign: | 171 * xmlXPathGetSign: |
172 * @val: a double value | 172 * @val: a double value |
173 * | 173 * |
174 * Provides a portable function to detect the sign of a double | 174 * Provides a portable function to detect the sign of a double |
175 * Modified from trio code | 175 * Modified from trio code |
176 * http://sourceforge.net/projects/ctrio/ | 176 * http://sourceforge.net/projects/ctrio/ |
177 * | 177 * |
178 * Returns 1 if the value is Negative, 0 if positive | 178 * Returns 1 if the value is Negative, 0 if positive |
179 */ | 179 */ |
180 static int | 180 static int |
181 xmlXPathGetSign(double val) { | 181 xmlXPathGetSign(double val) { |
182 return(trio_signbit(val)); | 182 return(trio_signbit(val)); |
183 } | 183 } |
184 | 184 |
185 | 185 |
186 /* | 186 /* |
187 * TODO: when compatibility allows remove all "fake node libxslt" strings | 187 * TODO: when compatibility allows remove all "fake node libxslt" strings |
188 * the test should just be name[0] = ' ' | 188 * the test should just be name[0] = ' ' |
189 */ | 189 */ |
190 /* #define DEBUG */ | 190 #ifdef DEBUG_XPATH_EXPRESSION |
191 /* #define DEBUG_STEP */ | 191 #define DEBUG_STEP |
192 /* #define DEBUG_STEP_NTH */ | 192 #define DEBUG_EXPR |
193 /* #define DEBUG_EXPR */ | 193 #define DEBUG_EVAL_COUNTS |
194 /* #define DEBUG_EVAL_COUNTS */ | 194 #endif |
195 | 195 |
196 static xmlNs xmlXPathXMLNamespaceStruct = { | 196 static xmlNs xmlXPathXMLNamespaceStruct = { |
197 NULL, | 197 NULL, |
198 XML_NAMESPACE_DECL, | 198 XML_NAMESPACE_DECL, |
199 XML_XML_NAMESPACE, | 199 XML_XML_NAMESPACE, |
200 BAD_CAST "xml", | 200 BAD_CAST "xml", |
201 NULL, | 201 NULL, |
202 NULL | 202 NULL |
203 }; | 203 }; |
204 static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct; | 204 static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct; |
205 #ifndef LIBXML_THREAD_ENABLED | 205 #ifndef LIBXML_THREAD_ENABLED |
206 /* | 206 /* |
207 * Optimizer is disabled only when threaded apps are detected while | 207 * Optimizer is disabled only when threaded apps are detected while |
208 * the library ain't compiled for thread safety. | 208 * the library ain't compiled for thread safety. |
209 */ | 209 */ |
210 static int xmlXPathDisableOptimizer = 0; | 210 static int xmlXPathDisableOptimizer = 0; |
211 #endif | 211 #endif |
212 | 212 |
213 /************************************************************************ | 213 /************************************************************************ |
214 * * | 214 * * |
215 * Error handling routines * | 215 * Error handling routines * |
216 * * | 216 * * |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 xmlXPathErr(xmlXPathParserContextPtr ctxt, int error) | 327 xmlXPathErr(xmlXPathParserContextPtr ctxt, int error) |
328 { | 328 { |
329 if ((error < 0) || (error > MAXERRNO)) | 329 if ((error < 0) || (error > MAXERRNO)) |
330 error = MAXERRNO; | 330 error = MAXERRNO; |
331 if (ctxt == NULL) { | 331 if (ctxt == NULL) { |
332 __xmlRaiseError(NULL, NULL, NULL, | 332 __xmlRaiseError(NULL, NULL, NULL, |
333 NULL, NULL, XML_FROM_XPATH, | 333 NULL, NULL, XML_FROM_XPATH, |
334 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, | 334 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, |
335 XML_ERR_ERROR, NULL, 0, | 335 XML_ERR_ERROR, NULL, 0, |
336 NULL, NULL, NULL, 0, 0, | 336 NULL, NULL, NULL, 0, 0, |
337 » » » xmlXPathErrorMessages[error]); | 337 » » » "%s", xmlXPathErrorMessages[error]); |
338 return; | 338 return; |
339 } | 339 } |
340 ctxt->error = error; | 340 ctxt->error = error; |
341 if (ctxt->context == NULL) { | 341 if (ctxt->context == NULL) { |
342 __xmlRaiseError(NULL, NULL, NULL, | 342 __xmlRaiseError(NULL, NULL, NULL, |
343 NULL, NULL, XML_FROM_XPATH, | 343 NULL, NULL, XML_FROM_XPATH, |
344 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, | 344 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, |
345 XML_ERR_ERROR, NULL, 0, | 345 XML_ERR_ERROR, NULL, 0, |
346 (const char *) ctxt->base, NULL, NULL, | 346 (const char *) ctxt->base, NULL, NULL, |
347 ctxt->cur - ctxt->base, 0, | 347 ctxt->cur - ctxt->base, 0, |
348 » » » xmlXPathErrorMessages[error]); | 348 » » » "%s", xmlXPathErrorMessages[error]); |
349 return; | 349 return; |
350 } | 350 } |
351 | 351 |
352 /* cleanup current last error */ | 352 /* cleanup current last error */ |
353 xmlResetError(&ctxt->context->lastError); | 353 xmlResetError(&ctxt->context->lastError); |
354 | 354 |
355 ctxt->context->lastError.domain = XML_FROM_XPATH; | 355 ctxt->context->lastError.domain = XML_FROM_XPATH; |
356 ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK - | 356 ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK - |
357 XPATH_EXPRESSION_OK; | 357 XPATH_EXPRESSION_OK; |
358 ctxt->context->lastError.level = XML_ERR_ERROR; | 358 ctxt->context->lastError.level = XML_ERR_ERROR; |
359 ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); | 359 ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); |
360 ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; | 360 ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; |
361 ctxt->context->lastError.node = ctxt->context->debugNode; | 361 ctxt->context->lastError.node = ctxt->context->debugNode; |
362 if (ctxt->context->error != NULL) { | 362 if (ctxt->context->error != NULL) { |
363 ctxt->context->error(ctxt->context->userData, | 363 ctxt->context->error(ctxt->context->userData, |
364 &ctxt->context->lastError); | 364 &ctxt->context->lastError); |
365 } else { | 365 } else { |
366 __xmlRaiseError(NULL, NULL, NULL, | 366 __xmlRaiseError(NULL, NULL, NULL, |
367 NULL, ctxt->context->debugNode, XML_FROM_XPATH, | 367 NULL, ctxt->context->debugNode, XML_FROM_XPATH, |
368 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, | 368 error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK, |
369 XML_ERR_ERROR, NULL, 0, | 369 XML_ERR_ERROR, NULL, 0, |
370 (const char *) ctxt->base, NULL, NULL, | 370 (const char *) ctxt->base, NULL, NULL, |
371 ctxt->cur - ctxt->base, 0, | 371 ctxt->cur - ctxt->base, 0, |
372 » » » xmlXPathErrorMessages[error]); | 372 » » » "%s", xmlXPathErrorMessages[error]); |
373 } | 373 } |
374 | 374 |
375 } | 375 } |
376 | 376 |
377 /** | 377 /** |
378 * xmlXPatherror: | 378 * xmlXPatherror: |
379 * @ctxt: the XPath Parser context | 379 * @ctxt: the XPath Parser context |
380 * @file: the file name | 380 * @file: the file name |
381 * @line: the line number | 381 * @line: the line number |
382 * @no: the error number | 382 * @no: the error number |
383 * | 383 * |
384 * Formats an error message. | 384 * Formats an error message. |
385 */ | 385 */ |
386 void | 386 void |
387 xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED, | 387 xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED, |
388 int line ATTRIBUTE_UNUSED, int no) { | 388 int line ATTRIBUTE_UNUSED, int no) { |
389 xmlXPathErr(ctxt, no); | 389 xmlXPathErr(ctxt, no); |
390 } | 390 } |
391 | 391 |
392 /************************************************************************ | 392 /************************************************************************ |
393 * » » » » » » » » » * | 393 *» » » » » » » » » * |
394 * » » » Utilities» » » » » * | 394 *» » » Utilities» » » » » * |
395 * » » » » » » » » » * | 395 *» » » » » » » » » * |
396 ************************************************************************/ | 396 ************************************************************************/ |
397 | 397 |
398 /** | 398 /** |
399 * xsltPointerList: | 399 * xsltPointerList: |
400 * | 400 * |
401 * Pointer-list for various purposes. | 401 * Pointer-list for various purposes. |
402 */ | 402 */ |
403 typedef struct _xmlPointerList xmlPointerList; | 403 typedef struct _xmlPointerList xmlPointerList; |
404 typedef xmlPointerList *xmlPointerListPtr; | 404 typedef xmlPointerList *xmlPointerListPtr; |
405 struct _xmlPointerList { | 405 struct _xmlPointerList { |
406 void **items; | 406 void **items; |
407 int number; | 407 int number; |
408 int size; | 408 int size; |
409 }; | 409 }; |
410 /* | 410 /* |
411 * TODO: Since such a list-handling is used in xmlschemas.c and libxslt | 411 * TODO: Since such a list-handling is used in xmlschemas.c and libxslt |
412 * and here, we should make the functions public. | 412 * and here, we should make the functions public. |
413 */ | 413 */ |
414 static int | 414 static int |
415 xmlPointerListAddSize(xmlPointerListPtr list,» » | 415 xmlPointerListAddSize(xmlPointerListPtr list, |
416 void *item, | 416 void *item, |
417 int initialSize) | 417 int initialSize) |
418 { | 418 { |
419 if (list->items == NULL) { | 419 if (list->items == NULL) { |
420 if (initialSize <= 0) | 420 if (initialSize <= 0) |
421 initialSize = 1; | 421 initialSize = 1; |
422 list->items = (void **) xmlMalloc( | 422 list->items = (void **) xmlMalloc( |
423 initialSize * sizeof(void *)); | 423 initialSize * sizeof(void *)); |
424 if (list->items == NULL) { | 424 if (list->items == NULL) { |
425 xmlXPathErrMemory(NULL, | 425 xmlXPathErrMemory(NULL, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 xmlPointerListFree(xmlPointerListPtr list) | 479 xmlPointerListFree(xmlPointerListPtr list) |
480 { | 480 { |
481 if (list == NULL) | 481 if (list == NULL) |
482 return; | 482 return; |
483 if (list->items != NULL) | 483 if (list->items != NULL) |
484 xmlFree(list->items); | 484 xmlFree(list->items); |
485 xmlFree(list); | 485 xmlFree(list); |
486 } | 486 } |
487 | 487 |
488 /************************************************************************ | 488 /************************************************************************ |
489 * » » » » » » » » » * | 489 *» » » » » » » » » * |
490 * » » » Parser Types» » » » » * | 490 *» » » Parser Types» » » » » * |
491 * » » » » » » » » » * | 491 *» » » » » » » » » * |
492 ************************************************************************/ | 492 ************************************************************************/ |
493 | 493 |
494 /* | 494 /* |
495 * Types are private: | 495 * Types are private: |
496 */ | 496 */ |
497 | 497 |
498 typedef enum { | 498 typedef enum { |
499 XPATH_OP_END=0, | 499 XPATH_OP_END=0, |
500 XPATH_OP_AND, | 500 XPATH_OP_AND, |
501 XPATH_OP_OR, | 501 XPATH_OP_OR, |
(...skipping 24 matching lines...) Expand all Loading... |
526 AXIS_ATTRIBUTE, | 526 AXIS_ATTRIBUTE, |
527 AXIS_CHILD, | 527 AXIS_CHILD, |
528 AXIS_DESCENDANT, | 528 AXIS_DESCENDANT, |
529 AXIS_DESCENDANT_OR_SELF, | 529 AXIS_DESCENDANT_OR_SELF, |
530 AXIS_FOLLOWING, | 530 AXIS_FOLLOWING, |
531 AXIS_FOLLOWING_SIBLING, | 531 AXIS_FOLLOWING_SIBLING, |
532 AXIS_NAMESPACE, | 532 AXIS_NAMESPACE, |
533 AXIS_PARENT, | 533 AXIS_PARENT, |
534 AXIS_PRECEDING, | 534 AXIS_PRECEDING, |
535 AXIS_PRECEDING_SIBLING, | 535 AXIS_PRECEDING_SIBLING, |
536 AXIS_SELF | 536 AXIS_SELF |
537 } xmlXPathAxisVal; | 537 } xmlXPathAxisVal; |
538 | 538 |
539 typedef enum { | 539 typedef enum { |
540 NODE_TEST_NONE = 0, | 540 NODE_TEST_NONE = 0, |
541 NODE_TEST_TYPE = 1, | 541 NODE_TEST_TYPE = 1, |
542 NODE_TEST_PI = 2, | 542 NODE_TEST_PI = 2, |
543 NODE_TEST_ALL = 3, | 543 NODE_TEST_ALL = 3, |
544 NODE_TEST_NS = 4, | 544 NODE_TEST_NS = 4, |
545 NODE_TEST_NAME = 5 | 545 NODE_TEST_NAME = 5 |
546 } xmlXPathTestVal; | 546 } xmlXPathTestVal; |
547 | 547 |
548 typedef enum { | 548 typedef enum { |
549 NODE_TYPE_NODE = 0, | 549 NODE_TYPE_NODE = 0, |
550 NODE_TYPE_COMMENT = XML_COMMENT_NODE, | 550 NODE_TYPE_COMMENT = XML_COMMENT_NODE, |
551 NODE_TYPE_TEXT = XML_TEXT_NODE, | 551 NODE_TYPE_TEXT = XML_TEXT_NODE, |
552 NODE_TYPE_PI = XML_PI_NODE | 552 NODE_TYPE_PI = XML_PI_NODE |
553 } xmlXPathTypeVal; | 553 } xmlXPathTypeVal; |
554 | 554 |
555 #define XP_REWRITE_DOS_CHILD_ELEM 1 | 555 #define XP_REWRITE_DOS_CHILD_ELEM 1 |
556 | 556 |
557 typedef struct _xmlXPathStepOp xmlXPathStepOp; | 557 typedef struct _xmlXPathStepOp xmlXPathStepOp; |
558 typedef xmlXPathStepOp *xmlXPathStepOpPtr; | 558 typedef xmlXPathStepOp *xmlXPathStepOpPtr; |
559 struct _xmlXPathStepOp { | 559 struct _xmlXPathStepOp { |
560 xmlXPathOp op; /* The identifier of the operation */ | 560 xmlXPathOp op; /* The identifier of the operation */ |
561 int ch1; /* First child */ | 561 int ch1; /* First child */ |
562 int ch2; /* Second child */ | 562 int ch2; /* Second child */ |
(...skipping 17 matching lines...) Expand all Loading... |
580 #ifdef DEBUG_EVAL_COUNTS | 580 #ifdef DEBUG_EVAL_COUNTS |
581 int nb; | 581 int nb; |
582 xmlChar *string; | 582 xmlChar *string; |
583 #endif | 583 #endif |
584 #ifdef XPATH_STREAMING | 584 #ifdef XPATH_STREAMING |
585 xmlPatternPtr stream; | 585 xmlPatternPtr stream; |
586 #endif | 586 #endif |
587 }; | 587 }; |
588 | 588 |
589 /************************************************************************ | 589 /************************************************************************ |
590 * » » » » » » » » » * | 590 *» » » » » » » » » * |
591 * » » » Forward declarations» » » » * | 591 *» » » Forward declarations» » » » * |
592 * » » » » » » » » » * | 592 *» » » » » » » » » * |
593 ************************************************************************/ | 593 ************************************************************************/ |
594 static void | 594 static void |
595 xmlXPathFreeValueTree(xmlNodeSetPtr obj); | 595 xmlXPathFreeValueTree(xmlNodeSetPtr obj); |
596 static void | 596 static void |
597 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj); | 597 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj); |
598 static int | 598 static int |
599 xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, | 599 xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, |
600 xmlXPathStepOpPtr op, xmlNodePtr *first); | 600 xmlXPathStepOpPtr op, xmlNodePtr *first); |
601 static int | 601 static int |
602 xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt, | 602 xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt, |
603 xmlXPathStepOpPtr op, | 603 xmlXPathStepOpPtr op, |
604 int isPredicate); | 604 int isPredicate); |
605 | 605 |
606 /************************************************************************ | 606 /************************************************************************ |
607 * » » » » » » » » » * | 607 *» » » » » » » » » * |
608 * » » » Parser Type functions » » » » * | 608 *» » » Parser Type functions» » » » * |
609 * » » » » » » » » » * | 609 *» » » » » » » » » * |
610 ************************************************************************/ | 610 ************************************************************************/ |
611 | 611 |
612 /** | 612 /** |
613 * xmlXPathNewCompExpr: | 613 * xmlXPathNewCompExpr: |
614 * | 614 * |
615 * Create a new Xpath component | 615 * Create a new Xpath component |
616 * | 616 * |
617 * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error | 617 * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error |
618 */ | 618 */ |
619 static xmlXPathCompExprPtr | 619 static xmlXPathCompExprPtr |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 op->ch2 = tmp; | 789 op->ch2 = tmp; |
790 } | 790 } |
791 | 791 |
792 #define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \ | 792 #define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \ |
793 xmlXPathCompExprAdd(ctxt->comp, (op1), (op2), \ | 793 xmlXPathCompExprAdd(ctxt->comp, (op1), (op2), \ |
794 (op), (val), (val2), (val3), (val4), (val5)) | 794 (op), (val), (val2), (val3), (val4), (val5)) |
795 #define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \ | 795 #define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \ |
796 xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1, \ | 796 xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1, \ |
797 (op), (val), (val2), (val3), (val4), (val5)) | 797 (op), (val), (val2), (val3), (val4), (val5)) |
798 | 798 |
799 #define PUSH_LEAVE_EXPR(op, val, val2) »» » » » \ | 799 #define PUSH_LEAVE_EXPR(op, val, val2)» » » » » \ |
800 xmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL) | 800 xmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL) |
801 | 801 |
802 #define PUSH_UNARY_EXPR(op, ch, val, val2) » » » » \ | 802 #define PUSH_UNARY_EXPR(op, ch, val, val2)» » » » \ |
803 xmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL) | 803 xmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL) |
804 | 804 |
805 #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) » » » \ | 805 #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2)» » » \ |
806 xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), \ | 806 xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), \ |
807 (val), (val2), 0 ,NULL ,NULL) | 807 (val), (val2), 0 ,NULL ,NULL) |
808 | 808 |
809 /************************************************************************ | 809 /************************************************************************ |
810 * * | 810 * * |
811 * » » XPath object cache structures» » » » * | 811 *» » XPath object cache structures» » » » * |
812 * * | 812 * * |
813 ************************************************************************/ | 813 ************************************************************************/ |
814 | 814 |
815 /* #define XP_DEFAULT_CACHE_ON */ | 815 /* #define XP_DEFAULT_CACHE_ON */ |
816 | 816 |
817 #define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL)) | 817 #define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL)) |
818 | 818 |
819 typedef struct _xmlXPathContextCache xmlXPathContextCache; | 819 typedef struct _xmlXPathContextCache xmlXPathContextCache; |
820 typedef xmlXPathContextCache *xmlXPathContextCachePtr; | 820 typedef xmlXPathContextCache *xmlXPathContextCachePtr; |
821 struct _xmlXPathContextCache { | 821 struct _xmlXPathContextCache { |
(...skipping 11 matching lines...) Expand all Loading... |
833 int dbgCachedAll; | 833 int dbgCachedAll; |
834 int dbgCachedNodeset; | 834 int dbgCachedNodeset; |
835 int dbgCachedString; | 835 int dbgCachedString; |
836 int dbgCachedBool; | 836 int dbgCachedBool; |
837 int dbgCachedNumber; | 837 int dbgCachedNumber; |
838 int dbgCachedPoint; | 838 int dbgCachedPoint; |
839 int dbgCachedRange; | 839 int dbgCachedRange; |
840 int dbgCachedLocset; | 840 int dbgCachedLocset; |
841 int dbgCachedUsers; | 841 int dbgCachedUsers; |
842 int dbgCachedXSLTTree; | 842 int dbgCachedXSLTTree; |
843 int dbgCachedUndefined; | 843 int dbgCachedUndefined; |
844 | 844 |
845 | 845 |
846 int dbgReusedAll; | 846 int dbgReusedAll; |
847 int dbgReusedNodeset; | 847 int dbgReusedNodeset; |
848 int dbgReusedString; | 848 int dbgReusedString; |
849 int dbgReusedBool; | 849 int dbgReusedBool; |
850 int dbgReusedNumber; | 850 int dbgReusedNumber; |
851 int dbgReusedPoint; | 851 int dbgReusedPoint; |
852 int dbgReusedRange; | 852 int dbgReusedRange; |
853 int dbgReusedLocset; | 853 int dbgReusedLocset; |
854 int dbgReusedUsers; | 854 int dbgReusedUsers; |
855 int dbgReusedXSLTTree; | 855 int dbgReusedXSLTTree; |
856 int dbgReusedUndefined; | 856 int dbgReusedUndefined; |
857 | 857 |
858 #endif | 858 #endif |
859 }; | 859 }; |
860 | 860 |
861 /************************************************************************ | 861 /************************************************************************ |
862 * * | 862 * * |
863 * » » Debugging related functions» » » » * | 863 *» » Debugging related functions» » » » * |
864 * * | 864 * * |
865 ************************************************************************/ | 865 ************************************************************************/ |
866 | 866 |
867 #define STRANGE » » » » » » » \ | 867 #define STRANGE»» » » » » » \ |
868 xmlGenericError(xmlGenericErrorContext, \ | 868 xmlGenericError(xmlGenericErrorContext, \ |
869 "Internal error at %s:%d\n", \ | 869 "Internal error at %s:%d\n", \ |
870 __FILE__, __LINE__); | 870 __FILE__, __LINE__); |
871 | 871 |
872 #ifdef LIBXML_DEBUG_ENABLED | 872 #ifdef LIBXML_DEBUG_ENABLED |
873 static void | 873 static void |
874 xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) { | 874 xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) { |
875 int i; | 875 int i; |
876 char shift[100]; | 876 char shift[100]; |
877 | 877 |
878 for (i = 0;((i < depth) && (i < 25));i++) | 878 for (i = 0;((i < depth) && (i < 25));i++) |
879 shift[2 * i] = shift[2 * i + 1] = ' '; | 879 shift[2 * i] = shift[2 * i + 1] = ' '; |
880 shift[2 * i] = shift[2 * i + 1] = 0; | 880 shift[2 * i] = shift[2 * i + 1] = 0; |
881 if (cur == NULL) { | 881 if (cur == NULL) { |
882 » fprintf(output, shift); | 882 » fprintf(output, "%s", shift); |
883 fprintf(output, "Node is NULL !\n"); | 883 fprintf(output, "Node is NULL !\n"); |
884 return; | 884 return; |
885 | 885 |
886 } | 886 } |
887 | 887 |
888 if ((cur->type == XML_DOCUMENT_NODE) || | 888 if ((cur->type == XML_DOCUMENT_NODE) || |
889 (cur->type == XML_HTML_DOCUMENT_NODE)) { | 889 (cur->type == XML_HTML_DOCUMENT_NODE)) { |
890 » fprintf(output, shift); | 890 » fprintf(output, "%s", shift); |
891 fprintf(output, " /\n"); | 891 fprintf(output, " /\n"); |
892 } else if (cur->type == XML_ATTRIBUTE_NODE) | 892 } else if (cur->type == XML_ATTRIBUTE_NODE) |
893 xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth); | 893 xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth); |
894 else | 894 else |
895 xmlDebugDumpOneNode(output, cur, depth); | 895 xmlDebugDumpOneNode(output, cur, depth); |
896 } | 896 } |
897 static void | 897 static void |
898 xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) { | 898 xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) { |
899 xmlNodePtr tmp; | 899 xmlNodePtr tmp; |
900 int i; | 900 int i; |
901 char shift[100]; | 901 char shift[100]; |
902 | 902 |
903 for (i = 0;((i < depth) && (i < 25));i++) | 903 for (i = 0;((i < depth) && (i < 25));i++) |
904 shift[2 * i] = shift[2 * i + 1] = ' '; | 904 shift[2 * i] = shift[2 * i + 1] = ' '; |
905 shift[2 * i] = shift[2 * i + 1] = 0; | 905 shift[2 * i] = shift[2 * i + 1] = 0; |
906 if (cur == NULL) { | 906 if (cur == NULL) { |
907 » fprintf(output, shift); | 907 » fprintf(output, "%s", shift); |
908 fprintf(output, "Node is NULL !\n"); | 908 fprintf(output, "Node is NULL !\n"); |
909 return; | 909 return; |
910 | 910 |
911 } | 911 } |
912 | 912 |
913 while (cur != NULL) { | 913 while (cur != NULL) { |
914 tmp = cur; | 914 tmp = cur; |
915 cur = cur->next; | 915 cur = cur->next; |
916 xmlDebugDumpOneNode(output, tmp, depth); | 916 xmlDebugDumpOneNode(output, tmp, depth); |
917 } | 917 } |
918 } | 918 } |
919 | 919 |
920 static void | 920 static void |
921 xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) { | 921 xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) { |
922 int i; | 922 int i; |
923 char shift[100]; | 923 char shift[100]; |
924 | 924 |
925 for (i = 0;((i < depth) && (i < 25));i++) | 925 for (i = 0;((i < depth) && (i < 25));i++) |
926 shift[2 * i] = shift[2 * i + 1] = ' '; | 926 shift[2 * i] = shift[2 * i + 1] = ' '; |
927 shift[2 * i] = shift[2 * i + 1] = 0; | 927 shift[2 * i] = shift[2 * i + 1] = 0; |
928 | 928 |
929 if (cur == NULL) { | 929 if (cur == NULL) { |
930 » fprintf(output, shift); | 930 » fprintf(output, "%s", shift); |
931 fprintf(output, "NodeSet is NULL !\n"); | 931 fprintf(output, "NodeSet is NULL !\n"); |
932 return; | 932 return; |
933 | 933 |
934 } | 934 } |
935 | 935 |
936 if (cur != NULL) { | 936 if (cur != NULL) { |
937 fprintf(output, "Set contains %d nodes:\n", cur->nodeNr); | 937 fprintf(output, "Set contains %d nodes:\n", cur->nodeNr); |
938 for (i = 0;i < cur->nodeNr;i++) { | 938 for (i = 0;i < cur->nodeNr;i++) { |
939 » fprintf(output, shift); | 939 » fprintf(output, "%s", shift); |
940 fprintf(output, "%d", i + 1); | 940 fprintf(output, "%d", i + 1); |
941 xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1); | 941 xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1); |
942 } | 942 } |
943 } | 943 } |
944 } | 944 } |
945 | 945 |
946 static void | 946 static void |
947 xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) { | 947 xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) { |
948 int i; | 948 int i; |
949 char shift[100]; | 949 char shift[100]; |
950 | 950 |
951 for (i = 0;((i < depth) && (i < 25));i++) | 951 for (i = 0;((i < depth) && (i < 25));i++) |
952 shift[2 * i] = shift[2 * i + 1] = ' '; | 952 shift[2 * i] = shift[2 * i + 1] = ' '; |
953 shift[2 * i] = shift[2 * i + 1] = 0; | 953 shift[2 * i] = shift[2 * i + 1] = 0; |
954 | 954 |
955 if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) { | 955 if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) { |
956 » fprintf(output, shift); | 956 » fprintf(output, "%s", shift); |
957 fprintf(output, "Value Tree is NULL !\n"); | 957 fprintf(output, "Value Tree is NULL !\n"); |
958 return; | 958 return; |
959 | 959 |
960 } | 960 } |
961 | 961 |
962 fprintf(output, shift); | 962 fprintf(output, "%s", shift); |
963 fprintf(output, "%d", i + 1); | 963 fprintf(output, "%d", i + 1); |
964 xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1); | 964 xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1); |
965 } | 965 } |
966 #if defined(LIBXML_XPTR_ENABLED) | 966 #if defined(LIBXML_XPTR_ENABLED) |
967 static void | 967 static void |
968 xmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) { | 968 xmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) { |
969 int i; | 969 int i; |
970 char shift[100]; | 970 char shift[100]; |
971 | 971 |
972 for (i = 0;((i < depth) && (i < 25));i++) | 972 for (i = 0;((i < depth) && (i < 25));i++) |
973 shift[2 * i] = shift[2 * i + 1] = ' '; | 973 shift[2 * i] = shift[2 * i + 1] = ' '; |
974 shift[2 * i] = shift[2 * i + 1] = 0; | 974 shift[2 * i] = shift[2 * i + 1] = 0; |
975 | 975 |
976 if (cur == NULL) { | 976 if (cur == NULL) { |
977 » fprintf(output, shift); | 977 » fprintf(output, "%s", shift); |
978 fprintf(output, "LocationSet is NULL !\n"); | 978 fprintf(output, "LocationSet is NULL !\n"); |
979 return; | 979 return; |
980 | 980 |
981 } | 981 } |
982 | 982 |
983 for (i = 0;i < cur->locNr;i++) { | 983 for (i = 0;i < cur->locNr;i++) { |
984 » fprintf(output, shift); | 984 » fprintf(output, "%s", shift); |
985 fprintf(output, "%d : ", i + 1); | 985 fprintf(output, "%d : ", i + 1); |
986 xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1); | 986 xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1); |
987 } | 987 } |
988 } | 988 } |
989 #endif /* LIBXML_XPTR_ENABLED */ | 989 #endif /* LIBXML_XPTR_ENABLED */ |
990 | 990 |
991 /** | 991 /** |
992 * xmlXPathDebugDumpObject: | 992 * xmlXPathDebugDumpObject: |
993 * @output: the FILE * to dump the output | 993 * @output: the FILE * to dump the output |
994 * @cur: the object to inspect | 994 * @cur: the object to inspect |
995 * @depth: indentation level | 995 * @depth: indentation level |
996 * | 996 * |
997 * Dump the content of the object for debugging purposes | 997 * Dump the content of the object for debugging purposes |
998 */ | 998 */ |
999 void | 999 void |
1000 xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) { | 1000 xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) { |
1001 int i; | 1001 int i; |
1002 char shift[100]; | 1002 char shift[100]; |
1003 | 1003 |
1004 if (output == NULL) return; | 1004 if (output == NULL) return; |
1005 | 1005 |
1006 for (i = 0;((i < depth) && (i < 25));i++) | 1006 for (i = 0;((i < depth) && (i < 25));i++) |
1007 shift[2 * i] = shift[2 * i + 1] = ' '; | 1007 shift[2 * i] = shift[2 * i + 1] = ' '; |
1008 shift[2 * i] = shift[2 * i + 1] = 0; | 1008 shift[2 * i] = shift[2 * i + 1] = 0; |
1009 | 1009 |
1010 | 1010 |
1011 fprintf(output, shift); | 1011 fprintf(output, "%s", shift); |
1012 | 1012 |
1013 if (cur == NULL) { | 1013 if (cur == NULL) { |
1014 fprintf(output, "Object is empty (NULL)\n"); | 1014 fprintf(output, "Object is empty (NULL)\n"); |
1015 return; | 1015 return; |
1016 } | 1016 } |
1017 switch(cur->type) { | 1017 switch(cur->type) { |
1018 case XPATH_UNDEFINED: | 1018 case XPATH_UNDEFINED: |
1019 fprintf(output, "Object is uninitialized\n"); | 1019 fprintf(output, "Object is uninitialized\n"); |
1020 break; | 1020 break; |
1021 case XPATH_NODESET: | 1021 case XPATH_NODESET: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 break; | 1056 break; |
1057 case XPATH_POINT: | 1057 case XPATH_POINT: |
1058 fprintf(output, "Object is a point : index %d in node", cur->index); | 1058 fprintf(output, "Object is a point : index %d in node", cur->index); |
1059 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1); | 1059 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1); |
1060 fprintf(output, "\n"); | 1060 fprintf(output, "\n"); |
1061 break; | 1061 break; |
1062 case XPATH_RANGE: | 1062 case XPATH_RANGE: |
1063 if ((cur->user2 == NULL) || | 1063 if ((cur->user2 == NULL) || |
1064 ((cur->user2 == cur->user) && (cur->index == cur->index2))) { | 1064 ((cur->user2 == cur->user) && (cur->index == cur->index2))) { |
1065 fprintf(output, "Object is a collapsed range :\n"); | 1065 fprintf(output, "Object is a collapsed range :\n"); |
1066 » » fprintf(output, shift); | 1066 » » fprintf(output, "%s", shift); |
1067 if (cur->index >= 0) | 1067 if (cur->index >= 0) |
1068 fprintf(output, "index %d in ", cur->index); | 1068 fprintf(output, "index %d in ", cur->index); |
1069 fprintf(output, "node\n"); | 1069 fprintf(output, "node\n"); |
1070 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, | 1070 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, |
1071 depth + 1); | 1071 depth + 1); |
1072 } else { | 1072 } else { |
1073 fprintf(output, "Object is a range :\n"); | 1073 fprintf(output, "Object is a range :\n"); |
1074 » » fprintf(output, shift); | 1074 » » fprintf(output, "%s", shift); |
1075 fprintf(output, "From "); | 1075 fprintf(output, "From "); |
1076 if (cur->index >= 0) | 1076 if (cur->index >= 0) |
1077 fprintf(output, "index %d in ", cur->index); | 1077 fprintf(output, "index %d in ", cur->index); |
1078 fprintf(output, "node\n"); | 1078 fprintf(output, "node\n"); |
1079 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, | 1079 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, |
1080 depth + 1); | 1080 depth + 1); |
1081 » » fprintf(output, shift); | 1081 » » fprintf(output, "%s", shift); |
1082 fprintf(output, "To "); | 1082 fprintf(output, "To "); |
1083 if (cur->index2 >= 0) | 1083 if (cur->index2 >= 0) |
1084 fprintf(output, "index %d in ", cur->index2); | 1084 fprintf(output, "index %d in ", cur->index2); |
1085 fprintf(output, "node\n"); | 1085 fprintf(output, "node\n"); |
1086 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2, | 1086 xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2, |
1087 depth + 1); | 1087 depth + 1); |
1088 fprintf(output, "\n"); | 1088 fprintf(output, "\n"); |
1089 } | 1089 } |
1090 break; | 1090 break; |
1091 case XPATH_LOCATIONSET: | 1091 case XPATH_LOCATIONSET: |
(...skipping 12 matching lines...) Expand all Loading... |
1104 static void | 1104 static void |
1105 xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp, | 1105 xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp, |
1106 xmlXPathStepOpPtr op, int depth) { | 1106 xmlXPathStepOpPtr op, int depth) { |
1107 int i; | 1107 int i; |
1108 char shift[100]; | 1108 char shift[100]; |
1109 | 1109 |
1110 for (i = 0;((i < depth) && (i < 25));i++) | 1110 for (i = 0;((i < depth) && (i < 25));i++) |
1111 shift[2 * i] = shift[2 * i + 1] = ' '; | 1111 shift[2 * i] = shift[2 * i + 1] = ' '; |
1112 shift[2 * i] = shift[2 * i + 1] = 0; | 1112 shift[2 * i] = shift[2 * i + 1] = 0; |
1113 | 1113 |
1114 fprintf(output, shift); | 1114 fprintf(output, "%s", shift); |
1115 if (op == NULL) { | 1115 if (op == NULL) { |
1116 fprintf(output, "Step is NULL\n"); | 1116 fprintf(output, "Step is NULL\n"); |
1117 return; | 1117 return; |
1118 } | 1118 } |
1119 switch (op->op) { | 1119 switch (op->op) { |
1120 case XPATH_OP_END: | 1120 case XPATH_OP_END: |
1121 fprintf(output, "END"); break; | 1121 fprintf(output, "END"); break; |
1122 case XPATH_OP_AND: | 1122 case XPATH_OP_AND: |
1123 fprintf(output, "AND"); break; | 1123 fprintf(output, "AND"); break; |
1124 case XPATH_OP_OR: | 1124 case XPATH_OP_OR: |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1291 int depth) { | 1291 int depth) { |
1292 int i; | 1292 int i; |
1293 char shift[100]; | 1293 char shift[100]; |
1294 | 1294 |
1295 if ((output == NULL) || (comp == NULL)) return; | 1295 if ((output == NULL) || (comp == NULL)) return; |
1296 | 1296 |
1297 for (i = 0;((i < depth) && (i < 25));i++) | 1297 for (i = 0;((i < depth) && (i < 25));i++) |
1298 shift[2 * i] = shift[2 * i + 1] = ' '; | 1298 shift[2 * i] = shift[2 * i + 1] = ' '; |
1299 shift[2 * i] = shift[2 * i + 1] = 0; | 1299 shift[2 * i] = shift[2 * i + 1] = 0; |
1300 | 1300 |
1301 fprintf(output, shift); | 1301 fprintf(output, "%s", shift); |
1302 | 1302 |
1303 fprintf(output, "Compiled Expression : %d elements\n", | 1303 fprintf(output, "Compiled Expression : %d elements\n", |
1304 comp->nbStep); | 1304 comp->nbStep); |
1305 i = comp->last; | 1305 i = comp->last; |
1306 xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1); | 1306 xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1); |
1307 } | 1307 } |
1308 | 1308 |
1309 #ifdef XP_DEBUG_OBJ_USAGE | 1309 #ifdef XP_DEBUG_OBJ_USAGE |
1310 | 1310 |
1311 /* | 1311 /* |
(...skipping 14 matching lines...) Expand all Loading... |
1326 static int xmlXPathDebugObjTotalUndefined = 0; | 1326 static int xmlXPathDebugObjTotalUndefined = 0; |
1327 static int xmlXPathDebugObjTotalNodeset = 0; | 1327 static int xmlXPathDebugObjTotalNodeset = 0; |
1328 static int xmlXPathDebugObjTotalBool = 0; | 1328 static int xmlXPathDebugObjTotalBool = 0; |
1329 static int xmlXPathDebugObjTotalNumber = 0; | 1329 static int xmlXPathDebugObjTotalNumber = 0; |
1330 static int xmlXPathDebugObjTotalString = 0; | 1330 static int xmlXPathDebugObjTotalString = 0; |
1331 static int xmlXPathDebugObjTotalPoint = 0; | 1331 static int xmlXPathDebugObjTotalPoint = 0; |
1332 static int xmlXPathDebugObjTotalRange = 0; | 1332 static int xmlXPathDebugObjTotalRange = 0; |
1333 static int xmlXPathDebugObjTotalLocset = 0; | 1333 static int xmlXPathDebugObjTotalLocset = 0; |
1334 static int xmlXPathDebugObjTotalUsers = 0; | 1334 static int xmlXPathDebugObjTotalUsers = 0; |
1335 static int xmlXPathDebugObjTotalXSLTTree = 0; | 1335 static int xmlXPathDebugObjTotalXSLTTree = 0; |
1336 static int xmlXPathDebugObjTotalAll = 0; | 1336 static int xmlXPathDebugObjTotalAll = 0; |
1337 | 1337 |
1338 static int xmlXPathDebugObjMaxUndefined = 0; | 1338 static int xmlXPathDebugObjMaxUndefined = 0; |
1339 static int xmlXPathDebugObjMaxNodeset = 0; | 1339 static int xmlXPathDebugObjMaxNodeset = 0; |
1340 static int xmlXPathDebugObjMaxBool = 0; | 1340 static int xmlXPathDebugObjMaxBool = 0; |
1341 static int xmlXPathDebugObjMaxNumber = 0; | 1341 static int xmlXPathDebugObjMaxNumber = 0; |
1342 static int xmlXPathDebugObjMaxString = 0; | 1342 static int xmlXPathDebugObjMaxString = 0; |
1343 static int xmlXPathDebugObjMaxPoint = 0; | 1343 static int xmlXPathDebugObjMaxPoint = 0; |
1344 static int xmlXPathDebugObjMaxRange = 0; | 1344 static int xmlXPathDebugObjMaxRange = 0; |
1345 static int xmlXPathDebugObjMaxLocset = 0; | 1345 static int xmlXPathDebugObjMaxLocset = 0; |
1346 static int xmlXPathDebugObjMaxUsers = 0; | 1346 static int xmlXPathDebugObjMaxUsers = 0; |
(...skipping 12 matching lines...) Expand all Loading... |
1359 cache->dbgCachedAll = 0; | 1359 cache->dbgCachedAll = 0; |
1360 cache->dbgCachedNodeset = 0; | 1360 cache->dbgCachedNodeset = 0; |
1361 cache->dbgCachedString = 0; | 1361 cache->dbgCachedString = 0; |
1362 cache->dbgCachedBool = 0; | 1362 cache->dbgCachedBool = 0; |
1363 cache->dbgCachedNumber = 0; | 1363 cache->dbgCachedNumber = 0; |
1364 cache->dbgCachedPoint = 0; | 1364 cache->dbgCachedPoint = 0; |
1365 cache->dbgCachedRange = 0; | 1365 cache->dbgCachedRange = 0; |
1366 cache->dbgCachedLocset = 0; | 1366 cache->dbgCachedLocset = 0; |
1367 cache->dbgCachedUsers = 0; | 1367 cache->dbgCachedUsers = 0; |
1368 cache->dbgCachedXSLTTree = 0; | 1368 cache->dbgCachedXSLTTree = 0; |
1369 » cache->dbgCachedUndefined = 0; | 1369 » cache->dbgCachedUndefined = 0; |
1370 | 1370 |
1371 cache->dbgReusedAll = 0; | 1371 cache->dbgReusedAll = 0; |
1372 cache->dbgReusedNodeset = 0; | 1372 cache->dbgReusedNodeset = 0; |
1373 cache->dbgReusedString = 0; | 1373 cache->dbgReusedString = 0; |
1374 cache->dbgReusedBool = 0; | 1374 cache->dbgReusedBool = 0; |
1375 cache->dbgReusedNumber = 0; | 1375 cache->dbgReusedNumber = 0; |
1376 cache->dbgReusedPoint = 0; | 1376 cache->dbgReusedPoint = 0; |
1377 cache->dbgReusedRange = 0; | 1377 cache->dbgReusedRange = 0; |
1378 cache->dbgReusedLocset = 0; | 1378 cache->dbgReusedLocset = 0; |
1379 cache->dbgReusedUsers = 0; | 1379 cache->dbgReusedUsers = 0; |
1380 cache->dbgReusedXSLTTree = 0; | 1380 cache->dbgReusedXSLTTree = 0; |
1381 cache->dbgReusedUndefined = 0; | 1381 cache->dbgReusedUndefined = 0; |
1382 } | 1382 } |
1383 } | 1383 } |
1384 | 1384 |
1385 xmlXPathDebugObjCounterUndefined = 0; | 1385 xmlXPathDebugObjCounterUndefined = 0; |
1386 xmlXPathDebugObjCounterNodeset = 0; | 1386 xmlXPathDebugObjCounterNodeset = 0; |
1387 xmlXPathDebugObjCounterBool = 0; | 1387 xmlXPathDebugObjCounterBool = 0; |
1388 xmlXPathDebugObjCounterNumber = 0; | 1388 xmlXPathDebugObjCounterNumber = 0; |
1389 xmlXPathDebugObjCounterString = 0; | 1389 xmlXPathDebugObjCounterString = 0; |
1390 xmlXPathDebugObjCounterPoint = 0; | 1390 xmlXPathDebugObjCounterPoint = 0; |
1391 xmlXPathDebugObjCounterRange = 0; | 1391 xmlXPathDebugObjCounterRange = 0; |
1392 xmlXPathDebugObjCounterLocset = 0; | 1392 xmlXPathDebugObjCounterLocset = 0; |
1393 xmlXPathDebugObjCounterUsers = 0; | 1393 xmlXPathDebugObjCounterUsers = 0; |
1394 xmlXPathDebugObjCounterXSLTTree = 0; | 1394 xmlXPathDebugObjCounterXSLTTree = 0; |
1395 xmlXPathDebugObjCounterAll = 0; | 1395 xmlXPathDebugObjCounterAll = 0; |
1396 | 1396 |
1397 xmlXPathDebugObjTotalUndefined = 0; | 1397 xmlXPathDebugObjTotalUndefined = 0; |
1398 xmlXPathDebugObjTotalNodeset = 0; | 1398 xmlXPathDebugObjTotalNodeset = 0; |
1399 xmlXPathDebugObjTotalBool = 0; | 1399 xmlXPathDebugObjTotalBool = 0; |
1400 xmlXPathDebugObjTotalNumber = 0; | 1400 xmlXPathDebugObjTotalNumber = 0; |
1401 xmlXPathDebugObjTotalString = 0; | 1401 xmlXPathDebugObjTotalString = 0; |
1402 xmlXPathDebugObjTotalPoint = 0; | 1402 xmlXPathDebugObjTotalPoint = 0; |
1403 xmlXPathDebugObjTotalRange = 0; | 1403 xmlXPathDebugObjTotalRange = 0; |
1404 xmlXPathDebugObjTotalLocset = 0; | 1404 xmlXPathDebugObjTotalLocset = 0; |
1405 xmlXPathDebugObjTotalUsers = 0; | 1405 xmlXPathDebugObjTotalUsers = 0; |
1406 xmlXPathDebugObjTotalXSLTTree = 0; | 1406 xmlXPathDebugObjTotalXSLTTree = 0; |
1407 xmlXPathDebugObjTotalAll = 0; | 1407 xmlXPathDebugObjTotalAll = 0; |
1408 | 1408 |
1409 xmlXPathDebugObjMaxUndefined = 0; | 1409 xmlXPathDebugObjMaxUndefined = 0; |
1410 xmlXPathDebugObjMaxNodeset = 0; | 1410 xmlXPathDebugObjMaxNodeset = 0; |
1411 xmlXPathDebugObjMaxBool = 0; | 1411 xmlXPathDebugObjMaxBool = 0; |
1412 xmlXPathDebugObjMaxNumber = 0; | 1412 xmlXPathDebugObjMaxNumber = 0; |
1413 xmlXPathDebugObjMaxString = 0; | 1413 xmlXPathDebugObjMaxString = 0; |
1414 xmlXPathDebugObjMaxPoint = 0; | 1414 xmlXPathDebugObjMaxPoint = 0; |
1415 xmlXPathDebugObjMaxRange = 0; | 1415 xmlXPathDebugObjMaxRange = 0; |
1416 xmlXPathDebugObjMaxLocset = 0; | 1416 xmlXPathDebugObjMaxLocset = 0; |
1417 xmlXPathDebugObjMaxUsers = 0; | 1417 xmlXPathDebugObjMaxUsers = 0; |
1418 xmlXPathDebugObjMaxXSLTTree = 0; | 1418 xmlXPathDebugObjMaxXSLTTree = 0; |
1419 xmlXPathDebugObjMaxAll = 0; | 1419 xmlXPathDebugObjMaxAll = 0; |
1420 | 1420 |
1421 } | 1421 } |
1422 | 1422 |
1423 static void | 1423 static void |
1424 xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt, | 1424 xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt, |
1425 xmlXPathObjectType objType) | 1425 xmlXPathObjectType objType) |
1426 { | 1426 { |
1427 int isCached = 0; | 1427 int isCached = 0; |
1428 | 1428 |
1429 if (ctxt != NULL) { | 1429 if (ctxt != NULL) { |
1430 if (ctxt->cache != NULL) { | 1430 if (ctxt->cache != NULL) { |
1431 xmlXPathContextCachePtr cache = | 1431 xmlXPathContextCachePtr cache = |
1432 (xmlXPathContextCachePtr) ctxt->cache; | 1432 (xmlXPathContextCachePtr) ctxt->cache; |
1433 » | 1433 |
1434 isCached = 1; | 1434 isCached = 1; |
1435 » | 1435 |
1436 » cache->dbgReusedAll++;» | 1436 » cache->dbgReusedAll++; |
1437 switch (objType) { | 1437 switch (objType) { |
1438 case XPATH_UNDEFINED: | 1438 case XPATH_UNDEFINED: |
1439 cache->dbgReusedUndefined++; | 1439 cache->dbgReusedUndefined++; |
1440 break; | 1440 break; |
1441 case XPATH_NODESET: | 1441 case XPATH_NODESET: |
1442 cache->dbgReusedNodeset++; | 1442 cache->dbgReusedNodeset++; |
1443 break; | 1443 break; |
1444 case XPATH_BOOLEAN: | 1444 case XPATH_BOOLEAN: |
1445 cache->dbgReusedBool++; | 1445 cache->dbgReusedBool++; |
1446 break; | 1446 break; |
(...skipping 13 matching lines...) Expand all Loading... |
1460 cache->dbgReusedLocset++; | 1460 cache->dbgReusedLocset++; |
1461 break; | 1461 break; |
1462 case XPATH_USERS: | 1462 case XPATH_USERS: |
1463 cache->dbgReusedUsers++; | 1463 cache->dbgReusedUsers++; |
1464 break; | 1464 break; |
1465 case XPATH_XSLT_TREE: | 1465 case XPATH_XSLT_TREE: |
1466 cache->dbgReusedXSLTTree++; | 1466 cache->dbgReusedXSLTTree++; |
1467 break; | 1467 break; |
1468 default: | 1468 default: |
1469 break; | 1469 break; |
1470 » }» | 1470 » } |
1471 } | 1471 } |
1472 } | 1472 } |
1473 | 1473 |
1474 switch (objType) { | 1474 switch (objType) { |
1475 case XPATH_UNDEFINED: | 1475 case XPATH_UNDEFINED: |
1476 if (! isCached) | 1476 if (! isCached) |
1477 xmlXPathDebugObjTotalUndefined++; | 1477 xmlXPathDebugObjTotalUndefined++; |
1478 » xmlXPathDebugObjCounterUndefined++;» | 1478 » xmlXPathDebugObjCounterUndefined++; |
1479 if (xmlXPathDebugObjCounterUndefined > | 1479 if (xmlXPathDebugObjCounterUndefined > |
1480 xmlXPathDebugObjMaxUndefined) | 1480 xmlXPathDebugObjMaxUndefined) |
1481 xmlXPathDebugObjMaxUndefined = | 1481 xmlXPathDebugObjMaxUndefined = |
1482 xmlXPathDebugObjCounterUndefined; | 1482 xmlXPathDebugObjCounterUndefined; |
1483 break; | 1483 break; |
1484 case XPATH_NODESET: | 1484 case XPATH_NODESET: |
1485 if (! isCached) | 1485 if (! isCached) |
1486 xmlXPathDebugObjTotalNodeset++; | 1486 xmlXPathDebugObjTotalNodeset++; |
1487 » xmlXPathDebugObjCounterNodeset++;» | 1487 » xmlXPathDebugObjCounterNodeset++; |
1488 if (xmlXPathDebugObjCounterNodeset > | 1488 if (xmlXPathDebugObjCounterNodeset > |
1489 xmlXPathDebugObjMaxNodeset) | 1489 xmlXPathDebugObjMaxNodeset) |
1490 xmlXPathDebugObjMaxNodeset = | 1490 xmlXPathDebugObjMaxNodeset = |
1491 xmlXPathDebugObjCounterNodeset; | 1491 xmlXPathDebugObjCounterNodeset; |
1492 break; | 1492 break; |
1493 case XPATH_BOOLEAN: | 1493 case XPATH_BOOLEAN: |
1494 if (! isCached) | 1494 if (! isCached) |
1495 xmlXPathDebugObjTotalBool++; | 1495 xmlXPathDebugObjTotalBool++; |
1496 » xmlXPathDebugObjCounterBool++;» | 1496 » xmlXPathDebugObjCounterBool++; |
1497 if (xmlXPathDebugObjCounterBool > | 1497 if (xmlXPathDebugObjCounterBool > |
1498 xmlXPathDebugObjMaxBool) | 1498 xmlXPathDebugObjMaxBool) |
1499 xmlXPathDebugObjMaxBool = | 1499 xmlXPathDebugObjMaxBool = |
1500 xmlXPathDebugObjCounterBool; | 1500 xmlXPathDebugObjCounterBool; |
1501 break; | 1501 break; |
1502 case XPATH_NUMBER: | 1502 case XPATH_NUMBER: |
1503 if (! isCached) | 1503 if (! isCached) |
1504 xmlXPathDebugObjTotalNumber++; | 1504 xmlXPathDebugObjTotalNumber++; |
1505 » xmlXPathDebugObjCounterNumber++;» | 1505 » xmlXPathDebugObjCounterNumber++; |
1506 if (xmlXPathDebugObjCounterNumber > | 1506 if (xmlXPathDebugObjCounterNumber > |
1507 xmlXPathDebugObjMaxNumber) | 1507 xmlXPathDebugObjMaxNumber) |
1508 xmlXPathDebugObjMaxNumber = | 1508 xmlXPathDebugObjMaxNumber = |
1509 xmlXPathDebugObjCounterNumber; | 1509 xmlXPathDebugObjCounterNumber; |
1510 break; | 1510 break; |
1511 case XPATH_STRING: | 1511 case XPATH_STRING: |
1512 if (! isCached) | 1512 if (! isCached) |
1513 xmlXPathDebugObjTotalString++; | 1513 xmlXPathDebugObjTotalString++; |
1514 » xmlXPathDebugObjCounterString++;» | 1514 » xmlXPathDebugObjCounterString++; |
1515 if (xmlXPathDebugObjCounterString > | 1515 if (xmlXPathDebugObjCounterString > |
1516 xmlXPathDebugObjMaxString) | 1516 xmlXPathDebugObjMaxString) |
1517 xmlXPathDebugObjMaxString = | 1517 xmlXPathDebugObjMaxString = |
1518 xmlXPathDebugObjCounterString; | 1518 xmlXPathDebugObjCounterString; |
1519 break; | 1519 break; |
1520 case XPATH_POINT: | 1520 case XPATH_POINT: |
1521 if (! isCached) | 1521 if (! isCached) |
1522 xmlXPathDebugObjTotalPoint++; | 1522 xmlXPathDebugObjTotalPoint++; |
1523 » xmlXPathDebugObjCounterPoint++;» | 1523 » xmlXPathDebugObjCounterPoint++; |
1524 if (xmlXPathDebugObjCounterPoint > | 1524 if (xmlXPathDebugObjCounterPoint > |
1525 xmlXPathDebugObjMaxPoint) | 1525 xmlXPathDebugObjMaxPoint) |
1526 xmlXPathDebugObjMaxPoint = | 1526 xmlXPathDebugObjMaxPoint = |
1527 xmlXPathDebugObjCounterPoint; | 1527 xmlXPathDebugObjCounterPoint; |
1528 break; | 1528 break; |
1529 case XPATH_RANGE: | 1529 case XPATH_RANGE: |
1530 if (! isCached) | 1530 if (! isCached) |
1531 xmlXPathDebugObjTotalRange++; | 1531 xmlXPathDebugObjTotalRange++; |
1532 xmlXPathDebugObjCounterRange++; | 1532 xmlXPathDebugObjCounterRange++; |
1533 if (xmlXPathDebugObjCounterRange > | 1533 if (xmlXPathDebugObjCounterRange > |
1534 xmlXPathDebugObjMaxRange) | 1534 xmlXPathDebugObjMaxRange) |
1535 xmlXPathDebugObjMaxRange = | 1535 xmlXPathDebugObjMaxRange = |
1536 xmlXPathDebugObjCounterRange; | 1536 xmlXPathDebugObjCounterRange; |
1537 break; | 1537 break; |
1538 case XPATH_LOCATIONSET: | 1538 case XPATH_LOCATIONSET: |
1539 if (! isCached) | 1539 if (! isCached) |
1540 xmlXPathDebugObjTotalLocset++; | 1540 xmlXPathDebugObjTotalLocset++; |
1541 xmlXPathDebugObjCounterLocset++; | 1541 xmlXPathDebugObjCounterLocset++; |
1542 if (xmlXPathDebugObjCounterLocset > | 1542 if (xmlXPathDebugObjCounterLocset > |
1543 xmlXPathDebugObjMaxLocset) | 1543 xmlXPathDebugObjMaxLocset) |
1544 xmlXPathDebugObjMaxLocset = | 1544 xmlXPathDebugObjMaxLocset = |
1545 xmlXPathDebugObjCounterLocset; | 1545 xmlXPathDebugObjCounterLocset; |
1546 break; | 1546 break; |
1547 case XPATH_USERS: | 1547 case XPATH_USERS: |
1548 if (! isCached) | 1548 if (! isCached) |
1549 xmlXPathDebugObjTotalUsers++; | 1549 xmlXPathDebugObjTotalUsers++; |
1550 » xmlXPathDebugObjCounterUsers++;» | 1550 » xmlXPathDebugObjCounterUsers++; |
1551 if (xmlXPathDebugObjCounterUsers > | 1551 if (xmlXPathDebugObjCounterUsers > |
1552 xmlXPathDebugObjMaxUsers) | 1552 xmlXPathDebugObjMaxUsers) |
1553 xmlXPathDebugObjMaxUsers = | 1553 xmlXPathDebugObjMaxUsers = |
1554 xmlXPathDebugObjCounterUsers; | 1554 xmlXPathDebugObjCounterUsers; |
1555 break; | 1555 break; |
1556 case XPATH_XSLT_TREE: | 1556 case XPATH_XSLT_TREE: |
1557 if (! isCached) | 1557 if (! isCached) |
1558 xmlXPathDebugObjTotalXSLTTree++; | 1558 xmlXPathDebugObjTotalXSLTTree++; |
1559 » xmlXPathDebugObjCounterXSLTTree++;» | 1559 » xmlXPathDebugObjCounterXSLTTree++; |
1560 if (xmlXPathDebugObjCounterXSLTTree > | 1560 if (xmlXPathDebugObjCounterXSLTTree > |
1561 xmlXPathDebugObjMaxXSLTTree) | 1561 xmlXPathDebugObjMaxXSLTTree) |
1562 xmlXPathDebugObjMaxXSLTTree = | 1562 xmlXPathDebugObjMaxXSLTTree = |
1563 xmlXPathDebugObjCounterXSLTTree; | 1563 xmlXPathDebugObjCounterXSLTTree; |
1564 break; | 1564 break; |
1565 default: | 1565 default: |
1566 break; | 1566 break; |
1567 } | 1567 } |
1568 if (! isCached) | 1568 if (! isCached) |
1569 xmlXPathDebugObjTotalAll++; | 1569 xmlXPathDebugObjTotalAll++; |
1570 xmlXPathDebugObjCounterAll++; | 1570 xmlXPathDebugObjCounterAll++; |
1571 if (xmlXPathDebugObjCounterAll > | 1571 if (xmlXPathDebugObjCounterAll > |
1572 xmlXPathDebugObjMaxAll) | 1572 xmlXPathDebugObjMaxAll) |
1573 xmlXPathDebugObjMaxAll = | 1573 xmlXPathDebugObjMaxAll = |
1574 xmlXPathDebugObjCounterAll; | 1574 xmlXPathDebugObjCounterAll; |
1575 } | 1575 } |
1576 | 1576 |
1577 static void | 1577 static void |
1578 xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt, | 1578 xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt, |
1579 xmlXPathObjectType objType) | 1579 xmlXPathObjectType objType) |
1580 { | 1580 { |
1581 int isCached = 0; | 1581 int isCached = 0; |
1582 | 1582 |
1583 if (ctxt != NULL) { | 1583 if (ctxt != NULL) { |
1584 if (ctxt->cache != NULL) { | 1584 if (ctxt->cache != NULL) { |
1585 xmlXPathContextCachePtr cache = | 1585 xmlXPathContextCachePtr cache = |
1586 (xmlXPathContextCachePtr) ctxt->cache; | 1586 (xmlXPathContextCachePtr) ctxt->cache; |
1587 | 1587 |
1588 » isCached = 1;» | 1588 » isCached = 1; |
1589 » | 1589 |
1590 cache->dbgCachedAll++; | 1590 cache->dbgCachedAll++; |
1591 switch (objType) { | 1591 switch (objType) { |
1592 case XPATH_UNDEFINED: | 1592 case XPATH_UNDEFINED: |
1593 cache->dbgCachedUndefined++; | 1593 cache->dbgCachedUndefined++; |
1594 break; | 1594 break; |
1595 case XPATH_NODESET: | 1595 case XPATH_NODESET: |
1596 cache->dbgCachedNodeset++; | 1596 cache->dbgCachedNodeset++; |
1597 break; | 1597 break; |
1598 case XPATH_BOOLEAN: | 1598 case XPATH_BOOLEAN: |
1599 cache->dbgCachedBool++; | 1599 cache->dbgCachedBool++; |
(...skipping 15 matching lines...) Expand all Loading... |
1615 break; | 1615 break; |
1616 case XPATH_USERS: | 1616 case XPATH_USERS: |
1617 cache->dbgCachedUsers++; | 1617 cache->dbgCachedUsers++; |
1618 break; | 1618 break; |
1619 case XPATH_XSLT_TREE: | 1619 case XPATH_XSLT_TREE: |
1620 cache->dbgCachedXSLTTree++; | 1620 cache->dbgCachedXSLTTree++; |
1621 break; | 1621 break; |
1622 default: | 1622 default: |
1623 break; | 1623 break; |
1624 } | 1624 } |
1625 » | 1625 |
1626 } | 1626 } |
1627 } | 1627 } |
1628 switch (objType) { | 1628 switch (objType) { |
1629 case XPATH_UNDEFINED: | 1629 case XPATH_UNDEFINED: |
1630 xmlXPathDebugObjCounterUndefined--; | 1630 xmlXPathDebugObjCounterUndefined--; |
1631 break; | 1631 break; |
1632 case XPATH_NODESET: | 1632 case XPATH_NODESET: |
1633 xmlXPathDebugObjCounterNodeset--; | 1633 xmlXPathDebugObjCounterNodeset--; |
1634 break; | 1634 break; |
1635 case XPATH_BOOLEAN: | 1635 case XPATH_BOOLEAN: |
(...skipping 15 matching lines...) Expand all Loading... |
1651 xmlXPathDebugObjCounterLocset--; | 1651 xmlXPathDebugObjCounterLocset--; |
1652 break; | 1652 break; |
1653 case XPATH_USERS: | 1653 case XPATH_USERS: |
1654 xmlXPathDebugObjCounterUsers--; | 1654 xmlXPathDebugObjCounterUsers--; |
1655 break; | 1655 break; |
1656 case XPATH_XSLT_TREE: | 1656 case XPATH_XSLT_TREE: |
1657 xmlXPathDebugObjCounterXSLTTree--; | 1657 xmlXPathDebugObjCounterXSLTTree--; |
1658 break; | 1658 break; |
1659 default: | 1659 default: |
1660 break; | 1660 break; |
1661 } | 1661 } |
1662 xmlXPathDebugObjCounterAll--; | 1662 xmlXPathDebugObjCounterAll--; |
1663 } | 1663 } |
1664 | 1664 |
1665 /* REVISIT TODO: Make this static when committing */ | 1665 /* REVISIT TODO: Make this static when committing */ |
1666 static void | 1666 static void |
1667 xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt) | 1667 xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt) |
1668 { | 1668 { |
1669 int reqAll, reqNodeset, reqString, reqBool, reqNumber, | 1669 int reqAll, reqNodeset, reqString, reqBool, reqNumber, |
1670 reqXSLTTree, reqUndefined; | 1670 reqXSLTTree, reqUndefined; |
1671 int caAll = 0, caNodeset = 0, caString = 0, caBool = 0, | 1671 int caAll = 0, caNodeset = 0, caString = 0, caBool = 0, |
1672 caNumber = 0, caXSLTTree = 0, caUndefined = 0; | 1672 caNumber = 0, caXSLTTree = 0, caUndefined = 0; |
1673 int reAll = 0, reNodeset = 0, reString = 0, reBool = 0, | 1673 int reAll = 0, reNodeset = 0, reString = 0, reBool = 0, |
1674 reNumber = 0, reXSLTTree = 0, reUndefined = 0; | 1674 reNumber = 0, reXSLTTree = 0, reUndefined = 0; |
1675 int leftObjs = xmlXPathDebugObjCounterAll; | 1675 int leftObjs = xmlXPathDebugObjCounterAll; |
1676 | 1676 |
1677 reqAll = xmlXPathDebugObjTotalAll; | 1677 reqAll = xmlXPathDebugObjTotalAll; |
1678 reqNodeset = xmlXPathDebugObjTotalNodeset; | 1678 reqNodeset = xmlXPathDebugObjTotalNodeset; |
1679 reqString = xmlXPathDebugObjTotalString; | 1679 reqString = xmlXPathDebugObjTotalString; |
1680 reqBool = xmlXPathDebugObjTotalBool; | 1680 reqBool = xmlXPathDebugObjTotalBool; |
1681 reqNumber = xmlXPathDebugObjTotalNumber; | 1681 reqNumber = xmlXPathDebugObjTotalNumber; |
1682 reqXSLTTree = xmlXPathDebugObjTotalXSLTTree; | 1682 reqXSLTTree = xmlXPathDebugObjTotalXSLTTree; |
1683 reqUndefined = xmlXPathDebugObjTotalUndefined; | 1683 reqUndefined = xmlXPathDebugObjTotalUndefined; |
1684 | 1684 |
1685 printf("# XPath object usage:\n"); | 1685 printf("# XPath object usage:\n"); |
1686 | 1686 |
1687 if (ctxt != NULL) { | 1687 if (ctxt != NULL) { |
1688 if (ctxt->cache != NULL) { | 1688 if (ctxt->cache != NULL) { |
1689 xmlXPathContextCachePtr cache = | 1689 xmlXPathContextCachePtr cache = |
1690 (xmlXPathContextCachePtr) ctxt->cache; | 1690 (xmlXPathContextCachePtr) ctxt->cache; |
1691 | 1691 |
1692 reAll = cache->dbgReusedAll; | 1692 reAll = cache->dbgReusedAll; |
1693 reqAll += reAll; | 1693 reqAll += reAll; |
1694 reNodeset = cache->dbgReusedNodeset; | 1694 reNodeset = cache->dbgReusedNodeset; |
1695 reqNodeset += reNodeset; | 1695 reqNodeset += reNodeset; |
1696 reString = cache->dbgReusedString; | 1696 reString = cache->dbgReusedString; |
1697 reqString += reString; | 1697 reqString += reString; |
1698 reBool = cache->dbgReusedBool; | 1698 reBool = cache->dbgReusedBool; |
1699 reqBool += reBool; | 1699 reqBool += reBool; |
1700 reNumber = cache->dbgReusedNumber; | 1700 reNumber = cache->dbgReusedNumber; |
1701 reqNumber += reNumber; | 1701 reqNumber += reNumber; |
1702 reXSLTTree = cache->dbgReusedXSLTTree; | 1702 reXSLTTree = cache->dbgReusedXSLTTree; |
1703 reqXSLTTree += reXSLTTree; | 1703 reqXSLTTree += reXSLTTree; |
1704 reUndefined = cache->dbgReusedUndefined; | 1704 reUndefined = cache->dbgReusedUndefined; |
1705 reqUndefined += reUndefined; | 1705 reqUndefined += reUndefined; |
1706 » | 1706 |
1707 caAll = cache->dbgCachedAll; | 1707 caAll = cache->dbgCachedAll; |
1708 caBool = cache->dbgCachedBool; | 1708 caBool = cache->dbgCachedBool; |
1709 caNodeset = cache->dbgCachedNodeset; | 1709 caNodeset = cache->dbgCachedNodeset; |
1710 caString = cache->dbgCachedString; | 1710 caString = cache->dbgCachedString; |
1711 caNumber = cache->dbgCachedNumber; | 1711 caNumber = cache->dbgCachedNumber; |
1712 caXSLTTree = cache->dbgCachedXSLTTree; | 1712 caXSLTTree = cache->dbgCachedXSLTTree; |
1713 caUndefined = cache->dbgCachedUndefined; | 1713 caUndefined = cache->dbgCachedUndefined; |
1714 » | 1714 |
1715 if (cache->nodesetObjs) | 1715 if (cache->nodesetObjs) |
1716 leftObjs -= cache->nodesetObjs->number; | 1716 leftObjs -= cache->nodesetObjs->number; |
1717 if (cache->stringObjs) | 1717 if (cache->stringObjs) |
1718 leftObjs -= cache->stringObjs->number; | 1718 leftObjs -= cache->stringObjs->number; |
1719 if (cache->booleanObjs) | 1719 if (cache->booleanObjs) |
1720 leftObjs -= cache->booleanObjs->number; | 1720 leftObjs -= cache->booleanObjs->number; |
1721 if (cache->numberObjs) | 1721 if (cache->numberObjs) |
1722 leftObjs -= cache->numberObjs->number; | 1722 leftObjs -= cache->numberObjs->number; |
1723 if (cache->miscObjs) | 1723 if (cache->miscObjs) |
1724 leftObjs -= cache->miscObjs->number; | 1724 leftObjs -= cache->miscObjs->number; |
1725 } | 1725 } |
1726 } | 1726 } |
1727 | 1727 |
1728 printf("# all\n"); | 1728 printf("# all\n"); |
1729 printf("# total : %d\n", reqAll); | 1729 printf("# total : %d\n", reqAll); |
1730 printf("# left : %d\n", leftObjs); | 1730 printf("# left : %d\n", leftObjs); |
1731 printf("# created: %d\n", xmlXPathDebugObjTotalAll); | 1731 printf("# created: %d\n", xmlXPathDebugObjTotalAll); |
1732 printf("# reused : %d\n", reAll); | 1732 printf("# reused : %d\n", reAll); |
1733 printf("# max : %d\n", xmlXPathDebugObjMaxAll); | 1733 printf("# max : %d\n", xmlXPathDebugObjMaxAll); |
1734 | 1734 |
1735 printf("# node-sets\n"); | 1735 printf("# node-sets\n"); |
1736 printf("# total : %d\n", reqNodeset); | 1736 printf("# total : %d\n", reqNodeset); |
1737 printf("# created: %d\n", xmlXPathDebugObjTotalNodeset); | 1737 printf("# created: %d\n", xmlXPathDebugObjTotalNodeset); |
1738 printf("# reused : %d\n", reNodeset); | 1738 printf("# reused : %d\n", reNodeset); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1841 return; | 1841 return; |
1842 if (cache->nodesetObjs) | 1842 if (cache->nodesetObjs) |
1843 xmlXPathCacheFreeObjectList(cache->nodesetObjs); | 1843 xmlXPathCacheFreeObjectList(cache->nodesetObjs); |
1844 if (cache->stringObjs) | 1844 if (cache->stringObjs) |
1845 xmlXPathCacheFreeObjectList(cache->stringObjs); | 1845 xmlXPathCacheFreeObjectList(cache->stringObjs); |
1846 if (cache->booleanObjs) | 1846 if (cache->booleanObjs) |
1847 xmlXPathCacheFreeObjectList(cache->booleanObjs); | 1847 xmlXPathCacheFreeObjectList(cache->booleanObjs); |
1848 if (cache->numberObjs) | 1848 if (cache->numberObjs) |
1849 xmlXPathCacheFreeObjectList(cache->numberObjs); | 1849 xmlXPathCacheFreeObjectList(cache->numberObjs); |
1850 if (cache->miscObjs) | 1850 if (cache->miscObjs) |
1851 » xmlXPathCacheFreeObjectList(cache->miscObjs); | 1851 » xmlXPathCacheFreeObjectList(cache->miscObjs); |
1852 xmlFree(cache); | 1852 xmlFree(cache); |
1853 } | 1853 } |
1854 | 1854 |
1855 /** | 1855 /** |
1856 * xmlXPathContextSetCache: | 1856 * xmlXPathContextSetCache: |
1857 * | 1857 * |
1858 * @ctxt: the XPath context | 1858 * @ctxt: the XPath context |
1859 * @active: enables/disables (creates/frees) the cache | 1859 * @active: enables/disables (creates/frees) the cache |
1860 * @value: a value with semantics dependant on @options | 1860 * @value: a value with semantics dependant on @options |
1861 * @options: options (currently only the value 0 is used) | 1861 * @options: options (currently only the value 0 is used) |
1862 * | 1862 * |
1863 * Creates/frees an object cache on the XPath context. | 1863 * Creates/frees an object cache on the XPath context. |
1864 * If activates XPath objects (xmlXPathObject) will be cached internally | 1864 * If activates XPath objects (xmlXPathObject) will be cached internally |
1865 * to be reused. | 1865 * to be reused. |
1866 * @options: | 1866 * @options: |
1867 * 0: This will set the XPath object caching: | 1867 * 0: This will set the XPath object caching: |
1868 * @value: | 1868 * @value: |
1869 * This will set the maximum number of XPath objects | 1869 * This will set the maximum number of XPath objects |
1870 * to be cached per slot | 1870 * to be cached per slot |
1871 * There are 5 slots for: node-set, string, number, boolean, and | 1871 * There are 5 slots for: node-set, string, number, boolean, and |
1872 * misc objects. Use <0 for the default number (100). | 1872 * misc objects. Use <0 for the default number (100). |
1873 * Other values for @options have currently no effect. | 1873 * Other values for @options have currently no effect. |
1874 * | 1874 * |
1875 * Returns 0 if the setting succeeded, and -1 on API or internal errors. | 1875 * Returns 0 if the setting succeeded, and -1 on API or internal errors. |
1876 */ | 1876 */ |
1877 int | 1877 int |
1878 xmlXPathContextSetCache(xmlXPathContextPtr ctxt, | 1878 xmlXPathContextSetCache(xmlXPathContextPtr ctxt, |
1879 int active, | 1879 int active, |
1880 int value, | 1880 int value, |
1881 int options) | 1881 int options) |
1882 { | 1882 { |
1883 if (ctxt == NULL) | 1883 if (ctxt == NULL) |
1884 return(-1); | 1884 return(-1); |
1885 if (active) { | 1885 if (active) { |
1886 xmlXPathContextCachePtr cache; | 1886 xmlXPathContextCachePtr cache; |
1887 » | 1887 |
1888 if (ctxt->cache == NULL) { | 1888 if (ctxt->cache == NULL) { |
1889 ctxt->cache = xmlXPathNewCache(); | 1889 ctxt->cache = xmlXPathNewCache(); |
1890 if (ctxt->cache == NULL) | 1890 if (ctxt->cache == NULL) |
1891 return(-1); | 1891 return(-1); |
1892 } | 1892 } |
1893 cache = (xmlXPathContextCachePtr) ctxt->cache; | 1893 cache = (xmlXPathContextCachePtr) ctxt->cache; |
1894 if (options == 0) { | 1894 if (options == 0) { |
1895 if (value < 0) | 1895 if (value < 0) |
1896 value = 100; | 1896 value = 100; |
1897 cache->maxNodeset = value; | 1897 cache->maxNodeset = value; |
(...skipping 14 matching lines...) Expand all Loading... |
1912 * @ctxt: the XPath context | 1912 * @ctxt: the XPath context |
1913 * @val: the NodePtr value | 1913 * @val: the NodePtr value |
1914 * | 1914 * |
1915 * This is the cached version of xmlXPathWrapNodeSet(). | 1915 * This is the cached version of xmlXPathWrapNodeSet(). |
1916 * Wrap the Nodeset @val in a new xmlXPathObjectPtr | 1916 * Wrap the Nodeset @val in a new xmlXPathObjectPtr |
1917 * | 1917 * |
1918 * Returns the created or reused object. | 1918 * Returns the created or reused object. |
1919 */ | 1919 */ |
1920 static xmlXPathObjectPtr | 1920 static xmlXPathObjectPtr |
1921 xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val) | 1921 xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val) |
1922 { | 1922 { |
1923 if ((ctxt != NULL) && (ctxt->cache != NULL)) { | 1923 if ((ctxt != NULL) && (ctxt->cache != NULL)) { |
1924 xmlXPathContextCachePtr cache = | 1924 xmlXPathContextCachePtr cache = |
1925 (xmlXPathContextCachePtr) ctxt->cache; | 1925 (xmlXPathContextCachePtr) ctxt->cache; |
1926 | 1926 |
1927 if ((cache->miscObjs != NULL) && | 1927 if ((cache->miscObjs != NULL) && |
1928 (cache->miscObjs->number != 0)) | 1928 (cache->miscObjs->number != 0)) |
1929 { | 1929 { |
1930 xmlXPathObjectPtr ret; | 1930 xmlXPathObjectPtr ret; |
1931 » | 1931 |
1932 ret = (xmlXPathObjectPtr) | 1932 ret = (xmlXPathObjectPtr) |
1933 cache->miscObjs->items[--cache->miscObjs->number]; | 1933 cache->miscObjs->items[--cache->miscObjs->number]; |
1934 ret->type = XPATH_NODESET; | 1934 ret->type = XPATH_NODESET; |
1935 ret->nodesetval = val; | 1935 ret->nodesetval = val; |
1936 #ifdef XP_DEBUG_OBJ_USAGE | 1936 #ifdef XP_DEBUG_OBJ_USAGE |
1937 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); | 1937 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); |
1938 #endif | 1938 #endif |
1939 » return(ret);» | 1939 » return(ret); |
1940 } | 1940 } |
1941 } | 1941 } |
1942 » | 1942 |
1943 return(xmlXPathWrapNodeSet(val)); | 1943 return(xmlXPathWrapNodeSet(val)); |
1944 | 1944 |
1945 } | 1945 } |
1946 | 1946 |
1947 /** | 1947 /** |
1948 * xmlXPathCacheWrapString: | 1948 * xmlXPathCacheWrapString: |
1949 * @ctxt: the XPath context | 1949 * @ctxt: the XPath context |
1950 * @val: the xmlChar * value | 1950 * @val: the xmlChar * value |
1951 * | 1951 * |
1952 * This is the cached version of xmlXPathWrapString(). | 1952 * This is the cached version of xmlXPathWrapString(). |
1953 * Wraps the @val string into an XPath object. | 1953 * Wraps the @val string into an XPath object. |
1954 * | 1954 * |
1955 * Returns the created or reused object. | 1955 * Returns the created or reused object. |
1956 */ | 1956 */ |
1957 static xmlXPathObjectPtr | 1957 static xmlXPathObjectPtr |
1958 xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val) | 1958 xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val) |
1959 { | 1959 { |
1960 if ((ctxt != NULL) && (ctxt->cache != NULL)) { | 1960 if ((ctxt != NULL) && (ctxt->cache != NULL)) { |
1961 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; | 1961 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; |
1962 | 1962 |
1963 if ((cache->stringObjs != NULL) && | 1963 if ((cache->stringObjs != NULL) && |
1964 (cache->stringObjs->number != 0)) | 1964 (cache->stringObjs->number != 0)) |
1965 { | 1965 { |
1966 » | 1966 |
1967 xmlXPathObjectPtr ret; | 1967 xmlXPathObjectPtr ret; |
1968 » | 1968 |
1969 ret = (xmlXPathObjectPtr) | 1969 ret = (xmlXPathObjectPtr) |
1970 cache->stringObjs->items[--cache->stringObjs->number]; | 1970 cache->stringObjs->items[--cache->stringObjs->number]; |
1971 ret->type = XPATH_STRING; | 1971 ret->type = XPATH_STRING; |
1972 ret->stringval = val; | 1972 ret->stringval = val; |
1973 #ifdef XP_DEBUG_OBJ_USAGE | 1973 #ifdef XP_DEBUG_OBJ_USAGE |
1974 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); | 1974 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); |
1975 #endif | 1975 #endif |
1976 return(ret); | 1976 return(ret); |
1977 } else if ((cache->miscObjs != NULL) && | 1977 } else if ((cache->miscObjs != NULL) && |
1978 (cache->miscObjs->number != 0)) | 1978 (cache->miscObjs->number != 0)) |
(...skipping 28 matching lines...) Expand all Loading... |
2007 * Returns the created or reused object. | 2007 * Returns the created or reused object. |
2008 */ | 2008 */ |
2009 static xmlXPathObjectPtr | 2009 static xmlXPathObjectPtr |
2010 xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) | 2010 xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) |
2011 { | 2011 { |
2012 if ((ctxt != NULL) && (ctxt->cache)) { | 2012 if ((ctxt != NULL) && (ctxt->cache)) { |
2013 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; | 2013 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; |
2014 | 2014 |
2015 if ((cache->nodesetObjs != NULL) && | 2015 if ((cache->nodesetObjs != NULL) && |
2016 (cache->nodesetObjs->number != 0)) | 2016 (cache->nodesetObjs->number != 0)) |
2017 » {» | 2017 » { |
2018 xmlXPathObjectPtr ret; | 2018 xmlXPathObjectPtr ret; |
2019 /* | 2019 /* |
2020 * Use the nodset-cache. | 2020 * Use the nodset-cache. |
2021 » */» | 2021 » */ |
2022 ret = (xmlXPathObjectPtr) | 2022 ret = (xmlXPathObjectPtr) |
2023 cache->nodesetObjs->items[--cache->nodesetObjs->number]; | 2023 cache->nodesetObjs->items[--cache->nodesetObjs->number]; |
2024 ret->type = XPATH_NODESET; | 2024 ret->type = XPATH_NODESET; |
2025 ret->boolval = 0; | 2025 ret->boolval = 0; |
2026 » if (val) {» » | 2026 » if (val) { |
2027 if ((ret->nodesetval->nodeMax == 0) || | 2027 if ((ret->nodesetval->nodeMax == 0) || |
2028 (val->type == XML_NAMESPACE_DECL)) | 2028 (val->type == XML_NAMESPACE_DECL)) |
2029 { | 2029 { |
2030 » » xmlXPathNodeSetAddUnique(ret->nodesetval, val);» » | 2030 » » xmlXPathNodeSetAddUnique(ret->nodesetval, val); |
2031 } else { | 2031 } else { |
2032 ret->nodesetval->nodeTab[0] = val; | 2032 ret->nodesetval->nodeTab[0] = val; |
2033 ret->nodesetval->nodeNr = 1; | 2033 ret->nodesetval->nodeNr = 1; |
2034 } | 2034 } |
2035 } | 2035 } |
2036 #ifdef XP_DEBUG_OBJ_USAGE | 2036 #ifdef XP_DEBUG_OBJ_USAGE |
2037 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); | 2037 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); |
2038 #endif | 2038 #endif |
2039 return(ret); | 2039 return(ret); |
2040 } else if ((cache->miscObjs != NULL) && | 2040 } else if ((cache->miscObjs != NULL) && |
(...skipping 24 matching lines...) Expand all Loading... |
2065 * @ctxt: the XPath context | 2065 * @ctxt: the XPath context |
2066 * @val: the char * value | 2066 * @val: the char * value |
2067 * | 2067 * |
2068 * This is the cached version of xmlXPathNewCString(). | 2068 * This is the cached version of xmlXPathNewCString(). |
2069 * Acquire an xmlXPathObjectPtr of type string and of value @val | 2069 * Acquire an xmlXPathObjectPtr of type string and of value @val |
2070 * | 2070 * |
2071 * Returns the created or reused object. | 2071 * Returns the created or reused object. |
2072 */ | 2072 */ |
2073 static xmlXPathObjectPtr | 2073 static xmlXPathObjectPtr |
2074 xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) | 2074 xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) |
2075 { | 2075 { |
2076 if ((ctxt != NULL) && (ctxt->cache)) { | 2076 if ((ctxt != NULL) && (ctxt->cache)) { |
2077 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; | 2077 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; |
2078 | 2078 |
2079 if ((cache->stringObjs != NULL) && | 2079 if ((cache->stringObjs != NULL) && |
2080 (cache->stringObjs->number != 0)) | 2080 (cache->stringObjs->number != 0)) |
2081 » {» | 2081 » { |
2082 xmlXPathObjectPtr ret; | 2082 xmlXPathObjectPtr ret; |
2083 » | 2083 |
2084 ret = (xmlXPathObjectPtr) | 2084 ret = (xmlXPathObjectPtr) |
2085 cache->stringObjs->items[--cache->stringObjs->number]; | 2085 cache->stringObjs->items[--cache->stringObjs->number]; |
2086 | 2086 |
2087 ret->type = XPATH_STRING; | 2087 ret->type = XPATH_STRING; |
2088 ret->stringval = xmlStrdup(BAD_CAST val); | 2088 ret->stringval = xmlStrdup(BAD_CAST val); |
2089 #ifdef XP_DEBUG_OBJ_USAGE | 2089 #ifdef XP_DEBUG_OBJ_USAGE |
2090 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); | 2090 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); |
2091 #endif | 2091 #endif |
2092 return(ret); | 2092 return(ret); |
2093 } else if ((cache->miscObjs != NULL) && | 2093 } else if ((cache->miscObjs != NULL) && |
(...skipping 20 matching lines...) Expand all Loading... |
2114 * @ctxt: the XPath context | 2114 * @ctxt: the XPath context |
2115 * @val: the xmlChar * value | 2115 * @val: the xmlChar * value |
2116 * | 2116 * |
2117 * This is the cached version of xmlXPathNewString(). | 2117 * This is the cached version of xmlXPathNewString(). |
2118 * Acquire an xmlXPathObjectPtr of type string and of value @val | 2118 * Acquire an xmlXPathObjectPtr of type string and of value @val |
2119 * | 2119 * |
2120 * Returns the created or reused object. | 2120 * Returns the created or reused object. |
2121 */ | 2121 */ |
2122 static xmlXPathObjectPtr | 2122 static xmlXPathObjectPtr |
2123 xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) | 2123 xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) |
2124 { | 2124 { |
2125 if ((ctxt != NULL) && (ctxt->cache)) { | 2125 if ((ctxt != NULL) && (ctxt->cache)) { |
2126 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; | 2126 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; |
2127 | 2127 |
2128 if ((cache->stringObjs != NULL) && | 2128 if ((cache->stringObjs != NULL) && |
2129 (cache->stringObjs->number != 0)) | 2129 (cache->stringObjs->number != 0)) |
2130 » {» | 2130 » { |
2131 xmlXPathObjectPtr ret; | 2131 xmlXPathObjectPtr ret; |
2132 » | 2132 |
2133 ret = (xmlXPathObjectPtr) | 2133 ret = (xmlXPathObjectPtr) |
2134 cache->stringObjs->items[--cache->stringObjs->number]; | 2134 cache->stringObjs->items[--cache->stringObjs->number]; |
2135 ret->type = XPATH_STRING; | 2135 ret->type = XPATH_STRING; |
2136 if (val != NULL) | 2136 if (val != NULL) |
2137 ret->stringval = xmlStrdup(val); | 2137 ret->stringval = xmlStrdup(val); |
2138 else | 2138 else |
2139 ret->stringval = xmlStrdup((const xmlChar *)""); | 2139 ret->stringval = xmlStrdup((const xmlChar *)""); |
2140 #ifdef XP_DEBUG_OBJ_USAGE | 2140 #ifdef XP_DEBUG_OBJ_USAGE |
2141 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); | 2141 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); |
2142 #endif | 2142 #endif |
(...skipping 25 matching lines...) Expand all Loading... |
2168 * @ctxt: the XPath context | 2168 * @ctxt: the XPath context |
2169 * @val: the boolean value | 2169 * @val: the boolean value |
2170 * | 2170 * |
2171 * This is the cached version of xmlXPathNewBoolean(). | 2171 * This is the cached version of xmlXPathNewBoolean(). |
2172 * Acquires an xmlXPathObjectPtr of type boolean and of value @val | 2172 * Acquires an xmlXPathObjectPtr of type boolean and of value @val |
2173 * | 2173 * |
2174 * Returns the created or reused object. | 2174 * Returns the created or reused object. |
2175 */ | 2175 */ |
2176 static xmlXPathObjectPtr | 2176 static xmlXPathObjectPtr |
2177 xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val) | 2177 xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val) |
2178 { | 2178 { |
2179 if ((ctxt != NULL) && (ctxt->cache)) { | 2179 if ((ctxt != NULL) && (ctxt->cache)) { |
2180 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; | 2180 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; |
2181 | 2181 |
2182 if ((cache->booleanObjs != NULL) && | 2182 if ((cache->booleanObjs != NULL) && |
2183 (cache->booleanObjs->number != 0)) | 2183 (cache->booleanObjs->number != 0)) |
2184 » {» | 2184 » { |
2185 xmlXPathObjectPtr ret; | 2185 xmlXPathObjectPtr ret; |
2186 » | 2186 |
2187 ret = (xmlXPathObjectPtr) | 2187 ret = (xmlXPathObjectPtr) |
2188 cache->booleanObjs->items[--cache->booleanObjs->number]; | 2188 cache->booleanObjs->items[--cache->booleanObjs->number]; |
2189 ret->type = XPATH_BOOLEAN; | 2189 ret->type = XPATH_BOOLEAN; |
2190 ret->boolval = (val != 0); | 2190 ret->boolval = (val != 0); |
2191 #ifdef XP_DEBUG_OBJ_USAGE | 2191 #ifdef XP_DEBUG_OBJ_USAGE |
2192 xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN); | 2192 xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN); |
2193 #endif | 2193 #endif |
2194 return(ret); | 2194 return(ret); |
2195 } else if ((cache->miscObjs != NULL) && | 2195 } else if ((cache->miscObjs != NULL) && |
2196 (cache->miscObjs->number != 0)) | 2196 (cache->miscObjs->number != 0)) |
(...skipping 25 matching lines...) Expand all Loading... |
2222 * Returns the created or reused object. | 2222 * Returns the created or reused object. |
2223 */ | 2223 */ |
2224 static xmlXPathObjectPtr | 2224 static xmlXPathObjectPtr |
2225 xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val) | 2225 xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val) |
2226 { | 2226 { |
2227 if ((ctxt != NULL) && (ctxt->cache)) { | 2227 if ((ctxt != NULL) && (ctxt->cache)) { |
2228 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; | 2228 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; |
2229 | 2229 |
2230 if ((cache->numberObjs != NULL) && | 2230 if ((cache->numberObjs != NULL) && |
2231 (cache->numberObjs->number != 0)) | 2231 (cache->numberObjs->number != 0)) |
2232 » {» | 2232 » { |
2233 xmlXPathObjectPtr ret; | 2233 xmlXPathObjectPtr ret; |
2234 » | 2234 |
2235 ret = (xmlXPathObjectPtr) | 2235 ret = (xmlXPathObjectPtr) |
2236 cache->numberObjs->items[--cache->numberObjs->number]; | 2236 cache->numberObjs->items[--cache->numberObjs->number]; |
2237 ret->type = XPATH_NUMBER; | 2237 ret->type = XPATH_NUMBER; |
2238 ret->floatval = val; | 2238 ret->floatval = val; |
2239 #ifdef XP_DEBUG_OBJ_USAGE | 2239 #ifdef XP_DEBUG_OBJ_USAGE |
2240 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER); | 2240 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER); |
2241 #endif | 2241 #endif |
2242 return(ret); | 2242 return(ret); |
2243 } else if ((cache->miscObjs != NULL) && | 2243 } else if ((cache->miscObjs != NULL) && |
2244 (cache->miscObjs->number != 0)) | 2244 (cache->miscObjs->number != 0)) |
(...skipping 21 matching lines...) Expand all Loading... |
2266 * | 2266 * |
2267 * This is the cached version of xmlXPathConvertString(). | 2267 * This is the cached version of xmlXPathConvertString(). |
2268 * Converts an existing object to its string() equivalent | 2268 * Converts an existing object to its string() equivalent |
2269 * | 2269 * |
2270 * Returns a created or reused object, the old one is freed (cached) | 2270 * Returns a created or reused object, the old one is freed (cached) |
2271 * (or the operation is done directly on @val) | 2271 * (or the operation is done directly on @val) |
2272 */ | 2272 */ |
2273 | 2273 |
2274 static xmlXPathObjectPtr | 2274 static xmlXPathObjectPtr |
2275 xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { | 2275 xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { |
2276 xmlChar *res = NULL; | 2276 xmlChar *res = NULL; |
2277 | 2277 |
2278 if (val == NULL) | 2278 if (val == NULL) |
2279 return(xmlXPathCacheNewCString(ctxt, "")); | 2279 return(xmlXPathCacheNewCString(ctxt, "")); |
2280 | 2280 |
2281 switch (val->type) { | 2281 switch (val->type) { |
2282 case XPATH_UNDEFINED: | 2282 case XPATH_UNDEFINED: |
2283 #ifdef DEBUG_EXPR | 2283 #ifdef DEBUG_EXPR |
2284 xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n"); | 2284 xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n"); |
2285 #endif | 2285 #endif |
2286 break; | 2286 break; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2350 * | 2350 * |
2351 * This is the cached version of xmlXPathConvertBoolean(). | 2351 * This is the cached version of xmlXPathConvertBoolean(). |
2352 * Converts an existing object to its boolean() equivalent | 2352 * Converts an existing object to its boolean() equivalent |
2353 * | 2353 * |
2354 * Returns a created or reused object, the old one is freed (or the operation | 2354 * Returns a created or reused object, the old one is freed (or the operation |
2355 * is done directly on @val) | 2355 * is done directly on @val) |
2356 */ | 2356 */ |
2357 static xmlXPathObjectPtr | 2357 static xmlXPathObjectPtr |
2358 xmlXPathCacheConvertBoolean(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { | 2358 xmlXPathCacheConvertBoolean(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { |
2359 xmlXPathObjectPtr ret; | 2359 xmlXPathObjectPtr ret; |
2360 | 2360 |
2361 if (val == NULL) | 2361 if (val == NULL) |
2362 return(xmlXPathCacheNewBoolean(ctxt, 0)); | 2362 return(xmlXPathCacheNewBoolean(ctxt, 0)); |
2363 if (val->type == XPATH_BOOLEAN) | 2363 if (val->type == XPATH_BOOLEAN) |
2364 return(val); | 2364 return(val); |
2365 ret = xmlXPathCacheNewBoolean(ctxt, xmlXPathCastToBoolean(val)); | 2365 ret = xmlXPathCacheNewBoolean(ctxt, xmlXPathCastToBoolean(val)); |
2366 xmlXPathReleaseObject(ctxt, val); | 2366 xmlXPathReleaseObject(ctxt, val); |
2367 return(ret); | 2367 return(ret); |
2368 } | 2368 } |
2369 | 2369 |
2370 /** | 2370 /** |
2371 * xmlXPathCacheConvertNumber: | 2371 * xmlXPathCacheConvertNumber: |
2372 * @ctxt: the XPath context | 2372 * @ctxt: the XPath context |
2373 * @val: an XPath object | 2373 * @val: an XPath object |
2374 * | 2374 * |
2375 * This is the cached version of xmlXPathConvertNumber(). | 2375 * This is the cached version of xmlXPathConvertNumber(). |
2376 * Converts an existing object to its number() equivalent | 2376 * Converts an existing object to its number() equivalent |
2377 * | 2377 * |
2378 * Returns a created or reused object, the old one is freed (or the operation | 2378 * Returns a created or reused object, the old one is freed (or the operation |
2379 * is done directly on @val) | 2379 * is done directly on @val) |
2380 */ | 2380 */ |
2381 static xmlXPathObjectPtr | 2381 static xmlXPathObjectPtr |
2382 xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { | 2382 xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) { |
2383 xmlXPathObjectPtr ret; | 2383 xmlXPathObjectPtr ret; |
2384 | 2384 |
2385 if (val == NULL) | 2385 if (val == NULL) |
2386 return(xmlXPathCacheNewFloat(ctxt, 0.0)); | 2386 return(xmlXPathCacheNewFloat(ctxt, 0.0)); |
2387 if (val->type == XPATH_NUMBER) | 2387 if (val->type == XPATH_NUMBER) |
2388 return(val); | 2388 return(val); |
2389 ret = xmlXPathCacheNewFloat(ctxt, xmlXPathCastToNumber(val)); | 2389 ret = xmlXPathCacheNewFloat(ctxt, xmlXPathCastToNumber(val)); |
2390 xmlXPathReleaseObject(ctxt, val); | 2390 xmlXPathReleaseObject(ctxt, val); |
2391 return(ret); | 2391 return(ret); |
2392 } | 2392 } |
2393 | 2393 |
2394 /************************************************************************ | 2394 /************************************************************************ |
2395 * * | 2395 * * |
2396 * » » Parser stacks related functions and macros» » * | 2396 *» » Parser stacks related functions and macros» » * |
2397 * * | 2397 * * |
2398 ************************************************************************/ | 2398 ************************************************************************/ |
2399 | 2399 |
2400 /** | 2400 /** |
2401 * valuePop: | 2401 * valuePop: |
2402 * @ctxt: an XPath evaluation context | 2402 * @ctxt: an XPath evaluation context |
2403 * | 2403 * |
2404 * Pops the top XPath object from the value stack | 2404 * Pops the top XPath object from the value stack |
2405 * | 2405 * |
2406 * Returns the XPath object just removed | 2406 * Returns the XPath object just removed |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2625 #define NXT(val) ctxt->cur[(val)] | 2625 #define NXT(val) ctxt->cur[(val)] |
2626 #define CUR_PTR ctxt->cur | 2626 #define CUR_PTR ctxt->cur |
2627 #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l) | 2627 #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l) |
2628 | 2628 |
2629 #define COPY_BUF(l,b,i,v) \ | 2629 #define COPY_BUF(l,b,i,v) \ |
2630 if (l == 1) b[i++] = (xmlChar) v; \ | 2630 if (l == 1) b[i++] = (xmlChar) v; \ |
2631 else i += xmlCopyChar(l,&b[i],v) | 2631 else i += xmlCopyChar(l,&b[i],v) |
2632 | 2632 |
2633 #define NEXTL(l) ctxt->cur += l | 2633 #define NEXTL(l) ctxt->cur += l |
2634 | 2634 |
2635 #define SKIP_BLANKS » » » » » » » \ | 2635 #define SKIP_BLANKS» » » » » » » \ |
2636 while (IS_BLANK_CH(*(ctxt->cur))) NEXT | 2636 while (IS_BLANK_CH(*(ctxt->cur))) NEXT |
2637 | 2637 |
2638 #define CURRENT (*ctxt->cur) | 2638 #define CURRENT (*ctxt->cur) |
2639 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) | 2639 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) |
2640 | 2640 |
2641 | 2641 |
2642 #ifndef DBL_DIG | 2642 #ifndef DBL_DIG |
2643 #define DBL_DIG 16 | 2643 #define DBL_DIG 16 |
2644 #endif | 2644 #endif |
2645 #ifndef DBL_EPSILON | 2645 #ifndef DBL_EPSILON |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2994 int misc = 0, precedence1 = 0, precedence2 = 0; | 2994 int misc = 0, precedence1 = 0, precedence2 = 0; |
2995 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL; | 2995 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL; |
2996 xmlNodePtr cur, root; | 2996 xmlNodePtr cur, root; |
2997 long l1, l2; | 2997 long l1, l2; |
2998 | 2998 |
2999 if ((node1 == NULL) || (node2 == NULL)) | 2999 if ((node1 == NULL) || (node2 == NULL)) |
3000 return(-2); | 3000 return(-2); |
3001 | 3001 |
3002 if (node1 == node2) | 3002 if (node1 == node2) |
3003 return(0); | 3003 return(0); |
3004 | 3004 |
3005 /* | 3005 /* |
3006 * a couple of optimizations which will avoid computations in most cases | 3006 * a couple of optimizations which will avoid computations in most cases |
3007 */ | 3007 */ |
3008 switch (node1->type) { | 3008 switch (node1->type) { |
3009 case XML_ELEMENT_NODE: | 3009 case XML_ELEMENT_NODE: |
3010 if (node2->type == XML_ELEMENT_NODE) { | 3010 if (node2->type == XML_ELEMENT_NODE) { |
3011 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice
here? */ | 3011 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice
here? */ |
3012 (0 > (long) node2->content) && | 3012 (0 > (long) node2->content) && |
3013 (node1->doc == node2->doc)) | 3013 (node1->doc == node2->doc)) |
3014 » » {» » | 3014 » » { |
3015 l1 = -((long) node1->content); | 3015 l1 = -((long) node1->content); |
3016 l2 = -((long) node2->content); | 3016 l2 = -((long) node2->content); |
3017 if (l1 < l2) | 3017 if (l1 < l2) |
3018 return(1); | 3018 return(1); |
3019 if (l1 > l2) | 3019 if (l1 > l2) |
3020 return(-1); | 3020 return(-1); |
3021 } else | 3021 } else |
3022 » » goto turtle_comparison;» » | 3022 » » goto turtle_comparison; |
3023 } | 3023 } |
3024 break; | 3024 break; |
3025 case XML_ATTRIBUTE_NODE: | 3025 case XML_ATTRIBUTE_NODE: |
3026 precedence1 = 1; /* element is owner */ | 3026 precedence1 = 1; /* element is owner */ |
3027 miscNode1 = node1; | 3027 miscNode1 = node1; |
3028 node1 = node1->parent; | 3028 node1 = node1->parent; |
3029 misc = 1; | 3029 misc = 1; |
3030 break; | 3030 break; |
3031 case XML_TEXT_NODE: | 3031 case XML_TEXT_NODE: |
3032 case XML_CDATA_SECTION_NODE: | 3032 case XML_CDATA_SECTION_NODE: |
3033 case XML_COMMENT_NODE: | 3033 case XML_COMMENT_NODE: |
3034 case XML_PI_NODE: { | 3034 case XML_PI_NODE: { |
3035 miscNode1 = node1; | 3035 miscNode1 = node1; |
3036 /* | 3036 /* |
3037 * Find nearest element node. | 3037 * Find nearest element node. |
3038 » */» | 3038 » */ |
3039 if (node1->prev != NULL) { | 3039 if (node1->prev != NULL) { |
3040 do { | 3040 do { |
3041 node1 = node1->prev; | 3041 node1 = node1->prev; |
3042 if (node1->type == XML_ELEMENT_NODE) { | 3042 if (node1->type == XML_ELEMENT_NODE) { |
3043 precedence1 = 3; /* element in prev-sibl axis */ | 3043 precedence1 = 3; /* element in prev-sibl axis */ |
3044 break; | 3044 break; |
3045 } | 3045 } |
3046 if (node1->prev == NULL) { | 3046 if (node1->prev == NULL) { |
3047 precedence1 = 2; /* element is parent */ | 3047 precedence1 = 2; /* element is parent */ |
3048 /* | 3048 /* |
(...skipping 19 matching lines...) Expand all Loading... |
3068 misc = 1; | 3068 misc = 1; |
3069 } | 3069 } |
3070 break; | 3070 break; |
3071 case XML_NAMESPACE_DECL: | 3071 case XML_NAMESPACE_DECL: |
3072 /* | 3072 /* |
3073 * TODO: why do we return 1 for namespace nodes? | 3073 * TODO: why do we return 1 for namespace nodes? |
3074 */ | 3074 */ |
3075 return(1); | 3075 return(1); |
3076 default: | 3076 default: |
3077 break; | 3077 break; |
3078 } | 3078 } |
3079 switch (node2->type) { | 3079 switch (node2->type) { |
3080 » case XML_ELEMENT_NODE:» | 3080 » case XML_ELEMENT_NODE: |
3081 break; | 3081 break; |
3082 case XML_ATTRIBUTE_NODE: | 3082 case XML_ATTRIBUTE_NODE: |
3083 precedence2 = 1; /* element is owner */ | 3083 precedence2 = 1; /* element is owner */ |
3084 miscNode2 = node2; | 3084 miscNode2 = node2; |
3085 node2 = node2->parent; | 3085 node2 = node2->parent; |
3086 misc = 1; | 3086 misc = 1; |
3087 break; | 3087 break; |
3088 case XML_TEXT_NODE: | 3088 case XML_TEXT_NODE: |
3089 case XML_CDATA_SECTION_NODE: | 3089 case XML_CDATA_SECTION_NODE: |
3090 case XML_COMMENT_NODE: | 3090 case XML_COMMENT_NODE: |
3091 case XML_PI_NODE: { | 3091 case XML_PI_NODE: { |
3092 miscNode2 = node2; | 3092 miscNode2 = node2; |
3093 if (node2->prev != NULL) { | 3093 if (node2->prev != NULL) { |
3094 do { | 3094 do { |
3095 node2 = node2->prev; | 3095 node2 = node2->prev; |
3096 if (node2->type == XML_ELEMENT_NODE) { | 3096 if (node2->type == XML_ELEMENT_NODE) { |
3097 precedence2 = 3; /* element in prev-sibl axis */ | 3097 precedence2 = 3; /* element in prev-sibl axis */ |
3098 break; | 3098 break; |
3099 } | 3099 } |
3100 if (node2->prev == NULL) { | 3100 if (node2->prev == NULL) { |
3101 precedence2 = 2; /* element is parent */ | 3101 precedence2 = 2; /* element is parent */ |
3102 node2 = node2->parent; | 3102 node2 = node2->parent; |
3103 break; | 3103 break; |
3104 } | 3104 } |
3105 } while (1); | 3105 } while (1); |
3106 } else { | 3106 } else { |
3107 precedence2 = 2; /* element is parent */ | 3107 precedence2 = 2; /* element is parent */ |
3108 node2 = node2->parent; | 3108 node2 = node2->parent; |
3109 » }» | 3109 » } |
3110 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) || | 3110 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) || |
3111 (0 <= (long) node1->content)) | 3111 (0 <= (long) node1->content)) |
3112 { | 3112 { |
3113 node2 = miscNode2; | 3113 node2 = miscNode2; |
3114 precedence2 = 0; | 3114 precedence2 = 0; |
3115 } else | 3115 } else |
3116 misc = 1; | 3116 misc = 1; |
3117 } | 3117 } |
3118 break; | 3118 break; |
3119 case XML_NAMESPACE_DECL: | 3119 case XML_NAMESPACE_DECL: |
(...skipping 17 matching lines...) Expand all Loading... |
3137 cur = cur->prev; | 3137 cur = cur->prev; |
3138 } | 3138 } |
3139 return (-1); | 3139 return (-1); |
3140 } else { | 3140 } else { |
3141 /* | 3141 /* |
3142 * Evaluate based on higher precedence wrt to the element. | 3142 * Evaluate based on higher precedence wrt to the element. |
3143 * TODO: This assumes attributes are sorted before content. | 3143 * TODO: This assumes attributes are sorted before content. |
3144 * Is this 100% correct? | 3144 * Is this 100% correct? |
3145 */ | 3145 */ |
3146 if (precedence1 < precedence2) | 3146 if (precedence1 < precedence2) |
3147 » » return(1); | 3147 » » return(1); |
3148 else | 3148 else |
3149 » » return(-1);» | 3149 » » return(-1); |
3150 } | 3150 } |
3151 » } | 3151 » } |
3152 /* | 3152 /* |
3153 * Special case: One of the helper-elements is contained by the other. | 3153 * Special case: One of the helper-elements is contained by the other. |
3154 * <foo> | 3154 * <foo> |
3155 * <node2> | 3155 * <node2> |
3156 * <node1>Text-1(precedence1 == 2)</node1> | 3156 * <node1>Text-1(precedence1 == 2)</node1> |
3157 * </node2> | 3157 * </node2> |
3158 * Text-6(precedence2 == 3) | 3158 * Text-6(precedence2 == 3) |
3159 * </foo> | 3159 * </foo> |
3160 » */» | 3160 » */ |
3161 if ((precedence2 == 3) && (precedence1 > 1)) { | 3161 if ((precedence2 == 3) && (precedence1 > 1)) { |
3162 cur = node1->parent; | 3162 cur = node1->parent; |
3163 while (cur) { | 3163 while (cur) { |
3164 if (cur == node2) | 3164 if (cur == node2) |
3165 return(1); | 3165 return(1); |
3166 cur = cur->parent; | 3166 cur = cur->parent; |
3167 } | 3167 } |
3168 } | 3168 } |
3169 » if ((precedence1 == 3) && (precedence2 > 1)) {» | 3169 » if ((precedence1 == 3) && (precedence2 > 1)) { |
3170 cur = node2->parent; | 3170 cur = node2->parent; |
3171 while (cur) { | 3171 while (cur) { |
3172 if (cur == node1) | 3172 if (cur == node1) |
3173 return(-1); | 3173 return(-1); |
3174 cur = cur->parent; | 3174 cur = cur->parent; |
3175 } | 3175 } |
3176 } | 3176 } |
3177 } | 3177 } |
3178 | 3178 |
3179 /* | 3179 /* |
3180 * Speedup using document order if availble. | 3180 * Speedup using document order if availble. |
3181 */ | 3181 */ |
3182 if ((node1->type == XML_ELEMENT_NODE) &&» | 3182 if ((node1->type == XML_ELEMENT_NODE) && |
3183 (node2->type == XML_ELEMENT_NODE) && | 3183 (node2->type == XML_ELEMENT_NODE) && |
3184 (0 > (long) node1->content) && | 3184 (0 > (long) node1->content) && |
3185 (0 > (long) node2->content) && | 3185 (0 > (long) node2->content) && |
3186 » (node1->doc == node2->doc)) {» | 3186 » (node1->doc == node2->doc)) { |
3187 | 3187 |
3188 l1 = -((long) node1->content); | 3188 l1 = -((long) node1->content); |
3189 l2 = -((long) node2->content); | 3189 l2 = -((long) node2->content); |
3190 if (l1 < l2) | 3190 if (l1 < l2) |
3191 return(1); | 3191 return(1); |
3192 if (l1 > l2) | 3192 if (l1 > l2) |
3193 return(-1); | 3193 return(-1); |
3194 } | 3194 } |
3195 | 3195 |
3196 turtle_comparison: | 3196 turtle_comparison: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3244 return(1); | 3244 return(1); |
3245 if (node1 == node2->next) | 3245 if (node1 == node2->next) |
3246 return(-1); | 3246 return(-1); |
3247 /* | 3247 /* |
3248 * Speedup using document order if availble. | 3248 * Speedup using document order if availble. |
3249 */ | 3249 */ |
3250 if ((node1->type == XML_ELEMENT_NODE) && | 3250 if ((node1->type == XML_ELEMENT_NODE) && |
3251 (node2->type == XML_ELEMENT_NODE) && | 3251 (node2->type == XML_ELEMENT_NODE) && |
3252 (0 > (long) node1->content) && | 3252 (0 > (long) node1->content) && |
3253 (0 > (long) node2->content) && | 3253 (0 > (long) node2->content) && |
3254 » (node1->doc == node2->doc)) {» | 3254 » (node1->doc == node2->doc)) { |
3255 | 3255 |
3256 l1 = -((long) node1->content); | 3256 l1 = -((long) node1->content); |
3257 l2 = -((long) node2->content); | 3257 l2 = -((long) node2->content); |
3258 if (l1 < l2) | 3258 if (l1 < l2) |
3259 return(1); | 3259 return(1); |
3260 if (l1 > l2) | 3260 if (l1 > l2) |
3261 return(-1); | 3261 return(-1); |
3262 } | 3262 } |
3263 | 3263 |
3264 for (cur = node1->next;cur != NULL;cur = cur->next) | 3264 for (cur = node1->next;cur != NULL;cur = cur->next) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3332 * Allocate a new Namespace and fill the fields. | 3332 * Allocate a new Namespace and fill the fields. |
3333 */ | 3333 */ |
3334 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); | 3334 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); |
3335 if (cur == NULL) { | 3335 if (cur == NULL) { |
3336 xmlXPathErrMemory(NULL, "duplicating namespace\n"); | 3336 xmlXPathErrMemory(NULL, "duplicating namespace\n"); |
3337 return(NULL); | 3337 return(NULL); |
3338 } | 3338 } |
3339 memset(cur, 0, sizeof(xmlNs)); | 3339 memset(cur, 0, sizeof(xmlNs)); |
3340 cur->type = XML_NAMESPACE_DECL; | 3340 cur->type = XML_NAMESPACE_DECL; |
3341 if (ns->href != NULL) | 3341 if (ns->href != NULL) |
3342 » cur->href = xmlStrdup(ns->href); | 3342 » cur->href = xmlStrdup(ns->href); |
3343 if (ns->prefix != NULL) | 3343 if (ns->prefix != NULL) |
3344 » cur->prefix = xmlStrdup(ns->prefix); | 3344 » cur->prefix = xmlStrdup(ns->prefix); |
3345 cur->next = (xmlNsPtr) node; | 3345 cur->next = (xmlNsPtr) node; |
3346 return((xmlNodePtr) cur); | 3346 return((xmlNodePtr) cur); |
3347 } | 3347 } |
3348 | 3348 |
3349 /** | 3349 /** |
3350 * xmlXPathNodeSetFreeNs: | 3350 * xmlXPathNodeSetFreeNs: |
3351 * @ns: the XPath namespace node found in a nodeset. | 3351 * @ns: the XPath namespace node found in a nodeset. |
3352 * | 3352 * |
3353 * Namespace nodes in libxml don't match the XPath semantic. In a node set | 3353 * Namespace nodes in libxml don't match the XPath semantic. In a node set |
3354 * the namespace nodes are duplicated and the next pointer is set to the | 3354 * the namespace nodes are duplicated and the next pointer is set to the |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3428 memset(ret, 0 , (size_t) sizeof(xmlNodeSet)); | 3428 memset(ret, 0 , (size_t) sizeof(xmlNodeSet)); |
3429 if (size < XML_NODESET_DEFAULT) | 3429 if (size < XML_NODESET_DEFAULT) |
3430 size = XML_NODESET_DEFAULT; | 3430 size = XML_NODESET_DEFAULT; |
3431 ret->nodeTab = (xmlNodePtr *) xmlMalloc(size * sizeof(xmlNodePtr)); | 3431 ret->nodeTab = (xmlNodePtr *) xmlMalloc(size * sizeof(xmlNodePtr)); |
3432 if (ret->nodeTab == NULL) { | 3432 if (ret->nodeTab == NULL) { |
3433 xmlXPathErrMemory(NULL, "creating nodeset\n"); | 3433 xmlXPathErrMemory(NULL, "creating nodeset\n"); |
3434 xmlFree(ret); | 3434 xmlFree(ret); |
3435 return(NULL); | 3435 return(NULL); |
3436 } | 3436 } |
3437 memset(ret->nodeTab, 0 , size * (size_t) sizeof(xmlNodePtr)); | 3437 memset(ret->nodeTab, 0 , size * (size_t) sizeof(xmlNodePtr)); |
3438 ret->nodeMax = size; | 3438 ret->nodeMax = size; |
3439 return(ret); | 3439 return(ret); |
3440 } | 3440 } |
3441 | 3441 |
3442 /** | 3442 /** |
3443 * xmlXPathNodeSetContains: | 3443 * xmlXPathNodeSetContains: |
3444 * @cur: the node-set | 3444 * @cur: the node-set |
3445 * @val: the node | 3445 * @val: the node |
3446 * | 3446 * |
3447 * checks whether @cur contains @val | 3447 * checks whether @cur contains @val |
3448 * | 3448 * |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3481 * @cur: the initial node set | 3481 * @cur: the initial node set |
3482 * @node: the hosting node | 3482 * @node: the hosting node |
3483 * @ns: a the namespace node | 3483 * @ns: a the namespace node |
3484 * | 3484 * |
3485 * add a new namespace node to an existing NodeSet | 3485 * add a new namespace node to an existing NodeSet |
3486 */ | 3486 */ |
3487 void | 3487 void |
3488 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { | 3488 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { |
3489 int i; | 3489 int i; |
3490 | 3490 |
3491 | 3491 |
3492 if ((cur == NULL) || (ns == NULL) || (node == NULL) || | 3492 if ((cur == NULL) || (ns == NULL) || (node == NULL) || |
3493 (ns->type != XML_NAMESPACE_DECL) || | 3493 (ns->type != XML_NAMESPACE_DECL) || |
3494 (node->type != XML_ELEMENT_NODE)) | 3494 (node->type != XML_ELEMENT_NODE)) |
3495 return; | 3495 return; |
3496 | 3496 |
3497 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ | 3497 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ |
3498 /* | 3498 /* |
3499 * prevent duplicates | 3499 * prevent duplicates |
3500 */ | 3500 */ |
3501 for (i = 0;i < cur->nodeNr;i++) { | 3501 for (i = 0;i < cur->nodeNr;i++) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3580 sizeof(xmlNodePtr)); | 3580 sizeof(xmlNodePtr)); |
3581 if (temp == NULL) { | 3581 if (temp == NULL) { |
3582 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3582 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
3583 return; | 3583 return; |
3584 } | 3584 } |
3585 cur->nodeTab = temp; | 3585 cur->nodeTab = temp; |
3586 } | 3586 } |
3587 if (val->type == XML_NAMESPACE_DECL) { | 3587 if (val->type == XML_NAMESPACE_DECL) { |
3588 xmlNsPtr ns = (xmlNsPtr) val; | 3588 xmlNsPtr ns = (xmlNsPtr) val; |
3589 | 3589 |
3590 » cur->nodeTab[cur->nodeNr++] = | 3590 » cur->nodeTab[cur->nodeNr++] = |
3591 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 3591 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
3592 } else | 3592 } else |
3593 cur->nodeTab[cur->nodeNr++] = val; | 3593 cur->nodeTab[cur->nodeNr++] = val; |
3594 } | 3594 } |
3595 | 3595 |
3596 /** | 3596 /** |
3597 * xmlXPathNodeSetAddUnique: | 3597 * xmlXPathNodeSetAddUnique: |
3598 * @cur: the initial node set | 3598 * @cur: the initial node set |
3599 * @val: a new xmlNodePtr | 3599 * @val: a new xmlNodePtr |
3600 * | 3600 * |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3632 sizeof(xmlNodePtr)); | 3632 sizeof(xmlNodePtr)); |
3633 if (temp == NULL) { | 3633 if (temp == NULL) { |
3634 xmlXPathErrMemory(NULL, "growing nodeset\n"); | 3634 xmlXPathErrMemory(NULL, "growing nodeset\n"); |
3635 return; | 3635 return; |
3636 } | 3636 } |
3637 cur->nodeTab = temp; | 3637 cur->nodeTab = temp; |
3638 } | 3638 } |
3639 if (val->type == XML_NAMESPACE_DECL) { | 3639 if (val->type == XML_NAMESPACE_DECL) { |
3640 xmlNsPtr ns = (xmlNsPtr) val; | 3640 xmlNsPtr ns = (xmlNsPtr) val; |
3641 | 3641 |
3642 » cur->nodeTab[cur->nodeNr++] = | 3642 » cur->nodeTab[cur->nodeNr++] = |
3643 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 3643 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
3644 } else | 3644 } else |
3645 cur->nodeTab[cur->nodeNr++] = val; | 3645 cur->nodeTab[cur->nodeNr++] = val; |
3646 } | 3646 } |
3647 | 3647 |
3648 /** | 3648 /** |
3649 * xmlXPathNodeSetMerge: | 3649 * xmlXPathNodeSetMerge: |
3650 * @val1: the first NodeSet or NULL | 3650 * @val1: the first NodeSet or NULL |
3651 * @val2: the second NodeSet | 3651 * @val2: the second NodeSet |
3652 * | 3652 * |
(...skipping 14 matching lines...) Expand all Loading... |
3667 return (NULL); | 3667 return (NULL); |
3668 #if 0 | 3668 #if 0 |
3669 /* | 3669 /* |
3670 * TODO: The optimization won't work in every case, since | 3670 * TODO: The optimization won't work in every case, since |
3671 * those nasty namespace nodes need to be added with | 3671 * those nasty namespace nodes need to be added with |
3672 * xmlXPathNodeSetDupNs() to the set; thus a pure | 3672 * xmlXPathNodeSetDupNs() to the set; thus a pure |
3673 * memcpy is not possible. | 3673 * memcpy is not possible. |
3674 * If there was a flag on the nodesetval, indicating that | 3674 * If there was a flag on the nodesetval, indicating that |
3675 * some temporary nodes are in, that would be helpfull. | 3675 * some temporary nodes are in, that would be helpfull. |
3676 */ | 3676 */ |
3677 » /*» | 3677 » /* |
3678 * Optimization: Create an equally sized node-set | 3678 * Optimization: Create an equally sized node-set |
3679 * and memcpy the content. | 3679 * and memcpy the content. |
3680 */ | 3680 */ |
3681 val1 = xmlXPathNodeSetCreateSize(val2->nodeNr); | 3681 val1 = xmlXPathNodeSetCreateSize(val2->nodeNr); |
3682 if (val1 == NULL) | 3682 if (val1 == NULL) |
3683 return(NULL); | 3683 return(NULL); |
3684 if (val2->nodeNr != 0) { | 3684 if (val2->nodeNr != 0) { |
3685 if (val2->nodeNr == 1) | 3685 if (val2->nodeNr == 1) |
3686 *(val1->nodeTab) = *(val2->nodeTab); | 3686 *(val1->nodeTab) = *(val2->nodeTab); |
3687 else { | 3687 else { |
3688 memcpy(val1->nodeTab, val2->nodeTab, | 3688 memcpy(val1->nodeTab, val2->nodeTab, |
3689 val2->nodeNr * sizeof(xmlNodePtr)); | 3689 val2->nodeNr * sizeof(xmlNodePtr)); |
3690 } | 3690 } |
3691 val1->nodeNr = val2->nodeNr; | 3691 val1->nodeNr = val2->nodeNr; |
3692 } | 3692 } |
3693 return(val1); | 3693 return(val1); |
3694 #endif | 3694 #endif |
3695 } | 3695 } |
3696 | 3696 |
3697 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ | 3697 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ |
3698 initNr = val1->nodeNr; | 3698 initNr = val1->nodeNr; |
3699 | 3699 |
3700 for (i = 0;i < val2->nodeNr;i++) { | 3700 for (i = 0;i < val2->nodeNr;i++) { |
3701 » n2 = val2->nodeTab[i]; | 3701 » n2 = val2->nodeTab[i]; |
3702 /* | 3702 /* |
3703 * check against duplicates | 3703 * check against duplicates |
3704 */ | 3704 */ |
3705 skip = 0; | 3705 skip = 0; |
3706 for (j = 0; j < initNr; j++) { | 3706 for (j = 0; j < initNr; j++) { |
3707 n1 = val1->nodeTab[j]; | 3707 n1 = val1->nodeTab[j]; |
3708 if (n1 == n2) { | 3708 if (n1 == n2) { |
3709 skip = 1; | 3709 skip = 1; |
3710 break; | 3710 break; |
3711 } else if ((n1->type == XML_NAMESPACE_DECL) && | 3711 } else if ((n1->type == XML_NAMESPACE_DECL) && |
3712 » » (n2->type == XML_NAMESPACE_DECL)) {» » | 3712 » » (n2->type == XML_NAMESPACE_DECL)) { |
3713 if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) && | 3713 if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) && |
3714 (xmlStrEqual(((xmlNsPtr) n1)->prefix, | 3714 (xmlStrEqual(((xmlNsPtr) n1)->prefix, |
3715 ((xmlNsPtr) n2)->prefix))) | 3715 ((xmlNsPtr) n2)->prefix))) |
3716 { | 3716 { |
3717 skip = 1; | 3717 skip = 1; |
3718 break; | 3718 break; |
3719 } | 3719 } |
3720 } | 3720 } |
3721 } | 3721 } |
3722 if (skip) | 3722 if (skip) |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3853 } | 3853 } |
3854 } else { | 3854 } else { |
3855 int i, j, initNbSet1; | 3855 int i, j, initNbSet1; |
3856 xmlNodePtr n1, n2; | 3856 xmlNodePtr n1, n2; |
3857 | 3857 |
3858 if (set1 == NULL) | 3858 if (set1 == NULL) |
3859 set1 = xmlXPathNodeSetCreate(NULL); | 3859 set1 = xmlXPathNodeSetCreate(NULL); |
3860 if (set1 == NULL) | 3860 if (set1 == NULL) |
3861 return (NULL); | 3861 return (NULL); |
3862 | 3862 |
3863 » initNbSet1 = set1->nodeNr; | 3863 » initNbSet1 = set1->nodeNr; |
3864 for (i = 0;i < set2->nodeNr;i++) { | 3864 for (i = 0;i < set2->nodeNr;i++) { |
3865 n2 = set2->nodeTab[i]; | 3865 n2 = set2->nodeTab[i]; |
3866 /* | 3866 /* |
3867 * Skip NULLed entries. | 3867 * Skip NULLed entries. |
3868 */ | 3868 */ |
3869 if (n2 == NULL) | 3869 if (n2 == NULL) |
3870 continue; | 3870 continue; |
3871 /* | 3871 /* |
3872 * Skip duplicates. | 3872 * Skip duplicates. |
3873 */ | 3873 */ |
3874 for (j = 0; j < initNbSet1; j++) { | 3874 for (j = 0; j < initNbSet1; j++) { |
3875 n1 = set1->nodeTab[j]; | 3875 n1 = set1->nodeTab[j]; |
3876 » » if (n1 == n2) {»» | 3876 » » if (n1 == n2) { |
3877 goto skip_node; | 3877 goto skip_node; |
3878 } else if ((n1->type == XML_NAMESPACE_DECL) && | 3878 } else if ((n1->type == XML_NAMESPACE_DECL) && |
3879 (n2->type == XML_NAMESPACE_DECL)) | 3879 (n2->type == XML_NAMESPACE_DECL)) |
3880 » » {» » | 3880 » » { |
3881 if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) && | 3881 if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) && |
3882 (xmlStrEqual(((xmlNsPtr) n1)->prefix, | 3882 (xmlStrEqual(((xmlNsPtr) n1)->prefix, |
3883 ((xmlNsPtr) n2)->prefix))) | 3883 ((xmlNsPtr) n2)->prefix))) |
3884 { | 3884 { |
3885 /* | 3885 /* |
3886 * Free the namespace node. | 3886 * Free the namespace node. |
3887 */ | 3887 */ |
3888 set2->nodeTab[i] = NULL; | 3888 set2->nodeTab[i] = NULL; |
3889 xmlXPathNodeSetFreeNs((xmlNsPtr) n2); | 3889 xmlXPathNodeSetFreeNs((xmlNsPtr) n2); |
3890 goto skip_node; | 3890 goto skip_node; |
3891 } | 3891 } |
3892 } | 3892 } |
3893 } | 3893 } |
3894 /* | 3894 /* |
3895 * grow the nodeTab if needed | 3895 * grow the nodeTab if needed |
3896 */ | 3896 */ |
3897 if (set1->nodeMax == 0) { | 3897 if (set1->nodeMax == 0) { |
3898 set1->nodeTab = (xmlNodePtr *) xmlMalloc( | 3898 set1->nodeTab = (xmlNodePtr *) xmlMalloc( |
3899 XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); | 3899 XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); |
3900 if (set1->nodeTab == NULL) { | 3900 if (set1->nodeTab == NULL) { |
3901 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 3901 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
3902 return(NULL); | 3902 return(NULL); |
3903 } | 3903 } |
3904 memset(set1->nodeTab, 0, | 3904 memset(set1->nodeTab, 0, |
3905 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 3905 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
3906 set1->nodeMax = XML_NODESET_DEFAULT; | 3906 set1->nodeMax = XML_NODESET_DEFAULT; |
3907 } else if (set1->nodeNr >= set1->nodeMax) { | 3907 } else if (set1->nodeNr >= set1->nodeMax) { |
3908 xmlNodePtr *temp; | 3908 xmlNodePtr *temp; |
3909 » » | 3909 |
3910 set1->nodeMax *= 2; | 3910 set1->nodeMax *= 2; |
3911 temp = (xmlNodePtr *) xmlRealloc( | 3911 temp = (xmlNodePtr *) xmlRealloc( |
3912 set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); | 3912 set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); |
3913 if (temp == NULL) { | 3913 if (temp == NULL) { |
3914 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 3914 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
3915 return(NULL); | 3915 return(NULL); |
3916 } | 3916 } |
3917 set1->nodeTab = temp; | 3917 set1->nodeTab = temp; |
3918 } | 3918 } |
3919 if (n2->type == XML_NAMESPACE_DECL) { | 3919 if (n2->type == XML_NAMESPACE_DECL) { |
3920 xmlNsPtr ns = (xmlNsPtr) n2; | 3920 xmlNsPtr ns = (xmlNsPtr) n2; |
3921 » » | 3921 |
3922 set1->nodeTab[set1->nodeNr++] = | 3922 set1->nodeTab[set1->nodeNr++] = |
3923 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); | 3923 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); |
3924 } else | 3924 } else |
3925 set1->nodeTab[set1->nodeNr++] = n2; | 3925 set1->nodeTab[set1->nodeNr++] = n2; |
3926 skip_node: | 3926 skip_node: |
3927 {} | 3927 {} |
3928 } | 3928 } |
3929 } | 3929 } |
3930 set2->nodeNr = 0; | 3930 set2->nodeNr = 0; |
3931 return(set1); | 3931 return(set1); |
3932 } | 3932 } |
3933 | 3933 |
3934 /** | 3934 /** |
3935 * xmlXPathNodeSetMergeAndClearNoDupls: | 3935 * xmlXPathNodeSetMergeAndClearNoDupls: |
3936 * @set1: the first NodeSet or NULL | 3936 * @set1: the first NodeSet or NULL |
3937 * @set2: the second NodeSet | 3937 * @set2: the second NodeSet |
3938 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes | 3938 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes |
3939 * | 3939 * |
3940 * Merges two nodesets, all nodes from @set2 are added to @set1 | 3940 * Merges two nodesets, all nodes from @set2 are added to @set1 |
3941 * if @set1 is NULL, a new set is created and copied from @set2. | 3941 * if @set1 is NULL, a new set is created and copied from @set2. |
3942 * Doesn't chack for duplicate nodes. Clears set2. | 3942 * Doesn't chack for duplicate nodes. Clears set2. |
3943 * | 3943 * |
3944 * Returns @set1 once extended or NULL in case of error. | 3944 * Returns @set1 once extended or NULL in case of error. |
3945 */ | 3945 */ |
3946 static xmlNodeSetPtr | 3946 static xmlNodeSetPtr |
3947 xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2, | 3947 xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2, |
3948 int hasNullEntries) | 3948 int hasNullEntries) |
3949 { | 3949 { |
3950 if (set2 == NULL) | 3950 if (set2 == NULL) |
3951 return(set1); | 3951 return(set1); |
3952 if ((set1 == NULL) && (hasNullEntries == 0)) { | 3952 if ((set1 == NULL) && (hasNullEntries == 0)) { |
3953 /* | 3953 /* |
3954 * Note that doing a memcpy of the list, namespace nodes are | 3954 * Note that doing a memcpy of the list, namespace nodes are |
3955 * just assigned to set1, since set2 is cleared anyway. | 3955 * just assigned to set1, since set2 is cleared anyway. |
3956 */ | 3956 */ |
3957 set1 = xmlXPathNodeSetCreateSize(set2->nodeNr); | 3957 set1 = xmlXPathNodeSetCreateSize(set2->nodeNr); |
3958 if (set1 == NULL) | 3958 if (set1 == NULL) |
3959 return(NULL); | 3959 return(NULL); |
3960 if (set2->nodeNr != 0) { | 3960 if (set2->nodeNr != 0) { |
3961 memcpy(set1->nodeTab, set2->nodeTab, | 3961 memcpy(set1->nodeTab, set2->nodeTab, |
3962 set2->nodeNr * sizeof(xmlNodePtr)); | 3962 set2->nodeNr * sizeof(xmlNodePtr)); |
3963 set1->nodeNr = set2->nodeNr; | 3963 set1->nodeNr = set2->nodeNr; |
3964 } | 3964 } |
3965 } else { | 3965 } else { |
3966 int i; | 3966 int i; |
3967 xmlNodePtr n2; | 3967 xmlNodePtr n2; |
3968 | 3968 |
3969 if (set1 == NULL) | 3969 if (set1 == NULL) |
3970 set1 = xmlXPathNodeSetCreate(NULL); | 3970 set1 = xmlXPathNodeSetCreate(NULL); |
3971 if (set1 == NULL) | 3971 if (set1 == NULL) |
3972 return (NULL); | 3972 return (NULL); |
3973 | 3973 |
3974 for (i = 0;i < set2->nodeNr;i++) { | 3974 for (i = 0;i < set2->nodeNr;i++) { |
3975 n2 = set2->nodeTab[i]; | 3975 n2 = set2->nodeTab[i]; |
3976 /* | 3976 /* |
3977 * Skip NULLed entries. | 3977 * Skip NULLed entries. |
3978 */ | 3978 */ |
3979 if (n2 == NULL) | 3979 if (n2 == NULL) |
3980 » » continue;» | 3980 » » continue; |
3981 if (set1->nodeMax == 0) { | 3981 if (set1->nodeMax == 0) { |
3982 set1->nodeTab = (xmlNodePtr *) xmlMalloc( | 3982 set1->nodeTab = (xmlNodePtr *) xmlMalloc( |
3983 XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); | 3983 XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); |
3984 if (set1->nodeTab == NULL) { | 3984 if (set1->nodeTab == NULL) { |
3985 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 3985 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
3986 return(NULL); | 3986 return(NULL); |
3987 } | 3987 } |
3988 memset(set1->nodeTab, 0, | 3988 memset(set1->nodeTab, 0, |
3989 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); | 3989 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); |
3990 set1->nodeMax = XML_NODESET_DEFAULT; | 3990 set1->nodeMax = XML_NODESET_DEFAULT; |
3991 } else if (set1->nodeNr >= set1->nodeMax) { | 3991 } else if (set1->nodeNr >= set1->nodeMax) { |
3992 xmlNodePtr *temp; | 3992 xmlNodePtr *temp; |
3993 » » | 3993 |
3994 set1->nodeMax *= 2; | 3994 set1->nodeMax *= 2; |
3995 temp = (xmlNodePtr *) xmlRealloc( | 3995 temp = (xmlNodePtr *) xmlRealloc( |
3996 set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); | 3996 set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); |
3997 if (temp == NULL) { | 3997 if (temp == NULL) { |
3998 xmlXPathErrMemory(NULL, "merging nodeset\n"); | 3998 xmlXPathErrMemory(NULL, "merging nodeset\n"); |
3999 return(NULL); | 3999 return(NULL); |
4000 } | 4000 } |
4001 set1->nodeTab = temp; | 4001 set1->nodeTab = temp; |
4002 } | 4002 } |
4003 set1->nodeTab[set1->nodeNr++] = n2; | 4003 set1->nodeTab[set1->nodeNr++] = n2; |
(...skipping 18 matching lines...) Expand all Loading... |
4022 if (val == NULL) return; | 4022 if (val == NULL) return; |
4023 | 4023 |
4024 /* | 4024 /* |
4025 * find node in nodeTab | 4025 * find node in nodeTab |
4026 */ | 4026 */ |
4027 for (i = 0;i < cur->nodeNr;i++) | 4027 for (i = 0;i < cur->nodeNr;i++) |
4028 if (cur->nodeTab[i] == val) break; | 4028 if (cur->nodeTab[i] == val) break; |
4029 | 4029 |
4030 if (i >= cur->nodeNr) { /* not found */ | 4030 if (i >= cur->nodeNr) { /* not found */ |
4031 #ifdef DEBUG | 4031 #ifdef DEBUG |
4032 xmlGenericError(xmlGenericErrorContext, | 4032 xmlGenericError(xmlGenericErrorContext, |
4033 "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n", | 4033 "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n", |
4034 val->name); | 4034 val->name); |
4035 #endif | 4035 #endif |
4036 return; | 4036 return; |
4037 } | 4037 } |
4038 if ((cur->nodeTab[i] != NULL) && | 4038 if ((cur->nodeTab[i] != NULL) && |
4039 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL)) | 4039 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL)) |
4040 xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]); | 4040 xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]); |
4041 cur->nodeNr--; | 4041 cur->nodeNr--; |
4042 for (;i < cur->nodeNr;i++) | 4042 for (;i < cur->nodeNr;i++) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4082 (obj->nodeTab[i]->type == XML_NAMESPACE_DECL)) | 4082 (obj->nodeTab[i]->type == XML_NAMESPACE_DECL)) |
4083 xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]); | 4083 xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]); |
4084 xmlFree(obj->nodeTab); | 4084 xmlFree(obj->nodeTab); |
4085 } | 4085 } |
4086 xmlFree(obj); | 4086 xmlFree(obj); |
4087 } | 4087 } |
4088 | 4088 |
4089 /** | 4089 /** |
4090 * xmlXPathNodeSetClear: | 4090 * xmlXPathNodeSetClear: |
4091 * @set: the node set to clear | 4091 * @set: the node set to clear |
4092 * | 4092 * |
4093 * Clears the list from all temporary XPath objects (e.g. namespace nodes | 4093 * Clears the list from all temporary XPath objects (e.g. namespace nodes |
4094 * are feed), but does *not* free the list itself. Sets the length of the | 4094 * are feed), but does *not* free the list itself. Sets the length of the |
4095 * list to 0. | 4095 * list to 0. |
4096 */ | 4096 */ |
4097 static void | 4097 static void |
4098 xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes) | 4098 xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes) |
4099 { | 4099 { |
4100 if ((set == NULL) || (set->nodeNr <= 0)) | 4100 if ((set == NULL) || (set->nodeNr <= 0)) |
4101 return; | 4101 return; |
4102 else if (hasNsNodes) { | 4102 else if (hasNsNodes) { |
4103 int i; | 4103 int i; |
4104 xmlNodePtr node; | 4104 xmlNodePtr node; |
4105 » | 4105 |
4106 for (i = 0; i < set->nodeNr; i++) { | 4106 for (i = 0; i < set->nodeNr; i++) { |
4107 node = set->nodeTab[i]; | 4107 node = set->nodeTab[i]; |
4108 if ((node != NULL) && | 4108 if ((node != NULL) && |
4109 (node->type == XML_NAMESPACE_DECL)) | 4109 (node->type == XML_NAMESPACE_DECL)) |
4110 xmlXPathNodeSetFreeNs((xmlNsPtr) node); | 4110 xmlXPathNodeSetFreeNs((xmlNsPtr) node); |
4111 » }» | 4111 » } |
4112 } | 4112 } |
4113 set->nodeNr = 0; | 4113 set->nodeNr = 0; |
4114 } | 4114 } |
4115 | 4115 |
4116 /** | 4116 /** |
4117 * xmlXPathNodeSetClearFromPos: | 4117 * xmlXPathNodeSetClearFromPos: |
4118 * @set: the node set to be cleared | 4118 * @set: the node set to be cleared |
4119 * @pos: the start position to clear from | 4119 * @pos: the start position to clear from |
4120 * | 4120 * |
4121 * Clears the list from temporary XPath objects (e.g. namespace nodes | 4121 * Clears the list from temporary XPath objects (e.g. namespace nodes |
4122 * are feed) starting with the entry at @pos, but does *not* free the list | 4122 * are feed) starting with the entry at @pos, but does *not* free the list |
4123 * itself. Sets the length of the list to @pos. | 4123 * itself. Sets the length of the list to @pos. |
4124 */ | 4124 */ |
4125 static void | 4125 static void |
4126 xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes) | 4126 xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes) |
4127 { | 4127 { |
4128 if ((set == NULL) || (set->nodeNr <= 0) || (pos >= set->nodeNr)) | 4128 if ((set == NULL) || (set->nodeNr <= 0) || (pos >= set->nodeNr)) |
4129 return; | 4129 return; |
4130 else if ((hasNsNodes)) { | 4130 else if ((hasNsNodes)) { |
4131 int i; | 4131 int i; |
4132 xmlNodePtr node; | 4132 xmlNodePtr node; |
4133 » | 4133 |
4134 for (i = pos; i < set->nodeNr; i++) { | 4134 for (i = pos; i < set->nodeNr; i++) { |
4135 node = set->nodeTab[i]; | 4135 node = set->nodeTab[i]; |
4136 if ((node != NULL) && | 4136 if ((node != NULL) && |
4137 (node->type == XML_NAMESPACE_DECL)) | 4137 (node->type == XML_NAMESPACE_DECL)) |
4138 xmlXPathNodeSetFreeNs((xmlNsPtr) node); | 4138 xmlXPathNodeSetFreeNs((xmlNsPtr) node); |
4139 » }» | 4139 » } |
4140 } | 4140 } |
4141 set->nodeNr = pos; | 4141 set->nodeNr = pos; |
4142 } | 4142 } |
4143 | 4143 |
4144 /** | 4144 /** |
4145 * xmlXPathFreeValueTree: | 4145 * xmlXPathFreeValueTree: |
4146 * @obj: the xmlNodeSetPtr to free | 4146 * @obj: the xmlNodeSetPtr to free |
4147 * | 4147 * |
4148 * Free the NodeSet compound and the actual tree, this is different | 4148 * Free the NodeSet compound and the actual tree, this is different |
4149 * from xmlXPathFreeNodeSet() | 4149 * from xmlXPathFreeNodeSet() |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4406 } | 4406 } |
4407 return(ret); | 4407 return(ret); |
4408 } | 4408 } |
4409 | 4409 |
4410 /** | 4410 /** |
4411 * xmlXPathDistinctSorted: | 4411 * xmlXPathDistinctSorted: |
4412 * @nodes: a node-set, sorted by document order | 4412 * @nodes: a node-set, sorted by document order |
4413 * | 4413 * |
4414 * Implements the EXSLT - Sets distinct() function: | 4414 * Implements the EXSLT - Sets distinct() function: |
4415 * node-set set:distinct (node-set) | 4415 * node-set set:distinct (node-set) |
4416 * | 4416 * |
4417 * Returns a subset of the nodes contained in @nodes, or @nodes if | 4417 * Returns a subset of the nodes contained in @nodes, or @nodes if |
4418 * it is empty | 4418 * it is empty |
4419 */ | 4419 */ |
4420 xmlNodeSetPtr | 4420 xmlNodeSetPtr |
4421 xmlXPathDistinctSorted (xmlNodeSetPtr nodes) { | 4421 xmlXPathDistinctSorted (xmlNodeSetPtr nodes) { |
4422 xmlNodeSetPtr ret; | 4422 xmlNodeSetPtr ret; |
4423 xmlHashTablePtr hash; | 4423 xmlHashTablePtr hash; |
4424 int i, l; | 4424 int i, l; |
4425 xmlChar * strval; | 4425 xmlChar * strval; |
4426 xmlNodePtr cur; | 4426 xmlNodePtr cur; |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4715 /** | 4715 /** |
4716 * xmlXPathRegisterFunc: | 4716 * xmlXPathRegisterFunc: |
4717 * @ctxt: the XPath context | 4717 * @ctxt: the XPath context |
4718 * @name: the function name | 4718 * @name: the function name |
4719 * @f: the function implementation or NULL | 4719 * @f: the function implementation or NULL |
4720 * | 4720 * |
4721 * Register a new function. If @f is NULL it unregisters the function | 4721 * Register a new function. If @f is NULL it unregisters the function |
4722 * | 4722 * |
4723 * Returns 0 in case of success, -1 in case of error | 4723 * Returns 0 in case of success, -1 in case of error |
4724 */ | 4724 */ |
4725 int» » | 4725 int |
4726 xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name, | 4726 xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name, |
4727 xmlXPathFunction f) { | 4727 xmlXPathFunction f) { |
4728 return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f)); | 4728 return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f)); |
4729 } | 4729 } |
4730 | 4730 |
4731 /** | 4731 /** |
4732 * xmlXPathRegisterFuncNS: | 4732 * xmlXPathRegisterFuncNS: |
4733 * @ctxt: the XPath context | 4733 * @ctxt: the XPath context |
4734 * @name: the function name | 4734 * @name: the function name |
4735 * @ns_uri: the function namespace URI | 4735 * @ns_uri: the function namespace URI |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4809 * | 4809 * |
4810 * Search in the Function array of the context for the given | 4810 * Search in the Function array of the context for the given |
4811 * function. | 4811 * function. |
4812 * | 4812 * |
4813 * Returns the xmlXPathFunction or NULL if not found | 4813 * Returns the xmlXPathFunction or NULL if not found |
4814 */ | 4814 */ |
4815 xmlXPathFunction | 4815 xmlXPathFunction |
4816 xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, | 4816 xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, |
4817 const xmlChar *ns_uri) { | 4817 const xmlChar *ns_uri) { |
4818 xmlXPathFunction ret; | 4818 xmlXPathFunction ret; |
4819 | 4819 |
4820 if (ctxt == NULL) | 4820 if (ctxt == NULL) |
4821 return(NULL); | 4821 return(NULL); |
4822 if (name == NULL) | 4822 if (name == NULL) |
4823 return(NULL); | 4823 return(NULL); |
4824 | 4824 |
4825 if (ctxt->funcLookupFunc != NULL) { | 4825 if (ctxt->funcLookupFunc != NULL) { |
4826 xmlXPathFuncLookupFunc f; | 4826 xmlXPathFuncLookupFunc f; |
4827 | 4827 |
4828 f = ctxt->funcLookupFunc; | 4828 f = ctxt->funcLookupFunc; |
4829 ret = f(ctxt->funcLookupData, name, ns_uri); | 4829 ret = f(ctxt->funcLookupData, name, ns_uri); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4863 * xmlXPathRegisterVariable: | 4863 * xmlXPathRegisterVariable: |
4864 * @ctxt: the XPath context | 4864 * @ctxt: the XPath context |
4865 * @name: the variable name | 4865 * @name: the variable name |
4866 * @value: the variable value or NULL | 4866 * @value: the variable value or NULL |
4867 * | 4867 * |
4868 * Register a new variable value. If @value is NULL it unregisters | 4868 * Register a new variable value. If @value is NULL it unregisters |
4869 * the variable | 4869 * the variable |
4870 * | 4870 * |
4871 * Returns 0 in case of success, -1 in case of error | 4871 * Returns 0 in case of success, -1 in case of error |
4872 */ | 4872 */ |
4873 int» » | 4873 int |
4874 xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name, | 4874 xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name, |
4875 xmlXPathObjectPtr value) { | 4875 xmlXPathObjectPtr value) { |
4876 return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value)); | 4876 return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value)); |
4877 } | 4877 } |
4878 | 4878 |
4879 /** | 4879 /** |
4880 * xmlXPathRegisterVariableNS: | 4880 * xmlXPathRegisterVariableNS: |
4881 * @ctxt: the XPath context | 4881 * @ctxt: the XPath context |
4882 * @name: the variable name | 4882 * @name: the variable name |
4883 * @ns_uri: the variable namespace URI | 4883 * @ns_uri: the variable namespace URI |
(...skipping 11 matching lines...) Expand all Loading... |
4895 if (ctxt == NULL) | 4895 if (ctxt == NULL) |
4896 return(-1); | 4896 return(-1); |
4897 if (name == NULL) | 4897 if (name == NULL) |
4898 return(-1); | 4898 return(-1); |
4899 | 4899 |
4900 if (ctxt->varHash == NULL) | 4900 if (ctxt->varHash == NULL) |
4901 ctxt->varHash = xmlHashCreate(0); | 4901 ctxt->varHash = xmlHashCreate(0); |
4902 if (ctxt->varHash == NULL) | 4902 if (ctxt->varHash == NULL) |
4903 return(-1); | 4903 return(-1); |
4904 if (value == NULL) | 4904 if (value == NULL) |
4905 return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri, | 4905 return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri, |
4906 (xmlHashDeallocator)xmlXPathFreeObject)); | 4906 (xmlHashDeallocator)xmlXPathFreeObject)); |
4907 return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri, | 4907 return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri, |
4908 (void *) value, | 4908 (void *) value, |
4909 (xmlHashDeallocator)xmlXPathFreeObject)); | 4909 (xmlHashDeallocator)xmlXPathFreeObject)); |
4910 } | 4910 } |
4911 | 4911 |
4912 /** | 4912 /** |
4913 * xmlXPathRegisterVariableLookup: | 4913 * xmlXPathRegisterVariableLookup: |
4914 * @ctxt: the XPath context | 4914 * @ctxt: the XPath context |
4915 * @f: the lookup function | 4915 * @f: the lookup function |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4951 return(xmlXPathVariableLookupNS(ctxt, name, NULL)); | 4951 return(xmlXPathVariableLookupNS(ctxt, name, NULL)); |
4952 } | 4952 } |
4953 | 4953 |
4954 /** | 4954 /** |
4955 * xmlXPathVariableLookupNS: | 4955 * xmlXPathVariableLookupNS: |
4956 * @ctxt: the XPath context | 4956 * @ctxt: the XPath context |
4957 * @name: the variable name | 4957 * @name: the variable name |
4958 * @ns_uri: the variable namespace URI | 4958 * @ns_uri: the variable namespace URI |
4959 * | 4959 * |
4960 * Search in the Variable array of the context for the given | 4960 * Search in the Variable array of the context for the given |
4961 * variable value. | 4961 * variable value. |
4962 * | 4962 * |
4963 * Returns the a copy of the value or NULL if not found | 4963 * Returns the a copy of the value or NULL if not found |
4964 */ | 4964 */ |
4965 xmlXPathObjectPtr | 4965 xmlXPathObjectPtr |
4966 xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, | 4966 xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name, |
4967 const xmlChar *ns_uri) { | 4967 const xmlChar *ns_uri) { |
4968 if (ctxt == NULL) | 4968 if (ctxt == NULL) |
4969 return(NULL); | 4969 return(NULL); |
4970 | 4970 |
4971 if (ctxt->varLookupFunc != NULL) { | 4971 if (ctxt->varLookupFunc != NULL) { |
(...skipping 24 matching lines...) Expand all Loading... |
4996 if (ctxt == NULL) | 4996 if (ctxt == NULL) |
4997 return; | 4997 return; |
4998 | 4998 |
4999 xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject); | 4999 xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject); |
5000 ctxt->varHash = NULL; | 5000 ctxt->varHash = NULL; |
5001 } | 5001 } |
5002 | 5002 |
5003 /** | 5003 /** |
5004 * xmlXPathRegisterNs: | 5004 * xmlXPathRegisterNs: |
5005 * @ctxt: the XPath context | 5005 * @ctxt: the XPath context |
5006 * @prefix: the namespace prefix | 5006 * @prefix: the namespace prefix cannot be NULL or empty string |
5007 * @ns_uri: the namespace name | 5007 * @ns_uri: the namespace name |
5008 * | 5008 * |
5009 * Register a new namespace. If @ns_uri is NULL it unregisters | 5009 * Register a new namespace. If @ns_uri is NULL it unregisters |
5010 * the namespace | 5010 * the namespace |
5011 * | 5011 * |
5012 * Returns 0 in case of success, -1 in case of error | 5012 * Returns 0 in case of success, -1 in case of error |
5013 */ | 5013 */ |
5014 int | 5014 int |
5015 xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix, | 5015 xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix, |
5016 const xmlChar *ns_uri) { | 5016 const xmlChar *ns_uri) { |
5017 if (ctxt == NULL) | 5017 if (ctxt == NULL) |
5018 return(-1); | 5018 return(-1); |
5019 if (prefix == NULL) | 5019 if (prefix == NULL) |
5020 return(-1); | 5020 return(-1); |
| 5021 if (prefix[0] == 0) |
| 5022 return(-1); |
5021 | 5023 |
5022 if (ctxt->nsHash == NULL) | 5024 if (ctxt->nsHash == NULL) |
5023 ctxt->nsHash = xmlHashCreate(10); | 5025 ctxt->nsHash = xmlHashCreate(10); |
5024 if (ctxt->nsHash == NULL) | 5026 if (ctxt->nsHash == NULL) |
5025 return(-1); | 5027 return(-1); |
5026 if (ns_uri == NULL) | 5028 if (ns_uri == NULL) |
5027 return(xmlHashRemoveEntry(ctxt->nsHash, prefix, | 5029 return(xmlHashRemoveEntry(ctxt->nsHash, prefix, |
5028 (xmlHashDeallocator)xmlFree)); | 5030 (xmlHashDeallocator)xmlFree)); |
5029 return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri), | 5031 return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri), |
5030 (xmlHashDeallocator)xmlFree)); | 5032 (xmlHashDeallocator)xmlFree)); |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5334 case XPATH_LOCATIONSET: | 5336 case XPATH_LOCATIONSET: |
5335 #ifdef LIBXML_XPTR_ENABLED | 5337 #ifdef LIBXML_XPTR_ENABLED |
5336 { | 5338 { |
5337 xmlLocationSetPtr loc = val->user; | 5339 xmlLocationSetPtr loc = val->user; |
5338 ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc); | 5340 ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc); |
5339 break; | 5341 break; |
5340 } | 5342 } |
5341 #endif | 5343 #endif |
5342 case XPATH_USERS: | 5344 case XPATH_USERS: |
5343 ret->user = val->user; | 5345 ret->user = val->user; |
5344 » break; | 5346 » break; |
5345 case XPATH_UNDEFINED: | 5347 case XPATH_UNDEFINED: |
5346 xmlGenericError(xmlGenericErrorContext, | 5348 xmlGenericError(xmlGenericErrorContext, |
5347 "xmlXPathObjectCopy: unsupported type %d\n", | 5349 "xmlXPathObjectCopy: unsupported type %d\n", |
5348 val->type); | 5350 val->type); |
5349 break; | 5351 break; |
5350 } | 5352 } |
5351 return(ret); | 5353 return(ret); |
5352 } | 5354 } |
5353 | 5355 |
5354 /** | 5356 /** |
5355 * xmlXPathFreeObject: | 5357 * xmlXPathFreeObject: |
5356 * @obj: the object to free | 5358 * @obj: the object to free |
5357 * | 5359 * |
5358 * Free up an xmlXPathObjectPtr object. | 5360 * Free up an xmlXPathObjectPtr object. |
5359 */ | 5361 */ |
5360 void | 5362 void |
5361 xmlXPathFreeObject(xmlXPathObjectPtr obj) { | 5363 xmlXPathFreeObject(xmlXPathObjectPtr obj) { |
5362 if (obj == NULL) return; | 5364 if (obj == NULL) return; |
5363 if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) { | 5365 if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) { |
5364 if (obj->boolval) { | 5366 if (obj->boolval) { |
5365 #if 0 | 5367 #if 0 |
5366 if (obj->user != NULL) { | 5368 if (obj->user != NULL) { |
5367 xmlXPathFreeNodeSet(obj->nodesetval); | 5369 xmlXPathFreeNodeSet(obj->nodesetval); |
5368 xmlFreeNodeList((xmlNodePtr) obj->user); | 5370 xmlFreeNodeList((xmlNodePtr) obj->user); |
5369 } else | 5371 } else |
5370 #endif | 5372 #endif |
5371 obj->type = XPATH_XSLT_TREE; /* TODO: Just for debugging. */ | 5373 obj->type = XPATH_XSLT_TREE; /* TODO: Just for debugging. */ |
5372 if (obj->nodesetval != NULL) | 5374 if (obj->nodesetval != NULL) |
5373 » » xmlXPathFreeValueTree(obj->nodesetval);» | 5375 » » xmlXPathFreeValueTree(obj->nodesetval); |
5374 } else { | 5376 } else { |
5375 if (obj->nodesetval != NULL) | 5377 if (obj->nodesetval != NULL) |
5376 xmlXPathFreeNodeSet(obj->nodesetval); | 5378 xmlXPathFreeNodeSet(obj->nodesetval); |
5377 } | 5379 } |
5378 #ifdef LIBXML_XPTR_ENABLED | 5380 #ifdef LIBXML_XPTR_ENABLED |
5379 } else if (obj->type == XPATH_LOCATIONSET) { | 5381 } else if (obj->type == XPATH_LOCATIONSET) { |
5380 if (obj->user != NULL) | 5382 if (obj->user != NULL) |
5381 xmlXPtrFreeLocationSet(obj->user); | 5383 xmlXPtrFreeLocationSet(obj->user); |
5382 #endif | 5384 #endif |
5383 } else if (obj->type == XPATH_STRING) { | 5385 } else if (obj->type == XPATH_STRING) { |
5384 if (obj->stringval != NULL) | 5386 if (obj->stringval != NULL) |
5385 xmlFree(obj->stringval); | 5387 xmlFree(obj->stringval); |
5386 } | 5388 } |
5387 #ifdef XP_DEBUG_OBJ_USAGE | 5389 #ifdef XP_DEBUG_OBJ_USAGE |
5388 xmlXPathDebugObjUsageReleased(NULL, obj->type); | 5390 xmlXPathDebugObjUsageReleased(NULL, obj->type); |
5389 #endif | 5391 #endif |
5390 xmlFree(obj); | 5392 xmlFree(obj); |
5391 } | 5393 } |
5392 | 5394 |
5393 /** | 5395 /** |
5394 * xmlXPathReleaseObject: | 5396 * xmlXPathReleaseObject: |
5395 * @obj: the xmlXPathObjectPtr to free or to cache | 5397 * @obj: the xmlXPathObjectPtr to free or to cache |
5396 * | 5398 * |
5397 * Depending on the state of the cache this frees the given | 5399 * Depending on the state of the cache this frees the given |
5398 * XPath object or stores it in the cache. | 5400 * XPath object or stores it in the cache. |
5399 */ | 5401 */ |
5400 static void | 5402 static void |
5401 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) | 5403 xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) |
5402 { | 5404 { |
5403 #define XP_CACHE_ADD(sl, o) if (sl == NULL) { \ | 5405 #define XP_CACHE_ADD(sl, o) if (sl == NULL) { \ |
5404 sl = xmlPointerListCreate(10); if (sl == NULL) goto free_obj; } \ | 5406 sl = xmlPointerListCreate(10); if (sl == NULL) goto free_obj; } \ |
5405 if (xmlPointerListAddSize(sl, obj, 0) == -1) goto free_obj; | 5407 if (xmlPointerListAddSize(sl, obj, 0) == -1) goto free_obj; |
5406 | 5408 |
5407 #define XP_CACHE_WANTS(sl, n) ((sl == NULL) || ((sl)->number < n)) | 5409 #define XP_CACHE_WANTS(sl, n) ((sl == NULL) || ((sl)->number < n)) |
5408 | 5410 |
5409 if (obj == NULL) | 5411 if (obj == NULL) |
5410 return; | 5412 return; |
5411 if ((ctxt == NULL) || (ctxt->cache == NULL)) { | 5413 if ((ctxt == NULL) || (ctxt->cache == NULL)) { |
5412 xmlXPathFreeObject(obj); | 5414 xmlXPathFreeObject(obj); |
5413 } else { | 5415 } else { |
5414 xmlXPathContextCachePtr cache = | 5416 xmlXPathContextCachePtr cache = |
5415 (xmlXPathContextCachePtr) ctxt->cache; | 5417 (xmlXPathContextCachePtr) ctxt->cache; |
5416 | 5418 |
5417 switch (obj->type) { | 5419 switch (obj->type) { |
5418 case XPATH_NODESET: | 5420 case XPATH_NODESET: |
5419 case XPATH_XSLT_TREE: | 5421 case XPATH_XSLT_TREE: |
5420 if (obj->nodesetval != NULL) { | 5422 if (obj->nodesetval != NULL) { |
5421 if (obj->boolval) { | 5423 if (obj->boolval) { |
5422 » » » /* | 5424 » » » /* |
5423 * It looks like the @boolval is used for | 5425 * It looks like the @boolval is used for |
5424 * evaluation if this an XSLT Result Tree Fragment. | 5426 * evaluation if this an XSLT Result Tree Fragment. |
5425 * TODO: Check if this assumption is correct. | 5427 * TODO: Check if this assumption is correct. |
5426 */ | 5428 */ |
5427 obj->type = XPATH_XSLT_TREE; /* just for debugging */ | 5429 obj->type = XPATH_XSLT_TREE; /* just for debugging */ |
5428 xmlXPathFreeValueTree(obj->nodesetval); | 5430 xmlXPathFreeValueTree(obj->nodesetval); |
5429 obj->nodesetval = NULL; | 5431 obj->nodesetval = NULL; |
5430 } else if ((obj->nodesetval->nodeMax <= 40) && | 5432 } else if ((obj->nodesetval->nodeMax <= 40) && |
5431 (XP_CACHE_WANTS(cache->nodesetObjs, | 5433 (XP_CACHE_WANTS(cache->nodesetObjs, |
5432 cache->maxNodeset))) | 5434 cache->maxNodeset))) |
(...skipping 26 matching lines...) Expand all Loading... |
5459 XP_CACHE_ADD(cache->numberObjs, obj); | 5461 XP_CACHE_ADD(cache->numberObjs, obj); |
5460 goto obj_cached; | 5462 goto obj_cached; |
5461 } | 5463 } |
5462 break; | 5464 break; |
5463 #ifdef LIBXML_XPTR_ENABLED | 5465 #ifdef LIBXML_XPTR_ENABLED |
5464 case XPATH_LOCATIONSET: | 5466 case XPATH_LOCATIONSET: |
5465 if (obj->user != NULL) { | 5467 if (obj->user != NULL) { |
5466 xmlXPtrFreeLocationSet(obj->user); | 5468 xmlXPtrFreeLocationSet(obj->user); |
5467 } | 5469 } |
5468 goto free_obj; | 5470 goto free_obj; |
5469 #endif» | 5471 #endif |
5470 default: | 5472 default: |
5471 goto free_obj; | 5473 goto free_obj; |
5472 } | 5474 } |
5473 | 5475 |
5474 /* | 5476 /* |
5475 * Fallback to adding to the misc-objects slot. | 5477 * Fallback to adding to the misc-objects slot. |
5476 */ | 5478 */ |
5477 if (XP_CACHE_WANTS(cache->miscObjs, cache->maxMisc)) { | 5479 if (XP_CACHE_WANTS(cache->miscObjs, cache->maxMisc)) { |
5478 XP_CACHE_ADD(cache->miscObjs, obj); | 5480 XP_CACHE_ADD(cache->miscObjs, obj); |
5479 } else | 5481 } else |
5480 goto free_obj; | 5482 goto free_obj; |
5481 | 5483 |
5482 obj_cached: | 5484 obj_cached: |
5483 | 5485 |
5484 #ifdef XP_DEBUG_OBJ_USAGE | 5486 #ifdef XP_DEBUG_OBJ_USAGE |
5485 xmlXPathDebugObjUsageReleased(ctxt, obj->type); | 5487 xmlXPathDebugObjUsageReleased(ctxt, obj->type); |
5486 #endif | 5488 #endif |
5487 | 5489 |
5488 if (obj->nodesetval != NULL) { | 5490 if (obj->nodesetval != NULL) { |
5489 xmlNodeSetPtr tmpset = obj->nodesetval; | 5491 xmlNodeSetPtr tmpset = obj->nodesetval; |
5490 » | 5492 |
5491 /* | 5493 /* |
5492 * TODO: Due to those nasty ns-nodes, we need to traverse | 5494 * TODO: Due to those nasty ns-nodes, we need to traverse |
5493 * the list and free the ns-nodes. | 5495 * the list and free the ns-nodes. |
5494 * URGENT TODO: Check if it's actually slowing things down. | 5496 * URGENT TODO: Check if it's actually slowing things down. |
5495 * Maybe we shouldn't try to preserve the list. | 5497 * Maybe we shouldn't try to preserve the list. |
5496 */ | 5498 */ |
5497 if (tmpset->nodeNr > 1) { | 5499 if (tmpset->nodeNr > 1) { |
5498 int i; | 5500 int i; |
5499 xmlNodePtr node; | 5501 xmlNodePtr node; |
5500 | 5502 |
5501 for (i = 0; i < tmpset->nodeNr; i++) { | 5503 for (i = 0; i < tmpset->nodeNr; i++) { |
5502 node = tmpset->nodeTab[i]; | 5504 node = tmpset->nodeTab[i]; |
5503 if ((node != NULL) && | 5505 if ((node != NULL) && |
5504 (node->type == XML_NAMESPACE_DECL)) | 5506 (node->type == XML_NAMESPACE_DECL)) |
5505 { | 5507 { |
5506 xmlXPathNodeSetFreeNs((xmlNsPtr) node); | 5508 xmlXPathNodeSetFreeNs((xmlNsPtr) node); |
5507 } | 5509 } |
5508 } | 5510 } |
5509 } else if (tmpset->nodeNr == 1) { | 5511 } else if (tmpset->nodeNr == 1) { |
5510 if ((tmpset->nodeTab[0] != NULL) && | 5512 if ((tmpset->nodeTab[0] != NULL) && |
5511 (tmpset->nodeTab[0]->type == XML_NAMESPACE_DECL)) | 5513 (tmpset->nodeTab[0]->type == XML_NAMESPACE_DECL)) |
5512 xmlXPathNodeSetFreeNs((xmlNsPtr) tmpset->nodeTab[0]); | 5514 xmlXPathNodeSetFreeNs((xmlNsPtr) tmpset->nodeTab[0]); |
5513 » }» » | 5515 » } |
5514 tmpset->nodeNr = 0; | 5516 tmpset->nodeNr = 0; |
5515 memset(obj, 0, sizeof(xmlXPathObject)); | 5517 memset(obj, 0, sizeof(xmlXPathObject)); |
5516 obj->nodesetval = tmpset; | 5518 obj->nodesetval = tmpset; |
5517 } else | 5519 } else |
5518 memset(obj, 0, sizeof(xmlXPathObject)); | 5520 memset(obj, 0, sizeof(xmlXPathObject)); |
5519 | 5521 |
5520 return; | 5522 return; |
5521 | 5523 |
5522 free_obj: | 5524 free_obj: |
5523 /* | 5525 /* |
5524 * Cache is full; free the object. | 5526 * Cache is full; free the object. |
5525 » */ | 5527 » */ |
5526 if (obj->nodesetval != NULL) | 5528 if (obj->nodesetval != NULL) |
5527 xmlXPathFreeNodeSet(obj->nodesetval); | 5529 xmlXPathFreeNodeSet(obj->nodesetval); |
5528 #ifdef XP_DEBUG_OBJ_USAGE | 5530 #ifdef XP_DEBUG_OBJ_USAGE |
5529 xmlXPathDebugObjUsageReleased(NULL, obj->type); | 5531 xmlXPathDebugObjUsageReleased(NULL, obj->type); |
5530 #endif | 5532 #endif |
5531 xmlFree(obj); | 5533 xmlFree(obj); |
5532 } | 5534 } |
5533 return; | 5535 return; |
5534 } | 5536 } |
5535 | 5537 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5626 return(xmlXPathCastNodeToString(ns->nodeTab[0])); | 5628 return(xmlXPathCastNodeToString(ns->nodeTab[0])); |
5627 } | 5629 } |
5628 | 5630 |
5629 /** | 5631 /** |
5630 * xmlXPathCastToString: | 5632 * xmlXPathCastToString: |
5631 * @val: an XPath object | 5633 * @val: an XPath object |
5632 * | 5634 * |
5633 * Converts an existing object to its string() equivalent | 5635 * Converts an existing object to its string() equivalent |
5634 * | 5636 * |
5635 * Returns the allocated string value of the object, NULL in case of error. | 5637 * Returns the allocated string value of the object, NULL in case of error. |
5636 * It's up to the caller to free the string memory with xmlFree(). | 5638 * It's up to the caller to free the string memory with xmlFree(). |
5637 */ | 5639 */ |
5638 xmlChar * | 5640 xmlChar * |
5639 xmlXPathCastToString(xmlXPathObjectPtr val) { | 5641 xmlXPathCastToString(xmlXPathObjectPtr val) { |
5640 xmlChar *ret = NULL; | 5642 xmlChar *ret = NULL; |
5641 | 5643 |
5642 if (val == NULL) | 5644 if (val == NULL) |
5643 return(xmlStrdup((const xmlChar *) "")); | 5645 return(xmlStrdup((const xmlChar *) "")); |
5644 switch (val->type) { | 5646 switch (val->type) { |
5645 case XPATH_UNDEFINED: | 5647 case XPATH_UNDEFINED: |
5646 #ifdef DEBUG_EXPR | 5648 #ifdef DEBUG_EXPR |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6017 ret->contextSize = -1; | 6019 ret->contextSize = -1; |
6018 ret->proximityPosition = -1; | 6020 ret->proximityPosition = -1; |
6019 | 6021 |
6020 #ifdef XP_DEFAULT_CACHE_ON | 6022 #ifdef XP_DEFAULT_CACHE_ON |
6021 if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) { | 6023 if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) { |
6022 xmlXPathFreeContext(ret); | 6024 xmlXPathFreeContext(ret); |
6023 return(NULL); | 6025 return(NULL); |
6024 } | 6026 } |
6025 #endif | 6027 #endif |
6026 | 6028 |
6027 xmlXPathRegisterAllFunctions(ret); | 6029 xmlXPathRegisterAllFunctions(ret); |
6028 | 6030 |
6029 return(ret); | 6031 return(ret); |
6030 } | 6032 } |
6031 | 6033 |
6032 /** | 6034 /** |
6033 * xmlXPathFreeContext: | 6035 * xmlXPathFreeContext: |
6034 * @ctxt: the context to free | 6036 * @ctxt: the context to free |
6035 * | 6037 * |
6036 * Free up an xmlXPathContext | 6038 * Free up an xmlXPathContext |
6037 */ | 6039 */ |
(...skipping 10 matching lines...) Expand all Loading... |
6048 xmlFree(ctxt); | 6050 xmlFree(ctxt); |
6049 } | 6051 } |
6050 | 6052 |
6051 /************************************************************************ | 6053 /************************************************************************ |
6052 * * | 6054 * * |
6053 * Routines to handle XPath parser contexts * | 6055 * Routines to handle XPath parser contexts * |
6054 * * | 6056 * * |
6055 ************************************************************************/ | 6057 ************************************************************************/ |
6056 | 6058 |
6057 #define CHECK_CTXT(ctxt) \ | 6059 #define CHECK_CTXT(ctxt) \ |
6058 if (ctxt == NULL) { » » » » » » \ | 6060 if (ctxt == NULL) {»» » » » » \ |
6059 __xmlRaiseError(NULL, NULL, NULL, \ | 6061 __xmlRaiseError(NULL, NULL, NULL, \ |
6060 NULL, NULL, XML_FROM_XPATH, \ | 6062 NULL, NULL, XML_FROM_XPATH, \ |
6061 XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ | 6063 XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ |
6062 __FILE__, __LINE__, \ | 6064 __FILE__, __LINE__, \ |
6063 NULL, NULL, NULL, 0, 0, \ | 6065 NULL, NULL, NULL, 0, 0, \ |
6064 "NULL context pointer\n"); \ | 6066 "NULL context pointer\n"); \ |
6065 return(NULL); \ | 6067 return(NULL); \ |
6066 } \ | 6068 } \ |
6067 | 6069 |
6068 #define CHECK_CTXT_NEG(ctxt) \ | 6070 #define CHECK_CTXT_NEG(ctxt) \ |
6069 if (ctxt == NULL) { » » » » » » \ | 6071 if (ctxt == NULL) {»» » » » » \ |
6070 __xmlRaiseError(NULL, NULL, NULL, \ | 6072 __xmlRaiseError(NULL, NULL, NULL, \ |
6071 NULL, NULL, XML_FROM_XPATH, \ | 6073 NULL, NULL, XML_FROM_XPATH, \ |
6072 XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ | 6074 XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL, \ |
6073 __FILE__, __LINE__, \ | 6075 __FILE__, __LINE__, \ |
6074 NULL, NULL, NULL, 0, 0, \ | 6076 NULL, NULL, NULL, 0, 0, \ |
6075 "NULL context pointer\n"); \ | 6077 "NULL context pointer\n"); \ |
6076 return(-1); \ | 6078 return(-1); \ |
6077 } \ | 6079 } \ |
6078 | 6080 |
6079 | 6081 |
6080 #define CHECK_CONTEXT(ctxt) \ | 6082 #define CHECK_CONTEXT(ctxt) \ |
6081 if ((ctxt == NULL) || (ctxt->doc == NULL) || \ | 6083 if ((ctxt == NULL) || (ctxt->doc == NULL) || \ |
6082 (ctxt->doc->children == NULL)) { » » » » \ | 6084 (ctxt->doc->children == NULL)) {» » » » \ |
6083 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT); \ | 6085 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT); \ |
6084 return(NULL); \ | 6086 return(NULL); \ |
6085 } | 6087 } |
6086 | 6088 |
6087 | 6089 |
6088 /** | 6090 /** |
6089 * xmlXPathNewParserContext: | 6091 * xmlXPathNewParserContext: |
6090 * @str: the XPath expression | 6092 * @str: the XPath expression |
6091 * @ctxt: the XPath context | 6093 * @ctxt: the XPath context |
6092 * | 6094 * |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6135 xmlXPathParserContextPtr ret; | 6137 xmlXPathParserContextPtr ret; |
6136 | 6138 |
6137 ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); | 6139 ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext)); |
6138 if (ret == NULL) { | 6140 if (ret == NULL) { |
6139 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); | 6141 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); |
6140 return(NULL); | 6142 return(NULL); |
6141 } | 6143 } |
6142 memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext)); | 6144 memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext)); |
6143 | 6145 |
6144 /* Allocate the value stack */ | 6146 /* Allocate the value stack */ |
6145 ret->valueTab = (xmlXPathObjectPtr *) | 6147 ret->valueTab = (xmlXPathObjectPtr *) |
6146 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); | 6148 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); |
6147 if (ret->valueTab == NULL) { | 6149 if (ret->valueTab == NULL) { |
6148 xmlFree(ret); | 6150 xmlFree(ret); |
6149 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); | 6151 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); |
6150 return(NULL); | 6152 return(NULL); |
6151 } | 6153 } |
6152 ret->valueNr = 0; | 6154 ret->valueNr = 0; |
6153 ret->valueMax = 10; | 6155 ret->valueMax = 10; |
6154 ret->value = NULL; | 6156 ret->value = NULL; |
6155 | 6157 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6282 continue; | 6284 continue; |
6283 } | 6285 } |
6284 } | 6286 } |
6285 if (tmp == node) | 6287 if (tmp == node) |
6286 break; | 6288 break; |
6287 | 6289 |
6288 if (tmp->next != NULL) { | 6290 if (tmp->next != NULL) { |
6289 tmp = tmp->next; | 6291 tmp = tmp->next; |
6290 continue; | 6292 continue; |
6291 } | 6293 } |
6292 » | 6294 |
6293 do { | 6295 do { |
6294 tmp = tmp->parent; | 6296 tmp = tmp->parent; |
6295 if (tmp == NULL) | 6297 if (tmp == NULL) |
6296 break; | 6298 break; |
6297 if (tmp == node) { | 6299 if (tmp == node) { |
6298 tmp = NULL; | 6300 tmp = NULL; |
6299 break; | 6301 break; |
6300 } | 6302 } |
6301 if (tmp->next != NULL) { | 6303 if (tmp->next != NULL) { |
6302 tmp = tmp->next; | 6304 tmp = tmp->next; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6441 * @inf: less than (1) or greater than (0) | 6443 * @inf: less than (1) or greater than (0) |
6442 * @strict: is the comparison strict | 6444 * @strict: is the comparison strict |
6443 * @arg1: the first node set object | 6445 * @arg1: the first node set object |
6444 * @arg2: the second node set object | 6446 * @arg2: the second node set object |
6445 * | 6447 * |
6446 * Implement the compare operation on nodesets: | 6448 * Implement the compare operation on nodesets: |
6447 * | 6449 * |
6448 * If both objects to be compared are node-sets, then the comparison | 6450 * If both objects to be compared are node-sets, then the comparison |
6449 * will be true if and only if there is a node in the first node-set | 6451 * will be true if and only if there is a node in the first node-set |
6450 * and a node in the second node-set such that the result of performing | 6452 * and a node in the second node-set such that the result of performing |
6451 * the comparison on the string-values of the two nodes is true. | 6453 * the comparison on the string-values of the two nodes is true. |
6452 * .... | 6454 * .... |
6453 * When neither object to be compared is a node-set and the operator | 6455 * When neither object to be compared is a node-set and the operator |
6454 * is <=, <, >= or >, then the objects are compared by converting both | 6456 * is <=, <, >= or >, then the objects are compared by converting both |
6455 * objects to numbers and comparing the numbers according to IEEE 754. | 6457 * objects to numbers and comparing the numbers according to IEEE 754. |
6456 * .... | 6458 * .... |
6457 * The number function converts its argument to a number as follows: | 6459 * The number function converts its argument to a number as follows: |
6458 * - a string that consists of optional whitespace followed by an | 6460 * - a string that consists of optional whitespace followed by an |
6459 * optional minus sign followed by a Number followed by whitespace | 6461 * optional minus sign followed by a Number followed by whitespace |
6460 * is converted to the IEEE 754 number that is nearest (according | 6462 * is converted to the IEEE 754 number that is nearest (according |
6461 * to the IEEE 754 round-to-nearest rule) to the mathematical value | 6463 * to the IEEE 754 round-to-nearest rule) to the mathematical value |
6462 * represented by the string; any other string is converted to NaN | 6464 * represented by the string; any other string is converted to NaN |
6463 * | 6465 * |
6464 * Conclusion all nodes need to be converted first to their string value | 6466 * Conclusion all nodes need to be converted first to their string value |
6465 * and then the comparison must be done when possible | 6467 * and then the comparison must be done when possible |
6466 */ | 6468 */ |
6467 static int | 6469 static int |
6468 xmlXPathCompareNodeSets(int inf, int strict, | 6470 xmlXPathCompareNodeSets(int inf, int strict, |
6469 xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { | 6471 xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { |
6470 int i, j, init = 0; | 6472 int i, j, init = 0; |
6471 double val1; | 6473 double val1; |
6472 double *values2; | 6474 double *values2; |
6473 int ret = 0; | 6475 int ret = 0; |
6474 xmlNodeSetPtr ns1; | 6476 xmlNodeSetPtr ns1; |
6475 xmlNodeSetPtr ns2; | 6477 xmlNodeSetPtr ns2; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6510 for (i = 0;i < ns1->nodeNr;i++) { | 6512 for (i = 0;i < ns1->nodeNr;i++) { |
6511 val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]); | 6513 val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]); |
6512 if (xmlXPathIsNaN(val1)) | 6514 if (xmlXPathIsNaN(val1)) |
6513 continue; | 6515 continue; |
6514 for (j = 0;j < ns2->nodeNr;j++) { | 6516 for (j = 0;j < ns2->nodeNr;j++) { |
6515 if (init == 0) { | 6517 if (init == 0) { |
6516 values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]); | 6518 values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]); |
6517 } | 6519 } |
6518 if (xmlXPathIsNaN(values2[j])) | 6520 if (xmlXPathIsNaN(values2[j])) |
6519 continue; | 6521 continue; |
6520 » if (inf && strict) | 6522 » if (inf && strict) |
6521 ret = (val1 < values2[j]); | 6523 ret = (val1 < values2[j]); |
6522 else if (inf && !strict) | 6524 else if (inf && !strict) |
6523 ret = (val1 <= values2[j]); | 6525 ret = (val1 <= values2[j]); |
6524 else if (!inf && strict) | 6526 else if (!inf && strict) |
6525 ret = (val1 > values2[j]); | 6527 ret = (val1 > values2[j]); |
6526 else if (!inf && !strict) | 6528 else if (!inf && !strict) |
6527 ret = (val1 >= values2[j]); | 6529 ret = (val1 >= values2[j]); |
6528 if (ret) | 6530 if (ret) |
6529 break; | 6531 break; |
6530 } | 6532 } |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6850 #endif | 6852 #endif |
6851 ret = (arg1->boolval == arg2->boolval); | 6853 ret = (arg1->boolval == arg2->boolval); |
6852 break; | 6854 break; |
6853 case XPATH_NUMBER: | 6855 case XPATH_NUMBER: |
6854 ret = (arg1->boolval == | 6856 ret = (arg1->boolval == |
6855 xmlXPathCastNumberToBoolean(arg2->floatval)); | 6857 xmlXPathCastNumberToBoolean(arg2->floatval)); |
6856 break; | 6858 break; |
6857 case XPATH_STRING: | 6859 case XPATH_STRING: |
6858 if ((arg2->stringval == NULL) || | 6860 if ((arg2->stringval == NULL) || |
6859 (arg2->stringval[0] == 0)) ret = 0; | 6861 (arg2->stringval[0] == 0)) ret = 0; |
6860 » » else | 6862 » » else |
6861 ret = 1; | 6863 ret = 1; |
6862 ret = (arg1->boolval == ret); | 6864 ret = (arg1->boolval == ret); |
6863 break; | 6865 break; |
6864 case XPATH_USERS: | 6866 case XPATH_USERS: |
6865 case XPATH_POINT: | 6867 case XPATH_POINT: |
6866 case XPATH_RANGE: | 6868 case XPATH_RANGE: |
6867 case XPATH_LOCATIONSET: | 6869 case XPATH_LOCATIONSET: |
6868 TODO | 6870 TODO |
6869 break; | 6871 break; |
6870 case XPATH_NODESET: | 6872 case XPATH_NODESET: |
(...skipping 14 matching lines...) Expand all Loading... |
6885 xmlXPathCastNumberToBoolean(arg1->floatval)); | 6887 xmlXPathCastNumberToBoolean(arg1->floatval)); |
6886 break; | 6888 break; |
6887 case XPATH_STRING: | 6889 case XPATH_STRING: |
6888 valuePush(ctxt, arg2); | 6890 valuePush(ctxt, arg2); |
6889 xmlXPathNumberFunction(ctxt, 1); | 6891 xmlXPathNumberFunction(ctxt, 1); |
6890 arg2 = valuePop(ctxt); | 6892 arg2 = valuePop(ctxt); |
6891 /* no break on purpose */ | 6893 /* no break on purpose */ |
6892 case XPATH_NUMBER: | 6894 case XPATH_NUMBER: |
6893 /* Hand check NaN and Infinity equalities */ | 6895 /* Hand check NaN and Infinity equalities */ |
6894 if (xmlXPathIsNaN(arg1->floatval) || | 6896 if (xmlXPathIsNaN(arg1->floatval) || |
6895 » » » xmlXPathIsNaN(arg2->floatval)) { | 6897 » » » xmlXPathIsNaN(arg2->floatval)) { |
6896 ret = 0; | 6898 ret = 0; |
6897 } else if (xmlXPathIsInf(arg1->floatval) == 1) { | 6899 } else if (xmlXPathIsInf(arg1->floatval) == 1) { |
6898 if (xmlXPathIsInf(arg2->floatval) == 1) | 6900 if (xmlXPathIsInf(arg2->floatval) == 1) |
6899 ret = 1; | 6901 ret = 1; |
6900 else | 6902 else |
6901 ret = 0; | 6903 ret = 0; |
6902 } else if (xmlXPathIsInf(arg1->floatval) == -1) { | 6904 } else if (xmlXPathIsInf(arg1->floatval) == -1) { |
6903 if (xmlXPathIsInf(arg2->floatval) == -1) | 6905 if (xmlXPathIsInf(arg2->floatval) == -1) |
6904 ret = 1; | 6906 ret = 1; |
6905 else | 6907 else |
(...skipping 27 matching lines...) Expand all Loading... |
6933 switch (arg2->type) { | 6935 switch (arg2->type) { |
6934 case XPATH_UNDEFINED: | 6936 case XPATH_UNDEFINED: |
6935 #ifdef DEBUG_EXPR | 6937 #ifdef DEBUG_EXPR |
6936 xmlGenericError(xmlGenericErrorContext, | 6938 xmlGenericError(xmlGenericErrorContext, |
6937 "Equal: undefined\n"); | 6939 "Equal: undefined\n"); |
6938 #endif | 6940 #endif |
6939 break; | 6941 break; |
6940 case XPATH_BOOLEAN: | 6942 case XPATH_BOOLEAN: |
6941 if ((arg1->stringval == NULL) || | 6943 if ((arg1->stringval == NULL) || |
6942 (arg1->stringval[0] == 0)) ret = 0; | 6944 (arg1->stringval[0] == 0)) ret = 0; |
6943 » » else | 6945 » » else |
6944 ret = 1; | 6946 ret = 1; |
6945 ret = (arg2->boolval == ret); | 6947 ret = (arg2->boolval == ret); |
6946 break; | 6948 break; |
6947 case XPATH_STRING: | 6949 case XPATH_STRING: |
6948 ret = xmlStrEqual(arg1->stringval, arg2->stringval); | 6950 ret = xmlStrEqual(arg1->stringval, arg2->stringval); |
6949 break; | 6951 break; |
6950 case XPATH_NUMBER: | 6952 case XPATH_NUMBER: |
6951 valuePush(ctxt, arg1); | 6953 valuePush(ctxt, arg1); |
6952 xmlXPathNumberFunction(ctxt, 1); | 6954 xmlXPathNumberFunction(ctxt, 1); |
6953 arg1 = valuePop(ctxt); | 6955 arg1 = valuePop(ctxt); |
6954 /* Hand check NaN and Infinity equalities */ | 6956 /* Hand check NaN and Infinity equalities */ |
6955 if (xmlXPathIsNaN(arg1->floatval) || | 6957 if (xmlXPathIsNaN(arg1->floatval) || |
6956 » » » xmlXPathIsNaN(arg2->floatval)) { | 6958 » » » xmlXPathIsNaN(arg2->floatval)) { |
6957 ret = 0; | 6959 ret = 0; |
6958 } else if (xmlXPathIsInf(arg1->floatval) == 1) { | 6960 } else if (xmlXPathIsInf(arg1->floatval) == 1) { |
6959 if (xmlXPathIsInf(arg2->floatval) == 1) | 6961 if (xmlXPathIsInf(arg2->floatval) == 1) |
6960 ret = 1; | 6962 ret = 1; |
6961 else | 6963 else |
6962 ret = 0; | 6964 ret = 0; |
6963 } else if (xmlXPathIsInf(arg1->floatval) == -1) { | 6965 } else if (xmlXPathIsInf(arg1->floatval) == -1) { |
6964 if (xmlXPathIsInf(arg2->floatval) == -1) | 6966 if (xmlXPathIsInf(arg2->floatval) == -1) |
6965 ret = 1; | 6967 ret = 1; |
6966 else | 6968 else |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7012 * Implement the equal operation on XPath objects content: @arg1 == @arg2 | 7014 * Implement the equal operation on XPath objects content: @arg1 == @arg2 |
7013 * | 7015 * |
7014 * Returns 0 or 1 depending on the results of the test. | 7016 * Returns 0 or 1 depending on the results of the test. |
7015 */ | 7017 */ |
7016 int | 7018 int |
7017 xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { | 7019 xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { |
7018 xmlXPathObjectPtr arg1, arg2, argtmp; | 7020 xmlXPathObjectPtr arg1, arg2, argtmp; |
7019 int ret = 0; | 7021 int ret = 0; |
7020 | 7022 |
7021 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); | 7023 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); |
7022 arg2 = valuePop(ctxt); | 7024 arg2 = valuePop(ctxt); |
7023 arg1 = valuePop(ctxt); | 7025 arg1 = valuePop(ctxt); |
7024 if ((arg1 == NULL) || (arg2 == NULL)) { | 7026 if ((arg1 == NULL) || (arg2 == NULL)) { |
7025 if (arg1 != NULL) | 7027 if (arg1 != NULL) |
7026 xmlXPathReleaseObject(ctxt->context, arg1); | 7028 xmlXPathReleaseObject(ctxt->context, arg1); |
7027 else | 7029 else |
7028 xmlXPathReleaseObject(ctxt->context, arg2); | 7030 xmlXPathReleaseObject(ctxt->context, arg2); |
7029 XP_ERROR0(XPATH_INVALID_OPERAND); | 7031 XP_ERROR0(XPATH_INVALID_OPERAND); |
7030 } | 7032 } |
7031 | 7033 |
7032 if (arg1 == arg2) { | 7034 if (arg1 == arg2) { |
(...skipping 25 matching lines...) Expand all Loading... |
7058 "Equal: undefined\n"); | 7060 "Equal: undefined\n"); |
7059 #endif | 7061 #endif |
7060 break; | 7062 break; |
7061 case XPATH_NODESET: | 7063 case XPATH_NODESET: |
7062 case XPATH_XSLT_TREE: | 7064 case XPATH_XSLT_TREE: |
7063 ret = xmlXPathEqualNodeSets(arg1, arg2, 0); | 7065 ret = xmlXPathEqualNodeSets(arg1, arg2, 0); |
7064 break; | 7066 break; |
7065 case XPATH_BOOLEAN: | 7067 case XPATH_BOOLEAN: |
7066 if ((arg1->nodesetval == NULL) || | 7068 if ((arg1->nodesetval == NULL) || |
7067 (arg1->nodesetval->nodeNr == 0)) ret = 0; | 7069 (arg1->nodesetval->nodeNr == 0)) ret = 0; |
7068 » » else | 7070 » » else |
7069 ret = 1; | 7071 ret = 1; |
7070 ret = (ret == arg2->boolval); | 7072 ret = (ret == arg2->boolval); |
7071 break; | 7073 break; |
7072 case XPATH_NUMBER: | 7074 case XPATH_NUMBER: |
7073 ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0); | 7075 ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0); |
7074 break; | 7076 break; |
7075 case XPATH_STRING: | 7077 case XPATH_STRING: |
7076 ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0); | 7078 ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0); |
7077 break; | 7079 break; |
7078 case XPATH_USERS: | 7080 case XPATH_USERS: |
(...skipping 18 matching lines...) Expand all Loading... |
7097 * Implement the equal operation on XPath objects content: @arg1 == @arg2 | 7099 * Implement the equal operation on XPath objects content: @arg1 == @arg2 |
7098 * | 7100 * |
7099 * Returns 0 or 1 depending on the results of the test. | 7101 * Returns 0 or 1 depending on the results of the test. |
7100 */ | 7102 */ |
7101 int | 7103 int |
7102 xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { | 7104 xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { |
7103 xmlXPathObjectPtr arg1, arg2, argtmp; | 7105 xmlXPathObjectPtr arg1, arg2, argtmp; |
7104 int ret = 0; | 7106 int ret = 0; |
7105 | 7107 |
7106 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); | 7108 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); |
7107 arg2 = valuePop(ctxt); | 7109 arg2 = valuePop(ctxt); |
7108 arg1 = valuePop(ctxt); | 7110 arg1 = valuePop(ctxt); |
7109 if ((arg1 == NULL) || (arg2 == NULL)) { | 7111 if ((arg1 == NULL) || (arg2 == NULL)) { |
7110 if (arg1 != NULL) | 7112 if (arg1 != NULL) |
7111 xmlXPathReleaseObject(ctxt->context, arg1); | 7113 xmlXPathReleaseObject(ctxt->context, arg1); |
7112 else | 7114 else |
7113 xmlXPathReleaseObject(ctxt->context, arg2); | 7115 xmlXPathReleaseObject(ctxt->context, arg2); |
7114 XP_ERROR0(XPATH_INVALID_OPERAND); | 7116 XP_ERROR0(XPATH_INVALID_OPERAND); |
7115 } | 7117 } |
7116 | 7118 |
7117 if (arg1 == arg2) { | 7119 if (arg1 == arg2) { |
(...skipping 25 matching lines...) Expand all Loading... |
7143 "NotEqual: undefined\n"); | 7145 "NotEqual: undefined\n"); |
7144 #endif | 7146 #endif |
7145 break; | 7147 break; |
7146 case XPATH_NODESET: | 7148 case XPATH_NODESET: |
7147 case XPATH_XSLT_TREE: | 7149 case XPATH_XSLT_TREE: |
7148 ret = xmlXPathEqualNodeSets(arg1, arg2, 1); | 7150 ret = xmlXPathEqualNodeSets(arg1, arg2, 1); |
7149 break; | 7151 break; |
7150 case XPATH_BOOLEAN: | 7152 case XPATH_BOOLEAN: |
7151 if ((arg1->nodesetval == NULL) || | 7153 if ((arg1->nodesetval == NULL) || |
7152 (arg1->nodesetval->nodeNr == 0)) ret = 0; | 7154 (arg1->nodesetval->nodeNr == 0)) ret = 0; |
7153 » » else | 7155 » » else |
7154 ret = 1; | 7156 ret = 1; |
7155 ret = (ret != arg2->boolval); | 7157 ret = (ret != arg2->boolval); |
7156 break; | 7158 break; |
7157 case XPATH_NUMBER: | 7159 case XPATH_NUMBER: |
7158 ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1); | 7160 ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1); |
7159 break; | 7161 break; |
7160 case XPATH_STRING: | 7162 case XPATH_STRING: |
7161 ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1); | 7163 ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1); |
7162 break; | 7164 break; |
7163 case XPATH_USERS: | 7165 case XPATH_USERS: |
(...skipping 10 matching lines...) Expand all Loading... |
7174 | 7176 |
7175 return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2)); | 7177 return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2)); |
7176 } | 7178 } |
7177 | 7179 |
7178 /** | 7180 /** |
7179 * xmlXPathCompareValues: | 7181 * xmlXPathCompareValues: |
7180 * @ctxt: the XPath Parser context | 7182 * @ctxt: the XPath Parser context |
7181 * @inf: less than (1) or greater than (0) | 7183 * @inf: less than (1) or greater than (0) |
7182 * @strict: is the comparison strict | 7184 * @strict: is the comparison strict |
7183 * | 7185 * |
7184 * Implement the compare operation on XPath objects: | 7186 * Implement the compare operation on XPath objects: |
7185 * @arg1 < @arg2 (1, 1, ... | 7187 * @arg1 < @arg2 (1, 1, ... |
7186 * @arg1 <= @arg2 (1, 0, ... | 7188 * @arg1 <= @arg2 (1, 0, ... |
7187 * @arg1 > @arg2 (0, 1, ... | 7189 * @arg1 > @arg2 (0, 1, ... |
7188 * @arg1 >= @arg2 (0, 0, ... | 7190 * @arg1 >= @arg2 (0, 0, ... |
7189 * | 7191 * |
7190 * When neither object to be compared is a node-set and the operator is | 7192 * When neither object to be compared is a node-set and the operator is |
7191 * <=, <, >=, >, then the objects are compared by converted both objects | 7193 * <=, <, >=, >, then the objects are compared by converted both objects |
7192 * to numbers and comparing the numbers according to IEEE 754. The < | 7194 * to numbers and comparing the numbers according to IEEE 754. The < |
7193 * comparison will be true if and only if the first number is less than the | 7195 * comparison will be true if and only if the first number is less than the |
7194 * second number. The <= comparison will be true if and only if the first | 7196 * second number. The <= comparison will be true if and only if the first |
7195 * number is less than or equal to the second number. The > comparison | 7197 * number is less than or equal to the second number. The > comparison |
7196 * will be true if and only if the first number is greater than the second | 7198 * will be true if and only if the first number is greater than the second |
7197 * number. The >= comparison will be true if and only if the first number | 7199 * number. The >= comparison will be true if and only if the first number |
7198 * is greater than or equal to the second number. | 7200 * is greater than or equal to the second number. |
7199 * | 7201 * |
7200 * Returns 1 if the comparison succeeded, 0 if it failed | 7202 * Returns 1 if the comparison succeeded, 0 if it failed |
7201 */ | 7203 */ |
7202 int | 7204 int |
7203 xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { | 7205 xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { |
7204 int ret = 0, arg1i = 0, arg2i = 0; | 7206 int ret = 0, arg1i = 0, arg2i = 0; |
7205 xmlXPathObjectPtr arg1, arg2; | 7207 xmlXPathObjectPtr arg1, arg2; |
7206 | 7208 |
7207 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); | 7209 if ((ctxt == NULL) || (ctxt->context == NULL)) return(0); |
7208 arg2 = valuePop(ctxt); | 7210 arg2 = valuePop(ctxt); |
7209 arg1 = valuePop(ctxt); | 7211 arg1 = valuePop(ctxt); |
7210 if ((arg1 == NULL) || (arg2 == NULL)) { | 7212 if ((arg1 == NULL) || (arg2 == NULL)) { |
7211 if (arg1 != NULL) | 7213 if (arg1 != NULL) |
7212 xmlXPathReleaseObject(ctxt->context, arg1); | 7214 xmlXPathReleaseObject(ctxt->context, arg1); |
7213 else | 7215 else |
7214 xmlXPathReleaseObject(ctxt->context, arg2); | 7216 xmlXPathReleaseObject(ctxt->context, arg2); |
7215 XP_ERROR0(XPATH_INVALID_OPERAND); | 7217 XP_ERROR0(XPATH_INVALID_OPERAND); |
7216 } | 7218 } |
7217 | 7219 |
7218 if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) || | 7220 if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) || |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7439 else if (ctxt->value->floatval < 0) | 7441 else if (ctxt->value->floatval < 0) |
7440 ctxt->value->floatval = xmlXPathPINF; | 7442 ctxt->value->floatval = xmlXPathPINF; |
7441 } | 7443 } |
7442 else if (val == 0) { | 7444 else if (val == 0) { |
7443 if (ctxt->value->floatval == 0) | 7445 if (ctxt->value->floatval == 0) |
7444 ctxt->value->floatval = xmlXPathNAN; | 7446 ctxt->value->floatval = xmlXPathNAN; |
7445 else if (ctxt->value->floatval > 0) | 7447 else if (ctxt->value->floatval > 0) |
7446 ctxt->value->floatval = xmlXPathPINF; | 7448 ctxt->value->floatval = xmlXPathPINF; |
7447 else if (ctxt->value->floatval < 0) | 7449 else if (ctxt->value->floatval < 0) |
7448 ctxt->value->floatval = xmlXPathNINF; | 7450 ctxt->value->floatval = xmlXPathNINF; |
7449 } else | 7451 } else |
7450 ctxt->value->floatval /= val; | 7452 ctxt->value->floatval /= val; |
7451 } | 7453 } |
7452 | 7454 |
7453 /** | 7455 /** |
7454 * xmlXPathModValues: | 7456 * xmlXPathModValues: |
7455 * @ctxt: the XPath Parser context | 7457 * @ctxt: the XPath Parser context |
7456 * | 7458 * |
7457 * Implement the mod operation on XPath objects: @arg1 / @arg2 | 7459 * Implement the mod operation on XPath objects: @arg1 / @arg2 |
7458 * The numeric operators convert their operands to numbers as if | 7460 * The numeric operators convert their operands to numbers as if |
7459 * by calling the number function. | 7461 * by calling the number function. |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7674 if (contextNode == NULL) | 7676 if (contextNode == NULL) |
7675 return(NULL); | 7677 return(NULL); |
7676 switch (contextNode->type) { | 7678 switch (contextNode->type) { |
7677 case XML_ELEMENT_NODE: | 7679 case XML_ELEMENT_NODE: |
7678 case XML_XINCLUDE_START: | 7680 case XML_XINCLUDE_START: |
7679 case XML_DOCUMENT_FRAG_NODE: | 7681 case XML_DOCUMENT_FRAG_NODE: |
7680 case XML_DOCUMENT_NODE: | 7682 case XML_DOCUMENT_NODE: |
7681 #ifdef LIBXML_DOCB_ENABLED | 7683 #ifdef LIBXML_DOCB_ENABLED |
7682 case XML_DOCB_DOCUMENT_NODE: | 7684 case XML_DOCB_DOCUMENT_NODE: |
7683 #endif | 7685 #endif |
7684 » case XML_HTML_DOCUMENT_NODE:» » | 7686 » case XML_HTML_DOCUMENT_NODE:» |
7685 return(contextNode); | 7687 return(contextNode); |
7686 default: | 7688 default: |
7687 » » return(NULL);» | 7689 » » return(NULL); |
7688 } | 7690 } |
7689 return(NULL); | 7691 return(NULL); |
7690 } else { | 7692 } else { |
7691 xmlNodePtr start = cur; | 7693 xmlNodePtr start = cur; |
7692 | 7694 |
7693 while (cur != NULL) { | 7695 while (cur != NULL) { |
7694 switch (cur->type) { | 7696 switch (cur->type) { |
7695 case XML_ELEMENT_NODE: | 7697 case XML_ELEMENT_NODE: |
7696 /* TODO: OK to have XInclude here? */ | 7698 /* TODO: OK to have XInclude here? */ |
7697 case XML_XINCLUDE_START: | 7699 case XML_XINCLUDE_START: |
7698 » » case XML_DOCUMENT_FRAG_NODE:» » | 7700 » » case XML_DOCUMENT_FRAG_NODE: |
7699 if (cur != start) | 7701 if (cur != start) |
7700 return(cur); | 7702 return(cur); |
7701 if (cur->children != NULL) { | 7703 if (cur->children != NULL) { |
7702 cur = cur->children; | 7704 cur = cur->children; |
7703 continue; | 7705 continue; |
7704 } | 7706 } |
7705 break; | 7707 break; |
7706 /* Not sure if we need those here. */ | 7708 /* Not sure if we need those here. */ |
7707 case XML_DOCUMENT_NODE: | 7709 case XML_DOCUMENT_NODE: |
7708 #ifdef LIBXML_DOCB_ENABLED | 7710 #ifdef LIBXML_DOCB_ENABLED |
7709 case XML_DOCB_DOCUMENT_NODE: | 7711 case XML_DOCB_DOCUMENT_NODE: |
7710 #endif | 7712 #endif |
7711 case XML_HTML_DOCUMENT_NODE: | 7713 case XML_HTML_DOCUMENT_NODE: |
7712 if (cur != start) | 7714 if (cur != start) |
7713 return(cur); | 7715 return(cur); |
7714 return(xmlDocGetRootElement((xmlDocPtr) cur)); | 7716 return(xmlDocGetRootElement((xmlDocPtr) cur)); |
7715 default: | 7717 default: |
7716 break; | 7718 break; |
7717 » }» | 7719 » } |
7718 » | 7720 |
7719 next_sibling: | 7721 next_sibling: |
7720 if ((cur == NULL) || (cur == contextNode)) | 7722 if ((cur == NULL) || (cur == contextNode)) |
7721 » » return(NULL);» | 7723 » » return(NULL); |
7722 if (cur->next != NULL) { | 7724 if (cur->next != NULL) { |
7723 » » cur = cur->next;» » | 7725 » » cur = cur->next; |
7724 } else { | 7726 } else { |
7725 cur = cur->parent; | 7727 cur = cur->parent; |
7726 goto next_sibling; | 7728 goto next_sibling; |
7727 } | 7729 } |
7728 } | 7730 } |
7729 } | 7731 } |
7730 return(NULL); | 7732 return(NULL); |
7731 } | 7733 } |
7732 | 7734 |
7733 /** | 7735 /** |
7734 * xmlXPathNextDescendant: | 7736 * xmlXPathNextDescendant: |
7735 * @ctxt: the XPath Parser context | 7737 * @ctxt: the XPath Parser context |
7736 * @cur: the current node in the traversal | 7738 * @cur: the current node in the traversal |
7737 * | 7739 * |
7738 * Traversal function for the "descendant" direction | 7740 * Traversal function for the "descendant" direction |
7739 * the descendant axis contains the descendants of the context node in document | 7741 * the descendant axis contains the descendants of the context node in document |
7740 * order; a descendant is a child or a child of a child and so on. | 7742 * order; a descendant is a child or a child of a child and so on. |
7741 * | 7743 * |
(...skipping 11 matching lines...) Expand all Loading... |
7753 | 7755 |
7754 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) | 7756 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) |
7755 return(ctxt->context->doc->children); | 7757 return(ctxt->context->doc->children); |
7756 return(ctxt->context->node->children); | 7758 return(ctxt->context->node->children); |
7757 } | 7759 } |
7758 | 7760 |
7759 if (cur->children != NULL) { | 7761 if (cur->children != NULL) { |
7760 /* | 7762 /* |
7761 * Do not descend on entities declarations | 7763 * Do not descend on entities declarations |
7762 */ | 7764 */ |
7763 » if (cur->children->type != XML_ENTITY_DECL) { | 7765 » if (cur->children->type != XML_ENTITY_DECL) { |
7764 cur = cur->children; | 7766 cur = cur->children; |
7765 /* | 7767 /* |
7766 * Skip DTDs | 7768 * Skip DTDs |
7767 */ | 7769 */ |
7768 if (cur->type != XML_DTD_NODE) | 7770 if (cur->type != XML_DTD_NODE) |
7769 return(cur); | 7771 return(cur); |
7770 } | 7772 } |
7771 } | 7773 } |
7772 | 7774 |
7773 if (cur == ctxt->context->node) return(NULL); | 7775 if (cur == ctxt->context->node) return(NULL); |
7774 | 7776 |
7775 while (cur->next != NULL) { | 7777 while (cur->next != NULL) { |
7776 cur = cur->next; | 7778 cur = cur->next; |
7777 if ((cur->type != XML_ENTITY_DECL) && | 7779 if ((cur->type != XML_ENTITY_DECL) && |
7778 (cur->type != XML_DTD_NODE)) | 7780 (cur->type != XML_DTD_NODE)) |
7779 return(cur); | 7781 return(cur); |
7780 } | 7782 } |
7781 | 7783 |
7782 do { | 7784 do { |
7783 cur = cur->parent; | 7785 cur = cur->parent; |
7784 if (cur == NULL) break; | 7786 if (cur == NULL) break; |
7785 if (cur == ctxt->context->node) return(NULL); | 7787 if (cur == ctxt->context->node) return(NULL); |
7786 if (cur->next != NULL) { | 7788 if (cur->next != NULL) { |
7787 cur = cur->next; | 7789 cur = cur->next; |
7788 return(cur); | 7790 return(cur); |
7789 } | 7791 } |
7790 } while (cur != NULL); | 7792 } while (cur != NULL); |
7791 return(cur); | 7793 return(cur); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7870 case XML_DOCUMENT_NODE: | 7872 case XML_DOCUMENT_NODE: |
7871 case XML_DOCUMENT_TYPE_NODE: | 7873 case XML_DOCUMENT_TYPE_NODE: |
7872 case XML_DOCUMENT_FRAG_NODE: | 7874 case XML_DOCUMENT_FRAG_NODE: |
7873 case XML_HTML_DOCUMENT_NODE: | 7875 case XML_HTML_DOCUMENT_NODE: |
7874 #ifdef LIBXML_DOCB_ENABLED | 7876 #ifdef LIBXML_DOCB_ENABLED |
7875 case XML_DOCB_DOCUMENT_NODE: | 7877 case XML_DOCB_DOCUMENT_NODE: |
7876 #endif | 7878 #endif |
7877 return(NULL); | 7879 return(NULL); |
7878 case XML_NAMESPACE_DECL: { | 7880 case XML_NAMESPACE_DECL: { |
7879 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; | 7881 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; |
7880 » » | 7882 |
7881 if ((ns->next != NULL) && | 7883 if ((ns->next != NULL) && |
7882 (ns->next->type != XML_NAMESPACE_DECL)) | 7884 (ns->next->type != XML_NAMESPACE_DECL)) |
7883 return((xmlNodePtr) ns->next); | 7885 return((xmlNodePtr) ns->next); |
7884 return(NULL); | 7886 return(NULL); |
7885 } | 7887 } |
7886 } | 7888 } |
7887 } | 7889 } |
7888 return(NULL); | 7890 return(NULL); |
7889 } | 7891 } |
7890 | 7892 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7943 case XML_DOCUMENT_NODE: | 7945 case XML_DOCUMENT_NODE: |
7944 case XML_DOCUMENT_TYPE_NODE: | 7946 case XML_DOCUMENT_TYPE_NODE: |
7945 case XML_DOCUMENT_FRAG_NODE: | 7947 case XML_DOCUMENT_FRAG_NODE: |
7946 case XML_HTML_DOCUMENT_NODE: | 7948 case XML_HTML_DOCUMENT_NODE: |
7947 #ifdef LIBXML_DOCB_ENABLED | 7949 #ifdef LIBXML_DOCB_ENABLED |
7948 case XML_DOCB_DOCUMENT_NODE: | 7950 case XML_DOCB_DOCUMENT_NODE: |
7949 #endif | 7951 #endif |
7950 return(NULL); | 7952 return(NULL); |
7951 case XML_NAMESPACE_DECL: { | 7953 case XML_NAMESPACE_DECL: { |
7952 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; | 7954 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; |
7953 » » | 7955 |
7954 if ((ns->next != NULL) && | 7956 if ((ns->next != NULL) && |
7955 (ns->next->type != XML_NAMESPACE_DECL)) | 7957 (ns->next->type != XML_NAMESPACE_DECL)) |
7956 return((xmlNodePtr) ns->next); | 7958 return((xmlNodePtr) ns->next); |
7957 /* Bad, how did that namespace end up here ? */ | 7959 /* Bad, how did that namespace end up here ? */ |
7958 return(NULL); | 7960 return(NULL); |
7959 } | 7961 } |
7960 } | 7962 } |
7961 return(NULL); | 7963 return(NULL); |
7962 } | 7964 } |
7963 if (cur == ctxt->context->doc->children) | 7965 if (cur == ctxt->context->doc->children) |
(...skipping 23 matching lines...) Expand all Loading... |
7987 BAD_CAST "fake node libxslt")))) | 7989 BAD_CAST "fake node libxslt")))) |
7988 return(NULL); | 7990 return(NULL); |
7989 return(cur->parent); | 7991 return(cur->parent); |
7990 case XML_ATTRIBUTE_NODE: { | 7992 case XML_ATTRIBUTE_NODE: { |
7991 xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node; | 7993 xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node; |
7992 | 7994 |
7993 return(att->parent); | 7995 return(att->parent); |
7994 } | 7996 } |
7995 case XML_NAMESPACE_DECL: { | 7997 case XML_NAMESPACE_DECL: { |
7996 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; | 7998 xmlNsPtr ns = (xmlNsPtr) ctxt->context->node; |
7997 » » | 7999 |
7998 if ((ns->next != NULL) && | 8000 if ((ns->next != NULL) && |
7999 (ns->next->type != XML_NAMESPACE_DECL)) | 8001 (ns->next->type != XML_NAMESPACE_DECL)) |
8000 return((xmlNodePtr) ns->next); | 8002 return((xmlNodePtr) ns->next); |
8001 /* Bad, how did that namespace end up here ? */ | 8003 /* Bad, how did that namespace end up here ? */ |
8002 return(NULL); | 8004 return(NULL); |
8003 } | 8005 } |
8004 case XML_DOCUMENT_NODE: | 8006 case XML_DOCUMENT_NODE: |
8005 case XML_DOCUMENT_TYPE_NODE: | 8007 case XML_DOCUMENT_TYPE_NODE: |
8006 case XML_DOCUMENT_FRAG_NODE: | 8008 case XML_DOCUMENT_FRAG_NODE: |
8007 case XML_HTML_DOCUMENT_NODE: | 8009 case XML_HTML_DOCUMENT_NODE: |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8184 /** | 8186 /** |
8185 * xmlXPathNextPrecedingInternal: | 8187 * xmlXPathNextPrecedingInternal: |
8186 * @ctxt: the XPath Parser context | 8188 * @ctxt: the XPath Parser context |
8187 * @cur: the current node in the traversal | 8189 * @cur: the current node in the traversal |
8188 * | 8190 * |
8189 * Traversal function for the "preceding" direction | 8191 * Traversal function for the "preceding" direction |
8190 * the preceding axis contains all nodes in the same document as the context | 8192 * the preceding axis contains all nodes in the same document as the context |
8191 * node that are before the context node in document order, excluding any | 8193 * node that are before the context node in document order, excluding any |
8192 * ancestors and excluding attribute nodes and namespace nodes; the nodes are | 8194 * ancestors and excluding attribute nodes and namespace nodes; the nodes are |
8193 * ordered in reverse document order | 8195 * ordered in reverse document order |
8194 * This is a faster implementation but internal only since it requires a | 8196 * This is a faster implementation but internal only since it requires a |
8195 * state kept in the parser context: ctxt->ancestor. | 8197 * state kept in the parser context: ctxt->ancestor. |
8196 * | 8198 * |
8197 * Returns the next element following that axis | 8199 * Returns the next element following that axis |
8198 */ | 8200 */ |
8199 static xmlNodePtr | 8201 static xmlNodePtr |
8200 xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt, | 8202 xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt, |
8201 xmlNodePtr cur) | 8203 xmlNodePtr cur) |
8202 { | 8204 { |
8203 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); | 8205 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); |
8204 if (cur == NULL) { | 8206 if (cur == NULL) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8241 * | 8243 * |
8242 * Returns the next element following that axis | 8244 * Returns the next element following that axis |
8243 */ | 8245 */ |
8244 xmlNodePtr | 8246 xmlNodePtr |
8245 xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { | 8247 xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { |
8246 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); | 8248 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); |
8247 if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL); | 8249 if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL); |
8248 if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNames
pace) { | 8250 if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNames
pace) { |
8249 if (ctxt->context->tmpNsList != NULL) | 8251 if (ctxt->context->tmpNsList != NULL) |
8250 xmlFree(ctxt->context->tmpNsList); | 8252 xmlFree(ctxt->context->tmpNsList); |
8251 » ctxt->context->tmpNsList = | 8253 » ctxt->context->tmpNsList = |
8252 xmlGetNsList(ctxt->context->doc, ctxt->context->node); | 8254 xmlGetNsList(ctxt->context->doc, ctxt->context->node); |
8253 ctxt->context->tmpNsNr = 0; | 8255 ctxt->context->tmpNsNr = 0; |
8254 if (ctxt->context->tmpNsList != NULL) { | 8256 if (ctxt->context->tmpNsList != NULL) { |
8255 while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) { | 8257 while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) { |
8256 ctxt->context->tmpNsNr++; | 8258 ctxt->context->tmpNsNr++; |
8257 } | 8259 } |
8258 } | 8260 } |
8259 return((xmlNodePtr) xmlXPathXMLNamespace); | 8261 return((xmlNodePtr) xmlXPathXMLNamespace); |
8260 } | 8262 } |
8261 if (ctxt->context->tmpNsNr > 0) { | 8263 if (ctxt->context->tmpNsNr > 0) { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8389 * @nargs: the number of arguments | 8391 * @nargs: the number of arguments |
8390 * | 8392 * |
8391 * Implement the count() XPath function | 8393 * Implement the count() XPath function |
8392 * number count(node-set) | 8394 * number count(node-set) |
8393 */ | 8395 */ |
8394 void | 8396 void |
8395 xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 8397 xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
8396 xmlXPathObjectPtr cur; | 8398 xmlXPathObjectPtr cur; |
8397 | 8399 |
8398 CHECK_ARITY(1); | 8400 CHECK_ARITY(1); |
8399 if ((ctxt->value == NULL) || | 8401 if ((ctxt->value == NULL) || |
8400 ((ctxt->value->type != XPATH_NODESET) && | 8402 ((ctxt->value->type != XPATH_NODESET) && |
8401 (ctxt->value->type != XPATH_XSLT_TREE))) | 8403 (ctxt->value->type != XPATH_XSLT_TREE))) |
8402 XP_ERROR(XPATH_INVALID_TYPE); | 8404 XP_ERROR(XPATH_INVALID_TYPE); |
8403 cur = valuePop(ctxt); | 8405 cur = valuePop(ctxt); |
8404 | 8406 |
8405 if ((cur == NULL) || (cur->nodesetval == NULL)) | 8407 if ((cur == NULL) || (cur->nodesetval == NULL)) |
8406 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); | 8408 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); |
8407 else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) { | 8409 else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) { |
8408 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, | 8410 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, |
8409 (double) cur->nodesetval->nodeNr)); | 8411 (double) cur->nodesetval->nodeNr)); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8534 if (tokens != NULL) | 8536 if (tokens != NULL) |
8535 xmlFree(tokens); | 8537 xmlFree(tokens); |
8536 } | 8538 } |
8537 } | 8539 } |
8538 xmlXPathReleaseObject(ctxt->context, obj); | 8540 xmlXPathReleaseObject(ctxt->context, obj); |
8539 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); | 8541 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); |
8540 return; | 8542 return; |
8541 } | 8543 } |
8542 obj = xmlXPathCacheConvertString(ctxt->context, obj); | 8544 obj = xmlXPathCacheConvertString(ctxt->context, obj); |
8543 ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval); | 8545 ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval); |
8544 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); | 8546 valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, ret)); |
8545 xmlXPathReleaseObject(ctxt->context, obj); | 8547 xmlXPathReleaseObject(ctxt->context, obj); |
8546 return; | 8548 return; |
8547 } | 8549 } |
8548 | 8550 |
8549 /** | 8551 /** |
8550 * xmlXPathLocalNameFunction: | 8552 * xmlXPathLocalNameFunction: |
8551 * @ctxt: the XPath Parser context | 8553 * @ctxt: the XPath Parser context |
8552 * @nargs: the number of arguments | 8554 * @nargs: the number of arguments |
8553 * | 8555 * |
8554 * Implement the local-name() XPath function | 8556 * Implement the local-name() XPath function |
(...skipping 10 matching lines...) Expand all Loading... |
8565 | 8567 |
8566 if (ctxt == NULL) return; | 8568 if (ctxt == NULL) return; |
8567 | 8569 |
8568 if (nargs == 0) { | 8570 if (nargs == 0) { |
8569 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, | 8571 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, |
8570 ctxt->context->node)); | 8572 ctxt->context->node)); |
8571 nargs = 1; | 8573 nargs = 1; |
8572 } | 8574 } |
8573 | 8575 |
8574 CHECK_ARITY(1); | 8576 CHECK_ARITY(1); |
8575 if ((ctxt->value == NULL) || | 8577 if ((ctxt->value == NULL) || |
8576 ((ctxt->value->type != XPATH_NODESET) && | 8578 ((ctxt->value->type != XPATH_NODESET) && |
8577 (ctxt->value->type != XPATH_XSLT_TREE))) | 8579 (ctxt->value->type != XPATH_XSLT_TREE))) |
8578 XP_ERROR(XPATH_INVALID_TYPE); | 8580 XP_ERROR(XPATH_INVALID_TYPE); |
8579 cur = valuePop(ctxt); | 8581 cur = valuePop(ctxt); |
8580 | 8582 |
8581 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { | 8583 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { |
8582 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); | 8584 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); |
8583 } else { | 8585 } else { |
8584 int i = 0; /* Should be first in document order !!!!! */ | 8586 int i = 0; /* Should be first in document order !!!!! */ |
8585 switch (cur->nodesetval->nodeTab[i]->type) { | 8587 switch (cur->nodesetval->nodeTab[i]->type) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8623 xmlXPathObjectPtr cur; | 8625 xmlXPathObjectPtr cur; |
8624 | 8626 |
8625 if (ctxt == NULL) return; | 8627 if (ctxt == NULL) return; |
8626 | 8628 |
8627 if (nargs == 0) { | 8629 if (nargs == 0) { |
8628 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, | 8630 valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context, |
8629 ctxt->context->node)); | 8631 ctxt->context->node)); |
8630 nargs = 1; | 8632 nargs = 1; |
8631 } | 8633 } |
8632 CHECK_ARITY(1); | 8634 CHECK_ARITY(1); |
8633 if ((ctxt->value == NULL) || | 8635 if ((ctxt->value == NULL) || |
8634 ((ctxt->value->type != XPATH_NODESET) && | 8636 ((ctxt->value->type != XPATH_NODESET) && |
8635 (ctxt->value->type != XPATH_XSLT_TREE))) | 8637 (ctxt->value->type != XPATH_XSLT_TREE))) |
8636 XP_ERROR(XPATH_INVALID_TYPE); | 8638 XP_ERROR(XPATH_INVALID_TYPE); |
8637 cur = valuePop(ctxt); | 8639 cur = valuePop(ctxt); |
8638 | 8640 |
8639 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { | 8641 if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { |
8640 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); | 8642 valuePush(ctxt, xmlXPathCacheNewCString(ctxt->context, "")); |
8641 } else { | 8643 } else { |
8642 int i = 0; /* Should be first in document order !!!!! */ | 8644 int i = 0; /* Should be first in document order !!!!! */ |
8643 switch (cur->nodesetval->nodeTab[i]->type) { | 8645 switch (cur->nodesetval->nodeTab[i]->type) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8707 if (cur->nodesetval->nodeTab[i]->name[0] == ' ') | 8709 if (cur->nodesetval->nodeTab[i]->name[0] == ' ') |
8708 valuePush(ctxt, | 8710 valuePush(ctxt, |
8709 xmlXPathCacheNewCString(ctxt->context, "")); | 8711 xmlXPathCacheNewCString(ctxt->context, "")); |
8710 else if ((cur->nodesetval->nodeTab[i]->ns == NULL) || | 8712 else if ((cur->nodesetval->nodeTab[i]->ns == NULL) || |
8711 (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) { | 8713 (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) { |
8712 valuePush(ctxt, | 8714 valuePush(ctxt, |
8713 xmlXPathCacheNewString(ctxt->context, | 8715 xmlXPathCacheNewString(ctxt->context, |
8714 cur->nodesetval->nodeTab[i]->name)); | 8716 cur->nodesetval->nodeTab[i]->name)); |
8715 } else { | 8717 } else { |
8716 xmlChar *fullname; | 8718 xmlChar *fullname; |
8717 » » | 8719 |
8718 fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name, | 8720 fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name, |
8719 cur->nodesetval->nodeTab[i]->ns->prefix, | 8721 cur->nodesetval->nodeTab[i]->ns->prefix, |
8720 NULL, 0); | 8722 NULL, 0); |
8721 if (fullname == cur->nodesetval->nodeTab[i]->name) | 8723 if (fullname == cur->nodesetval->nodeTab[i]->name) |
8722 fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name); | 8724 fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name); |
8723 if (fullname == NULL) { | 8725 if (fullname == NULL) { |
8724 XP_ERROR(XPATH_MEMORY_ERROR); | 8726 XP_ERROR(XPATH_MEMORY_ERROR); |
8725 } | 8727 } |
8726 valuePush(ctxt, xmlXPathCacheWrapString( | 8728 valuePush(ctxt, xmlXPathCacheWrapString( |
8727 ctxt->context, fullname)); | 8729 ctxt->context, fullname)); |
(...skipping 14 matching lines...) Expand all Loading... |
8742 * @ctxt: the XPath Parser context | 8744 * @ctxt: the XPath Parser context |
8743 * @nargs: the number of arguments | 8745 * @nargs: the number of arguments |
8744 * | 8746 * |
8745 * Implement the string() XPath function | 8747 * Implement the string() XPath function |
8746 * string string(object?) | 8748 * string string(object?) |
8747 * The string function converts an object to a string as follows: | 8749 * The string function converts an object to a string as follows: |
8748 * - A node-set is converted to a string by returning the value of | 8750 * - A node-set is converted to a string by returning the value of |
8749 * the node in the node-set that is first in document order. | 8751 * the node in the node-set that is first in document order. |
8750 * If the node-set is empty, an empty string is returned. | 8752 * If the node-set is empty, an empty string is returned. |
8751 * - A number is converted to a string as follows | 8753 * - A number is converted to a string as follows |
8752 * + NaN is converted to the string NaN | 8754 * + NaN is converted to the string NaN |
8753 * + positive zero is converted to the string 0 | 8755 * + positive zero is converted to the string 0 |
8754 * + negative zero is converted to the string 0 | 8756 * + negative zero is converted to the string 0 |
8755 * + positive infinity is converted to the string Infinity | 8757 * + positive infinity is converted to the string Infinity |
8756 * + negative infinity is converted to the string -Infinity | 8758 * + negative infinity is converted to the string -Infinity |
8757 * + if the number is an integer, the number is represented in | 8759 * + if the number is an integer, the number is represented in |
8758 * decimal form as a Number with no decimal point and no leading | 8760 * decimal form as a Number with no decimal point and no leading |
8759 * zeros, preceded by a minus sign (-) if the number is negative | 8761 * zeros, preceded by a minus sign (-) if the number is negative |
8760 * + otherwise, the number is represented in decimal form as a | 8762 * + otherwise, the number is represented in decimal form as a |
8761 * Number including a decimal point with at least one digit | 8763 * Number including a decimal point with at least one digit |
8762 * before the decimal point and at least one digit after the | 8764 * before the decimal point and at least one digit after the |
8763 * decimal point, preceded by a minus sign (-) if the number | 8765 * decimal point, preceded by a minus sign (-) if the number |
8764 * is negative; there must be no leading zeros before the decimal | 8766 * is negative; there must be no leading zeros before the decimal |
8765 * point apart possibly from the one required digit immediately | 8767 * point apart possibly from the one required digit immediately |
8766 * before the decimal point; beyond the one required digit | 8768 * before the decimal point; beyond the one required digit |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8820 xmlUTF8Strlen(content))); | 8822 xmlUTF8Strlen(content))); |
8821 xmlFree(content); | 8823 xmlFree(content); |
8822 } | 8824 } |
8823 return; | 8825 return; |
8824 } | 8826 } |
8825 CHECK_ARITY(1); | 8827 CHECK_ARITY(1); |
8826 CAST_TO_STRING; | 8828 CAST_TO_STRING; |
8827 CHECK_TYPE(XPATH_STRING); | 8829 CHECK_TYPE(XPATH_STRING); |
8828 cur = valuePop(ctxt); | 8830 cur = valuePop(ctxt); |
8829 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, | 8831 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, |
8830 » xmlUTF8Strlen(cur->stringval))); | 8832 » xmlUTF8Strlen(cur->stringval))); |
8831 xmlXPathReleaseObject(ctxt->context, cur); | 8833 xmlXPathReleaseObject(ctxt->context, cur); |
8832 } | 8834 } |
8833 | 8835 |
8834 /** | 8836 /** |
8835 * xmlXPathConcatFunction: | 8837 * xmlXPathConcatFunction: |
8836 * @ctxt: the XPath Parser context | 8838 * @ctxt: the XPath Parser context |
8837 * @nargs: the number of arguments | 8839 * @nargs: the number of arguments |
8838 * | 8840 * |
8839 * Implement the concat() XPath function | 8841 * Implement the concat() XPath function |
8840 * string concat(string, string, string*) | 8842 * string concat(string, string, string*) |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8959 * specified, it returns the substring starting at the position specified | 8961 * specified, it returns the substring starting at the position specified |
8960 * in the second argument and continuing to the end of the string. For | 8962 * in the second argument and continuing to the end of the string. For |
8961 * example, substring("12345",2) returns "2345". More precisely, each | 8963 * example, substring("12345",2) returns "2345". More precisely, each |
8962 * character in the string (see [3.6 Strings]) is considered to have a | 8964 * character in the string (see [3.6 Strings]) is considered to have a |
8963 * numeric position: the position of the first character is 1, the position | 8965 * numeric position: the position of the first character is 1, the position |
8964 * of the second character is 2 and so on. The returned substring contains | 8966 * of the second character is 2 and so on. The returned substring contains |
8965 * those characters for which the position of the character is greater than | 8967 * those characters for which the position of the character is greater than |
8966 * or equal to the second argument and, if the third argument is specified, | 8968 * or equal to the second argument and, if the third argument is specified, |
8967 * less than the sum of the second and third arguments; the comparisons | 8969 * less than the sum of the second and third arguments; the comparisons |
8968 * and addition used for the above follow the standard IEEE 754 rules. Thus: | 8970 * and addition used for the above follow the standard IEEE 754 rules. Thus: |
8969 * - substring("12345", 1.5, 2.6) returns "234" | 8971 * - substring("12345", 1.5, 2.6) returns "234" |
8970 * - substring("12345", 0, 3) returns "12" | 8972 * - substring("12345", 0, 3) returns "12" |
8971 * - substring("12345", 0 div 0, 3) returns "" | 8973 * - substring("12345", 0 div 0, 3) returns "" |
8972 * - substring("12345", 1, 0 div 0) returns "" | 8974 * - substring("12345", 1, 0 div 0) returns "" |
8973 * - substring("12345", -42, 1 div 0) returns "12345" | 8975 * - substring("12345", -42, 1 div 0) returns "12345" |
8974 * - substring("12345", -1 div 0, 1 div 0) returns "" | 8976 * - substring("12345", -1 div 0, 1 div 0) returns "" |
8975 */ | 8977 */ |
8976 void | 8978 void |
8977 xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 8979 xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
8978 xmlXPathObjectPtr str, start, len; | 8980 xmlXPathObjectPtr str, start, len; |
8979 double le=0, in; | 8981 double le=0, in; |
8980 int i, l, m; | 8982 int i, l, m; |
8981 xmlChar *ret; | 8983 xmlChar *ret; |
8982 | 8984 |
8983 if (nargs < 2) { | 8985 if (nargs < 2) { |
8984 CHECK_ARITY(2); | 8986 CHECK_ARITY(2); |
(...skipping 20 matching lines...) Expand all Loading... |
9005 CAST_TO_STRING; | 9007 CAST_TO_STRING; |
9006 CHECK_TYPE(XPATH_STRING); | 9008 CHECK_TYPE(XPATH_STRING); |
9007 str = valuePop(ctxt); | 9009 str = valuePop(ctxt); |
9008 m = xmlUTF8Strlen((const unsigned char *)str->stringval); | 9010 m = xmlUTF8Strlen((const unsigned char *)str->stringval); |
9009 | 9011 |
9010 /* | 9012 /* |
9011 * If last pos not present, calculate last position | 9013 * If last pos not present, calculate last position |
9012 */ | 9014 */ |
9013 if (nargs != 3) { | 9015 if (nargs != 3) { |
9014 le = (double)m; | 9016 le = (double)m; |
9015 » if (in < 1.0) | 9017 » if (in < 1.0) |
9016 in = 1.0; | 9018 in = 1.0; |
9017 } | 9019 } |
9018 | 9020 |
9019 /* Need to check for the special cases where either | 9021 /* Need to check for the special cases where either |
9020 * the index is NaN, the length is NaN, or both | 9022 * the index is NaN, the length is NaN, or both |
9021 * arguments are infinity (relying on Inf + -Inf = NaN) | 9023 * arguments are infinity (relying on Inf + -Inf = NaN) |
9022 */ | 9024 */ |
9023 if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) { | 9025 if (!xmlXPathIsInf(in) && !xmlXPathIsNaN(in + le)) { |
9024 /* | 9026 /* |
9025 * To meet the requirements of the spec, the arguments | 9027 * To meet the requirements of the spec, the arguments |
9026 » * must be converted to integer format before | 9028 » * must be converted to integer format before |
9027 * initial index calculations are done | 9029 * initial index calculations are done |
9028 * | 9030 * |
9029 * First we go to integer form, rounding up | 9031 * First we go to integer form, rounding up |
9030 * and checking for special cases | 9032 * and checking for special cases |
9031 */ | 9033 */ |
9032 i = (int) in; | 9034 i = (int) in; |
9033 if (((double)i)+0.5 <= in) i++; | 9035 if (((double)i)+0.5 <= in) i++; |
9034 | 9036 |
9035 if (xmlXPathIsInf(le) == 1) { | 9037 if (xmlXPathIsInf(le) == 1) { |
9036 l = m; | 9038 l = m; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9082 * if the first argument string does not contain the second argument | 9084 * if the first argument string does not contain the second argument |
9083 * string. For example, substring-before("1999/04/01","/") returns 1999. | 9085 * string. For example, substring-before("1999/04/01","/") returns 1999. |
9084 */ | 9086 */ |
9085 void | 9087 void |
9086 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9088 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
9087 xmlXPathObjectPtr str; | 9089 xmlXPathObjectPtr str; |
9088 xmlXPathObjectPtr find; | 9090 xmlXPathObjectPtr find; |
9089 xmlBufferPtr target; | 9091 xmlBufferPtr target; |
9090 const xmlChar *point; | 9092 const xmlChar *point; |
9091 int offset; | 9093 int offset; |
9092 | 9094 |
9093 CHECK_ARITY(2); | 9095 CHECK_ARITY(2); |
9094 CAST_TO_STRING; | 9096 CAST_TO_STRING; |
9095 find = valuePop(ctxt); | 9097 find = valuePop(ctxt); |
9096 CAST_TO_STRING; | 9098 CAST_TO_STRING; |
9097 str = valuePop(ctxt); | 9099 str = valuePop(ctxt); |
9098 | 9100 |
9099 target = xmlBufferCreate(); | 9101 target = xmlBufferCreate(); |
9100 if (target) { | 9102 if (target) { |
9101 point = xmlStrstr(str->stringval, find->stringval); | 9103 point = xmlStrstr(str->stringval, find->stringval); |
9102 if (point) { | 9104 if (point) { |
9103 offset = (int)(point - str->stringval); | 9105 offset = (int)(point - str->stringval); |
9104 xmlBufferAdd(target, str->stringval, offset); | 9106 xmlBufferAdd(target, str->stringval, offset); |
9105 } | 9107 } |
9106 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 9108 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
9107 xmlBufferContent(target))); | 9109 xmlBufferContent(target))); |
9108 xmlBufferFree(target); | 9110 xmlBufferFree(target); |
(...skipping 16 matching lines...) Expand all Loading... |
9125 * string. For example, substring-after("1999/04/01","/") returns 04/01, | 9127 * string. For example, substring-after("1999/04/01","/") returns 04/01, |
9126 * and substring-after("1999/04/01","19") returns 99/04/01. | 9128 * and substring-after("1999/04/01","19") returns 99/04/01. |
9127 */ | 9129 */ |
9128 void | 9130 void |
9129 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9131 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
9130 xmlXPathObjectPtr str; | 9132 xmlXPathObjectPtr str; |
9131 xmlXPathObjectPtr find; | 9133 xmlXPathObjectPtr find; |
9132 xmlBufferPtr target; | 9134 xmlBufferPtr target; |
9133 const xmlChar *point; | 9135 const xmlChar *point; |
9134 int offset; | 9136 int offset; |
9135 | 9137 |
9136 CHECK_ARITY(2); | 9138 CHECK_ARITY(2); |
9137 CAST_TO_STRING; | 9139 CAST_TO_STRING; |
9138 find = valuePop(ctxt); | 9140 find = valuePop(ctxt); |
9139 CAST_TO_STRING; | 9141 CAST_TO_STRING; |
9140 str = valuePop(ctxt); | 9142 str = valuePop(ctxt); |
9141 | 9143 |
9142 target = xmlBufferCreate(); | 9144 target = xmlBufferCreate(); |
9143 if (target) { | 9145 if (target) { |
9144 point = xmlStrstr(str->stringval, find->stringval); | 9146 point = xmlStrstr(str->stringval, find->stringval); |
9145 if (point) { | 9147 if (point) { |
9146 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval); | 9148 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval); |
9147 xmlBufferAdd(target, &str->stringval[offset], | 9149 xmlBufferAdd(target, &str->stringval[offset], |
9148 xmlStrlen(str->stringval) - offset); | 9150 xmlStrlen(str->stringval) - offset); |
9149 } | 9151 } |
9150 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 9152 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
9151 » xmlBufferContent(target))); | 9153 » xmlBufferContent(target))); |
9152 xmlBufferFree(target); | 9154 xmlBufferFree(target); |
9153 } | 9155 } |
9154 xmlXPathReleaseObject(ctxt->context, str); | 9156 xmlXPathReleaseObject(ctxt->context, str); |
9155 xmlXPathReleaseObject(ctxt->context, find); | 9157 xmlXPathReleaseObject(ctxt->context, find); |
9156 } | 9158 } |
9157 | 9159 |
9158 /** | 9160 /** |
9159 * xmlXPathNormalizeFunction: | 9161 * xmlXPathNormalizeFunction: |
9160 * @ctxt: the XPath Parser context | 9162 * @ctxt: the XPath Parser context |
9161 * @nargs: the number of arguments | 9163 * @nargs: the number of arguments |
9162 * | 9164 * |
9163 * Implement the normalize-space() XPath function | 9165 * Implement the normalize-space() XPath function |
9164 * string normalize-space(string?) | 9166 * string normalize-space(string?) |
9165 * The normalize-space function returns the argument string with white | 9167 * The normalize-space function returns the argument string with white |
9166 * space normalized by stripping leading and trailing whitespace | 9168 * space normalized by stripping leading and trailing whitespace |
9167 * and replacing sequences of whitespace characters by a single | 9169 * and replacing sequences of whitespace characters by a single |
9168 * space. Whitespace characters are the same allowed by the S production | 9170 * space. Whitespace characters are the same allowed by the S production |
9169 * in XML. If the argument is omitted, it defaults to the context | 9171 * in XML. If the argument is omitted, it defaults to the context |
9170 * node converted to a string, in other words the value of the context node. | 9172 * node converted to a string, in other words the value of the context node. |
9171 */ | 9173 */ |
9172 void | 9174 void |
9173 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9175 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
9174 xmlXPathObjectPtr obj = NULL; | 9176 xmlXPathObjectPtr obj = NULL; |
9175 xmlChar *source = NULL; | 9177 xmlChar *source = NULL; |
9176 xmlBufferPtr target; | 9178 xmlBufferPtr target; |
9177 xmlChar blank; | 9179 xmlChar blank; |
9178 | 9180 |
9179 if (ctxt == NULL) return; | 9181 if (ctxt == NULL) return; |
9180 if (nargs == 0) { | 9182 if (nargs == 0) { |
9181 /* Use current context node */ | 9183 /* Use current context node */ |
9182 valuePush(ctxt, | 9184 valuePush(ctxt, |
9183 xmlXPathCacheWrapString(ctxt->context, | 9185 xmlXPathCacheWrapString(ctxt->context, |
9184 xmlXPathCastNodeToString(ctxt->context->node))); | 9186 xmlXPathCastNodeToString(ctxt->context->node))); |
9185 nargs = 1; | 9187 nargs = 1; |
9186 } | 9188 } |
9187 | 9189 |
9188 CHECK_ARITY(1); | 9190 CHECK_ARITY(1); |
9189 CAST_TO_STRING; | 9191 CAST_TO_STRING; |
9190 CHECK_TYPE(XPATH_STRING); | 9192 CHECK_TYPE(XPATH_STRING); |
9191 obj = valuePop(ctxt); | 9193 obj = valuePop(ctxt); |
9192 source = obj->stringval; | 9194 source = obj->stringval; |
9193 | 9195 |
9194 target = xmlBufferCreate(); | 9196 target = xmlBufferCreate(); |
9195 if (target && source) { | 9197 if (target && source) { |
9196 | 9198 |
9197 /* Skip leading whitespaces */ | 9199 /* Skip leading whitespaces */ |
9198 while (IS_BLANK_CH(*source)) | 9200 while (IS_BLANK_CH(*source)) |
9199 source++; | 9201 source++; |
9200 | 9202 |
9201 /* Collapse intermediate whitespaces, and skip trailing whitespaces */ | 9203 /* Collapse intermediate whitespaces, and skip trailing whitespaces */ |
9202 blank = 0; | 9204 blank = 0; |
9203 while (*source) { | 9205 while (*source) { |
9204 if (IS_BLANK_CH(*source)) { | 9206 if (IS_BLANK_CH(*source)) { |
9205 blank = 0x20; | 9207 blank = 0x20; |
9206 } else { | 9208 } else { |
9207 if (blank) { | 9209 if (blank) { |
9208 xmlBufferAdd(target, &blank, 1); | 9210 xmlBufferAdd(target, &blank, 1); |
9209 blank = 0; | 9211 blank = 0; |
9210 } | 9212 } |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9465 * The sum function returns the sum of the values of the nodes in | 9467 * The sum function returns the sum of the values of the nodes in |
9466 * the argument node-set. | 9468 * the argument node-set. |
9467 */ | 9469 */ |
9468 void | 9470 void |
9469 xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 9471 xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
9470 xmlXPathObjectPtr cur; | 9472 xmlXPathObjectPtr cur; |
9471 int i; | 9473 int i; |
9472 double res = 0.0; | 9474 double res = 0.0; |
9473 | 9475 |
9474 CHECK_ARITY(1); | 9476 CHECK_ARITY(1); |
9475 if ((ctxt->value == NULL) || | 9477 if ((ctxt->value == NULL) || |
9476 ((ctxt->value->type != XPATH_NODESET) && | 9478 ((ctxt->value->type != XPATH_NODESET) && |
9477 (ctxt->value->type != XPATH_XSLT_TREE))) | 9479 (ctxt->value->type != XPATH_XSLT_TREE))) |
9478 XP_ERROR(XPATH_INVALID_TYPE); | 9480 XP_ERROR(XPATH_INVALID_TYPE); |
9479 cur = valuePop(ctxt); | 9481 cur = valuePop(ctxt); |
9480 | 9482 |
9481 if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) { | 9483 if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) { |
9482 for (i = 0; i < cur->nodesetval->nodeNr; i++) { | 9484 for (i = 0; i < cur->nodesetval->nodeNr; i++) { |
9483 res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]); | 9485 res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]); |
9484 } | 9486 } |
9485 } | 9487 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9584 if ((xmlXPathIsNaN(ctxt->value->floatval)) || | 9586 if ((xmlXPathIsNaN(ctxt->value->floatval)) || |
9585 (xmlXPathIsInf(ctxt->value->floatval) == 1) || | 9587 (xmlXPathIsInf(ctxt->value->floatval) == 1) || |
9586 (xmlXPathIsInf(ctxt->value->floatval) == -1) || | 9588 (xmlXPathIsInf(ctxt->value->floatval) == -1) || |
9587 (ctxt->value->floatval == 0.0)) | 9589 (ctxt->value->floatval == 0.0)) |
9588 return; | 9590 return; |
9589 | 9591 |
9590 XTRUNC(f, ctxt->value->floatval); | 9592 XTRUNC(f, ctxt->value->floatval); |
9591 if (ctxt->value->floatval < 0) { | 9593 if (ctxt->value->floatval < 0) { |
9592 if (ctxt->value->floatval < f - 0.5) | 9594 if (ctxt->value->floatval < f - 0.5) |
9593 ctxt->value->floatval = f - 1; | 9595 ctxt->value->floatval = f - 1; |
9594 » else | 9596 » else |
9595 ctxt->value->floatval = f; | 9597 ctxt->value->floatval = f; |
9596 if (ctxt->value->floatval == 0) | 9598 if (ctxt->value->floatval == 0) |
9597 ctxt->value->floatval = xmlXPathNZERO; | 9599 ctxt->value->floatval = xmlXPathNZERO; |
9598 } else { | 9600 } else { |
9599 if (ctxt->value->floatval < f + 0.5) | 9601 if (ctxt->value->floatval < f + 0.5) |
9600 ctxt->value->floatval = f; | 9602 ctxt->value->floatval = f; |
9601 » else | 9603 » else |
9602 ctxt->value->floatval = f + 1; | 9604 ctxt->value->floatval = f + 1; |
9603 } | 9605 } |
9604 } | 9606 } |
9605 | 9607 |
9606 /************************************************************************ | 9608 /************************************************************************ |
9607 * * | 9609 * * |
9608 * The Parser * | 9610 * The Parser * |
9609 * * | 9611 * * |
9610 ************************************************************************/ | 9612 ************************************************************************/ |
9611 | 9613 |
(...skipping 30 matching lines...) Expand all Loading... |
9642 return(0); | 9644 return(0); |
9643 cur = ctxt->cur; | 9645 cur = ctxt->cur; |
9644 | 9646 |
9645 /* | 9647 /* |
9646 * We are supposed to handle UTF8, check it's valid | 9648 * We are supposed to handle UTF8, check it's valid |
9647 * From rfc2044: encoding of the Unicode values on UTF-8: | 9649 * From rfc2044: encoding of the Unicode values on UTF-8: |
9648 * | 9650 * |
9649 * UCS-4 range (hex.) UTF-8 octet sequence (binary) | 9651 * UCS-4 range (hex.) UTF-8 octet sequence (binary) |
9650 * 0000 0000-0000 007F 0xxxxxxx | 9652 * 0000 0000-0000 007F 0xxxxxxx |
9651 * 0000 0080-0000 07FF 110xxxxx 10xxxxxx | 9653 * 0000 0080-0000 07FF 110xxxxx 10xxxxxx |
9652 * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx | 9654 * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx |
9653 * | 9655 * |
9654 * Check for the 0x110000 limit too | 9656 * Check for the 0x110000 limit too |
9655 */ | 9657 */ |
9656 c = *cur; | 9658 c = *cur; |
9657 if (c & 0x80) { | 9659 if (c & 0x80) { |
9658 if ((cur[1] & 0xc0) != 0x80) | 9660 if ((cur[1] & 0xc0) != 0x80) |
9659 goto encoding_error; | 9661 goto encoding_error; |
9660 if ((c & 0xe0) == 0xe0) { | 9662 if ((c & 0xe0) == 0xe0) { |
9661 | 9663 |
9662 if ((cur[2] & 0xc0) != 0x80) | 9664 if ((cur[2] & 0xc0) != 0x80) |
(...skipping 16 matching lines...) Expand all Loading... |
9679 val |= cur[2] & 0x3f; | 9681 val |= cur[2] & 0x3f; |
9680 } | 9682 } |
9681 } else { | 9683 } else { |
9682 /* 2-byte code */ | 9684 /* 2-byte code */ |
9683 *len = 2; | 9685 *len = 2; |
9684 val = (cur[0] & 0x1f) << 6; | 9686 val = (cur[0] & 0x1f) << 6; |
9685 val |= cur[1] & 0x3f; | 9687 val |= cur[1] & 0x3f; |
9686 } | 9688 } |
9687 if (!IS_CHAR(val)) { | 9689 if (!IS_CHAR(val)) { |
9688 XP_ERROR0(XPATH_INVALID_CHAR_ERROR); | 9690 XP_ERROR0(XPATH_INVALID_CHAR_ERROR); |
9689 » } | 9691 » } |
9690 return(val); | 9692 return(val); |
9691 } else { | 9693 } else { |
9692 /* 1-byte code */ | 9694 /* 1-byte code */ |
9693 *len = 1; | 9695 *len = 1; |
9694 return((int) *cur); | 9696 return((int) *cur); |
9695 } | 9697 } |
9696 encoding_error: | 9698 encoding_error: |
9697 /* | 9699 /* |
9698 * If we detect an UTF8 error that probably means that the | 9700 * If we detect an UTF8 error that probably means that the |
9699 * input encoding didn't get properly advertised in the | 9701 * input encoding didn't get properly advertised in the |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9751 return(ret); | 9753 return(ret); |
9752 } | 9754 } |
9753 } | 9755 } |
9754 return(xmlXPathParseNameComplex(ctxt, 0)); | 9756 return(xmlXPathParseNameComplex(ctxt, 0)); |
9755 } | 9757 } |
9756 | 9758 |
9757 | 9759 |
9758 /** | 9760 /** |
9759 * xmlXPathParseQName: | 9761 * xmlXPathParseQName: |
9760 * @ctxt: the XPath Parser context | 9762 * @ctxt: the XPath Parser context |
9761 * @prefix: a xmlChar ** | 9763 * @prefix: a xmlChar ** |
9762 * | 9764 * |
9763 * parse an XML qualified name | 9765 * parse an XML qualified name |
9764 * | 9766 * |
9765 * [NS 5] QName ::= (Prefix ':')? LocalPart | 9767 * [NS 5] QName ::= (Prefix ':')? LocalPart |
9766 * | 9768 * |
9767 * [NS 6] Prefix ::= NCName | 9769 * [NS 6] Prefix ::= NCName |
9768 * | 9770 * |
9769 * [NS 7] LocalPart ::= NCName | 9771 * [NS 7] LocalPart ::= NCName |
9770 * | 9772 * |
9771 * Returns the function returns the local part, and prefix is updated | 9773 * Returns the function returns the local part, and prefix is updated |
9772 * to get the Prefix if any. | 9774 * to get the Prefix if any. |
9773 */ | 9775 */ |
9774 | 9776 |
9775 static xmlChar * | 9777 static xmlChar * |
9776 xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) { | 9778 xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) { |
9777 xmlChar *ret = NULL; | 9779 xmlChar *ret = NULL; |
9778 | 9780 |
9779 *prefix = NULL; | 9781 *prefix = NULL; |
9780 ret = xmlXPathParseNCName(ctxt); | 9782 ret = xmlXPathParseNCName(ctxt); |
9781 if (CUR == ':') { | 9783 if (ret && CUR == ':') { |
9782 *prefix = ret; | 9784 *prefix = ret; |
9783 NEXT; | 9785 NEXT; |
9784 ret = xmlXPathParseNCName(ctxt); | 9786 ret = xmlXPathParseNCName(ctxt); |
9785 } | 9787 } |
9786 return(ret); | 9788 return(ret); |
9787 } | 9789 } |
9788 | 9790 |
9789 /** | 9791 /** |
9790 * xmlXPathParseName: | 9792 * xmlXPathParseName: |
9791 * @ctxt: the XPath Parser context | 9793 * @ctxt: the XPath Parser context |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9845 (c == '[') || (c == ']') || (c == '@') || /* accelerators */ | 9847 (c == '[') || (c == ']') || (c == '@') || /* accelerators */ |
9846 (c == '*') || /* accelerators */ | 9848 (c == '*') || /* accelerators */ |
9847 (!IS_LETTER(c) && (c != '_') && | 9849 (!IS_LETTER(c) && (c != '_') && |
9848 ((qualified) && (c != ':')))) { | 9850 ((qualified) && (c != ':')))) { |
9849 return(NULL); | 9851 return(NULL); |
9850 } | 9852 } |
9851 | 9853 |
9852 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ | 9854 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ |
9853 ((IS_LETTER(c)) || (IS_DIGIT(c)) || | 9855 ((IS_LETTER(c)) || (IS_DIGIT(c)) || |
9854 (c == '.') || (c == '-') || | 9856 (c == '.') || (c == '-') || |
9855 » (c == '_') || ((qualified) && (c == ':')) || | 9857 » (c == '_') || ((qualified) && (c == ':')) || |
9856 (IS_COMBINING(c)) || | 9858 (IS_COMBINING(c)) || |
9857 (IS_EXTENDER(c)))) { | 9859 (IS_EXTENDER(c)))) { |
9858 COPY_BUF(l,buf,len,c); | 9860 COPY_BUF(l,buf,len,c); |
9859 NEXTL(l); | 9861 NEXTL(l); |
9860 c = CUR_CHAR(l); | 9862 c = CUR_CHAR(l); |
9861 if (len >= XML_MAX_NAMELEN) { | 9863 if (len >= XML_MAX_NAMELEN) { |
9862 /* | 9864 /* |
9863 * Okay someone managed to make a huge name, so he's ready to pay | 9865 * Okay someone managed to make a huge name, so he's ready to pay |
9864 * for the processing speed. | 9866 * for the processing speed. |
9865 */ | 9867 */ |
9866 xmlChar *buffer; | 9868 xmlChar *buffer; |
9867 int max = len * 2; | 9869 int max = len * 2; |
9868 » | 9870 |
9869 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); | 9871 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); |
9870 if (buffer == NULL) { | 9872 if (buffer == NULL) { |
9871 XP_ERRORNULL(XPATH_MEMORY_ERROR); | 9873 XP_ERRORNULL(XPATH_MEMORY_ERROR); |
9872 } | 9874 } |
9873 memcpy(buffer, buf, len); | 9875 memcpy(buffer, buf, len); |
9874 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ | 9876 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ |
9875 (c == '.') || (c == '-') || | 9877 (c == '.') || (c == '-') || |
9876 » » (c == '_') || ((qualified) && (c == ':')) || | 9878 » » (c == '_') || ((qualified) && (c == ':')) || |
9877 (IS_COMBINING(c)) || | 9879 (IS_COMBINING(c)) || |
9878 (IS_EXTENDER(c))) { | 9880 (IS_EXTENDER(c))) { |
9879 if (len + 10 > max) { | 9881 if (len + 10 > max) { |
9880 max *= 2; | 9882 max *= 2; |
9881 buffer = (xmlChar *) xmlRealloc(buffer, | 9883 buffer = (xmlChar *) xmlRealloc(buffer, |
9882 max * sizeof(xmlChar)); | 9884 max * sizeof(xmlChar)); |
9883 if (buffer == NULL) { | 9885 if (buffer == NULL) { |
9884 XP_ERRORNULL(XPATH_MEMORY_ERROR); | 9886 XP_ERRORNULL(XPATH_MEMORY_ERROR); |
9885 } | 9887 } |
9886 } | 9888 } |
(...skipping 26 matching lines...) Expand all Loading... |
9913 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0 | 9915 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0 |
9914 }; | 9916 }; |
9915 | 9917 |
9916 /** | 9918 /** |
9917 * xmlXPathStringEvalNumber: | 9919 * xmlXPathStringEvalNumber: |
9918 * @str: A string to scan | 9920 * @str: A string to scan |
9919 * | 9921 * |
9920 * [30a] Float ::= Number ('e' Digits?)? | 9922 * [30a] Float ::= Number ('e' Digits?)? |
9921 * | 9923 * |
9922 * [30] Number ::= Digits ('.' Digits?)? | 9924 * [30] Number ::= Digits ('.' Digits?)? |
9923 * | '.' Digits | 9925 * | '.' Digits |
9924 * [31] Digits ::= [0-9]+ | 9926 * [31] Digits ::= [0-9]+ |
9925 * | 9927 * |
9926 * Compile a Number in the string | 9928 * Compile a Number in the string |
9927 * In complement of the Number expression, this function also handles | 9929 * In complement of the Number expression, this function also handles |
9928 * negative values : '-' Number. | 9930 * negative values : '-' Number. |
9929 * | 9931 * |
9930 * Returns the double value. | 9932 * Returns the double value. |
9931 */ | 9933 */ |
9932 double | 9934 double |
9933 xmlXPathStringEvalNumber(const xmlChar *str) { | 9935 xmlXPathStringEvalNumber(const xmlChar *str) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10012 if (is_exponent_negative) exponent = -exponent; | 10014 if (is_exponent_negative) exponent = -exponent; |
10013 ret *= pow(10.0, (double)exponent); | 10015 ret *= pow(10.0, (double)exponent); |
10014 return(ret); | 10016 return(ret); |
10015 } | 10017 } |
10016 | 10018 |
10017 /** | 10019 /** |
10018 * xmlXPathCompNumber: | 10020 * xmlXPathCompNumber: |
10019 * @ctxt: the XPath Parser context | 10021 * @ctxt: the XPath Parser context |
10020 * | 10022 * |
10021 * [30] Number ::= Digits ('.' Digits?)? | 10023 * [30] Number ::= Digits ('.' Digits?)? |
10022 * | '.' Digits | 10024 * | '.' Digits |
10023 * [31] Digits ::= [0-9]+ | 10025 * [31] Digits ::= [0-9]+ |
10024 * | 10026 * |
10025 * Compile a Number, then push it on the stack | 10027 * Compile a Number, then push it on the stack |
10026 * | 10028 * |
10027 */ | 10029 */ |
10028 static void | 10030 static void |
10029 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) | 10031 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) |
10030 { | 10032 { |
10031 double ret = 0.0; | 10033 double ret = 0.0; |
10032 double mult = 1; | 10034 double mult = 1; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10192 * | 10194 * |
10193 * Parse a VariableReference, evaluate it and push it on the stack. | 10195 * Parse a VariableReference, evaluate it and push it on the stack. |
10194 * | 10196 * |
10195 * The variable bindings consist of a mapping from variable names | 10197 * The variable bindings consist of a mapping from variable names |
10196 * to variable values. The value of a variable is an object, which can be | 10198 * to variable values. The value of a variable is an object, which can be |
10197 * of any of the types that are possible for the value of an expression, | 10199 * of any of the types that are possible for the value of an expression, |
10198 * and may also be of additional types not specified here. | 10200 * and may also be of additional types not specified here. |
10199 * | 10201 * |
10200 * Early evaluation is possible since: | 10202 * Early evaluation is possible since: |
10201 * The variable bindings [...] used to evaluate a subexpression are | 10203 * The variable bindings [...] used to evaluate a subexpression are |
10202 * always the same as those used to evaluate the containing expression. | 10204 * always the same as those used to evaluate the containing expression. |
10203 * | 10205 * |
10204 * [36] VariableReference ::= '$' QName | 10206 * [36] VariableReference ::= '$' QName |
10205 */ | 10207 */ |
10206 static void | 10208 static void |
10207 xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) { | 10209 xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) { |
10208 xmlChar *name; | 10210 xmlChar *name; |
10209 xmlChar *prefix; | 10211 xmlChar *prefix; |
10210 | 10212 |
10211 SKIP_BLANKS; | 10213 SKIP_BLANKS; |
10212 if (CUR != '$') { | 10214 if (CUR != '$') { |
10213 XP_ERROR(XPATH_VARIABLE_REF_ERROR); | 10215 XP_ERROR(XPATH_VARIABLE_REF_ERROR); |
10214 } | 10216 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10253 if (xmlStrEqual(name, BAD_CAST "processing-instruction")) | 10255 if (xmlStrEqual(name, BAD_CAST "processing-instruction")) |
10254 return(1); | 10256 return(1); |
10255 return(0); | 10257 return(0); |
10256 } | 10258 } |
10257 | 10259 |
10258 /** | 10260 /** |
10259 * xmlXPathCompFunctionCall: | 10261 * xmlXPathCompFunctionCall: |
10260 * @ctxt: the XPath Parser context | 10262 * @ctxt: the XPath Parser context |
10261 * | 10263 * |
10262 * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')' | 10264 * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')' |
10263 * [17] Argument ::= Expr | 10265 * [17] Argument ::= Expr |
10264 * | 10266 * |
10265 * Compile a function call, the evaluation of all arguments are | 10267 * Compile a function call, the evaluation of all arguments are |
10266 * pushed on the stack | 10268 * pushed on the stack |
10267 */ | 10269 */ |
10268 static void | 10270 static void |
10269 xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) { | 10271 xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) { |
10270 xmlChar *name; | 10272 xmlChar *name; |
10271 xmlChar *prefix; | 10273 xmlChar *prefix; |
10272 int nbargs = 0; | 10274 int nbargs = 0; |
10273 int sort = 1; | 10275 int sort = 1; |
10274 | 10276 |
10275 name = xmlXPathParseQName(ctxt, &prefix); | 10277 name = xmlXPathParseQName(ctxt, &prefix); |
10276 if (name == NULL) { | 10278 if (name == NULL) { |
| 10279 xmlFree(prefix); |
10277 XP_ERROR(XPATH_EXPR_ERROR); | 10280 XP_ERROR(XPATH_EXPR_ERROR); |
10278 } | 10281 } |
10279 SKIP_BLANKS; | 10282 SKIP_BLANKS; |
10280 #ifdef DEBUG_EXPR | 10283 #ifdef DEBUG_EXPR |
10281 if (prefix == NULL) | 10284 if (prefix == NULL) |
10282 xmlGenericError(xmlGenericErrorContext, "Calling function %s\n", | 10285 xmlGenericError(xmlGenericErrorContext, "Calling function %s\n", |
10283 name); | 10286 name); |
10284 else | 10287 else |
10285 xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n", | 10288 xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n", |
10286 prefix, name); | 10289 prefix, name); |
(...skipping 12 matching lines...) Expand all Loading... |
10299 xmlStrEqual(name, BAD_CAST "count")) | 10302 xmlStrEqual(name, BAD_CAST "count")) |
10300 { | 10303 { |
10301 sort = 0; | 10304 sort = 0; |
10302 } | 10305 } |
10303 ctxt->comp->last = -1; | 10306 ctxt->comp->last = -1; |
10304 if (CUR != ')') { | 10307 if (CUR != ')') { |
10305 while (CUR != 0) { | 10308 while (CUR != 0) { |
10306 int op1 = ctxt->comp->last; | 10309 int op1 = ctxt->comp->last; |
10307 ctxt->comp->last = -1; | 10310 ctxt->comp->last = -1; |
10308 xmlXPathCompileExpr(ctxt, sort); | 10311 xmlXPathCompileExpr(ctxt, sort); |
10309 » CHECK_ERROR; | 10312 » if (ctxt->error != XPATH_EXPRESSION_OK) { |
| 10313 » » xmlFree(name); |
| 10314 » » xmlFree(prefix); |
| 10315 » » return; |
| 10316 » } |
10310 PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0); | 10317 PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0); |
10311 nbargs++; | 10318 nbargs++; |
10312 if (CUR == ')') break; | 10319 if (CUR == ')') break; |
10313 if (CUR != ',') { | 10320 if (CUR != ',') { |
10314 XP_ERROR(XPATH_EXPR_ERROR); | 10321 XP_ERROR(XPATH_EXPR_ERROR); |
10315 } | 10322 } |
10316 NEXT; | 10323 NEXT; |
10317 SKIP_BLANKS; | 10324 SKIP_BLANKS; |
10318 } | 10325 } |
10319 } | 10326 } |
10320 PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, | 10327 PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, |
10321 name, prefix); | 10328 name, prefix); |
10322 NEXT; | 10329 NEXT; |
10323 SKIP_BLANKS; | 10330 SKIP_BLANKS; |
10324 } | 10331 } |
10325 | 10332 |
10326 /** | 10333 /** |
10327 * xmlXPathCompPrimaryExpr: | 10334 * xmlXPathCompPrimaryExpr: |
10328 * @ctxt: the XPath Parser context | 10335 * @ctxt: the XPath Parser context |
10329 * | 10336 * |
10330 * [15] PrimaryExpr ::= VariableReference | 10337 * [15] PrimaryExpr ::= VariableReference |
10331 * | '(' Expr ')' | 10338 * | '(' Expr ')' |
10332 * | Literal | 10339 * | Literal |
10333 * | Number | 10340 * | Number |
10334 * | FunctionCall | 10341 * | FunctionCall |
10335 * | 10342 * |
10336 * Compile a primary expression. | 10343 * Compile a primary expression. |
10337 */ | 10344 */ |
10338 static void | 10345 static void |
10339 xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) { | 10346 xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) { |
10340 SKIP_BLANKS; | 10347 SKIP_BLANKS; |
10341 if (CUR == '$') xmlXPathCompVariableReference(ctxt); | 10348 if (CUR == '$') xmlXPathCompVariableReference(ctxt); |
10342 else if (CUR == '(') { | 10349 else if (CUR == '(') { |
10343 NEXT; | 10350 NEXT; |
10344 SKIP_BLANKS; | 10351 SKIP_BLANKS; |
(...skipping 11 matching lines...) Expand all Loading... |
10356 } else { | 10363 } else { |
10357 xmlXPathCompFunctionCall(ctxt); | 10364 xmlXPathCompFunctionCall(ctxt); |
10358 } | 10365 } |
10359 SKIP_BLANKS; | 10366 SKIP_BLANKS; |
10360 } | 10367 } |
10361 | 10368 |
10362 /** | 10369 /** |
10363 * xmlXPathCompFilterExpr: | 10370 * xmlXPathCompFilterExpr: |
10364 * @ctxt: the XPath Parser context | 10371 * @ctxt: the XPath Parser context |
10365 * | 10372 * |
10366 * [20] FilterExpr ::= PrimaryExpr | 10373 * [20] FilterExpr ::= PrimaryExpr |
10367 * | FilterExpr Predicate | 10374 * | FilterExpr Predicate |
10368 * | 10375 * |
10369 * Compile a filter expression. | 10376 * Compile a filter expression. |
10370 * Square brackets are used to filter expressions in the same way that | 10377 * Square brackets are used to filter expressions in the same way that |
10371 * they are used in location paths. It is an error if the expression to | 10378 * they are used in location paths. It is an error if the expression to |
10372 * be filtered does not evaluate to a node-set. The context node list | 10379 * be filtered does not evaluate to a node-set. The context node list |
10373 * used for evaluating the expression in square brackets is the node-set | 10380 * used for evaluating the expression in square brackets is the node-set |
10374 * to be filtered listed in document order. | 10381 * to be filtered listed in document order. |
10375 */ | 10382 */ |
10376 | 10383 |
10377 static void | 10384 static void |
10378 xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) { | 10385 xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) { |
10379 xmlXPathCompPrimaryExpr(ctxt); | 10386 xmlXPathCompPrimaryExpr(ctxt); |
10380 CHECK_ERROR; | 10387 CHECK_ERROR; |
10381 SKIP_BLANKS; | 10388 SKIP_BLANKS; |
10382 | 10389 |
10383 while (CUR == '[') { | 10390 while (CUR == '[') { |
10384 xmlXPathCompPredicate(ctxt, 1); | 10391 xmlXPathCompPredicate(ctxt, 1); |
10385 SKIP_BLANKS; | 10392 SKIP_BLANKS; |
10386 } | 10393 } |
10387 | 10394 |
10388 | 10395 |
10389 } | 10396 } |
10390 | 10397 |
10391 /** | 10398 /** |
10392 * xmlXPathScanName: | 10399 * xmlXPathScanName: |
10393 * @ctxt: the XPath Parser context | 10400 * @ctxt: the XPath Parser context |
10394 * | 10401 * |
10395 * Trickery: parse an XML name but without consuming the input flow | 10402 * Trickery: parse an XML name but without consuming the input flow |
10396 * Needed to avoid insanity in the parser state. | 10403 * Needed to avoid insanity in the parser state. |
10397 * | 10404 * |
10398 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | | 10405 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | |
(...skipping 18 matching lines...) Expand all Loading... |
10417 c = CUR_CHAR(l); | 10424 c = CUR_CHAR(l); |
10418 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ | 10425 if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ |
10419 (!IS_LETTER(c) && (c != '_') && | 10426 (!IS_LETTER(c) && (c != '_') && |
10420 (c != ':'))) { | 10427 (c != ':'))) { |
10421 return(NULL); | 10428 return(NULL); |
10422 } | 10429 } |
10423 | 10430 |
10424 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ | 10431 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ |
10425 ((IS_LETTER(c)) || (IS_DIGIT(c)) || | 10432 ((IS_LETTER(c)) || (IS_DIGIT(c)) || |
10426 (c == '.') || (c == '-') || | 10433 (c == '.') || (c == '-') || |
10427 » (c == '_') || (c == ':') || | 10434 » (c == '_') || (c == ':') || |
10428 (IS_COMBINING(c)) || | 10435 (IS_COMBINING(c)) || |
10429 (IS_EXTENDER(c)))) { | 10436 (IS_EXTENDER(c)))) { |
10430 len += l; | 10437 len += l; |
10431 NEXTL(l); | 10438 NEXTL(l); |
10432 c = CUR_CHAR(l); | 10439 c = CUR_CHAR(l); |
10433 } | 10440 } |
10434 ret = xmlStrndup(cur, ctxt->cur - cur); | 10441 ret = xmlStrndup(cur, ctxt->cur - cur); |
10435 ctxt->cur = cur; | 10442 ctxt->cur = cur; |
10436 return(ret); | 10443 return(ret); |
10437 } | 10444 } |
10438 | 10445 |
10439 /** | 10446 /** |
10440 * xmlXPathCompPathExpr: | 10447 * xmlXPathCompPathExpr: |
10441 * @ctxt: the XPath Parser context | 10448 * @ctxt: the XPath Parser context |
10442 * | 10449 * |
10443 * [19] PathExpr ::= LocationPath | 10450 * [19] PathExpr ::= LocationPath |
10444 * | FilterExpr | 10451 * | FilterExpr |
10445 * | FilterExpr '/' RelativeLocationPath | 10452 * | FilterExpr '/' RelativeLocationPath |
10446 * | FilterExpr '//' RelativeLocationPath | 10453 * | FilterExpr '//' RelativeLocationPath |
10447 * | 10454 * |
10448 * Compile a path expression. | 10455 * Compile a path expression. |
10449 * The / operator and // operators combine an arbitrary expression | 10456 * The / operator and // operators combine an arbitrary expression |
10450 * and a relative location path. It is an error if the expression | 10457 * and a relative location path. It is an error if the expression |
10451 * does not evaluate to a node-set. | 10458 * does not evaluate to a node-set. |
10452 * The / operator does composition in the same way as when / is | 10459 * The / operator does composition in the same way as when / is |
10453 * used in a location path. As in location paths, // is short for | 10460 * used in a location path. As in location paths, // is short for |
10454 * /descendant-or-self::node()/. | 10461 * /descendant-or-self::node()/. |
10455 */ | 10462 */ |
10456 | 10463 |
10457 static void | 10464 static void |
10458 xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { | 10465 xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { |
10459 int lc = 1; /* Should we branch to LocationPath ? */ | 10466 int lc = 1; /* Should we branch to LocationPath ? */ |
10460 xmlChar *name = NULL; /* we may have to preparse a name to find out */ | 10467 xmlChar *name = NULL; /* we may have to preparse a name to find out */ |
10461 | 10468 |
10462 SKIP_BLANKS; | 10469 SKIP_BLANKS; |
10463 if ((CUR == '$') || (CUR == '(') || | 10470 if ((CUR == '$') || (CUR == '(') || |
10464 » (IS_ASCII_DIGIT(CUR)) || | 10471 » (IS_ASCII_DIGIT(CUR)) || |
10465 (CUR == '\'') || (CUR == '"') || | 10472 (CUR == '\'') || (CUR == '"') || |
10466 (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) { | 10473 (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) { |
10467 lc = 0; | 10474 lc = 0; |
10468 } else if (CUR == '*') { | 10475 } else if (CUR == '*') { |
10469 /* relative or absolute location path */ | 10476 /* relative or absolute location path */ |
10470 lc = 1; | 10477 lc = 1; |
10471 } else if (CUR == '/') { | 10478 } else if (CUR == '/') { |
10472 /* relative or absolute location path */ | 10479 /* relative or absolute location path */ |
10473 lc = 1; | 10480 lc = 1; |
10474 } else if (CUR == '@') { | 10481 } else if (CUR == '@') { |
(...skipping 19 matching lines...) Expand all Loading... |
10494 if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) { | 10501 if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) { |
10495 #ifdef DEBUG_STEP | 10502 #ifdef DEBUG_STEP |
10496 xmlGenericError(xmlGenericErrorContext, | 10503 xmlGenericError(xmlGenericErrorContext, |
10497 "PathExpr: Axis\n"); | 10504 "PathExpr: Axis\n"); |
10498 #endif | 10505 #endif |
10499 lc = 1; | 10506 lc = 1; |
10500 xmlFree(name); | 10507 xmlFree(name); |
10501 } else if (name != NULL) { | 10508 } else if (name != NULL) { |
10502 int len =xmlStrlen(name); | 10509 int len =xmlStrlen(name); |
10503 | 10510 |
10504 » | 10511 |
10505 while (NXT(len) != 0) { | 10512 while (NXT(len) != 0) { |
10506 if (NXT(len) == '/') { | 10513 if (NXT(len) == '/') { |
10507 /* element name */ | 10514 /* element name */ |
10508 #ifdef DEBUG_STEP | 10515 #ifdef DEBUG_STEP |
10509 xmlGenericError(xmlGenericErrorContext, | 10516 xmlGenericError(xmlGenericErrorContext, |
10510 "PathExpr: AbbrRelLocation\n"); | 10517 "PathExpr: AbbrRelLocation\n"); |
10511 #endif | 10518 #endif |
10512 lc = 1; | 10519 lc = 1; |
10513 break; | 10520 break; |
10514 } else if (IS_BLANK_CH(NXT(len))) { | 10521 } else if (IS_BLANK_CH(NXT(len))) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10561 "PathExpr: AbbrRelLocation\n"); | 10568 "PathExpr: AbbrRelLocation\n"); |
10562 #endif | 10569 #endif |
10563 /* element name */ | 10570 /* element name */ |
10564 lc = 1; | 10571 lc = 1; |
10565 } | 10572 } |
10566 xmlFree(name); | 10573 xmlFree(name); |
10567 } else { | 10574 } else { |
10568 /* make sure all cases are covered explicitly */ | 10575 /* make sure all cases are covered explicitly */ |
10569 XP_ERROR(XPATH_EXPR_ERROR); | 10576 XP_ERROR(XPATH_EXPR_ERROR); |
10570 } | 10577 } |
10571 } | 10578 } |
10572 | 10579 |
10573 if (lc) { | 10580 if (lc) { |
10574 if (CUR == '/') { | 10581 if (CUR == '/') { |
10575 PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0); | 10582 PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0); |
10576 } else { | 10583 } else { |
10577 PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0); | 10584 PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0); |
10578 } | 10585 } |
10579 xmlXPathCompLocationPath(ctxt); | 10586 xmlXPathCompLocationPath(ctxt); |
10580 } else { | 10587 } else { |
10581 xmlXPathCompFilterExpr(ctxt); | 10588 xmlXPathCompFilterExpr(ctxt); |
(...skipping 11 matching lines...) Expand all Loading... |
10593 xmlXPathCompRelativeLocationPath(ctxt); | 10600 xmlXPathCompRelativeLocationPath(ctxt); |
10594 } | 10601 } |
10595 } | 10602 } |
10596 SKIP_BLANKS; | 10603 SKIP_BLANKS; |
10597 } | 10604 } |
10598 | 10605 |
10599 /** | 10606 /** |
10600 * xmlXPathCompUnionExpr: | 10607 * xmlXPathCompUnionExpr: |
10601 * @ctxt: the XPath Parser context | 10608 * @ctxt: the XPath Parser context |
10602 * | 10609 * |
10603 * [18] UnionExpr ::= PathExpr | 10610 * [18] UnionExpr ::= PathExpr |
10604 * | UnionExpr '|' PathExpr | 10611 * | UnionExpr '|' PathExpr |
10605 * | 10612 * |
10606 * Compile an union expression. | 10613 * Compile an union expression. |
10607 */ | 10614 */ |
10608 | 10615 |
10609 static void | 10616 static void |
10610 xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) { | 10617 xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) { |
10611 xmlXPathCompPathExpr(ctxt); | 10618 xmlXPathCompPathExpr(ctxt); |
10612 CHECK_ERROR; | 10619 CHECK_ERROR; |
10613 SKIP_BLANKS; | 10620 SKIP_BLANKS; |
10614 while (CUR == '|') { | 10621 while (CUR == '|') { |
10615 int op1 = ctxt->comp->last; | 10622 int op1 = ctxt->comp->last; |
10616 PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0); | 10623 PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0); |
10617 | 10624 |
10618 NEXT; | 10625 NEXT; |
10619 SKIP_BLANKS; | 10626 SKIP_BLANKS; |
10620 xmlXPathCompPathExpr(ctxt); | 10627 xmlXPathCompPathExpr(ctxt); |
10621 | 10628 |
10622 PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0); | 10629 PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0); |
10623 | 10630 |
10624 SKIP_BLANKS; | 10631 SKIP_BLANKS; |
10625 } | 10632 } |
10626 } | 10633 } |
10627 | 10634 |
10628 /** | 10635 /** |
10629 * xmlXPathCompUnaryExpr: | 10636 * xmlXPathCompUnaryExpr: |
10630 * @ctxt: the XPath Parser context | 10637 * @ctxt: the XPath Parser context |
10631 * | 10638 * |
10632 * [27] UnaryExpr ::= UnionExpr | 10639 * [27] UnaryExpr ::= UnionExpr |
10633 * | '-' UnaryExpr | 10640 * | '-' UnaryExpr |
10634 * | 10641 * |
10635 * Compile an unary expression. | 10642 * Compile an unary expression. |
10636 */ | 10643 */ |
10637 | 10644 |
10638 static void | 10645 static void |
10639 xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) { | 10646 xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) { |
10640 int minus = 0; | 10647 int minus = 0; |
10641 int found = 0; | 10648 int found = 0; |
10642 | 10649 |
10643 SKIP_BLANKS; | 10650 SKIP_BLANKS; |
(...skipping 11 matching lines...) Expand all Loading... |
10655 PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0); | 10662 PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0); |
10656 else | 10663 else |
10657 PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0); | 10664 PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0); |
10658 } | 10665 } |
10659 } | 10666 } |
10660 | 10667 |
10661 /** | 10668 /** |
10662 * xmlXPathCompMultiplicativeExpr: | 10669 * xmlXPathCompMultiplicativeExpr: |
10663 * @ctxt: the XPath Parser context | 10670 * @ctxt: the XPath Parser context |
10664 * | 10671 * |
10665 * [26] MultiplicativeExpr ::= UnaryExpr | 10672 * [26] MultiplicativeExpr ::= UnaryExpr |
10666 * | MultiplicativeExpr MultiplyOperator UnaryExpr | 10673 * | MultiplicativeExpr MultiplyOperator UnaryExpr |
10667 * | MultiplicativeExpr 'div' UnaryExpr | 10674 * | MultiplicativeExpr 'div' UnaryExpr |
10668 * | MultiplicativeExpr 'mod' UnaryExpr | 10675 * | MultiplicativeExpr 'mod' UnaryExpr |
10669 * [34] MultiplyOperator ::= '*' | 10676 * [34] MultiplyOperator ::= '*' |
10670 * | 10677 * |
10671 * Compile an Additive expression. | 10678 * Compile an Additive expression. |
10672 */ | 10679 */ |
10673 | 10680 |
10674 static void | 10681 static void |
10675 xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) { | 10682 xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) { |
10676 xmlXPathCompUnaryExpr(ctxt); | 10683 xmlXPathCompUnaryExpr(ctxt); |
10677 CHECK_ERROR; | 10684 CHECK_ERROR; |
10678 SKIP_BLANKS; | 10685 SKIP_BLANKS; |
10679 while ((CUR == '*') || | 10686 while ((CUR == '*') || |
10680 ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) || | 10687 ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) || |
10681 ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) { | 10688 ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) { |
10682 int op = -1; | 10689 int op = -1; |
10683 int op1 = ctxt->comp->last; | 10690 int op1 = ctxt->comp->last; |
10684 | 10691 |
10685 if (CUR == '*') { | 10692 if (CUR == '*') { |
10686 op = 0; | 10693 op = 0; |
10687 NEXT; | 10694 NEXT; |
10688 } else if (CUR == 'd') { | 10695 } else if (CUR == 'd') { |
10689 op = 1; | 10696 op = 1; |
10690 SKIP(3); | 10697 SKIP(3); |
10691 } else if (CUR == 'm') { | 10698 } else if (CUR == 'm') { |
10692 op = 2; | 10699 op = 2; |
10693 SKIP(3); | 10700 SKIP(3); |
10694 } | 10701 } |
10695 SKIP_BLANKS; | 10702 SKIP_BLANKS; |
10696 xmlXPathCompUnaryExpr(ctxt); | 10703 xmlXPathCompUnaryExpr(ctxt); |
10697 CHECK_ERROR; | 10704 CHECK_ERROR; |
10698 PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0); | 10705 PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0); |
10699 SKIP_BLANKS; | 10706 SKIP_BLANKS; |
10700 } | 10707 } |
10701 } | 10708 } |
10702 | 10709 |
10703 /** | 10710 /** |
10704 * xmlXPathCompAdditiveExpr: | 10711 * xmlXPathCompAdditiveExpr: |
10705 * @ctxt: the XPath Parser context | 10712 * @ctxt: the XPath Parser context |
10706 * | 10713 * |
10707 * [25] AdditiveExpr ::= MultiplicativeExpr | 10714 * [25] AdditiveExpr ::= MultiplicativeExpr |
10708 * | AdditiveExpr '+' MultiplicativeExpr | 10715 * | AdditiveExpr '+' MultiplicativeExpr |
10709 * | AdditiveExpr '-' MultiplicativeExpr | 10716 * | AdditiveExpr '-' MultiplicativeExpr |
10710 * | 10717 * |
10711 * Compile an Additive expression. | 10718 * Compile an Additive expression. |
10712 */ | 10719 */ |
10713 | 10720 |
10714 static void | 10721 static void |
10715 xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) { | 10722 xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) { |
10716 | 10723 |
10717 xmlXPathCompMultiplicativeExpr(ctxt); | 10724 xmlXPathCompMultiplicativeExpr(ctxt); |
10718 CHECK_ERROR; | 10725 CHECK_ERROR; |
10719 SKIP_BLANKS; | 10726 SKIP_BLANKS; |
10720 while ((CUR == '+') || (CUR == '-')) { | 10727 while ((CUR == '+') || (CUR == '-')) { |
10721 int plus; | 10728 int plus; |
10722 int op1 = ctxt->comp->last; | 10729 int op1 = ctxt->comp->last; |
10723 | 10730 |
10724 if (CUR == '+') plus = 1; | 10731 if (CUR == '+') plus = 1; |
10725 else plus = 0; | 10732 else plus = 0; |
10726 NEXT; | 10733 NEXT; |
10727 SKIP_BLANKS; | 10734 SKIP_BLANKS; |
10728 xmlXPathCompMultiplicativeExpr(ctxt); | 10735 xmlXPathCompMultiplicativeExpr(ctxt); |
10729 CHECK_ERROR; | 10736 CHECK_ERROR; |
10730 PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0); | 10737 PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0); |
10731 SKIP_BLANKS; | 10738 SKIP_BLANKS; |
10732 } | 10739 } |
10733 } | 10740 } |
10734 | 10741 |
10735 /** | 10742 /** |
10736 * xmlXPathCompRelationalExpr: | 10743 * xmlXPathCompRelationalExpr: |
10737 * @ctxt: the XPath Parser context | 10744 * @ctxt: the XPath Parser context |
10738 * | 10745 * |
10739 * [24] RelationalExpr ::= AdditiveExpr | 10746 * [24] RelationalExpr ::= AdditiveExpr |
10740 * | RelationalExpr '<' AdditiveExpr | 10747 * | RelationalExpr '<' AdditiveExpr |
10741 * | RelationalExpr '>' AdditiveExpr | 10748 * | RelationalExpr '>' AdditiveExpr |
10742 * | RelationalExpr '<=' AdditiveExpr | 10749 * | RelationalExpr '<=' AdditiveExpr |
10743 * | RelationalExpr '>=' AdditiveExpr | 10750 * | RelationalExpr '>=' AdditiveExpr |
10744 * | 10751 * |
10745 * A <= B > C is allowed ? Answer from James, yes with | 10752 * A <= B > C is allowed ? Answer from James, yes with |
10746 * (AdditiveExpr <= AdditiveExpr) > AdditiveExpr | 10753 * (AdditiveExpr <= AdditiveExpr) > AdditiveExpr |
10747 * which is basically what got implemented. | 10754 * which is basically what got implemented. |
10748 * | 10755 * |
10749 * Compile a Relational expression, then push the result | 10756 * Compile a Relational expression, then push the result |
10750 * on the stack | 10757 * on the stack |
10751 */ | 10758 */ |
10752 | 10759 |
10753 static void | 10760 static void |
(...skipping 19 matching lines...) Expand all Loading... |
10773 CHECK_ERROR; | 10780 CHECK_ERROR; |
10774 PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict); | 10781 PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict); |
10775 SKIP_BLANKS; | 10782 SKIP_BLANKS; |
10776 } | 10783 } |
10777 } | 10784 } |
10778 | 10785 |
10779 /** | 10786 /** |
10780 * xmlXPathCompEqualityExpr: | 10787 * xmlXPathCompEqualityExpr: |
10781 * @ctxt: the XPath Parser context | 10788 * @ctxt: the XPath Parser context |
10782 * | 10789 * |
10783 * [23] EqualityExpr ::= RelationalExpr | 10790 * [23] EqualityExpr ::= RelationalExpr |
10784 * | EqualityExpr '=' RelationalExpr | 10791 * | EqualityExpr '=' RelationalExpr |
10785 * | EqualityExpr '!=' RelationalExpr | 10792 * | EqualityExpr '!=' RelationalExpr |
10786 * | 10793 * |
10787 * A != B != C is allowed ? Answer from James, yes with | 10794 * A != B != C is allowed ? Answer from James, yes with |
10788 * (RelationalExpr = RelationalExpr) = RelationalExpr | 10795 * (RelationalExpr = RelationalExpr) = RelationalExpr |
10789 * (RelationalExpr != RelationalExpr) != RelationalExpr | 10796 * (RelationalExpr != RelationalExpr) != RelationalExpr |
10790 * which is basically what got implemented. | 10797 * which is basically what got implemented. |
10791 * | 10798 * |
10792 * Compile an Equality expression. | 10799 * Compile an Equality expression. |
10793 * | 10800 * |
10794 */ | 10801 */ |
10795 static void | 10802 static void |
(...skipping 14 matching lines...) Expand all Loading... |
10810 CHECK_ERROR; | 10817 CHECK_ERROR; |
10811 PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0); | 10818 PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0); |
10812 SKIP_BLANKS; | 10819 SKIP_BLANKS; |
10813 } | 10820 } |
10814 } | 10821 } |
10815 | 10822 |
10816 /** | 10823 /** |
10817 * xmlXPathCompAndExpr: | 10824 * xmlXPathCompAndExpr: |
10818 * @ctxt: the XPath Parser context | 10825 * @ctxt: the XPath Parser context |
10819 * | 10826 * |
10820 * [22] AndExpr ::= EqualityExpr | 10827 * [22] AndExpr ::= EqualityExpr |
10821 * | AndExpr 'and' EqualityExpr | 10828 * | AndExpr 'and' EqualityExpr |
10822 * | 10829 * |
10823 * Compile an AND expression. | 10830 * Compile an AND expression. |
10824 * | 10831 * |
10825 */ | 10832 */ |
10826 static void | 10833 static void |
10827 xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) { | 10834 xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) { |
10828 xmlXPathCompEqualityExpr(ctxt); | 10835 xmlXPathCompEqualityExpr(ctxt); |
10829 CHECK_ERROR; | 10836 CHECK_ERROR; |
10830 SKIP_BLANKS; | 10837 SKIP_BLANKS; |
10831 while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) { | 10838 while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) { |
10832 int op1 = ctxt->comp->last; | 10839 int op1 = ctxt->comp->last; |
10833 SKIP(3); | 10840 SKIP(3); |
10834 SKIP_BLANKS; | 10841 SKIP_BLANKS; |
10835 xmlXPathCompEqualityExpr(ctxt); | 10842 xmlXPathCompEqualityExpr(ctxt); |
10836 CHECK_ERROR; | 10843 CHECK_ERROR; |
10837 PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0); | 10844 PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0); |
10838 SKIP_BLANKS; | 10845 SKIP_BLANKS; |
10839 } | 10846 } |
10840 } | 10847 } |
10841 | 10848 |
10842 /** | 10849 /** |
10843 * xmlXPathCompileExpr: | 10850 * xmlXPathCompileExpr: |
10844 * @ctxt: the XPath Parser context | 10851 * @ctxt: the XPath Parser context |
10845 * | 10852 * |
10846 * [14] Expr ::= OrExpr | 10853 * [14] Expr ::= OrExpr |
10847 * [21] OrExpr ::= AndExpr | 10854 * [21] OrExpr ::= AndExpr |
10848 * | OrExpr 'or' AndExpr | 10855 * | OrExpr 'or' AndExpr |
10849 * | 10856 * |
10850 * Parse and compile an expression | 10857 * Parse and compile an expression |
10851 */ | 10858 */ |
10852 static void | 10859 static void |
10853 xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) { | 10860 xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) { |
10854 xmlXPathCompAndExpr(ctxt); | 10861 xmlXPathCompAndExpr(ctxt); |
10855 CHECK_ERROR; | 10862 CHECK_ERROR; |
10856 SKIP_BLANKS; | 10863 SKIP_BLANKS; |
10857 while ((CUR == 'o') && (NXT(1) == 'r')) { | 10864 while ((CUR == 'o') && (NXT(1) == 'r')) { |
10858 int op1 = ctxt->comp->last; | 10865 int op1 = ctxt->comp->last; |
10859 SKIP(2); | 10866 SKIP(2); |
10860 SKIP_BLANKS; | 10867 SKIP_BLANKS; |
10861 xmlXPathCompAndExpr(ctxt); | 10868 xmlXPathCompAndExpr(ctxt); |
10862 CHECK_ERROR; | 10869 CHECK_ERROR; |
10863 PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0); | 10870 PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0); |
10864 op1 = ctxt->comp->nbStep; | |
10865 SKIP_BLANKS; | 10871 SKIP_BLANKS; |
10866 } | 10872 } |
10867 if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) { | 10873 if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) { |
10868 /* more ops could be optimized too */ | 10874 /* more ops could be optimized too */ |
10869 /* | 10875 /* |
10870 * This is the main place to eliminate sorting for | 10876 * This is the main place to eliminate sorting for |
10871 * operations which don't require a sorted node-set. | 10877 * operations which don't require a sorted node-set. |
10872 * E.g. count(). | 10878 * E.g. count(). |
10873 */ | 10879 */ |
10874 PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0); | 10880 PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0); |
10875 } | 10881 } |
10876 } | 10882 } |
10877 | 10883 |
10878 /** | 10884 /** |
10879 * xmlXPathCompPredicate: | 10885 * xmlXPathCompPredicate: |
10880 * @ctxt: the XPath Parser context | 10886 * @ctxt: the XPath Parser context |
10881 * @filter: act as a filter | 10887 * @filter: act as a filter |
10882 * | 10888 * |
10883 * [8] Predicate ::= '[' PredicateExpr ']' | 10889 * [8] Predicate ::= '[' PredicateExpr ']' |
10884 * [9] PredicateExpr ::= Expr | 10890 * [9] PredicateExpr ::= Expr |
10885 * | 10891 * |
10886 * Compile a predicate expression | 10892 * Compile a predicate expression |
10887 */ | 10893 */ |
10888 static void | 10894 static void |
10889 xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) { | 10895 xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) { |
10890 int op1 = ctxt->comp->last; | 10896 int op1 = ctxt->comp->last; |
10891 | 10897 |
10892 SKIP_BLANKS; | 10898 SKIP_BLANKS; |
10893 if (CUR != '[') { | 10899 if (CUR != '[') { |
10894 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); | 10900 XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10991 *type = NODE_TYPE_PI; | 10997 *type = NODE_TYPE_PI; |
10992 else if (xmlStrEqual(name, BAD_CAST "text")) | 10998 else if (xmlStrEqual(name, BAD_CAST "text")) |
10993 *type = NODE_TYPE_TEXT; | 10999 *type = NODE_TYPE_TEXT; |
10994 else { | 11000 else { |
10995 if (name != NULL) | 11001 if (name != NULL) |
10996 xmlFree(name); | 11002 xmlFree(name); |
10997 XP_ERRORNULL(XPATH_EXPR_ERROR); | 11003 XP_ERRORNULL(XPATH_EXPR_ERROR); |
10998 } | 11004 } |
10999 | 11005 |
11000 *test = NODE_TEST_TYPE; | 11006 *test = NODE_TEST_TYPE; |
11001 » | 11007 |
11002 SKIP_BLANKS; | 11008 SKIP_BLANKS; |
11003 if (*type == NODE_TYPE_PI) { | 11009 if (*type == NODE_TYPE_PI) { |
11004 /* | 11010 /* |
11005 * Specific case: search a PI by name. | 11011 * Specific case: search a PI by name. |
11006 */ | 11012 */ |
11007 if (name != NULL) | 11013 if (name != NULL) |
11008 xmlFree(name); | 11014 xmlFree(name); |
11009 name = NULL; | 11015 name = NULL; |
11010 if (CUR != ')') { | 11016 if (CUR != ')') { |
11011 name = xmlXPathParseLiteral(ctxt); | 11017 name = xmlXPathParseLiteral(ctxt); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11127 break; | 11133 break; |
11128 } | 11134 } |
11129 return(ret); | 11135 return(ret); |
11130 } | 11136 } |
11131 | 11137 |
11132 /** | 11138 /** |
11133 * xmlXPathCompStep: | 11139 * xmlXPathCompStep: |
11134 * @ctxt: the XPath Parser context | 11140 * @ctxt: the XPath Parser context |
11135 * | 11141 * |
11136 * [4] Step ::= AxisSpecifier NodeTest Predicate* | 11142 * [4] Step ::= AxisSpecifier NodeTest Predicate* |
11137 * | AbbreviatedStep | 11143 * | AbbreviatedStep |
11138 * | 11144 * |
11139 * [12] AbbreviatedStep ::= '.' | '..' | 11145 * [12] AbbreviatedStep ::= '.' | '..' |
11140 * | 11146 * |
11141 * [5] AxisSpecifier ::= AxisName '::' | 11147 * [5] AxisSpecifier ::= AxisName '::' |
11142 * | AbbreviatedAxisSpecifier | 11148 * | AbbreviatedAxisSpecifier |
11143 * | 11149 * |
11144 * [13] AbbreviatedAxisSpecifier ::= '@'? | 11150 * [13] AbbreviatedAxisSpecifier ::= '@'? |
11145 * | 11151 * |
11146 * Modified for XPtr range support as: | 11152 * Modified for XPtr range support as: |
11147 * | 11153 * |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11299 else | 11305 else |
11300 xmlGenericErrorContextNodeSet(xmlGenericErrorContext, | 11306 xmlGenericErrorContextNodeSet(xmlGenericErrorContext, |
11301 ctxt->value->nodesetval); | 11307 ctxt->value->nodesetval); |
11302 #endif | 11308 #endif |
11303 } | 11309 } |
11304 | 11310 |
11305 /** | 11311 /** |
11306 * xmlXPathCompRelativeLocationPath: | 11312 * xmlXPathCompRelativeLocationPath: |
11307 * @ctxt: the XPath Parser context | 11313 * @ctxt: the XPath Parser context |
11308 * | 11314 * |
11309 * [3] RelativeLocationPath ::= Step | 11315 * [3] RelativeLocationPath ::= Step |
11310 * | RelativeLocationPath '/' Step | 11316 * | RelativeLocationPath '/' Step |
11311 * | AbbreviatedRelativeLocationPath | 11317 * | AbbreviatedRelativeLocationPath |
11312 * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step | 11318 * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step |
11313 * | 11319 * |
11314 * Compile a relative location path. | 11320 * Compile a relative location path. |
11315 */ | 11321 */ |
11316 static void | 11322 static void |
11317 xmlXPathCompRelativeLocationPath | 11323 xmlXPathCompRelativeLocationPath |
11318 (xmlXPathParserContextPtr ctxt) { | 11324 (xmlXPathParserContextPtr ctxt) { |
11319 SKIP_BLANKS; | 11325 SKIP_BLANKS; |
11320 if ((CUR == '/') && (NXT(1) == '/')) { | 11326 if ((CUR == '/') && (NXT(1) == '/')) { |
11321 SKIP(2); | 11327 SKIP(2); |
11322 SKIP_BLANKS; | 11328 SKIP_BLANKS; |
11323 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, | 11329 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, |
11324 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); | 11330 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); |
11325 } else if (CUR == '/') { | 11331 } else if (CUR == '/') { |
11326 NEXT; | 11332 NEXT; |
11327 SKIP_BLANKS; | 11333 SKIP_BLANKS; |
11328 } | 11334 } |
11329 xmlXPathCompStep(ctxt); | 11335 xmlXPathCompStep(ctxt); |
| 11336 CHECK_ERROR; |
11330 SKIP_BLANKS; | 11337 SKIP_BLANKS; |
11331 while (CUR == '/') { | 11338 while (CUR == '/') { |
11332 if ((CUR == '/') && (NXT(1) == '/')) { | 11339 if ((CUR == '/') && (NXT(1) == '/')) { |
11333 SKIP(2); | 11340 SKIP(2); |
11334 SKIP_BLANKS; | 11341 SKIP_BLANKS; |
11335 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, | 11342 PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF, |
11336 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); | 11343 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); |
11337 xmlXPathCompStep(ctxt); | 11344 xmlXPathCompStep(ctxt); |
11338 } else if (CUR == '/') { | 11345 } else if (CUR == '/') { |
11339 NEXT; | 11346 NEXT; |
11340 SKIP_BLANKS; | 11347 SKIP_BLANKS; |
11341 xmlXPathCompStep(ctxt); | 11348 xmlXPathCompStep(ctxt); |
11342 } | 11349 } |
11343 SKIP_BLANKS; | 11350 SKIP_BLANKS; |
11344 } | 11351 } |
11345 } | 11352 } |
11346 | 11353 |
11347 /** | 11354 /** |
11348 * xmlXPathCompLocationPath: | 11355 * xmlXPathCompLocationPath: |
11349 * @ctxt: the XPath Parser context | 11356 * @ctxt: the XPath Parser context |
11350 * | 11357 * |
11351 * [1] LocationPath ::= RelativeLocationPath | 11358 * [1] LocationPath ::= RelativeLocationPath |
11352 * | AbsoluteLocationPath | 11359 * | AbsoluteLocationPath |
11353 * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? | 11360 * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath? |
11354 * | AbbreviatedAbsoluteLocationPath | 11361 * | AbbreviatedAbsoluteLocationPath |
11355 * [10] AbbreviatedAbsoluteLocationPath ::= | 11362 * [10] AbbreviatedAbsoluteLocationPath ::= |
11356 * '//' RelativeLocationPath | 11363 * '//' RelativeLocationPath |
11357 * | 11364 * |
11358 * Compile a location path | 11365 * Compile a location path |
11359 * | 11366 * |
11360 * // is short for /descendant-or-self::node()/. For example, | 11367 * // is short for /descendant-or-self::node()/. For example, |
11361 * //para is short for /descendant-or-self::node()/child::para and | 11368 * //para is short for /descendant-or-self::node()/child::para and |
11362 * so will select any para element in the document (even a para element | 11369 * so will select any para element in the document (even a para element |
11363 * that is a document element will be selected by //para since the | 11370 * that is a document element will be selected by //para since the |
11364 * document element node is a child of the root node); div//para is | 11371 * document element node is a child of the root node); div//para is |
11365 * short for div/descendant-or-self::node()/child::para and so will | 11372 * short for div/descendant-or-self::node()/child::para and so will |
11366 * select all para descendants of div children. | 11373 * select all para descendants of div children. |
(...skipping 12 matching lines...) Expand all Loading... |
11379 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); | 11386 NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL); |
11380 xmlXPathCompRelativeLocationPath(ctxt); | 11387 xmlXPathCompRelativeLocationPath(ctxt); |
11381 } else if (CUR == '/') { | 11388 } else if (CUR == '/') { |
11382 NEXT; | 11389 NEXT; |
11383 SKIP_BLANKS; | 11390 SKIP_BLANKS; |
11384 if ((CUR != 0 ) && | 11391 if ((CUR != 0 ) && |
11385 ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') || | 11392 ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') || |
11386 (CUR == '@') || (CUR == '*'))) | 11393 (CUR == '@') || (CUR == '*'))) |
11387 xmlXPathCompRelativeLocationPath(ctxt); | 11394 xmlXPathCompRelativeLocationPath(ctxt); |
11388 } | 11395 } |
| 11396 CHECK_ERROR; |
11389 } | 11397 } |
11390 } | 11398 } |
11391 } | 11399 } |
11392 | 11400 |
11393 /************************************************************************ | 11401 /************************************************************************ |
11394 * * | 11402 * * |
11395 * » » XPath precompiled expression evaluation»» » * | 11403 *» » XPath precompiled expression evaluation»» » * |
11396 * * | 11404 * * |
11397 ************************************************************************/ | 11405 ************************************************************************/ |
11398 | 11406 |
11399 static int | 11407 static int |
11400 xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op); | 11408 xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op); |
11401 | 11409 |
11402 #ifdef DEBUG_STEP | 11410 #ifdef DEBUG_STEP |
11403 static void | 11411 static void |
11404 xmlXPathDebugDumpStepAxis(xmlXPathAxisVal axis, | 11412 xmlXPathDebugDumpStepAxis(xmlXPathStepOpPtr op, |
11405 » » » xmlXPathTestVal test, | |
11406 int nbNodes) | 11413 int nbNodes) |
11407 { | 11414 { |
11408 xmlGenericError(xmlGenericErrorContext, "new step : "); | 11415 xmlGenericError(xmlGenericErrorContext, "new step : "); |
11409 switch (axis) { | 11416 switch (op->value) { |
11410 case AXIS_ANCESTOR: | 11417 case AXIS_ANCESTOR: |
11411 xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' "); | 11418 xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' "); |
11412 break; | 11419 break; |
11413 case AXIS_ANCESTOR_OR_SELF: | 11420 case AXIS_ANCESTOR_OR_SELF: |
11414 xmlGenericError(xmlGenericErrorContext, | 11421 xmlGenericError(xmlGenericErrorContext, |
11415 "axis 'ancestors-or-self' "); | 11422 "axis 'ancestors-or-self' "); |
11416 break; | 11423 break; |
11417 case AXIS_ATTRIBUTE: | 11424 case AXIS_ATTRIBUTE: |
11418 xmlGenericError(xmlGenericErrorContext, "axis 'attributes' "); | 11425 xmlGenericError(xmlGenericErrorContext, "axis 'attributes' "); |
11419 break; | 11426 break; |
(...skipping 26 matching lines...) Expand all Loading... |
11446 case AXIS_PRECEDING_SIBLING: | 11453 case AXIS_PRECEDING_SIBLING: |
11447 xmlGenericError(xmlGenericErrorContext, | 11454 xmlGenericError(xmlGenericErrorContext, |
11448 "axis 'preceding-sibling' "); | 11455 "axis 'preceding-sibling' "); |
11449 break; | 11456 break; |
11450 case AXIS_SELF: | 11457 case AXIS_SELF: |
11451 xmlGenericError(xmlGenericErrorContext, "axis 'self' "); | 11458 xmlGenericError(xmlGenericErrorContext, "axis 'self' "); |
11452 break; | 11459 break; |
11453 } | 11460 } |
11454 xmlGenericError(xmlGenericErrorContext, | 11461 xmlGenericError(xmlGenericErrorContext, |
11455 " context contains %d nodes\n", nbNodes); | 11462 " context contains %d nodes\n", nbNodes); |
11456 switch (test) { | 11463 switch (op->value2) { |
11457 case NODE_TEST_NONE: | 11464 case NODE_TEST_NONE: |
11458 xmlGenericError(xmlGenericErrorContext, | 11465 xmlGenericError(xmlGenericErrorContext, |
11459 " searching for none !!!\n"); | 11466 " searching for none !!!\n"); |
11460 break; | 11467 break; |
11461 case NODE_TEST_TYPE: | 11468 case NODE_TEST_TYPE: |
11462 xmlGenericError(xmlGenericErrorContext, | 11469 xmlGenericError(xmlGenericErrorContext, |
11463 " searching for type %d\n", type); | 11470 " searching for type %d\n", op->value3); |
11464 break; | 11471 break; |
11465 case NODE_TEST_PI: | 11472 case NODE_TEST_PI: |
11466 xmlGenericError(xmlGenericErrorContext, | 11473 xmlGenericError(xmlGenericErrorContext, |
11467 " searching for PI !!!\n"); | 11474 " searching for PI !!!\n"); |
11468 break; | 11475 break; |
11469 case NODE_TEST_ALL: | 11476 case NODE_TEST_ALL: |
11470 xmlGenericError(xmlGenericErrorContext, | 11477 xmlGenericError(xmlGenericErrorContext, |
11471 " searching for *\n"); | 11478 " searching for *\n"); |
11472 break; | 11479 break; |
11473 case NODE_TEST_NS: | 11480 case NODE_TEST_NS: |
11474 xmlGenericError(xmlGenericErrorContext, | 11481 xmlGenericError(xmlGenericErrorContext, |
11475 " searching for namespace %s\n", | 11482 " searching for namespace %s\n", |
11476 prefix); | 11483 op->value5); |
11477 break; | 11484 break; |
11478 case NODE_TEST_NAME: | 11485 case NODE_TEST_NAME: |
11479 xmlGenericError(xmlGenericErrorContext, | 11486 xmlGenericError(xmlGenericErrorContext, |
11480 " searching for name %s\n", name); | 11487 " searching for name %s\n", op->value5); |
11481 if (prefix != NULL) | 11488 if (op->value4) |
11482 xmlGenericError(xmlGenericErrorContext, | 11489 xmlGenericError(xmlGenericErrorContext, |
11483 " with namespace %s\n", prefix); | 11490 " with namespace %s\n", op->value4); |
11484 break; | 11491 break; |
11485 } | 11492 } |
11486 xmlGenericError(xmlGenericErrorContext, "Testing : "); | 11493 xmlGenericError(xmlGenericErrorContext, "Testing : "); |
11487 } | 11494 } |
11488 #endif /* DEBUG_STEP */ | 11495 #endif /* DEBUG_STEP */ |
11489 | 11496 |
11490 static int | 11497 static int |
11491 xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt, | 11498 xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt, |
11492 xmlXPathStepOpPtr op, | 11499 xmlXPathStepOpPtr op, |
11493 xmlNodeSetPtr set, | 11500 xmlNodeSetPtr set, |
11494 int contextSize, | 11501 int contextSize, |
11495 int hasNsNodes) | 11502 int hasNsNodes) |
11496 { | 11503 { |
11497 if (op->ch1 != -1) { | 11504 if (op->ch1 != -1) { |
11498 xmlXPathCompExprPtr comp = ctxt->comp; | 11505 xmlXPathCompExprPtr comp = ctxt->comp; |
11499 /* | 11506 /* |
11500 * Process inner predicates first. | 11507 * Process inner predicates first. |
11501 */ | 11508 */ |
11502 if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) { | 11509 if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) { |
11503 /* | 11510 /* |
11504 * TODO: raise an internal error. | 11511 * TODO: raise an internal error. |
11505 */ | 11512 */ |
11506 } | 11513 } |
11507 contextSize = xmlXPathCompOpEvalPredicate(ctxt, | 11514 contextSize = xmlXPathCompOpEvalPredicate(ctxt, |
11508 &comp->steps[op->ch1], set, contextSize, hasNsNodes); | 11515 &comp->steps[op->ch1], set, contextSize, hasNsNodes); |
11509 CHECK_ERROR0; | 11516 CHECK_ERROR0; |
11510 if (contextSize <= 0) | 11517 if (contextSize <= 0) |
11511 return(0); | 11518 return(0); |
11512 } | 11519 } |
11513 if (op->ch2 != -1) { | 11520 if (op->ch2 != -1) { |
11514 xmlXPathContextPtr xpctxt = ctxt->context; | 11521 xmlXPathContextPtr xpctxt = ctxt->context; |
11515 xmlNodePtr contextNode, oldContextNode; | 11522 xmlNodePtr contextNode, oldContextNode; |
11516 xmlDocPtr oldContextDoc; | 11523 xmlDocPtr oldContextDoc; |
11517 int i, res, contextPos = 0, newContextSize; | 11524 int i, res, contextPos = 0, newContextSize; |
11518 xmlXPathStepOpPtr exprOp; | 11525 xmlXPathStepOpPtr exprOp; |
11519 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; | 11526 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; |
11520 | 11527 |
11521 #ifdef LIBXML_XPTR_ENABLED | 11528 #ifdef LIBXML_XPTR_ENABLED |
11522 /* | 11529 /* |
(...skipping 23 matching lines...) Expand all Loading... |
11546 * After applying predicate [position() > 1] : | 11553 * After applying predicate [position() > 1] : |
11547 * node-set context pos | 11554 * node-set context pos |
11548 * nB 1 | 11555 * nB 1 |
11549 * nC 2 | 11556 * nC 2 |
11550 */ | 11557 */ |
11551 oldContextNode = xpctxt->node; | 11558 oldContextNode = xpctxt->node; |
11552 oldContextDoc = xpctxt->doc; | 11559 oldContextDoc = xpctxt->doc; |
11553 /* | 11560 /* |
11554 * Get the expression of this predicate. | 11561 * Get the expression of this predicate. |
11555 */ | 11562 */ |
11556 » exprOp = &ctxt->comp->steps[op->ch2];» | 11563 » exprOp = &ctxt->comp->steps[op->ch2]; |
11557 newContextSize = 0; | 11564 newContextSize = 0; |
11558 for (i = 0; i < set->nodeNr; i++) { | 11565 for (i = 0; i < set->nodeNr; i++) { |
11559 if (set->nodeTab[i] == NULL) | 11566 if (set->nodeTab[i] == NULL) |
11560 continue; | 11567 continue; |
11561 | 11568 |
11562 contextNode = set->nodeTab[i]; | 11569 contextNode = set->nodeTab[i]; |
11563 xpctxt->node = contextNode; | 11570 xpctxt->node = contextNode; |
11564 xpctxt->contextSize = contextSize; | 11571 xpctxt->contextSize = contextSize; |
11565 xpctxt->proximityPosition = ++contextPos; | 11572 xpctxt->proximityPosition = ++contextPos; |
11566 » | 11573 |
11567 » /*» | 11574 » /* |
11568 * Also set the xpath document in case things like | 11575 * Also set the xpath document in case things like |
11569 * key() are evaluated in the predicate. | 11576 * key() are evaluated in the predicate. |
11570 */ | 11577 */ |
11571 if ((contextNode->type != XML_NAMESPACE_DECL) && | 11578 if ((contextNode->type != XML_NAMESPACE_DECL) && |
11572 (contextNode->doc != NULL)) | 11579 (contextNode->doc != NULL)) |
11573 xpctxt->doc = contextNode->doc; | 11580 xpctxt->doc = contextNode->doc; |
11574 /* | 11581 /* |
11575 * Evaluate the predicate expression with 1 context node | 11582 * Evaluate the predicate expression with 1 context node |
11576 * at a time; this node is packaged into a node set; this | 11583 * at a time; this node is packaged into a node set; this |
11577 * node set is handed over to the evaluation mechanism. | 11584 * node set is handed over to the evaluation mechanism. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11616 * Can this happen? Maybe in internal-error cases. | 11623 * Can this happen? Maybe in internal-error cases. |
11617 */ | 11624 */ |
11618 contextObj = NULL; | 11625 contextObj = NULL; |
11619 } | 11626 } |
11620 } | 11627 } |
11621 | 11628 |
11622 if (contextObj != NULL) { | 11629 if (contextObj != NULL) { |
11623 if (ctxt->value == contextObj) | 11630 if (ctxt->value == contextObj) |
11624 valuePop(ctxt); | 11631 valuePop(ctxt); |
11625 xmlXPathReleaseObject(xpctxt, contextObj); | 11632 xmlXPathReleaseObject(xpctxt, contextObj); |
11626 » }» | 11633 » } |
11627 evaluation_exit: | 11634 evaluation_exit: |
11628 if (exprRes != NULL) | 11635 if (exprRes != NULL) |
11629 xmlXPathReleaseObject(ctxt->context, exprRes); | 11636 xmlXPathReleaseObject(ctxt->context, exprRes); |
11630 /* | 11637 /* |
11631 * Reset/invalidate the context. | 11638 * Reset/invalidate the context. |
11632 */ | 11639 */ |
11633 xpctxt->node = oldContextNode; | 11640 xpctxt->node = oldContextNode; |
11634 xpctxt->doc = oldContextDoc; | 11641 xpctxt->doc = oldContextDoc; |
11635 xpctxt->contextSize = -1; | 11642 xpctxt->contextSize = -1; |
11636 xpctxt->proximityPosition = -1; | 11643 xpctxt->proximityPosition = -1; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11700 */ | 11707 */ |
11701 exprOp = &ctxt->comp->steps[op->ch2]; | 11708 exprOp = &ctxt->comp->steps[op->ch2]; |
11702 for (i = 0; i < set->nodeNr; i++) { | 11709 for (i = 0; i < set->nodeNr; i++) { |
11703 if (set->nodeTab[i] == NULL) | 11710 if (set->nodeTab[i] == NULL) |
11704 continue; | 11711 continue; |
11705 | 11712 |
11706 contextNode = set->nodeTab[i]; | 11713 contextNode = set->nodeTab[i]; |
11707 xpctxt->node = contextNode; | 11714 xpctxt->node = contextNode; |
11708 xpctxt->contextSize = contextSize; | 11715 xpctxt->contextSize = contextSize; |
11709 xpctxt->proximityPosition = ++contextPos; | 11716 xpctxt->proximityPosition = ++contextPos; |
11710 » | 11717 |
11711 /* | 11718 /* |
11712 * Initialize the new set. | 11719 * Initialize the new set. |
11713 * Also set the xpath document in case things like | 11720 * Also set the xpath document in case things like |
11714 * key() evaluation are attempted on the predicate | 11721 * key() evaluation are attempted on the predicate |
11715 */ | 11722 */ |
11716 if ((contextNode->type != XML_NAMESPACE_DECL) && | 11723 if ((contextNode->type != XML_NAMESPACE_DECL) && |
11717 (contextNode->doc != NULL)) | 11724 (contextNode->doc != NULL)) |
11718 xpctxt->doc = contextNode->doc; | 11725 xpctxt->doc = contextNode->doc; |
11719 /* | 11726 /* |
11720 * Evaluate the predicate expression with 1 context node | 11727 * Evaluate the predicate expression with 1 context node |
11721 * at a time; this node is packaged into a node set; this | 11728 * at a time; this node is packaged into a node set; this |
11722 * node set is handed over to the evaluation mechanism. | 11729 * node set is handed over to the evaluation mechanism. |
11723 */ | 11730 */ |
11724 if (contextObj == NULL) | 11731 if (contextObj == NULL) |
11725 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); | 11732 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); |
11726 else | 11733 else |
11727 xmlXPathNodeSetAddUnique(contextObj->nodesetval, | 11734 xmlXPathNodeSetAddUnique(contextObj->nodesetval, |
11728 contextNode); | 11735 contextNode); |
11729 | 11736 |
11730 valuePush(ctxt, contextObj); | 11737 valuePush(ctxt, contextObj); |
11731 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); | 11738 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); |
11732 » | 11739 |
11733 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { | 11740 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { |
11734 xmlXPathObjectPtr tmp; | 11741 xmlXPathObjectPtr tmp; |
11735 /* pop the result */ | 11742 /* pop the result */ |
11736 tmp = valuePop(ctxt); | 11743 tmp = valuePop(ctxt); |
11737 xmlXPathReleaseObject(xpctxt, tmp); | 11744 xmlXPathReleaseObject(xpctxt, tmp); |
11738 /* then pop off contextObj, which will be freed later */ | 11745 /* then pop off contextObj, which will be freed later */ |
11739 valuePop(ctxt); | 11746 valuePop(ctxt); |
11740 goto evaluation_error; | 11747 goto evaluation_error; |
11741 } | 11748 } |
11742 | 11749 |
(...skipping 11 matching lines...) Expand all Loading... |
11754 */ | 11761 */ |
11755 if (contextNode->type == XML_NAMESPACE_DECL) { | 11762 if (contextNode->type == XML_NAMESPACE_DECL) { |
11756 /* | 11763 /* |
11757 * As always: take care of those nasty | 11764 * As always: take care of those nasty |
11758 * namespace nodes. | 11765 * namespace nodes. |
11759 */ | 11766 */ |
11760 set->nodeTab[i] = NULL; | 11767 set->nodeTab[i] = NULL; |
11761 } | 11768 } |
11762 xmlXPathNodeSetClear(set, hasNsNodes); | 11769 xmlXPathNodeSetClear(set, hasNsNodes); |
11763 set->nodeNr = 1; | 11770 set->nodeNr = 1; |
11764 » » set->nodeTab[0] = contextNode;» » | 11771 » » set->nodeTab[0] = contextNode; |
11765 goto evaluation_exit; | 11772 goto evaluation_exit; |
11766 » » }» » | 11773 » » } |
11767 if (pos == maxPos) { | 11774 if (pos == maxPos) { |
11768 /* | 11775 /* |
11769 * We are done. | 11776 * We are done. |
11770 */ | 11777 */ |
11771 xmlXPathNodeSetClearFromPos(set, i +1, hasNsNodes); | 11778 xmlXPathNodeSetClearFromPos(set, i +1, hasNsNodes); |
11772 goto evaluation_exit; | 11779 goto evaluation_exit; |
11773 } | 11780 } |
11774 } else { | 11781 } else { |
11775 /* | 11782 /* |
11776 * Remove the entry from the initial node set. | 11783 * Remove the entry from the initial node set. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11820 xpctxt->doc = oldContextDoc; | 11827 xpctxt->doc = oldContextDoc; |
11821 xpctxt->contextSize = -1; | 11828 xpctxt->contextSize = -1; |
11822 xpctxt->proximityPosition = -1; | 11829 xpctxt->proximityPosition = -1; |
11823 return(newContextSize); | 11830 return(newContextSize); |
11824 } | 11831 } |
11825 return(contextSize); | 11832 return(contextSize); |
11826 } | 11833 } |
11827 | 11834 |
11828 static int | 11835 static int |
11829 xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt, | 11836 xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt, |
11830 » » » xmlXPathStepOpPtr op,» » » | 11837 » » » xmlXPathStepOpPtr op, |
11831 int *maxPos) | 11838 int *maxPos) |
11832 { | 11839 { |
11833 | 11840 |
11834 xmlXPathStepOpPtr exprOp; | 11841 xmlXPathStepOpPtr exprOp; |
11835 | 11842 |
11836 /* | 11843 /* |
11837 * BIG NOTE: This is not intended for XPATH_OP_FILTER yet! | 11844 * BIG NOTE: This is not intended for XPATH_OP_FILTER yet! |
11838 */ | 11845 */ |
11839 | 11846 |
11840 /* | 11847 /* |
11841 * If not -1, then ch1 will point to: | 11848 * If not -1, then ch1 will point to: |
11842 * 1) For predicates (XPATH_OP_PREDICATE): | 11849 * 1) For predicates (XPATH_OP_PREDICATE): |
11843 * - an inner predicate operator | 11850 * - an inner predicate operator |
11844 * 2) For filters (XPATH_OP_FILTER): | 11851 * 2) For filters (XPATH_OP_FILTER): |
11845 * - an inner filter operater OR | 11852 * - an inner filter operater OR |
11846 * - an expression selecting the node set. | 11853 * - an expression selecting the node set. |
11847 * E.g. "key('a', 'b')" or "(//foo | //bar)". | 11854 * E.g. "key('a', 'b')" or "(//foo | //bar)". |
11848 */ | 11855 */ |
11849 if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER)) | 11856 if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER)) |
11850 return(0); | 11857 return(0); |
11851 | 11858 |
11852 if (op->ch2 != -1) { | 11859 if (op->ch2 != -1) { |
11853 exprOp = &ctxt->comp->steps[op->ch2]; | 11860 exprOp = &ctxt->comp->steps[op->ch2]; |
11854 } else» | 11861 } else |
11855 return(0); | 11862 return(0); |
11856 | 11863 |
11857 if ((exprOp != NULL) && | 11864 if ((exprOp != NULL) && |
11858 (exprOp->op == XPATH_OP_VALUE) && | 11865 (exprOp->op == XPATH_OP_VALUE) && |
11859 (exprOp->value4 != NULL) && | 11866 (exprOp->value4 != NULL) && |
11860 (((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER)) | 11867 (((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER)) |
11861 { | 11868 { |
11862 /* | 11869 /* |
11863 * We have a "[n]" predicate here. | 11870 * We have a "[n]" predicate here. |
11864 * TODO: Unfortunately this simplistic test here is not | 11871 * TODO: Unfortunately this simplistic test here is not |
11865 * able to detect a position() predicate in compound | 11872 * able to detect a position() predicate in compound |
11866 * expressions like "[@attr = 'a" and position() = 1], | 11873 * expressions like "[@attr = 'a" and position() = 1], |
11867 * and even not the usage of position() in | 11874 * and even not the usage of position() in |
11868 * "[position() = 1]"; thus - obviously - a position-range, | 11875 * "[position() = 1]"; thus - obviously - a position-range, |
11869 * like it "[position() < 5]", is also not detected. | 11876 * like it "[position() < 5]", is also not detected. |
11870 * Maybe we could rewrite the AST to ease the optimization. | 11877 * Maybe we could rewrite the AST to ease the optimization. |
11871 */ | 11878 */ |
11872 *maxPos = (int) ((xmlXPathObjectPtr) exprOp->value4)->floatval; | 11879 *maxPos = (int) ((xmlXPathObjectPtr) exprOp->value4)->floatval; |
11873 » | 11880 |
11874 if (((xmlXPathObjectPtr) exprOp->value4)->floatval == | 11881 if (((xmlXPathObjectPtr) exprOp->value4)->floatval == |
11875 (float) *maxPos) | 11882 (float) *maxPos) |
11876 » {» | 11883 » { |
11877 return(1); | 11884 return(1); |
11878 } | 11885 } |
11879 } | 11886 } |
11880 return(0); | 11887 return(0); |
11881 } | 11888 } |
11882 | 11889 |
11883 static int | 11890 static int |
11884 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, | 11891 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, |
11885 xmlXPathStepOpPtr op, | 11892 xmlXPathStepOpPtr op, |
11886 xmlNodePtr * first, xmlNodePtr * last, | 11893 xmlNodePtr * first, xmlNodePtr * last, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11927 xmlNodePtr contextNode; | 11934 xmlNodePtr contextNode; |
11928 /* The context node for a compound traversal */ | 11935 /* The context node for a compound traversal */ |
11929 xmlNodePtr outerContextNode; | 11936 xmlNodePtr outerContextNode; |
11930 /* The final resulting node set wrt to all context nodes */ | 11937 /* The final resulting node set wrt to all context nodes */ |
11931 xmlNodeSetPtr outSeq; | 11938 xmlNodeSetPtr outSeq; |
11932 /* | 11939 /* |
11933 * The temporary resulting node set wrt 1 context node. | 11940 * The temporary resulting node set wrt 1 context node. |
11934 * Used to feed predicate evaluation. | 11941 * Used to feed predicate evaluation. |
11935 */ | 11942 */ |
11936 xmlNodeSetPtr seq; | 11943 xmlNodeSetPtr seq; |
11937 xmlNodePtr cur; | 11944 xmlNodePtr cur; |
11938 /* First predicate operator */ | 11945 /* First predicate operator */ |
11939 xmlXPathStepOpPtr predOp; | 11946 xmlXPathStepOpPtr predOp; |
11940 int maxPos; /* The requested position() (when a "[n]" predicate) */ | 11947 int maxPos; /* The requested position() (when a "[n]" predicate) */ |
11941 int hasPredicateRange, hasAxisRange, pos, size, newSize; | 11948 int hasPredicateRange, hasAxisRange, pos, size, newSize; |
11942 int breakOnFirstHit; | 11949 int breakOnFirstHit; |
11943 | 11950 |
11944 xmlXPathTraversalFunction next = NULL; | 11951 xmlXPathTraversalFunction next = NULL; |
11945 /* compound axis traversal */ | 11952 /* compound axis traversal */ |
11946 xmlXPathTraversalFunctionExt outerNext = NULL; | 11953 xmlXPathTraversalFunctionExt outerNext = NULL; |
11947 void (*addNode) (xmlNodeSetPtr, xmlNodePtr); | 11954 void (*addNode) (xmlNodeSetPtr, xmlNodePtr); |
11948 xmlXPathNodeSetMergeFunction mergeAndClear; | 11955 xmlXPathNodeSetMergeFunction mergeAndClear; |
11949 xmlNodePtr oldContextNode; | 11956 xmlNodePtr oldContextNode; |
11950 xmlXPathContextPtr xpctxt = ctxt->context; | 11957 xmlXPathContextPtr xpctxt = ctxt->context; |
11951 | 11958 |
11952 | 11959 |
11953 CHECK_TYPE0(XPATH_NODESET); | 11960 CHECK_TYPE0(XPATH_NODESET); |
11954 obj = valuePop(ctxt); | 11961 obj = valuePop(ctxt); |
11955 /* | 11962 /* |
11956 * Setup namespaces. | 11963 * Setup namespaces. |
11957 */ | 11964 */ |
11958 if (prefix != NULL) { | 11965 if (prefix != NULL) { |
11959 URI = xmlXPathNsLookup(xpctxt, prefix); | 11966 URI = xmlXPathNsLookup(xpctxt, prefix); |
11960 if (URI == NULL) { | 11967 if (URI == NULL) { |
11961 xmlXPathReleaseObject(xpctxt, obj); | 11968 xmlXPathReleaseObject(xpctxt, obj); |
11962 XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR); | 11969 XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR); |
11963 } | 11970 } |
11964 } | 11971 } |
11965 /* | 11972 /* |
11966 * Setup axis. | 11973 * Setup axis. |
11967 * | 11974 * |
11968 * MAYBE FUTURE TODO: merging optimizations: | 11975 * MAYBE FUTURE TODO: merging optimizations: |
11969 * - If the nodes to be traversed wrt to the initial nodes and | 11976 * - If the nodes to be traversed wrt to the initial nodes and |
11970 * the current axis cannot overlap, then we could avoid searching | 11977 * the current axis cannot overlap, then we could avoid searching |
11971 * for duplicates during the merge. | 11978 * for duplicates during the merge. |
11972 * But the question is how/when to evaluate if they cannot overlap. | 11979 * But the question is how/when to evaluate if they cannot overlap. |
11973 * Example: if we know that for two initial nodes, the one is | 11980 * Example: if we know that for two initial nodes, the one is |
11974 * not in the ancestor-or-self axis of the other, then we could safely | 11981 * not in the ancestor-or-self axis of the other, then we could safely |
11975 * avoid a duplicate-aware merge, if the axis to be traversed is e.g. | 11982 * avoid a duplicate-aware merge, if the axis to be traversed is e.g. |
11976 * the descendant-or-self axis. | 11983 * the descendant-or-self axis. |
11977 */ | 11984 */ |
11978 addNode = xmlXPathNodeSetAdd; | |
11979 mergeAndClear = xmlXPathNodeSetMergeAndClear; | 11985 mergeAndClear = xmlXPathNodeSetMergeAndClear; |
11980 switch (axis) { | 11986 switch (axis) { |
11981 case AXIS_ANCESTOR: | 11987 case AXIS_ANCESTOR: |
11982 first = NULL; | 11988 first = NULL; |
11983 next = xmlXPathNextAncestor; | 11989 next = xmlXPathNextAncestor; |
11984 break; | 11990 break; |
11985 case AXIS_ANCESTOR_OR_SELF: | 11991 case AXIS_ANCESTOR_OR_SELF: |
11986 first = NULL; | 11992 first = NULL; |
11987 next = xmlXPathNextAncestorOrSelf; | 11993 next = xmlXPathNextAncestorOrSelf; |
11988 break; | 11994 break; |
11989 case AXIS_ATTRIBUTE: | 11995 case AXIS_ATTRIBUTE: |
11990 first = NULL; | 11996 first = NULL; |
11991 last = NULL; | 11997 last = NULL; |
11992 next = xmlXPathNextAttribute; | 11998 next = xmlXPathNextAttribute; |
11993 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; | 11999 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; |
11994 break; | 12000 break; |
11995 case AXIS_CHILD: | 12001 case AXIS_CHILD: |
11996 last = NULL; | 12002 last = NULL; |
11997 if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) { | 12003 if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) { |
11998 /* | 12004 /* |
11999 * This iterator will give us only nodes which can | 12005 * This iterator will give us only nodes which can |
12000 * hold element nodes. | 12006 * hold element nodes. |
12001 */ | 12007 */ |
12002 » » outerNext = xmlXPathNextDescendantOrSelfElemParent;» » | 12008 » » outerNext = xmlXPathNextDescendantOrSelfElemParent; |
12003 » }» | 12009 » } |
12004 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) && | 12010 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) && |
12005 (type == NODE_TYPE_NODE)) | 12011 (type == NODE_TYPE_NODE)) |
12006 { | 12012 { |
12007 /* | 12013 /* |
12008 * Optimization if an element node type is 'element'. | 12014 * Optimization if an element node type is 'element'. |
12009 */ | 12015 */ |
12010 next = xmlXPathNextChildElement; | 12016 next = xmlXPathNextChildElement; |
12011 } else | 12017 } else |
12012 next = xmlXPathNextChild; | 12018 next = xmlXPathNextChild; |
12013 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; | 12019 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12048 break; | 12054 break; |
12049 case AXIS_SELF: | 12055 case AXIS_SELF: |
12050 first = NULL; | 12056 first = NULL; |
12051 last = NULL; | 12057 last = NULL; |
12052 next = xmlXPathNextSelf; | 12058 next = xmlXPathNextSelf; |
12053 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; | 12059 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; |
12054 break; | 12060 break; |
12055 } | 12061 } |
12056 | 12062 |
12057 #ifdef DEBUG_STEP | 12063 #ifdef DEBUG_STEP |
12058 xmlXPathDebugDumpStepAxis(axis, test, | 12064 xmlXPathDebugDumpStepAxis(op, |
12059 » (obj->nodesetval != NULL) ? obj->nodsetval->nodeNr : 0); | 12065 » (obj->nodesetval != NULL) ? obj->nodesetval->nodeNr : 0); |
12060 #endif | 12066 #endif |
12061 | 12067 |
12062 if (next == NULL) { | 12068 if (next == NULL) { |
12063 » xmlXPathReleaseObject(xpctxt, obj); | 12069 » xmlXPathReleaseObject(xpctxt, obj); |
12064 return(0); | 12070 return(0); |
12065 } | 12071 } |
12066 contextSeq = obj->nodesetval; | 12072 contextSeq = obj->nodesetval; |
12067 if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) { | 12073 if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) { |
12068 xmlXPathReleaseObject(xpctxt, obj); | 12074 xmlXPathReleaseObject(xpctxt, obj); |
12069 valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, NULL)); | 12075 valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, NULL)); |
12070 return(0); | 12076 return(0); |
12071 } | 12077 } |
12072 /* | 12078 /* |
12073 * Predicate optimization --------------------------------------------- | 12079 * Predicate optimization --------------------------------------------- |
12074 * If this step has a last predicate, which contains a position(), | 12080 * If this step has a last predicate, which contains a position(), |
12075 * then we'll optimize (although not exactly "position()", but only | 12081 * then we'll optimize (although not exactly "position()", but only |
12076 * the short-hand form, i.e., "[n]". | 12082 * the short-hand form, i.e., "[n]". |
12077 * | 12083 * |
12078 * Example - expression "/foo[parent::bar][1]": | 12084 * Example - expression "/foo[parent::bar][1]": |
12079 * | 12085 * |
12080 * COLLECT 'child' 'name' 'node' foo -- op (we are here) | 12086 * COLLECT 'child' 'name' 'node' foo -- op (we are here) |
12081 * ROOT -- op->ch1 | 12087 * ROOT -- op->ch1 |
12082 * PREDICATE -- op->ch2 (predOp) | 12088 * PREDICATE -- op->ch2 (predOp) |
12083 * PREDICATE -- predOp->ch1 = [parent::bar] | 12089 * PREDICATE -- predOp->ch1 = [parent::bar] |
12084 * SORT | 12090 * SORT |
12085 * COLLECT 'parent' 'name' 'node' bar | 12091 * COLLECT 'parent' 'name' 'node' bar |
12086 * NODE | 12092 * NODE |
12087 * ELEM Object is a number : 1 -- predOp->ch2 = [1] | 12093 * ELEM Object is a number : 1 -- predOp->ch2 = [1] |
12088 * | 12094 * |
12089 */ | 12095 */ |
(...skipping 12 matching lines...) Expand all Loading... |
12102 * Use the next inner predicate operator. | 12108 * Use the next inner predicate operator. |
12103 */ | 12109 */ |
12104 predOp = &ctxt->comp->steps[predOp->ch1]; | 12110 predOp = &ctxt->comp->steps[predOp->ch1]; |
12105 hasPredicateRange = 1; | 12111 hasPredicateRange = 1; |
12106 } else { | 12112 } else { |
12107 /* | 12113 /* |
12108 * There's no other predicate than the [n] predicate. | 12114 * There's no other predicate than the [n] predicate. |
12109 */ | 12115 */ |
12110 predOp = NULL; | 12116 predOp = NULL; |
12111 hasAxisRange = 1; | 12117 hasAxisRange = 1; |
12112 » }» | 12118 » } |
12113 } | 12119 } |
12114 } | 12120 } |
12115 breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0; | 12121 breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0; |
12116 /* | 12122 /* |
12117 * Axis traversal ----------------------------------------------------- | 12123 * Axis traversal ----------------------------------------------------- |
12118 */ | 12124 */ |
12119 /* | 12125 /* |
12120 * 2.3 Node Tests | 12126 * 2.3 Node Tests |
12121 * - For the attribute axis, the principal node type is attribute. | 12127 * - For the attribute axis, the principal node type is attribute. |
12122 * - For the namespace axis, the principal node type is namespace. | 12128 * - For the namespace axis, the principal node type is namespace. |
12123 * - For other axes, the principal node type is element. | 12129 * - For other axes, the principal node type is element. |
12124 * | 12130 * |
12125 * A node test * is true for any node of the | 12131 * A node test * is true for any node of the |
12126 * principal node type. For example, child::* will | 12132 * principal node type. For example, child::* will |
12127 * select all element children of the context node | 12133 * select all element children of the context node |
12128 */ | 12134 */ |
12129 oldContextNode = xpctxt->node; | 12135 oldContextNode = xpctxt->node; |
12130 addNode = xmlXPathNodeSetAddUnique; | 12136 addNode = xmlXPathNodeSetAddUnique; |
12131 outSeq = NULL; | 12137 outSeq = NULL; |
(...skipping 16 matching lines...) Expand all Loading... |
12148 contextNode = outerNext(NULL, outerContextNode); | 12154 contextNode = outerNext(NULL, outerContextNode); |
12149 } else | 12155 } else |
12150 contextNode = outerNext(contextNode, outerContextNode); | 12156 contextNode = outerNext(contextNode, outerContextNode); |
12151 if (contextNode == NULL) | 12157 if (contextNode == NULL) |
12152 continue; | 12158 continue; |
12153 /* | 12159 /* |
12154 * Set the context for the main traversal. | 12160 * Set the context for the main traversal. |
12155 */ | 12161 */ |
12156 xpctxt->node = contextNode; | 12162 xpctxt->node = contextNode; |
12157 } else | 12163 } else |
12158 » xpctxt->node = contextSeq->nodeTab[contextIdx++];» | 12164 » xpctxt->node = contextSeq->nodeTab[contextIdx++]; |
12159 | 12165 |
12160 if (seq == NULL) { | 12166 if (seq == NULL) { |
12161 seq = xmlXPathNodeSetCreate(NULL); | 12167 seq = xmlXPathNodeSetCreate(NULL); |
12162 if (seq == NULL) { | 12168 if (seq == NULL) { |
12163 total = 0; | 12169 total = 0; |
12164 goto error; | 12170 goto error; |
12165 } | 12171 } |
12166 } | 12172 } |
12167 /* | 12173 /* |
12168 * Traverse the axis and test the nodes. | 12174 * Traverse the axis and test the nodes. |
12169 */ | 12175 */ |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12203 { | 12209 { |
12204 break; | 12210 break; |
12205 } | 12211 } |
12206 } | 12212 } |
12207 | 12213 |
12208 total++; | 12214 total++; |
12209 | 12215 |
12210 #ifdef DEBUG_STEP | 12216 #ifdef DEBUG_STEP |
12211 xmlGenericError(xmlGenericErrorContext, " %s", cur->name); | 12217 xmlGenericError(xmlGenericErrorContext, " %s", cur->name); |
12212 #endif | 12218 #endif |
12213 | 12219 |
12214 switch (test) { | 12220 switch (test) { |
12215 case NODE_TEST_NONE: | 12221 case NODE_TEST_NONE: |
12216 total = 0; | 12222 total = 0; |
12217 STRANGE | 12223 STRANGE |
12218 goto error; | 12224 goto error; |
12219 case NODE_TEST_TYPE: | 12225 case NODE_TEST_TYPE: |
12220 /* | 12226 /* |
12221 * TODO: Don't we need to use | 12227 * TODO: Don't we need to use |
12222 * xmlXPathNodeSetAddNs() for namespace nodes here? | 12228 * xmlXPathNodeSetAddNs() for namespace nodes here? |
12223 * Surprisingly, some c14n tests fail, if we do this. | 12229 * Surprisingly, some c14n tests fail, if we do this. |
12224 */ | 12230 */ |
12225 if (type == NODE_TYPE_NODE) { | 12231 if (type == NODE_TYPE_NODE) { |
12226 switch (cur->type) { | 12232 switch (cur->type) { |
12227 case XML_DOCUMENT_NODE: | 12233 case XML_DOCUMENT_NODE: |
12228 case XML_HTML_DOCUMENT_NODE: | 12234 case XML_HTML_DOCUMENT_NODE: |
12229 #ifdef LIBXML_DOCB_ENABLED | 12235 #ifdef LIBXML_DOCB_ENABLED |
12230 case XML_DOCB_DOCUMENT_NODE: | 12236 case XML_DOCB_DOCUMENT_NODE: |
12231 #endif | 12237 #endif |
12232 » » » case XML_ELEMENT_NODE:» » » | 12238 » » » case XML_ELEMENT_NODE: |
12233 case XML_ATTRIBUTE_NODE: | 12239 case XML_ATTRIBUTE_NODE: |
12234 case XML_PI_NODE: | 12240 case XML_PI_NODE: |
12235 case XML_COMMENT_NODE: | 12241 case XML_COMMENT_NODE: |
12236 case XML_CDATA_SECTION_NODE: | 12242 case XML_CDATA_SECTION_NODE: |
12237 case XML_TEXT_NODE: | 12243 case XML_TEXT_NODE: |
12238 case XML_NAMESPACE_DECL: | 12244 case XML_NAMESPACE_DECL: |
12239 XP_TEST_HIT | 12245 XP_TEST_HIT |
12240 break; | 12246 break; |
12241 default: | 12247 default: |
12242 break; | 12248 break; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12350 break; | 12356 break; |
12351 default: | 12357 default: |
12352 break; | 12358 break; |
12353 } | 12359 } |
12354 break; | 12360 break; |
12355 } /* switch(test) */ | 12361 } /* switch(test) */ |
12356 } while (cur != NULL); | 12362 } while (cur != NULL); |
12357 | 12363 |
12358 goto apply_predicates; | 12364 goto apply_predicates; |
12359 | 12365 |
12360 axis_range_end: /* ----------------------------------------------------- */» | 12366 axis_range_end: /* ----------------------------------------------------- */ |
12361 /* | 12367 /* |
12362 * We have a "/foo[n]", and position() = n was reached. | 12368 * We have a "/foo[n]", and position() = n was reached. |
12363 * Note that we can have as well "/foo/::parent::foo[1]", so | 12369 * Note that we can have as well "/foo/::parent::foo[1]", so |
12364 * a duplicate-aware merge is still needed. | 12370 * a duplicate-aware merge is still needed. |
12365 * Merge with the result. | 12371 * Merge with the result. |
12366 */ | 12372 */ |
12367 if (outSeq == NULL) { | 12373 if (outSeq == NULL) { |
12368 outSeq = seq; | 12374 outSeq = seq; |
12369 seq = NULL; | 12375 seq = NULL; |
12370 } else | 12376 } else |
(...skipping 18 matching lines...) Expand all Loading... |
12389 break; | 12395 break; |
12390 | 12396 |
12391 #ifdef DEBUG_STEP | 12397 #ifdef DEBUG_STEP |
12392 if (seq != NULL) | 12398 if (seq != NULL) |
12393 nbMatches += seq->nodeNr; | 12399 nbMatches += seq->nodeNr; |
12394 #endif | 12400 #endif |
12395 | 12401 |
12396 apply_predicates: /* --------------------------------------------------- */ | 12402 apply_predicates: /* --------------------------------------------------- */ |
12397 /* | 12403 /* |
12398 * Apply predicates. | 12404 * Apply predicates. |
12399 » */» | 12405 » */ |
12400 if ((predOp != NULL) && (seq->nodeNr > 0)) { | 12406 if ((predOp != NULL) && (seq->nodeNr > 0)) { |
12401 /* | 12407 /* |
12402 * E.g. when we have a "/foo[some expression][n]". | 12408 * E.g. when we have a "/foo[some expression][n]". |
12403 » */» » | 12409 » */» |
12404 /* | 12410 /* |
12405 * QUESTION TODO: The old predicate evaluation took into | 12411 * QUESTION TODO: The old predicate evaluation took into |
12406 * account location-sets. | 12412 * account location-sets. |
12407 * (E.g. ctxt->value->type == XPATH_LOCATIONSET) | 12413 * (E.g. ctxt->value->type == XPATH_LOCATIONSET) |
12408 * Do we expect such a set here? | 12414 * Do we expect such a set here? |
12409 * All what I learned now from the evaluation semantics | 12415 * All what I learned now from the evaluation semantics |
12410 * does not indicate that a location-set will be processed | 12416 * does not indicate that a location-set will be processed |
12411 * here, so this looks OK. | 12417 * here, so this looks OK. |
12412 » */» » | 12418 » */» |
12413 /* | 12419 /* |
12414 * Iterate over all predicates, starting with the outermost | 12420 * Iterate over all predicates, starting with the outermost |
12415 * predicate. | 12421 * predicate. |
12416 * TODO: Problem: we cannot execute the inner predicates first | 12422 * TODO: Problem: we cannot execute the inner predicates first |
12417 * since we cannot go back *up* the operator tree! | 12423 * since we cannot go back *up* the operator tree! |
12418 * Options we have: | 12424 * Options we have: |
12419 * 1) Use of recursive functions (like is it currently done | 12425 * 1) Use of recursive functions (like is it currently done |
12420 * via xmlXPathCompOpEval()) | 12426 * via xmlXPathCompOpEval()) |
12421 * 2) Add a predicate evaluation information stack to the | 12427 * 2) Add a predicate evaluation information stack to the |
12422 * context struct | 12428 * context struct |
12423 * 3) Change the way the operators are linked; we need a | 12429 * 3) Change the way the operators are linked; we need a |
12424 * "parent" field on xmlXPathStepOp | 12430 * "parent" field on xmlXPathStepOp |
12425 * | 12431 * |
12426 * For the moment, I'll try to solve this with a recursive | 12432 * For the moment, I'll try to solve this with a recursive |
12427 * function: xmlXPathCompOpEvalPredicate(). | 12433 * function: xmlXPathCompOpEvalPredicate(). |
12428 » */» | 12434 » */ |
12429 size = seq->nodeNr; | 12435 size = seq->nodeNr; |
12430 if (hasPredicateRange != 0) | 12436 if (hasPredicateRange != 0) |
12431 newSize = xmlXPathCompOpEvalPositionalPredicate(ctxt, | 12437 newSize = xmlXPathCompOpEvalPositionalPredicate(ctxt, |
12432 predOp, seq, size, maxPos, maxPos, hasNsNodes); | 12438 predOp, seq, size, maxPos, maxPos, hasNsNodes); |
12433 else | 12439 else |
12434 newSize = xmlXPathCompOpEvalPredicate(ctxt, | 12440 newSize = xmlXPathCompOpEvalPredicate(ctxt, |
12435 predOp, seq, size, hasNsNodes); | 12441 predOp, seq, size, hasNsNodes); |
12436 | 12442 |
12437 if (ctxt->error != XPATH_EXPRESSION_OK) { | 12443 if (ctxt->error != XPATH_EXPRESSION_OK) { |
12438 total = 0; | 12444 total = 0; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12473 } else if (seq->nodeNr > 0) { | 12479 } else if (seq->nodeNr > 0) { |
12474 /* | 12480 /* |
12475 * Add to result set. | 12481 * Add to result set. |
12476 */ | 12482 */ |
12477 if (outSeq == NULL) { | 12483 if (outSeq == NULL) { |
12478 outSeq = seq; | 12484 outSeq = seq; |
12479 seq = NULL; | 12485 seq = NULL; |
12480 } else { | 12486 } else { |
12481 outSeq = mergeAndClear(outSeq, seq, 0); | 12487 outSeq = mergeAndClear(outSeq, seq, 0); |
12482 } | 12488 } |
12483 » }» | 12489 » } |
12484 } | 12490 } |
12485 | 12491 |
12486 error: | 12492 error: |
12487 if ((obj->boolval) && (obj->user != NULL)) { | 12493 if ((obj->boolval) && (obj->user != NULL)) { |
12488 /* | 12494 /* |
12489 * QUESTION TODO: What does this do and why? | 12495 * QUESTION TODO: What does this do and why? |
12490 * TODO: Do we have to do this also for the "error" | 12496 * TODO: Do we have to do this also for the "error" |
12491 * cleanup further down? | 12497 * cleanup further down? |
12492 */ | 12498 */ |
12493 ctxt->value->boolval = 1; | 12499 ctxt->value->boolval = 1; |
12494 ctxt->value->user = obj->user; | 12500 ctxt->value->user = obj->user; |
12495 obj->user = NULL; | 12501 obj->user = NULL; |
12496 obj->boolval = 0; | 12502 obj->boolval = 0; |
12497 } | 12503 } |
12498 xmlXPathReleaseObject(xpctxt, obj); | 12504 xmlXPathReleaseObject(xpctxt, obj); |
12499 | 12505 |
12500 /* | 12506 /* |
12501 * Ensure we return at least an emtpy set. | 12507 * Ensure we return at least an emtpy set. |
12502 */ | 12508 */ |
12503 if (outSeq == NULL) { | 12509 if (outSeq == NULL) { |
12504 if ((seq != NULL) && (seq->nodeNr == 0)) | 12510 if ((seq != NULL) && (seq->nodeNr == 0)) |
12505 outSeq = seq; | 12511 outSeq = seq; |
12506 else | 12512 else |
12507 outSeq = xmlXPathNodeSetCreate(NULL); | 12513 outSeq = xmlXPathNodeSetCreate(NULL); |
12508 /* XXX what if xmlXPathNodeSetCreate returned NULL here? */ | 12514 /* XXX what if xmlXPathNodeSetCreate returned NULL here? */ |
12509 } | 12515 } |
12510 if ((seq != NULL) && (seq != outSeq)) { | 12516 if ((seq != NULL) && (seq != outSeq)) { |
12511 xmlXPathFreeNodeSet(seq); | 12517 xmlXPathFreeNodeSet(seq); |
12512 } | 12518 } |
12513 /* | 12519 /* |
12514 * Hand over the result. Better to push the set also in | 12520 * Hand over the result. Better to push the set also in |
12515 * case of errors. | 12521 * case of errors. |
12516 */ | 12522 */ |
12517 valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, outSeq)); | 12523 valuePush(ctxt, xmlXPathCacheWrapNodeSet(xpctxt, outSeq)); |
12518 /* | 12524 /* |
12519 * Reset the context node. | 12525 * Reset the context node. |
12520 */ | 12526 */ |
12521 xpctxt->node = oldContextNode; | 12527 xpctxt->node = oldContextNode; |
12522 | 12528 |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12786 return (xmlXPathCompOpEval(ctxt, op)); | 12792 return (xmlXPathCompOpEval(ctxt, op)); |
12787 } | 12793 } |
12788 } | 12794 } |
12789 | 12795 |
12790 #ifdef XP_OPTIMIZED_FILTER_FIRST | 12796 #ifdef XP_OPTIMIZED_FILTER_FIRST |
12791 static int | 12797 static int |
12792 xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt, | 12798 xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt, |
12793 xmlXPathStepOpPtr op, xmlNodePtr * first) | 12799 xmlXPathStepOpPtr op, xmlNodePtr * first) |
12794 { | 12800 { |
12795 int total = 0; | 12801 int total = 0; |
12796 xmlXPathCompExprPtr comp; | 12802 xmlXPathCompExprPtr comp; |
12797 xmlXPathObjectPtr res; | 12803 xmlXPathObjectPtr res; |
12798 xmlXPathObjectPtr obj; | 12804 xmlXPathObjectPtr obj; |
12799 xmlNodeSetPtr oldset; | 12805 xmlNodeSetPtr oldset; |
12800 xmlNodePtr oldnode; | 12806 xmlNodePtr oldnode; |
12801 xmlDocPtr oldDoc; | 12807 xmlDocPtr oldDoc; |
12802 int i; | 12808 int i; |
12803 | 12809 |
12804 CHECK_ERROR0; | 12810 CHECK_ERROR0; |
12805 comp = ctxt->comp; | 12811 comp = ctxt->comp; |
12806 /* | 12812 /* |
12807 * Optimization for ()[last()] selection i.e. the last elem | 12813 * Optimization for ()[last()] selection i.e. the last elem |
12808 */ | 12814 */ |
12809 if ((op->ch1 != -1) && (op->ch2 != -1) && | 12815 if ((op->ch1 != -1) && (op->ch2 != -1) && |
12810 (comp->steps[op->ch1].op == XPATH_OP_SORT) && | 12816 (comp->steps[op->ch1].op == XPATH_OP_SORT) && |
12811 (comp->steps[op->ch2].op == XPATH_OP_SORT)) { | 12817 (comp->steps[op->ch2].op == XPATH_OP_SORT)) { |
12812 int f = comp->steps[op->ch2].ch1; | 12818 int f = comp->steps[op->ch2].ch1; |
12813 » | 12819 |
12814 if ((f != -1) && | 12820 if ((f != -1) && |
12815 (comp->steps[f].op == XPATH_OP_FUNCTION) && | 12821 (comp->steps[f].op == XPATH_OP_FUNCTION) && |
12816 (comp->steps[f].value5 == NULL) && | 12822 (comp->steps[f].value5 == NULL) && |
12817 (comp->steps[f].value == 0) && | 12823 (comp->steps[f].value == 0) && |
12818 (comp->steps[f].value4 != NULL) && | 12824 (comp->steps[f].value4 != NULL) && |
12819 (xmlStrEqual | 12825 (xmlStrEqual |
12820 (comp->steps[f].value4, BAD_CAST "last"))) { | 12826 (comp->steps[f].value4, BAD_CAST "last"))) { |
12821 xmlNodePtr last = NULL; | 12827 xmlNodePtr last = NULL; |
12822 » | 12828 |
12823 total += | 12829 total += |
12824 xmlXPathCompOpEvalLast(ctxt, | 12830 xmlXPathCompOpEvalLast(ctxt, |
12825 &comp->steps[op->ch1], | 12831 &comp->steps[op->ch1], |
12826 &last); | 12832 &last); |
12827 CHECK_ERROR0; | 12833 CHECK_ERROR0; |
12828 /* | 12834 /* |
12829 * The nodeset should be in document order, | 12835 * The nodeset should be in document order, |
12830 * Keep only the last value | 12836 * Keep only the last value |
12831 */ | 12837 */ |
12832 if ((ctxt->value != NULL) && | 12838 if ((ctxt->value != NULL) && |
12833 (ctxt->value->type == XPATH_NODESET) && | 12839 (ctxt->value->type == XPATH_NODESET) && |
12834 (ctxt->value->nodesetval != NULL) && | 12840 (ctxt->value->nodesetval != NULL) && |
12835 (ctxt->value->nodesetval->nodeTab != NULL) && | 12841 (ctxt->value->nodesetval->nodeTab != NULL) && |
12836 (ctxt->value->nodesetval->nodeNr > 1)) { | 12842 (ctxt->value->nodesetval->nodeNr > 1)) { |
12837 ctxt->value->nodesetval->nodeTab[0] = | 12843 ctxt->value->nodesetval->nodeTab[0] = |
12838 ctxt->value->nodesetval->nodeTab[ctxt-> | 12844 ctxt->value->nodesetval->nodeTab[ctxt-> |
12839 value-> | 12845 value-> |
12840 nodesetval-> | 12846 nodesetval-> |
12841 nodeNr - | 12847 nodeNr - |
12842 1]; | 12848 1]; |
12843 ctxt->value->nodesetval->nodeNr = 1; | 12849 ctxt->value->nodesetval->nodeNr = 1; |
12844 *first = *(ctxt->value->nodesetval->nodeTab); | 12850 *first = *(ctxt->value->nodesetval->nodeTab); |
12845 } | 12851 } |
12846 return (total); | 12852 return (total); |
12847 } | 12853 } |
12848 } | 12854 } |
12849 | 12855 |
12850 if (op->ch1 != -1) | 12856 if (op->ch1 != -1) |
12851 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); | 12857 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); |
12852 CHECK_ERROR0; | 12858 CHECK_ERROR0; |
12853 if (op->ch2 == -1) | 12859 if (op->ch2 == -1) |
12854 return (total); | 12860 return (total); |
12855 if (ctxt->value == NULL) | 12861 if (ctxt->value == NULL) |
12856 return (total); | 12862 return (total); |
12857 | 12863 |
12858 #ifdef LIBXML_XPTR_ENABLED | 12864 #ifdef LIBXML_XPTR_ENABLED |
12859 oldnode = ctxt->context->node; | 12865 oldnode = ctxt->context->node; |
12860 /* | 12866 /* |
12861 * Hum are we filtering the result of an XPointer expression | 12867 * Hum are we filtering the result of an XPointer expression |
12862 */ | 12868 */ |
12863 if (ctxt->value->type == XPATH_LOCATIONSET) { | 12869 if (ctxt->value->type == XPATH_LOCATIONSET) { |
12864 xmlXPathObjectPtr tmp = NULL; | 12870 xmlXPathObjectPtr tmp = NULL; |
12865 xmlLocationSetPtr newlocset = NULL; | 12871 xmlLocationSetPtr newlocset = NULL; |
12866 xmlLocationSetPtr oldlocset; | 12872 xmlLocationSetPtr oldlocset; |
12867 » | 12873 |
12868 /* | 12874 /* |
12869 * Extract the old locset, and then evaluate the result of the | 12875 * Extract the old locset, and then evaluate the result of the |
12870 * expression for all the element in the locset. use it to grow | 12876 * expression for all the element in the locset. use it to grow |
12871 * up a new locset. | 12877 * up a new locset. |
12872 */ | 12878 */ |
12873 CHECK_TYPE0(XPATH_LOCATIONSET); | 12879 CHECK_TYPE0(XPATH_LOCATIONSET); |
12874 obj = valuePop(ctxt); | 12880 obj = valuePop(ctxt); |
12875 oldlocset = obj->user; | 12881 oldlocset = obj->user; |
12876 ctxt->context->node = NULL; | 12882 ctxt->context->node = NULL; |
12877 » | 12883 |
12878 if ((oldlocset == NULL) || (oldlocset->locNr == 0)) { | 12884 if ((oldlocset == NULL) || (oldlocset->locNr == 0)) { |
12879 ctxt->context->contextSize = 0; | 12885 ctxt->context->contextSize = 0; |
12880 ctxt->context->proximityPosition = 0; | 12886 ctxt->context->proximityPosition = 0; |
12881 if (op->ch2 != -1) | 12887 if (op->ch2 != -1) |
12882 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 12888 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
12883 res = valuePop(ctxt); | 12889 res = valuePop(ctxt); |
12884 if (res != NULL) { | 12890 if (res != NULL) { |
12885 xmlXPathReleaseObject(ctxt->context, res); | 12891 xmlXPathReleaseObject(ctxt->context, res); |
12886 } | 12892 } |
12887 valuePush(ctxt, obj); | 12893 valuePush(ctxt, obj); |
12888 CHECK_ERROR0; | 12894 CHECK_ERROR0; |
12889 return (total); | 12895 return (total); |
12890 } | 12896 } |
12891 newlocset = xmlXPtrLocationSetCreate(NULL); | 12897 newlocset = xmlXPtrLocationSetCreate(NULL); |
12892 » | 12898 |
12893 for (i = 0; i < oldlocset->locNr; i++) { | 12899 for (i = 0; i < oldlocset->locNr; i++) { |
12894 /* | 12900 /* |
12895 * Run the evaluation with a node list made of a | 12901 * Run the evaluation with a node list made of a |
12896 * single item in the nodelocset. | 12902 * single item in the nodelocset. |
12897 */ | 12903 */ |
12898 ctxt->context->node = oldlocset->locTab[i]->user; | 12904 ctxt->context->node = oldlocset->locTab[i]->user; |
12899 ctxt->context->contextSize = oldlocset->locNr; | 12905 ctxt->context->contextSize = oldlocset->locNr; |
12900 ctxt->context->proximityPosition = i + 1; | 12906 ctxt->context->proximityPosition = i + 1; |
12901 if (tmp == NULL) { | 12907 if (tmp == NULL) { |
12902 tmp = xmlXPathCacheNewNodeSet(ctxt->context, | 12908 tmp = xmlXPathCacheNewNodeSet(ctxt->context, |
12903 ctxt->context->node); | 12909 ctxt->context->node); |
12904 } else { | 12910 } else { |
12905 xmlXPathNodeSetAddUnique(tmp->nodesetval, | 12911 xmlXPathNodeSetAddUnique(tmp->nodesetval, |
12906 ctxt->context->node); | 12912 ctxt->context->node); |
12907 » }» | 12913 » } |
12908 valuePush(ctxt, tmp); | 12914 valuePush(ctxt, tmp); |
12909 if (op->ch2 != -1) | 12915 if (op->ch2 != -1) |
12910 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 12916 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
12911 if (ctxt->error != XPATH_EXPRESSION_OK) { | 12917 if (ctxt->error != XPATH_EXPRESSION_OK) { |
12912 xmlXPathFreeObject(obj); | 12918 xmlXPathFreeObject(obj); |
12913 return(0); | 12919 return(0); |
12914 } | 12920 } |
12915 /* | 12921 /* |
12916 * The result of the evaluation need to be tested to | 12922 * The result of the evaluation need to be tested to |
12917 * decided whether the filter succeeded or not | 12923 * decided whether the filter succeeded or not |
12918 */ | 12924 */ |
12919 res = valuePop(ctxt); | 12925 res = valuePop(ctxt); |
12920 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { | 12926 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { |
12921 xmlXPtrLocationSetAdd(newlocset, | 12927 xmlXPtrLocationSetAdd(newlocset, |
12922 xmlXPathCacheObjectCopy(ctxt->context, | 12928 xmlXPathCacheObjectCopy(ctxt->context, |
12923 oldlocset->locTab[i])); | 12929 oldlocset->locTab[i])); |
12924 } | 12930 } |
12925 /* | 12931 /* |
12926 * Cleanup | 12932 * Cleanup |
12927 */ | 12933 */ |
12928 if (res != NULL) { | 12934 if (res != NULL) { |
12929 xmlXPathReleaseObject(ctxt->context, res); | 12935 xmlXPathReleaseObject(ctxt->context, res); |
12930 } | 12936 } |
12931 if (ctxt->value == tmp) { | 12937 if (ctxt->value == tmp) { |
12932 valuePop(ctxt); | 12938 valuePop(ctxt); |
12933 » » xmlXPathNodeSetClear(tmp->nodesetval, 1);» » | 12939 » » xmlXPathNodeSetClear(tmp->nodesetval, 1); |
12934 /* | 12940 /* |
12935 * REVISIT TODO: Don't create a temporary nodeset | 12941 * REVISIT TODO: Don't create a temporary nodeset |
12936 * for everly iteration. | 12942 * for everly iteration. |
12937 */ | 12943 */ |
12938 /* OLD: xmlXPathFreeObject(res); */ | 12944 /* OLD: xmlXPathFreeObject(res); */ |
12939 } else | 12945 } else |
12940 » » tmp = NULL;» | 12946 » » tmp = NULL; |
12941 ctxt->context->node = NULL; | 12947 ctxt->context->node = NULL; |
12942 /* | 12948 /* |
12943 * Only put the first node in the result, then leave. | 12949 * Only put the first node in the result, then leave. |
12944 */ | 12950 */ |
12945 if (newlocset->locNr > 0) { | 12951 if (newlocset->locNr > 0) { |
12946 *first = (xmlNodePtr) oldlocset->locTab[i]->user; | 12952 *first = (xmlNodePtr) oldlocset->locTab[i]->user; |
12947 break; | 12953 break; |
12948 } | 12954 } |
12949 } | 12955 } |
12950 if (tmp != NULL) { | 12956 if (tmp != NULL) { |
12951 xmlXPathReleaseObject(ctxt->context, tmp); | 12957 xmlXPathReleaseObject(ctxt->context, tmp); |
12952 } | 12958 } |
12953 /* | 12959 /* |
12954 * The result is used as the new evaluation locset. | 12960 * The result is used as the new evaluation locset. |
12955 */ | 12961 */ |
12956 xmlXPathReleaseObject(ctxt->context, obj); | 12962 xmlXPathReleaseObject(ctxt->context, obj); |
12957 ctxt->context->node = NULL; | 12963 ctxt->context->node = NULL; |
12958 ctxt->context->contextSize = -1; | 12964 ctxt->context->contextSize = -1; |
12959 ctxt->context->proximityPosition = -1; | 12965 ctxt->context->proximityPosition = -1; |
12960 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); | 12966 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); |
12961 ctxt->context->node = oldnode; | 12967 ctxt->context->node = oldnode; |
12962 return (total); | 12968 return (total); |
12963 } | 12969 } |
12964 #endif /* LIBXML_XPTR_ENABLED */ | 12970 #endif /* LIBXML_XPTR_ENABLED */ |
12965 | 12971 |
12966 /* | 12972 /* |
12967 * Extract the old set, and then evaluate the result of the | 12973 * Extract the old set, and then evaluate the result of the |
12968 * expression for all the element in the set. use it to grow | 12974 * expression for all the element in the set. use it to grow |
12969 * up a new set. | 12975 * up a new set. |
12970 */ | 12976 */ |
12971 CHECK_TYPE0(XPATH_NODESET); | 12977 CHECK_TYPE0(XPATH_NODESET); |
12972 obj = valuePop(ctxt); | 12978 obj = valuePop(ctxt); |
12973 oldset = obj->nodesetval; | 12979 oldset = obj->nodesetval; |
12974 | 12980 |
12975 oldnode = ctxt->context->node; | 12981 oldnode = ctxt->context->node; |
12976 oldDoc = ctxt->context->doc; | 12982 oldDoc = ctxt->context->doc; |
12977 ctxt->context->node = NULL; | 12983 ctxt->context->node = NULL; |
12978 | 12984 |
12979 if ((oldset == NULL) || (oldset->nodeNr == 0)) { | 12985 if ((oldset == NULL) || (oldset->nodeNr == 0)) { |
12980 ctxt->context->contextSize = 0; | 12986 ctxt->context->contextSize = 0; |
12981 ctxt->context->proximityPosition = 0; | 12987 ctxt->context->proximityPosition = 0; |
12982 /* QUESTION TODO: Why was this code commented out? | 12988 /* QUESTION TODO: Why was this code commented out? |
12983 if (op->ch2 != -1) | 12989 if (op->ch2 != -1) |
12984 total += | 12990 total += |
12985 xmlXPathCompOpEval(ctxt, | 12991 xmlXPathCompOpEval(ctxt, |
12986 &comp->steps[op->ch2]); | 12992 &comp->steps[op->ch2]); |
12987 CHECK_ERROR0; | 12993 CHECK_ERROR0; |
12988 res = valuePop(ctxt); | 12994 res = valuePop(ctxt); |
12989 if (res != NULL) | 12995 if (res != NULL) |
12990 xmlXPathFreeObject(res); | 12996 xmlXPathFreeObject(res); |
12991 */ | 12997 */ |
12992 valuePush(ctxt, obj); | 12998 valuePush(ctxt, obj); |
12993 ctxt->context->node = oldnode; | 12999 ctxt->context->node = oldnode; |
12994 CHECK_ERROR0; | 13000 CHECK_ERROR0; |
12995 } else { | 13001 } else { |
12996 xmlNodeSetPtr newset; | 13002 xmlNodeSetPtr newset; |
12997 xmlXPathObjectPtr tmp = NULL; | 13003 xmlXPathObjectPtr tmp = NULL; |
12998 /* | 13004 /* |
12999 * Initialize the new set. | 13005 * Initialize the new set. |
13000 * Also set the xpath document in case things like | 13006 * Also set the xpath document in case things like |
13001 * key() evaluation are attempted on the predicate | 13007 * key() evaluation are attempted on the predicate |
13002 » */» | 13008 » */ |
13003 newset = xmlXPathNodeSetCreate(NULL); | 13009 newset = xmlXPathNodeSetCreate(NULL); |
13004 /* XXX what if xmlXPathNodeSetCreate returned NULL? */ | 13010 /* XXX what if xmlXPathNodeSetCreate returned NULL? */ |
13005 » | 13011 |
13006 for (i = 0; i < oldset->nodeNr; i++) { | 13012 for (i = 0; i < oldset->nodeNr; i++) { |
13007 /* | 13013 /* |
13008 * Run the evaluation with a node list made of | 13014 * Run the evaluation with a node list made of |
13009 * a single item in the nodeset. | 13015 * a single item in the nodeset. |
13010 */ | 13016 */ |
13011 ctxt->context->node = oldset->nodeTab[i]; | 13017 ctxt->context->node = oldset->nodeTab[i]; |
13012 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && | 13018 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && |
13013 (oldset->nodeTab[i]->doc != NULL)) | 13019 (oldset->nodeTab[i]->doc != NULL)) |
13014 ctxt->context->doc = oldset->nodeTab[i]->doc; | 13020 ctxt->context->doc = oldset->nodeTab[i]->doc; |
13015 if (tmp == NULL) { | 13021 if (tmp == NULL) { |
13016 tmp = xmlXPathCacheNewNodeSet(ctxt->context, | 13022 tmp = xmlXPathCacheNewNodeSet(ctxt->context, |
13017 ctxt->context->node); | 13023 ctxt->context->node); |
13018 } else { | 13024 } else { |
13019 xmlXPathNodeSetAddUnique(tmp->nodesetval, | 13025 xmlXPathNodeSetAddUnique(tmp->nodesetval, |
13020 ctxt->context->node); | 13026 ctxt->context->node); |
13021 } | 13027 } |
13022 valuePush(ctxt, tmp); | 13028 valuePush(ctxt, tmp); |
13023 ctxt->context->contextSize = oldset->nodeNr; | 13029 ctxt->context->contextSize = oldset->nodeNr; |
13024 ctxt->context->proximityPosition = i + 1; | 13030 ctxt->context->proximityPosition = i + 1; |
13025 if (op->ch2 != -1) | 13031 if (op->ch2 != -1) |
13026 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 13032 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
13027 if (ctxt->error != XPATH_EXPRESSION_OK) { | 13033 if (ctxt->error != XPATH_EXPRESSION_OK) { |
13028 xmlXPathFreeNodeSet(newset); | 13034 xmlXPathFreeNodeSet(newset); |
13029 xmlXPathFreeObject(obj); | 13035 xmlXPathFreeObject(obj); |
13030 return(0); | 13036 return(0); |
13031 » }» | 13037 » } |
13032 /* | 13038 /* |
13033 * The result of the evaluation needs to be tested to | 13039 * The result of the evaluation needs to be tested to |
13034 * decide whether the filter succeeded or not | 13040 * decide whether the filter succeeded or not |
13035 */ | 13041 */ |
13036 res = valuePop(ctxt); | 13042 res = valuePop(ctxt); |
13037 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { | 13043 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { |
13038 xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); | 13044 xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); |
13039 » }» | 13045 » } |
13040 /* | 13046 /* |
13041 * Cleanup | 13047 * Cleanup |
13042 */ | 13048 */ |
13043 if (res != NULL) { | 13049 if (res != NULL) { |
13044 xmlXPathReleaseObject(ctxt->context, res); | 13050 xmlXPathReleaseObject(ctxt->context, res); |
13045 } | 13051 } |
13046 if (ctxt->value == tmp) { | 13052 if (ctxt->value == tmp) { |
13047 valuePop(ctxt); | 13053 valuePop(ctxt); |
13048 /* | 13054 /* |
13049 * Don't free the temporary nodeset | 13055 * Don't free the temporary nodeset |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13165 cs = ctxt->context->contextSize; | 13171 cs = ctxt->context->contextSize; |
13166 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); | 13172 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); |
13167 CHECK_ERROR0; | 13173 CHECK_ERROR0; |
13168 ctxt->context->doc = bakd; | 13174 ctxt->context->doc = bakd; |
13169 ctxt->context->node = bak; | 13175 ctxt->context->node = bak; |
13170 ctxt->context->proximityPosition = pp; | 13176 ctxt->context->proximityPosition = pp; |
13171 ctxt->context->contextSize = cs; | 13177 ctxt->context->contextSize = cs; |
13172 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); | 13178 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); |
13173 CHECK_ERROR0; | 13179 CHECK_ERROR0; |
13174 if (op->value) | 13180 if (op->value) |
13175 » equal = xmlXPathEqualValues(ctxt); | 13181 » » equal = xmlXPathEqualValues(ctxt); |
13176 else | 13182 else |
13177 equal = xmlXPathNotEqualValues(ctxt); | 13183 equal = xmlXPathNotEqualValues(ctxt); |
13178 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal)); | 13184 valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal)); |
13179 return (total); | 13185 return (total); |
13180 case XPATH_OP_CMP: | 13186 case XPATH_OP_CMP: |
13181 bakd = ctxt->context->doc; | 13187 bakd = ctxt->context->doc; |
13182 bak = ctxt->context->node; | 13188 bak = ctxt->context->node; |
13183 pp = ctxt->context->proximityPosition; | 13189 pp = ctxt->context->proximityPosition; |
13184 cs = ctxt->context->contextSize; | 13190 cs = ctxt->context->contextSize; |
13185 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); | 13191 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13318 ctxt->error = XPATH_UNDEF_VARIABLE_ERROR; | 13324 ctxt->error = XPATH_UNDEF_VARIABLE_ERROR; |
13319 return(0); | 13325 return(0); |
13320 } | 13326 } |
13321 valuePush(ctxt, val); | 13327 valuePush(ctxt, val); |
13322 } else { | 13328 } else { |
13323 const xmlChar *URI; | 13329 const xmlChar *URI; |
13324 | 13330 |
13325 URI = xmlXPathNsLookup(ctxt->context, op->value5); | 13331 URI = xmlXPathNsLookup(ctxt->context, op->value5); |
13326 if (URI == NULL) { | 13332 if (URI == NULL) { |
13327 xmlGenericError(xmlGenericErrorContext, | 13333 xmlGenericError(xmlGenericErrorContext, |
13328 "xmlXPathCompOpEval: variable %s bound t
o undefined prefix %s\n", | 13334 "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n", |
13329 op->value4, op->value5); | 13335 (char *) op->value4, (char *)op->value5); |
13330 return (total); | 13336 return (total); |
13331 } | 13337 } |
13332 val = xmlXPathVariableLookupNS(ctxt->context, | 13338 val = xmlXPathVariableLookupNS(ctxt->context, |
13333 op->value4, URI); | 13339 op->value4, URI); |
13334 if (val == NULL) { | 13340 if (val == NULL) { |
13335 ctxt->error = XPATH_UNDEF_VARIABLE_ERROR; | 13341 ctxt->error = XPATH_UNDEF_VARIABLE_ERROR; |
13336 return(0); | 13342 return(0); |
13337 } | 13343 } |
13338 valuePush(ctxt, val); | 13344 valuePush(ctxt, val); |
13339 } | 13345 } |
(...skipping 26 matching lines...) Expand all Loading... |
13366 const xmlChar *URI = NULL; | 13372 const xmlChar *URI = NULL; |
13367 | 13373 |
13368 if (op->value5 == NULL) | 13374 if (op->value5 == NULL) |
13369 func = | 13375 func = |
13370 xmlXPathFunctionLookup(ctxt->context, | 13376 xmlXPathFunctionLookup(ctxt->context, |
13371 op->value4); | 13377 op->value4); |
13372 else { | 13378 else { |
13373 URI = xmlXPathNsLookup(ctxt->context, op->value5); | 13379 URI = xmlXPathNsLookup(ctxt->context, op->value5); |
13374 if (URI == NULL) { | 13380 if (URI == NULL) { |
13375 xmlGenericError(xmlGenericErrorContext, | 13381 xmlGenericError(xmlGenericErrorContext, |
13376 "xmlXPathCompOpEval: function %s bou
nd to undefined prefix %s\n", | 13382 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", |
13377 op->value4, op->value5); | 13383 (char *)op->value4, (char *)op->value5); |
13378 return (total); | 13384 return (total); |
13379 } | 13385 } |
13380 func = xmlXPathFunctionLookupNS(ctxt->context, | 13386 func = xmlXPathFunctionLookupNS(ctxt->context, |
13381 op->value4, URI); | 13387 op->value4, URI); |
13382 } | 13388 } |
13383 if (func == NULL) { | 13389 if (func == NULL) { |
13384 xmlGenericError(xmlGenericErrorContext, | 13390 xmlGenericError(xmlGenericErrorContext, |
13385 "xmlXPathCompOpEval: function %s not fou
nd\n", | 13391 "xmlXPathCompOpEval: function %s not found\n", |
13386 op->value4); | 13392 (char *)op->value4); |
13387 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); | 13393 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); |
13388 } | 13394 } |
13389 op->cache = XML_CAST_FPTR(func); | 13395 op->cache = XML_CAST_FPTR(func); |
13390 op->cacheURI = (void *) URI; | 13396 op->cacheURI = (void *) URI; |
13391 } | 13397 } |
13392 oldFunc = ctxt->context->function; | 13398 oldFunc = ctxt->context->function; |
13393 oldFuncURI = ctxt->context->functionURI; | 13399 oldFuncURI = ctxt->context->functionURI; |
13394 ctxt->context->function = op->value4; | 13400 ctxt->context->function = op->value4; |
13395 ctxt->context->functionURI = op->cacheURI; | 13401 ctxt->context->functionURI = op->cacheURI; |
13396 func(ctxt, op->value); | 13402 func(ctxt, op->value); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13574 /* | 13580 /* |
13575 * Run the evaluation with a node list made of a | 13581 * Run the evaluation with a node list made of a |
13576 * single item in the nodelocset. | 13582 * single item in the nodelocset. |
13577 */ | 13583 */ |
13578 ctxt->context->node = oldlocset->locTab[i]->user; | 13584 ctxt->context->node = oldlocset->locTab[i]->user; |
13579 ctxt->context->contextSize = oldlocset->locNr; | 13585 ctxt->context->contextSize = oldlocset->locNr; |
13580 ctxt->context->proximityPosition = i + 1; | 13586 ctxt->context->proximityPosition = i + 1; |
13581 tmp = xmlXPathCacheNewNodeSet(ctxt->context, | 13587 tmp = xmlXPathCacheNewNodeSet(ctxt->context, |
13582 ctxt->context->node); | 13588 ctxt->context->node); |
13583 valuePush(ctxt, tmp); | 13589 valuePush(ctxt, tmp); |
13584 » » » | 13590 |
13585 if (op->ch2 != -1) | 13591 if (op->ch2 != -1) |
13586 total += | 13592 total += |
13587 xmlXPathCompOpEval(ctxt, | 13593 xmlXPathCompOpEval(ctxt, |
13588 &comp->steps[op->ch2]); | 13594 &comp->steps[op->ch2]); |
13589 if (ctxt->error != XPATH_EXPRESSION_OK) { | 13595 if (ctxt->error != XPATH_EXPRESSION_OK) { |
13590 xmlXPathFreeObject(obj); | 13596 xmlXPathFreeObject(obj); |
13591 return(0); | 13597 return(0); |
13592 } | 13598 } |
13593 | 13599 |
13594 /* | 13600 /* |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13683 * node-set context pos | 13689 * node-set context pos |
13684 * nA 1 | 13690 * nA 1 |
13685 * nB 2 | 13691 * nB 2 |
13686 * nC 3 | 13692 * nC 3 |
13687 * After applying predicate [position() > 1] : | 13693 * After applying predicate [position() > 1] : |
13688 * node-set context pos | 13694 * node-set context pos |
13689 * nB 1 | 13695 * nB 1 |
13690 * nC 2 | 13696 * nC 2 |
13691 * | 13697 * |
13692 * removed the first node in the node-set, then | 13698 * removed the first node in the node-set, then |
13693 » » * the context position of the | 13699 » » * the context position of the |
13694 */ | 13700 */ |
13695 for (i = 0; i < oldset->nodeNr; i++) { | 13701 for (i = 0; i < oldset->nodeNr; i++) { |
13696 /* | 13702 /* |
13697 * Run the evaluation with a node list made of | 13703 * Run the evaluation with a node list made of |
13698 * a single item in the nodeset. | 13704 * a single item in the nodeset. |
13699 */ | 13705 */ |
13700 ctxt->context->node = oldset->nodeTab[i]; | 13706 ctxt->context->node = oldset->nodeTab[i]; |
13701 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && | 13707 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && |
13702 (oldset->nodeTab[i]->doc != NULL)) | 13708 (oldset->nodeTab[i]->doc != NULL)) |
13703 ctxt->context->doc = oldset->nodeTab[i]->doc; | 13709 ctxt->context->doc = oldset->nodeTab[i]->doc; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13740 } | 13746 } |
13741 | 13747 |
13742 /* | 13748 /* |
13743 * Cleanup | 13749 * Cleanup |
13744 */ | 13750 */ |
13745 if (res != NULL) { | 13751 if (res != NULL) { |
13746 xmlXPathReleaseObject(ctxt->context, res); | 13752 xmlXPathReleaseObject(ctxt->context, res); |
13747 } | 13753 } |
13748 if (ctxt->value == tmp) { | 13754 if (ctxt->value == tmp) { |
13749 valuePop(ctxt); | 13755 valuePop(ctxt); |
13750 » » » xmlXPathNodeSetClear(tmp->nodesetval, 1);» »
» | 13756 » » » xmlXPathNodeSetClear(tmp->nodesetval, 1); |
13751 /* | 13757 /* |
13752 * Don't free the temporary nodeset | 13758 * Don't free the temporary nodeset |
13753 * in order to avoid massive recreation inside this | 13759 * in order to avoid massive recreation inside this |
13754 * loop. | 13760 * loop. |
13755 */ | 13761 */ |
13756 } else | 13762 } else |
13757 tmp = NULL; | 13763 tmp = NULL; |
13758 ctxt->context->node = NULL; | 13764 ctxt->context->node = NULL; |
13759 } | 13765 } |
13760 if (tmp != NULL) | 13766 if (tmp != NULL) |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13843 total += | 13849 total += |
13844 xmlXPathCompOpEval(ctxt, | 13850 xmlXPathCompOpEval(ctxt, |
13845 &comp->steps[op->ch2]); | 13851 &comp->steps[op->ch2]); |
13846 if (ctxt->error != XPATH_EXPRESSION_OK) { | 13852 if (ctxt->error != XPATH_EXPRESSION_OK) { |
13847 xmlXPathFreeObject(obj); | 13853 xmlXPathFreeObject(obj); |
13848 return(0); | 13854 return(0); |
13849 } | 13855 } |
13850 | 13856 |
13851 res = valuePop(ctxt); | 13857 res = valuePop(ctxt); |
13852 if (res->type == XPATH_LOCATIONSET) { | 13858 if (res->type == XPATH_LOCATIONSET) { |
13853 » » » xmlLocationSetPtr rloc = | 13859 » » » xmlLocationSetPtr rloc = |
13854 (xmlLocationSetPtr)res->user; | 13860 (xmlLocationSetPtr)res->user; |
13855 for (j=0; j<rloc->locNr; j++) { | 13861 for (j=0; j<rloc->locNr; j++) { |
13856 range = xmlXPtrNewRange( | 13862 range = xmlXPtrNewRange( |
13857 oldlocset->locTab[i]->user, | 13863 oldlocset->locTab[i]->user, |
13858 oldlocset->locTab[i]->index, | 13864 oldlocset->locTab[i]->index, |
13859 rloc->locTab[j]->user2, | 13865 rloc->locTab[j]->user2, |
13860 rloc->locTab[j]->index2); | 13866 rloc->locTab[j]->index2); |
13861 if (range != NULL) { | 13867 if (range != NULL) { |
13862 xmlXPtrLocationSetAdd(newlocset, range); | 13868 xmlXPtrLocationSetAdd(newlocset, range); |
13863 } | 13869 } |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14005 if (resObj == NULL) | 14011 if (resObj == NULL) |
14006 return(-1); | 14012 return(-1); |
14007 break; | 14013 break; |
14008 default: | 14014 default: |
14009 /* | 14015 /* |
14010 * Fallback to call xmlXPathCompOpEval(). | 14016 * Fallback to call xmlXPathCompOpEval(). |
14011 */ | 14017 */ |
14012 xmlXPathCompOpEval(ctxt, op); | 14018 xmlXPathCompOpEval(ctxt, op); |
14013 if (ctxt->error != XPATH_EXPRESSION_OK) | 14019 if (ctxt->error != XPATH_EXPRESSION_OK) |
14014 return(-1); | 14020 return(-1); |
14015 » | 14021 |
14016 resObj = valuePop(ctxt); | 14022 resObj = valuePop(ctxt); |
14017 if (resObj == NULL) | 14023 if (resObj == NULL) |
14018 return(-1); | 14024 return(-1); |
14019 break; | 14025 break; |
14020 } | 14026 } |
14021 | 14027 |
14022 if (resObj) { | 14028 if (resObj) { |
14023 int res; | 14029 int res; |
14024 | 14030 |
14025 if (resObj->type == XPATH_BOOLEAN) { | 14031 if (resObj->type == XPATH_BOOLEAN) { |
14026 res = resObj->boolval; | 14032 res = resObj->boolval; |
14027 } else if (isPredicate) { | 14033 } else if (isPredicate) { |
14028 /* | 14034 /* |
14029 * For predicates a result of type "number" is handled | 14035 * For predicates a result of type "number" is handled |
14030 * differently: | 14036 * differently: |
14031 * SPEC XPath 1.0: | 14037 * SPEC XPath 1.0: |
14032 * "If the result is a number, the result will be converted | 14038 * "If the result is a number, the result will be converted |
14033 * to true if the number is equal to the context position | 14039 * to true if the number is equal to the context position |
14034 * and will be converted to false otherwise;" | 14040 * and will be converted to false otherwise;" |
14035 */ | 14041 */ |
14036 » res = xmlXPathEvaluatePredicateResult(ctxt, resObj); | 14042 » res = xmlXPathEvaluatePredicateResult(ctxt, resObj); |
14037 } else { | 14043 } else { |
14038 res = xmlXPathCastToBoolean(resObj); | 14044 res = xmlXPathCastToBoolean(resObj); |
14039 } | 14045 } |
14040 xmlXPathReleaseObject(ctxt->context, resObj); | 14046 xmlXPathReleaseObject(ctxt->context, resObj); |
14041 return(res); | 14047 return(res); |
14042 } | 14048 } |
14043 | 14049 |
14044 return(0); | 14050 return(0); |
14045 } | 14051 } |
14046 | 14052 |
14047 #ifdef XPATH_STREAMING | 14053 #ifdef XPATH_STREAMING |
14048 /** | 14054 /** |
14049 * xmlXPathRunStreamEval: | 14055 * xmlXPathRunStreamEval: |
14050 * @ctxt: the XPath parser context with the compiled expression | 14056 * @ctxt: the XPath parser context with the compiled expression |
14051 * | 14057 * |
14052 * Evaluate the Precompiled Streamable XPath expression in the given context. | 14058 * Evaluate the Precompiled Streamable XPath expression in the given context. |
14053 */ | 14059 */ |
14054 static int | 14060 static int |
14055 xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, | 14061 xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp, |
14056 xmlXPathObjectPtr *resultSeq, int toBool) | 14062 xmlXPathObjectPtr *resultSeq, int toBool) |
14057 { | 14063 { |
14058 int max_depth, min_depth; | 14064 int max_depth, min_depth; |
14059 int from_root; | 14065 int from_root; |
14060 int ret, depth; | 14066 int ret, depth; |
14061 int eval_all_nodes; | 14067 int eval_all_nodes; |
14062 xmlNodePtr cur = NULL, limit = NULL; | 14068 xmlNodePtr cur = NULL, limit = NULL; |
14063 xmlStreamCtxtPtr patstream = NULL; | 14069 xmlStreamCtxtPtr patstream = NULL; |
14064 | 14070 |
14065 int nb_nodes = 0; | 14071 int nb_nodes = 0; |
14066 | 14072 |
14067 if ((ctxt == NULL) || (comp == NULL)) | 14073 if ((ctxt == NULL) || (comp == NULL)) |
14068 return(-1); | 14074 return(-1); |
14069 max_depth = xmlPatternMaxDepth(comp); | 14075 max_depth = xmlPatternMaxDepth(comp); |
14070 if (max_depth == -1) | 14076 if (max_depth == -1) |
14071 return(-1); | 14077 return(-1); |
14072 if (max_depth == -2) | 14078 if (max_depth == -2) |
14073 max_depth = 10000; | 14079 max_depth = 10000; |
14074 min_depth = xmlPatternMinDepth(comp); | 14080 min_depth = xmlPatternMinDepth(comp); |
14075 if (min_depth == -1) | 14081 if (min_depth == -1) |
14076 return(-1); | 14082 return(-1); |
14077 from_root = xmlPatternFromRoot(comp); | 14083 from_root = xmlPatternFromRoot(comp); |
14078 if (from_root < 0) | 14084 if (from_root < 0) |
14079 return(-1); | 14085 return(-1); |
14080 #if 0 | 14086 #if 0 |
14081 printf("stream eval: depth %d from root %d\n", max_depth, from_root); | 14087 printf("stream eval: depth %d from root %d\n", max_depth, from_root); |
14082 #endif | 14088 #endif |
14083 | 14089 |
14084 if (! toBool) { | 14090 if (! toBool) { |
14085 if (resultSeq == NULL) | 14091 if (resultSeq == NULL) |
14086 return(-1); | 14092 return(-1); |
14087 *resultSeq = xmlXPathCacheNewNodeSet(ctxt, NULL); | 14093 *resultSeq = xmlXPathCacheNewNodeSet(ctxt, NULL); |
14088 if (*resultSeq == NULL) | 14094 if (*resultSeq == NULL) |
14089 return(-1); | 14095 return(-1); |
14090 } | 14096 } |
14091 | 14097 |
14092 /* | 14098 /* |
14093 * handle the special cases of "/" amd "." being matched | 14099 * handle the special cases of "/" amd "." being matched |
14094 */ | 14100 */ |
14095 if (min_depth == 0) { | 14101 if (min_depth == 0) { |
14096 if (from_root) { | 14102 if (from_root) { |
14097 /* Select "/" */ | 14103 /* Select "/" */ |
14098 if (toBool) | 14104 if (toBool) |
14099 return(1); | 14105 return(1); |
14100 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, | 14106 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, |
14101 (xmlNodePtr) ctxt->doc); | 14107 (xmlNodePtr) ctxt->doc); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14178 case XML_CDATA_SECTION_NODE: | 14184 case XML_CDATA_SECTION_NODE: |
14179 case XML_COMMENT_NODE: | 14185 case XML_COMMENT_NODE: |
14180 case XML_PI_NODE: | 14186 case XML_PI_NODE: |
14181 if (cur->type == XML_ELEMENT_NODE) { | 14187 if (cur->type == XML_ELEMENT_NODE) { |
14182 ret = xmlStreamPush(patstream, cur->name, | 14188 ret = xmlStreamPush(patstream, cur->name, |
14183 (cur->ns ? cur->ns->href : NULL)); | 14189 (cur->ns ? cur->ns->href : NULL)); |
14184 } else if (eval_all_nodes) | 14190 } else if (eval_all_nodes) |
14185 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type); | 14191 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type); |
14186 else | 14192 else |
14187 break; | 14193 break; |
14188 » » | 14194 |
14189 if (ret < 0) { | 14195 if (ret < 0) { |
14190 /* NOP. */ | 14196 /* NOP. */ |
14191 } else if (ret == 1) { | 14197 } else if (ret == 1) { |
14192 if (toBool) | 14198 if (toBool) |
14193 goto return_1; | 14199 goto return_1; |
14194 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); | 14200 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); |
14195 } | 14201 } |
14196 if ((cur->children == NULL) || (depth >= max_depth)) { | 14202 if ((cur->children == NULL) || (depth >= max_depth)) { |
14197 ret = xmlStreamPop(patstream); | 14203 ret = xmlStreamPop(patstream); |
14198 while (cur->next != NULL) { | 14204 while (cur->next != NULL) { |
14199 cur = cur->next; | 14205 cur = cur->next; |
14200 if ((cur->type != XML_ENTITY_DECL) && | 14206 if ((cur->type != XML_ENTITY_DECL) && |
14201 (cur->type != XML_DTD_NODE)) | 14207 (cur->type != XML_DTD_NODE)) |
14202 goto next_node; | 14208 goto next_node; |
14203 } | 14209 } |
14204 } | 14210 } |
14205 default: | 14211 default: |
14206 break; | 14212 break; |
14207 } | 14213 } |
14208 | 14214 |
14209 scan_children: | 14215 scan_children: |
14210 if ((cur->children != NULL) && (depth < max_depth)) { | 14216 if ((cur->children != NULL) && (depth < max_depth)) { |
14211 /* | 14217 /* |
14212 » * Do not descend on entities declarations» | 14218 » * Do not descend on entities declarations |
14213 */ | 14219 */ |
14214 if (cur->children->type != XML_ENTITY_DECL) { | 14220 if (cur->children->type != XML_ENTITY_DECL) { |
14215 cur = cur->children; | 14221 cur = cur->children; |
14216 depth++; | 14222 depth++; |
14217 /* | 14223 /* |
14218 * Skip DTDs | 14224 * Skip DTDs |
14219 */ | 14225 */ |
14220 if (cur->type != XML_DTD_NODE) | 14226 if (cur->type != XML_DTD_NODE) |
14221 continue; | 14227 continue; |
14222 } | 14228 } |
14223 } | 14229 } |
14224 | 14230 |
14225 if (cur == limit) | 14231 if (cur == limit) |
14226 break; | 14232 break; |
14227 | 14233 |
14228 while (cur->next != NULL) { | 14234 while (cur->next != NULL) { |
14229 cur = cur->next; | 14235 cur = cur->next; |
14230 if ((cur->type != XML_ENTITY_DECL) && | 14236 if ((cur->type != XML_ENTITY_DECL) && |
14231 (cur->type != XML_DTD_NODE)) | 14237 (cur->type != XML_DTD_NODE)) |
14232 goto next_node; | 14238 goto next_node; |
14233 } | 14239 } |
14234 » | 14240 |
14235 do { | 14241 do { |
14236 cur = cur->parent; | 14242 cur = cur->parent; |
14237 depth--; | 14243 depth--; |
14238 if ((cur == NULL) || (cur == limit)) | 14244 if ((cur == NULL) || (cur == limit)) |
14239 goto done; | 14245 goto done; |
14240 if (cur->type == XML_ELEMENT_NODE) { | 14246 if (cur->type == XML_ELEMENT_NODE) { |
14241 ret = xmlStreamPop(patstream); | 14247 ret = xmlStreamPop(patstream); |
14242 } else if ((eval_all_nodes) && | 14248 } else if ((eval_all_nodes) && |
14243 ((cur->type == XML_TEXT_NODE) || | 14249 ((cur->type == XML_TEXT_NODE) || |
14244 (cur->type == XML_CDATA_SECTION_NODE) || | 14250 (cur->type == XML_CDATA_SECTION_NODE) || |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14283 static int | 14289 static int |
14284 xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) | 14290 xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool) |
14285 { | 14291 { |
14286 xmlXPathCompExprPtr comp; | 14292 xmlXPathCompExprPtr comp; |
14287 | 14293 |
14288 if ((ctxt == NULL) || (ctxt->comp == NULL)) | 14294 if ((ctxt == NULL) || (ctxt->comp == NULL)) |
14289 return(-1); | 14295 return(-1); |
14290 | 14296 |
14291 if (ctxt->valueTab == NULL) { | 14297 if (ctxt->valueTab == NULL) { |
14292 /* Allocate the value stack */ | 14298 /* Allocate the value stack */ |
14293 » ctxt->valueTab = (xmlXPathObjectPtr *) | 14299 » ctxt->valueTab = (xmlXPathObjectPtr *) |
14294 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); | 14300 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); |
14295 if (ctxt->valueTab == NULL) { | 14301 if (ctxt->valueTab == NULL) { |
14296 xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); | 14302 xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); |
14297 xmlFree(ctxt); | 14303 xmlFree(ctxt); |
14298 } | 14304 } |
14299 ctxt->valueNr = 0; | 14305 ctxt->valueNr = 0; |
14300 ctxt->valueMax = 10; | 14306 ctxt->valueMax = 10; |
14301 ctxt->value = NULL; | 14307 ctxt->value = NULL; |
14302 } | 14308 } |
14303 #ifdef XPATH_STREAMING | 14309 #ifdef XPATH_STREAMING |
14304 if (ctxt->comp->stream) { | 14310 if (ctxt->comp->stream) { |
14305 int res; | 14311 int res; |
14306 | 14312 |
14307 if (toBool) { | 14313 if (toBool) { |
14308 /* | 14314 /* |
14309 * Evaluation to boolean result. | 14315 * Evaluation to boolean result. |
14310 */ | 14316 */ |
14311 res = xmlXPathRunStreamEval(ctxt->context, | 14317 res = xmlXPathRunStreamEval(ctxt->context, |
14312 ctxt->comp->stream, NULL, 1); | 14318 ctxt->comp->stream, NULL, 1); |
14313 if (res != -1) | 14319 if (res != -1) |
14314 return(res); | 14320 return(res); |
14315 } else { | 14321 } else { |
14316 » xmlXPathObjectPtr resObj = NULL;» | 14322 » xmlXPathObjectPtr resObj = NULL; |
14317 | 14323 |
14318 /* | 14324 /* |
14319 * Evaluation to a sequence. | 14325 * Evaluation to a sequence. |
14320 */ | 14326 */ |
14321 res = xmlXPathRunStreamEval(ctxt->context, | 14327 res = xmlXPathRunStreamEval(ctxt->context, |
14322 ctxt->comp->stream, &resObj, 0); | 14328 ctxt->comp->stream, &resObj, 0); |
14323 | 14329 |
14324 if ((res != -1) && (resObj != NULL)) { | 14330 if ((res != -1) && (resObj != NULL)) { |
14325 valuePush(ctxt, resObj); | 14331 valuePush(ctxt, resObj); |
14326 return(0); | 14332 return(0); |
14327 } | 14333 } |
14328 if (resObj != NULL) | 14334 if (resObj != NULL) |
14329 » » xmlXPathReleaseObject(ctxt->context, resObj);» | 14335 » » xmlXPathReleaseObject(ctxt->context, resObj); |
14330 } | 14336 } |
14331 /* | 14337 /* |
14332 * QUESTION TODO: This falls back to normal XPath evaluation | 14338 * QUESTION TODO: This falls back to normal XPath evaluation |
14333 * if res == -1. Is this intended? | 14339 * if res == -1. Is this intended? |
14334 */ | 14340 */ |
14335 } | 14341 } |
14336 #endif | 14342 #endif |
14337 comp = ctxt->comp; | 14343 comp = ctxt->comp; |
14338 if (comp->last < 0) { | 14344 if (comp->last < 0) { |
14339 xmlGenericError(xmlGenericErrorContext, | 14345 xmlGenericError(xmlGenericErrorContext, |
14340 "xmlXPathRunEval: last is less than zero\n"); | 14346 "xmlXPathRunEval: last is less than zero\n"); |
14341 return(-1); | 14347 return(-1); |
14342 } | 14348 } |
14343 if (toBool) | 14349 if (toBool) |
14344 return(xmlXPathCompOpEvalToBoolean(ctxt, | 14350 return(xmlXPathCompOpEvalToBoolean(ctxt, |
14345 &comp->steps[comp->last], 0)); | 14351 &comp->steps[comp->last], 0)); |
14346 else | 14352 else |
14347 xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]); | 14353 xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]); |
14348 | 14354 |
14349 return(0); | 14355 return(0); |
14350 } | 14356 } |
14351 | 14357 |
14352 /************************************************************************ | 14358 /************************************************************************ |
14353 * * | 14359 * * |
14354 * » » » Public interfaces» » » » * | 14360 *» » » Public interfaces» » » » * |
14355 * * | 14361 * * |
14356 ************************************************************************/ | 14362 ************************************************************************/ |
14357 | 14363 |
14358 /** | 14364 /** |
14359 * xmlXPathEvalPredicate: | 14365 * xmlXPathEvalPredicate: |
14360 * @ctxt: the XPath context | 14366 * @ctxt: the XPath context |
14361 * @res: the Predicate Expression evaluation result | 14367 * @res: the Predicate Expression evaluation result |
14362 * | 14368 * |
14363 * Evaluate a predicate result for the current node. | 14369 * Evaluate a predicate result for the current node. |
14364 * A PredicateExpr is evaluated by evaluating the Expr and converting | 14370 * A PredicateExpr is evaluated by evaluating the Expr and converting |
14365 * the result to a boolean. If the result is a number, the result will | 14371 * the result to a boolean. If the result is a number, the result will |
14366 * be converted to true if the number is equal to the position of the | 14372 * be converted to true if the number is equal to the position of the |
14367 * context node in the context node list (as returned by the position | 14373 * context node in the context node list (as returned by the position |
14368 * function) and will be converted to false otherwise; if the result | 14374 * function) and will be converted to false otherwise; if the result |
14369 * is not a number, then the result will be converted as if by a call | 14375 * is not a number, then the result will be converted as if by a call |
14370 * to the boolean function. | 14376 * to the boolean function. |
14371 * | 14377 * |
14372 * Returns 1 if predicate is true, 0 otherwise | 14378 * Returns 1 if predicate is true, 0 otherwise |
14373 */ | 14379 */ |
14374 int | 14380 int |
14375 xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) { | 14381 xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) { |
14376 if ((ctxt == NULL) || (res == NULL)) return(0); | 14382 if ((ctxt == NULL) || (res == NULL)) return(0); |
14377 switch (res->type) { | 14383 switch (res->type) { |
14378 case XPATH_BOOLEAN: | 14384 case XPATH_BOOLEAN: |
14379 return(res->boolval); | 14385 return(res->boolval); |
14380 case XPATH_NUMBER: | 14386 case XPATH_NUMBER: |
(...skipping 17 matching lines...) Expand all Loading... |
14398 * @ctxt: the XPath Parser context | 14404 * @ctxt: the XPath Parser context |
14399 * @res: the Predicate Expression evaluation result | 14405 * @res: the Predicate Expression evaluation result |
14400 * | 14406 * |
14401 * Evaluate a predicate result for the current node. | 14407 * Evaluate a predicate result for the current node. |
14402 * A PredicateExpr is evaluated by evaluating the Expr and converting | 14408 * A PredicateExpr is evaluated by evaluating the Expr and converting |
14403 * the result to a boolean. If the result is a number, the result will | 14409 * the result to a boolean. If the result is a number, the result will |
14404 * be converted to true if the number is equal to the position of the | 14410 * be converted to true if the number is equal to the position of the |
14405 * context node in the context node list (as returned by the position | 14411 * context node in the context node list (as returned by the position |
14406 * function) and will be converted to false otherwise; if the result | 14412 * function) and will be converted to false otherwise; if the result |
14407 * is not a number, then the result will be converted as if by a call | 14413 * is not a number, then the result will be converted as if by a call |
14408 * to the boolean function. | 14414 * to the boolean function. |
14409 * | 14415 * |
14410 * Returns 1 if predicate is true, 0 otherwise | 14416 * Returns 1 if predicate is true, 0 otherwise |
14411 */ | 14417 */ |
14412 int | 14418 int |
14413 xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt, | 14419 xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt, |
14414 xmlXPathObjectPtr res) { | 14420 xmlXPathObjectPtr res) { |
14415 if ((ctxt == NULL) || (res == NULL)) return(0); | 14421 if ((ctxt == NULL) || (res == NULL)) return(0); |
14416 switch (res->type) { | 14422 switch (res->type) { |
14417 case XPATH_BOOLEAN: | 14423 case XPATH_BOOLEAN: |
14418 return(res->boolval); | 14424 return(res->boolval); |
14419 case XPATH_NUMBER: | 14425 case XPATH_NUMBER: |
14420 #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200)) | 14426 #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200)) |
14421 return((res->floatval == ctxt->context->proximityPosition) && | 14427 return((res->floatval == ctxt->context->proximityPosition) && |
14422 (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/ | 14428 (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/ |
14423 #else | 14429 #else |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14476 * specifiers ("::"), just the simplied form at this point. | 14482 * specifiers ("::"), just the simplied form at this point. |
14477 * Additionally, if there is no list of namespaces available and | 14483 * Additionally, if there is no list of namespaces available and |
14478 * there's a ":" in the expression, indicating a prefixed QName, | 14484 * there's a ":" in the expression, indicating a prefixed QName, |
14479 * then we won't try to compile either. xmlPatterncompile() needs | 14485 * then we won't try to compile either. xmlPatterncompile() needs |
14480 * to have a list of namespaces at compilation time in order to | 14486 * to have a list of namespaces at compilation time in order to |
14481 * compile prefixed name tests. | 14487 * compile prefixed name tests. |
14482 */ | 14488 */ |
14483 tmp = xmlStrchr(str, ':'); | 14489 tmp = xmlStrchr(str, ':'); |
14484 if ((tmp != NULL) && | 14490 if ((tmp != NULL) && |
14485 ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':'))) | 14491 ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':'))) |
14486 » return(NULL);» | 14492 » return(NULL); |
14487 | 14493 |
14488 if (ctxt != NULL) { | 14494 if (ctxt != NULL) { |
14489 dict = ctxt->dict; | 14495 dict = ctxt->dict; |
14490 if (ctxt->nsNr > 0) { | 14496 if (ctxt->nsNr > 0) { |
14491 namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*)); | 14497 namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*)); |
14492 if (namespaces == NULL) { | 14498 if (namespaces == NULL) { |
14493 xmlXPathErrMemory(ctxt, "allocating namespaces array\n"); | 14499 xmlXPathErrMemory(ctxt, "allocating namespaces array\n"); |
14494 return(NULL); | 14500 return(NULL); |
14495 } | 14501 } |
14496 for (i = 0, j = 0; (j < ctxt->nsNr); j++) { | 14502 for (i = 0, j = 0; (j < ctxt->nsNr); j++) { |
14497 ns = ctxt->namespaces[j]; | 14503 ns = ctxt->namespaces[j]; |
14498 namespaces[i++] = ns->href; | 14504 namespaces[i++] = ns->href; |
14499 namespaces[i++] = ns->prefix; | 14505 namespaces[i++] = ns->prefix; |
14500 } | 14506 } |
14501 namespaces[i++] = NULL; | 14507 namespaces[i++] = NULL; |
14502 » » namespaces[i++] = NULL; | 14508 » » namespaces[i] = NULL; |
14503 } | 14509 } |
14504 } | 14510 } |
14505 | 14511 |
14506 stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, | 14512 stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, |
14507 &namespaces[0]); | 14513 &namespaces[0]); |
14508 if (namespaces != NULL) { | 14514 if (namespaces != NULL) { |
14509 xmlFree((xmlChar **)namespaces); | 14515 xmlFree((xmlChar **)namespaces); |
14510 » } | 14516 » } |
14511 if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) { | 14517 if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) { |
14512 comp = xmlXPathNewCompExpr(); | 14518 comp = xmlXPathNewCompExpr(); |
14513 if (comp == NULL) { | 14519 if (comp == NULL) { |
14514 xmlXPathErrMemory(ctxt, "allocating streamable expression\n"); | 14520 xmlXPathErrMemory(ctxt, "allocating streamable expression\n"); |
14515 return(NULL); | 14521 return(NULL); |
14516 } | 14522 } |
14517 comp->stream = stream; | 14523 comp->stream = stream; |
14518 comp->dict = dict; | 14524 comp->dict = dict; |
14519 if (comp->dict) | 14525 if (comp->dict) |
14520 xmlDictReference(comp->dict); | 14526 xmlDictReference(comp->dict); |
(...skipping 18 matching lines...) Expand all Loading... |
14539 } | 14545 } |
14540 static void | 14546 static void |
14541 xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) | 14547 xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) |
14542 { | 14548 { |
14543 /* | 14549 /* |
14544 * Try to rewrite "descendant-or-self::node()/foo" to an optimized | 14550 * Try to rewrite "descendant-or-self::node()/foo" to an optimized |
14545 * internal representation. | 14551 * internal representation. |
14546 */ | 14552 */ |
14547 if (op->ch1 != -1) { | 14553 if (op->ch1 != -1) { |
14548 if ((op->op == XPATH_OP_COLLECT /* 11 */) && | 14554 if ((op->op == XPATH_OP_COLLECT /* 11 */) && |
14549 » ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) &&» | 14555 » ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) && |
14550 ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) && | 14556 ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) && |
14551 ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */)) | 14557 ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */)) |
14552 { | 14558 { |
14553 /* | 14559 /* |
14554 * This is a "child::foo" | 14560 * This is a "child::foo" |
14555 */ | 14561 */ |
14556 » xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];» | 14562 » xmlXPathStepOpPtr prevop = &comp->steps[op->ch1]; |
14557 | 14563 |
14558 if ((prevop->op == XPATH_OP_COLLECT /* 11 */) && | 14564 if ((prevop->op == XPATH_OP_COLLECT /* 11 */) && |
14559 » » (prevop->ch1 != -1) &&» | 14565 » » (prevop->ch1 != -1) && |
14560 ((xmlXPathAxisVal) prevop->value == | 14566 ((xmlXPathAxisVal) prevop->value == |
14561 AXIS_DESCENDANT_OR_SELF) && | 14567 AXIS_DESCENDANT_OR_SELF) && |
14562 (prevop->ch2 == -1) && | 14568 (prevop->ch2 == -1) && |
14563 ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) && | 14569 ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) && |
14564 ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) && | 14570 ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) && |
14565 (comp->steps[prevop->ch1].op == XPATH_OP_ROOT)) | 14571 (comp->steps[prevop->ch1].op == XPATH_OP_ROOT)) |
14566 » {» » | 14572 » { |
14567 /* | 14573 /* |
14568 * This is a "/descendant-or-self::node()" without predicates. | 14574 * This is a "/descendant-or-self::node()" without predicates. |
14569 * Eliminate it. | 14575 * Eliminate it. |
14570 */ | 14576 */ |
14571 op->ch1 = prevop->ch1; | 14577 op->ch1 = prevop->ch1; |
14572 » » op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM;» » | 14578 » » op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM; |
14573 } | 14579 } |
14574 } | 14580 } |
14575 if (op->ch1 != -1) | 14581 if (op->ch1 != -1) |
14576 xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]); | 14582 xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]); |
14577 } | 14583 } |
14578 if (op->ch2 != -1) | 14584 if (op->ch2 != -1) |
14579 xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]); | 14585 xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]); |
14580 } | 14586 } |
14581 | 14587 |
14582 /** | 14588 /** |
(...skipping 24 matching lines...) Expand all Loading... |
14607 return NULL; | 14613 return NULL; |
14608 xmlXPathCompileExpr(pctxt, 1); | 14614 xmlXPathCompileExpr(pctxt, 1); |
14609 | 14615 |
14610 if( pctxt->error != XPATH_EXPRESSION_OK ) | 14616 if( pctxt->error != XPATH_EXPRESSION_OK ) |
14611 { | 14617 { |
14612 xmlXPathFreeParserContext(pctxt); | 14618 xmlXPathFreeParserContext(pctxt); |
14613 return(NULL); | 14619 return(NULL); |
14614 } | 14620 } |
14615 | 14621 |
14616 if (*pctxt->cur != 0) { | 14622 if (*pctxt->cur != 0) { |
14617 » /* | 14623 » /* |
14618 * aleksey: in some cases this line prints *second* error message | 14624 * aleksey: in some cases this line prints *second* error message |
14619 * (see bug #78858) and probably this should be fixed. | 14625 * (see bug #78858) and probably this should be fixed. |
14620 * However, we are not sure that all error messages are printed | 14626 * However, we are not sure that all error messages are printed |
14621 * out in other places. It's not critical so we leave it as-is for now | 14627 * out in other places. It's not critical so we leave it as-is for now |
14622 */ | 14628 */ |
14623 xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); | 14629 xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); |
14624 comp = NULL; | 14630 comp = NULL; |
14625 } else { | 14631 } else { |
14626 comp = pctxt->comp; | 14632 comp = pctxt->comp; |
14627 pctxt->comp = NULL; | 14633 pctxt->comp = NULL; |
14628 } | 14634 } |
14629 xmlXPathFreeParserContext(pctxt); | 14635 xmlXPathFreeParserContext(pctxt); |
14630 | 14636 |
14631 if (comp != NULL) { | 14637 if (comp != NULL) { |
14632 comp->expr = xmlStrdup(str); | 14638 comp->expr = xmlStrdup(str); |
14633 #ifdef DEBUG_EVAL_COUNTS | 14639 #ifdef DEBUG_EVAL_COUNTS |
14634 comp->string = xmlStrdup(str); | 14640 comp->string = xmlStrdup(str); |
14635 comp->nb = 0; | 14641 comp->nb = 0; |
14636 #endif | 14642 #endif |
14637 if ((comp->expr != NULL) && | 14643 if ((comp->expr != NULL) && |
14638 (comp->nbStep > 2) && | 14644 (comp->nbStep > 2) && |
14639 (comp->last >= 0) && | 14645 (comp->last >= 0) && |
14640 (xmlXPathCanRewriteDosExpression(comp->expr) == 1)) | 14646 (xmlXPathCanRewriteDosExpression(comp->expr) == 1)) |
14641 { | 14647 { |
14642 xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]); | 14648 xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]); |
14643 } | 14649 } |
14644 } | 14650 } |
14645 return(comp); | 14651 return(comp); |
14646 } | 14652 } |
(...skipping 24 matching lines...) Expand all Loading... |
14671 * | 14677 * |
14672 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. | 14678 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. |
14673 * the caller has to free the object. | 14679 * the caller has to free the object. |
14674 */ | 14680 */ |
14675 static int | 14681 static int |
14676 xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, | 14682 xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, |
14677 xmlXPathContextPtr ctxt, | 14683 xmlXPathContextPtr ctxt, |
14678 xmlXPathObjectPtr *resObj, | 14684 xmlXPathObjectPtr *resObj, |
14679 int toBool) | 14685 int toBool) |
14680 { | 14686 { |
14681 xmlXPathParserContextPtr pctxt; | 14687 xmlXPathParserContextPtr pctxt; |
14682 #ifndef LIBXML_THREAD_ENABLED | 14688 #ifndef LIBXML_THREAD_ENABLED |
14683 static int reentance = 0; | 14689 static int reentance = 0; |
14684 #endif | 14690 #endif |
14685 int res; | 14691 int res; |
14686 | 14692 |
14687 CHECK_CTXT_NEG(ctxt) | 14693 CHECK_CTXT_NEG(ctxt) |
14688 | 14694 |
14689 if (comp == NULL) | 14695 if (comp == NULL) |
14690 return(-1); | 14696 return(-1); |
14691 xmlXPathInit(); | 14697 xmlXPathInit(); |
14692 | 14698 |
14693 #ifndef LIBXML_THREAD_ENABLED | 14699 #ifndef LIBXML_THREAD_ENABLED |
14694 reentance++; | 14700 reentance++; |
14695 if (reentance > 1) | 14701 if (reentance > 1) |
14696 xmlXPathDisableOptimizer = 1; | 14702 xmlXPathDisableOptimizer = 1; |
14697 #endif | 14703 #endif |
14698 | 14704 |
14699 #ifdef DEBUG_EVAL_COUNTS | 14705 #ifdef DEBUG_EVAL_COUNTS |
14700 comp->nb++; | 14706 comp->nb++; |
14701 if ((comp->string != NULL) && (comp->nb > 100)) { | 14707 if ((comp->string != NULL) && (comp->nb > 100)) { |
14702 fprintf(stderr, "100 x %s\n", comp->string); | 14708 fprintf(stderr, "100 x %s\n", comp->string); |
14703 comp->nb = 0; | 14709 comp->nb = 0; |
14704 } | 14710 } |
14705 #endif | 14711 #endif |
14706 pctxt = xmlXPathCompParserContext(comp, ctxt); | 14712 pctxt = xmlXPathCompParserContext(comp, ctxt); |
14707 res = xmlXPathRunEval(pctxt, toBool); | 14713 res = xmlXPathRunEval(pctxt, toBool); |
14708 | 14714 |
14709 if (resObj) { | 14715 if (resObj) { |
14710 » if (pctxt->value == NULL) {» | 14716 » if (pctxt->value == NULL) { |
14711 xmlGenericError(xmlGenericErrorContext, | 14717 xmlGenericError(xmlGenericErrorContext, |
14712 "xmlXPathCompiledEval: evaluation failed\n"); | 14718 "xmlXPathCompiledEval: evaluation failed\n"); |
14713 » *resObj = NULL;» | 14719 » *resObj = NULL; |
14714 } else { | 14720 } else { |
14715 *resObj = valuePop(pctxt); | 14721 *resObj = valuePop(pctxt); |
14716 } | 14722 } |
14717 } | 14723 } |
14718 | 14724 |
14719 /* | 14725 /* |
14720 * Pop all remaining objects from the stack. | 14726 * Pop all remaining objects from the stack. |
14721 */ | 14727 */ |
14722 if (pctxt->valueNr > 0) { | 14728 if (pctxt->valueNr > 0) { |
14723 xmlXPathObjectPtr tmp; | 14729 xmlXPathObjectPtr tmp; |
14724 int stack = 0; | 14730 int stack = 0; |
14725 | 14731 |
14726 do { | 14732 do { |
14727 tmp = valuePop(pctxt); | 14733 tmp = valuePop(pctxt); |
14728 if (tmp != NULL) { | 14734 if (tmp != NULL) { |
14729 » » stack++; | 14735 » » stack++; |
14730 xmlXPathReleaseObject(ctxt, tmp); | 14736 xmlXPathReleaseObject(ctxt, tmp); |
14731 } | 14737 } |
14732 } while (tmp != NULL); | 14738 } while (tmp != NULL); |
14733 if ((stack != 0) && | 14739 if ((stack != 0) && |
14734 ((toBool) || ((resObj) && (*resObj)))) | 14740 ((toBool) || ((resObj) && (*resObj)))) |
14735 { | 14741 { |
14736 xmlGenericError(xmlGenericErrorContext, | 14742 xmlGenericError(xmlGenericErrorContext, |
14737 "xmlXPathCompiledEval: %d objects left on the stack.\n", | 14743 "xmlXPathCompiledEval: %d objects left on the stack.\n", |
14738 stack); | 14744 stack); |
14739 } | 14745 } |
14740 } | 14746 } |
14741 | 14747 |
14742 if ((pctxt->error != XPATH_EXPRESSION_OK) && (resObj) && (*resObj)) { | 14748 if ((pctxt->error != XPATH_EXPRESSION_OK) && (resObj) && (*resObj)) { |
14743 xmlXPathFreeObject(*resObj); | 14749 xmlXPathFreeObject(*resObj); |
14744 *resObj = NULL; | 14750 *resObj = NULL; |
14745 } | 14751 } |
14746 pctxt->comp = NULL; | 14752 pctxt->comp = NULL; |
14747 xmlXPathFreeParserContext(pctxt); | 14753 xmlXPathFreeParserContext(pctxt); |
14748 #ifndef LIBXML_THREAD_ENABLED | 14754 #ifndef LIBXML_THREAD_ENABLED |
14749 reentance--; | 14755 reentance--; |
14750 #endif | 14756 #endif |
14751 | 14757 |
14752 return(res); | 14758 return(res); |
14753 } | 14759 } |
14754 | 14760 |
14755 /** | 14761 /** |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14796 * Parse and evaluate an XPath expression in the given context, | 14802 * Parse and evaluate an XPath expression in the given context, |
14797 * then push the result on the context stack | 14803 * then push the result on the context stack |
14798 */ | 14804 */ |
14799 void | 14805 void |
14800 xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) { | 14806 xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) { |
14801 #ifdef XPATH_STREAMING | 14807 #ifdef XPATH_STREAMING |
14802 xmlXPathCompExprPtr comp; | 14808 xmlXPathCompExprPtr comp; |
14803 #endif | 14809 #endif |
14804 | 14810 |
14805 if (ctxt == NULL) return; | 14811 if (ctxt == NULL) return; |
14806 | 14812 |
14807 #ifdef XPATH_STREAMING | 14813 #ifdef XPATH_STREAMING |
14808 comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base); | 14814 comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base); |
14809 if (comp != NULL) { | 14815 if (comp != NULL) { |
14810 if (ctxt->comp != NULL) | 14816 if (ctxt->comp != NULL) |
14811 xmlXPathFreeCompExpr(ctxt->comp); | 14817 xmlXPathFreeCompExpr(ctxt->comp); |
14812 ctxt->comp = comp; | 14818 ctxt->comp = comp; |
14813 if (ctxt->cur != NULL) | 14819 if (ctxt->cur != NULL) |
14814 while (*ctxt->cur != 0) ctxt->cur++; | 14820 while (*ctxt->cur != 0) ctxt->cur++; |
14815 } else | 14821 } else |
14816 #endif | 14822 #endif |
14817 { | 14823 { |
14818 xmlXPathCompileExpr(ctxt, 1); | 14824 xmlXPathCompileExpr(ctxt, 1); |
14819 /* | 14825 /* |
14820 * In this scenario the expression string will sit in ctxt->base. | 14826 * In this scenario the expression string will sit in ctxt->base. |
14821 */ | 14827 */ |
14822 if ((ctxt->error == XPATH_EXPRESSION_OK) && | 14828 if ((ctxt->error == XPATH_EXPRESSION_OK) && |
14823 (ctxt->comp != NULL) && | 14829 (ctxt->comp != NULL) && |
14824 (ctxt->base != NULL) && | 14830 (ctxt->base != NULL) && |
14825 (ctxt->comp->nbStep > 2) && | 14831 (ctxt->comp->nbStep > 2) && |
14826 (ctxt->comp->last >= 0) && | 14832 (ctxt->comp->last >= 0) && |
14827 (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1)) | 14833 (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1)) |
14828 { | 14834 { |
14829 xmlXPathRewriteDOSExpression(ctxt->comp, | 14835 xmlXPathRewriteDOSExpression(ctxt->comp, |
14830 &ctxt->comp->steps[ctxt->comp->last]); | 14836 &ctxt->comp->steps[ctxt->comp->last]); |
14831 } | 14837 } |
14832 } | 14838 } |
14833 CHECK_ERROR; | 14839 CHECK_ERROR; |
14834 xmlXPathRunEval(ctxt, 0); | 14840 xmlXPathRunEval(ctxt, 0); |
14835 } | 14841 } |
14836 | 14842 |
14837 /** | 14843 /** |
14838 * xmlXPathEval: | 14844 * xmlXPathEval: |
14839 * @str: the XPath expression | 14845 * @str: the XPath expression |
14840 * @ctx: the XPath context | 14846 * @ctx: the XPath context |
14841 * | 14847 * |
14842 * Evaluate the XPath Location Path in the given context. | 14848 * Evaluate the XPath Location Path in the given context. |
14843 * | 14849 * |
14844 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. | 14850 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. |
(...skipping 11 matching lines...) Expand all Loading... |
14856 | 14862 |
14857 ctxt = xmlXPathNewParserContext(str, ctx); | 14863 ctxt = xmlXPathNewParserContext(str, ctx); |
14858 if (ctxt == NULL) | 14864 if (ctxt == NULL) |
14859 return NULL; | 14865 return NULL; |
14860 xmlXPathEvalExpr(ctxt); | 14866 xmlXPathEvalExpr(ctxt); |
14861 | 14867 |
14862 if (ctxt->value == NULL) { | 14868 if (ctxt->value == NULL) { |
14863 xmlGenericError(xmlGenericErrorContext, | 14869 xmlGenericError(xmlGenericErrorContext, |
14864 "xmlXPathEval: evaluation failed\n"); | 14870 "xmlXPathEval: evaluation failed\n"); |
14865 res = NULL; | 14871 res = NULL; |
14866 } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL) | 14872 } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL) |
14867 #ifdef XPATH_STREAMING | 14873 #ifdef XPATH_STREAMING |
14868 && (ctxt->comp->stream == NULL) | 14874 && (ctxt->comp->stream == NULL) |
14869 #endif | 14875 #endif |
14870 ) { | 14876 ) { |
14871 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); | 14877 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR); |
14872 res = NULL; | 14878 res = NULL; |
14873 } else { | 14879 } else { |
14874 res = valuePop(ctxt); | 14880 res = valuePop(ctxt); |
14875 } | 14881 } |
14876 | 14882 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14969 * If $escape-reserved is true, all characters are escaped other than lower | 14975 * If $escape-reserved is true, all characters are escaped other than lower |
14970 * case letters a-z, upper case letters A-Z, digits 0-9, and the characters | 14976 * case letters a-z, upper case letters A-Z, digits 0-9, and the characters |
14971 * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!" | 14977 * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!" |
14972 * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only | 14978 * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only |
14973 * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and | 14979 * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and |
14974 * A-F). | 14980 * A-F). |
14975 * | 14981 * |
14976 * If $escape-reserved is false, the behavior differs in that characters | 14982 * If $escape-reserved is false, the behavior differs in that characters |
14977 * referred to in [RFC 2396] as reserved characters are not escaped. These | 14983 * referred to in [RFC 2396] as reserved characters are not escaped. These |
14978 * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",". | 14984 * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",". |
14979 * | 14985 * |
14980 * [RFC 2396] does not define whether escaped URIs should use lower case or | 14986 * [RFC 2396] does not define whether escaped URIs should use lower case or |
14981 * upper case for hexadecimal digits. To ensure that escaped URIs can be | 14987 * upper case for hexadecimal digits. To ensure that escaped URIs can be |
14982 * compared using string comparison functions, this function must always use | 14988 * compared using string comparison functions, this function must always use |
14983 * the upper-case letters A-F. | 14989 * the upper-case letters A-F. |
14984 * | 14990 * |
14985 * Generally, $escape-reserved should be set to true when escaping a string | 14991 * Generally, $escape-reserved should be set to true when escaping a string |
14986 * that is to form a single part of a URI, and to false when escaping an | 14992 * that is to form a single part of a URI, and to false when escaping an |
14987 * entire URI or URI reference. | 14993 * entire URI or URI reference. |
14988 * | 14994 * |
14989 * In the case of non-ascii characters, the string is encoded according to | 14995 * In the case of non-ascii characters, the string is encoded according to |
14990 * utf-8 and then converted according to RFC 2396. | 14996 * utf-8 and then converted according to RFC 2396. |
14991 * | 14997 * |
14992 * Examples | 14998 * Examples |
14993 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), true()) | 14999 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), true()) |
14994 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%
2FLos%20Angeles%23ocean" | 15000 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%
2FLos%20Angeles%23ocean" |
14995 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), false()) | 15001 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2
0Angeles#ocean"), false()) |
14996 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angele
s%23ocean" | 15002 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angele
s%23ocean" |
14997 * | 15003 * |
14998 */ | 15004 */ |
14999 static void | 15005 static void |
15000 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { | 15006 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
15001 xmlXPathObjectPtr str; | 15007 xmlXPathObjectPtr str; |
15002 int escape_reserved; | 15008 int escape_reserved; |
15003 xmlBufferPtr target; | 15009 xmlBufferPtr target; |
15004 xmlChar *cptr; | 15010 xmlChar *cptr; |
15005 xmlChar escape[4]; | 15011 xmlChar escape[4]; |
15006 | 15012 |
15007 CHECK_ARITY(2); | 15013 CHECK_ARITY(2); |
15008 | 15014 |
15009 escape_reserved = xmlXPathPopBoolean(ctxt); | 15015 escape_reserved = xmlXPathPopBoolean(ctxt); |
15010 | 15016 |
15011 CAST_TO_STRING; | 15017 CAST_TO_STRING; |
15012 str = valuePop(ctxt); | 15018 str = valuePop(ctxt); |
15013 | 15019 |
15014 target = xmlBufferCreate(); | 15020 target = xmlBufferCreate(); |
15015 | 15021 |
15016 escape[0] = '%'; | 15022 escape[0] = '%'; |
15017 escape[3] = 0; | 15023 escape[3] = 0; |
15018 | 15024 |
15019 if (target) { | 15025 if (target) { |
15020 for (cptr = str->stringval; *cptr; cptr++) { | 15026 for (cptr = str->stringval; *cptr; cptr++) { |
15021 if ((*cptr >= 'A' && *cptr <= 'Z') || | 15027 if ((*cptr >= 'A' && *cptr <= 'Z') || |
15022 (*cptr >= 'a' && *cptr <= 'z') || | 15028 (*cptr >= 'a' && *cptr <= 'z') || |
15023 (*cptr >= '0' && *cptr <= '9') || | 15029 (*cptr >= '0' && *cptr <= '9') || |
15024 » » *cptr == '-' || *cptr == '_' || *cptr == '.' || | 15030 » » *cptr == '-' || *cptr == '_' || *cptr == '.' || |
15025 *cptr == '!' || *cptr == '~' || *cptr == '*' || | 15031 *cptr == '!' || *cptr == '~' || *cptr == '*' || |
15026 *cptr == '\''|| *cptr == '(' || *cptr == ')' || | 15032 *cptr == '\''|| *cptr == '(' || *cptr == ')' || |
15027 » » (*cptr == '%' && | 15033 » » (*cptr == '%' && |
15028 ((cptr[1] >= 'A' && cptr[1] <= 'F') || | 15034 ((cptr[1] >= 'A' && cptr[1] <= 'F') || |
15029 (cptr[1] >= 'a' && cptr[1] <= 'f') || | 15035 (cptr[1] >= 'a' && cptr[1] <= 'f') || |
15030 (cptr[1] >= '0' && cptr[1] <= '9')) && | 15036 (cptr[1] >= '0' && cptr[1] <= '9')) && |
15031 ((cptr[2] >= 'A' && cptr[2] <= 'F') || | 15037 ((cptr[2] >= 'A' && cptr[2] <= 'F') || |
15032 (cptr[2] >= 'a' && cptr[2] <= 'f') || | 15038 (cptr[2] >= 'a' && cptr[2] <= 'f') || |
15033 (cptr[2] >= '0' && cptr[2] <= '9'))) || | 15039 (cptr[2] >= '0' && cptr[2] <= '9'))) || |
15034 (!escape_reserved && | 15040 (!escape_reserved && |
15035 (*cptr == ';' || *cptr == '/' || *cptr == '?' || | 15041 (*cptr == ';' || *cptr == '/' || *cptr == '?' || |
15036 *cptr == ':' || *cptr == '@' || *cptr == '&' || | 15042 *cptr == ':' || *cptr == '@' || *cptr == '&' || |
15037 *cptr == '=' || *cptr == '+' || *cptr == '$' || | 15043 *cptr == '=' || *cptr == '+' || *cptr == '$' || |
15038 *cptr == ','))) { | 15044 *cptr == ','))) { |
15039 xmlBufferAdd(target, cptr, 1); | 15045 xmlBufferAdd(target, cptr, 1); |
15040 } else { | 15046 } else { |
15041 if ((*cptr >> 4) < 10) | 15047 if ((*cptr >> 4) < 10) |
15042 escape[1] = '0' + (*cptr >> 4); | 15048 escape[1] = '0' + (*cptr >> 4); |
15043 else | 15049 else |
15044 escape[1] = 'A' - 10 + (*cptr >> 4); | 15050 escape[1] = 'A' - 10 + (*cptr >> 4); |
15045 if ((*cptr & 0xF) < 10) | 15051 if ((*cptr & 0xF) < 10) |
15046 escape[2] = '0' + (*cptr & 0xF); | 15052 escape[2] = '0' + (*cptr & 0xF); |
15047 else | 15053 else |
15048 escape[2] = 'A' - 10 + (*cptr & 0xF); | 15054 escape[2] = 'A' - 10 + (*cptr & 0xF); |
15049 » » | 15055 |
15050 xmlBufferAdd(target, &escape[0], 3); | 15056 xmlBufferAdd(target, &escape[0], 3); |
15051 } | 15057 } |
15052 } | 15058 } |
15053 } | 15059 } |
15054 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, | 15060 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, |
15055 xmlBufferContent(target))); | 15061 xmlBufferContent(target))); |
15056 xmlBufferFree(target); | 15062 xmlBufferFree(target); |
15057 xmlXPathReleaseObject(ctxt->context, str); | 15063 xmlXPathReleaseObject(ctxt->context, str); |
15058 } | 15064 } |
15059 | 15065 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15122 xmlXPathTranslateFunction); | 15128 xmlXPathTranslateFunction); |
15123 | 15129 |
15124 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", | 15130 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", |
15125 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", | 15131 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", |
15126 xmlXPathEscapeUriFunction); | 15132 xmlXPathEscapeUriFunction); |
15127 } | 15133 } |
15128 | 15134 |
15129 #endif /* LIBXML_XPATH_ENABLED */ | 15135 #endif /* LIBXML_XPATH_ENABLED */ |
15130 #define bottom_xpath | 15136 #define bottom_xpath |
15131 #include "elfgcchack.h" | 15137 #include "elfgcchack.h" |
OLD | NEW |