aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-03-24 05:20:22 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-03-24 05:20:22 +0000
commit44a247c745368ad9950d2ed02f2b3424e5759ef5 (patch)
treee4792c0cdd91ae15df1295bdb020755efe4f1e80
parent0f4c580b20c3da5a9b6615e4d22fb815eea05548 (diff)
downloadruby-44a247c745368ad9950d2ed02f2b3424e5759ef5.tar.gz
strftime.c: case conversion
* strftime.c (STRFTIME): deal with case conversion flags for recursive formats. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54245 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--strftime.c43
-rw-r--r--test/ruby/test_time.rb7
3 files changed, 38 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 25d3ab3fef..f91c97267d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Mar 24 14:20:21 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * strftime.c (STRFTIME): deal with case conversion flags for
+ recursive formats.
+
Thu Mar 24 12:43:26 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/date/date_core.c (dt_lite_iso8601): strftimev() always
diff --git a/strftime.c b/strftime.c
index f532bb0ac6..6502ec6f8f 100644
--- a/strftime.c
+++ b/strftime.c
@@ -157,6 +157,9 @@ max(int a, int b)
/* strftime --- produce formatted time */
+enum {LEFT, CHCASE, LOWER, UPPER};
+#define BIT_OF(n) (1U<<(n))
+
static char *
resize_buffer(VALUE ftime, char *s, const char **start, const char **endp,
ptrdiff_t n)
@@ -171,6 +174,27 @@ resize_buffer(VALUE ftime, char *s, const char **start, const char **endp,
return s += len;
}
+static char *
+case_conv(char *s, ptrdiff_t i, int flags)
+{
+ switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) {
+ case BIT_OF(UPPER):
+ do {
+ if (ISLOWER(*s)) *s = TOUPPER(*s);
+ } while (s++, --i);
+ break;
+ case BIT_OF(LOWER):
+ do {
+ if (ISUPPER(*s)) *s = TOLOWER(*s);
+ } while (s++, --i);
+ break;
+ default:
+ s += i;
+ break;
+ }
+ return s;
+}
+
/*
* enc is the encoding of the format. It is used as the encoding of resulted
* string, but the name of the month and weekday are always US-ASCII. So it
@@ -195,8 +219,6 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
long y;
int precision, flags, colons;
char padding;
- enum {LEFT, CHCASE, LOWER, UPPER};
-#define BIT_OF(n) (1U<<(n))
#ifdef MAILHEADER_EXT
int sign;
#endif
@@ -269,6 +291,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
i = RSTRING_LEN(ftime) - len; \
endp = (start = s) + rb_str_capacity(ftime); \
s += len; \
+ if (i > 0) case_conv(s, i, flags); \
if (precision > i) {\
NEEDS(precision); \
memmove(s + precision - i, s, i);\
@@ -834,21 +857,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
if (i) {
FILL_PADDING(i);
memcpy(s, tp, i);
- switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) {
- case BIT_OF(UPPER):
- do {
- if (ISLOWER(*s)) *s = TOUPPER(*s);
- } while (s++, --i);
- break;
- case BIT_OF(LOWER):
- do {
- if (ISUPPER(*s)) *s = TOLOWER(*s);
- } while (s++, --i);
- break;
- default:
- s += i;
- break;
- }
+ s = case_conv(s, i, flags);
}
}
if (format != format_end) {
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index 3e7d9613ed..24545b216c 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -730,6 +730,13 @@ class TestTime < Test::Unit::TestCase
assert_equal(" 2", t.strftime("%l"))
assert_equal("02", t.strftime("%0l"))
assert_equal(" 2", t.strftime("%_l"))
+ assert_equal("MON", t.strftime("%^a"))
+ assert_equal("OCT", t.strftime("%^b"))
+
+ t = get_t2000
+ assert_equal("UTC", t.strftime("%^Z"))
+ assert_equal("utc", t.strftime("%#Z"))
+ assert_equal("SAT JAN 1 00:00:00 2000", t.strftime("%^c"))
end
def test_strftime_invalid_flags