diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-10-18 10:36:20 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-10-18 10:36:20 +0000 |
commit | 3f0ec8887f3bc75a98fd3ec8926518b635c70b7b (patch) | |
tree | cd0f721ca0e03ccec39353962869b9a6e8477c93 /string.c | |
parent | 88aa8632741d027d1d2e58f8073d4ec90845499d (diff) | |
download | ruby-3f0ec8887f3bc75a98fd3ec8926518b635c70b7b.tar.gz |
* string.c (rb_external_str_new): a new function to convert from
external encoding to internal encoding. if something went
wrong, it returns a string with the external encoding.
* string.c (rb_external_str_new_with_enc): same as above besides
you can specify the source encoding.
* ruby.c (ruby_set_argv): use rb_external_str_new()
* ruby.c (set_arg0, ruby_script): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r-- | string.c | 54 |
1 files changed, 54 insertions, 0 deletions
@@ -472,6 +472,60 @@ rb_tainted_str_new_cstr(const char *ptr) RUBY_ALIAS_FUNCTION(rb_tainted_str_new2(const char *ptr), rb_tainted_str_new_cstr, (ptr)) #define rb_tainted_str_new2 rb_tainted_str_new_cstr +VALUE +rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *eenc) +{ + VALUE str; + rb_encoding *ienc; + + if (len == 0 && !ptr) len = strlen(ptr); + str = rb_tainted_str_new(ptr, len); + rb_enc_associate(str, eenc); + ienc = rb_default_internal_encoding(); + if (ienc) { + rb_econv_t *ec; + rb_econv_result_t ret; + VALUE newstr = rb_str_new(0, len); + long nlen = len; + const unsigned char *sp; + unsigned char *dp; + + retry: + ec = rb_econv_open_opts(eenc->name, ienc->name, 0, Qnil); + if (!ec) return str; + + sp = (unsigned char*)RSTRING_PTR(str); + dp = (unsigned char*)RSTRING_PTR(newstr); + ret = rb_econv_convert(ec, &sp, (unsigned char*)RSTRING_END(str), + &dp, (unsigned char*)RSTRING_END(newstr), 0); + rb_econv_close(ec); + switch (ret) { + case econv_destination_buffer_full: + /* destination buffer short */ + nlen *= 2; + rb_str_resize(newstr, nlen); + goto retry; + + case econv_finished: + nlen = dp - (unsigned char*)RSTRING_PTR(newstr); + rb_str_set_len(newstr, nlen); + rb_enc_associate(newstr, ienc); + return newstr; + + default: + /* some error, return original */ + return str; + } + } + return str; +} + +VALUE +rb_external_str_new(const char *ptr, long len) +{ + return rb_external_str_new_with_enc(ptr, len, rb_default_external_encoding()); +} + static VALUE str_replace_shared(VALUE str2, VALUE str) { |