first implementation for | support Daniel
* pattern.c: first implementation for | support
Daniel
diff --git a/pattern.c b/pattern.c
index 6645224..c28bf29 100644
--- a/pattern.c
+++ b/pattern.c
@@ -66,6 +66,7 @@
};
struct _xmlStreamCtxt {
+ struct _xmlStreamCtxt *next;/* link to next sub pattern if | */
xmlStreamCompPtr comp; /* the compiled stream */
int nbState; /* number of state in the automata */
int maxState; /* allocated number of state */
@@ -118,7 +119,7 @@
struct _xmlPattern {
void *data; /* the associated template */
xmlDictPtr dict; /* the optional dictionnary */
- struct _xmlPattern *next; /* siblings */
+ struct _xmlPattern *next; /* next pattern if | is used */
const xmlChar *pattern; /* the pattern */
int nbStep;
@@ -188,6 +189,8 @@
if (comp == NULL)
return;
+ if (comp->next != NULL)
+ xmlFreePattern(comp->next);
if (comp->stream != NULL)
xmlFreeStreamComp(comp->stream);
if (comp->pattern != NULL)
@@ -1362,132 +1365,132 @@
int
xmlStreamPush(xmlStreamCtxtPtr stream,
const xmlChar *name, const xmlChar *ns) {
- int ret = 0, tmp, i, m, match, step, desc, final;
+ int ret = 0, err = 0, tmp, i, m, match, step, desc, final;
xmlStreamCompPtr comp;
if ((stream == NULL) || (stream->nbState < 0))
return(-1);
- comp = stream->comp;
- if ((name == NULL) && (ns == NULL)) {
- stream->nbState = 0;
- stream->level = 0;
- if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
- tmp = xmlStreamCtxtAddState(stream, 0, 0);
- if (tmp < 0)
- return(-1);
- if (comp->steps[tmp].flags & XML_STREAM_STEP_FINAL)
- return(1);
- }
- return(0);
- }
- /*
- * Check evolution of existing states
- */
- m = stream->nbState;
- for (i = 0;i < m;i++) {
- match = 0;
- step = stream->states[2 * i];
- /* dead states */
- if (step < 0) continue;
- /* skip new states just added */
- if (stream->states[(2 * i) + 1] > stream->level) continue;
- /* skip continuations */
- desc = comp->steps[step].flags & XML_STREAM_STEP_DESC;
- if ((stream->states[(2 * i) + 1] < stream->level) && (!desc))continue;
- /* discard old states */
- /* something needed about old level discarded */
-
- if (comp->dict) {
- if (comp->steps[step].name == NULL) {
- if (comp->steps[step].ns == NULL)
- match = 1;
- else
- match = (comp->steps[step].ns == ns);
- } else {
- match = ((comp->steps[step].name == name) &&
- (comp->steps[step].ns == ns));
- }
- } else {
- if (comp->steps[step].name == NULL) {
- if (comp->steps[step].ns == NULL)
- match = 1;
- else
- match = xmlStrEqual(comp->steps[step].ns, ns);
- } else {
- match = ((xmlStrEqual(comp->steps[step].name, name)) &&
- (xmlStrEqual(comp->steps[step].ns, ns)));
- }
- }
- if (match) {
- final = comp->steps[step].flags & XML_STREAM_STEP_FINAL;
- if (desc) {
- if (final) {
+ while (stream != NULL) {
+ comp = stream->comp;
+ if ((name == NULL) && (ns == NULL)) {
+ stream->nbState = 0;
+ stream->level = 0;
+ if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
+ tmp = xmlStreamCtxtAddState(stream, 0, 0);
+ if (tmp < 0)
+ err++;
+ if (comp->steps[tmp].flags & XML_STREAM_STEP_FINAL)
ret = 1;
+ continue; /* while */
+ }
+ continue; /* while */
+ }
+ /*
+ * Check evolution of existing states
+ */
+ m = stream->nbState;
+ for (i = 0;i < m;i++) {
+ match = 0;
+ step = stream->states[2 * i];
+ /* dead states */
+ if (step < 0) continue;
+ /* skip new states just added */
+ if (stream->states[(2 * i) + 1] > stream->level)
+ continue;
+ /* skip continuations */
+ desc = comp->steps[step].flags & XML_STREAM_STEP_DESC;
+ if ((stream->states[(2 * i) + 1] < stream->level) && (!desc))
+ continue;
+
+ /* discard old states */
+ /* something needed about old level discarded */
+
+ if (comp->dict) {
+ if (comp->steps[step].name == NULL) {
+ if (comp->steps[step].ns == NULL)
+ match = 1;
+ else
+ match = (comp->steps[step].ns == ns);
} else {
- /* descending match create a new state */
- xmlStreamCtxtAddState(stream, step + 1, stream->level + 1);
+ match = ((comp->steps[step].name == name) &&
+ (comp->steps[step].ns == ns));
}
} else {
- if (final) {
- ret = 1;
-#if 0
- stream->states[2 * i] = -1;
-#endif
+ if (comp->steps[step].name == NULL) {
+ if (comp->steps[step].ns == NULL)
+ match = 1;
+ else
+ match = xmlStrEqual(comp->steps[step].ns, ns);
} else {
-#if 0
- stream->states[2 * i] = step + 1;
- stream->states[2 * i + 1] = stream->level + 1;
-#endif
- xmlStreamCtxtAddState(stream, step + 1, stream->level + 1);
+ match = ((xmlStrEqual(comp->steps[step].name, name)) &&
+ (xmlStrEqual(comp->steps[step].ns, ns)));
}
}
-#if 0
- } else if (!desc) {
- /* didn't match, discard */
- stream->states[2 * i] = -1;
-#endif
+ if (match) {
+ final = comp->steps[step].flags & XML_STREAM_STEP_FINAL;
+ if (desc) {
+ if (final) {
+ ret = 1;
+ } else {
+ /* descending match create a new state */
+ xmlStreamCtxtAddState(stream, step + 1,
+ stream->level + 1);
+ }
+ } else {
+ if (final) {
+ ret = 1;
+ } else {
+ xmlStreamCtxtAddState(stream, step + 1,
+ stream->level + 1);
+ }
+ }
+ }
}
- }
- /*
- * Check creating a new state.
- */
- stream->level++;
- if (!(comp->steps[0].flags & XML_STREAM_STEP_ROOT)) {
- match = 0;
- if (comp->dict) {
- if (comp->steps[0].name == NULL) {
- if (comp->steps[0].ns == NULL)
- match = 1;
- else
- match = (comp->steps[0].ns == ns);
+ /*
+ * Check creating a new state.
+ */
+ stream->level++;
+ if (!(comp->steps[0].flags & XML_STREAM_STEP_ROOT)) {
+ match = 0;
+ if (comp->dict) {
+ if (comp->steps[0].name == NULL) {
+ if (comp->steps[0].ns == NULL)
+ match = 1;
+ else
+ match = (comp->steps[0].ns == ns);
+ } else {
+ match = ((comp->steps[0].name == name) &&
+ (comp->steps[0].ns == ns));
+ }
} else {
- match = ((comp->steps[0].name == name) &&
- (comp->steps[0].ns == ns));
+ if (comp->steps[0].name == NULL) {
+ if (comp->steps[0].ns == NULL)
+ match = 1;
+ else
+ match = xmlStrEqual(comp->steps[0].ns, ns);
+ } else {
+ match = ((xmlStrEqual(comp->steps[0].name, name)) &&
+ (xmlStrEqual(comp->steps[0].ns, ns)));
+ }
}
- } else {
- if (comp->steps[0].name == NULL) {
- if (comp->steps[0].ns == NULL)
- match = 1;
+ if (match) {
+ if (comp->steps[0].flags & XML_STREAM_STEP_FINAL)
+ ret = 1;
else
- match = xmlStrEqual(comp->steps[0].ns, ns);
- } else {
- match = ((xmlStrEqual(comp->steps[0].name, name)) &&
- (xmlStrEqual(comp->steps[0].ns, ns)));
+ xmlStreamCtxtAddState(stream, 1, stream->level);
}
}
- if (match) {
- if (comp->steps[0].flags & XML_STREAM_STEP_FINAL)
- ret = 1;
- else
- xmlStreamCtxtAddState(stream, 1, stream->level);
- }
- }
+
+ stream = stream->next;
+ } /* while stream != NULL */
#ifdef DEBUG_STREAMING
xmlDebugStreamCtxt(stream, ret);
#endif
+ if (err > 0)
+ ret = -1;
return(ret);
}
@@ -1502,22 +1505,27 @@
int
xmlStreamPop(xmlStreamCtxtPtr stream) {
int i, m;
+ int ret;
if (stream == NULL)
return(-1);
- stream->level--;
- if (stream->level < 0)
- return(-1);
-
- /*
- * Check evolution of existing states
- */
- m = stream->nbState;
- for (i = 0;i < m;i++) {
- if (stream->states[(2 * i)] < 0) break;
- /* discard obsoleted states */
- if (stream->states[(2 * i) + 1] > stream->level)
- stream->states[(2 * i)] = -1;
+ ret = 0;
+ while (stream != NULL) {
+ stream->level--;
+ if (stream->level < 0)
+ ret = -1;
+
+ /*
+ * Check evolution of existing states
+ */
+ m = stream->nbState;
+ for (i = 0;i < m;i++) {
+ if (stream->states[(2 * i)] < 0) break;
+ /* discard obsoleted states */
+ if (stream->states[(2 * i) + 1] > stream->level)
+ stream->states[(2 * i)] = -1;
+ }
+ stream = stream->next;
}
return(0);
}
@@ -1543,25 +1551,57 @@
xmlPatterncompile(const xmlChar *pattern, xmlDict *dict,
int flags ATTRIBUTE_UNUSED,
const xmlChar **namespaces) {
- xmlPatternPtr ret = NULL;
+ xmlPatternPtr ret = NULL, cur;
xmlPatParserContextPtr ctxt = NULL;
+ const xmlChar *or, *start;
+ xmlChar *tmp = NULL;
- ctxt = xmlNewPatParserContext(pattern, dict, namespaces);
- if (ctxt == NULL) goto error;
- ret = xmlNewPattern();
- if (ret == NULL) goto error;
- ctxt->comp = ret;
+ if (pattern == NULL)
+ return(NULL);
- xmlCompilePathPattern(ctxt);
- xmlFreePatParserContext(ctxt);
+ start = pattern;
+ while (*or != 0) {
+ or = start;
+ tmp = NULL;
+ while ((*or != 0) && (*or != '|')) or++;
+ if (*or == 0)
+ ctxt = xmlNewPatParserContext(start, dict, namespaces);
+ else {
+ tmp = xmlStrndup(start, or - start);
+ if (tmp != NULL) {
+ ctxt = xmlNewPatParserContext(tmp, dict, namespaces);
+ }
+ or++;
+ }
+ if (ctxt == NULL) goto error;
+ cur = xmlNewPattern();
+ if (cur == NULL) goto error;
+ if (ret == NULL)
+ ret = cur;
+ else {
+ cur->next = ret->next;
+ ret->next = cur;
+ }
+ ctxt->comp = cur;
- xmlStreamCompile(ret);
- if (xmlReversePattern(ret) < 0)
- goto error;
+ xmlCompilePathPattern(ctxt);
+ xmlFreePatParserContext(ctxt);
+
+
+ xmlStreamCompile(cur);
+ if (xmlReversePattern(cur) < 0)
+ goto error;
+ start = or;
+ if (tmp != NULL) {
+ xmlFree(tmp);
+ tmp = NULL;
+ }
+ }
return(ret);
error:
if (ctxt != NULL) xmlFreePatParserContext(ctxt);
if (ret != NULL) xmlFreePattern(ret);
+ if (tmp != NULL) xmlFree(tmp);
return(NULL);
}
@@ -1577,9 +1617,18 @@
int
xmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node)
{
+ int ret = 0;
+
if ((comp == NULL) || (node == NULL))
return(-1);
- return(xmlPatMatch(comp, node));
+
+ while (comp != NULL) {
+ ret = xmlPatMatch(comp, node);
+ if (ret != 0)
+ return(ret);
+ comp = comp->next;
+ }
+ return(ret);
}
/**
@@ -1594,9 +1643,29 @@
xmlStreamCtxtPtr
xmlPatternGetStreamCtxt(xmlPatternPtr comp)
{
+ xmlStreamCtxtPtr ret = NULL, cur;
+
if ((comp == NULL) || (comp->stream == NULL))
return(NULL);
- return(xmlNewStreamCtxt(comp->stream));
+
+ while (comp != NULL) {
+ if (comp->stream == NULL)
+ goto failed;
+ cur = xmlNewStreamCtxt(comp->stream);
+ if (cur == NULL)
+ goto failed;
+ if (ret == NULL)
+ ret = cur;
+ else {
+ cur->next = ret->next;
+ ret->next = cur;
+ }
+ comp = comp->next;
+ }
+ return(ret);
+failed:
+ xmlFreeStreamCtxt(ret);
+ return(NULL);
}
#endif /* LIBXML_PATTERN_ENABLED */