gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r9921: More tests, fewer macros for


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r9921: More tests, fewer macros for Date class to try and catch why there is a
Date: Sat, 04 Oct 2008 12:53:09 +0200
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 9921
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Sat 2008-10-04 12:53:09 +0200
message:
  More tests, fewer macros for Date class to try and catch why there is a
  failure on Debian Lenny.
modified:
  libbase/ClockTime.cpp
  libcore/asobj/Date.cpp
  libcore/asobj/Date.h
  testsuite/actionscript.all/Date.as
    ------------------------------------------------------------
    revno: 9911.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Fri 2008-10-03 19:25:18 +0200
    message:
      Move Date class definition to implementation file, drop unused code, 
      provide default argument to constructor.
    modified:
      libcore/asobj/Date.cpp
      libcore/asobj/Date.h
    ------------------------------------------------------------
    revno: 9911.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2008-10-04 10:13:59 +0200
    message:
      Use inline functions instead of a macro for Date get* methods. Provide
      a skeleton function for each method, so that the code is at least 
readable.
    modified:
      libcore/asobj/Date.cpp
    ------------------------------------------------------------
    revno: 9911.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2008-10-04 10:15:56 +0200
    message:
      Minor cleanup.
    modified:
      libcore/asobj/Date.h
    ------------------------------------------------------------
    revno: 9911.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2008-10-04 10:55:27 +0200
    message:
      Safely truncate large doubles.
    modified:
      libcore/asobj/Date.cpp
    ------------------------------------------------------------
    revno: 9911.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2008-10-04 11:55:12 +0200
    message:
      Correct truncation.
    modified:
      libcore/asobj/Date.cpp
    ------------------------------------------------------------
    revno: 9911.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2008-10-04 12:21:33 +0200
    message:
      Use LOG_ONCE.
    modified:
      libbase/ClockTime.cpp
    ------------------------------------------------------------
    revno: 9911.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2008-10-04 12:29:04 +0200
    message:
      Add more tests to large date value.
    modified:
      testsuite/actionscript.all/Date.as
=== modified file 'libbase/ClockTime.cpp'
--- a/libbase/ClockTime.cpp     2008-04-07 10:43:55 +0000
+++ b/libbase/ClockTime.cpp     2008-10-04 10:21:33 +0000
@@ -264,11 +264,9 @@
     else {
         // tm_isdst is negative: cannot get TZ info.
         // Convert and print in UTC instead.
-        static bool warned = false;
-        if (!warned) {
+        LOG_ONCE(
             gnash::log_error(_("Cannot get requested timezone information"));
-            warned = true;
-        }
+        );
         offset = 0;
     }
 

=== modified file 'libcore/asobj/Date.cpp'
--- a/libcore/asobj/Date.cpp    2008-09-12 21:18:45 +0000
+++ b/libcore/asobj/Date.cpp    2008-10-04 09:55:12 +0000
@@ -79,7 +79,6 @@
 #include "ClockTime.h"
 #include "VM.h"
 
-#include <ctime>
 #include <cmath>
 #include <boost/format.hpp>
 
@@ -111,9 +110,9 @@
 // forward declarations
 static void fillGnashTime(const double& time, GnashTime& gt);
 static double makeTimeValue(GnashTime& gt);
-static void getLocalTime(const double& time, GnashTime& gt);
-static void getUniversalTime(const double& time, GnashTime& gt);
-static int getLocalTimeZoneOffset(const double& time);
+static void localTime(const double& time, GnashTime& gt);
+static void universalTime(const double& time, GnashTime& gt);
+static int localTimeZoneOffset(const double& time);
 
 static double rogue_date_args(const fn_call& fn, unsigned maxargs);
 
@@ -124,31 +123,57 @@
 // to get the actual number
 #define COUNT_LEAP_YEARS(n)   ( (n - 70) / 4 - (n - 70) / 100 + (n - 70) / 400 
)
 
-
-// FIND_YEAR_ALGORITHM:
-//      default: ("brute force"):   up to 400 iterations to find the correct
-//                                  year. Accurate.
-//      MATHEMATIC_ALGORITHM        small number of iterations, fairly 
accurate.
-//      APPROXIMATE_ALGORITHM       no iterations, not all that accurate.
-//#define USE_MATHEMATIC_ALGORITHM
-//#define USE_APPROXIMATE_ALGORITHM
-
-static void
-getLocalTime(const double& time, GnashTime& gt)
+class Date : public as_object
+{
+public:
+    void setTimeValue(const double& value) { _value = value; }
+    double getTimeValue() const { return _value; }
+
+    Date(double value = clocktime::getTicks());
+
+    as_value toString() const;
+
+    bool isDateObject() { return true; }
+
+private:
+    double _value;
+};
+
+/// Return the broken-down time as a local time.
+inline void
+localTime(const double& time, GnashTime& gt)
 {
     // find local timezone offset for the desired time.
-    gt.timeZoneOffset = getLocalTimeZoneOffset(time);
+    gt.timeZoneOffset = localTimeZoneOffset(time);
     fillGnashTime(time, gt);
 }
 
-static void
-getUniversalTime(const double& time, GnashTime& gt)
+/// Return the broken-down time as UTC
+inline void
+universalTime(const double& time, GnashTime& gt)
 {
     // No time zone needed.
     gt.timeZoneOffset = 0;
     fillGnashTime(time, gt);
 }
 
+
+/// Safely truncate a double to an integer, returning the min()
+/// limit on overflow.
+template <typename T>
+inline void truncateDouble(T& target, double value)
+{
+    if (value < std::numeric_limits<T>::min() ||
+            value > std::numeric_limits<T>::max())
+    {
+        target = std::numeric_limits<T>::min();
+        return;
+    }
+    target = static_cast<T>(value);
+
+}
+
+
 // Seconds and milliseconds should be exactly the same whether in UTC
 // or in localtime, so we always use localtime.
 
@@ -320,21 +345,11 @@
 }
 
 
-Date::Date()
-    :
-    as_object(getDateInterface()),
-    _value(clocktime::getTicks())
-{
-
-}
-
-
 Date::Date(double value)
     :
     as_object(getDateInterface()),
     _value(value)
 {
-
 }
 
 
@@ -358,7 +373,7 @@
     GnashTime gt;
     // Time zone offset (including DST) as hours and minutes east of GMT
 
-    getLocalTime(_value, gt);
+    localTime(_value, gt);
 
     int offsetHours = gt.timeZoneOffset / 60;
     int offsetMinutes = gt.timeZoneOffset % 60;    
@@ -391,7 +406,6 @@
 /// and negative values are years prior to 1900. Thus the only way to
 /// specify the year 50AD is as -1850.
 /// Defaults are 0 except for date (day of month) whose default it 1.
-
 as_value
 date_new(const fn_call& fn)
 {
@@ -441,7 +455,8 @@
         switch (fn.nargs) {
             default:
                 IF_VERBOSE_ASCODING_ERRORS(
-                log_aserror(_("Date constructor called with more than 7 
arguments"));
+                log_aserror(_("Date constructor called with more than 7 "
+                        "arguments"));
                 )
             case 7:
                 // fractions of milliseconds are ignored
@@ -476,93 +491,190 @@
 
 // Date.getTime() is implemented by Date.valueOf()
 
-// Functions to return broken-out elements of the date and time.
-
-// We use a prototype macro to generate the function bodies because the many
-// individual functions are small and almost identical.
-
-// This calls _gmtime_r and _localtime_r, which are defined above into
-// gmtime_r and localtime_r or our own local equivalents.
-
-#define date_get_proto(function, timefn, element) \
-  static as_value function(const fn_call& fn) { \
-    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr); \
-    if (isNaN(date->getTimeValue()) || isinf(date->getTimeValue())) { as_value 
rv; rv.set_nan(); return rv; } \
-    GnashTime gt; \
-    timefn(date->getTimeValue(), gt); \
-    return as_value(gt.element); \
-  }
-
-/// \brief Date.getYear
-/// returns a Date's Gregorian year minus 1900 according to local time.
-
-date_get_proto(date_getyear, getLocalTime, year)
+/// Return true if the date is invalid.
+inline
+bool invalidDate(double timeValue)
+{
+    return (isNaN(timeValue) || isinf(timeValue));
+}
+
+/// Returns an element of the Date object as an as_value
+//
+/// An invalid date value is returned as NaN (this is probably not correct,
+/// as the pp returns something weird in this case).
+//
+/// @param dateFunc     The date function (either localTime or universalTime)
+///                     to use to break the time value into elements.
+/// @param element      A pointer-to-data-member of the GnashTime struct, 
+///                     specifying which element to return.
+/// @param timeValue    The time value to break into elements.
+/// @param adjustment   Adjust the result by this amount (used for full year).
+template<typename T>
+inline as_value timeElement(T dateFunc, boost::int32_t GnashTime::* element,
+        double timeValue, int adjustment = 0)
+{
+    if (invalidDate(timeValue)) return as_value();
+    GnashTime gt;
+    dateFunc(timeValue, gt);
+    return as_value(gt.*element + adjustment);
+}
+
+
+/// Date.getYear()
+//
+/// Returns a Date's Gregorian year minus 1900 according to local time.
+static as_value
+date_getyear(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::year, date->getTimeValue());
+}
 
 /// \brief Date.getFullYear
 /// returns a Date's Gregorian year according to local time.
-
-date_get_proto(date_getfullyear, getLocalTime, year + 1900)
+static as_value
+date_getfullyear(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::year, date->getTimeValue(), 
1900);
+}
 
 /// \brief Date.getMonth
 /// returns a Date's month in the range 0 to 11.
-
-date_get_proto(date_getmonth, getLocalTime, month)
+static as_value
+date_getmonth(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::month, date->getTimeValue());
+}
 
 /// \brief Date.getDate
 /// returns a Date's day-of-month, from 1 to 31 according to local time.
-
-date_get_proto(date_getdate, getLocalTime, monthday)
+static as_value
+date_getdate(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::monthday, date->getTimeValue());
+}
 
 /// \brief Date.getDay
 /// returns the day of the week for a Date according to local time,
 /// where 0 is Sunday and 6 is Saturday.
+static as_value
+date_getday(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::weekday, date->getTimeValue());
+}
 
-date_get_proto(date_getday, getLocalTime, weekday)
 
 /// \brief Date.getHours
 /// Returns the hour number for a Date, from 0 to 23, according to local time.
-
-date_get_proto(date_gethours, getLocalTime, hour)
+static as_value
+date_gethours(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::hour, date->getTimeValue());
+}
 
 /// \brief Date.getMinutes
 /// returns a Date's minutes, from 0-59, according to localtime.
-// (Yes, some places do have a fractions of an hour's timezone offset
-// or daylight saving time!)
-
-date_get_proto(date_getminutes, getLocalTime, minute)
+/// (Yes, some places do have a fractions of an hour's timezone offset
+/// or daylight saving time!)
+static as_value
+date_getminutes(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::minute, date->getTimeValue());
+}
 
 /// \brief Date.getSeconds
 /// returns a Date's seconds, from 0-59.
 /// Localtime should be irrelevant.
-
-date_get_proto(date_getseconds, getLocalTime, second)
+static as_value
+date_getseconds(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(localTime, &GnashTime::second, date->getTimeValue());
+}
 
 /// \brief Date.getMilliseconds
 /// returns a Date's millisecond component as an integer from 0 to 999.
 /// Localtime is irrelevant!
 //
 // Also implements Date.getUTCMilliseconds
-date_get_proto(date_getmilliseconds, getLocalTime, millisecond)
+static as_value
+date_getmilliseconds(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(
+            localTime, &GnashTime::millisecond, date->getTimeValue());
+}
 
 
 // The same functions for universal time.
 //
-date_get_proto(date_getutcfullyear, getUniversalTime, year + 1900)
-date_get_proto(date_getutcyear,     getUniversalTime, year)
-date_get_proto(date_getutcmonth,    getUniversalTime, month)
-date_get_proto(date_getutcdate,     getUniversalTime, monthday)
-date_get_proto(date_getutcday,      getUniversalTime, weekday)
-date_get_proto(date_getutchours,    getUniversalTime, hour)
-date_get_proto(date_getutcminutes,  getUniversalTime, minute)
+static as_value
+date_getutcfullyear(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(universalTime, &GnashTime::year,
+           date->getTimeValue(), 1900);
+}
+
+static as_value
+date_getutcyear(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(universalTime, &GnashTime::year, date->getTimeValue());
+}
+
+static as_value
+date_getutcmonth(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(universalTime, &GnashTime::month, date->getTimeValue());
+}
+
+static as_value
+date_getutcdate(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(
+            universalTime, &GnashTime::monthday, date->getTimeValue());
+}
+
+    
+static as_value
+date_getutcday(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(
+                universalTime, &GnashTime::weekday, date->getTimeValue());
+}
+
+static as_value
+date_getutchours(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(
+                universalTime, &GnashTime::hour, date->getTimeValue());
+}
+
+static as_value
+date_getutcminutes(const fn_call& fn)
+{
+    boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
+    return timeElement(universalTime, &GnashTime::minute, 
date->getTimeValue());
+}
 
 
 // Return the difference between UTC and localtime in minutes.
-static int getLocalTimeZoneOffset(const double& time)
+inline int localTimeZoneOffset(const double& time)
 {
     // This simply has to return the difference in minutes
     // between UTC (Greenwich Mean Time, GMT) and the localtime.
     // Obviously, this includes Daylight Saving Time if it applies.
-
     return clocktime::getTimeZoneOffset(time);
 }
 
@@ -575,7 +687,7 @@
 date_gettimezoneoffset(const fn_call& fn)
 {
     boost::intrusive_ptr<Date> date = ensureType<Date>(fn.this_ptr);
-    return as_value( -getLocalTimeZoneOffset(date->getTimeValue()) );
+    return as_value(-localTimeZoneOffset(date->getTimeValue()));
 }
 
 
@@ -603,7 +715,8 @@
 
     if (fn.nargs > 1) {
         IF_VERBOSE_ASCODING_ERRORS(
-            log_aserror(_("Date.setTime was called with more than one 
argument"));
+            log_aserror(_("Date.setTime was called with more than one "
+                    "argument"));
         )
     }
 
@@ -635,7 +748,8 @@
 
     else {
         double localTime = makeTimeValue(gt);
-        date.setTimeValue(localTime - clocktime::getTimeZoneOffset(localTime) 
* 60000);
+        date.setTimeValue(localTime - 
+                clocktime::getTimeZoneOffset(localTime) * 60000);
     }
 }
 
@@ -643,8 +757,8 @@
 dateToGnashTime(Date& date, GnashTime& gt, bool utc)
 {
     // Needs timezone.
-    if (utc) getUniversalTime(date.getTimeValue(), gt);
-    else getLocalTime(date.getTimeValue(), gt);
+    if (utc) universalTime(date.getTimeValue(), gt);
+    else localTime(date.getTimeValue(), gt);
 }
 
 //
@@ -747,13 +861,17 @@
         GnashTime gt;
 
         dateToGnashTime(*date, gt, false);
-        gt.year = static_cast<int>(fn.arg(0).to_number()) - 1900;
+
+        // TODO: Should truncation be done before or after subtracting 1900?
+        truncateDouble(gt.year, fn.arg(0).to_number());
+        gt.year -= 1900;
 
         if (fn.nargs >= 2) gt.month = fn.arg(1).to_int();
         if (fn.nargs >= 3) gt.monthday = fn.arg(2).to_int();
         if (fn.nargs > 3) {
             IF_VERBOSE_ASCODING_ERRORS(
-                log_aserror(_("Date.setYear was called with more than three 
arguments"));
+                log_aserror(_("Date.setYear was called with more than three "
+                        "arguments"));
             )
         }
         gnashTimeToDate(gt, *date, false); // utc=false: use localtime
@@ -799,7 +917,7 @@
         // January
         double monthvalue =  fn.arg(0).to_number();
         if (isNaN(monthvalue) || isinf(monthvalue)) monthvalue = 0.0;
-        gt.month = static_cast<int>(monthvalue);
+        truncateDouble(gt.month, monthvalue);
 
         // If the day-of-month value is invalid instead, the result is NaN.
         if (fn.nargs >= 2) {
@@ -809,12 +927,13 @@
                 return as_value(date->getTimeValue());
             }
             else {
-                gt.monthday = static_cast<int>(mdayvalue);
+                truncateDouble(gt.monthday, mdayvalue);
             }
         }
         if (fn.nargs > 2) {
             IF_VERBOSE_ASCODING_ERRORS(
-                log_aserror(_("Date.setMonth was called with more than three 
arguments"));
+                log_aserror(_("Date.setMonth was called with more than three "
+                        "arguments"));
             )
         }
         gnashTimeToDate(gt, *date, utc);
@@ -1003,7 +1122,7 @@
         GnashTime gt;
 
         dateToGnashTime(*date, gt, utc);
-        gt.millisecond = static_cast<int>(fn.arg(0).to_number());
+        truncateDouble(gt.millisecond, fn.arg(0).to_number());
 
         if (fn.nargs > 1) {
             IF_VERBOSE_ASCODING_ERRORS(
@@ -1140,7 +1259,8 @@
         case 2:   // these last two are always performed
             gt.month = fn.arg(1).to_int();
             {
-                int year = static_cast<int>(fn.arg(0).to_number());
+                boost::int32_t year = 0;
+                truncateDouble(year, fn.arg(0).to_number());
                 if (year < 100) gt.year = year;
                 else gt.year = year - 1900;
             }
@@ -1248,8 +1368,6 @@
 makeTimeValue(GnashTime& t)
 {
 
-#if 1
-
     // First, adjust years to deal with strange month
     // values.
     
@@ -1294,102 +1412,9 @@
     ret += t.second * 1000.0;
     ret += t.millisecond;
     return ret;
-#else
-
-  boost::int32_t d = t.monthday;
-  boost::int32_t m = t.month + 1;
-  boost::int32_t ya = t.year;  /* Years since 1900 */
-  boost::int32_t k;  /* day number since 1 Jan 1900 */
-
-  // For calculation, convert to a year starting on 1 March
-  if (m > 2) m -= 3;
-  else {
-    m += 9;
-    ya--;
-  }
-
-  k = (1461 * ya) / 4 + (153 * m + 2) / 5 + d + 58;
-
-  /* K is now the day number since 1 Jan 1900.
-   * Convert to minutes since 1 Jan 1970 */
-  /* 25567 is the number of days from 1 Jan 1900 to 1 Jan 1970 */
-  k = ((k - 25567) * 24 + t.hour) * 60 + t.minute;
-  
-  // Converting to double after minutes allows for +/- 4082 years with
-  // 32-bit signed integers.
-  return  (k * 60.0 + t.second) * 1000.0 + t.millisecond;
-#endif
-}
-
-
-#ifdef USE_MATHEMATICAL_ALGORITHM
-/// Helper function for getYearMathematical
-static double
-daysSinceUTCForYear(double year)
-{
-    return (
-        365 * (year - 1970) +
-        std::floor ((year - 1969) / 4.0f) -
-        std::floor ((year - 1901) / 100.0f) +
-        std::floor ((year - 1601) / 400.0f)
-    );
-}
-
-// The algorithm used by swfdec. It iterates only a small number of
-// times and is reliable to within a few milliseconds in 
-// +- 100000 years. However, it appears to get the year wrong for
-// midnight on January 1 of some years (as well as a few milliseconds
-// before the end of other years, though that seems less serious).
-static boost::int32_t
-getYearMathematical(double days)
-{
-
-    boost::int32_t low = std::floor ((days >= 0 ? days / 366.0 : days / 
365.0)) + 1970;
-    boost::int32_t high = std::ceil ((days >= 0 ? days / 365.0 : days / 
366.0)) + 1970;
-
-    while (low < high) {
-        boost::int32_t pivot = (low + high) / 2;
-
-        if (daysSinceUTCForYear (pivot) <= days) {
-            if (daysSinceUTCForYear (pivot + 1) > days) {
-                return pivot;
-            }
-            else {
-                low = pivot + 1;
-            }
-        }
-        else {
-        high = pivot - 1;
-        }
-    }
-
-    return low;
-}
-
-#elif defined (USE_APPROXIMATE_ALGORITHM) // approximate algorithm
-// Another mathematical way of working out the year, which
-// appears to be less reliable than swfdec's way. Adjusts
-// days as well as returning the year.
-static boost::int32_t
-getYearApproximate(boost::int32_t& days)
-{
-    boost::int32_t year = ((days - 16) - COUNT_LEAP_YEARS((days - 16) / 365)) 
/ 365 + 70;
-    if (time < 0) year--;
-
-    days -= (year - 70) * 365;
-    if (year < 70) {
-        days -= COUNT_LEAP_YEARS(year - 2);
-        if (year <= 0) days--;
-    }
-    else {
-        days -= COUNT_LEAP_YEARS(year + 1);
-    }
-    
-    return year;
-}
-
-
-#else
+}
+
+
 // The brute force way of converting days into years since the epoch.
 // This also reduces the number of days accurately. Its disadvantage is,
 // of course, that it iterates; its advantage that it's always correct.
@@ -1424,7 +1449,6 @@
     }
     return year - 1900;
 }
-#endif // brute force algorithm
 
 
 void fillGnashTime(const double& t, GnashTime& gt)
@@ -1439,8 +1463,13 @@
     
     // Get the sub-day part of the time, if any and reduce time
     // to number of complete days.
-    boost::int32_t remainder = static_cast<boost::int32_t>(std::fmod(time, 
86400.0));
-    boost::int32_t days = static_cast<boost::int32_t>(time / 86400.0); // 
complete days
+    // This is a safe cast.
+    boost::int32_t remainder = 
+        static_cast<boost::int32_t>(std::fmod(time, 86400.0));
+
+    // This could overflow.
+    boost::int32_t days;
+    truncateDouble(days, time / 86400.0); // complete days
    
     gt.second = remainder % 60;
     remainder /= 60;
@@ -1461,18 +1490,8 @@
     if (days >= -4) gt.weekday = (days + 4) % 7;
     else gt.weekday = 6 - (((-5) - days ) % 7);
 
-#ifdef USE_MATHEMATICAL_ALGORITHM
-    // approximate way:
-    gt.year = getYearApproximate(days);
-#elif defined(USE_APPROXIMATE_ALGORITHM) // approximate algorithm
-    /// swfdec way:
-    gt.year = getYearMathematical(static_cast<double>(days));
-    days -= 365 * (gt.year - 1970) + COUNT_LEAP_YEARS(gt.year - 1900);
-    gt.year -= 1900;
-#else
     // default, brute force:
     gt.year = getYearBruteForce(days);
-#endif
             
     gt.month = 0;
     for (int i = 0; i < 12; ++i)

=== modified file 'libcore/asobj/Date.h'
--- a/libcore/asobj/Date.h      2008-04-20 16:53:57 +0000
+++ b/libcore/asobj/Date.h      2008-10-04 08:15:56 +0000
@@ -15,37 +15,19 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-#ifndef __DATE_H__
-#define __DATE_H__
+#ifndef GNASH_ASOBJ_DATE_H
+#define GNASH_ASOBJ_DATE_H
 
 #include "as_object.h" // for inheritance
 #include "fn_call.h" // for inheritance
 
 namespace gnash {
 
-class Date : public as_object
-{
-public:
-    void setTimeValue(const double& value) { _value = value; }
-    double getTimeValue() const { return _value; }
-
-    Date();
-    Date(double value);
-    
-    as_value toString() const;
-    
-    bool isDateObject() { return true; }
-    
-private:
-    double _value;
-};
-
 void registerDateNative(as_object& global);
 
 void date_class_init(as_object& global);
 
 } // end of gnash namespace
 
-// __DATE_H__
 #endif
 

=== modified file 'testsuite/actionscript.all/Date.as'
--- a/testsuite/actionscript.all/Date.as        2008-04-10 15:55:10 +0000
+++ b/testsuite/actionscript.all/Date.as        2008-10-04 10:29:04 +0000
@@ -339,6 +339,7 @@
 // The commercial player for these first three cases gives
 // -6.77681005679712e+19  Tue Jan -719527 00:00:00 GMT+0000
 // but that doesn't seem worth emulating...
+note("The pp is known to fail the next three tests");
     delete d; var d = new Date(notanumber,0);
        check_equals(d.valueOf().toString(), "NaN");
     delete d; var d = new Date(plusinfinity,0);
@@ -546,6 +547,9 @@
        check_equals(wierddate.getFullYear(), -100000);    
 
     h = new Date(3.0935415006117e+23);
+    check_equals(h.valueOf().toString(), "3.0935415006117e+23");
+    check_equals(h.getMilliseconds(), 584);
+    check_equals(h.getSeconds(), 0);
        check_equals(h.getUTCMilliseconds(), 584);
        check_equals(h.getUTCSeconds(), 0);
        check_equals(h.getUTCMinutes(), 4);
@@ -666,7 +670,7 @@
 #endif
 
 #if OUTPUT_VERSION == 5
-totals(282);
+totals(285);
 #else
-totals (324);
+totals (327);
 #endif


reply via email to

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