Skip to content

Commit d67faf1

Browse files
committed
Normalize subseconds using wideint_t instead of time_t
1 parent a61aa60 commit d67faf1

1 file changed

Lines changed: 25 additions & 21 deletions

File tree

time.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ divmodv(VALUE n, VALUE d, VALUE *q, VALUE *r)
249249
# define FIXWV2WINT(w) FIX2LONG(WIDEVAL_GET(w))
250250
#endif
251251

252+
#define SIZEOF_WIDEINT SIZEOF_INT64_T
252253
#define POSFIXWVABLE(wi) ((wi) < FIXWV_MAX+1)
253254
#define NEGFIXWVABLE(wi) ((wi) >= FIXWV_MIN)
254255
#define FIXWV_P(w) FIXWINT_P(WIDEVAL_GET(w))
@@ -1968,11 +1969,11 @@ time_modify(VALUE time)
19681969
}
19691970

19701971
static wideval_t
1971-
timenano2timew(time_t sec, long nsec)
1972+
timenano2timew(wideint_t sec, long nsec)
19721973
{
19731974
wideval_t timew;
19741975

1975-
timew = rb_time_magnify(TIMET2WV(sec));
1976+
timew = rb_time_magnify(WINT2WV(sec));
19761977
if (nsec)
19771978
timew = wadd(timew, wmulquoll(WINT2WV(nsec), TIME_SCALE, 1000000000));
19781979
return timew;
@@ -2747,46 +2748,35 @@ time_init_parse(rb_execution_context_t *ec, VALUE time, VALUE str, VALUE zone, V
27472748
}
27482749

27492750
static void
2750-
subsec_normalize(time_t *secp, long *subsecp, const long maxsubsec)
2751+
subsec_normalize(wideint_t *secp, long *subsecp, const long maxsubsec)
27512752
{
2752-
time_t sec = *secp;
2753+
wideint_t sec = *secp;
27532754
long subsec = *subsecp;
27542755
long sec2;
27552756

27562757
if (UNLIKELY(subsec >= maxsubsec)) { /* subsec positive overflow */
27572758
sec2 = subsec / maxsubsec;
2758-
if (TIMET_MAX - sec2 < sec) {
2759+
if (WIDEINT_MAX - sec2 < sec) {
27592760
rb_raise(rb_eRangeError, "out of Time range");
27602761
}
27612762
subsec -= sec2 * maxsubsec;
27622763
sec += sec2;
27632764
}
27642765
else if (UNLIKELY(subsec < 0)) { /* subsec negative overflow */
27652766
sec2 = NDIV(subsec, maxsubsec); /* negative div */
2766-
if (sec < TIMET_MIN - sec2) {
2767+
if (sec < WIDEINT_MIN - sec2) {
27672768
rb_raise(rb_eRangeError, "out of Time range");
27682769
}
27692770
subsec -= sec2 * maxsubsec;
27702771
sec += sec2;
27712772
}
2772-
#ifndef NEGATIVE_TIME_T
2773-
if (sec < 0)
2774-
rb_raise(rb_eArgError, "time must be positive");
2775-
#endif
27762773
*secp = sec;
27772774
*subsecp = subsec;
27782775
}
27792776

27802777
#define time_usec_normalize(secp, usecp) subsec_normalize(secp, usecp, 1000000)
27812778
#define time_nsec_normalize(secp, nsecp) subsec_normalize(secp, nsecp, 1000000000)
27822779

2783-
static wideval_t
2784-
nsec2timew(time_t sec, long nsec)
2785-
{
2786-
time_nsec_normalize(&sec, &nsec);
2787-
return timenano2timew(sec, nsec);
2788-
}
2789-
27902780
static VALUE
27912781
time_new_timew(VALUE klass, wideval_t timew)
27922782
{
@@ -2800,25 +2790,39 @@ time_new_timew(VALUE klass, wideval_t timew)
28002790
return time;
28012791
}
28022792

2793+
static wideint_t
2794+
TIMETtoWIDEINT(time_t t)
2795+
{
2796+
#if SIZEOF_TIME_T * CHAR_BIT - (SIGNEDNESS_OF_TIME_T < 0) > \
2797+
SIZEOF_WIDEINT * CHAR_BIT - 1
2798+
/* compare in bit size without sign bit */
2799+
if (t > WIDEINT_MAX) rb_raise(rb_eArgError, "out of Time range");
2800+
#endif
2801+
return (wideint_t)t;
2802+
}
2803+
28032804
VALUE
28042805
rb_time_new(time_t sec, long usec)
28052806
{
2806-
time_usec_normalize(&sec, &usec);
2807-
return time_new_timew(rb_cTime, timenano2timew(sec, usec * 1000));
2807+
wideint_t isec = TIMETtoWIDEINT(sec);
2808+
time_usec_normalize(&isec, &usec);
2809+
return time_new_timew(rb_cTime, timenano2timew(isec, usec * 1000));
28082810
}
28092811

28102812
/* returns localtime time object */
28112813
VALUE
28122814
rb_time_nano_new(time_t sec, long nsec)
28132815
{
2814-
return time_new_timew(rb_cTime, nsec2timew(sec, nsec));
2816+
wideint_t isec = TIMETtoWIDEINT(sec);
2817+
time_nsec_normalize(&isec, &nsec);
2818+
return time_new_timew(rb_cTime, timenano2timew(isec, nsec));
28152819
}
28162820

28172821
VALUE
28182822
rb_time_timespec_new(const struct timespec *ts, int offset)
28192823
{
28202824
struct time_object *tobj;
2821-
VALUE time = time_new_timew(rb_cTime, nsec2timew(ts->tv_sec, ts->tv_nsec));
2825+
VALUE time = rb_time_nano_new(ts->tv_sec, ts->tv_nsec);
28222826

28232827
if (-86400 < offset && offset < 86400) { /* fixoff */
28242828
GetTimeval(time, tobj);

0 commit comments

Comments
 (0)