[前][次][番号順一覧][スレッド一覧]

ruby-changes:52012

From: akr <ko1@a...>
Date: Wed, 8 Aug 2018 19:00:49 +0900 (JST)
Subject: [ruby-changes:52012] akr:r64227 (trunk): Store String as zone in struct vtm.

akr	2018-08-08 19:00:43 +0900 (Wed, 08 Aug 2018)

  New Revision: 64227

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64227

  Log:
    Store String as zone in struct vtm.
    
    This removes zone_table and use fstring instead.

  Modified files:
    trunk/strftime.c
    trunk/time.c
    trunk/timev.h
Index: timev.h
===================================================================
--- timev.h	(revision 64226)
+++ timev.h	(revision 64227)
@@ -5,7 +5,7 @@ PACKED_STRUCT_UNALIGNED(struct vtm { https://github.com/ruby/ruby/blob/trunk/timev.h#L5
     VALUE year; /* 2000 for example.  Integer. */
     VALUE subsecx; /* 0 <= subsecx < TIME_SCALE.  possibly Rational. */
     VALUE utc_offset; /* -3600 as -01:00 for example.  possibly Rational. */
-    const char *zone; /* "JST", "EST", "EDT", etc. */
+    VALUE zone; /* "JST", "EST", "EDT", etc. as String */
     unsigned int yday:9; /* 1..366 */
     unsigned int mon:4; /* 1..12 */
     unsigned int mday:5; /* 1..31 */
Index: strftime.c
===================================================================
--- strftime.c	(revision 64226)
+++ strftime.c	(revision 64227)
@@ -619,11 +619,11 @@ rb_strftime_with_timespec(VALUE ftime, c https://github.com/ruby/ruby/blob/trunk/strftime.c#L619
 				tp = "UTC";
 				break;
 			}
-			if (vtm->zone == NULL) {
+			if (NIL_P(vtm->zone)) {
 			    i = 0;
 			}
 			else {
-                            tp = vtm->zone;
+                            tp = RSTRING_PTR(vtm->zone);
 			    if (enc) {
 				for (i = 0; i < TBUFSIZE && tp[i]; i++) {
 				    if ((unsigned char)tp[i] > 0x7F) {
Index: time.c
===================================================================
--- time.c	(revision 64226)
+++ time.c	(revision 64227)
@@ -799,31 +799,29 @@ timegmw_noleapsecond(struct vtm *vtm) https://github.com/ruby/ruby/blob/trunk/time.c#L799
     return wret;
 }
 
-static st_table *zone_table;
+#define rb_fstring_usascii(str) rb_fstring_enc_cstr((str), rb_usascii_encoding())
 
-static int
-zone_str_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+static VALUE
+zone_str(const char *zone)
 {
-    const char *s = (const char *)*key;
-    const char **ret = (const char **)arg;
-
-    if (existing) {
-	*ret = (const char *)*value;
-	return ST_STOP;
-    }
-    *ret = s = strdup(s);
-    *key = *value = (st_data_t)s;
-    return ST_CONTINUE;
-}
+    const char *p;
+    int ascii_only = 1;
 
-static const char *
-zone_str(const char *s)
-{
-    if (!zone_table)
-        zone_table = st_init_strtable();
+    if (zone == NULL) {
+        return rb_fstring_usascii("(NO-TIMEZONE-ABBREVIATION)");
+    }
 
-    st_update(zone_table, (st_data_t)s, zone_str_update, (st_data_t)&s);
-    return s;
+    for (p = zone; *p; p++)
+        if (!ISASCII(*p)) {
+            ascii_only = 0;
+            break;
+        }
+    if (ascii_only) {
+        return rb_fstring_usascii(zone);
+    }
+    else {
+        return rb_fstring_enc_cstr(zone, rb_locale_encoding());
+    }
 }
 
 static void
@@ -931,7 +929,7 @@ gmtimew_noleapsecond(wideval_t timew, st https://github.com/ruby/ruby/blob/trunk/time.c#L929
     }
 
     vtm->utc_offset = INT2FIX(0);
-    vtm->zone = "UTC";
+    vtm->zone = rb_fstring_usascii("UTC");
 }
 
 static struct tm *
@@ -1198,12 +1196,12 @@ gmtimew(wideval_t timew, struct vtm *res https://github.com/ruby/ruby/blob/trunk/time.c#L1196
     result->wday = tm.tm_wday;
     result->yday = tm.tm_yday+1;
     result->isdst = tm.tm_isdst;
-    result->zone = "UTC";
+    result->zone = rb_fstring_usascii("UTC");
 
     return result;
 }
 
-static struct tm *localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);
+static struct tm *localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VALUE *zone);
 
 /*
  * The idea is borrowed from Perl:
@@ -1299,11 +1297,11 @@ calc_wday(int year, int month, int day) https://github.com/ruby/ruby/blob/trunk/time.c#L1297
 }
 
 static VALUE
-guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, const char **zone_ret)
+guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, VALUE *zone_ret)
 {
     struct tm tm;
     long gmtoff;
-    const char *zone;
+    VALUE zone;
     time_t t;
     struct vtm vtm2;
     VALUE timev;
@@ -1314,7 +1312,7 @@ guess_local_offset(struct vtm *vtm_utc, https://github.com/ruby/ruby/blob/trunk/time.c#L1312
     if (lt(vtm_utc->year, INT2FIX(1916))) {
         VALUE off = INT2FIX(0);
         int isdst = 0;
-        zone = "UTC";
+        zone = rb_fstring_usascii("UTC");
 
 # if defined(NEGATIVE_TIME_T)
 #  if SIZEOF_TIME_T <= 4
@@ -1358,7 +1356,7 @@ guess_local_offset(struct vtm *vtm_utc, https://github.com/ruby/ruby/blob/trunk/time.c#L1356
 
     timev = w2v(rb_time_unmagnify(timegmw(&vtm2)));
     t = NUM2TIMET(timev);
-    zone = "UTC";
+    zone = rb_fstring_usascii("UTC");
     if (localtime_with_gmtoff_zone(&t, &tm, &gmtoff, &zone)) {
         if (isdst_ret)
             *isdst_ret = tm.tm_isdst;
@@ -1371,13 +1369,19 @@ guess_local_offset(struct vtm *vtm_utc, https://github.com/ruby/ruby/blob/trunk/time.c#L1369
         /* Use the current time offset as a last resort. */
         static time_t now = 0;
         static long now_gmtoff = 0;
-        static const char *now_zone = "UTC";
+        static int now_isdst = 0;
+        static VALUE now_zone;
         if (now == 0) {
+            VALUE zone;
             now = time(NULL);
-            localtime_with_gmtoff_zone(&now, &tm, &now_gmtoff, &now_zone);
+            localtime_with_gmtoff_zone(&now, &tm, &now_gmtoff, &zone);
+            now_isdst = tm.tm_isdst;
+            zone = rb_fstring(zone);
+            rb_gc_register_mark_object(zone);
+            now_zone = zone;
         }
         if (isdst_ret)
-            *isdst_ret = tm.tm_isdst;
+            *isdst_ret = now_isdst;
         if (zone_ret)
             *zone_ret = now_zone;
         return LONG2FIX(now_gmtoff);
@@ -1485,7 +1489,7 @@ timelocalw(struct vtm *vtm) https://github.com/ruby/ruby/blob/trunk/time.c#L1489
 }
 
 static struct tm *
-localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone)
+localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VALUE *zone)
 {
     struct tm tm;
 
@@ -1516,10 +1520,7 @@ localtime_with_gmtoff_zone(const time_t https://github.com/ruby/ruby/blob/trunk/time.c#L1520
 
         if (zone) {
 #if defined(HAVE_TM_ZONE)
-            if (tm.tm_zone)
-                *zone = zone_str(tm.tm_zone);
-            else
-                *zone = zone_str("(NO-TIMEZONE-ABBREVIATION)");
+            *zone = zone_str(tm.tm_zone);
 #elif defined(HAVE_TZNAME) && defined(HAVE_DAYLIGHT)
 # if RUBY_MSVCRT_VERSION >= 140
 #  define tzname _tzname
@@ -1579,7 +1580,7 @@ static struct vtm * https://github.com/ruby/ruby/blob/trunk/time.c#L1580
 localtimew(wideval_t timew, struct vtm *result)
 {
     VALUE subsecx, offset;
-    const char *zone;
+    VALUE zone;
     int isdst;
 
     if (!timew_out_of_timet_range(timew)) {
@@ -1647,7 +1648,7 @@ PACKED_STRUCT_UNALIGNED(struct time_obje https://github.com/ruby/ruby/blob/trunk/time.c#L1648
 #define TIME_SET_FIXOFF(tobj, off) \
     ((tobj)->gmt = 2, \
      (tobj)->vtm.utc_offset = (off), \
-     (tobj)->vtm.zone = NULL)
+     (tobj)->vtm.zone = Qnil)
 
 #define TIME_COPY_GMT(tobj1, tobj2) \
     ((tobj1)->gmt = (tobj2)->gmt, \
@@ -1671,6 +1672,7 @@ time_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/time.c#L1672
     rb_gc_mark(tobj->vtm.year);
     rb_gc_mark(tobj->vtm.subsecx);
     rb_gc_mark(tobj->vtm.utc_offset);
+    rb_gc_mark(tobj->vtm.zone);
 }
 
 static size_t
@@ -2000,7 +2002,7 @@ time_init_1(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/time.c#L2002
 
     vtm.wday = VTM_WDAY_INITVAL;
     vtm.yday = 0;
-    vtm.zone = "";
+    vtm.zone = rb_fstring_usascii("");
 
     /*                             year  mon   mday  hour  min   sec   off */
     rb_scan_args(argc, argv, "16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]);
@@ -2596,7 +2598,7 @@ time_arg(int argc, VALUE *argv, struct v https://github.com/ruby/ruby/blob/trunk/time.c#L2598
     vtm->wday = 0;
     vtm->yday = 0;
     vtm->isdst = 0;
-    vtm->zone = "";
+    vtm->zone = rb_fstring_usascii("");
 
     if (argc == 10) {
 	v[0] = argv[5];
@@ -3653,7 +3655,7 @@ time_to_s(VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L3655
 static VALUE
 time_add(struct time_object *tobj, VALUE torig, VALUE offset, int sign)
 {
-    VALUE result, zone;
+    VALUE result;
     offset = num_exact(offset);
     if (sign < 0)
         result = time_new_timew(rb_cTime, wsub(tobj->timew, rb_time_magnify(v2w(offset))));
@@ -3668,10 +3670,6 @@ time_add(struct time_object *tobj, VALUE https://github.com/ruby/ruby/blob/trunk/time.c#L3670
         GetTimeval(result, tobj);
         TIME_SET_FIXOFF(tobj, off);
     }
-    if (!tobj->vtm.zone && !NIL_P(zone = rb_attr_get(torig, id_zone))) {
-	tobj->vtm.zone = StringValueCStr(zone);
-	rb_ivar_set(result, id_zone, zone);
-    }
 
     return result;
 }
@@ -4164,19 +4162,6 @@ time_isdst(VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L4162
     return tobj->vtm.isdst ? Qtrue : Qfalse;
 }
 
-static VALUE
-time_zone_name(const char *zone)
-{
-    VALUE name = rb_str_new_cstr(zone);
-    if (!rb_enc_str_asciionly_p(name)) {
-	name = rb_external_str_with_enc(name, rb_locale_encoding());
-    }
-    else {
-	rb_enc_associate(name, rb_usascii_encoding());
-    }
-    return name;
-}
-
 /*
  *  call-seq:
  *     time.zone -> string
@@ -4201,10 +4186,10 @@ time_zone(VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L4186
     if (TIME_UTC_P(tobj)) {
 	return rb_usascii_str_new_cstr("UTC");
     }
-    if (tobj->vtm.zone == NULL)
+    if (tobj->vtm.zone == Qnil)
         return Qnil;
 
-    return time_zone_name(tobj->vtm.zone);
+    return rb_str_dup(tobj->vtm.zone);
 }
 
 /*
@@ -4620,9 +4605,7 @@ time_mdump(VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L4605
 	    off = rb_Integer(div);
 	rb_ivar_set(str, id_offset, off);
     }
-    if (tobj->vtm.zone) {
-	rb_ivar_set(str, id_zone, time_zone_name(tobj->vtm.zone));
-    }
+    rb_ivar_set(str, id_zone, tobj->vtm.zone);
     return str;
 }
 
@@ -4706,7 +4689,7 @@ time_mload(VALUE time, VALUE str) https://github.com/ruby/ruby/blob/trunk/time.c#L4689
         vtm.utc_offset = INT2FIX(0);
 	vtm.yday = vtm.wday = 0;
 	vtm.isdst = 0;
-	vtm.zone = "";
+	vtm.zone = rb_fstring_usascii("");
 
 	usec = (long)(s & 0xfffff);
         nsec = usec * 1000;
@@ -4754,8 +4737,7 @@ end_submicro: ; https://github.com/ruby/ruby/blob/trunk/time.c#L4737
     if (!NIL_P(zone)) {
 	if (TIME_FIXOFF_P(tobj)) TIME_SET_LOCALTIME(tobj);
 	zone = rb_fstring(zone);
-	tobj->vtm.zone = StringValueCStr(zone);
-	rb_ivar_set(time, id_zone, zone);
+	tobj->vtm.zone = zone;
     }
 
     return time;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]