gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog server/as_value.cpp


From: Benjamin Wolsey
Subject: [Gnash-commit] gnash ChangeLog server/as_value.cpp
Date: Thu, 08 Nov 2007 15:03:58 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Benjamin Wolsey <bwy>   07/11/08 15:03:58

Modified files:
        .              : ChangeLog 
        server         : as_value.cpp 

Log message:
                * server/as_value.cpp (doubletoString): replace C code with a 
c++
                  implementation that ought to do the same thing. Uses 
stringstream
                  and locale to imbue the result with the standard C locale, 
which
                  fixes problems with locales that have a comma decimal 
separator.
                  The test below should now pass in all locales.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4806&r2=1.4807
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.cpp?cvsroot=gnash&r1=1.92&r2=1.93

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4806
retrieving revision 1.4807
diff -u -b -r1.4806 -r1.4807
--- ChangeLog   8 Nov 2007 14:47:55 -0000       1.4806
+++ ChangeLog   8 Nov 2007 15:03:58 -0000       1.4807
@@ -1,5 +1,10 @@
 2007-11-08 Benjamin Wolsey <address@hidden>
 
+       * server/as_value.cpp (doubletoString): replace C code with a c++
+         implementation that ought to do the same thing. Uses stringstream
+         and locale to imbue the result with the standard C locale, which
+         fixes problems with locales that have a comma decimal separator.
+         The test below should now pass in all locales.
        * testsuite/actionscript.all/Number.as: add tests for number formatting
          based on comments in server/as_value.cpp. Presently they should fail
          for locales with a comma decimal separator.

Index: server/as_value.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_value.cpp,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -b -r1.92 -r1.93
--- server/as_value.cpp 1 Nov 2007 16:14:20 -0000       1.92
+++ server/as_value.cpp 8 Nov 2007 15:03:58 -0000       1.93
@@ -37,6 +37,9 @@
 
 #include <boost/algorithm/string/case_conv.hpp>
 #include <boost/lexical_cast.hpp>
+#include <locale>
+#include <sstream>
+#include <iomanip>
 
 
 using namespace std;
@@ -1146,7 +1149,7 @@
        // 1.11111111111111e+16
        // ...
        // For values < 1, print up to 4 leading zeroes after the
-       // deciman point, then switch to scientific notation with up
+       // decimal point, then switch to scientific notation with up
        // to 15 significant digits, rounding with no trailing zeroes
        // e.g. for 1.234567890123456789 * 10^-i:
        // 1.23456789012346
@@ -1163,12 +1166,11 @@
        // If the value is negative, just add a '-' to the start; this
        // does not affect the precision of the printed value.
        //
-       // This almost corresponds to printf("%.15g") format, except
-       // that %.15g switches to scientific notation at e-05 not e-06,
-       // and %g always prints at least two digits for the exponent.
+       // This almost corresponds to iomanip's std::setprecision(15)
+       // format, except that iomanip switches to scientific notation
+       // at e-05 not e-06, and always prints at least two digits for the 
exponent.
 
-       // The following code gives the same results as Adobe player
-       // except for
+       // The C implementation had problems with the following cases:
        // 9.99999999999999[39-61] e{-2,-3}. Adobe prints these as
        // 0.0999999999999999 and 0.00999999999999 while we print them
        // as 0.1 and 0.01
@@ -1184,88 +1186,64 @@
        // There may be some milage in comparing against
        // 0.00009999999999999995 and
        // 0.000009999999999999995 instead.
+       //
+       // The stringstream implementation seems to have no problems with them,
+       // but that may just be a better compiler.
 
        // Handle non-numeric values.
        // "printf" gives "nan", "inf", "-inf", so we check explicitly
        if(isnan(_val))
        {
-               //strcpy(_str, "NaN");
                return "NaN";
        }
        else if(isinf(_val))
        {
                return _val < 0 ? "-Infinity" : "Infinity";
-               //strcpy(_str, _val < 0 ? "-Infinity" : "Infinity");
        }
        else if(_val == 0.0 || _val == -0.0)
        {
                return "0";
-               //strcpy(_str, _val < 0 ? "-Infinity" : "Infinity");
        }
 
-       char _str[256];
+       ostringstream _ostr;
+       std::string _str;
+       
+       // ActionScript always expects dot as decimal point?
+       _ostr.imbue(std::locale("C")); 
 
-       // FP_ZERO, FP_NORMAL and FP_SUBNORMAL
+       // force to decimal notation for this range (because the reference 
player does)
        if (fabs(_val) < 0.0001 && fabs(_val) >= 0.00001)
        {
-               // This is the range for which %.15g gives scientific
-               // notation but for which we must give decimal.
-               // We can't easily use %f bcos it prints a fixed number
-               // of digits after the point, not the maximum number of
-               // significant digits with trailing zeroes removed that
-               // we require. So we just get %g to do its non-e stuff
-               // by multiplying the value by ten and then stuffing
-               // an extra zero into the result after the decimal
-               // point. Yuk!
-               char *cp;
-               
-               sprintf(_str, "%.15g", _val * 10.0);
-               if ((cp = strchr(_str, '.')) == NULL || cp[1] != '0') {
-                       log_error(_("Internal error: Cannot find \".0\" in %s 
for %.15g"), _str, _val);
-                       // Just give it to them raw instead
-                       sprintf(_str, "%.15g", _val);
-               } else {
-#if HAVE_MEMMOVE
-                       // Shunt the digits right one place after the
-                       // decimal point.
-                       memmove(cp+2, cp+1, strlen(cp+1)+1);
-#else
-                       // We can't use strcpy() cos the args overlap.
+               // All nineteen digits (4 zeros + up to 15 significant digits)
+               _ostr << fixed << std::setprecision(19) << _val;
 
-                       char c; // character being moved forward
+               _str = _ostr.str();
                        
-                       // At this point, cp points at the '.'
-                       //
-                       // In the loop body it points at where we pick
-                       // up the next char to move forward and where
-                       // we drop the one we picked up on its left.
-                       // We stop when we have just picked up the \0.
-                       for (c = '0', cp++; c != '\0'; cp++) {
-                               char tmp = *cp; *cp = c; c = tmp;
-                       }
-                       // Store the '\0' we just picked up
-                       *cp = c;
-#endif
+               // Because 'fixed' also adds trailing zeros, remove them.
+               std::string::size_type pos = _str.find_last_not_of('0');
+               if (pos != std::string::npos) {
+                       _str.erase(pos + 1);
                }
+               
        }
+       
        else
        {
-               // Regular case
-               char *cp;
+               _ostr << std::setprecision(15) << _val;
+               
+               _str = _ostr.str();
 
-               sprintf(_str, "%.15g", _val);
                // Remove a leading zero from 2-digit exponent if any
-               if ((cp = strchr(_str, 'e')) != NULL &&
-                   cp[2] == '0') {
-                       // We can't use strcpy() cos its src&dest can't
-                       // overlap. However, this can only be "...e+0n"
-                       // or ...e-0n;  3+digit exponents never have
-                       // leading 0s.
-                       cp[2] = cp[3]; cp[3] = '\0';
+               std::string::size_type pos = _str.find("e", 0);
+
+               if (pos != std::string::npos && _str.at(pos + 2) == '0') {
+                       _str.erase(pos + 2, 1);
                }
+               
        }
 
-       return std::string(_str);
+       return _str;
+       
 }
 
 void




reply via email to

[Prev in Thread] Current Thread [Next in Thread]