From: Nobuyoshi Nakada Date: 2008-01-23T19:32:03+09:00 Subject: [ruby-dev:33317] Re: Time#strftimeのエンコーディング なかだです。 At Wed, 23 Jan 2008 16:43:38 +0900, Kazuhiro NISHIYAMA wrote in [ruby-dev:33316]: > > とりあえずformat.encodingを無視するのはまずかろうと思われるので、 > > 前者にしておきました。strftimeが非ASCIIを返すことがあるとしても、 > > strftimeの終了時にはすでにformatと混じってしまっているわけで、ど > > うしたもんでしょうね。 > > strftime(format.encode(locale)).encode(format.encoding) > という感じでstrftimeにはlocaleのencodingでわたして > Time#strftimeの返値はformatのencodingになっていると > うれしい気がするのですが、どうでしょうか? こんなとこですか。 $ ./ruby --arch=.i386-mingw32 -Ke -ve 'p Time.now.strftime("\xc6\xfc\xcb\xdc/%Z")' ruby 1.9.0 (2008-01-23 revision 15187) [i386-mingw32] "日本/東京 (標準時)" Index: time.c =================================================================== --- time.c (revision 15187) +++ time.c (working copy) @@ -11,4 +11,5 @@ #include "ruby/ruby.h" +#include "ruby/encoding.h" #include #include @@ -2072,4 +2073,5 @@ time_strftime(VALUE time, VALUE format) long len; VALUE str; + rb_encoding *enc, *lenc; GetTimeval(time, tobj); @@ -2081,6 +2083,75 @@ time_strftime(VALUE time, VALUE format) fmt = RSTRING_PTR(format); len = RSTRING_LEN(format); + enc = rb_enc_get(format); + lenc = rb_locale_encoding(); if (len == 0) { rb_warning("strftime called with empty format string"); + str = rb_str_new(0, 0); + } + else if (enc != lenc && !rb_enc_str_asciionly_p(format)) { + VALUE strenc = rb_enc_from_encoding(enc), tmp; + const char *p = fmt, *pe = fmt + len, *start = p; + char *s; + int c, n; + + str = rb_enc_str_new(0, 0, enc); + while (p < pe) { + int n2 = 0; + start = p; + while ((c = rb_enc_ascget(p, pe, &n, enc)) != 0 && c != '%' && + (p += c < 0 ? rb_enc_mbclen(p, pe, enc) : n) < pe); + switch (c) { + case 0: + p += n; + break; + case '%': + if (p+n >= pe) { + p = pe; + } + else if (rb_enc_ascget(p+n, pe, &n2, enc) == '%') { + p += n; + n = n2; + c = -1; + } + break; + } + rb_str_cat(str, start, p - start); + p += n; + switch (c) { + case 0: + while ((c = rb_enc_ascget(p, pe, &n, enc)) == 0 && + (p += n) < pe); + break; + case '%': + start = p; + len = 1; + while ((c = rb_enc_ascget(p, pe, &n, enc)) > 0) { + p += n; + ++len; + if (ISALPHA(c)) break; + } + s = buf = ALLOC_N(char, len+1); + *s++ = '%'; + p = start; + while ((c = rb_enc_ascget(p, pe, &n, enc)) > 0) { + *s++ = c; + p += n; + if (ISALPHA(c)) break; + } + *s = '\0'; + s = buf; + buf = buffer; + len = rb_strftime(&buf, s, &tobj->tm); + free(s); + tmp = rb_enc_str_new(buf, len, lenc); + if (buf != buffer) { + free(buf); + buf = buffer; + } + tmp = rb_funcall(tmp, rb_intern("encode"), 1, strenc); + rb_str_append(str, tmp); + break; + } + } } else if (strlen(fmt) < len) { @@ -2088,5 +2159,5 @@ time_strftime(VALUE time, VALUE format) const char *p = fmt, *pe = fmt + len; - str = rb_str_new(0, 0); + str = rb_enc_str_new(0, 0, enc); while (p < pe) { len = rb_strftime(&buf, p, &tobj->tm); @@ -2100,12 +2171,10 @@ time_strftime(VALUE time, VALUE format) if (p > fmt) rb_str_cat(str, fmt, p - fmt); } - return str; } else { len = rb_strftime(&buf, RSTRING_PTR(format), &tobj->tm); + str = rb_enc_str_new(buf, len, enc); + if (buf != buffer) free(buf); } - str = rb_str_new(buf, len); - if (buf != buffer) free(buf); - rb_enc_copy(str, format); return str; } -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦