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

ruby-changes:23608

From: tadf <ko1@a...>
Date: Wed, 16 May 2012 07:03:51 +0900 (JST)
Subject: [ruby-changes:23608] tadf:r35659 (trunk): * ext/date/date_strftime.c: should also be aware of flags on

tadf	2012-05-16 07:03:37 +0900 (Wed, 16 May 2012)

  New Revision: 35659

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35659

  Log:
    * ext/date/date_strftime.c: should also be aware of flags on
      complex specifier.

  Modified files:
    trunk/ChangeLog
    trunk/ext/date/date_strftime.c
    trunk/test/date/test_date_strftime.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 35658)
+++ ChangeLog	(revision 35659)
@@ -1,3 +1,8 @@
+Wed May 16 06:59:41 2012  Tadayoshi Funaba  <tadf@d...>
+
+	* ext/date/date_strftime.c: should also be aware of flags on
+	  complex specifier.
+
 Wed May 16 05:11:29 2012  Aaron Patterson <aaron@t...>
 
 	* ext/psych/lib/psych/visitors/to_ruby.rb: fix a bug with string
Index: ext/date/date_strftime.c
===================================================================
--- ext/date/date_strftime.c	(revision 35658)
+++ ext/date/date_strftime.c	(revision 35659)
@@ -23,6 +23,24 @@
 #define div(x,y) (rb_funcall((x), rb_intern("div"), 1, (y)))
 #define mod(x,y) (rb_funcall((x), '%', 1, (y)))
 
+static void
+upcase(char *s, size_t i)
+{
+    do {
+	if (ISLOWER(*s))
+	    *s = TOUPPER(*s);
+    } while (s++, --i);
+}
+
+static void
+downcase(char *s, size_t i)
+{
+    do {
+	if (ISUPPER(*s))
+	    *s = TOLOWER(*s);
+    } while (s++, --i);
+}
+
 /* strftime --- produce formatted time */
 
 static size_t
@@ -37,7 +55,8 @@
     int v, w;
     int precision, flags, colons;
     char padding;
-    enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E};
+    /* LOCALE_[OE] and COLONS are actually modifiers, not flags */
+    enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E, COLONS};
 #define BIT_OF(n) (1U<<(n))
 
     /* various tables for locale C */
@@ -64,7 +83,7 @@
 
     for (; *format && s < endp - 1; format++) {
 #define FLAG_FOUND() do {						\
-	    if (precision > 0 || flags & (BIT_OF(LOCALE_E)|BIT_OF(LOCALE_O))) \
+	    if (precision > 0 || flags & (BIT_OF(LOCALE_E) | BIT_OF(LOCALE_O) | BIT_OF(COLONS))) \
 		goto unknown;						\
 	} while (0)
 #define NEEDS(n) do if (s >= endp || (n) >= endp - s - 1) goto err; while (0)
@@ -94,7 +113,9 @@
 	do {								\
 	    i = date_strftime_with_tmx(s, endp - s, (fmt), tmx);	\
 	    if (!i) return 0;						\
-	    if (precision > i) {					\
+	    if (flags & BIT_OF(UPPER))					\
+		upcase(s, i);						\
+	    if (!(flags & BIT_OF(LEFT)) && precision > i) {		\
 		if (start + maxsize < s + precision) {			\
 		    errno = ERANGE;					\
 		    return 0;						\
@@ -148,7 +169,7 @@
 	  case 'A':	/* full weekday name */
 	  case 'a':	/* abbreviated weekday name */
 	    if (flags & BIT_OF(CHCASE)) {
-		flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE));
+		flags &= ~(BIT_OF(LOWER) | BIT_OF(CHCASE));
 		flags |= BIT_OF(UPPER);
 	    }
 	    {
@@ -168,7 +189,7 @@
 	  case 'b':	/* abbreviated month name */
 	  case 'h':	/* same as %b */
 	    if (flags & BIT_OF(CHCASE)) {
-		flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE));
+		flags &= ~(BIT_OF(LOWER) | BIT_OF(CHCASE));
 		flags |= BIT_OF(UPPER);
 	    }
 	    {
@@ -311,8 +332,8 @@
 	  case 'P':	/* am or pm based on 12-hour clock */
 	  case 'p':	/* AM or PM based on 12-hour clock */
 	    if ((*format == 'p' && (flags & BIT_OF(CHCASE))) ||
-		(*format == 'P' && !(flags & (BIT_OF(CHCASE)|BIT_OF(UPPER))))) {
-		flags &= ~(BIT_OF(UPPER)|BIT_OF(CHCASE));
+		(*format == 'P' && !(flags & (BIT_OF(CHCASE) | BIT_OF(UPPER))))) {
+		flags &= ~(BIT_OF(UPPER) | BIT_OF(CHCASE));
 		flags |= BIT_OF(LOWER);
 	    }
 	    v = range(0, tmx_hour, 23);
@@ -401,7 +422,7 @@
 
 	  case 'Z':	/* time zone name or abbreviation */
 	    if (flags & BIT_OF(CHCASE)) {
-		flags &= ~(BIT_OF(UPPER)|BIT_OF(CHCASE));
+		flags &= ~(BIT_OF(UPPER) | BIT_OF(CHCASE));
 		flags |= BIT_OF(LOWER);
 	    }
 	    {
@@ -508,6 +529,10 @@
 	    }
 	    continue;
 
+	  case '+':
+	    STRFTIME("%a %b %e %H:%M:%S %Z %Y");
+	    continue;
+
 	  case 'E':
 	    /* POSIX locale extensions, ignored for now */
 	    flags |= BIT_OF(LOCALE_E);
@@ -522,9 +547,19 @@
 		goto again;
 	    goto unknown;
 
-	  case '+':
-	    STRFTIME("%a %b %e %H:%M:%S %Z %Y");
-	    continue;
+	  case ':':
+	    flags |= BIT_OF(COLONS);
+	    {
+		size_t l = strspn(format, ":");
+		format += l;
+		if (*format == 'z') {
+		    colons = l;
+		    format--;
+		    goto again;
+		}
+		format -= l;
+	    }
+	    goto unknown;
 
 	  case '_':
 	    FLAG_FOUND();
@@ -534,7 +569,6 @@
 	  case '-':
 	    FLAG_FOUND();
 	    flags |= BIT_OF(LEFT);
-	    padding = precision = 0;
 	    goto again;
 
 	  case '^':
@@ -547,16 +581,8 @@
 	    flags |= BIT_OF(CHCASE);
 	    goto again;
 
-	  case ':':
-	    colons++;
-	    goto again;
-
-	  case '%':
-	    FILL_PADDING(1);
-	    *s++ = '%';
-	    continue;
-
 	  case '0':
+	    FLAG_FOUND();
 	    padding = '0';
 	  case '1':  case '2': case '3': case '4':
 	  case '5': case '6':  case '7': case '8': case '9':
@@ -567,6 +593,11 @@
 		goto again;
 	    }
 
+	  case '%':
+	    FILL_PADDING(1);
+	    *s++ = '%';
+	    continue;
+
 	  default:
 	  unknown:
 	    i = format - sp + 1;
@@ -580,21 +611,15 @@
 	if (i) {
 	    FILL_PADDING(i);
 	    memcpy(s, tp, i);
-	    switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) {
+	    switch (flags & (BIT_OF(UPPER) | BIT_OF(LOWER))) {
 	      case BIT_OF(UPPER):
-		do {
-		    if (ISLOWER(*s)) *s = TOUPPER(*s);
-		} while (s++, --i);
+		upcase(s, i);
 		break;
 	      case BIT_OF(LOWER):
-		do {
-		    if (ISUPPER(*s)) *s = TOLOWER(*s);
-		} while (s++, --i);
+		downcase(s, i);
 		break;
-	      default:
-		s += i;
-		break;
 	    }
+	    s += i;
 	}
     }
     if (s >= endp) {
Index: test/date/test_date_strftime.rb
===================================================================
--- test/date/test_date_strftime.rb	(revision 35658)
+++ test/date/test_date_strftime.rb	(revision 35659)
@@ -336,6 +336,21 @@
     assert_equal('+09:08:07', d.strftime('%:::z'))
   end
 
+  def test_strftime__gnuext_complex
+    d = DateTime.parse('2001-02-03T04:05:06+09:00')
+    assert_equal('Sat Feb  3 04:05:06 2001', d.strftime('%-100c'))
+    assert_equal('Sat Feb  3 04:05:06 2001'.rjust(100), d.strftime('%100c'))
+    assert_equal('Sat Feb  3 04:05:06 2001'.rjust(100), d.strftime('%_100c'))
+    assert_equal('Sat Feb  3 04:05:06 2001'.rjust(100, '0'), d.strftime('%0100c'))
+    assert_equal('SAT FEB  3 04:05:06 2001', d.strftime('%^c'))
+
+    assert_equal('Sat Feb  3 04:05:06 +09:00 2001', d.strftime('%-100+'))
+    assert_equal('Sat Feb  3 04:05:06 +09:00 2001'.rjust(100), d.strftime('%100+'))
+    assert_equal('Sat Feb  3 04:05:06 +09:00 2001'.rjust(100), d.strftime('%_100+'))
+    assert_equal('Sat Feb  3 04:05:06 +09:00 2001'.rjust(100, '0'), d.strftime('%0100+'))
+    assert_equal('SAT FEB  3 04:05:06 +09:00 2001', d.strftime('%^+'))
+  end
+
   def test__different_format
     d = Date.new(2001,2,3)
 

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

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