ruby-changes:42168
From: nobu <ko1@a...>
Date: Thu, 24 Mar 2016 12:43:10 +0900 (JST)
Subject: [ruby-changes:42168] nobu:r54242 (trunk): date_core.c: fix jisx0301 and iso8601
nobu 2016-03-24 12:43:06 +0900 (Thu, 24 Mar 2016) New Revision: 54242 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=54242 Log: date_core.c: fix jisx0301 and iso8601 * ext/date/date_core.c (d_lite_jisx0301, iso8601_timediv), (dt_lite_jisx0301): format by the format string in local buffer to prevent intermediate strings from GC. Modified files: trunk/ChangeLog trunk/ext/date/date_core.c trunk/ext/date/depend Index: ext/date/depend =================================================================== --- ext/date/depend (revision 54241) +++ ext/date/depend (revision 54242) @@ -9,6 +9,7 @@ date_core.o: $(hdrdir)/ruby/oniguruma.h https://github.com/ruby/ruby/blob/trunk/ext/date/depend#L9 date_core.o: $(hdrdir)/ruby/ruby.h date_core.o: $(hdrdir)/ruby/st.h date_core.o: $(hdrdir)/ruby/subst.h +date_core.o: $(hdrdir)/ruby/util.h date_core.o: $(top_srcdir)/include/ruby.h date_core.o: date_core.c date_core.o: date_tmx.h Index: ext/date/date_core.c =================================================================== --- ext/date/date_core.c (revision 54241) +++ ext/date/date_core.c (revision 54242) @@ -4,6 +4,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L4 #include "ruby.h" #include "ruby/encoding.h" +#include "ruby/util.h" #include <math.h> #include <time.h> #if defined(HAVE_SYS_TIME_H) @@ -6880,6 +6881,7 @@ strftimev(const char *fmt, VALUE self, https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L6881 (*func)(self, &tmx); len = date_strftime_alloc(&buf, fmt, &tmx); + RB_GC_GUARD(self); str = rb_usascii_str_new(buf, len); if (buf != buffer) xfree(buf); return str; @@ -6953,30 +6955,40 @@ d_lite_httpdate(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L6955 return strftimev("%a, %d %b %Y %T GMT", dup, set_tmx); } -static VALUE -jisx0301_date(VALUE jd, VALUE y) -{ - VALUE a[2]; +enum { + DECIMAL_SIZE_OF_LONG = DECIMAL_SIZE_OF_BITS(CHAR_BIT*sizeof(long)), + JISX0301_DATE_SIZE = DECIMAL_SIZE_OF_LONG+8 +}; - if (f_lt_p(jd, INT2FIX(2405160))) - return rb_usascii_str_new2("%Y-%m-%d"); - if (f_lt_p(jd, INT2FIX(2419614))) { - a[0] = rb_usascii_str_new2("M%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1867)); - } - else if (f_lt_p(jd, INT2FIX(2424875))) { - a[0] = rb_usascii_str_new2("T%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1911)); - } - else if (f_lt_p(jd, INT2FIX(2447535))) { - a[0] = rb_usascii_str_new2("S%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1925)); - } - else { - a[0] = rb_usascii_str_new2("H%02d" ".%%m.%%d"); - a[1] = f_sub(y, INT2FIX(1988)); +static const char * +jisx0301_date_format(char *fmt, size_t size, VALUE jd, VALUE y) +{ + if (FIXNUM_P(jd)) { + long d = FIX2INT(jd); + long s; + char c; + if (d < 2405160) + return "%Y-%m-%d"; + if (d < 2419614) { + c = 'M'; + s = 1867; + } + else if (d < 2424875) { + c = 'T'; + s = 1911; + } + else if (d < 2447535) { + c = 'S'; + s = 1925; + } + else { + c = 'H'; + s = 1988; + } + snprintf(fmt, size, "%c%02ld" ".%%m.%%d", c, FIX2INT(y) - s); + return fmt; } - return rb_f_sprintf(2, a); + return "%Y-%m-%d"; } /* @@ -6990,12 +7002,14 @@ jisx0301_date(VALUE jd, VALUE y) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L7002 static VALUE d_lite_jisx0301(VALUE self) { - VALUE s; + char fmtbuf[JISX0301_DATE_SIZE]; + const char *fmt; get_d1(self); - s = jisx0301_date(m_real_local_jd(dat), - m_real_year(dat)); - return strftimev(RSTRING_PTR(s), self, set_tmx); + fmt = jisx0301_date_format(fmtbuf, sizeof(fmtbuf), + m_real_local_jd(dat), + m_real_year(dat)); + return strftimev(fmt, self, set_tmx); } #ifndef NDEBUG @@ -8301,26 +8315,19 @@ dt_lite_strftime(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L8315 } static VALUE -iso8601_timediv(VALUE self, VALUE n) +iso8601_timediv(VALUE self, long n) { - VALUE fmt; - - n = to_integer(n); - fmt = rb_usascii_str_new2("T%H:%M:%S"); - if (f_gt_p(n, INT2FIX(0))) { - VALUE argv[3]; - - get_d1(self); - - argv[0] = rb_usascii_str_new2(".%0*d"); - argv[1] = n; - argv[2] = f_round(f_quo(m_sf_in_sec(dat), - f_quo(INT2FIX(1), - f_expt(INT2FIX(10), n)))); - rb_str_append(fmt, rb_f_sprintf(3, argv)); - } - rb_str_append(fmt, rb_usascii_str_new2("%:z")); - return strftimev(RSTRING_PTR(fmt), self, set_tmx); + static const char timefmt[] = "T%H:%M:%S"; + static const char zone[] = "%:z"; + char fmt[sizeof(timefmt) + sizeof(zone) + rb_strlen_lit(".%N") + + DECIMAL_SIZE_OF_LONG]; + char *p = fmt; + + memcpy(p, timefmt, sizeof(timefmt)-1); + p += sizeof(timefmt)-1; + if (n > 0) p += snprintf(p, fmt+sizeof(fmt)-p, ".%%%ldN", n); + memcpy(p, zone, sizeof(zone)); + return strftimev(fmt, self, set_tmx); } /* @@ -8337,12 +8344,11 @@ iso8601_timediv(VALUE self, VALUE n) https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L8344 static VALUE dt_lite_iso8601(int argc, VALUE *argv, VALUE self) { - VALUE n; - - rb_scan_args(argc, argv, "01", &n); + long n = 0; - if (argc < 1) - n = INT2FIX(0); + rb_check_arity(argc, 0, 1); + if (argc >= 1) + n = NUM2LONG(argv[0]); return f_add(strftimev("%Y-%m-%d", self, set_tmx), iso8601_timediv(self, n)); @@ -8377,18 +8383,15 @@ dt_lite_rfc3339(int argc, VALUE *argv, V https://github.com/ruby/ruby/blob/trunk/ext/date/date_core.c#L8383 static VALUE dt_lite_jisx0301(int argc, VALUE *argv, VALUE self) { - VALUE n, s; - - rb_scan_args(argc, argv, "01", &n); + long n = 0; - if (argc < 1) - n = INT2FIX(0); + rb_check_arity(argc, 0, 1); + if (argc >= 1) + n = NUM2LONG(argv[0]); { get_d1(self); - s = jisx0301_date(m_real_local_jd(dat), - m_real_year(dat)); - return rb_str_append(strftimev(RSTRING_PTR(s), self, set_tmx), + return rb_str_append(d_lite_jisx0301(self), iso8601_timediv(self, n)); } } Index: ChangeLog =================================================================== --- ChangeLog (revision 54241) +++ ChangeLog (revision 54242) @@ -1,4 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 -Thu Mar 24 12:42:36 2016 Nobuyoshi Nakada <nobu@r...> +Thu Mar 24 12:43:05 2016 Nobuyoshi Nakada <nobu@r...> + + * ext/date/date_core.c (d_lite_jisx0301, iso8601_timediv), + (dt_lite_jisx0301): format by the format string in local buffer + to prevent intermediate strings from GC. * ext/date/date_core.c (mk_inspect_raw, mk_inspect): inspect by "%+"PRIsVALUE, to prevent intermediate strings from GC. -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/