📄 xpointer.c
字号:
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
xmlXPtrNewCollapsedRange(xmlNodePtr start) {
xmlXPathObjectPtr ret;
if (start == 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 = NULL;
ret->index2 = -1;
return(ret);
}
/**
* xmlXPtrNewRangeNodeObject:
* @start: the starting node
* @end: the ending object
*
* Create a new xmlXPathObjectPtr of type range from a not to an object
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
xmlXPathObjectPtr ret;
if (start == NULL)
return(NULL);
if (end == NULL)
return(NULL);
switch (end->type) {
case XPATH_POINT:
case XPATH_RANGE:
break;
case XPATH_NODESET:
/*
* Empty set ...
*/
if (end->nodesetval->nodeNr <= 0)
return(NULL);
break;
default:
/* TODO */
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;
switch (end->type) {
case XPATH_POINT:
ret->user2 = end->user;
ret->index2 = end->index;
break;
case XPATH_RANGE:
ret->user2 = end->user2;
ret->index2 = end->index2;
break;
case XPATH_NODESET: {
ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
ret->index2 = -1;
break;
}
default:
STRANGE
return(NULL);
}
xmlXPtrRangeCheckOrder(ret);
return(ret);
}
#define XML_RANGESET_DEFAULT 10
/**
* xmlXPtrLocationSetCreate:
* @val: an initial xmlXPathObjectPtr, or NULL
*
* Create a new xmlLocationSetPtr of type double and of value @val
*
* Returns the newly created object.
*/
xmlLocationSetPtr
xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
xmlLocationSetPtr ret;
ret = (xmlLocationSetPtr) xmlMalloc(sizeof(xmlLocationSet));
if (ret == NULL) {
xmlXPtrErrMemory("allocating locationset");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlLocationSet));
if (val != NULL) {
ret->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
sizeof(xmlXPathObjectPtr));
if (ret->locTab == NULL) {
xmlXPtrErrMemory("allocating locationset");
xmlFree(ret);
return(NULL);
}
memset(ret->locTab, 0 ,
XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
ret->locMax = XML_RANGESET_DEFAULT;
ret->locTab[ret->locNr++] = val;
}
return(ret);
}
/**
* xmlXPtrLocationSetAdd:
* @cur: the initial range set
* @val: a new xmlXPathObjectPtr
*
* add a new xmlXPathObjectPtr to an existing LocationSet
* If the location already exist in the set @val is freed.
*/
void
xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
int i;
if ((cur == NULL) || (val == NULL)) return;
/*
* check against doublons
*/
for (i = 0;i < cur->locNr;i++) {
if (xmlXPtrRangesEqual(cur->locTab[i], val)) {
xmlXPathFreeObject(val);
return;
}
}
/*
* grow the locTab if needed
*/
if (cur->locMax == 0) {
cur->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
sizeof(xmlXPathObjectPtr));
if (cur->locTab == NULL) {
xmlXPtrErrMemory("adding location to set");
return;
}
memset(cur->locTab, 0 ,
XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
cur->locMax = XML_RANGESET_DEFAULT;
} else if (cur->locNr == cur->locMax) {
xmlXPathObjectPtr *temp;
cur->locMax *= 2;
temp = (xmlXPathObjectPtr *) xmlRealloc(cur->locTab, cur->locMax *
sizeof(xmlXPathObjectPtr));
if (temp == NULL) {
xmlXPtrErrMemory("adding location to set");
return;
}
cur->locTab = temp;
}
cur->locTab[cur->locNr++] = val;
}
/**
* xmlXPtrLocationSetMerge:
* @val1: the first LocationSet
* @val2: the second LocationSet
*
* Merges two rangesets, all ranges from @val2 are added to @val1
*
* Returns val1 once extended or NULL in case of error.
*/
xmlLocationSetPtr
xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr 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->locNr;i++)
xmlXPtrLocationSetAdd(val1, val2->locTab[i]);
return(val1);
}
/**
* xmlXPtrLocationSetDel:
* @cur: the initial range set
* @val: an xmlXPathObjectPtr
*
* Removes an xmlXPathObjectPtr from an existing LocationSet
*/
void
xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
int i;
if (cur == NULL) return;
if (val == NULL) return;
/*
* check against doublons
*/
for (i = 0;i < cur->locNr;i++)
if (cur->locTab[i] == val) break;
if (i >= cur->locNr) {
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlXPtrLocationSetDel: Range wasn't found in RangeList\n");
#endif
return;
}
cur->locNr--;
for (;i < cur->locNr;i++)
cur->locTab[i] = cur->locTab[i + 1];
cur->locTab[cur->locNr] = NULL;
}
/**
* xmlXPtrLocationSetRemove:
* @cur: the initial range set
* @val: the index to remove
*
* Removes an entry from an existing LocationSet list.
*/
void
xmlXPtrLocationSetRemove(xmlLocationSetPtr cur, int val) {
if (cur == NULL) return;
if (val >= cur->locNr) return;
cur->locNr--;
for (;val < cur->locNr;val++)
cur->locTab[val] = cur->locTab[val + 1];
cur->locTab[cur->locNr] = NULL;
}
/**
* xmlXPtrFreeLocationSet:
* @obj: the xmlLocationSetPtr to free
*
* Free the LocationSet compound (not the actual ranges !).
*/
void
xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) {
int i;
if (obj == NULL) return;
if (obj->locTab != NULL) {
for (i = 0;i < obj->locNr; i++) {
xmlXPathFreeObject(obj->locTab[i]);
}
xmlFree(obj->locTab);
}
xmlFree(obj);
}
/**
* xmlXPtrNewLocationSetNodes:
* @start: the start NodePtr value
* @end: the end NodePtr value or NULL
*
* Create a new xmlXPathObjectPtr of type LocationSet and initialize
* it with the single range made of the two nodes @start and @end
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end) {
xmlXPathObjectPtr ret;
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) {
xmlXPtrErrMemory("allocating locationset");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
ret->type = XPATH_LOCATIONSET;
if (end == NULL)
ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewCollapsedRange(start));
else
ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewRangeNodes(start,end));
return(ret);
}
/**
* xmlXPtrNewLocationSetNodeSet:
* @set: a node set
*
* Create a new xmlXPathObjectPtr of type LocationSet and initialize
* it with all the nodes from @set
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set) {
xmlXPathObjectPtr ret;
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) {
xmlXPtrErrMemory("allocating locationset");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
ret->type = XPATH_LOCATIONSET;
if (set != NULL) {
int i;
xmlLocationSetPtr newset;
newset = xmlXPtrLocationSetCreate(NULL);
if (newset == NULL)
return(ret);
for (i = 0;i < set->nodeNr;i++)
xmlXPtrLocationSetAdd(newset,
xmlXPtrNewCollapsedRange(set->nodeTab[i]));
ret->user = (void *) newset;
}
return(ret);
}
/**
* xmlXPtrWrapLocationSet:
* @val: the LocationSet value
*
* Wrap the LocationSet @val in a new xmlXPathObjectPtr
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
xmlXPathObjectPtr ret;
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) {
xmlXPtrErrMemory("allocating locationset");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
ret->type = XPATH_LOCATIONSET;
ret->user = (void *) val;
return(ret);
}
/************************************************************************
* *
* The parser *
* *
************************************************************************/
static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
/*
* 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_CH(*(ctxt->cur))) NEXT
#define CURRENT (*ctxt->cur)
#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
/*
* xmlXPtrGetChildNo:
* @ctxt: the XPointer Parser context
* @index: the child number
*
* Move the current node of the nodeset on the stack to the
* given child if found
*/
static void
xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int indx) {
xmlNodePtr cur = NULL;
xmlXPathObjectPtr obj;
xmlNodeSetPtr oldset;
CHECK_TYPE(XPATH_NODESET);
obj = valuePop(ctxt);
oldset = obj->nodesetval;
if ((indx <= 0) || (oldset == NULL) || (oldset->nodeNr != 1)) {
xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
return;
}
cur = xmlXPtrGetNthChild(oldset->nodeTab[0], indx);
if (cur == NULL) {
xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPathNewNodeSet(NULL));
return;
}
oldset->nodeTab[0] = cur;
valuePush(ctxt, obj);
}
/**
* xmlXPtrEvalXPtrPart:
* @ctxt: the XPointer Parser context
* @name: the preparsed Scheme for the XPtrPart
*
* XPtrPart ::= 'xpointer' '(' XPtrExpr ')'
* | Scheme '(' SchemeSpecificExpr ')'
*
* Scheme ::= NCName - 'xpointer' [VC: Non-XPointer schemes]
*
* SchemeSpecificExpr ::= StringWithBalancedParens
*
* StringWithBalancedParens ::=
* [^()]* ('(' StringWithBalancedParens ')' [^()]*)*
* [VC: Parenthesis escaping]
*
* XPtrExpr ::= Expr [VC: Parenthesis escaping]
*
* VC: Parenthesis escaping:
* The end of an XPointer part is signaled by the right parenthesis ")"
* character that is balanced with the left parenthesis "(" character
* that began the part. Any unbalanced parenthesis character inside the
* expression, even within literals, must be escaped with a circumflex (^)
* character preceding it. If the expression contains any literal
* occurrences of the circumflex, each must be escaped with an additional
* circumflex (that is, ^^). If the unescaped parentheses in the expression
* are not balanced, a syntax error results.
*
* Parse and evaluate an XPtrPart. Basically it generates the unescaped
* string and if the scheme is 'xpointer' it will call the XPath interpreter.
*
* TODO: there is no new scheme registration mechanism
*/
static void
xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
xmlChar *buffer, *cur;
int len;
int level;
if (name == NULL)
name = xmlXPathParseName(ctxt);
if (name == NULL)
XP_ERROR(XPATH_EXPR_ERROR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -