summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-10-17 04:55:47 (GMT)
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-10-17 04:55:47 (GMT)
commit78baa98e69f741ba92823470ffb3875838c912ab (patch)
tree15f33dd753ed7d23321d3116810d9586f0471bba /string.c
parentc72ddc4467971871fd7b35597663d0c1879f68c6 (diff)
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
Diffstat (limited to 'string.c')
-rw-r--r--string.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/string.c b/string.c
index 313825c..99f0c1e 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;
}
}