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

📄 xpath.c

📁 SIP 1.5.0源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * xpath.c: XML Path Language implementation *          XPath is a language for addressing parts of an XML document, *          designed to be used by both XSLT and XPointer. * * Reference: W3C Working Draft internal 5 July 1999 *     http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html * Public reference: *     http://www.w3.org/TR/WD-xpath/ * * See COPYRIGHT for the status of this software * * Author: Daniel.Veillard@w3.org */#include "global.h"#ifdef WIN32#include "win32config.h"#else#include "config.h"#endif#include "xmlversion.h"#ifdef LIBXML_XPATH_ENABLED#include <stdio.h>#include <string.h>#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_MATH_H#include <math.h>#endif#ifdef HAVE_MATH_H#include <float.h>#endif#ifdef HAVE_IEEEFP_H#include <ieeefp.h>#endif#ifdef HAVE_NAN_H#include <nan.h>#endif#ifdef HAVE_CTYPE_H#include <ctype.h>#endif#include <libxml/xmlmemory.h>#include <libxml/tree.h>#include <libxml/valid.h>#include <libxml/xpath.h>#include <libxml/parserInternals.h>/* #define DEBUG *//* #define DEBUG_STEP *//* #define DEBUG_EXPR *//* * Setup stuff for floating point * The lack of portability of this section of the libc is annoying ! */double xmlXPathNAN = 0;double xmlXPathPINF = 1;double xmlXPathMINF = -1;#ifndef isinf#ifndef HAVE_ISINF#if HAVE_FPCLASSint isinf(double d) {    fpclass_t	type = fpclass(d);    switch (type) {	case FP_NINF:	    return(-1);	case FP_PINF:	    return(1);    }    return(0);}#elif defined(HAVE_FP_CLASS) || defined(HAVE_FP_CLASS_D)#if HAVE_FP_CLASS_H#include <fp_class.h>#endifint isinf(double d) {#if HAVE_FP_CLASS    int	fpclass = fp_class(d);#else    int	fpclass = fp_class_d(d);#endif    if (fpclass == FP_POS_INF)	return(1);    if (fpclass == FP_NEG_INF)	return(-1);    return(0);}#elif defined(HAVE_CLASS)int isinf(double d) {    int	fpclass = class(d);    if (fpclass == FP_PLUS_INF)	return(1);    if (fpclass == FP_MINUS_INF)	return(-1);    return(0);}#elif defined(finite) || defined(HAVE_FINITE)int isinf(double x) { return !finite(x) && x==x; }#elif defined(HUGE_VAL)int isinf(double x){    if (x == HUGE_VAL)        return(1);    if (x == -HUGE_VAL)        return(-1);    return(0);}#endif #endif /* ! HAVE_ISINF */#endif /* ! defined(isinf) */#ifndef isnan#ifndef HAVE_ISNAN#ifdef HAVE_ISNAND#define isnan(f) isnand(f)#endif /* HAVE_iSNAND */#endif /* ! HAVE_iSNAN */#endif /* ! defined(isnan) *//** * xmlXPathInit: * * Initialize the XPath environment */voidxmlXPathInit(void) {    static int initialized = 0;    if (initialized) return;    xmlXPathNAN = 0;    xmlXPathNAN /= 0;    xmlXPathPINF = 1;    xmlXPathPINF /= 0;    xmlXPathMINF = -1;    xmlXPathMINF /= 0;    initialized = 1;}FILE *xmlXPathDebug = NULL;#define TODO 								\    fprintf(xmlXPathDebug, "Unimplemented block at %s:%d\n",		\            __FILE__, __LINE__);#define STRANGE 							\    fprintf(xmlXPathDebug, "Internal error at %s:%d\n",			\            __FILE__, __LINE__);double xmlXPathStringEvalNumber(const xmlChar *str);void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);/************************************************************************ *									* * 		Parser stacks related functions and macros		* *									* ************************************************************************//* * Generic function for accessing stacks in the Parser Context */#define PUSH_AND_POP(type, name)					\extern int name##Push(xmlXPathParserContextPtr ctxt, type value) {	\    if (ctxt->name##Nr >= ctxt->name##Max) {				\	ctxt->name##Max *= 2;						\        ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab,		\	             ctxt->name##Max * sizeof(ctxt->name##Tab[0]));	\        if (ctxt->name##Tab == NULL) {					\	    fprintf(xmlXPathDebug, "realloc failed !\n");		\	    return(0);							\	}								\    }									\    ctxt->name##Tab[ctxt->name##Nr] = value;				\    ctxt->name = value;							\    return(ctxt->name##Nr++);						\}									\extern type name##Pop(xmlXPathParserContextPtr ctxt) {			\    type ret;								\    if (ctxt->name##Nr <= 0) return(0);					\    ctxt->name##Nr--;							\    if (ctxt->name##Nr > 0)						\	ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1];		\    else								\        ctxt->name = NULL;						\    ret = ctxt->name##Tab[ctxt->name##Nr];				\    ctxt->name##Tab[ctxt->name##Nr] = 0;				\    return(ret);							\}									\PUSH_AND_POP(xmlXPathObjectPtr, value)/* * Macros for accessing the content. Those should be used only by the parser, * and not exported. * * Dirty macros, i.e. one need to make assumption on the context to use them * *   CUR_PTR return the current pointer to the xmlChar to be parsed. *   CUR     returns the current xmlChar value, i.e. a 8 bit value *           in ISO-Latin or UTF-8. *           This should be used internally by the parser *           only to compare to ASCII values otherwise it would break when *           running with UTF-8 encoding. *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only *           to compare on ASCII based substring. *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined *           strings within the parser. *   CURRENT Returns the current char value, with the full decoding of *           UTF-8 if we are using this mode. It returns an int. *   NEXT    Skip to the next character, this does the proper decoding *           in UTF-8 mode. It also pop-up unfinished entities on the fly. *           It returns the pointer to the current xmlChar. */#define CUR (*ctxt->cur)#define SKIP(val) ctxt->cur += (val)#define NXT(val) ctxt->cur[(val)]#define CUR_PTR ctxt->cur#define SKIP_BLANKS 							\    while (IS_BLANK(*(ctxt->cur))) NEXT#define CURRENT (*ctxt->cur)#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)/************************************************************************ *									* *			Error handling routines				* *									* ************************************************************************/#define XPATH_EXPRESSION_OK		0#define XPATH_NUMBER_ERROR		1#define XPATH_UNFINISHED_LITERAL_ERROR	2#define XPATH_START_LITERAL_ERROR	3#define XPATH_VARIABLE_REF_ERROR	4#define XPATH_UNDEF_VARIABLE_ERROR	5#define XPATH_INVALID_PREDICATE_ERROR	6#define XPATH_EXPR_ERROR		7#define XPATH_UNCLOSED_ERROR		8#define XPATH_UNKNOWN_FUNC_ERROR	9#define XPATH_INVALID_OPERAND		10#define XPATH_INVALID_TYPE		11#define XPATH_INVALID_ARITY		12const char *xmlXPathErrorMessages[] = {    "Ok",    "Number encoding",    "Unfinished litteral",    "Start of litteral",    "Expected $ for variable reference",    "Undefined variable",    "Invalid predicate",    "Invalid expression",    "Missing closing curly brace",    "Unregistered function",    "Invalid operand",    "Invalid type",    "Invalid number of arguments",};/** * xmlXPathError: * @ctxt:  the XPath Parser context * @file:  the file name * @line:  the line number * @no:  the error number * * Create a new xmlNodeSetPtr of type double and of value @val * * Returns the newly created object. */voidxmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file,              int line, int no) {    int n;    const xmlChar *cur;    const xmlChar *base;    fprintf(xmlXPathDebug, "Error %s:%d: %s\n", file, line,            xmlXPathErrorMessages[no]);    cur = ctxt->cur;    base = ctxt->base;    while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {	cur--;    }    n = 0;    while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))        cur--;    if ((*cur == '\n') || (*cur == '\r')) cur++;    base = cur;    n = 0;    while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {        fprintf(xmlXPathDebug, "%c", (unsigned char) *cur++);	n++;    }    fprintf(xmlXPathDebug, "\n");    cur = ctxt->cur;    while ((*cur == '\n') || (*cur == '\r'))	cur--;    n = 0;    while ((cur != base) && (n++ < 80)) {        fprintf(xmlXPathDebug, " ");        base++;    }    fprintf(xmlXPathDebug,"^\n");}#define CHECK_ERROR							\    if (ctxt->error != XPATH_EXPRESSION_OK) return
#ifdef WIN32
#undef ERROR
#endif#define ERROR(X)							\    { xmlXPatherror(ctxt, __FILE__, __LINE__, X);			\      ctxt->error = (X); return; }#define ERROR0(X)							\    { xmlXPatherror(ctxt, __FILE__, __LINE__, X);			\      ctxt->error = (X); return(0); }#define CHECK_TYPE(typeval)						\    if ((ctxt->value == NULL) || (ctxt->value->type != typeval))	\        ERROR(XPATH_INVALID_TYPE)					\/************************************************************************ *									* *			Routines to handle NodeSets			* *									* ************************************************************************/#define XML_NODESET_DEFAULT	10/** * xmlXPathNodeSetCreate: * @val:  an initial xmlNodePtr, or NULL * * Create a new xmlNodeSetPtr of type double and of value @val * * Returns the newly created object. */xmlNodeSetPtrxmlXPathNodeSetCreate(xmlNodePtr val) {    xmlNodeSetPtr ret;    ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));    if (ret == NULL) {        fprintf(xmlXPathDebug, "xmlXPathNewNodeSet: out of memory\n");	return(NULL);    }    memset(ret, 0 , (size_t) sizeof(xmlNodeSet));    if (val != NULL) {        ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *					     sizeof(xmlNodePtr));	if (ret->nodeTab == NULL) {	    fprintf(xmlXPathDebug, "xmlXPathNewNodeSet: out of memory\n");	    return(NULL);	}	memset(ret->nodeTab, 0 ,	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));        ret->nodeMax = XML_NODESET_DEFAULT;	ret->nodeTab[ret->nodeNr++] = val;    }    return(ret);}/** * xmlXPathNodeSetAdd: * @cur:  the initial node set * @val:  a new xmlNodePtr * * add a new xmlNodePtr ot an existing NodeSet */voidxmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {    int i;    if (val == NULL) return;    /*     * check against doublons     */    for (i = 0;i < cur->nodeNr;i++)        if (cur->nodeTab[i] == val) return;    /*     * grow the nodeTab if needed     */    if (cur->nodeMax == 0) {        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *					     sizeof(xmlNodePtr));	if (cur->nodeTab == NULL) {	    fprintf(xmlXPathDebug, "xmlXPathNodeSetAdd: out of memory\n");	    return;	}	memset(cur->nodeTab, 0 ,	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));        cur->nodeMax = XML_NODESET_DEFAULT;    } else if (cur->nodeNr == cur->nodeMax) {        xmlNodePtr *temp;        cur->nodeMax *= 2;	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *				      sizeof(xmlNodePtr));	if (temp == NULL) {	    fprintf(xmlXPathDebug, "xmlXPathNodeSetAdd: out of memory\n");	    return;	}	cur->nodeTab = temp;    }    cur->nodeTab[cur->nodeNr++] = val;}/** * xmlXPathNodeSetMerge: * @val1:  the first NodeSet * @val2:  the second NodeSet * * Merges two nodesets, all nodes from @val2 are added to @val1 * * Returns val1 once extended or NULL in case of error. */xmlNodeSetPtrxmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {    int i;    if (val1 == NULL) return(NULL);    if (val2 == NULL) return(val1);    /*     * !!!!! this can be optimized a lot, knowing that both     *       val1 and val2 already have unicity of their values.     */    for (i = 0;i < val2->nodeNr;i++)        xmlXPathNodeSetAdd(val1, val2->nodeTab[i]);    return(val1);}/** * xmlXPathNodeSetDel: * @cur:  the initial node set * @val:  an xmlNodePtr * * Removes an xmlNodePtr from an existing NodeSet */voidxmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {    int i;    if (cur == NULL) return;    if (val == NULL) return;    /*     * check against doublons     */    for (i = 0;i < cur->nodeNr;i++)        if (cur->nodeTab[i] == val) break;

⌨️ 快捷键说明

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