From 78baa98e69f741ba92823470ffb3875838c912ab Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 17 Oct 2015 04:55:47 +0000 Subject: string.c: rb_str_cat_conv_enc_opts * file.c (rb_file_expand_path_internal): concatenate converted string to the result instead of making converted string and append it. * string.c (rb_str_cat_conv_enc_opts): from rb_str_conv_enc_opts, separate function to concatenate with transcoding. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52147 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 18 +++++++++++++++++ file.c | 16 ++++++++------- internal.h | 2 ++ string.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index f337a504df..d9a3c598e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +Sat Oct 17 13:55:45 2015 Nobuyoshi Nakada + + * file.c (rb_file_expand_path_internal): concatenate converted + string to the result instead of making converted string and + append it. + + * string.c (rb_str_cat_conv_enc_opts): from rb_str_conv_enc_opts, + separate function to concatenate with transcoding. + +Sat Oct 17 13:55:32 2015 Nobuyoshi Nakada + + * file.c (rb_file_expand_path_internal): concatenate converted + string to the result instead of making converted string and + append it. + + * string.c (rb_str_cat_conv_enc_opts): from rb_str_conv_enc_opts, + separate function to concatenate with transcoding. + Sat Oct 17 13:19:10 2015 Nobuyoshi Nakada * ruby.c (load_file): unify each preparations and clean-ups by diff --git a/file.c b/file.c index 60975104f7..15ce4c1f4e 100644 --- a/file.c +++ b/file.c @@ -3604,14 +3604,16 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na ++p; wlen = (int)len; len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, NULL, 0, NULL, NULL); - BUFCHECK(bdiff + len >= buflen); - WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1, NULL, NULL); - if (tmp != result) { - rb_str_buf_cat(tmp, p, len); - tmp = rb_str_encode(tmp, rb_enc_from_encoding(enc), 0, Qnil); - len = RSTRING_LEN(tmp); + if (tmp == result) { BUFCHECK(bdiff + len >= buflen); - memcpy(p, RSTRING_PTR(tmp), len); + WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1, NULL, NULL); + } + else { + rb_str_modify_expand(tmp, len); + WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, RSTRING_PTR(tmp), len + 1, NULL, NULL); + rb_str_cat_conv_enc_opts(result, bdiff, RSTRING_PTR(tmp), len, + rb_utf8_encoding(), 0, Qnil); + BUFINIT(); rb_str_resize(tmp, 0); } p += len; diff --git a/internal.h b/internal.h index 232218634d..8f7ab96cd8 100644 --- a/internal.h +++ b/internal.h @@ -1101,6 +1101,8 @@ void rb_str_fill_terminator(VALUE str, const int termlen); VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg); #ifdef RUBY_ENCODING_H VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc); +VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, + rb_encoding *from, int ecflags, VALUE ecopts); #endif #define STR_NOEMBED FL_USER1 #define STR_SHARED FL_USER2 /* = ELTS_SHARED */ diff --git a/string.c b/string.c index 313825c504..99f0c1e9f8 100644 --- a/string.c +++ b/string.c @@ -802,17 +802,16 @@ rb_tainted_str_new_cstr(const char *ptr) return str; } +static VALUE str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, + rb_encoding *from, rb_encoding *to, + int ecflags, VALUE ecopts); + VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts) { - rb_econv_t *ec; - rb_econv_result_t ret; - long len, olen; - VALUE econv_wrapper; + long len; + const char *ptr; VALUE newstr; - const unsigned char *start, *sp; - unsigned char *dest, *dp; - size_t converted_output = 0; if (!to) return str; if (!from) from = rb_enc_get(str); @@ -826,18 +825,60 @@ rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, return str; } - len = RSTRING_LEN(str); - newstr = rb_str_new(0, len); + RSTRING_GETMEM(str, ptr, len); + newstr = str_cat_conv_enc_opts(rb_str_buf_new(len), 0, ptr, len, + from, to, ecflags, ecopts); + if (NIL_P(newstr)) { + /* some error, return original */ + return str; + } OBJ_INFECT(newstr, str); - olen = len; + return newstr; +} + +VALUE +rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, + rb_encoding *from, int ecflags, VALUE ecopts) +{ + long olen; + + olen = RSTRING_LEN(newstr); + if (ofs < -olen || olen <= ofs) + rb_raise(rb_eIndexError, "index %ld out of string", ofs); + if (ofs < 0) ofs += olen; + if (!from) { + STR_SET_LEN(newstr, ofs); + return rb_str_cat(newstr, ptr, len); + } + + rb_str_modify(newstr); + return str_cat_conv_enc_opts(newstr, ofs, ptr, len, from, + rb_enc_get(newstr), + ecflags, ecopts); +} + +static VALUE +str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, + rb_encoding *from, rb_encoding *to, + int ecflags, VALUE ecopts) +{ + rb_econv_t *ec; + rb_econv_result_t ret; + long olen; + VALUE econv_wrapper; + const unsigned char *start, *sp; + unsigned char *dest, *dp; + size_t converted_output = (size_t)ofs; + + olen = rb_str_capacity(newstr); econv_wrapper = rb_obj_alloc(rb_cEncodingConverter); RBASIC_CLEAR_CLASS(econv_wrapper); ec = rb_econv_open_opts(from->name, to->name, ecflags, ecopts); - if (!ec) return str; + if (!ec) return Qnil; DATA_PTR(econv_wrapper) = ec; - sp = (unsigned char*)RSTRING_PTR(str); + sp = (unsigned char*)ptr; start = sp; while ((dest = (unsigned char*)RSTRING_PTR(newstr)), (dp = dest + converted_output), @@ -869,8 +910,7 @@ rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, return newstr; default: - /* some error, return original */ - return str; + return Qnil; } } -- cgit v1.2.3