Skip to content

Commit

Permalink
Add support for read_until(limit:).
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Oct 14, 2024
1 parent c19735d commit f7d5f6a
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 5 deletions.
13 changes: 9 additions & 4 deletions lib/io/stream/generic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ def readpartial(size = nil)
end

# Efficiently read data from the stream until encountering pattern.
# @param pattern [String] The pattern to match.
# @return [String] The contents of the stream up until the pattern, which is consumed but not returned.
def read_until(pattern, offset = 0, chomp: true)
# @parameter pattern [String] The pattern to match.
# @parameter offset [Integer] The offset to start searching from.
# @parameter limit [Integer] The maximum number of bytes to read, including the pattern (even if chomped).
# @returns [String | Nil] The contents of the stream up until the pattern, which is consumed but not returned.
def read_until(pattern, offset = 0, limit: nil, chomp: true)
# We don't want to split on the pattern, so we subtract the size of the pattern.
split_offset = pattern.bytesize - 1

Expand All @@ -97,9 +99,12 @@ def read_until(pattern, offset = 0, chomp: true)

offset = 0 if offset < 0

return unless fill_read_buffer
return nil if limit and offset >= limit
return nil unless fill_read_buffer
end

return nil if limit and index >= limit

@read_buffer.freeze
matched = @read_buffer.byteslice(0, index+(chomp ? 0 : pattern.bytesize))
@read_buffer = @read_buffer.byteslice(index+pattern.bytesize, @read_buffer.bytesize)
Expand Down
12 changes: 11 additions & 1 deletion test/io/stream/buffered.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,17 @@
expect(client.read_until("\n")).to be == "world"
expect(client.read_until("\n")).to be_nil
end


it "can read with a limit" do
server.write("hello\nworld\n")
server.close

expect(client.read_until("\n", limit: 4)).to be_nil
expect(client.read_until("\n", limit: 5)).to be_nil
expect(client.read_until("\n", limit: 6)).to be == "hello"
expect(client.read_until("\n", limit: nil)).to be == "world"
end

with "with 1-byte block size" do
it "can read a line with a multi-byte pattern" do
server.write("hello\nworld\n")
Expand Down

0 comments on commit f7d5f6a

Please sign in to comment.