diff --git a/ChangeLog b/ChangeLog index df3c002f..50a6e656 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Feb 21 11:41:41 CET 2005 Daniel Veillard + + * pattern.c xpath.c: fixed remaining known bugs in the XPath streaming, + and switched XPath to use it by default when possible + Sat Feb 19 19:25:14 CET 2005 Daniel Veillard * xmlschemastypes.c: a bit of cleanup diff --git a/pattern.c b/pattern.c index 560dc20b..22d5c31d 100644 --- a/pattern.c +++ b/pattern.c @@ -231,6 +231,7 @@ xmlFreePatternList(xmlPatternPtr comp) { while (comp != NULL) { cur = comp; comp = comp->next; + cur->next = NULL; xmlFreePattern(cur); } } @@ -1081,6 +1082,10 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { xmlFree(name); } } else if (CUR == '*') { + if (name != NULL) { + ctxt->error = 1; + goto error; + } NEXT; PUSH(XML_OP_ALL, token, NULL); } else { @@ -1350,7 +1355,19 @@ xmlStreamCompile(xmlPatternPtr comp) { stream->dict = comp->dict; xmlDictReference(stream->dict); } - for (i = 0;i < comp->nbStep;i++) { + + /* + * Skip leading ./ on relative paths + */ + i = 0; + while ((comp->flags & PAT_FROM_CUR) && (comp->nbStep > i + 2) && + (comp->steps[i].op == XML_OP_ELEM) && + (comp->steps[i].value == NULL) && + (comp->steps[i].value2 == NULL) && + (comp->steps[i + 1].op == XML_OP_PARENT)) { + i += 2; + } + for (;i < comp->nbStep;i++) { switch (comp->steps[i].op) { case XML_OP_END: break; @@ -1374,8 +1391,15 @@ xmlStreamCompile(xmlPatternPtr comp) { if (s < 0) goto error; break; - case XML_OP_CHILD: case XML_OP_ELEM: + if ((comp->steps[i].value == NULL) && + (comp->steps[i].value2 == NULL) && + (comp->nbStep > i + 2) && + (comp->steps[i + 1].op == XML_OP_PARENT)) { + i++; + continue; + } + case XML_OP_CHILD: s = xmlStreamCompAddStep(stream, comp->steps[i].value, comp->steps[i].value2, flags); flags = 0; @@ -1389,6 +1413,13 @@ xmlStreamCompile(xmlPatternPtr comp) { goto error; break; case XML_OP_PARENT: + if ((comp->nbStep > i + 1) && + (comp->steps[i + 1].op == XML_OP_ELEM) && + (comp->steps[i + 1].value == NULL) && + (comp->steps[i + 1].value2 == NULL)) { + i++; + continue; + } break; case XML_OP_ANCESTOR: flags |= XML_STREAM_STEP_DESC; @@ -1816,6 +1847,8 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, xmlPatParserContextPtr ctxt = NULL; const xmlChar *or, *start; xmlChar *tmp = NULL; + int type = 0; + int streamable = 1; if (pattern == NULL) return(NULL); @@ -1851,7 +1884,19 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, xmlFreePatParserContext(ctxt); - xmlStreamCompile(cur); + if (streamable) { + if (type == 0) { + type = cur->flags & (PAT_FROM_ROOT | PAT_FROM_CUR); + } else if (type == PAT_FROM_ROOT) { + if (cur->flags & PAT_FROM_CUR) + streamable = 0; + } else if (type == PAT_FROM_CUR) { + if (cur->flags & PAT_FROM_ROOT) + streamable = 0; + } + } + if (streamable) + xmlStreamCompile(cur); if (xmlReversePattern(cur) < 0) goto error; if (tmp != NULL) { @@ -1860,6 +1905,16 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, } start = or; } + if (streamable == 0) { + cur = ret; + while (cur != NULL) { + if (cur->stream != NULL) { + xmlFreeStreamComp(cur->stream); + cur->stream = NULL; + } + cur = cur->next; + } + } return(ret); error: if (ctxt != NULL) xmlFreePatParserContext(ctxt); diff --git a/xpath.c b/xpath.c index 4e7941e7..c5bbf2a5 100644 --- a/xpath.c +++ b/xpath.c @@ -56,16 +56,7 @@ #endif #ifdef LIBXML_PATTERN_ENABLED -/* currently only in testing for DV as it's not yet solid enough for XSLT */ -/* - * TODO: - * - fix the | where there is both relative and absolute expressions - * probably need new pattens APIs to separate both e.g "//b | a " - * - fix also the 0 depth trick used for "/" and "." when or'ed - * - double check /. is a noop - * - libxslt tests show a mem leak of a few bytes - */ -/* #define XPATH_STREAMING */ +#define XPATH_STREAMING #endif #define TODO \ @@ -10963,13 +10954,14 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp) { from_root = xmlPatternFromRoot(comp); if (from_root < 0) return(NULL); -/* printf("stream eval: depth %d from root %d\n", max_depth, from_root); */ +#if 0 + printf("stream eval: depth %d from root %d\n", max_depth, from_root); +#endif retval = xmlXPathNewNodeSet(NULL); if (retval == NULL) return(NULL); - /* FIXME '. | /' */ if ((from_root) && (max_depth == 0)) { xmlXPathNodeSetAddUnique(retval->nodesetval, (xmlNodePtr) ctxt->doc); return(retval); @@ -11085,8 +11077,10 @@ scan_children: } while ((cur != NULL) && (depth >= 0)); done: -/* printf("stream eval: checked %d nodes selected %d\n", - nb_nodes, retval->nodesetval->nodeNr); */ +#if 0 + printf("stream eval: checked %d nodes selected %d\n", + nb_nodes, retval->nodesetval->nodeNr); +#endif xmlFreeStreamCtxt(patstream); return(retval); }