Refactored sub-seconds normalizations

* separated argument to `timespec2timew` from `timespec` to seconds and
  nano-seconds.

* unified nano-seconds and micro-seconds normalizations.
This commit is contained in:
Nobuyoshi Nakada 2021-04-01 12:00:10 +09:00 коммит произвёл GitHub
Родитель 2a02b61fae
Коммит a5567350f7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 21 добавлений и 40 удалений

61
time.c
Просмотреть файл

@ -1844,13 +1844,13 @@ time_modify(VALUE time)
}
static wideval_t
timespec2timew(struct timespec *ts)
timenano2timew(time_t sec, long nsec)
{
wideval_t timew;
timew = rb_time_magnify(TIMET2WV(ts->tv_sec));
if (ts->tv_nsec)
timew = wadd(timew, wmulquoll(WINT2WV(ts->tv_nsec), TIME_SCALE, 1000000000));
timew = rb_time_magnify(TIMET2WV(sec));
if (nsec)
timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000));
return timew;
}
@ -1918,7 +1918,7 @@ time_init_now(rb_execution_context_t *ec, VALUE time, VALUE zone)
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
rb_timespec_now(&ts);
tobj->timew = timespec2timew(&ts);
tobj->timew = timenano2timew(ts.tv_sec, ts.tv_nsec);
if (!NIL_P(zone)) {
time_zonelocal(time, zone);
@ -2409,26 +2409,26 @@ time_init_args(rb_execution_context_t *ec, VALUE time, VALUE year, VALUE mon, VA
}
static void
time_overflow_p(time_t *secp, long *nsecp)
subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec)
{
time_t sec = *secp;
long nsec = *nsecp;
long subsec = *subsecp;
long sec2;
if (nsec >= 1000000000) { /* nsec positive overflow */
sec2 = nsec / 1000000000;
if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */
sec2 = subsec / maxsubsec;
if (TIMET_MAX - sec2 < sec) {
rb_raise(rb_eRangeError, "out of Time range");
}
nsec -= sec2 * 1000000000;
subsec -= sec2 * maxsubsec;
sec += sec2;
}
else if (nsec < 0) { /* nsec negative overflow */
sec2 = NDIV(nsec,1000000000); /* negative div */
else if (UNLIKELY(subsec < 0)) { /* subsec negative overflow */
sec2 = NDIV(subsec, maxsubsec); /* negative div */
if (sec < TIMET_MIN - sec2) {
rb_raise(rb_eRangeError, "out of Time range");
}
nsec -= sec2 * 1000000000;
subsec -= sec2 * maxsubsec;
sec += sec2;
}
#ifndef NEGATIVE_TIME_T
@ -2436,17 +2436,17 @@ time_overflow_p(time_t *secp, long *nsecp)
rb_raise(rb_eArgError, "time must be positive");
#endif
*secp = sec;
*nsecp = nsec;
*subsecp = subsec;
}
#define time_usec_normalize(secp, usecp) subsec_normalize(secp, usecp, 1000000)
#define time_nsec_normalize(secp, nsecp) subsec_normalize(secp, nsecp, 1000000000)
static wideval_t
nsec2timew(time_t sec, long nsec)
{
struct timespec ts;
time_overflow_p(&sec, &nsec);
ts.tv_sec = sec;
ts.tv_nsec = nsec;
return timespec2timew(&ts);
time_nsec_normalize(&sec, &nsec);
return timenano2timew(sec, nsec);
}
static VALUE
@ -2465,27 +2465,8 @@ time_new_timew(VALUE klass, wideval_t timew)
VALUE
rb_time_new(time_t sec, long usec)
{
wideval_t timew;
if (usec >= 1000000) {
long sec2 = usec / 1000000;
if (sec > TIMET_MAX - sec2) {
rb_raise(rb_eRangeError, "out of Time range");
}
usec -= sec2 * 1000000;
sec += sec2;
}
else if (usec < 0) {
long sec2 = NDIV(usec,1000000); /* negative div */
if (sec < TIMET_MIN - sec2) {
rb_raise(rb_eRangeError, "out of Time range");
}
usec -= sec2 * 1000000;
sec += sec2;
}
timew = nsec2timew(sec, usec * 1000);
return time_new_timew(rb_cTime, timew);
time_usec_normalize(&sec, &usec);
return time_new_timew(rb_cTime, timenano2timew(sec, usec * 1000));
}
/* returns localtime time object */