Commit 277c8406 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

Cleanup pytime.c (#3955)

* Move _PyTime_overflow() at the top
* Move assertion on numerator into _PyTime_ObjectToDenominator()
* PEP 7: add { ... } to if blocks
parent 703ff381
...@@ -35,6 +35,13 @@ error_time_t_overflow(void) ...@@ -35,6 +35,13 @@ error_time_t_overflow(void)
"timestamp out of range for platform time_t"); "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 time_t
_PyLong_AsTime_t(PyObject *obj) _PyLong_AsTime_t(PyObject *obj)
{ {
...@@ -47,8 +54,9 @@ _PyLong_AsTime_t(PyObject *obj) ...@@ -47,8 +54,9 @@ _PyLong_AsTime_t(PyObject *obj)
val = PyLong_AsLong(obj); val = PyLong_AsLong(obj);
#endif #endif
if (val == -1 && PyErr_Occurred()) { if (val == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError)) if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
error_time_t_overflow(); error_time_t_overflow();
}
return -1; return -1;
} }
return (time_t)val; return (time_t)val;
...@@ -71,9 +79,10 @@ static double ...@@ -71,9 +79,10 @@ static double
_PyTime_RoundHalfEven(double x) _PyTime_RoundHalfEven(double x)
{ {
double rounded = round(x); double rounded = round(x);
if (fabs(x-rounded) == 0.5) if (fabs(x-rounded) == 0.5) {
/* halfway case: round to even */ /* halfway case: round to even */
rounded = 2.0*round(x/2.0); rounded = 2.0*round(x/2.0);
}
return rounded; return rounded;
} }
...@@ -84,19 +93,23 @@ _PyTime_Round(double x, _PyTime_round_t round) ...@@ -84,19 +93,23 @@ _PyTime_Round(double x, _PyTime_round_t round)
volatile double d; volatile double d;
d = x; d = x;
if (round == _PyTime_ROUND_HALF_EVEN) if (round == _PyTime_ROUND_HALF_EVEN) {
d = _PyTime_RoundHalfEven(d); d = _PyTime_RoundHalfEven(d);
else if (round == _PyTime_ROUND_CEILING) }
else if (round == _PyTime_ROUND_CEILING) {
d = ceil(d); d = ceil(d);
else }
else {
d = floor(d); d = floor(d);
}
return d; return d;
} }
static int static int
_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, _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; double intpart;
/* volatile avoids optimization changing how numbers are rounded */ /* volatile avoids optimization changing how numbers are rounded */
volatile double floatpart; volatile double floatpart;
...@@ -121,15 +134,15 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, ...@@ -121,15 +134,15 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
} }
*sec = (time_t)intpart; *sec = (time_t)intpart;
*numerator = (long)floatpart; *numerator = (long)floatpart;
assert(0 <= *numerator && *numerator < idenominator);
return 0; return 0;
} }
static int static int
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, _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)) { if (PyFloat_Check(obj)) {
double d = PyFloat_AsDouble(obj); double d = PyFloat_AsDouble(obj);
...@@ -144,8 +157,9 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, ...@@ -144,8 +157,9 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
else { else {
*sec = _PyLong_AsTime_t(obj); *sec = _PyLong_AsTime_t(obj);
*numerator = 0; *numerator = 0;
if (*sec == (time_t)-1 && PyErr_Occurred()) if (*sec == (time_t)-1 && PyErr_Occurred()) {
return -1; return -1;
}
return 0; return 0;
} }
} }
...@@ -176,8 +190,9 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) ...@@ -176,8 +190,9 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
} }
else { else {
*sec = _PyLong_AsTime_t(obj); *sec = _PyLong_AsTime_t(obj);
if (*sec == (time_t)-1 && PyErr_Occurred()) if (*sec == (time_t)-1 && PyErr_Occurred()) {
return -1; return -1;
}
return 0; return 0;
} }
} }
...@@ -186,43 +201,27 @@ int ...@@ -186,43 +201,27 @@ int
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec, _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
_PyTime_round_t round) _PyTime_round_t round)
{ {
int res; return _PyTime_ObjectToDenominator(obj, sec, nsec, SEC_TO_NS, round);
res = _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
if (res == 0) {
assert(0 <= *nsec && *nsec < SEC_TO_NS);
}
return res;
} }
int int
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
_PyTime_round_t round) _PyTime_round_t round)
{ {
int res; return _PyTime_ObjectToDenominator(obj, sec, usec, SEC_TO_US, round);
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");
} }
_PyTime_t _PyTime_t
_PyTime_FromSeconds(int seconds) _PyTime_FromSeconds(int seconds)
{ {
_PyTime_t t; _PyTime_t t;
t = (_PyTime_t)seconds;
/* ensure that integer overflow cannot happen, int type should have 32 /* 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, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
bits). */ bits). */
Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS); Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / 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) assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
|| (t < 0 && t >= _PyTime_MIN / SEC_TO_NS)); || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
t *= SEC_TO_NS; t *= SEC_TO_NS;
...@@ -249,8 +248,9 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise) ...@@ -249,8 +248,9 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
t = (_PyTime_t)ts->tv_sec; t = (_PyTime_t)ts->tv_sec;
if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
if (raise) if (raise) {
_PyTime_overflow(); _PyTime_overflow();
}
res = -1; res = -1;
} }
t = t * SEC_TO_NS; t = t * SEC_TO_NS;
...@@ -271,8 +271,9 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise) ...@@ -271,8 +271,9 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
t = (_PyTime_t)tv->tv_sec; t = (_PyTime_t)tv->tv_sec;
if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
if (raise) if (raise) {
_PyTime_overflow(); _PyTime_overflow();
}
res = -1; res = -1;
} }
t = t * SEC_TO_NS; t = t * SEC_TO_NS;
...@@ -323,8 +324,9 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, ...@@ -323,8 +324,9 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
sec = PyLong_AsLongLong(obj); sec = PyLong_AsLongLong(obj);
if (sec == -1 && PyErr_Occurred()) { if (sec == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError)) if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
_PyTime_overflow(); _PyTime_overflow();
}
return -1; return -1;
} }
...@@ -387,24 +389,30 @@ _PyTime_Divide(const _PyTime_t t, const _PyTime_t k, ...@@ -387,24 +389,30 @@ _PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
r = t % k; r = t % k;
abs_r = Py_ABS(r); abs_r = Py_ABS(r);
if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) { if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {
if (t >= 0) if (t >= 0) {
x++; x++;
else }
else {
x--; x--;
}
} }
return x; return x;
} }
else if (round == _PyTime_ROUND_CEILING) { else if (round == _PyTime_ROUND_CEILING) {
if (t >= 0) if (t >= 0) {
return (t + k - 1) / k; return (t + k - 1) / k;
else }
else {
return t / k; return t / k;
}
} }
else { else {
if (t >= 0) if (t >= 0) {
return t / k; return t / k;
else }
else {
return (t - (k - 1)) / k; return (t - (k - 1)) / k;
}
} }
} }
...@@ -434,17 +442,21 @@ _PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us, ...@@ -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); usec = (int)_PyTime_Divide(ns, US_TO_NS, round);
if (usec < 0) { if (usec < 0) {
usec += SEC_TO_US; usec += SEC_TO_US;
if (secs != _PyTime_MIN) if (secs != _PyTime_MIN) {
secs -= 1; secs -= 1;
else }
else {
res = -1; res = -1;
}
} }
else if (usec >= SEC_TO_US) { else if (usec >= SEC_TO_US) {
usec -= SEC_TO_US; usec -= SEC_TO_US;
if (secs != _PyTime_MAX) if (secs != _PyTime_MAX) {
secs += 1; secs += 1;
else }
else {
res = -1; res = -1;
}
} }
assert(0 <= usec && usec < SEC_TO_US); assert(0 <= usec && usec < SEC_TO_US);
...@@ -473,8 +485,9 @@ _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv, ...@@ -473,8 +485,9 @@ _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv,
secs2 = (_PyTime_t)tv->tv_sec; secs2 = (_PyTime_t)tv->tv_sec;
if (res < 0 || secs2 != secs) { if (res < 0 || secs2 != secs) {
if (raise) if (raise) {
error_time_t_overflow(); error_time_t_overflow();
}
return -1; return -1;
} }
return 0; return 0;
...@@ -580,22 +593,26 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) ...@@ -580,22 +593,26 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
#ifdef HAVE_CLOCK_GETTIME #ifdef HAVE_CLOCK_GETTIME
err = clock_gettime(CLOCK_REALTIME, &ts); err = clock_gettime(CLOCK_REALTIME, &ts);
if (err) { if (err) {
if (raise) if (raise) {
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
}
return -1; return -1;
} }
if (_PyTime_FromTimespec(tp, &ts, raise) < 0) if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
return -1; return -1;
}
if (info) { if (info) {
struct timespec res; struct timespec res;
info->implementation = "clock_gettime(CLOCK_REALTIME)"; info->implementation = "clock_gettime(CLOCK_REALTIME)";
info->monotonic = 0; info->monotonic = 0;
info->adjustable = 1; 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; info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
else }
else {
info->resolution = 1e-9; info->resolution = 1e-9;
}
} }
#else /* HAVE_CLOCK_GETTIME */ #else /* HAVE_CLOCK_GETTIME */
...@@ -606,12 +623,14 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) ...@@ -606,12 +623,14 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
err = gettimeofday(&tv, (struct timezone *)NULL); err = gettimeofday(&tv, (struct timezone *)NULL);
#endif #endif
if (err) { if (err) {
if (raise) if (raise) {
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
}
return -1; return -1;
} }
if (_PyTime_FromTimeval(tp, &tv, raise) < 0) if (_PyTime_FromTimeval(tp, &tv, raise) < 0) {
return -1; return -1;
}
if (info) { if (info) {
info->implementation = "gettimeofday()"; info->implementation = "gettimeofday()";
...@@ -755,8 +774,9 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise) ...@@ -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; 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; return -1;
}
#endif #endif
return 0; return 0;
} }
...@@ -872,8 +892,9 @@ _PyTime_localtime(time_t t, struct tm *tm) ...@@ -872,8 +892,9 @@ _PyTime_localtime(time_t t, struct tm *tm)
#else /* !MS_WINDOWS */ #else /* !MS_WINDOWS */
if (localtime_r(&t, tm) == NULL) { if (localtime_r(&t, tm) == NULL) {
#ifdef EINVAL #ifdef EINVAL
if (errno == 0) if (errno == 0) {
errno = EINVAL; errno = EINVAL;
}
#endif #endif
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
return -1; return -1;
...@@ -898,8 +919,9 @@ _PyTime_gmtime(time_t t, struct tm *tm) ...@@ -898,8 +919,9 @@ _PyTime_gmtime(time_t t, struct tm *tm)
#else /* !MS_WINDOWS */ #else /* !MS_WINDOWS */
if (gmtime_r(&t, tm) == NULL) { if (gmtime_r(&t, tm) == NULL) {
#ifdef EINVAL #ifdef EINVAL
if (errno == 0) if (errno == 0) {
errno = EINVAL; errno = EINVAL;
}
#endif #endif
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment