📄 xpointer.c.svn-base
字号:
/* * xpointer.c : Code to handle XML Pointer * * Base implementation was made accordingly to * W3C Candidate Recommendation 7 June 2000 * http://www.w3.org/TR/2000/CR-xptr-20000607 * * Added support for the element() scheme described in: * W3C Proposed Recommendation 13 November 2002 * http://www.w3.org/TR/2002/PR-xptr-element-20021113/ * * See Copyright for the status of this software. * * daniel@veillard.com */#define IN_LIBXML#include "libxml.h"/* * TODO: better handling of error cases, the full expression should * be parsed beforehand instead of a progressive evaluation * TODO: Access into entities references are not supported now ... * need a start to be able to pop out of entities refs since * parent is the endity declaration, not the ref. */#include <string.h>#include <libxml/xpointer.h>#include <libxml/xmlmemory.h>#include <libxml/parserInternals.h>#include <libxml/uri.h>#include <libxml/xpath.h>#include <libxml/xpathInternals.h>#include <libxml/xmlerror.h>#include <libxml/globals.h>#ifdef LIBXML_XPTR_ENABLED/* Add support of the xmlns() xpointer scheme to initialize the namespaces */#define XPTR_XMLNS_SCHEME/* #define DEBUG_RANGES */#ifdef DEBUG_RANGES#ifdef LIBXML_DEBUG_ENABLED#include <libxml/debugXML.h>#endif#endif#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);#define STRANGE \ xmlGenericError(xmlGenericErrorContext, \ "Internal error at %s:%d\n", \ __FILE__, __LINE__);/************************************************************************ * * * Some factorized error routines * * * ************************************************************************//** * xmlXPtrErrMemory: * @extra: extra informations * * Handle a redefinition of attribute error */static voidxmlXPtrErrMemory(const char *extra){ __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER, XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra, NULL, NULL, 0, 0, "Memory allocation failed : %s\n", extra);}/** * xmlXPtrErr: * @ctxt: an XPTR evaluation context * @extra: extra informations * * Handle a redefinition of attribute error */static voidxmlXPtrErr(xmlXPathParserContextPtr ctxt, int error, const char * msg, const xmlChar *extra){ if (ctxt != NULL) ctxt->error = error; if ((ctxt == NULL) || (ctxt->context == NULL)) { __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER, error, XML_ERR_ERROR, NULL, 0, (const char *) extra, NULL, NULL, 0, 0, msg, extra); return; } ctxt->context->lastError.domain = XML_FROM_XPOINTER; ctxt->context->lastError.code = error; ctxt->context->lastError.level = XML_ERR_ERROR; ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base); ctxt->context->lastError.int1 = ctxt->cur - ctxt->base; ctxt->context->lastError.node = ctxt->context->debugNode; if (ctxt->context->error != NULL) { ctxt->context->error(ctxt->context->userData, &ctxt->context->lastError); } else { __xmlRaiseError(NULL, NULL, NULL, NULL, ctxt->context->debugNode, XML_FROM_XPOINTER, error, XML_ERR_ERROR, NULL, 0, (const char *) extra, (const char *) ctxt->base, NULL, ctxt->cur - ctxt->base, 0, msg, extra); }}/************************************************************************ * * * A few helper functions for child sequences * * * ************************************************************************//* xmlXPtrAdvanceNode is a private function, but used by xinclude.c */xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level);/** * xmlXPtrGetArity: * @cur: the node * * Returns the number of child for an element, -1 in case of error */static intxmlXPtrGetArity(xmlNodePtr cur) { int i; if (cur == NULL) return(-1); cur = cur->children; for (i = 0;cur != NULL;cur = cur->next) { if ((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)) { i++; } } return(i);}/** * xmlXPtrGetIndex: * @cur: the node * * Returns the index of the node in its parent children list, -1 * in case of error */static intxmlXPtrGetIndex(xmlNodePtr cur) { int i; if (cur == NULL) return(-1); for (i = 1;cur != NULL;cur = cur->prev) { if ((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)) { i++; } } return(i);}/** * xmlXPtrGetNthChild: * @cur: the node * @no: the child number * * Returns the @no'th element child of @cur or NULL */static xmlNodePtrxmlXPtrGetNthChild(xmlNodePtr cur, int no) { int i; if (cur == NULL) return(cur); cur = cur->children; for (i = 0;i <= no;cur = cur->next) { if (cur == NULL) return(cur); if ((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)) { i++; if (i == no) break; } } return(cur);}/************************************************************************ * * * Handling of XPointer specific types * * * ************************************************************************//** * xmlXPtrCmpPoints: * @node1: the first node * @index1: the first index * @node2: the second node * @index2: the second index * * Compare two points w.r.t document order * * Returns -2 in case of error 1 if first point < second point, 0 if * that's the same point, -1 otherwise */static intxmlXPtrCmpPoints(xmlNodePtr node1, int index1, xmlNodePtr node2, int index2) { if ((node1 == NULL) || (node2 == NULL)) return(-2); /* * a couple of optimizations which will avoid computations in most cases */ if (node1 == node2) { if (index1 < index2) return(1); if (index1 > index2) return(-1); return(0); } return(xmlXPathCmpNodes(node1, node2));}/** * xmlXPtrNewPoint: * @node: the xmlNodePtr * @indx: the indx within the node * * Create a new xmlXPathObjectPtr of type point * * Returns the newly created object. */static xmlXPathObjectPtrxmlXPtrNewPoint(xmlNodePtr node, int indx) { xmlXPathObjectPtr ret; if (node == NULL) return(NULL); if (indx < 0) return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { xmlXPtrErrMemory("allocating point"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); ret->type = XPATH_POINT; ret->user = (void *) node; ret->index = indx; return(ret);}/** * xmlXPtrRangeCheckOrder: * @range: an object range * * Make sure the points in the range are in the right order */static voidxmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) { int tmp; xmlNodePtr tmp2; if (range == NULL) return; if (range->type != XPATH_RANGE) return; if (range->user2 == NULL) return; tmp = xmlXPtrCmpPoints(range->user, range->index, range->user2, range->index2); if (tmp == -1) { tmp2 = range->user; range->user = range->user2; range->user2 = tmp2; tmp = range->index; range->index = range->index2; range->index2 = tmp; }}/** * xmlXPtrRangesEqual: * @range1: the first range * @range2: the second range * * Compare two ranges * * Returns 1 if equal, 0 otherwise */static intxmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) { if (range1 == range2) return(1); if ((range1 == NULL) || (range2 == NULL)) return(0); if (range1->type != range2->type) return(0); if (range1->type != XPATH_RANGE) return(0); if (range1->user != range2->user) return(0); if (range1->index != range2->index) return(0); if (range1->user2 != range2->user2) return(0); if (range1->index2 != range2->index2) return(0); return(1);}/** * xmlXPtrNewRange: * @start: the starting node * @startindex: the start index * @end: the ending point * @endindex: the ending index * * Create a new xmlXPathObjectPtr of type range * * Returns the newly created object. */xmlXPathObjectPtrxmlXPtrNewRange(xmlNodePtr start, int startindex, xmlNodePtr end, int endindex) { xmlXPathObjectPtr ret; if (start == NULL) return(NULL); if (end == NULL) return(NULL); if (startindex < 0) return(NULL); if (endindex < 0) return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { xmlXPtrErrMemory("allocating range"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); ret->type = XPATH_RANGE; ret->user = start; ret->index = startindex; ret->user2 = end; ret->index2 = endindex; xmlXPtrRangeCheckOrder(ret); return(ret);}/** * xmlXPtrNewRangePoints: * @start: the starting point * @end: the ending point * * Create a new xmlXPathObjectPtr of type range using 2 Points * * Returns the newly created object. */xmlXPathObjectPtrxmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) { xmlXPathObjectPtr ret; if (start == NULL) return(NULL); if (end == NULL) return(NULL); if (start->type != XPATH_POINT) return(NULL); if (end->type != XPATH_POINT) return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { xmlXPtrErrMemory("allocating range"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); ret->type = XPATH_RANGE; ret->user = start->user; ret->index = start->index; ret->user2 = end->user; ret->index2 = end->index; xmlXPtrRangeCheckOrder(ret); return(ret);}/** * xmlXPtrNewRangePointNode: * @start: the starting point * @end: the ending node * * Create a new xmlXPathObjectPtr of type range from a point to a node * * Returns the newly created object. */xmlXPathObjectPtrxmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) { xmlXPathObjectPtr ret; if (start == NULL) return(NULL); if (end == NULL) return(NULL); if (start->type != XPATH_POINT) return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { xmlXPtrErrMemory("allocating range"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); ret->type = XPATH_RANGE; ret->user = start->user; ret->index = start->index; ret->user2 = end; ret->index2 = -1; xmlXPtrRangeCheckOrder(ret); return(ret);}/** * xmlXPtrNewRangeNodePoint: * @start: the starting node * @end: the ending point * * Create a new xmlXPathObjectPtr of type range from a node to a point * * Returns the newly created object. */xmlXPathObjectPtrxmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) { xmlXPathObjectPtr ret; if (start == NULL) return(NULL); if (end == NULL) return(NULL); if (start->type != XPATH_POINT) return(NULL); if (end->type != XPATH_POINT) return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { xmlXPtrErrMemory("allocating range"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); ret->type = XPATH_RANGE; ret->user = start; ret->index = -1; ret->user2 = end->user; ret->index2 = end->index; xmlXPtrRangeCheckOrder(ret); return(ret);}/** * xmlXPtrNewRangeNodes: * @start: the starting node * @end: the ending node * * Create a new xmlXPathObjectPtr of type range using 2 nodes * * Returns the newly created object. */xmlXPathObjectPtrxmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) { xmlXPathObjectPtr ret; if (start == NULL) return(NULL); if (end == NULL) return(NULL); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); if (ret == NULL) { xmlXPtrErrMemory("allocating range"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); ret->type = XPATH_RANGE; ret->user = start; ret->index = -1; ret->user2 = end; ret->index2 = -1; xmlXPtrRangeCheckOrder(ret); return(ret);}/** * xmlXPtrNewCollapsedRange: * @start: the starting and ending node * * Create a new xmlXPathObjectPtr of type range using a single nodes * * Returns the newly created object. */xmlXPathObjectPtr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -