lib/protocol/http/body/stream.rb in protocol-http-0.39.0 vs lib/protocol/http/body/stream.rb in protocol-http-0.40.0
- old
+ new
@@ -189,12 +189,66 @@
end
# Read a single line from the stream.
#
# @parameter separator [String] The line separator, defaults to `\n`.
+ # @parameter limit [Integer] The maximum number of bytes to read.
# @parameter *options [Hash] Additional options, passed to {read_until}.
- def gets(separator = NEWLINE, **options)
- read_until(separator, **options)
+ def gets(separator = NEWLINE, limit = nil, chomp: false)
+ # If the separator is an integer, it is actually the limit:
+ if separator.is_a?(Integer)
+ limit = separator
+ separator = NEWLINE
+ end
+
+ # If no separator is given, this is the same as a read operation:
+ if separator.nil?
+ return read(limit)
+ end
+
+ # We don't want to split on the separator, so we subtract the size of the separator:
+ split_offset = separator.bytesize - 1
+
+ @buffer ||= read_next
+ return nil if @buffer.nil?
+
+ offset = 0
+ until index = @buffer.index(separator, offset)
+ offset = @buffer.bytesize - split_offset
+ offset = 0 if offset < 0
+
+ # If we have gone past the limit, we are done:
+ if limit and offset >= limit
+ @buffer.freeze
+ matched = @buffer.byteslice(0, limit)
+ @buffer = @buffer.byteslice(limit, @buffer.bytesize)
+ return matched
+ end
+
+ # Read more data:
+ if chunk = read_next
+ @buffer << chunk
+ else
+ # No more data could be read, return the remaining data:
+ buffer = @buffer
+ @buffer = nil
+
+ return @buffer
+ end
+ end
+
+ # Freeze the buffer, as this enables us to use byteslice without generating a hidden copy:
+ @buffer.freeze
+
+ if limit and index > limit
+ line = @buffer.byteslice(0, limit)
+ @buffer = @buffer.byteslice(limit, @buffer.bytesize)
+ else
+ line = @buffer.byteslice(0, index+(chomp ? 0 : separator.bytesize))
+ @buffer = @buffer.byteslice(index+separator.bytesize, @buffer.bytesize)
+ end
+
+ return line
end
end
include Reader