📄 pattern.c
字号:
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->nbStep == 0) ret = 1; stream = stream->next; continue; /* while */ } stream = stream->next; continue; /* while */ } /* * Fast check for ".". */ if (comp->nbStep == 0) { if (nodeType == XML_ELEMENT_NODE) ret = 1; goto stream_next; } /* * 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 */ /* * Check for correct node-type. */ if ((comp->steps[step].flags & XML_STREAM_STEP_ATTR) && (nodeType != XML_ATTRIBUTE_NODE)) continue; 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) { 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++; /* * Check the start only if this is a "desc" evaluation * or if we are at the first level of evaluation. */ desc = comp->steps[0].flags & XML_STREAM_STEP_DESC; if ( ((comp->steps[0].flags & XML_STREAM_STEP_ROOT) == 0) && ( ((stream->flags & XML_PATTERN_NOTPATTERN) == 0) || ( (desc || (stream->level == 1)) ) ) ) {/*#ifdef SUPPORT_IDC if ((desc || (stream->level == 1)) && (!(comp->steps[0].flags & XML_STREAM_STEP_ROOT))) { * * Workaround for missing "self::node()" on "@foo". * if (comp->steps[0].flags & XML_STREAM_STEP_ATTR) { xmlStreamCtxtAddState(stream, 0, stream->level); goto stream_next; }#else if (!(comp->steps[0].flags & XML_STREAM_STEP_ROOT)) {#endif */ 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 { if (stream->flags & XML_PATTERN_NOTPATTERN) { /* * Workaround for missing "self::node() on "foo". */ if (!desc) { xmlStreamCtxtAddState(stream, 0, stream->level); goto stream_next; } else { match = ((comp->steps[0].name == name) && (comp->steps[0].ns == ns)); } } else { match = ((comp->steps[0].name == name) && (comp->steps[0].ns == ns)); } } } else { if (comp->steps[0].name == NULL) { if (comp->steps[0].ns == NULL) match = 1; else match = xmlStrEqual(comp->steps[0].ns, ns); } else { if (stream->flags & XML_PATTERN_NOTPATTERN) { /* * Workaround for missing "self::node() on "foo". */ if (!desc) { xmlStreamCtxtAddState(stream, 0, stream->level); goto stream_next; } else { match = ((xmlStrEqual(comp->steps[0].name, name)) && (xmlStrEqual(comp->steps[0].ns, ns))); } } else { match = ((xmlStrEqual(comp->steps[0].name, name)) && (xmlStrEqual(comp->steps[0].ns, ns))); } } } if (match) { if (comp->steps[0].flags & XML_STREAM_STEP_FINAL) ret = 1; else xmlStreamCtxtAddState(stream, 1, stream->level); } }stream_next: stream = stream->next; } /* while stream != NULL */ if (err > 0) ret = -1;#ifdef DEBUG_STREAMING xmlDebugStreamCtxt(orig, ret);#endif return(ret);}/** * xmlStreamPush: * @stream: the stream context * @name: the current name * @ns: the namespace name * * push new data onto the stream. NOTE: if the call xmlPatterncompile() * indicated a dictionnary, then strings for name and ns will be expected * to come from the dictionary. * Both @name and @ns being NULL means the / i.e. the root of the document. * This can also act as a reset. * * Returns: -1 in case of error, 1 if the current state in the stream is a * match and 0 otherwise. */intxmlStreamPush(xmlStreamCtxtPtr stream, const xmlChar *name, const xmlChar *ns) { return (xmlStreamPushInternal(stream, name, ns, XML_ELEMENT_NODE));}/*** xmlStreamPushAttr:* @stream: the stream context* @name: the current name* @ns: the namespace name** push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()* indicated a dictionnary, then strings for name and ns will be expected* to come from the dictionary.* Both @name and @ns being NULL means the / i.e. the root of the document.* This can also act as a reset.** Returns: -1 in case of error, 1 if the current state in the stream is a* match and 0 otherwise.*/intxmlStreamPushAttr(xmlStreamCtxtPtr stream, const xmlChar *name, const xmlChar *ns) { return (xmlStreamPushInternal(stream, name, ns, XML_ATTRIBUTE_NODE));}/** * xmlStreamPop: * @stream: the stream context * * push one level from the stream. * * Returns: -1 in case of error, 0 otherwise. */intxmlStreamPop(xmlStreamCtxtPtr stream) { int i, m; int ret; if (stream == NULL) return(-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);}/************************************************************************ * * * The public interfaces * * * ************************************************************************//** * xmlPatterncompile: * @pattern: the pattern to compile * @dict: an optional dictionnary for interned strings * @flags: compilation flags, undefined yet * @namespaces: the prefix definitions, array of [URI, prefix] or NULL * * Compile a pattern. * * Returns the compiled for of the pattern or NULL in case of error */xmlPatternPtrxmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags ATTRIBUTE_UNUSED, const xmlChar **namespaces) { xmlPatternPtr ret = NULL, cur; xmlPatParserContextPtr ctxt = NULL; const xmlChar *or, *start; xmlChar *tmp = NULL; int type = 0; int streamable = 1; if (pattern == NULL) return(NULL); start = pattern; or = start; while (*or != 0) { 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; } cur->flags = flags; ctxt->comp = cur; xmlCompilePathPattern(ctxt); if (ctxt->error != 0) goto error; 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); if (xmlReversePattern(cur) < 0) goto error; if (tmp != NULL) { xmlFree(tmp); tmp = NULL; } 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); if (ret != NULL) xmlFreePattern(ret); if (tmp != NULL) xmlFree(tmp); return(NULL);}/** * xmlPatternMatch: * @comp: the precompiled pattern * @node: a node * * Test wether the node matches the pattern * * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure */intxmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node){ int ret = 0; if ((comp == NULL) || (node == NULL)) return(-1); while (comp != NULL) { ret = xmlPatMatch(comp, node); if (ret != 0) return(ret); comp = comp->next; } return(ret);}/** * xmlPatternGetStreamCtxt: * @comp: the precompiled pattern * * Get a streaming context for that pattern * Use xmlFreeStreamCtxt to free the context. * * Returns a pointer to the context or NULL in case of failure */xmlStreamCtxtPtrxmlPatternGetStreamCtxt(xmlPatternPtr comp){ xmlStreamCtxtPtr ret = NULL, cur; if ((comp == NULL) || (comp->stream == NULL)) return(NULL); 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; } cur->flags = comp->flags; comp = comp->next; } return(ret);failed: xmlFreeStreamCtxt(ret); return(NULL);}/** * xmlPatternStreamable: * @comp: the precompiled pattern * * Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt() * should work. * * Returns 1 if streamable, 0 if not and -1 in case of error. */intxmlPatternStreamable(xmlPatternPtr comp) { if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(0); comp = comp->next; } return(1);}/** * xmlPatternMaxDepth: * @comp: the precompiled pattern * * Check the maximum depth reachable by a pattern * * Returns -2 if no limit (using //), otherwise the depth, * and -1 in case of error */intxmlPatternMaxDepth(xmlPatternPtr comp) { int ret = 0, i; if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(-1); for (i = 0;i < comp->stream->nbStep;i++) if (comp->stream->steps[i].flags & XML_STREAM_STEP_DESC) return(-2); if (comp->stream->nbStep > ret) ret = comp->stream->nbStep; comp = comp->next; } return(ret);}/** * xmlPatternFromRoot: * @comp: the precompiled pattern * * Check if the pattern must be looked at from the root. * * Returns 1 if true, 0 if false and -1 in case of error */intxmlPatternFromRoot(xmlPatternPtr comp) { if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(-1); if (comp->flags & PAT_FROM_ROOT) return(1); comp = comp->next; } return(0);}#define bottom_pattern#include "elfgcchack.h"#endif /* LIBXML_PATTERN_ENABLED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -