diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-10-20 08:05:44 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-10-20 08:05:44 +0000 |
commit | 6259c87d02fce0a77ac90b6786ed1f2bc5baea32 (patch) | |
tree | 941121f72d4e32b756acdc1c2a1c4f7a0cb849a3 /string.c | |
parent | 52b3e3b97f42498c1f30984cb1e174422c235c80 (diff) | |
download | ruby-6259c87d02fce0a77ac90b6786ed1f2bc5baea32.tar.gz |
* include/ruby/ruby.h (ExportStringValue): new macro to convert
string in internal encoding to external to export.
* string.c (rb_str_export): new function to do conversion to
external encoding.
* ext/sdbm/init.c: encoding conversion support.
* ext/dbm/dbm.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r-- | string.c | 97 |
1 files changed, 59 insertions, 38 deletions
@@ -472,52 +472,61 @@ 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 +static VALUE +str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to) +{ + rb_econv_t *ec; + rb_econv_result_t ret; + long len; + VALUE newstr; + const unsigned char *sp; + unsigned char *dp; + + if (!to) return str; + if (from == to) return str; + if (rb_enc_asciicompat(to) && ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) + return str; + + len = RSTRING_LEN(str); + newstr = rb_str_new(0, len); + + retry: + ec = rb_econv_open_opts(from->name, to->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 */ + len *= 2; + rb_str_resize(newstr, len); + goto retry; + + case econv_finished: + len = dp - (unsigned char*)RSTRING_PTR(newstr); + rb_str_set_len(newstr, len); + rb_enc_associate(newstr, to); + return newstr; + + default: + /* some error, return original */ + return str; + } +} + 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; + return str_conv_enc(str, eenc, rb_default_internal_encoding()); } VALUE @@ -532,6 +541,18 @@ rb_locale_str_new(const char *ptr, long len) return rb_external_str_new_with_enc(ptr, len, rb_locale_encoding()); } +VALUE +rb_str_export(VALUE str) +{ + return str_conv_enc(str, STR_ENC_GET(str), rb_default_external_encoding()); +} + +VALUE +rb_str_export_to_enc(VALUE str, rb_encoding *enc) +{ + return str_conv_enc(str, STR_ENC_GET(str), enc); +} + static VALUE str_replace_shared(VALUE str2, VALUE str) { |