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

ruby-changes:44239

From: nobu <ko1@a...>
Date: Sat, 1 Oct 2016 17:52:50 +0900 (JST)
Subject: [ruby-changes:44239] nobu:r56312 (trunk): date_parse.c: refactor

nobu	2016-10-01 17:52:42 +0900 (Sat, 01 Oct 2016)

  New Revision: 56312

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

  Log:
    date_parse.c: refactor
    
    * ext/date/date_parse.c (date_zone_to_diff): refactor without
      allocating strings.

  Modified files:
    trunk/ext/date/date_parse.c
Index: ext/date/date_parse.c
===================================================================
--- ext/date/date_parse.c	(revision 56311)
+++ ext/date/date_parse.c	(revision 56312)
@@ -7,6 +7,9 @@ https://github.com/ruby/ruby/blob/trunk/ext/date/date_parse.c#L7
 #include "ruby/re.h"
 #include <ctype.h>
 
+RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
+RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
+
 /* #define TIGHT_PARSER */
 
 #define sizeof_array(o) (sizeof o / sizeof o[0])
@@ -373,44 +376,30 @@ date_zone_to_diff(VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/date/date_parse.c#L376
 	    --d;
 	*d = '\0';
     }
-    str = rb_str_new2(dest);
+    l = d - dest;
+    s = dest;
     {
-#define STD " standard time"
-#define DST " daylight time"
-	char *ss, *ds;
-	long sl, dl;
+	static const char STD[] = " standard time";
+	static const char DST1[] = " daylight time";
+	static const char DST2[] = " dst";
 	int dst = 0;
 
-	sl = RSTRING_LEN(str) - (sizeof STD - 1);
-	ss = RSTRING_PTR(str) + sl;
-	dl = RSTRING_LEN(str) - (sizeof DST - 1);
-	ds = RSTRING_PTR(str) + dl;
-
-	if (sl >= 0 && strcmp(ss, STD) == 0) {
-	    str = rb_str_new(RSTRING_PTR(str), sl);
-	}
-	else if (dl >= 0 && strcmp(ds, DST) == 0) {
-	    str = rb_str_new(RSTRING_PTR(str), dl);
+	if (l >= (int)sizeof(STD) - 1 && strcmp(d - (sizeof(STD) - 1), STD) == 0) {
+	    l -= sizeof(STD) - 1;
+	    s[l] = '\0';
+	}
+	else if (l >= (int)sizeof(DST1) - 1 && strcmp(d - (sizeof(DST1) - 1), DST1) == 0) {
+	    l -= sizeof(DST1) - 1;
+	    s[l] = '\0';
 	    dst = 1;
 	}
-#undef STD
-#undef DST
-	else {
-#define DST " dst"
-	    char *ds;
-	    long dl;
-
-	    dl = RSTRING_LEN(str) - (sizeof DST - 1);
-	    ds = RSTRING_PTR(str) + dl;
-
-	    if (dl >= 0 && strcmp(ds, DST) == 0) {
-		str = rb_str_new(RSTRING_PTR(str), dl);
-		dst = 1;
-	    }
-#undef DST
+	else if (l >= (int)sizeof(DST2) - 1 && strcmp(d - (sizeof(DST2) - 1), DST2) == 0) {
+	    l -= sizeof(DST2) - 1;
+	    s[l] = '\0';
+	    dst = 1;
 	}
 	{
-	    const struct zone *z = zonetab(RSTRING_PTR(str), (unsigned int)RSTRING_LEN(str));
+	    const struct zone *z = zonetab(s, (unsigned int)l);
 	    if (z) {
 		int d = z->offset;
 		if (dst)
@@ -420,100 +409,60 @@ date_zone_to_diff(VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/date/date_parse.c#L409
 	    }
 	}
 	{
-	    char *s, *p;
-	    VALUE sign;
-	    VALUE hour = Qnil, min = Qnil, sec = Qnil;
-	    VALUE str_orig;
-
-	    s = RSTRING_PTR(str);
-	    str_orig = str;
-
-	    if (strncmp(s, "gmt", 3) == 0 ||
-		strncmp(s, "utc", 3) == 0)
+	    char *p;
+	    int sign = 0;
+	    unsigned long hour = 0, min = 0, sec = 0;
+
+	    if (l > 3 &&
+		(strncmp(s, "gmt", 3) == 0 ||
+		 strncmp(s, "utc", 3) == 0)) {
 		s += 3;
+		l -= 3;
+	    }
 	    if (issign(*s)) {
-		sign = rb_str_new(s, 1);
+		sign = *s == '-';
 		s++;
+		l--;
 
-		str = rb_str_new2(s);
-
-		if ((p = strchr(s, ':')) != NULL) {
-		    hour = rb_str_new(s, p - s);
+		hour = STRTOUL(s, &p, 10);
+		if (*p == ':') {
 		    s = ++p;
-		    if ((p = strchr(s, ':')) != NULL) {
-			min = rb_str_new(s, p - s);
+		    min = STRTOUL(s, &p, 10);
+		    if (*p == ':') {
 			s = ++p;
-			if ((p = strchr(s, ':')) != NULL) {
-			    sec = rb_str_new(s, p - s);
-			}
-			else
-			    sec = rb_str_new2(s);
+			sec = STRTOUL(s, &p, 10);
 		    }
-		    else
-			min = rb_str_new2(s);
-		    RB_GC_GUARD(str_orig);
-		    goto num;
-		}
-		if (strpbrk(RSTRING_PTR(str), ",.")) {
-		    VALUE astr = 0;
-		    char *a, *b;
-
-		    a = ALLOCV_N(char, astr, RSTRING_LEN(str) + 1);
-		    strcpy(a, RSTRING_PTR(str));
-		    b = strpbrk(a, ",.");
-		    *b = '\0';
-		    b++;
-
-		    hour = cstr2num(a);
-		    min = f_mul(rb_rational_new2
-				(cstr2num(b),
-				 f_expt(INT2FIX(10),
-					LONG2NUM((long)strlen(b)))),
-				INT2FIX(60));
-		    ALLOCV_END(astr);
 		    goto num;
 		}
-		{
-		    const char *cs = RSTRING_PTR(str);
-		    long cl = RSTRING_LEN(str);
-
-		    if (cl % 2) {
-			if (cl >= 1)
-			    hour = rb_str_new(&cs[0], 1);
-			if (cl >= 3)
-			    min  = rb_str_new(&cs[1], 2);
-			if (cl >= 5)
-			    sec  = rb_str_new(&cs[3], 2);
-		    }
-		    else {
-			if (cl >= 2)
-			    hour = rb_str_new(&cs[0], 2);
-			if (cl >= 4)
-			    min  = rb_str_new(&cs[2], 2);
-			if (cl >= 6)
-			    sec  = rb_str_new(&cs[4], 2);
+		if (*p == ',' || *p == '.') {
+		    char *e = 0;
+		    p++;
+		    min = STRTOUL(p, &e, 10) * 3600;
+		    if (sign) {
+			hour = -hour;
+			min = -min;
 		    }
+		    offset = rb_rational_new(INT2FIX(min),
+					     rb_int_positive_pow(10, (int)(e - p)));
+		    offset = f_add(INT2FIX(hour * 3600), offset);
+		    goto ok;
+		}
+		else if (l > 2) {
+		    size_t n;
+		    int ov;
+
+		    if (l >= 1)
+			hour = ruby_scan_digits(&s[0], 2 - l % 2, 10, &n, &ov);
+		    if (l >= 3)
+			min  = ruby_scan_digits(&s[2 - l % 2], 2, 10, &n, &ov);
+		    if (l >= 5)
+			sec  = ruby_scan_digits(&s[4 - l % 2], 2, 10, &n, &ov);
 		    goto num;
 		}
 	      num:
-		if (NIL_P(hour))
-		    offset = INT2FIX(0);
-		else {
-		    if (RB_TYPE_P(hour, T_STRING))
-			hour = str2num(hour);
-		    offset = f_mul(hour, INT2FIX(3600));
-		}
-		if (!NIL_P(min)) {
-		    if (RB_TYPE_P(min, T_STRING))
-			min = str2num(min);
-		    offset = f_add(offset, f_mul(min, INT2FIX(60)));
-		}
-		if (!NIL_P(sec))
-		    offset = f_add(offset, str2num(sec));
-		if (!NIL_P(sign) &&
-		    RSTRING_LEN(sign) == 1 &&
-		    *RSTRING_PTR(sign) == '-')
-		    offset = f_negate(offset);
+		sec += min * 60 + hour * 3600;
+		if (sign) sec = -sec;
+		offset = INT2FIX(sec);
 	    }
 	}
     }

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

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