From 44a247c745368ad9950d2ed02f2b3424e5759ef5 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 24 Mar 2016 05:20:22 +0000 Subject: 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 --- strftime.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'strftime.c') 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) { -- cgit v1.2.3