diff --git a/ChangeLog b/ChangeLog index 10685567cd..5c4a47422f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Wed Jul 1 21:09:25 2009 Tanaka Akira + + * include/ruby/intern.h (rb_time_num_new): declared. + + * time.c (nsec2timev): extracted from time_new_internal. + (time_new_internal): change argument to VALUE. + (rb_time_new): follow the argument change. + (rb_time_nano_new): ditto. + (rb_time_num_new): new function. + + * ext/socket/ancdata.c (ancillary_timestamp): use rb_time_num_new to + represent struct bintime preciously. + Wed Jul 1 08:46:11 2009 Nobuyoshi Nakada * marshal.c (w_encoding): encodings need extra depth. diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c index d30ddf6e7c..78dcba70c3 100644 --- a/ext/socket/ancdata.c +++ b/ext/socket/ancdata.c @@ -327,14 +327,20 @@ ancillary_timestamp(VALUE self) } # endif +#define add(x,y) (rb_funcall((x), '+', 1, (y))) +#define mul(x,y) (rb_funcall((x), '*', 1, (y))) +#define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y))) + # ifdef SCM_BINTIME if (level == SOL_SOCKET && type == SCM_BINTIME && RSTRING_LEN(data) == sizeof(struct bintime)) { struct bintime bt; - struct timespec ts; + VALUE d, timev; memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt)); - bintime2timespec(&bt, &ts); - result = rb_time_nano_new(ts.tv_sec, ts.tv_nsec); + d = ULL2NUM(0x100000000UL); + d = mul(d,d); + timev = add(TIMET2NUM(bt.sec), quo(ULL2NUM(bt.frac), d)); + result = rb_time_num_new(timev, Qnil); } # endif diff --git a/include/ruby/intern.h b/include/ruby/intern.h index f153658d50..efa7bfbb1b 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -745,6 +745,7 @@ VALUE rb_barrier_destroy(VALUE self); /* time.c */ VALUE rb_time_new(time_t, long); VALUE rb_time_nano_new(time_t, long); +VALUE rb_time_num_new(VALUE, VALUE); /* variable.c */ VALUE rb_mod_name(VALUE); VALUE rb_class_path(VALUE); diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb index ddfd61b9ed..aaaa9c43c3 100644 --- a/test/socket/test_socket.rb +++ b/test/socket/test_socket.rb @@ -383,6 +383,7 @@ class TestSocket < Test::Unit::TestCase assert_match(pat, stamp.inspect) t = stamp.timestamp assert_match(pat, t.strftime("%Y-%m-%d")) + assert_equal(stamp.data[-8,8].unpack("Q")[0], t.subsec * 2**64) end end if defined?(Socket) diff --git a/time.c b/time.c index d856fc6f44..0a9ed630b5 100644 --- a/time.c +++ b/time.c @@ -51,6 +51,7 @@ static VALUE time_utc_offset _((VALUE)); static long obj2long(VALUE obj); static VALUE obj2vint(VALUE obj); static int month_arg(VALUE arg); +static void validate_utc_offset(VALUE utc_offset); static void validate_vtm(struct vtm *vtm); static VALUE time_gmtime(VALUE); @@ -1451,18 +1452,24 @@ time_overflow_p(time_t *secp, long *nsecp) *nsecp = nsec; } +static VALUE nsec2timev(time_t sec, long nsec) +{ + struct timespec ts; + time_overflow_p(&sec, &nsec); + ts.tv_sec = sec; + ts.tv_nsec = nsec; + return timespec2timev(&ts); +} + static VALUE -time_new_internal(VALUE klass, time_t sec, long nsec) +time_new_internal(VALUE klass, VALUE timev) { VALUE time = time_s_alloc(klass); struct time_object *tobj; struct timespec ts; GetTimeval(time, tobj); - time_overflow_p(&sec, &nsec); - ts.tv_sec = sec; - ts.tv_nsec = nsec; - tobj->timev = timespec2timev(&ts); + tobj->timev = num_exact(timev); return time; } @@ -1470,13 +1477,28 @@ time_new_internal(VALUE klass, time_t sec, long nsec) VALUE rb_time_new(time_t sec, long usec) { - return time_new_internal(rb_cTime, sec, usec * 1000); + return time_new_internal(rb_cTime, nsec2timev(sec, usec * 1000)); } VALUE rb_time_nano_new(time_t sec, long nsec) { - return time_new_internal(rb_cTime, sec, nsec); + return time_new_internal(rb_cTime, nsec2timev(sec, nsec)); +} + +VALUE +rb_time_num_new(VALUE timev, VALUE off) +{ + VALUE time = time_new_internal(rb_cTime, timev); + + if (!NIL_P(off)) { + off = utc_offset_arg(off); + validate_utc_offset(off); + time_set_utc_offset(time, off); + return time; + } + + return time; } static VALUE