xmlXPathNodeCollectAndTest fixed (by William Brack)
xmlXPathFormatNumber added
xmlXPathNodeSetSort changed
diff --git a/xpath.c b/xpath.c
index 1bc30e6..9d1ba1b 100644
--- a/xpath.c
+++ b/xpath.c
@@ -462,6 +462,157 @@
#define CURRENT (*ctxt->cur)
#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
+
+#ifndef DBL_DIG
+#define DBL_DIG 16
+#endif
+#ifndef DBL_EPSILON
+#define DBL_EPSILON 1E-9
+#endif
+
+#define UPPER_DOUBLE 1E9
+#define LOWER_DOUBLE 1E-5
+
+#define INTEGER_DIGITS DBL_DIG
+#define FRACTION_DIGITS (DBL_DIG + 1)
+#define EXPONENT_DIGITS (3 + 2)
+
+/**
+ * xmlXPathFormatNumber:
+ * @number: number to format
+ * @buffer: output buffer
+ * @buffersize: size of output buffer
+ *
+ * Convert the number into a string representation.
+ */
+static void
+xmlXPathFormatNumber(double number, char buffer[], int buffersize)
+{
+ switch (isinf(number)) {
+ case 1:
+ if (buffersize > (int)sizeof("+Infinity"))
+ sprintf(buffer, "+Infinity");
+ break;
+ case -1:
+ if (buffersize > (int)sizeof("-Infinity"))
+ sprintf(buffer, "-Infinity");
+ break;
+ default:
+ if (isnan(number)) {
+ if (buffersize > (int)sizeof("NaN"))
+ sprintf(buffer, "NaN");
+ } else {
+ char work[INTEGER_DIGITS + FRACTION_DIGITS + EXPONENT_DIGITS + 1];
+ char *pointer;
+ char *start;
+ int i;
+ int digits;
+ int is_negative;
+ int use_scientific;
+ int exponent;
+ int index;
+ int count;
+ double n;
+
+ i = digits = 0;
+ is_negative = (number < 0.0);
+ if (is_negative)
+ number = -number;
+
+ /* Scale number */
+ n = log10(number);
+ exponent = (isinf(n) == -1) ? 0 : (int)n;
+ use_scientific = (((number <= LOWER_DOUBLE) ||
+ (number > UPPER_DOUBLE)) &&
+ (number != 0));
+ if (use_scientific) {
+ number /= pow(10.0, (double)exponent);
+ while (number < 1.0) {
+ number *= 10.0;
+ exponent--;
+ }
+ }
+
+ /* Integer part is build from back */
+ pointer = &work[INTEGER_DIGITS + 1];
+ if (number < 1.0) {
+ *(--pointer) = '0';
+ digits++;
+ } else {
+ n = number;
+ for (i = 1; i < INTEGER_DIGITS - 1; i++) {
+ index = (int)n % 10;
+ *(--pointer) = "0123456789"[index];
+ n /= 10.0;
+ if (n < 1.0)
+ break;
+ }
+ digits += i;
+ }
+ if (is_negative) {
+ *(--pointer) = '-';
+ digits++;
+ }
+ start = pointer;
+
+ /* Fraction part is build from front */
+ i = 0;
+ pointer = &work[INTEGER_DIGITS + 1];
+ if (number - floor(number) > DBL_EPSILON) {
+ *(pointer++) = '.';
+ i++;
+ n = number;
+ count = 0;
+ while (i < FRACTION_DIGITS) {
+ n -= floor(n);
+ n *= 10.0;
+ index = (int)n % 10;
+ *(pointer++) = "0123456789"[index];
+ i++;
+ if ((index != 0) || (count > 0))
+ count++;
+ if ((n > 10.0) || (count > FRACTION_DIGITS / 2))
+ break;
+ }
+ }
+ /* Remove trailing zeroes */
+ while ((pointer[-1] == '0') && (i > 0)) {
+ pointer--;
+ i--;
+ }
+ digits += i;
+
+ if (use_scientific) {
+ *(pointer++) = 'e';
+ digits++;
+ if (exponent < 0) {
+ *(pointer++) = '-';
+ exponent = -exponent;
+ } else {
+ *(pointer++) = '+';
+ }
+ digits++;
+ if (exponent >= 100)
+ pointer += 2;
+ else if (exponent >= 10)
+ pointer += 1;
+ while (exponent >= 1) {
+ *(pointer--) = "0123456789"[exponent % 10];
+ exponent /= 10;
+ digits++;
+ }
+ }
+
+ if (digits >= buffersize)
+ digits = buffersize - 1;
+
+ memcpy(buffer, start, digits);
+ buffer[digits] = 0;
+ }
+ break;
+ }
+}
+
/************************************************************************
* *
* Error handling routines *
@@ -632,7 +783,7 @@
*/
void
xmlXPathNodeSetSort(xmlNodeSetPtr set) {
- int i, j, incr, len, rc;
+ int i, j, incr, len;
xmlNodePtr tmp;
if (set == NULL)
@@ -644,8 +795,8 @@
for (i = incr; i < len; i++) {
j = i - incr;
while (j >= 0) {
- rc = xmlXPathCmpNodes(set->nodeTab[j], set->nodeTab[j + incr]);
- if (rc != 1 && rc != -2) {
+ if (xmlXPathCmpNodes(set->nodeTab[j],
+ set->nodeTab[j + incr]) == -1) {
tmp = set->nodeTab[j];
set->nodeTab[j] = set->nodeTab[j + incr];
set->nodeTab[j + incr] = tmp;
@@ -2093,15 +2244,7 @@
((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
return(0);
- if (isnan(f))
- sprintf(buf, "NaN");
- else if (isinf(f) > 0)
- sprintf(buf, "+Infinity");
- else if (isinf(f) < 0)
- sprintf(buf, "-Infinity");
- else
- sprintf(buf, "%0g", f);
-
+ xmlXPathFormatNumber(f, buf, sizeof(buf));
return(xmlXPathEqualNodeSetString(arg, BAD_CAST buf));
}
@@ -3191,6 +3334,7 @@
xmlNodePtr cur = NULL;
xmlXPathObjectPtr obj;
xmlNodeSetPtr nodelist;
+ xmlNodePtr tmp;
CHECK_TYPE(XPATH_NODESET);
obj = valuePop(ctxt);
@@ -3343,6 +3487,7 @@
* principal node type. For example, child::* willi
* select all element children of the context node
*/
+ tmp = ctxt->context->node;
for (i = 0;i < nodelist->nodeNr; i++) {
ctxt->context->node = nodelist->nodeTab[i];
@@ -3356,6 +3501,7 @@
#endif
switch (test) {
case NODE_TEST_NONE:
+ ctxt->context->node = tmp;
STRANGE
return;
case NODE_TEST_TYPE:
@@ -3483,6 +3629,7 @@
}
} while (cur != NULL);
}
+ ctxt->context->node = tmp;
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext,
"\nExamined %d nodes, found %d nodes at that step\n", t, n);
@@ -3944,14 +4091,7 @@
case XPATH_NUMBER: {
char buf[100];
- if (isnan(cur->floatval))
- sprintf(buf, "NaN");
- else if (isinf(cur->floatval) > 0)
- sprintf(buf, "+Infinity");
- else if (isinf(cur->floatval) < 0)
- sprintf(buf, "-Infinity");
- else
- sprintf(buf, "%0g", cur->floatval);
+ xmlXPathFormatNumber(cur->floatval, buf, sizeof(buf));
valuePush(ctxt, xmlXPathNewCString(buf));
xmlXPathFreeObject(cur);
return;