diff options
author | Jeremy Evans <code@jeremyevans.net> | 2022-05-26 13:25:22 -0700 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2022-07-21 08:02:32 -0700 |
commit | 423b41cba77719b4f62aa530593ad36a990f7c74 (patch) | |
tree | 546b853d2bd8396719d426262436c0e4215b9a5b | |
parent | cdbb9b8555b4ddcc4c557f25ad785cae6209478d (diff) |
Make String#each_line work correctly with paragraph separator and chomp
Previously, it was including one newline when chomp was used,
which is inconsistent with IO#each_line behavior. This makes
behavior consistent with IO#each_line, chomping all paragraph
separators (multiple consecutive newlines), but not single
newlines.
Partially Fixes [Bug #18768]
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5960
-rw-r--r-- | string.c | 9 | ||||
-rw-r--r-- | test/ruby/test_string.rb | 17 |
2 files changed, 18 insertions, 8 deletions
@@ -8967,6 +8967,7 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary) const char *eol = NULL; subend = subptr; while (subend < pend) { + long chomp_rslen = 0; do { if (rb_enc_ascget(subend, pend, &n, enc) != '\r') n = 0; @@ -8974,7 +8975,10 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary) if (rb_enc_is_newline(subend + n, pend, enc)) { if (eol == subend) break; subend += rslen; - if (subptr) eol = subend; + if (subptr) { + eol = subend; + chomp_rslen = -rslen; + } } else { if (!subptr) subptr = subend; @@ -8983,8 +8987,9 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary) rslen = 0; } while (subend < pend); if (!subptr) break; + if (rslen == 0) chomp_rslen = 0; line = rb_str_subseq(str, subptr - ptr, - subend - subptr + (chomp ? 0 : rslen)); + subend - subptr + (chomp ? chomp_rslen : rslen)); if (ENUM_ELEM(ary, line)) { str_mod_check(str, ptr, len); } diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index d96e8dff22..d37924dec1 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1121,14 +1121,19 @@ CODE assert_equal(S("world"), res[1]) res = [] - S("hello\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x} - assert_equal(S("hello\n"), res[0]) - assert_equal(S("world"), res[1]) + S("hello\n\n\nworld\n").each_line(S(''), chomp: true) {|x| res << x} + assert_equal(S("hello"), res[0]) + assert_equal(S("world\n"), res[1]) res = [] - S("hello\r\n\r\nworld").each_line(S(''), chomp: true) {|x| res << x} - assert_equal(S("hello\r\n"), res[0]) - assert_equal(S("world"), res[1]) + S("hello\r\n\r\nworld\r\n").each_line(S(''), chomp: true) {|x| res << x} + assert_equal(S("hello"), res[0]) + assert_equal(S("world\r\n"), res[1]) + + res = [] + S("hello\r\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x} + assert_equal(S("hello"), res[0]) + assert_equal(S("world"), res[1]) res = [] S("hello!world").each_line(S('!'), chomp: true) {|x| res << x} |