summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--test/ruby/test_econv.rb21
-rw-r--r--transcode.c36
3 files changed, 54 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index dab168c311..17d2f7a5c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Aug 29 02:38:14 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (econv_primitive_convert): accept nil as
+ destination_bytesize for unlimited destination size.
+
Fri Aug 29 02:11:46 2008 Tanaka Akira <akr@fsij.org>
* transcode.c (econv_primitive_convert): accept nil as input for empty
diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb
index bc22da567d..7d6e78227b 100644
--- a/test/ruby/test_econv.rb
+++ b/test/ruby/test_econv.rb
@@ -79,12 +79,31 @@ class TestEncodingConverter < Test::Unit::TestCase
}
end
- def test_nil_input
+ def test_nil_source_buffer
ec = Encoding::Converter.new("UTF-8", "EUC-JP")
ret = ec.primitive_convert(nil, dst="", nil, 10)
assert_equal(:finished, ret)
end
+ def test_nil_destination_bytesize
+ ec = Encoding::Converter.new("Shift_JIS", "UTF-8")
+ n = 10000
+ src = "\xa1".force_encoding("Shift_JIS") * n
+ ret = ec.primitive_convert(src, dst="", nil, nil)
+ assert_equal(:finished, ret)
+ assert_equal("\xEF\xBD\xA1".force_encoding("UTF-8") * n, dst)
+ end
+
+ def test_nil_destination_bytesize_with_nonnli_byteoffset
+ ec = Encoding::Converter.new("Shift_JIS", "UTF-8")
+ n = 2000
+ src = "\xa1".force_encoding("Shift_JIS") * n
+ dst = "abcd" * 2000
+ ret = ec.primitive_convert(src, dst, 3, nil)
+ assert_equal(:finished, ret)
+ assert_equal("abc" + "\xEF\xBD\xA1".force_encoding("UTF-8") * n, dst)
+ end
+
def test_partial_input
ec = Encoding::Converter.new("UTF-8", "EUC-JP")
ret = ec.primitive_convert(src="", dst="", nil, 10, Encoding::Converter::PARTIAL_INPUT)
diff --git a/transcode.c b/transcode.c
index c6f7b73e6a..52c6d27ef8 100644
--- a/transcode.c
+++ b/transcode.c
@@ -2342,11 +2342,12 @@ econv_result_to_symbol(rb_econv_result_t res)
* source_buffer should be a string or nil.
* nil means a empty string.
*
- * adestination_buffer should be a string.
+ * destination_buffer should be a string.
*
* destination_byteoffset should be an integer or nil.
*
- * destination_bytesize and flags should be an integer.
+ * destination_bytesize and flags should be an integer or nil.
+ * nil means that unlimited.
*
* primitive_convert convert the content of source_buffer from beginning
* and store the result into destination_buffer.
@@ -2357,6 +2358,8 @@ econv_result_to_symbol(rb_econv_result_t res)
* If destination_byteoffset is nil,
* destination_buffer.bytesize is used for appending the result.
* destination_bytesize specifies maximum number of bytes.
+ * If destination_bytesize is nil,
+ * destination size is unlimited.
* After conversion, destination_buffer is resized to
* destination_byteoffset + actually converted number of bytes.
* Also destination_buffer's encoding is set to destination_encoding.
@@ -2407,14 +2410,17 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "41", &input, &output, &output_byteoffset_v, &output_bytesize_v, &flags_v);
- if (output_byteoffset_v == Qnil)
- output_byteoffset = 0;
+ if (NIL_P(output_byteoffset_v))
+ output_byteoffset = 0; /* dummy */
else
output_byteoffset = NUM2LONG(output_byteoffset_v);
- output_bytesize = NUM2LONG(output_bytesize_v);
+ if (NIL_P(output_bytesize_v))
+ output_bytesize = 0; /* dummy */
+ else
+ output_bytesize = NUM2LONG(output_bytesize_v);
- if (flags_v == Qnil)
+ if (NIL_P(flags_v))
flags = 0;
else
flags = NUM2INT(flags_v);
@@ -2424,7 +2430,15 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self)
StringValue(input);
rb_str_modify(output);
- if (output_byteoffset_v == Qnil)
+ if (NIL_P(output_bytesize_v)) {
+ output_bytesize = RSTRING_EMBED_LEN_MAX;
+ if (!NIL_P(input) && output_bytesize < RSTRING_LEN(input))
+ output_bytesize = RSTRING_LEN(input);
+ }
+
+ retry:
+
+ if (NIL_P(output_byteoffset_v))
output_byteoffset = RSTRING_LEN(output);
if (output_byteoffset < 0)
@@ -2462,6 +2476,14 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self)
if (!NIL_P(input))
rb_str_drop_bytes(input, ip - (unsigned char *)RSTRING_PTR(input));
+ if (NIL_P(output_bytesize_v) && res == econv_destination_buffer_full) {
+ if (LONG_MAX / 2 < output_bytesize)
+ rb_raise(rb_eArgError, "too long conversion result");
+ output_bytesize *= 2;
+ output_byteoffset_v = Qnil;
+ goto retry;
+ }
+
if (ec->destination_encoding) {
rb_enc_associate(output, ec->destination_encoding);
}