From a5567350f706d6c72b2d4e0cdc95ceff80e87bbf Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 1 Apr 2021 12:00:10 +0900 Subject: Refactored sub-seconds normalizations * separated argument to `timespec2timew` from `timespec` to seconds and nano-seconds. * unified nano-seconds and micro-seconds normalizations. --- time.c | 61 +++++++++++++++++++++---------------------------------------- 1 file changed, 21 insertions(+), 40 deletions(-) (limited to 'time.c') diff --git a/time.c b/time.c index bfcce8ee0f..e24bb5a012 100644 --- a/time.c +++ b/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 */ -- cgit v1.2.3