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 --- string.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 14 deletions(-) (limited to 'string.c') 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