* time.c (time_plus): must detect result overflow.

* time.c (time_minus): ditto.

* time.c (time_new_internal): round usec overflow and underflow
  here.

* time.c (time_plus): move operand overflow/underflow check to
  time_new_internal().

* time.c (time_minus): ditto.

* time.c (time_cmp): should consider tv_usec too.

* time.c (time_gmtime): time_modify() should be called even if tm
  struct is not calculated yet.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1880 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2001-12-03 10:07:48 +00:00
Родитель 9e8553e5cc
Коммит b3144a7a0e
3 изменённых файлов: 117 добавлений и 77 удалений

Просмотреть файл

@ -8,6 +8,22 @@ Mon Dec 3 16:04:16 2001 Usaku Nakamura <usa@ruby-lang.org>
* configure.in: not use X11BASE, since it's not always set.
Mon Dec 3 09:59:08 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* time.c (time_plus): must detect result overflow.
* time.c (time_minus): ditto.
* time.c (time_new_internal): round usec overflow and underflow
here.
* time.c (time_plus): move operand overflow/underflow check to
time_new_internal().
* time.c (time_minus): ditto.
* time.c (time_cmp): should consider tv_usec too.
Mon Dec 3 03:32:22 2001 Usaku Nakamura <usa@ruby-lang.org>
* configure.in: apply patch from NetBSD's pkgsrc (patch-aa).
@ -20,6 +36,11 @@ Sun Dec 2 22:01:52 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* ext/dbm/extconf.rb: check if $CFLAGS includes DBM_HDR.
Sat Dec 1 12:13:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* time.c (time_gmtime): time_modify() should be called even if tm
struct is not calculated yet.
Fri Nov 30 17:02:55 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* configure.in: set target_cpu to i386 on cygwin and mingw32.
@ -13145,4 +13166,3 @@ Fri Aug 15 19:40:43 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
Wed Aug 13 17:51:46 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* version 1.1 alpha0 released.

Просмотреть файл

@ -44,60 +44,64 @@
# of a previous state of ``the instance'' - see third example.
#
module Singleton
def Singleton.included (klass)
# should this be checked?
# raise TypeError.new "..." if klass.type == Module
class << klass
def inherited(sub_klass)
# @__instance__ takes on one of the following values
# * nil - before (and after a failed) creation
# * false - during creation
# * sub_class instance - after a successful creation
sub_klass.instance_eval { @__instance__ = nil }
def sub_klass.instance
unless @__instance__.nil?
# is the extra flexiblity having the hook method
# _wait() around ever useful?
_wait()
# check for instance creation
return @__instance__ if @__instance__
end
Thread.critical = true
unless @__instance__
@__instance__ = false
Thread.critical = false
begin
@__instance__ = new
ensure
if @__instance__
define_method(:instance) {@__instance__ }
else
# failed instance creation
@__instance__ = nil
end
end
else
Thread.critical = false
end
return @__instance__
end
end
def _load(str)
instance
end
def _wait
sleep(0.05) while false.equal?(@__instance__)
end
private :new, :allocate
# hook methods are also marked private
private :_load,:_wait
end
klass.inherited klass
end
private
def _dump(depth)
return ""
def Singleton.included (klass)
# should this be checked?
# raise TypeError.new "..." if klass.type == Module
klass.module_eval {
undef_method :clone
undef_method :dup
}
class << klass
def inherited(sub_klass)
# @__instance__ takes on one of the following values
# * nil - before (and after a failed) creation
# * false - during creation
# * sub_class instance - after a successful creation
sub_klass.instance_eval { @__instance__ = nil }
def sub_klass.instance
unless @__instance__.nil?
# is the extra flexiblity having the hook method
# _wait() around ever useful?
_wait()
# check for instance creation
return @__instance__ if @__instance__
end
Thread.critical = true
unless @__instance__
@__instance__ = false
Thread.critical = false
begin
@__instance__ = new
ensure
if @__instance__
define_method(:instance) {@__instance__ }
else
# failed instance creation
@__instance__ = nil
end
end
else
Thread.critical = false
end
return @__instance__
end
end
def _load(str)
instance
end
def _wait
sleep(0.05) while false.equal?(@__instance__)
end
private :new, :allocate
# hook methods are also marked private
private :_load,:_wait
end
klass.inherited klass
end
private
def _dump(depth)
return ""
end
end
if __FILE__ == $0

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

@ -68,6 +68,14 @@ time_new_internal(klass, sec, usec)
VALUE obj;
struct time_object *tobj;
if (usec >= 1000000) { /* usec overflow */
sec += usec / 1000000;
usec %= 1000000;
}
if (usec < 0) { /* usec underflow */
sec -= (-usec) / 1000000;
usec %= 1000000;
}
#ifndef NEGATIVE_TIME_T
if (sec < 0 || (sec == 0 && usec < 0))
rb_raise(rb_eArgError, "time must be positive");
@ -601,7 +609,13 @@ time_cmp(time1, time2)
switch (TYPE(time2)) {
case T_FIXNUM:
i = FIX2LONG(time2);
if (tobj1->tv.tv_sec == i) return INT2FIX(0);
if (tobj1->tv.tv_sec == i) {
if (tobj1->tv.tv_usec == 0)
return INT2FIX(0);
if (tobj1->tv.tv_usec > 0)
return INT2FIX(1);
return INT2FIX(-1);
}
if (tobj1->tv.tv_sec > i) return INT2FIX(1);
return INT2FIX(-1);
@ -706,8 +720,11 @@ time_localtime(time)
time_t t;
GetTimeval(time, tobj);
if (tobj->tm_got) {
if (!tobj->gmt) return time;
if (!tobj->gmt) {
if (tobj->tm_got)
return time;
}
else {
time_modify(time);
}
t = tobj->tv.tv_sec;
@ -727,8 +744,11 @@ time_gmtime(time)
time_t t;
GetTimeval(time, tobj);
if (tobj->tm_got) {
if (tobj->gmt) return time;
if (tobj->gmt) {
if (tobj->tm_got)
return time;
}
else {
time_modify(time);
}
t = tobj->tv.tv_sec;
@ -804,14 +824,12 @@ time_plus(time1, time2)
usec = tobj->tv.tv_usec + (time_t)((f - (double)sec)*1e6);
sec = tobj->tv.tv_sec + sec;
if (usec >= 1000000) { /* usec overflow */
sec++;
usec -= 1000000;
}
if (usec < 0) { /* usec underflow */
sec--;
usec += 1000000;
#ifdef NEGATIVE_TIME_T
if ((tobj->tv.tv_sec > 0 && f > 0 && sec < 0) ||
(tobj->tv.tv_sec < 0 && f < 0 && sec > 0)) {
rb_raise(rb_eRangeError, "time + %f out of Time range", f);
}
#endif
time2 = rb_time_new(sec, usec);
if (tobj->gmt) {
GetTimeval(time2, tobj);
@ -833,8 +851,8 @@ time_minus(time1, time2)
struct time_object *tobj2;
GetTimeval(time2, tobj2);
f = tobj->tv.tv_sec - tobj2->tv.tv_sec;
f += (tobj->tv.tv_usec - tobj2->tv.tv_usec)*1e-6;
f = (double)tobj->tv.tv_sec - (double)tobj2->tv.tv_sec;
f += ((double)tobj->tv.tv_usec - (double)tobj2->tv.tv_usec)*1e-6;
return rb_float_new(f);
}
@ -844,16 +862,14 @@ time_minus(time1, time2)
usec = tobj->tv.tv_usec - (time_t)((f - (double)sec)*1e6);
sec = tobj->tv.tv_sec - sec;
}
#ifdef NEGATIVE_TIME_T
if ((tobj->tv.tv_sec < 0 && f > 0 && sec > 0) ||
(tobj->tv.tv_sec > 0 && f < 0 && sec < 0)) {
rb_raise(rb_eRangeError, "time - %f out of Time range", f);
}
#endif
if (usec >= 1000000) { /* usec overflow */
sec++;
usec -= 1000000;
}
if (usec < 0) { /* usec underflow */
sec--;
usec += 1000000;
}
time2 = time_new_internal(rb_obj_class(time1), sec, usec);
time2 = rb_time_new(sec, usec);
if (tobj->gmt) {
GetTimeval(time2, tobj);
tobj->gmt = 1;