Chromium Code Reviews| Index: base/third_party/nspr/prtime.cc |
| diff --git a/base/third_party/nspr/prtime.cc b/base/third_party/nspr/prtime.cc |
| index 177cc90243feb0040e5d0a0353b67f3df139e0c2..8bbff32272bccacbfb05c620b339bba457ad02c7 100644 |
| --- a/base/third_party/nspr/prtime.cc |
| +++ b/base/third_party/nspr/prtime.cc |
| @@ -71,19 +71,38 @@ |
| #include "base/third_party/nspr/prtime.h" |
| #include "build/build_config.h" |
| -#if defined(OS_WIN) |
| -#include <windows.h> |
| -#elif defined(OS_MACOSX) |
| -#include <CoreFoundation/CoreFoundation.h> |
| -#elif defined(OS_ANDROID) |
| -#include <ctype.h> |
| -#include "base/os_compat_android.h" // For timegm() |
| -#elif defined(OS_NACL) |
| -#include "base/os_compat_nacl.h" // For timegm() |
| -#endif |
| #include <errno.h> /* for EINVAL */ |
| #include <time.h> |
| +/* |
| + * Long-long (64-bit signed integer type) support functions |
|
wtc
2016/02/12 16:15:32
Nit: functions => macros
pkl (ping after 24h if needed)
2016/02/15 18:07:16
Done.
|
| + * used by PR_ImplodeTime(). |
| + * See http://lxr.mozilla.org/nspr/source/pr/include/prlong.h |
| + */ |
| +#define LL_I2L(l, i) ((l) = (PRInt64)(i)) |
| +#define LL_MUL(r, a, b) ((r) = (a) * (b)) |
| +#define LL_ADD(r, a, b) ((r) = (a) + (b)) |
| +#define LL_SUB(r, a, b) ((r) = (a) - (b)) |
|
wtc
2016/02/12 16:15:32
Optional: Based on the comment at lines 58-63, the
pkl (ping after 24h if needed)
2016/02/15 18:07:15
I would rather defer this move until a later time.
|
| + |
| +/* |
| + * The COUNT_LEAPS macro counts the number of leap years passed by |
| + * till the start of the given year Y. At the start of the year 4 |
| + * A.D. the number of leap years passed by is 0, while at the start of |
| + * the year 5 A.D. this count is 1. The number of years divisible by |
| + * 100 but not divisible by 400 (the non-leap years) is deducted from |
| + * the count to get the correct number of leap years. |
| + * |
| + * The COUNT_DAYS macro counts the number of days since 01/01/01 till the |
| + * start of the given year Y. The number of days at the start of the year |
| + * 1 is 0 while the number of days at the start of the year 2 is 365 |
| + * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 |
| + * midnight 00:00:00. |
| + */ |
| + |
| +#define COUNT_LEAPS(Y) (((Y)-1) / 4 - ((Y)-1) / 100 + ((Y)-1) / 400) |
| +#define COUNT_DAYS(Y) (((Y)-1) * 365 + COUNT_LEAPS(Y)) |
| +#define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) |
| + |
| /* Implements the Unix localtime_r() function for windows */ |
| #if defined(OS_WIN) |
| static void localtime_r(const time_t* secs, struct tm* time) { |
| @@ -99,125 +118,51 @@ static void localtime_r(const time_t* secs, struct tm* time) { |
| * Cf. time_t mktime(struct tm *tp) |
| * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. |
| * |
| + * Upstream implementation from |
| + * http://lxr.mozilla.org/nspr/source/pr/src/misc/prtime.c#221 |
|
wtc
2016/02/12 16:15:32
This note can be omitted or should be moved to the
pkl (ping after 24h if needed)
2016/02/15 18:07:15
I moved it to the beginning of the file (around li
|
| + * |
| *------------------------------------------------------------------------ |
| */ |
| PRTime |
| PR_ImplodeTime(const PRExplodedTime *exploded) |
| { |
| - // This is important, we want to make sure multiplications are |
| - // done with the correct precision. |
| - static const PRTime kSecondsToMicroseconds = static_cast<PRTime>(1000000); |
| -#if defined(OS_WIN) |
| - // Create the system struct representing our exploded time. |
| - SYSTEMTIME st = {}; |
| - FILETIME ft = {}; |
| - ULARGE_INTEGER uli = {}; |
| - |
| - st.wYear = exploded->tm_year; |
| - st.wMonth = static_cast<WORD>(exploded->tm_month + 1); |
| - st.wDayOfWeek = exploded->tm_wday; |
| - st.wDay = static_cast<WORD>(exploded->tm_mday); |
| - st.wHour = static_cast<WORD>(exploded->tm_hour); |
| - st.wMinute = static_cast<WORD>(exploded->tm_min); |
| - st.wSecond = static_cast<WORD>(exploded->tm_sec); |
| - st.wMilliseconds = static_cast<WORD>(exploded->tm_usec/1000); |
| - // Convert to FILETIME. |
| - if (!SystemTimeToFileTime(&st, &ft)) { |
| - NOTREACHED() << "Unable to convert time"; |
| - return 0; |
| - } |
| - // Apply offsets. |
| - uli.LowPart = ft.dwLowDateTime; |
| - uli.HighPart = ft.dwHighDateTime; |
| - // Convert from Windows epoch to NSPR epoch, and 100-nanoseconds units |
| - // to microsecond units. |
| - PRTime result = |
| - static_cast<PRTime>((uli.QuadPart / 10) - 11644473600000000i64); |
| - // Adjust for time zone and dst. Convert from seconds to microseconds. |
| - result -= (exploded->tm_params.tp_gmt_offset + |
| - exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds; |
| - // Add microseconds that cannot be represented in |st|. |
| - result += exploded->tm_usec % 1000; |
| - return result; |
| -#elif defined(OS_MACOSX) |
| - // Create the system struct representing our exploded time. |
| - CFGregorianDate gregorian_date; |
| - gregorian_date.year = exploded->tm_year; |
| - gregorian_date.month = exploded->tm_month + 1; |
| - gregorian_date.day = exploded->tm_mday; |
| - gregorian_date.hour = exploded->tm_hour; |
| - gregorian_date.minute = exploded->tm_min; |
| - gregorian_date.second = exploded->tm_sec; |
| - |
| - // Compute |absolute_time| in seconds, correct for gmt and dst |
| - // (note the combined offset will be negative when we need to add it), then |
| - // convert to microseconds which is what PRTime expects. |
| - CFAbsoluteTime absolute_time = |
| - CFGregorianDateGetAbsoluteTime(gregorian_date, NULL); |
| - PRTime result = static_cast<PRTime>(absolute_time); |
| - result -= exploded->tm_params.tp_gmt_offset + |
| - exploded->tm_params.tp_dst_offset; |
| - result += kCFAbsoluteTimeIntervalSince1970; // PRTime epoch is 1970 |
| - result *= kSecondsToMicroseconds; |
| - result += exploded->tm_usec; |
| - return result; |
| -#elif defined(OS_POSIX) |
| - struct tm exp_tm = {0}; |
| - exp_tm.tm_sec = exploded->tm_sec; |
| - exp_tm.tm_min = exploded->tm_min; |
| - exp_tm.tm_hour = exploded->tm_hour; |
| - exp_tm.tm_mday = exploded->tm_mday; |
| - exp_tm.tm_mon = exploded->tm_month; |
| - exp_tm.tm_year = exploded->tm_year - 1900; |
| - |
| - time_t absolute_time = timegm(&exp_tm); |
| - |
| - // If timegm returned -1. Since we don't pass it a time zone, the only |
| - // valid case of returning -1 is 1 second before Epoch (Dec 31, 1969). |
| - if (absolute_time == -1 && |
| - !(exploded->tm_year == 1969 && exploded->tm_month == 11 && |
| - exploded->tm_mday == 31 && exploded->tm_hour == 23 && |
| - exploded->tm_min == 59 && exploded->tm_sec == 59)) { |
| - // If we get here, time_t must be 32 bits. |
| - // Date was possibly too far in the future and would overflow. Return |
| - // the most future date possible (year 2038). |
| - if (exploded->tm_year >= 1970) |
| - return INT_MAX * kSecondsToMicroseconds; |
| - // Date was possibly too far in the past and would underflow. Return |
| - // the most past date possible (year 1901). |
| - return INT_MIN * kSecondsToMicroseconds; |
| - } |
| - |
| - PRTime result = static_cast<PRTime>(absolute_time); |
| - result -= exploded->tm_params.tp_gmt_offset + |
| - exploded->tm_params.tp_dst_offset; |
| - result *= kSecondsToMicroseconds; |
| - result += exploded->tm_usec; |
| - return result; |
| -#else |
| -#error No PR_ImplodeTime implemented on your platform. |
| -#endif |
| + PRExplodedTime copy; |
| + PRTime retVal; |
| + PRInt64 secPerDay, usecPerSec; |
| + PRInt64 temp; |
| + PRInt64 numSecs64; |
| + PRInt32 numDays; |
| + PRInt32 numSecs; |
| + |
| + /* Normalize first. Do this on our copy */ |
| + copy = *exploded; |
| + PR_NormalizeTime(©, PR_GMTParameters); |
| + |
| + numDays = DAYS_BETWEEN_YEARS(1970, copy.tm_year); |
| + |
| + numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600 + copy.tm_min * 60 + |
| + copy.tm_sec; |
| + |
| + LL_I2L(temp, numDays); |
| + LL_I2L(secPerDay, 86400); |
| + LL_MUL(temp, temp, secPerDay); |
| + LL_I2L(numSecs64, numSecs); |
| + LL_ADD(numSecs64, numSecs64, temp); |
| + |
| + /* apply the GMT and DST offsets */ |
| + LL_I2L(temp, copy.tm_params.tp_gmt_offset); |
| + LL_SUB(numSecs64, numSecs64, temp); |
| + LL_I2L(temp, copy.tm_params.tp_dst_offset); |
| + LL_SUB(numSecs64, numSecs64, temp); |
| + |
| + LL_I2L(usecPerSec, 1000000L); |
| + LL_MUL(temp, numSecs64, usecPerSec); |
| + LL_I2L(retVal, copy.tm_usec); |
| + LL_ADD(retVal, retVal, temp); |
| + |
| + return retVal; |
| } |
| -/* |
| - * The COUNT_LEAPS macro counts the number of leap years passed by |
| - * till the start of the given year Y. At the start of the year 4 |
| - * A.D. the number of leap years passed by is 0, while at the start of |
| - * the year 5 A.D. this count is 1. The number of years divisible by |
| - * 100 but not divisible by 400 (the non-leap years) is deducted from |
| - * the count to get the correct number of leap years. |
| - * |
| - * The COUNT_DAYS macro counts the number of days since 01/01/01 till the |
| - * start of the given year Y. The number of days at the start of the year |
| - * 1 is 0 while the number of days at the start of the year 2 is 365 |
| - * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 |
| - * midnight 00:00:00. |
| - */ |
| - |
| -#define COUNT_LEAPS(Y) ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 ) |
| -#define COUNT_DAYS(Y) ( ((Y)-1)*365 + COUNT_LEAPS(Y) ) |
| -#define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) |
| - |
| /* |
| * Static variables used by functions in this file |
| */ |