CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/04/27 08:46:46
Modified files: . : ChangeLog server : as_value.cpp as_value.h server/asobj : Number.cpp testsuite/swfdec: PASSING Log message: * server/as_value.{cpp,h}: add a static doubleToString(double) function moved here from a static in Number.cpp, given its good quality. * server/asobj/Number.cpp: use as_value::doubleToString() for returning text value. Drop the string representation cache, no more needed. * testsuite/swfdec/PASSING: double.swf now succeeds CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.3016&r2=1.3017 http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.cpp?cvsroot=gnash&r1=1.49&r2=1.50 http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.h?cvsroot=gnash&r1=1.50&r2=1.51 http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Number.cpp?cvsroot=gnash&r1=1.29&r2=1.30 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/swfdec/PASSING?cvsroot=gnash&r1=1.18&r2=1.19 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.3016 retrieving revision 1.3017 diff -u -b -r1.3016 -r1.3017 --- ChangeLog 27 Apr 2007 07:51:33 -0000 1.3016 +++ ChangeLog 27 Apr 2007 08:46:45 -0000 1.3017 @@ -1,5 +1,14 @@ 2007-04-27 Sandro Santilli <[EMAIL PROTECTED]> + * server/as_value.{cpp,h}: add a static doubleToString(double) function + moved here from a static in Number.cpp, given its good quality. + * server/asobj/Number.cpp: use as_value::doubleToString() for + returning text value. Drop the string representation cache, no + more needed. + * testsuite/swfdec/PASSING: double.swf now succeeds + +2007-04-27 Sandro Santilli <[EMAIL PROTECTED]> + * libbase/triangulate_impl.h: include config.h. * libbase/network.{cpp,h}: (writeNet): take a const string ref, not a copy. Index: server/as_value.cpp =================================================================== RCS file: /sources/gnash/gnash/server/as_value.cpp,v retrieving revision 1.49 retrieving revision 1.50 diff -u -b -r1.49 -r1.50 --- server/as_value.cpp 26 Apr 2007 17:06:10 -0000 1.49 +++ server/as_value.cpp 27 Apr 2007 08:46:46 -0000 1.50 @@ -88,35 +88,7 @@ break; case NUMBER: - // @@ Moock says if value is a NAN, - // then result is "NaN" - // INF goes to "Infinity" - // -INF goes to "-Infinity" - if (isnan(m_number_value)) - { - m_string_value = "NaN"; - } - else if (isinf(m_number_value)) - { - if (m_number_value > 0.0) - { - m_string_value = "Infinity"; - } - else - { - m_string_value = "-Infinity"; - } - } - else if ( m_number_value == -0.0 || m_number_value == 0.0 ) - { - m_string_value = "0"; - } - else - { - char buffer[50]; - snprintf(buffer, 50, "%.14g", m_number_value); - m_string_value = buffer; - } + m_string_value = doubleToString(m_number_value); break; case UNDEFINED: @@ -851,6 +823,165 @@ set_as_object(obj); } + +// Convert numeric value to string value, following ECMA-262 specification +std::string +as_value::doubleToString(double _val) +{ + // Printing formats: + // + // If _val > 1, Print up to 15 significant digits, then switch + // to scientific notation, rounding at the last place and + // omitting trailing zeroes. + // e.g. for 9*.1234567890123456789 + // ... + // 9999.12345678901 + // 99999.123456789 + // 999999.123456789 + // 9999999.12345679 + // 99999999.1234568 + // 999999999.123457 + // 9999999999.12346 + // 99999999999.1235 + // 999999999999.123 + // 9999999999999.12 + // 99999999999999.1 + // 999999999999999 + // 1e+16 + // 1e+17 + // ... + // e.g. for 1*.111111111111111111111111111111111111 + // ... + // 1111111111111.11 + // 11111111111111.1 + // 111111111111111 + // 1.11111111111111e+15 + // 1.11111111111111e+16 + // ... + // For values < 1, print up to 4 leading zeroes after the + // deciman 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 + // 0.123456789012346 + // 0.0123456789012346 + // 0.00123456789012346 + // 0.000123456789012346 + // 0.0000123456789012346 + // 0.00000123456789012346 + // 1.23456789012346e-6 + // 1.23456789012346e-7 + // ... + // + // 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. + + // The following code gives the same results as Adobe player + // except for + // 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 + // These values are at the limit of a double's precision, + // for example, in C, + // .99999999999999938 printfs as + // .99999999999999933387 and + // .99999999999999939 printfs as + // .99999999999999944489 + // so this behaviour is probably too compiler-dependent to + // reproduce exactly. + // + // There may be some milage in comparing against + // 0.00009999999999999995 and + // 0.000009999999999999995 instead. + + // 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]; + + // FP_ZERO, FP_NORMAL and FP_SUBNORMAL + 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. + + char c; // character being moved forward + + // 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 + } + } + else + { + // Regular case + char *cp; + + 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'; + } + } + + return std::string(_str); +} + + } // namespace gnash Index: server/as_value.h =================================================================== RCS file: /sources/gnash/gnash/server/as_value.h,v retrieving revision 1.50 retrieving revision 1.51 diff -u -b -r1.50 -r1.51 --- server/as_value.h 26 Apr 2007 10:17:56 -0000 1.50 +++ server/as_value.h 27 Apr 2007 08:46:46 -0000 1.51 @@ -14,7 +14,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -/* $Id: as_value.h,v 1.50 2007/04/26 10:17:56 strk Exp $ */ +/* $Id: as_value.h,v 1.51 2007/04/27 08:46:46 strk Exp $ */ #ifndef GNASH_AS_VALUE_H #define GNASH_AS_VALUE_H @@ -185,6 +185,7 @@ { } + /// Construct a NUMBER value as_value(long val) : m_type(NUMBER), @@ -192,6 +193,7 @@ { } + /// Construct a NUMBER value as_value(unsigned long val) : m_type(NUMBER), @@ -216,6 +218,7 @@ set_as_object(obj); } + /// Construct an NULL, MOVIECLIP, AS_FUNCTION or OBJECT value as_value(boost::intrusive_ptr<as_object> obj); /// Construct a NULL or AS_FUNCTION value @@ -223,6 +226,12 @@ ~as_value() { drop_refs(); } + /// Convert numeric value to string value, following ECMA-262 specification + // + /// TODO: move here some of the good comments found in the function definition. + /// + static std::string doubleToString(double val); + /// Drop any ref counts we have. // /// This happens prior to changing our value. Index: server/asobj/Number.cpp =================================================================== RCS file: /sources/gnash/gnash/server/asobj/Number.cpp,v retrieving revision 1.29 retrieving revision 1.30 diff -u -b -r1.29 -r1.30 --- server/asobj/Number.cpp 26 Apr 2007 07:00:29 -0000 1.29 +++ server/asobj/Number.cpp 27 Apr 2007 08:46:46 -0000 1.30 @@ -1,4 +1,4 @@ -/*/ Number.cpp: ActionScript Number class, for Gnash. +// Number.cpp: ActionScript Number class, for Gnash. // // Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. // @@ -17,7 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -/* $Id: Number.cpp,v 1.29 2007/04/26 07:00:29 strk Exp $ */ +/* $Id: Number.cpp,v 1.30 2007/04/27 08:46:46 strk Exp $ */ #include "log.h" #include "tu_config.h" @@ -25,6 +25,7 @@ #include "smart_ptr.h" #include "fn_call.h" #include "as_object.h" // for inheritance +#include "as_value.h" // for doubleToString #include "builtin_function.h" // need builtin_function #include <sstream> @@ -52,7 +53,7 @@ namespace gnash { // Forward declarations -static void number_val_to_str(double val, char *str); +//static void number_val_to_str(double val, char *str); //static as_value number_to_string(const fn_call& fn); static void @@ -91,7 +92,7 @@ double _val; // string representation of the above number - mutable char _str[256]; + //mutable char _str[256]; public: @@ -105,8 +106,8 @@ // override from as_object std::string get_text_value() const { - number_val_to_str(_val, _str); - return _str; + return as_value::doubleToString(_val); // number_val_to_str(_val, _str); + //return _str; } // override from as_object @@ -122,146 +123,6 @@ }; -// Convert numeric value to string value -static void -number_val_to_str(double _val, char *_str) -{ - // Printing formats: - // - // If _val > 1, Print up to 15 significant digits, then switch - // to scientific notation, rounding at the last place and - // omitting trailing zeroes. - // e.g. for 9*.1234567890123456789 - // ... - // 9999.12345678901 - // 99999.123456789 - // 999999.123456789 - // 9999999.12345679 - // 99999999.1234568 - // 999999999.123457 - // 9999999999.12346 - // 99999999999.1235 - // 999999999999.123 - // 9999999999999.12 - // 99999999999999.1 - // 999999999999999 - // 1e+16 - // 1e+17 - // ... - // e.g. for 1*.111111111111111111111111111111111111 - // ... - // 1111111111111.11 - // 11111111111111.1 - // 111111111111111 - // 1.11111111111111e+15 - // 1.11111111111111e+16 - // ... - // For values < 1, print up to 4 leading zeroes after the - // deciman 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 - // 0.123456789012346 - // 0.0123456789012346 - // 0.00123456789012346 - // 0.000123456789012346 - // 0.0000123456789012346 - // 0.00000123456789012346 - // 1.23456789012346e-6 - // 1.23456789012346e-7 - // ... - // - // 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. - - // The following code gives the same results as Adobe player - // except for - // 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 - // These values are at the limit of a double's precision, - // for example, in C, - // .99999999999999938 printfs as - // .99999999999999933387 and - // .99999999999999939 printfs as - // .99999999999999944489 - // so this behaviour is probably too compiler-dependent to - // reproduce exactly. - // - // There may be some milage in comparing against - // 0.00009999999999999995 and - // 0.000009999999999999995 instead. - - // Handle non-numeric values. - // "printf" gives "nan", "inf", "-inf", so we check explicitly - if(isnan(_val)) - strcpy(_str, "NaN"); - else if(isinf(_val)) - strcpy(_str, _val < 0 ? "-Infinity" : "Infinity"); - else{ // FP_ZERO, FP_NORMAL and FP_SUBNORMAL - 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. - - char c; // character being moved forward - - // 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 - } - } else { - // Regular case - char *cp; - - 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'; - } - } - } -} - static as_value number_ctor(const fn_call& fn) { Index: testsuite/swfdec/PASSING =================================================================== RCS file: /sources/gnash/gnash/testsuite/swfdec/PASSING,v retrieving revision 1.18 retrieving revision 1.19 diff -u -b -r1.18 -r1.19 --- testsuite/swfdec/PASSING 24 Apr 2007 07:25:20 -0000 1.18 +++ testsuite/swfdec/PASSING 27 Apr 2007 08:46:46 -0000 1.19 @@ -56,3 +56,4 @@ divide-7.swf object-math-7.swf event-order.swf +double.swf _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit