summaryrefslogtreecommitdiffstats
path: root/string.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-10-18 10:36:20 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-10-18 10:36:20 +0000
commit4fa2318b6f166bb16fd21901b7027647ae953d27 (patch)
treecd0f721ca0e03ccec39353962869b9a6e8477c93 /string.c
parent30fc916ecc75b3933530e6c97353681b7b3b4d47 (diff)
downloadruby-4fa2318b6f166bb16fd21901b7027647ae953d27.tar.gz
ruby-4fa2318b6f166bb16fd21901b7027647ae953d27.tar.xz
ruby-4fa2318b6f166bb16fd21901b7027647ae953d27.zip
* 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: http://svn.ruby-lang.org/repos/ruby/trunk@19834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/string.c b/string.c
index 601845c44..2b126934c 100644
--- a/string.c
+++ b/string.c
@@ -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)
{