Commit ba0b8c94 authored by Daniel Veillard's avatar Daniel Veillard
Browse files

- xpath.c xpath.h xpathInternals.h: apply an XPath API cleanup

  patch from Thomas Broyer
Daniel
parent e62d36c4
Tue May 15 11:42:39 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* xpath.c xpath.h xpathInternals.h: apply an XPath API cleanup
patch from Thomas Broyer
Tue May 15 10:52:19 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* valid.c test/VCM/v2[34].xml: Fixed bug #54631 added specific test
......
......@@ -276,6 +276,23 @@ int xmlXPathCmpNodes (xmlNodePtr node1,
/**
* Conversion functions to basic types
*/
int xmlXPathCastNumberToBoolean (double val);
int xmlXPathCastStringToBoolean (const xmlChar * val);
int xmlXPathCastNodeToBoolean (xmlNodeSetPtr ns);
int xmlXPathCastToBoolean (xmlXPathObjectPtr val);
double xmlXPathCastBooleanToNumber (int val);
double xmlXPathCastStringToNumber (const xmlChar * val);
double xmlXPathCastNodeToNumber (xmlNodePtr node);
double xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns);
double xmlXPathCastToNumber (xmlXPathObjectPtr val);
xmlChar * xmlXPathCastBooleanToString (int val);
xmlChar * xmlXPathCastNumberToString (double val);
xmlChar * xmlXPathCastNodeToString (xmlNodePtr node);
xmlChar * xmlXPathCastNodeSetToString (xmlNodeSetPtr ns);
xmlChar * xmlXPathCastToString (xmlXPathObjectPtr val);
xmlXPathObjectPtr xmlXPathConvertBoolean (xmlXPathObjectPtr val);
xmlXPathObjectPtr xmlXPathConvertNumber (xmlXPathObjectPtr val);
xmlXPathObjectPtr xmlXPathConvertString (xmlXPathObjectPtr val);
......
......@@ -135,6 +135,8 @@ int valuePush (xmlXPathParserContextPtr ctxt,
xmlXPathObjectPtr xmlXPathNewString (const xmlChar *val);
xmlXPathObjectPtr xmlXPathNewCString (const char *val);
xmlXPathObjectPtr xmlXPathWrapString (xmlChar *val);
xmlXPathObjectPtr xmlXPathWrapCString (char *val);
xmlXPathObjectPtr xmlXPathNewFloat (double val);
xmlXPathObjectPtr xmlXPathNewBoolean (int val);
xmlXPathObjectPtr xmlXPathNewNodeSet (xmlNodePtr val);
......
......@@ -2090,6 +2090,30 @@ xmlXPathNewString(const xmlChar *val) {
return(ret);
}
/**
* xmlXPathWrapString:
* @val: the xmlChar * value
*
* Wraps the @val string into an XPath object.
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPathWrapString (xmlChar *val) {
xmlXPathObjectPtr ret;
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathWrapString: out of memory\n");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
ret->type = XPATH_STRING;
ret->stringval = val;
return(ret);
}
/**
* xmlXPathNewCString:
* @val: the char * value
......@@ -2114,6 +2138,19 @@ xmlXPathNewCString(const char *val) {
return(ret);
}
/**
* xmlXPathWrapCString:
* @val: the char * value
*
* Wraps a string into an XPath object.
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPathWrapCString (char * val) {
return(xmlXPathWrapString((xmlChar *)(val)));
}
/**
* xmlXPathObjectCopy:
* @val: the original object
......@@ -2208,6 +2245,439 @@ xmlXPathFreeObject(xmlXPathObjectPtr obj) {
xmlFree(obj);
}
/************************************************************************
* *
* Type Casting Routines *
* *
************************************************************************/
/**
* xmlXPathCastBooleanToString:
* @val: a boolean
*
* Converts a boolean to its string value.
*
* Returns a newly allocated string.
*/
xmlChar *
xmlXPathCastBooleanToString (int val) {
xmlChar *ret;
if (val)
ret = xmlStrdup((const xmlChar *) "true");
else
ret = xmlStrdup((const xmlChar *) "false");
return(ret);
}
/**
* xmlXPathCastNumberToString:
* @val: a number
*
* Converts a number to its string value.
*
* Returns a newly allocated string.
*/
xmlChar *
xmlXPathCastNumberToString (double val) {
xmlChar *ret;
switch (isinf(val)) {
case 1:
ret = xmlStrdup((const xmlChar *) "+Infinity");
break;
case -1:
ret = xmlStrdup((const xmlChar *) "-Infinity");
break;
default:
if (isnan(val)) {
ret = xmlStrdup((const xmlChar *) "NaN");
} else {
/* could be improved */
char buf[100];
xmlXPathFormatNumber(val, buf, 100);
ret = xmlStrdup((const xmlChar *) buf);
}
}
return(ret);
}
/**
* xmlXPathCastNodeToString:
* @node: a node
*
* Converts a node to its string value.
*
* Returns a newly allocated string.
*/
xmlChar *
xmlXPathCastNodeToString (xmlNodePtr node) {
return(xmlNodeGetContent(node));
}
/**
* xmlXPathCastNodeSetToString:
* @ns: a node-set
*
* Converts a node-set to its string value.
*
* Returns a newly allocated string.
*/
xmlChar *
xmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
return(xmlStrdup((const xmlChar *) ""));
xmlXPathNodeSetSort(ns);
return(xmlXPathCastNodeToString(ns->nodeTab[0]));
}
/**
* xmlXPathCastToString:
* @val: an XPath object
*
* Converts an existing object to its string() equivalent
*
* Returns the string value of the object, NULL in case of error.
* A new string is allocated only if needed (val isn't a
* string object).
*/
xmlChar *
xmlXPathCastToString(xmlXPathObjectPtr val) {
xmlChar *ret = NULL;
if (val == NULL)
return(xmlStrdup((const xmlChar *) ""));
switch (val->type) {
case XPATH_UNDEFINED:
#ifdef DEBUG_EXPR
xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
#endif
ret = xmlStrdup((const xmlChar *) "");
break;
case XPATH_XSLT_TREE:
case XPATH_NODESET:
ret = xmlXPathCastNodeSetToString(val->nodesetval);
break;
case XPATH_STRING:
return(val->stringval);
case XPATH_BOOLEAN:
ret = xmlXPathCastBooleanToString(val->boolval);
break;
case XPATH_NUMBER: {
ret = xmlXPathCastNumberToString(val->floatval);
break;
}
case XPATH_USERS:
case XPATH_POINT:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
TODO
ret = xmlStrdup((const xmlChar *) "");
break;
}
return(ret);
}
/**
* xmlXPathConvertString:
* @val: an XPath object
*
* Converts an existing object to its string() equivalent
*
* Returns the new object, the old one is freed (or the operation
* is done directly on @val)
*/
xmlXPathObjectPtr
xmlXPathConvertString(xmlXPathObjectPtr val) {
xmlChar *res = NULL;
if (val == NULL)
return(xmlXPathNewCString(""));
switch (val->type) {
case XPATH_UNDEFINED:
#ifdef DEBUG_EXPR
xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
#endif
break;
case XPATH_XSLT_TREE:
case XPATH_NODESET:
res = xmlXPathCastNodeSetToString(val->nodesetval);
break;
case XPATH_STRING:
return(val);
case XPATH_BOOLEAN:
res = xmlXPathCastBooleanToString(val->boolval);
break;
case XPATH_NUMBER:
res = xmlXPathCastNumberToString(val->floatval);
break;
case XPATH_USERS:
case XPATH_POINT:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
TODO;
break;
}
xmlXPathFreeObject(val);
if (res == NULL)
return(xmlXPathNewCString(""));
return(xmlXPathWrapString(res));
}
/**
* xmlXPathCastBooleanToNumber:
* @val: a boolean
*
* Converts a boolean to its number value
*
* Returns the number value
*/
double
xmlXPathCastBooleanToNumber(int val) {
if (val)
return(1.0);
return(0.0);
}
/**
* xmlXPathCastStringToNumber:
* @val: a string
*
* Converts a string to its number value
*
* Returns the number value
*/
double
xmlXPathCastStringToNumber(const xmlChar * val) {
return(xmlXPathStringEvalNumber(val));
}
/**
* xmlXPathCastNodeToNumber:
* @node: a node
*
* Converts a node to its number value
*
* Returns the number value
*/
double
xmlXPathCastNodeToNumber (xmlNodePtr node) {
xmlChar *strval;
double ret;
if (node == NULL)
return(xmlXPathNAN);
strval = xmlXPathCastNodeToString(node);
if (strval == NULL)
return(xmlXPathNAN);
ret = xmlXPathCastStringToNumber(strval);
xmlFree(strval);
return(ret);
}
/**
* xmlXPathCastNodeSetToNumber:
* @ns: a node-set
*
* Converts a node-set to its number value
*
* Returns the number value
*/
double
xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
xmlChar *str;
double ret;
if (ns == NULL)
return(xmlXPathNAN);
str = xmlXPathCastNodeSetToString(ns);
ret = xmlXPathCastStringToNumber(str);
xmlFree(str);
return(ret);
}
/**
* xmlXPathCastToNumber:
* @val: an XPath object
*
* Converts an XPath object to its number value
*
* Returns the number value
*/
double
xmlXPathCastToNumber(xmlXPathObjectPtr val) {
double ret = 0.0;
if (val == NULL)
return(xmlXPathNAN);
switch (val->type) {
case XPATH_UNDEFINED:
#ifdef DEGUB_EXPR
xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
#endif
ret = xmlXPathNAN;
break;
case XPATH_XSLT_TREE:
case XPATH_NODESET:
ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
break;
case XPATH_STRING:
ret = xmlXPathCastStringToNumber(val->stringval);
break;
case XPATH_NUMBER:
ret = val->floatval;
break;
case XPATH_BOOLEAN:
ret = xmlXPathCastBooleanToNumber(val->boolval);
break;
case XPATH_USERS:
case XPATH_POINT:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
TODO;
ret = xmlXPathNAN;
break;
}
return(ret);
}
/**
* xmlXPathConvertNumber:
* @val: an XPath object
*
* Converts an existing object to its number() equivalent
*
* Returns the new object, the old one is freed (or the operation
* is done directly on @val)
*/
xmlXPathObjectPtr
xmlXPathConvertNumber(xmlXPathObjectPtr val) {
xmlXPathObjectPtr ret;
if (val == NULL)
return(xmlXPathNewFloat(0.0));
if (val->type == XPATH_NUMBER)
return(val);
ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
xmlXPathFreeObject(val);
return(ret);
}
/**
* xmlXPathCastNumberToBoolean:
* @val: a number
*
* Converts a number to its boolean value
*
* Returns the boolean value
*/
int
xmlXPathCastNumberToBoolean (double val) {
if (isnan(val) || (val == 0.0))
return(0);
return(1);
}
/**
* xmlXPathCastStringToBoolean:
* @val: a string
*
* Converts a string to its boolean value
*
* Returns the boolean value
*/
int
xmlXPathCastStringToBoolean (const xmlChar *val) {
if ((val == NULL) || (xmlStrlen(val) == 0))
return(0);
return(1);
}
/**
* xmlXPathCastNodeSetToBoolean:
* @ns: a node-set
*
* Converts a node-set to its boolean value
*
* Returns the boolean value
*/
int
xmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
if ((ns == NULL) || (ns->nodeNr == 0))
return(0);
return(1);
}
/**
* xmlXpathCastToBoolean:
* @val: an XPath object
*
* Converts an XPath object to its boolean value
*
* Returns the boolean value
*/
int
xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
int ret = 0;
if (val == NULL)
return(0);
switch (val->type) {
case XPATH_UNDEFINED:
#ifdef DEBUG_EXPR
xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
#endif
ret = 0;
break;
case XPATH_XSLT_TREE:
case XPATH_NODESET:
ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
break;
case XPATH_STRING:
ret = xmlXPathCastStringToBoolean(val->stringval);
break;
case XPATH_NUMBER:
ret = xmlXPathCastNumberToBoolean(val->floatval);
break;
case XPATH_BOOLEAN:
ret = val->boolval;
break;
case XPATH_USERS:
case XPATH_POINT:
case XPATH_RANGE:
case XPATH_LOCATIONSET:
TODO;
ret = 0;
break;
}
return(ret);
}
/**
* xmlXPathConvertBoolean:
* @val: an XPath object
*
* Converts an existing object to its boolean() equivalent
*
* Returns the new object, the old one is freed (or the operation
* is done directly on @val)
*/
xmlXPathObjectPtr
xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
xmlXPathObjectPtr ret;
if (val == NULL)
return(xmlXPathNewBoolean(0));
if (val->type == XPATH_BOOLEAN)
return(val);
ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
xmlXPathFreeObject(val);
return(ret);
}
/************************************************************************
* *
* Routines to handle XPath contexts *
......@@ -2400,23 +2870,6 @@ xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
* *
************************************************************************/
/*
* Auto-pop and cast to a number
*/
void xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs);
#define POP_FLOAT \
arg = valuePop(ctxt); \
if (arg == NULL) { \
XP_ERROR(XPATH_INVALID_OPERAND); \
} \
if (arg->type != XPATH_NUMBER) { \
valuePush(ctxt, arg); \
xmlXPathNumberFunction(ctxt, 1); \
arg = valuePop(ctxt); \
}
/**
* xmlXPathCompareNodeSetFloat:
* @ctxt: the XPath Parser context
......@@ -2455,7 +2908,7 @@ xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
ns = arg->nodesetval;
if (ns != NULL) {
for (i = 0;i < ns->nodeNr;i++) {
str2 = xmlNodeGetContent(ns->nodeTab[i]);
str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
if (str2 != NULL) {
valuePush(ctxt,
xmlXPathNewString(str2));
......@@ -2510,7 +2963,7 @@ xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
ns = arg->nodesetval;
if (ns != NULL) {
for (i = 0;i < ns->nodeNr;i++) {
str2 = xmlNodeGetContent(ns->nodeTab[i]);
str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
if (str2 != NULL) {
valuePush(ctxt,
xmlXPathNewString(str2));
......@@ -2529,7 +2982,7 @@ xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
/**
* xmlXPathCompareNodeSets:
* @op: less than (-1), equal (0) or greater than (1)
* @inf: less than (1) or greater than (0)
* @strict: is the comparison strict
* @arg1: the fist node set object
* @arg2: the second node set object
......@@ -2562,7 +3015,6 @@ xmlXPathCompareNodeSets(int inf, int strict,
double val1;
double *values2;
int ret = 0;
xmlChar *str;
xmlNodeSetPtr ns1;
xmlNodeSetPtr ns2;
......@@ -2599,22 +3051,12 @@ xmlXPathCompareNodeSets(int inf, int strict,
return(0);
}
for (i = 0;i < ns1->nodeNr;i++) {
str = xmlNodeGetContent(ns1->nodeTab[i]);
if (str == NULL)
continue;
val1 = xmlXPathStringEvalNumber(str);
xmlFree(str);
val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
if (isnan(val1))
continue;
for (j = 0;j < ns2->nodeNr;j++) {
if (init == 0) {
str = xmlNodeGetContent(ns2->nodeTab[j]);
if (str == NULL) {
values2[j] = xmlXPathNAN;
} else {
values2[j] = xmlXPathStringEvalNumber(str);
xmlFree(str);
}
values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
}
if (isnan(values2[j]))
continue;
......@@ -3133,11 +3575,9 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
*/
void
xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
xmlXPathObjectPtr arg;
POP_FLOAT
arg->floatval = -arg->floatval;
valuePush(ctxt, arg);
CAST_TO_NUMBER;
CHECK_TYPE(XPATH_NUMBER);
ctxt->value->floatval = - ctxt->value->floatval;
}
/**
......@@ -3153,13 +3593,15 @@ xmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
xmlXPathObjectPtr arg;
double val;
POP_FLOAT
val = arg->floatval;
arg = valuePop(ctxt);
if (arg == NULL)
XP_ERROR(XPATH_INVALID_OPERAND);
val = xmlXPathCastToNumber(arg);
xmlXPathFreeObject(arg);
POP_FLOAT