From 23b280869314c59be4e4fb01d68ebacf753475a9 Mon Sep 17 00:00:00 2001 From: naruse Date: Sat, 27 Aug 2011 09:18:18 +0000 Subject: * strftime.c (rb_strftime_with_timespec): get enc argument to specify the encoding of the format. On Windows (at least Japanese Windows), Time#strftime("%Z") includes non ASCII in locale encoding (CP932). So convert locale to default internal. [ruby-core:39092] [Bug #5226] * strftime.c (rb_strftime): ditto. * strftime.c (rb_strftime_timespec): ditto. * internal.h (rb_strftime_timespec): follow above. * time.c (rb_strftime_alloc): ditto. * time.c (strftimev): ditto. * time.c (time_strftime): ditto. * time.c (time_to_s): the resulted string of Time#to_s is always ascii only, so this should be US-ASCII. * time.c (time_asctime): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33094 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- strftime.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'strftime.c') diff --git a/strftime.c b/strftime.c index 1164db01d1..b02c482d3b 100644 --- a/strftime.c +++ b/strftime.c @@ -48,6 +48,7 @@ */ #include "ruby/ruby.h" +#include "ruby/encoding.h" #include "timev.h" #ifndef GAWK @@ -167,13 +168,19 @@ max(int a, int b) /* strftime --- produce formatted time */ +/* + * 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 + * is only used for the timezone name on Windows. + */ static size_t -rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, struct timespec *ts, int gmt) +rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, rb_encoding *enc, const struct vtm *vtm, VALUE timev, struct timespec *ts, int gmt) { const char *const endp = s + maxsize; const char *const start = s; const char *sp, *tp; - auto char tbuf[100]; +#define TBUFSIZE 100 + auto char tbuf[TBUFSIZE]; long off; ptrdiff_t i; int w; @@ -205,6 +212,11 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str return 0; } + if (enc && (enc == rb_usascii_encoding() || + enc == rb_ascii8bit_encoding() || enc == rb_locale_encoding())) { + enc = NULL; + } + for (; *format && s < endp - 1; format++) { #define FLAG_FOUND() do { \ if (precision > 0 || flags & (BIT_OF(LOCALE_E)|BIT_OF(LOCALE_O))) \ @@ -234,7 +246,7 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str } while (0) #define STRFTIME(fmt) \ do { \ - i = rb_strftime_with_timespec(s, endp - s, (fmt), vtm, timev, ts, gmt); \ + i = rb_strftime_with_timespec(s, endp - s, (fmt), enc, vtm, timev, ts, gmt); \ if (!i) return 0; \ if (precision > i) {\ NEEDS(precision); \ @@ -506,11 +518,24 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str tp = "UTC"; break; } - if (vtm->zone == NULL) - tp = ""; - else + if (vtm->zone == NULL) { + i = 0; + } + else { tp = vtm->zone; - i = strlen(tp); + if (enc) { + for (i = 0; i < TBUFSIZE && tp[i]; i++) { + if ((unsigned char)tp[i] > 0x7F) { + VALUE str = rb_str_conv_enc_opts(rb_str_new_cstr(tp), rb_locale_encoding(), enc, ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE, Qnil); + i = strlcpy(tbuf, RSTRING_PTR(str), TBUFSIZE); + tp = tbuf; + break; + } + } + } + else + i = strlen(tp); + } break; #ifdef SYSV_EXT @@ -782,15 +807,15 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str } size_t -rb_strftime(char *s, size_t maxsize, const char *format, const struct vtm *vtm, VALUE timev, int gmt) +rb_strftime(char *s, size_t maxsize, const char *format, rb_encoding *enc, const struct vtm *vtm, VALUE timev, int gmt) { - return rb_strftime_with_timespec(s, maxsize, format, vtm, timev, NULL, gmt); + return rb_strftime_with_timespec(s, maxsize, format, enc, vtm, timev, NULL, gmt); } size_t -rb_strftime_timespec(char *s, size_t maxsize, const char *format, const struct vtm *vtm, struct timespec *ts, int gmt) +rb_strftime_timespec(char *s, size_t maxsize, const char *format, rb_encoding *enc, const struct vtm *vtm, struct timespec *ts, int gmt) { - return rb_strftime_with_timespec(s, maxsize, format, vtm, Qnil, ts, gmt); + return rb_strftime_with_timespec(s, maxsize, format, enc, vtm, Qnil, ts, gmt); } /* isleap --- is a year a leap year? */ -- cgit v1.2.3