enhanced the coding for xmlXPathCastNumberToString in order to produce the

* xpath.c: enhanced the coding for xmlXPathCastNumberToString
  in order to produce the required number of significant digits
  (bug #437179)

svn path=/trunk/; revision=3615
diff --git a/ChangeLog b/ChangeLog
index aecf060..3809d2a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Fri May 11 22:45:18 HKT 2007 William Brack <wbrack@mmm.com.hk>
+
+	* xpath.c: enhanced the coding for xmlXPathCastNumberToString
+	  in order to produce the required number of significant digits
+	  (bug #437179)
+
 Thu May 10 01:52:42 CEST 2007 Daniel Veillard <daniel@veillard.com>
 
 	* list.c: applied patch to fix xmlListAppend() from 
diff --git a/xpath.c b/xpath.c
index 8c35e30..20ab273 100644
--- a/xpath.c
+++ b/xpath.c
@@ -2648,9 +2648,10 @@
 
 #define UPPER_DOUBLE 1E9
 #define LOWER_DOUBLE 1E-5
+#define	LOWER_DOUBLE_EXP 5
 
 #define INTEGER_DIGITS DBL_DIG
-#define FRACTION_DIGITS (DBL_DIG + 1)
+#define FRACTION_DIGITS (DBL_DIG + 1 + (LOWER_DOUBLE_EXP))
 #define EXPONENT_DIGITS (3 + 2)
 
 /**
@@ -2701,8 +2702,16 @@
 		*ptr = 0;
 	    }
 	} else {
-	    /* 3 is sign, decimal point, and terminating zero */
-	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
+	    /*
+	      For the dimension of work,
+	          DBL_DIG is number of significant digits
+		  EXPONENT is only needed for "scientific notation"
+	          3 is sign, decimal point, and terminating zero
+		  LOWER_DOUBLE_EXP is max number of leading zeroes in fraction
+	      Note that this dimension is slightly (a few characters)
+	      larger than actually necessary.
+	    */
+	    char work[DBL_DIG + EXPONENT_DIGITS + 3 + LOWER_DOUBLE_EXP];
 	    int integer_place, fraction_place;
 	    char *ptr;
 	    char *after_fraction;
@@ -2725,24 +2734,25 @@
 		size = snprintf(work, sizeof(work),"%*.*e",
 			 integer_place, fraction_place, number);
 		while ((size > 0) && (work[size] != 'e')) size--;
-		after_fraction = work + size;
 
 	    }
 	    else {
 		/* Use regular notation */
-		if (absolute_value > 0.0)
-		    integer_place = 1 + (int)log10(absolute_value);
-		else
-		    integer_place = 0;
-		fraction_place = (integer_place > 0)
-		    ? DBL_DIG - integer_place
-		    : DBL_DIG;
+		if (absolute_value > 0.0) {
+		    integer_place = (int)log10(absolute_value);
+		    if (integer_place > 0)
+		        fraction_place = DBL_DIG - integer_place - 1;
+		    else
+		        fraction_place = DBL_DIG - integer_place;
+		} else {
+		    fraction_place = 1;
+		}
 		size = snprintf(work, sizeof(work), "%0.*f",
 				fraction_place, number);
-		after_fraction = work + size;
 	    }
 
 	    /* Remove fractional trailing zeroes */
+	    after_fraction = work + size;
 	    ptr = after_fraction;
 	    while (*(--ptr) == '0')
 		;