summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--ext/socket/ancdata.c12
-rw-r--r--include/ruby/intern.h1
-rw-r--r--test/socket/test_socket.rb1
-rw-r--r--time.c36
5 files changed, 53 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 10685567c..5c4a47422 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Wed Jul 1 21:09:25 2009 Tanaka Akira <akr@fsij.org>
+
+ * 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 <nobu@ruby-lang.org>
* marshal.c (w_encoding): encodings need extra depth.
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index d30ddf6e7..78dcba70c 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 f153658d5..efa7bfbb1 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 ddfd61b9e..aaaa9c43c 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 d856fc6f4..0a9ed630b 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