Skip to content

Commit

Permalink
strio_read: preserve buffer encoding on partial reads (#95)
Browse files Browse the repository at this point in the history
[[Bug #20418]](https://bugs.ruby-lang.org/issues/20418)

Ruby IO#read preserves the encoding on partial read, but change it when
reading the whole IO

from commit ruby/ruby@0ca7036:
> * io.c (read_all): should associate default external encoding.
> * io.c (io_read): should NOT associate default external encoding.

Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
  • Loading branch information
casperisfine and byroot committed Apr 17, 2024
1 parent 0da5b72 commit 073172d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 7 deletions.
5 changes: 2 additions & 3 deletions ext/stringio/stringio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1623,10 +1623,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
if (len > rest) len = rest;
rb_str_resize(str, len);
MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
if (binary)
rb_enc_associate(str, rb_ascii8bit_encoding());
else
if (!binary) {
rb_enc_copy(str, ptr->string);
}
}
ptr->pos += RSTRING_LEN(str);
return str;
Expand Down
20 changes: 16 additions & 4 deletions test/stringio/test_stringio.rb
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,18 @@ def test_read
s.force_encoding(Encoding::US_ASCII)
assert_same(s, f.read(nil, s))
assert_string("", Encoding::UTF_8, s, bug13806)

bug20418 = '[Bug #20418] ™€®'.b
f = StringIO.new(bug20418)
s = ""
assert_equal(Encoding::UTF_8, s.encoding, bug20418)
f.read(4, s)
assert_equal(Encoding::UTF_8, s.encoding, bug20418)

f.rewind
s = ""
f.read(nil, s)
assert_equal(Encoding::ASCII_8BIT, s.encoding, bug20418)
end

def test_readpartial
Expand All @@ -711,8 +723,8 @@ def test_readpartial
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size))
f.rewind
# not empty buffer
s = '0123456789'
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size, s))
s = '0123456789'.b
assert_equal("\u3042\u3044".b, f.readpartial(f.size, s))
end

def test_read_nonblock
Expand All @@ -736,8 +748,8 @@ def test_read_nonblock_no_exceptions
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size))
f.rewind
# not empty buffer
s = '0123456789'
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size, s))
s = '0123456789'.b
assert_equal("\u3042\u3044".b, f.read_nonblock(f.size, s))
end

def test_sysread
Expand Down

0 comments on commit 073172d

Please sign in to comment.