Commit 2d38f047 authored by Daniel Veillard's avatar Daniel Veillard
Browse files

- xpath.[ch] xpointer.[ch]: worked on XPath functions and variable

  handlings (registration, lookup, cleanup)
Daniel
parent e8eac3d9
Wed Oct 11 12:41:30 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* xpath.[ch] xpointer.[ch]: worked on XPath functions and variable
handlings (registration, lookup, cleanup)
Wed Oct 11 01:46:44 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* configure.in Makefile.am include/makefile.am: adding XPointer
......
......@@ -311,7 +311,7 @@ dnl create the libxml and include links needed to get dependencies right
dnl
if test ! -d $srcdir/include/libxml
then
if [ ! -d $srcdir/include ]
if test ! -d $srcdir/include
then
rm -f $srcdir/include
mkdir $srcdir/include
......@@ -325,7 +325,7 @@ then
fi
if test ! -e include/libxml
then
if [ ! -d include ]
if test ! -d include
then
rm -f include
mkdir include
......
......@@ -288,6 +288,7 @@ void xmlXPathIdFunction (xmlXPathParserContextPtr ctxt,
int nargs);
void xmlXPathRoot (xmlXPathParserContextPtr ctxt);
void xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt);
xmlChar * xmlXPathParseName (xmlXPathParserContextPtr ctxt);
/************************************************************************
* *
......@@ -296,20 +297,14 @@ void xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt);
************************************************************************/
/**
* Registering extensions to the expression language
* Extending a context
*/
/* TODO */ int xmlXPathRegisterType (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathConvertFunc f);
/* TODO */ int xmlXPathRegisterAxis (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathAxisFunc f);
/* TODO */ int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathFunction f);
/* TODO */ int xmlXPathRegisterVariable (xmlXPathContextPtr ctxt,
int xmlXPathRegisterVariable (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathObject value);
xmlXPathObjectPtr value);
/**
* Evaluation functions.
......@@ -327,6 +322,7 @@ xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
xmlNodeSetPtr xmlXPathNodeSetCreate (xmlNodePtr val);
void xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj);
void xmlXPathFreeNodeSet (xmlNodeSetPtr obj);
xmlXPathObjectPtr xmlXPathObjectCopy (xmlXPathObjectPtr val);
#ifdef __cplusplus
......
......@@ -30,6 +30,14 @@ struct _xmlLocationSet {
xmlXPathObjectPtr *locTab;/* array of locations */
};
/*
* Handling of location sets
*/
void xmlXPtrFreeLocationSet (xmlLocationSetPtr obj);
xmlLocationSetPtr xmlXPtrLocationSetMerge (xmlLocationSetPtr val1,
xmlLocationSetPtr val2);
/*
* Functions
*/
......@@ -40,7 +48,6 @@ xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str,
xmlXPathContextPtr ctx);
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
int nargs);
void xmlXPtrFreeLocationSet (xmlLocationSetPtr obj);
#ifdef __cplusplus
}
......
......@@ -413,10 +413,11 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
/**
* xmlXPathNodeSetMerge:
* @val1: the first NodeSet
* @val1: the first NodeSet or NULL
* @val2: the second NodeSet
*
* Merges two nodesets, all nodes from @val2 are added to @val1
* if @val1 is NULL, a new set is created and copied from @val2
*
* Returns val1 once extended or NULL in case of error.
*/
......@@ -424,8 +425,10 @@ xmlNodeSetPtr
xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
int i;
if (val1 == NULL) return(NULL);
if (val2 == NULL) return(val1);
if (val1 == NULL) {
val1 = xmlXPathNodeSetCreate(NULL);
}
/*
* !!!!! this can be optimized a lot, knowing that both
......@@ -644,31 +647,218 @@ xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
/************************************************************************
* *
* Routines to handle Variable *
* Routines to handle extra functions *
* *
************************************************************************/
/**
* xmlXPathRegisterFunc:
* @ctxt: the XPath context
* @name: the function name
* @f: the function implementation or NULL
*
* Register a new function. If @f is NULL it unregisters the function
*
* Returns 0 in case of success, -1 in case of error
*/
int
xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
xmlXPathFunction f) {
int i;
if (ctxt == NULL)
return(-1);
if (name == NULL)
return(-1);
for (i = 0;i < ctxt->nb_funcs;i++) {
if (xmlStrEqual(ctxt->funcs[i]->name, name)) {
/*
* It's just an update or a removal
*/
ctxt->funcs[i]->func = f;
return(0);
}
}
if (ctxt->max_funcs <= 0) {
ctxt->max_funcs = 10;
ctxt->nb_funcs = 0;
ctxt->funcs = (xmlXPathFuncPtr *) xmlMalloc(ctxt->max_funcs *
sizeof(xmlXPathFuncPtr));
} else if (ctxt->max_funcs <= ctxt->nb_funcs) {
ctxt->max_funcs *= 2;
ctxt->funcs = (xmlXPathFuncPtr *) xmlRealloc(ctxt->funcs,
ctxt->max_funcs * sizeof(xmlXPathFuncPtr));
}
if (ctxt->funcs == NULL) {
fprintf(xmlXPathDebug, "xmlXPathRegisterFunc: out of memory\n");
return(-1);
}
ctxt->funcs[i]->name = xmlStrdup(name);
ctxt->funcs[i]->func = f;
return(0);
}
/**
* xmlXPathFunctionLookup:
* @ctxt: the XPath context
* @name: the function name
*
* Search in the Function array of the context for the given
* function.
*
* Returns the xmlXPathFunction or NULL if not found
*/
xmlXPathFunction
xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
int i;
if (ctxt == NULL)
return(NULL);
if (name == NULL)
return(NULL);
for (i = 0;i < ctxt->nb_funcs;i++) {
if (xmlStrEqual(ctxt->funcs[i]->name, name)) {
return(ctxt->funcs[i]->func);
}
}
return(NULL);
}
/**
* xmlXPathRegisteredFuncsCleanup:
* @ctxt: the XPath context
*
* Cleanup the XPath context data associated to registered functions
*/
void
xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
int i;
if (ctxt == NULL)
return;
for (i = 0;i < ctxt->nb_funcs;i++) {
xmlFree((xmlChar *) ctxt->funcs[i]->name);
}
ctxt->nb_funcs = -1;
ctxt->max_funcs = -1;
if (ctxt->funcs != NULL)
xmlFree(ctxt->funcs);
ctxt->funcs = NULL;
}
/************************************************************************
* *
* UNIMPLEMENTED CURRENTLY *
* Routines to handle Variable *
* *
************************************************************************/
/**
* xmlXPathVariablelookup:
* @ctxt: the XPath Parser context
* @prefix: the variable name namespace if any
* xmlXPathRegisterVariable:
* @ctxt: the XPath context
* @name: the variable name
* @value: the variable value or NULL
*
* Register a new variable value. If @value is NULL it unregisters
* the variable
*
* Returns 0 in case of success, -1 in case of error
*/
int
xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
xmlXPathObjectPtr value) {
int i;
if (ctxt == NULL)
return(-1);
if (name == NULL)
return(-1);
for (i = 0;i < ctxt->nb_variables;i++) {
if (xmlStrEqual(ctxt->variables[i]->name, name)) {
/*
* It's just an update or a removal
*/
if (ctxt->variables[i]->value != NULL) {
xmlXPathFreeObject(ctxt->variables[i]->value);
}
ctxt->variables[i]->value = xmlXPathObjectCopy(value);
return(0);
}
}
if (ctxt->max_variables <= 0) {
ctxt->max_variables = 10;
ctxt->nb_variables = 0;
ctxt->variables = (xmlXPathVariablePtr *)
xmlMalloc(ctxt->max_variables * sizeof(xmlXPathVariablePtr));
} else if (ctxt->max_variables <= ctxt->nb_variables) {
ctxt->max_variables *= 2;
ctxt->variables = (xmlXPathVariablePtr *)
xmlRealloc(ctxt->variables,
ctxt->max_variables * sizeof(xmlXPathVariablePtr));
}
if (ctxt->variables == NULL) {
fprintf(xmlXPathDebug, "xmlXPathRegisterVariable: out of memory\n");
return(-1);
}
ctxt->variables[i]->name = xmlStrdup(name);
ctxt->variables[i]->value = xmlXPathObjectCopy(value);
return(0);
}
/**
* xmlXPathVariableLookup:
* @ctxt: the XPath context
* @name: the variable name
*
* Search in the Variable array of the context for the given
* variable value.
*
* UNIMPLEMENTED: always return NULL.
*
* Returns the value or NULL if not found
*/
xmlXPathObjectPtr
xmlXPathVariablelookup(xmlXPathParserContextPtr ctxt,
const xmlChar *prefix, const xmlChar *name) {
xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
int i;
if (ctxt == NULL)
return(NULL);
if (name == NULL)
return(NULL);
for (i = 0;i < ctxt->nb_variables;i++) {
if (xmlStrEqual(ctxt->variables[i]->name, name)) {
return(xmlXPathObjectCopy(ctxt->variables[i]->value));
}
}
return(NULL);
}
/**
* xmlXPathRegisteredVariablesCleanup:
* @ctxt: the XPath context
*
* Cleanup the XPath context data associated to registered variables
*/
void
xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
int i;
if (ctxt == NULL)
return;
for (i = 0;i < ctxt->nb_variables;i++) {
xmlFree((xmlChar *) ctxt->variables[i]->name);
xmlXPathFreeObject(ctxt->variables[i]->value);
}
ctxt->nb_variables = -1;
ctxt->max_variables = -1;
if (ctxt->variables != NULL)
xmlFree(ctxt->variables);
ctxt->variables = NULL;
}
/************************************************************************
* *
* Routines to handle Values *
......@@ -769,6 +959,53 @@ xmlXPathNewCString(const char *val) {
return(ret);
}
/**
* xmlXPathObjectCopy:
* @val: the original object
*
* allocate a new copy of a given object
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPathObjectCopy(xmlXPathObjectPtr val) {
xmlXPathObjectPtr ret;
if (val == NULL)
return(NULL);
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) {
fprintf(xmlXPathDebug, "xmlXPathObjectCopy: out of memory\n");
return(NULL);
}
memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
switch (val->type) {
case XPATH_BOOLEAN:
case XPATH_NUMBER:
case XPATH_STRING:
case XPATH_POINT:
case XPATH_RANGE:
break;
case XPATH_NODESET:
ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
break;
case XPATH_LOCATIONSET:
#ifdef LIBXML_XPTR_ENABLED
{
xmlLocationSetPtr loc = val->user;
ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
break;
}
#endif
case XPATH_UNDEFINED:
case XPATH_USERS:
fprintf(xmlXPathDebug, "xmlXPathObjectCopy: unsupported type %d\n",
val->type);
}
return(ret);
}
/**
* xmlXPathFreeObject:
* @obj: the object to free
......@@ -860,6 +1097,8 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
if (ctxt->namespaces != NULL)
xmlFree(ctxt->namespaces);
xmlXPathRegisteredFuncsCleanup(ctxt);
xmlXPathRegisteredVariablesCleanup(ctxt);
#ifdef DEBUG
memset(ctxt, 0xB , (size_t) sizeof(xmlXPathContext));
#endif
......@@ -3348,6 +3587,41 @@ xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
return(ret);
}
/**
* xmlXPathParseName:
* @ctxt: the XPointer Parser context
*
* parse an XML name
*
* [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
* CombiningChar | Extender
*
* [5] Name ::= (Letter | '_' | ':') (NameChar)*
*
* Returns the namespace name or NULL
*/
xmlChar *
xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
const xmlChar *q;
xmlChar *ret = NULL;
if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
q = NEXT;
/* TODO Make this UTF8 compliant !!! */
while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
(CUR == '.') || (CUR == '-') ||
(CUR == '_') || (CUR == ':') ||
(IS_COMBINING(CUR)) ||
(IS_EXTENDER(CUR)))
NEXT;
ret = xmlStrndup(q, CUR_PTR - q);
return(ret);
}
/**
* xmlXPathStringEvalNumber:
* @str: A string to scan
......@@ -3503,23 +3777,21 @@ xmlXPathEvalLiteral(xmlXPathParserContextPtr ctxt) {
void
xmlXPathEvalVariableReference(xmlXPathParserContextPtr ctxt) {
xmlChar *name;
xmlChar *prefix;
xmlXPathObjectPtr value;
SKIP_BLANKS;
if (CUR != '$') {
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
}
name = xmlXPathParseQName(ctxt, &prefix);
name = xmlXPathParseName(ctxt);
if (name == NULL) {
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
}
value = xmlXPathVariablelookup(ctxt, prefix, name);
value = xmlXPathVariableLookup(ctxt->context, name);
if (value == NULL) {
XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR);
}
valuePush(ctxt, value);
if (prefix != NULL) xmlFree(prefix);
xmlFree(name);
SKIP_BLANKS;
}
......@@ -3570,6 +3842,9 @@ xmlXPathIsNodeType(const xmlChar *name) {
*/
xmlXPathFunction
xmlXPathIsFunction(xmlXPathParserContextPtr ctxt, const xmlChar *name) {
if (name == NULL)
return(NULL);
switch (name[0]) {
case 'b':
if (xmlStrEqual(name, BAD_CAST "boolean"))
......@@ -3648,7 +3923,7 @@ xmlXPathIsFunction(xmlXPathParserContextPtr ctxt, const xmlChar *name) {
return(xmlXPathTranslateFunction);
break;
}
return(NULL);
return(xmlXPathFunctionLookup(ctxt->context, name));
}
/**
......
......@@ -288,6 +288,7 @@ void xmlXPathIdFunction (xmlXPathParserContextPtr ctxt,
int nargs);
void xmlXPathRoot (xmlXPathParserContextPtr ctxt);
void xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt);
xmlChar * xmlXPathParseName (xmlXPathParserContextPtr ctxt);
/************************************************************************
* *
......@@ -296,20 +297,14 @@ void xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt);
************************************************************************/
/**
* Registering extensions to the expression language
* Extending a context
*/
/* TODO */ int xmlXPathRegisterType (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathConvertFunc f);
/* TODO */ int xmlXPathRegisterAxis (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathAxisFunc f);
/* TODO */ int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathFunction f);
/* TODO */ int xmlXPathRegisterVariable (xmlXPathContextPtr ctxt,
int xmlXPathRegisterVariable (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathObject value);
xmlXPathObjectPtr value);
/**
* Evaluation functions.
......@@ -327,6 +322,7 @@ xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
xmlNodeSetPtr xmlXPathNodeSetCreate (xmlNodePtr val);
void xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj);
void xmlXPathFreeNodeSet (xmlNodeSetPtr obj);
xmlXPathObjectPtr xmlXPathObjectCopy (xmlXPathObjectPtr val);
#ifdef __cplusplus
......
......@@ -656,41 +656,6 @@ xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
#define CURRENT (*ctxt->cur)
#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
/**
* xmlXPtrParseName:
* @ctxt: the XPointer Parser context
*
* parse an XML name
*
* [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
* CombiningChar | Extender
*
* [5] Name ::= (Letter | '_' | ':') (NameChar)*
*
* Returns the namespace name or NULL
*/
xmlChar *
xmlXPtrParseName(xmlXPathParserContextPtr ctxt) {
const xmlChar *q;
xmlChar *ret = NULL;
if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
q = NEXT;
/* TODO Make this UTF8 compliant !!! */
while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
(CUR == '.') || (CUR == '-') ||
(CUR == '_') || (CUR == ':') ||
(IS_COMBINING(CUR)) ||
(IS_EXTENDER(CUR)))
NEXT;
ret = xmlStrndup(q, CUR_PTR - q);
return(ret);
}
/*
* xmlXPtrGetChildNo:
* @ctxt: the XPointer Parser context
......@@ -781,7 +746,7 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
int level;
if (name == NULL)
name = xmlXPtrParseName(ctxt);
name = xmlXPathParseName(ctxt);
if (name == NULL)
XP_ERROR(XPATH_EXPR_ERROR);
......@@ -878,7 +843,7 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
void
xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) {
if (name == NULL)
name = xmlXPtrParseName(ctxt);
name = xmlXPathParseName(ctxt);
if (name == NULL)
XP_ERROR(XPATH_EXPR_ERROR);
while (name != NULL) {
......@@ -928,7 +893,7 @@ xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) {
* Is there another XPoointer part.
*/
SKIP_BLANKS;
name = xmlXPtrParseName(ctxt);
name = xmlXPathParseName(ctxt);
}
}
......@@ -992,7 +957,7 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
} else {
xmlChar *name;
name = xmlXPtrParseName(ctxt);
name = xmlXPathParseName(ctxt);
if (name == NULL)
XP_ERROR(XPATH_EXPR_ERROR);
if (CUR == '(') {
......
......@@ -30,6 +30,14 @@ struct _xmlLocationSet {
xmlXPathObjectPtr *locTab;/* array of locations */
};
/*
* Handling of location sets
*/
void xmlXPtrFreeLocationSet (xmlLocationSetPtr obj);
xmlLocationSetPtr xmlXPtrLocationSetMerge (xmlLocationSetPtr val1,
xmlLocationSetPtr val2);
/*
* Functions
*/
......@@ -40,7 +48,6 @@ xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str,
xmlXPathContextPtr ctx);
void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt,
int nargs);
void xmlXPtrFreeLocationSet (xmlLocationSetPtr obj);
#ifdef __cplusplus
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment