@@ -191,9 +191,63 @@ def read_until(pattern, offset = 0, chomp: false)
191
191
# Read a single line from the stream.
192
192
#
193
193
# @parameter separator [String] The line separator, defaults to `\n`.
194
+ # @parameter limit [Integer] The maximum number of bytes to read.
194
195
# @parameter *options [Hash] Additional options, passed to {read_until}.
195
- def gets ( separator = NEWLINE , **options )
196
- read_until ( separator , **options )
196
+ def gets ( separator = NEWLINE , limit = nil , chomp : false )
197
+ # If the separator is an integer, it is actually the limit:
198
+ if separator . is_a? ( Integer )
199
+ limit = separator
200
+ separator = NEWLINE
201
+ end
202
+
203
+ # If no separator is given, this is the same as a read operation:
204
+ if separator . nil?
205
+ return read ( limit )
206
+ end
207
+
208
+ # We don't want to split on the separator, so we subtract the size of the separator:
209
+ split_offset = separator . bytesize - 1
210
+
211
+ @buffer ||= read_next
212
+ return nil if @buffer . nil?
213
+
214
+ offset = 0
215
+ until index = @buffer . index ( separator , offset )
216
+ offset = @buffer . bytesize - split_offset
217
+ offset = 0 if offset < 0
218
+
219
+ # If we have gone past the limit, we are done:
220
+ if limit and offset >= limit
221
+ @buffer . freeze
222
+ matched = @buffer . byteslice ( 0 , limit )
223
+ @buffer = @buffer . byteslice ( limit , @buffer . bytesize )
224
+ return matched
225
+ end
226
+
227
+ # Read more data:
228
+ if chunk = read_next
229
+ @buffer << chunk
230
+ else
231
+ # No more data could be read, return the remaining data:
232
+ buffer = @buffer
233
+ @buffer = nil
234
+
235
+ return @buffer
236
+ end
237
+ end
238
+
239
+ # Freeze the buffer, as this enables us to use byteslice without generating a hidden copy:
240
+ @buffer . freeze
241
+
242
+ if limit and index > limit
243
+ line = @buffer . byteslice ( 0 , limit )
244
+ @buffer = @buffer . byteslice ( limit , @buffer . bytesize )
245
+ else
246
+ line = @buffer . byteslice ( 0 , index +( chomp ? 0 : separator . bytesize ) )
247
+ @buffer = @buffer . byteslice ( index +separator . bytesize , @buffer . bytesize )
248
+ end
249
+
250
+ return line
197
251
end
198
252
end
199
253
0 commit comments