From e4f3a2a3c979fbcdbe39af92f63a25b5324ed2d5 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 16 Mar 2022 13:00:33 +0100 Subject: [PATCH] Implement `chomp:` option for `gets`, `readline`, `readlines`, `each_line` It was added to IO methods in Ruby 2.4, but OpenSSL sockets don't have them, so any code accepting SSL sockets can't make use of it. Ref: https://github.com/ruby/ruby/commit/a2144bd72aad7c25e160cf283f957d59fe7c90b2 --- lib/openssl/buffering.rb | 18 ++++++++++-------- test/openssl/test_pair.rb | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lib/openssl/buffering.rb b/lib/openssl/buffering.rb index d47e1082e..2c8cd093a 100644 --- a/lib/openssl/buffering.rb +++ b/lib/openssl/buffering.rb @@ -232,7 +232,7 @@ def read_nonblock(maxlen, buf=nil, exception: true) # # Unlike IO#gets the separator must be provided if a limit is provided. - def gets(eol=$/, limit=nil) + def gets(eol=$/, limit=nil, chomp: false) idx = @rbuffer.index(eol) until @eof break if idx @@ -247,7 +247,9 @@ def gets(eol=$/, limit=nil) if size && limit && limit >= 0 size = [size, limit].min end - consume_rbuff(size) + str = consume_rbuff(size) + str.chomp!(eol) if chomp && str + str end ## @@ -256,8 +258,8 @@ def gets(eol=$/, limit=nil) # # See also #gets - def each(eol=$/) - while line = self.gets(eol) + def each(eol=$/, chomp: false) + while line = self.gets(eol, chomp: chomp) yield line end end @@ -268,9 +270,9 @@ def each(eol=$/) # # See also #gets - def readlines(eol=$/) + def readlines(eol=$/, chomp: false) ary = [] - while line = self.gets(eol) + while line = self.gets(eol, chomp: chomp) ary << line end ary @@ -281,9 +283,9 @@ def readlines(eol=$/) # # Raises EOFError if at end of file. - def readline(eol=$/) + def readline(eol=$/, chomp: false) raise EOFError if eof? - gets(eol) + gets(eol, chomp: chomp) end ## diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index 4249b4afb..2ec1bae86 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -115,6 +115,41 @@ def test_gets } end + def test_gets_chomp + ssl_pair {|s1, s2| + s1 << "abcd\r\n" * 50 + s1.close + + 50.times do + assert_equal "abcd", s2.gets(chomp: true) + end + } + end + + def test_gets_chomp_rs + rs = ":" + ssl_pair {|s1, s2| + s1 << "aaa:bbb" + s1.close + + assert_equal "aaa", s2.gets(rs, chomp: true) + assert_equal "bbb", s2.gets(rs, chomp: true) + assert_nil s2.gets(rs, chomp: true) + } + end + + def test_gets_chomp_default_rs + ssl_pair {|s1, s2| + s1 << "aaa\r\nbbb\nccc" + s1.close + + assert_equal "aaa", s2.gets(chomp: true) + assert_equal "bbb", s2.gets(chomp: true) + assert_equal "ccc", s2.gets(chomp: true) + assert_nil s2.gets + } + end + def test_gets_eof_limit ssl_pair {|s1, s2| s1.write("hello")