1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-21 14:53:44 +03:00

fixed remaining known bugs in the XPath streaming, and switched XPath to

* pattern.c xpath.c: fixed remaining known bugs in the XPath streaming,
  and switched XPath to use it by default when possible
Daniel
This commit is contained in:
Daniel Veillard
2005-02-21 10:44:36 +00:00
parent 5c4cb2d0e8
commit fa1f77f2f0
3 changed files with 71 additions and 17 deletions

View File

@@ -1,3 +1,8 @@
Mon Feb 21 11:41:41 CET 2005 Daniel Veillard <daniel@veillard.com>
* 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 <daniel@veillard.com> Sat Feb 19 19:25:14 CET 2005 Daniel Veillard <daniel@veillard.com>
* xmlschemastypes.c: a bit of cleanup * xmlschemastypes.c: a bit of cleanup

View File

@@ -231,6 +231,7 @@ xmlFreePatternList(xmlPatternPtr comp) {
while (comp != NULL) { while (comp != NULL) {
cur = comp; cur = comp;
comp = comp->next; comp = comp->next;
cur->next = NULL;
xmlFreePattern(cur); xmlFreePattern(cur);
} }
} }
@@ -1081,6 +1082,10 @@ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
xmlFree(name); xmlFree(name);
} }
} else if (CUR == '*') { } else if (CUR == '*') {
if (name != NULL) {
ctxt->error = 1;
goto error;
}
NEXT; NEXT;
PUSH(XML_OP_ALL, token, NULL); PUSH(XML_OP_ALL, token, NULL);
} else { } else {
@@ -1350,7 +1355,19 @@ xmlStreamCompile(xmlPatternPtr comp) {
stream->dict = comp->dict; stream->dict = comp->dict;
xmlDictReference(stream->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) { switch (comp->steps[i].op) {
case XML_OP_END: case XML_OP_END:
break; break;
@@ -1374,8 +1391,15 @@ xmlStreamCompile(xmlPatternPtr comp) {
if (s < 0) if (s < 0)
goto error; goto error;
break; break;
case XML_OP_CHILD:
case XML_OP_ELEM: 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, s = xmlStreamCompAddStep(stream, comp->steps[i].value,
comp->steps[i].value2, flags); comp->steps[i].value2, flags);
flags = 0; flags = 0;
@@ -1389,6 +1413,13 @@ xmlStreamCompile(xmlPatternPtr comp) {
goto error; goto error;
break; break;
case XML_OP_PARENT: 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; break;
case XML_OP_ANCESTOR: case XML_OP_ANCESTOR:
flags |= XML_STREAM_STEP_DESC; flags |= XML_STREAM_STEP_DESC;
@@ -1816,6 +1847,8 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict,
xmlPatParserContextPtr ctxt = NULL; xmlPatParserContextPtr ctxt = NULL;
const xmlChar *or, *start; const xmlChar *or, *start;
xmlChar *tmp = NULL; xmlChar *tmp = NULL;
int type = 0;
int streamable = 1;
if (pattern == NULL) if (pattern == NULL)
return(NULL); return(NULL);
@@ -1851,6 +1884,18 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict,
xmlFreePatParserContext(ctxt); xmlFreePatParserContext(ctxt);
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); xmlStreamCompile(cur);
if (xmlReversePattern(cur) < 0) if (xmlReversePattern(cur) < 0)
goto error; goto error;
@@ -1860,6 +1905,16 @@ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict,
} }
start = or; 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); return(ret);
error: error:
if (ctxt != NULL) xmlFreePatParserContext(ctxt); if (ctxt != NULL) xmlFreePatParserContext(ctxt);

22
xpath.c
View File

@@ -56,16 +56,7 @@
#endif #endif
#ifdef LIBXML_PATTERN_ENABLED #ifdef LIBXML_PATTERN_ENABLED
/* currently only in testing for DV as it's not yet solid enough for XSLT */ #define XPATH_STREAMING
/*
* 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 */
#endif #endif
#define TODO \ #define TODO \
@@ -10963,13 +10954,14 @@ xmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp) {
from_root = xmlPatternFromRoot(comp); from_root = xmlPatternFromRoot(comp);
if (from_root < 0) if (from_root < 0)
return(NULL); 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); retval = xmlXPathNewNodeSet(NULL);
if (retval == NULL) if (retval == NULL)
return(NULL); return(NULL);
/* FIXME '. | /' */
if ((from_root) && (max_depth == 0)) { if ((from_root) && (max_depth == 0)) {
xmlXPathNodeSetAddUnique(retval->nodesetval, (xmlNodePtr) ctxt->doc); xmlXPathNodeSetAddUnique(retval->nodesetval, (xmlNodePtr) ctxt->doc);
return(retval); return(retval);
@@ -11085,8 +11077,10 @@ scan_children:
} while ((cur != NULL) && (depth >= 0)); } while ((cur != NULL) && (depth >= 0));
done: done:
/* printf("stream eval: checked %d nodes selected %d\n", #if 0
nb_nodes, retval->nodesetval->nodeNr); */ printf("stream eval: checked %d nodes selected %d\n",
nb_nodes, retval->nodesetval->nodeNr);
#endif
xmlFreeStreamCtxt(patstream); xmlFreeStreamCtxt(patstream);
return(retval); return(retval);
} }