⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pattern.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (stream->blockLevel != -1) {
	    /*
	    * Skip blocked expressions.
	    */
    	    stream->level++;
	    goto stream_next;
	}
	/*
	 * Check evolution of existing states
	 */
	i = 0;
	m = stream->nbState;
	while (i < m) {
	    if ((comp->flags & XML_STREAM_DESC) == 0) {
		/*
		* If there is no "//", then only the last
		* added state is of interest.
		*/
		step = stream->states[2 * (stream->nbState -1)];
		/*
		* TODO: Security check, should not happen, remove it.
		*/
		if (stream->states[(2 * (stream->nbState -1)) + 1] <
		    stream->level) {
		    return (-1);
		}
		desc = 0;
		/* loop-stopper */
		i = m;
	    } else {
		/*
		* If there are "//", then we need to process every "//"
		* occuring in the states, plus any other state for this
		* level.
		*/		
		step = stream->states[2 * i];

		/* TODO: should not happen anymore: dead states */
		if (step < 0)
		    goto next_state;

		tmp = stream->states[(2 * i) + 1];

		/* skip new states just added */
		if (tmp > stream->level)
		    goto next_state;

		/* skip states at ancestor levels, except if "//" */
		desc = comp->steps[step].flags & XML_STREAM_STEP_DESC;
		if ((tmp < stream->level) && (!desc))
		    goto next_state;
	    }
	    /* 
	    * Check for correct node-type.
	    */
	    if ((nodeType == XML_ATTRIBUTE_NODE) && 
		((comp->steps[step].flags & XML_STREAM_STEP_ATTR) == 0))
		goto next_state;
	    /*
	    * Compare local/namespace-name.
	    */
	    match = 0;
	    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);
		    }
		}
	    }
	    if (((comp->flags & XML_STREAM_DESC) == 0) &&
		((! match) || final))  {
		/*
		* Mark this expression as blocked for any evaluation at
		* deeper levels. Note that this includes "/foo"
		* expressions if the *pattern* behaviour is used.
		*/
		stream->blockLevel = stream->level +1;
	    }
next_state:
	    i++;
	}

	stream->level++;

	/*
	* Re/enter the expression.
	*/
	if (comp->steps[0].flags & XML_STREAM_STEP_ROOT)
	    goto stream_next;

	desc = comp->steps[0].flags & XML_STREAM_STEP_DESC;
	if (stream->flags & XML_PATTERN_NOTPATTERN) {
	    /*
	    * Re/enter the expression if it is a "descendant" one,
	    * or if we are at the 1st level of evaluation.
	    */
	    
	    if (stream->level == 1) {
		if (XML_STREAM_XS_IDC(stream)) {
		    /*
		    * XS-IDC: The missing "self::node()" will always
		    * match the first given node.
		    */
		    goto stream_next;
		} else
		    goto compare;
	    }	    
	    /*
	    * A "//" is always reentrant.
	    */
	    if (desc)
		goto compare;

	    /*
	    * XS-IDC: Process the 2nd level, since the missing
	    * "self::node()" is responsible for the 2nd level being
	    * the real start level.	    
	    */	    
	    if ((stream->level == 2) && XML_STREAM_XS_IDC(stream))
		goto compare;

	    goto stream_next;
	}
	
compare:
	/*
	* Check expected node-type.
	*/
	if ((nodeType == XML_ATTRIBUTE_NODE) && 
	    ((comp->steps[0].flags & XML_STREAM_STEP_ATTR) == 0))
	    goto stream_next;
	/*
	* Compare local/namespace-name.
	*/
	match = 0;
	if (comp->steps[0].name == NULL) {
	    if (comp->steps[0].ns == NULL)
		match = 1;
	    else {
		if (comp->dict)
		    match = (comp->steps[0].ns == ns);
		else
		    match = xmlStrEqual(comp->steps[0].ns, ns);
	    }
	} else {
	    if (comp->dict)
		match = ((comp->steps[0].name == name) &&
		    (comp->steps[0].ns == ns));
	    else
		match = ((xmlStrEqual(comp->steps[0].name, name)) &&
		    (xmlStrEqual(comp->steps[0].ns, ns)));
	}
	if (match) {
	    final = comp->steps[0].flags & XML_STREAM_STEP_FINAL;
	    if (final)
		ret = 1;
	    else
		xmlStreamCtxtAddState(stream, 1, stream->level);
	}
	if (((comp->flags & XML_STREAM_DESC) == 0) &&
	    ((! match) || final))  {
	    /*
	    * Mark this expression as blocked for any evaluation at
	    * deeper levels.
	    */
	    stream->blockLevel = 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 dictionary, 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.
 */
int
xmlStreamPush(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 dictionary, 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.
*/
int
xmlStreamPushAttr(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.
 */
int
xmlStreamPop(xmlStreamCtxtPtr stream) {
    int i, lev;
    int ret;

    if (stream == NULL)
        return(-1);
    ret = 0;
    while (stream != NULL) {
	/*
	* Reset block-level.
	*/
	if (stream->blockLevel == stream->level)
	    stream->blockLevel = -1;

	stream->level--;
	if (stream->level < 0)
	    ret = -1;		
	/*
	 * Check evolution of existing states
	 */	
	for (i = stream->nbState -1; i >= 0; i--) {
	    /* discard obsoleted states */
	    lev = stream->states[(2 * i) + 1];
	    if (lev > stream->level)
		stream->nbState--;
	    if (lev <= stream->level)
		break;
	}
	stream = stream->next;
    }
    return(0);
}

/************************************************************************
 *									*
 *			The public interfaces				*
 *									*
 ************************************************************************/

/**
 * xmlPatterncompile:
 * @pattern: the pattern to compile
 * @dict: an optional dictionary for interned strings
 * @flags: compilation flags, undefined yet
 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
 *
 * Compile a pattern.
 *
 * Returns the compiled form of the pattern or NULL in case of error
 */
xmlPatternPtr
xmlPatterncompile(const xmlChar *pattern, xmlDict *dict,
                  xmlPatternFlags flags,
                  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);
	ctxt = NULL;


        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 whether the node matches the pattern
 *
 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
 */
int
xmlPatternMatch(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
 */
xmlStreamCtxtPtr
xmlPatternGetStreamCtxt(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.
 */
int
xmlPatternStreamable(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
 */
int
xmlPatternMaxDepth(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
 */
int
xmlPatternFromRoot(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 + -