Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 76 additions & 54 deletions Python/pytime.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ error_time_t_overflow(void)
"timestamp out of range for platform time_t");
}

static void
_PyTime_overflow(void)
{
PyErr_SetString(PyExc_OverflowError,
"timestamp too large to convert to C _PyTime_t");
}

time_t
_PyLong_AsTime_t(PyObject *obj)
{
Expand All @@ -47,8 +54,9 @@ _PyLong_AsTime_t(PyObject *obj)
val = PyLong_AsLong(obj);
#endif
if (val == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError))
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
error_time_t_overflow();
}
return -1;
}
return (time_t)val;
Expand All @@ -71,9 +79,10 @@ static double
_PyTime_RoundHalfEven(double x)
{
double rounded = round(x);
if (fabs(x-rounded) == 0.5)
if (fabs(x-rounded) == 0.5) {
/* halfway case: round to even */
rounded = 2.0*round(x/2.0);
}
return rounded;
}

Expand All @@ -84,19 +93,23 @@ _PyTime_Round(double x, _PyTime_round_t round)
volatile double d;

d = x;
if (round == _PyTime_ROUND_HALF_EVEN)
if (round == _PyTime_ROUND_HALF_EVEN) {
d = _PyTime_RoundHalfEven(d);
else if (round == _PyTime_ROUND_CEILING)
}
else if (round == _PyTime_ROUND_CEILING) {
d = ceil(d);
else
}
else {
d = floor(d);
}
return d;
}

static int
_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
double denominator, _PyTime_round_t round)
long idenominator, _PyTime_round_t round)
{
double denominator = (double)idenominator;
double intpart;
/* volatile avoids optimization changing how numbers are rounded */
volatile double floatpart;
Expand All @@ -121,15 +134,15 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
}
*sec = (time_t)intpart;
*numerator = (long)floatpart;

assert(0 <= *numerator && *numerator < idenominator);
return 0;
}

static int
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
double denominator, _PyTime_round_t round)
long denominator, _PyTime_round_t round)
{
assert(denominator <= (double)LONG_MAX);
assert(denominator >= 1);

if (PyFloat_Check(obj)) {
double d = PyFloat_AsDouble(obj);
Expand All @@ -144,8 +157,9 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
else {
*sec = _PyLong_AsTime_t(obj);
*numerator = 0;
if (*sec == (time_t)-1 && PyErr_Occurred())
if (*sec == (time_t)-1 && PyErr_Occurred()) {
return -1;
}
return 0;
}
}
Expand Down Expand Up @@ -176,8 +190,9 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
}
else {
*sec = _PyLong_AsTime_t(obj);
if (*sec == (time_t)-1 && PyErr_Occurred())
if (*sec == (time_t)-1 && PyErr_Occurred()) {
return -1;
}
return 0;
}
}
Expand All @@ -186,43 +201,27 @@ int
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
_PyTime_round_t round)
{
int res;
res = _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
if (res == 0) {
assert(0 <= *nsec && *nsec < SEC_TO_NS);
}
return res;
return _PyTime_ObjectToDenominator(obj, sec, nsec, SEC_TO_NS, round);
}

int
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
_PyTime_round_t round)
{
int res;
res = _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
if (res == 0) {
assert(0 <= *usec && *usec < SEC_TO_US);
}
return res;
}

static void
_PyTime_overflow(void)
{
PyErr_SetString(PyExc_OverflowError,
"timestamp too large to convert to C _PyTime_t");
return _PyTime_ObjectToDenominator(obj, sec, usec, SEC_TO_US, round);
}

_PyTime_t
_PyTime_FromSeconds(int seconds)
{
_PyTime_t t;
t = (_PyTime_t)seconds;
/* ensure that integer overflow cannot happen, int type should have 32
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
bits). */
Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS);

t = (_PyTime_t)seconds;
assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
|| (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
t *= SEC_TO_NS;
Expand All @@ -249,8 +248,9 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
t = (_PyTime_t)ts->tv_sec;

if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
if (raise)
if (raise) {
_PyTime_overflow();
}
res = -1;
}
t = t * SEC_TO_NS;
Expand All @@ -271,8 +271,9 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
t = (_PyTime_t)tv->tv_sec;

if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
if (raise)
if (raise) {
_PyTime_overflow();
}
res = -1;
}
t = t * SEC_TO_NS;
Expand Down Expand Up @@ -323,8 +324,9 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,

sec = PyLong_AsLongLong(obj);
if (sec == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError))
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
_PyTime_overflow();
}
return -1;
}

Expand Down Expand Up @@ -387,24 +389,30 @@ _PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
r = t % k;
abs_r = Py_ABS(r);
if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {
if (t >= 0)
if (t >= 0) {
x++;
else
}
else {
x--;
}
}
return x;
}
else if (round == _PyTime_ROUND_CEILING) {
if (t >= 0)
if (t >= 0) {
return (t + k - 1) / k;
else
}
else {
return t / k;
}
}
else {
if (t >= 0)
if (t >= 0) {
return t / k;
else
}
else {
return (t - (k - 1)) / k;
}
}
}

Expand Down Expand Up @@ -434,17 +442,21 @@ _PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us,
usec = (int)_PyTime_Divide(ns, US_TO_NS, round);
if (usec < 0) {
usec += SEC_TO_US;
if (secs != _PyTime_MIN)
if (secs != _PyTime_MIN) {
secs -= 1;
else
}
else {
res = -1;
}
}
else if (usec >= SEC_TO_US) {
usec -= SEC_TO_US;
if (secs != _PyTime_MAX)
if (secs != _PyTime_MAX) {
secs += 1;
else
}
else {
res = -1;
}
}
assert(0 <= usec && usec < SEC_TO_US);

Expand Down Expand Up @@ -473,8 +485,9 @@ _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv,

secs2 = (_PyTime_t)tv->tv_sec;
if (res < 0 || secs2 != secs) {
if (raise)
if (raise) {
error_time_t_overflow();
}
return -1;
}
return 0;
Expand Down Expand Up @@ -580,22 +593,26 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
#ifdef HAVE_CLOCK_GETTIME
err = clock_gettime(CLOCK_REALTIME, &ts);
if (err) {
if (raise)
if (raise) {
PyErr_SetFromErrno(PyExc_OSError);
}
return -1;
}
if (_PyTime_FromTimespec(tp, &ts, raise) < 0)
if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
return -1;
}

if (info) {
struct timespec res;
info->implementation = "clock_gettime(CLOCK_REALTIME)";
info->monotonic = 0;
info->adjustable = 1;
if (clock_getres(CLOCK_REALTIME, &res) == 0)
if (clock_getres(CLOCK_REALTIME, &res) == 0) {
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
else
}
else {
info->resolution = 1e-9;
}
}
#else /* HAVE_CLOCK_GETTIME */

Expand All @@ -606,12 +623,14 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
err = gettimeofday(&tv, (struct timezone *)NULL);
#endif
if (err) {
if (raise)
if (raise) {
PyErr_SetFromErrno(PyExc_OSError);
}
return -1;
}
if (_PyTime_FromTimeval(tp, &tv, raise) < 0)
if (_PyTime_FromTimeval(tp, &tv, raise) < 0) {
return -1;
}

if (info) {
info->implementation = "gettimeofday()";
Expand Down Expand Up @@ -755,8 +774,9 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
}
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
}
if (_PyTime_FromTimespec(tp, &ts, raise) < 0)
if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
return -1;
}
#endif
return 0;
}
Expand Down Expand Up @@ -872,8 +892,9 @@ _PyTime_localtime(time_t t, struct tm *tm)
#else /* !MS_WINDOWS */
if (localtime_r(&t, tm) == NULL) {
#ifdef EINVAL
if (errno == 0)
if (errno == 0) {
errno = EINVAL;
}
#endif
PyErr_SetFromErrno(PyExc_OSError);
return -1;
Expand All @@ -898,8 +919,9 @@ _PyTime_gmtime(time_t t, struct tm *tm)
#else /* !MS_WINDOWS */
if (gmtime_r(&t, tm) == NULL) {
#ifdef EINVAL
if (errno == 0)
if (errno == 0) {
errno = EINVAL;
}
#endif
PyErr_SetFromErrno(PyExc_OSError);
return -1;
Expand Down