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

📄 pattern.c

📁 xml开源解析代码.版本为libxml2-2.6.29,可支持GB3212.网络消息发送XML时很有用.
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * Returns -1 in case of failure and 0 in case of success. */static intxmlStreamCompile(xmlPatternPtr comp) {    xmlStreamCompPtr stream;    int i, s = 0, root = 0, flags = 0, prevs = -1;    xmlStepOp step;    if ((comp == NULL) || (comp->steps == NULL))        return(-1);    /*     * special case for .     */    if ((comp->nbStep == 1) &&        (comp->steps[0].op == XML_OP_ELEM) &&	(comp->steps[0].value == NULL) &&	(comp->steps[0].value2 == NULL)) {	stream = xmlNewStreamComp(0);	if (stream == NULL)	    return(-1);	/* Note that the stream will have no steps in this case. */	stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;	comp->stream = stream;	return(0);    }    stream = xmlNewStreamComp((comp->nbStep / 2) + 1);    if (stream == NULL)        return(-1);    if (comp->dict != NULL) {        stream->dict = comp->dict;	xmlDictReference(stream->dict);    }    i = 0;            if (comp->flags & PAT_FROM_ROOT)	stream->flags |= XML_STREAM_FROM_ROOT;    for (;i < comp->nbStep;i++) {	step = comp->steps[i];        switch (step.op) {	    case XML_OP_END:	        break;	    case XML_OP_ROOT:	        if (i != 0)		    goto error;		root = 1;		break;	    case XML_OP_NS:		s = xmlStreamCompAddStep(stream, NULL, step.value,		    XML_ELEMENT_NODE, flags);				if (s < 0)		    goto error;		prevs = s;		flags = 0;				break;	    	    case XML_OP_ATTR:		flags |= XML_STREAM_STEP_ATTR;		prevs = -1;		s = xmlStreamCompAddStep(stream,		    step.value, step.value2, XML_ATTRIBUTE_NODE, flags);		flags = 0;		if (s < 0)		    goto error;		break;	    case XML_OP_ELEM:			        if ((step.value == NULL) && (step.value2 == NULL)) {		    /*		    * We have a "." or "self::node()" here.		    * Eliminate redundant self::node() tests like in "/./."		    * or "//./"		    * The only case we won't eliminate is "//.", i.e. if		    * self::node() is the last node test and we had		    * continuation somewhere beforehand.		    */		    if ((comp->nbStep == i + 1) &&			(flags & XML_STREAM_STEP_DESC)) {			/*			* Mark the special case where the expression resolves			* to any type of node.			*/			if (comp->nbStep == i + 1) {			    stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;			}			flags |= XML_STREAM_STEP_NODE;						s = xmlStreamCompAddStep(stream, NULL, NULL,			    XML_STREAM_ANY_NODE, flags);			if (s < 0)			    goto error;			flags = 0;			/*			* If there was a previous step, mark it to be added to			* the result node-set; this is needed since only			* the last step will be marked as "final" and only			* "final" nodes are added to the resulting set.			*/			if (prevs != -1) {			    stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET;			    prevs = -1;			}			break;			    } else {			/* Just skip this one. */			continue;		    }		}		/* An element node. */			        s = xmlStreamCompAddStep(stream, step.value, step.value2,		    XML_ELEMENT_NODE, flags);				if (s < 0)		    goto error;		prevs = s;		flags = 0;				break;			    case XML_OP_CHILD:		/* An element node child. */	        s = xmlStreamCompAddStep(stream, step.value, step.value2,		    XML_ELEMENT_NODE, flags);				if (s < 0)		    goto error;		prevs = s;		flags = 0;		break;	    	    case XML_OP_ALL:	        s = xmlStreamCompAddStep(stream, NULL, NULL,		    XML_ELEMENT_NODE, flags);				if (s < 0)		    goto error;		prevs = s;		flags = 0;		break;	    case XML_OP_PARENT:		        break;	    case XML_OP_ANCESTOR:		/* Skip redundant continuations. */		if (flags & XML_STREAM_STEP_DESC)		    break;	        flags |= XML_STREAM_STEP_DESC;		/*		* Mark the expression as having "//".		*/		if ((stream->flags & XML_STREAM_DESC) == 0)		    stream->flags |= XML_STREAM_DESC;		break;	}    }        if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) {	/*	* If this should behave like a real pattern, we will mark	* the first step as having "//", to be reentrant on every	* tree level.	*/	if ((stream->flags & XML_STREAM_DESC) == 0)	    stream->flags |= XML_STREAM_DESC;	if (stream->nbStep > 0) {	    if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0)		stream->steps[0].flags |= XML_STREAM_STEP_DESC;	    	}    }    if (stream->nbStep <= s)	goto error;    stream->steps[s].flags |= XML_STREAM_STEP_FINAL;    if (root)	stream->steps[0].flags |= XML_STREAM_STEP_ROOT;#ifdef DEBUG_STREAMING    xmlDebugStreamComp(stream);#endif    comp->stream = stream;    return(0);error:    xmlFreeStreamComp(stream);    return(0);}/** * xmlNewStreamCtxt: * @size: the number of expected states * * build a new stream context * * Returns the new structure or NULL in case of error. */static xmlStreamCtxtPtrxmlNewStreamCtxt(xmlStreamCompPtr stream) {    xmlStreamCtxtPtr cur;    cur = (xmlStreamCtxtPtr) xmlMalloc(sizeof(xmlStreamCtxt));    if (cur == NULL) {	ERROR(NULL, NULL, NULL,		"xmlNewStreamCtxt: malloc failed\n");	return(NULL);    }    memset(cur, 0, sizeof(xmlStreamCtxt));    cur->states = (int *) xmlMalloc(4 * 2 * sizeof(int));    if (cur->states == NULL) {	xmlFree(cur);	ERROR(NULL, NULL, NULL,	      "xmlNewStreamCtxt: malloc failed\n");	return(NULL);    }    cur->nbState = 0;    cur->maxState = 4;    cur->level = 0;    cur->comp = stream;    cur->blockLevel = -1;    return(cur);}/** * xmlFreeStreamCtxt: * @stream: the stream context * * Free the stream context */voidxmlFreeStreamCtxt(xmlStreamCtxtPtr stream) {    xmlStreamCtxtPtr next;    while (stream != NULL) {        next = stream->next;        if (stream->states != NULL)	    xmlFree(stream->states);        xmlFree(stream);	stream = next;    }}/** * xmlStreamCtxtAddState: * @comp: the stream context * @idx: the step index for that streaming state * * Add a new state to the stream context * * Returns -1 in case of error or the state index if successful */static intxmlStreamCtxtAddState(xmlStreamCtxtPtr comp, int idx, int level) {    int i;    for (i = 0;i < comp->nbState;i++) {        if (comp->states[2 * i] < 0) {	    comp->states[2 * i] = idx;	    comp->states[2 * i + 1] = level;	    return(i);	}    }    if (comp->nbState >= comp->maxState) {        int *cur;	cur = (int *) xmlRealloc(comp->states,				 comp->maxState * 4 * sizeof(int));	if (cur == NULL) {	    ERROR(NULL, NULL, NULL,		  "xmlNewStreamCtxt: malloc failed\n");	    return(-1);	}	comp->states = cur;        comp->maxState *= 2;    }    comp->states[2 * comp->nbState] = idx;    comp->states[2 * comp->nbState++ + 1] = level;    return(comp->nbState - 1);}/** * xmlStreamPushInternal: * @stream: the stream context * @name: the current name * @ns: the namespace name * @nodeType: the type of the node * * 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. */static intxmlStreamPushInternal(xmlStreamCtxtPtr stream,		      const xmlChar *name, const xmlChar *ns,		      int nodeType) {    int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;    xmlStreamCompPtr comp;    xmlStreamStep step;#ifdef DEBUG_STREAMING    xmlStreamCtxtPtr orig = stream;#endif    if ((stream == NULL) || (stream->nbState < 0))        return(-1);    while (stream != NULL) {	comp = stream->comp;	if ((nodeType == XML_ELEMENT_NODE) &&	    (name == NULL) && (ns == NULL)) {	    /* We have a document node here (or a reset). */	    stream->nbState = 0;	    stream->level = 0;	    stream->blockLevel = -1;	    if (comp->flags & XML_STREAM_FROM_ROOT) {		if (comp->nbStep == 0) {		    /* TODO: We have a "/." here? */		    ret = 1;		} else {		    if ((comp->nbStep == 1) &&			(comp->steps[0].nodeType == XML_STREAM_ANY_NODE) &&			(comp->steps[0].flags & XML_STREAM_STEP_DESC))		    {			/*			* In the case of "//." the document node will match			* as well.			*/			ret = 1;		    } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {			/* TODO: Do we need this ? */			tmp = xmlStreamCtxtAddState(stream, 0, 0);			if (tmp < 0)			    err++;		    }		}	    }	    stream = stream->next;	    continue; /* while */	}	/*	* Fast check for ".".	*/	if (comp->nbStep == 0) {	    /*	     * / and . are handled at the XPath node set creation	     * level by checking min depth	     */	    if (stream->flags & XML_PATTERN_XPATH) {		stream = stream->next;		continue; /* while */	    }	    /*	    * For non-pattern like evaluation like XML Schema IDCs	    * or traditional XPath expressions, this will match if	    * we are at the first level only, otherwise on every level.	    */	    if ((nodeType != XML_ATTRIBUTE_NODE) &&		(((stream->flags & XML_PATTERN_NOTPATTERN) == 0) ||		(stream->level == 0))) {		    ret = 1;			    }	    stream->level++;	    goto stream_next;	}	if (stream->blockLevel != -1) {	    /*	    * Skip blocked expressions.	    */    	    stream->level++;	    goto stream_next;	}	if ((nodeType != XML_ELEMENT_NODE) &&	    (nodeType != XML_ATTRIBUTE_NODE) &&	    ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) {	    /*	    * No need to process nodes of other types if we don't	    * resolve to those types.	    * TODO: Do we need to block the context here?	    */	    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.		*/		stepNr = 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.		*/				stepNr = stream->states[2 * i];		/* TODO: should not happen anymore: dead states */		if (stepNr < 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[stepNr].flags & XML_STREAM_STEP_DESC;		if ((tmp < stream->level) && (!desc))		    goto next_state;	    }	    /* 	    * Check for correct node-type.	    */	    step = comp->steps[stepNr];	    if (step.nodeType != nodeType) {		if (step.nodeType == XML_ATTRIBUTE_NODE) {		    /*		    * Block this expression for deeper evaluation.		    */		    if ((comp->flags & XML_STREAM_DESC) == 0)			stream->blockLevel = stream->level +1;		    goto next_state;		} else if (step.nodeType != XML_STREAM_ANY_NODE)		    goto next_state;	    }	    	    /*	    * Compare local/namespace-name.	    */	    match = 0;	    if (step.nodeType == XML_STREAM_ANY_NODE) {		match = 1;	    } else if (step.name == NULL) {		if (step.ns == NULL) {		    /*		    * This lets through all elements/attributes.		    */		    match = 1;		} else if (ns != NULL)		    match = xmlStrEqual(step.ns, ns);	    } else if (((step.ns != NULL) == (ns != NULL)) &&		(name != NULL) &&		(step.name[0] == name[0]) &&		xmlStrEqual(step.name, name) &&		((step.ns == ns) || xmlStrEqual(step.ns, ns)))	    {		match = 1;	    	    }	 #if 0 /** TODO: Pointer comparison won't work, since not guaranteed that the given*  values are in the same dict; especially if it's the namespace name,*  normally coming from ns->href. We need a namespace dict mechanism !*/	    } else if (comp->dict) {		if (step.name == NULL) {		    if (step.ns == NULL)			match = 1;		    else			match = (step.ns == ns);		} else {		    match = ((step.name == name) && (step.ns == ns));		}#endif /* if 0 ------------------------------------------------------- */	    	    if (match) {				final = step.flags & XML_STREAM_STEP_FINAL;		if (desc) {		    if (final) {			ret = 1;		    } else {			/* descending match create a new state */			xmlStreamCtxtAddState(stream, stepNr + 1,			                      stream->level + 1);		    }		} else {		    if (final) {			ret = 1;		    } else {			xmlStreamCtxtAddState(stream, stepNr + 1,			                      stream->level + 1);		    }		}		if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {		    /*		    * Check if we have a special case like "foo/bar//.", where		    * "foo" is selected as well.		    */		    ret = 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.	* Don't reenter if it's an absolute expression like "/foo",	*   except "//foo".	*/	step = comp->steps[0];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -