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 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 comp->steps[comp->nbStep].value5 = (xmlChar *) | 1125 comp->steps[comp->nbStep].value5 = (xmlChar *) |
1126 (void *)xmlDictLookup(comp->dict, value5, -1); | 1126 (void *)xmlDictLookup(comp->dict, value5, -1); |
1127 xmlFree(value5); | 1127 xmlFree(value5); |
1128 } else | 1128 } else |
1129 comp->steps[comp->nbStep].value5 = NULL; | 1129 comp->steps[comp->nbStep].value5 = NULL; |
1130 } else { | 1130 } else { |
1131 comp->steps[comp->nbStep].value4 = value4; | 1131 comp->steps[comp->nbStep].value4 = value4; |
1132 comp->steps[comp->nbStep].value5 = value5; | 1132 comp->steps[comp->nbStep].value5 = value5; |
1133 } | 1133 } |
1134 comp->steps[comp->nbStep].cache = NULL; | 1134 comp->steps[comp->nbStep].cache = NULL; |
| 1135 comp->steps[comp->nbStep].cacheURI = NULL; |
1135 return(comp->nbStep++); | 1136 return(comp->nbStep++); |
1136 } | 1137 } |
1137 | 1138 |
1138 /** | 1139 /** |
1139 * xmlXPathCompSwap: | 1140 * xmlXPathCompSwap: |
1140 * @comp: the compiled expression | 1141 * @comp: the compiled expression |
1141 * @op: operation index | 1142 * @op: operation index |
1142 * | 1143 * |
1143 * Swaps 2 operations in the compiled expression | 1144 * Swaps 2 operations in the compiled expression |
1144 */ | 1145 */ |
(...skipping 13580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14725 xmlDictReference(comp->dict); | 14726 xmlDictReference(comp->dict); |
14726 return(comp); | 14727 return(comp); |
14727 } | 14728 } |
14728 xmlFreePattern(stream); | 14729 xmlFreePattern(stream); |
14729 } | 14730 } |
14730 return(NULL); | 14731 return(NULL); |
14731 } | 14732 } |
14732 #endif /* XPATH_STREAMING */ | 14733 #endif /* XPATH_STREAMING */ |
14733 | 14734 |
14734 static void | 14735 static void |
14735 xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) | 14736 xmlXPathOptimizeExpressionInternal(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr o
p) |
14736 { | 14737 { |
| 14738 /* Already optimized? */ |
| 14739 if (op->cacheURI != NULL) |
| 14740 return; |
| 14741 |
14737 /* | 14742 /* |
14738 * Try to rewrite "descendant-or-self::node()/foo" to an optimized | 14743 * Try to rewrite "descendant-or-self::node()/foo" to an optimized |
14739 * internal representation. | 14744 * internal representation. |
14740 */ | 14745 */ |
14741 | 14746 |
14742 if ((op->op == XPATH_OP_COLLECT /* 11 */) && | 14747 if ((op->op == XPATH_OP_COLLECT /* 11 */) && |
14743 (op->ch1 != -1) && | 14748 (op->ch1 != -1) && |
14744 (op->ch2 == -1 /* no predicate */)) | 14749 (op->ch2 == -1 /* no predicate */)) |
14745 { | 14750 { |
14746 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1]; | 14751 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1]; |
(...skipping 30 matching lines...) Expand all Loading... |
14777 */ | 14782 */ |
14778 op->ch1 = prevop->ch1; | 14783 op->ch1 = prevop->ch1; |
14779 op->value = AXIS_DESCENDANT_OR_SELF; | 14784 op->value = AXIS_DESCENDANT_OR_SELF; |
14780 break; | 14785 break; |
14781 default: | 14786 default: |
14782 break; | 14787 break; |
14783 } | 14788 } |
14784 } | 14789 } |
14785 } | 14790 } |
14786 | 14791 |
| 14792 /* Mark the node. */ |
| 14793 op->cacheURI = (void*)(~0); |
| 14794 |
14787 /* Recurse */ | 14795 /* Recurse */ |
14788 if (op->ch1 != -1) | 14796 if (op->ch1 != -1) |
14789 xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]); | 14797 xmlXPathOptimizeExpressionInternal(comp, &comp->steps[op->ch1]); |
14790 if (op->ch2 != -1) | 14798 if (op->ch2 != -1) |
14791 » xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]); | 14799 » xmlXPathOptimizeExpressionInternal(comp, &comp->steps[op->ch2]); |
| 14800 } |
| 14801 |
| 14802 static void |
| 14803 xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, int root) |
| 14804 { |
| 14805 int i; |
| 14806 /* The expression tree/graph traversal is linear, visiting |
| 14807 * each node at most once. Mark each xmlXPathStepOp node |
| 14808 * upon visiting, taking care of clearing out the marks |
| 14809 * afterwards. |
| 14810 */ |
| 14811 xmlXPathOptimizeExpressionInternal(comp, &comp->steps[root]); |
| 14812 for (i = 0; i <= root; ++i) |
| 14813 comp->steps[i].cacheURI = NULL; |
14792 } | 14814 } |
14793 | 14815 |
14794 /** | 14816 /** |
14795 * xmlXPathCtxtCompile: | 14817 * xmlXPathCtxtCompile: |
14796 * @ctxt: an XPath context | 14818 * @ctxt: an XPath context |
14797 * @str: the XPath expression | 14819 * @str: the XPath expression |
14798 * | 14820 * |
14799 * Compile an XPath expression | 14821 * Compile an XPath expression |
14800 * | 14822 * |
14801 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. | 14823 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14840 } | 14862 } |
14841 xmlXPathFreeParserContext(pctxt); | 14863 xmlXPathFreeParserContext(pctxt); |
14842 | 14864 |
14843 if (comp != NULL) { | 14865 if (comp != NULL) { |
14844 comp->expr = xmlStrdup(str); | 14866 comp->expr = xmlStrdup(str); |
14845 #ifdef DEBUG_EVAL_COUNTS | 14867 #ifdef DEBUG_EVAL_COUNTS |
14846 comp->string = xmlStrdup(str); | 14868 comp->string = xmlStrdup(str); |
14847 comp->nb = 0; | 14869 comp->nb = 0; |
14848 #endif | 14870 #endif |
14849 if ((comp->nbStep > 1) && (comp->last >= 0)) { | 14871 if ((comp->nbStep > 1) && (comp->last >= 0)) { |
14850 » xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]); | 14872 » xmlXPathOptimizeExpression(comp, comp->last); |
14851 } | 14873 } |
14852 } | 14874 } |
14853 return(comp); | 14875 return(comp); |
14854 } | 14876 } |
14855 | 14877 |
14856 /** | 14878 /** |
14857 * xmlXPathCompile: | 14879 * xmlXPathCompile: |
14858 * @str: the XPath expression | 14880 * @str: the XPath expression |
14859 * | 14881 * |
14860 * Compile an XPath expression | 14882 * Compile an XPath expression |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15022 while (*ctxt->cur != 0) ctxt->cur++; | 15044 while (*ctxt->cur != 0) ctxt->cur++; |
15023 } else | 15045 } else |
15024 #endif | 15046 #endif |
15025 { | 15047 { |
15026 xmlXPathCompileExpr(ctxt, 1); | 15048 xmlXPathCompileExpr(ctxt, 1); |
15027 if ((ctxt->error == XPATH_EXPRESSION_OK) && | 15049 if ((ctxt->error == XPATH_EXPRESSION_OK) && |
15028 (ctxt->comp != NULL) && | 15050 (ctxt->comp != NULL) && |
15029 (ctxt->comp->nbStep > 1) && | 15051 (ctxt->comp->nbStep > 1) && |
15030 (ctxt->comp->last >= 0)) | 15052 (ctxt->comp->last >= 0)) |
15031 { | 15053 { |
15032 » xmlXPathOptimizeExpression(ctxt->comp, | 15054 » xmlXPathOptimizeExpression(ctxt->comp, ctxt->comp->last); |
15033 » » &ctxt->comp->steps[ctxt->comp->last]); | |
15034 } | 15055 } |
15035 } | 15056 } |
15036 CHECK_ERROR; | 15057 CHECK_ERROR; |
15037 xmlXPathRunEval(ctxt, 0); | 15058 xmlXPathRunEval(ctxt, 0); |
15038 } | 15059 } |
15039 | 15060 |
15040 /** | 15061 /** |
15041 * xmlXPathEval: | 15062 * xmlXPathEval: |
15042 * @str: the XPath expression | 15063 * @str: the XPath expression |
15043 * @ctx: the XPath context | 15064 * @ctx: the XPath context |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15368 xmlXPathTranslateFunction); | 15389 xmlXPathTranslateFunction); |
15369 | 15390 |
15370 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", | 15391 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", |
15371 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", | 15392 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", |
15372 xmlXPathEscapeUriFunction); | 15393 xmlXPathEscapeUriFunction); |
15373 } | 15394 } |
15374 | 15395 |
15375 #endif /* LIBXML_XPATH_ENABLED */ | 15396 #endif /* LIBXML_XPATH_ENABLED */ |
15376 #define bottom_xpath | 15397 #define bottom_xpath |
15377 #include "elfgcchack.h" | 15398 #include "elfgcchack.h" |
OLD | NEW |