mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Cleanup pytime.c (#3955)
* Move _PyTime_overflow() at the top * Move assertion on numerator into _PyTime_ObjectToDenominator() * PEP 7: add { ... } to if blocks
This commit is contained in:
parent
703ff381ff
commit
277c84067f
1 changed files with 76 additions and 54 deletions
130
Python/pytime.c
130
Python/pytime.c
|
@ -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)
|
||||||
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
|
||||||
_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)
|
||||||
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,
|
||||||
}
|
}
|
||||||
*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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
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
|
||||||
_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)
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
#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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
#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)
|
||||||
#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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue