Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IO#getb_to_end #11830

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions spec/std/io/io_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,21 @@ describe IO do
io = SimpleIOMemory.new("foo\nbar\nbaz\n")
io.gets.should eq("foo")
io.gets_to_end.should eq("bar\nbaz\n")
io.gets_to_end.should eq("")
end

it "reads all remaining content as bytes" do
io = SimpleIOMemory.new(Bytes[0, 1, 3, 6, 10, 15])
io.getb_to_end.should eq(Bytes[0, 1, 3, 6, 10, 15])
io.getb_to_end.should eq(Bytes.new(0))
io.rewind
bytes = io.getb_to_end
bytes.should eq(Bytes[0, 1, 3, 6, 10, 15])
bytes.read_only?.should be_false

io.rewind
io.write(Bytes[2, 4, 5])
bytes.should eq(Bytes[0, 1, 3, 6, 10, 15])
end

it "reads char" do
Expand Down
17 changes: 17 additions & 0 deletions spec/std/io/memory_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,23 @@ describe IO::Memory do
io.gets_to_end.should eq("")
end

it "consumes with getb_to_end" do
io = IO::Memory.new(Bytes[0, 1, 3, 6, 10, 15])
io.getb_to_end.should eq(Bytes[0, 1, 3, 6, 10, 15])
io.getb_to_end.should eq(Bytes.new(0))
io.seek(3)
bytes = io.getb_to_end
bytes.should eq(Bytes[6, 10, 15])
bytes.read_only?.should be_false

io.seek(3)
io.write(Bytes[2, 4, 5])
bytes.should eq(Bytes[6, 10, 15])

io.seek(10)
io.getb_to_end.should eq(Bytes.new(0))
end

it "peeks" do
str = "hello world"
io = IO::Memory.new(str)
Expand Down
16 changes: 15 additions & 1 deletion src/io.cr
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ require "c/errno"
# An `IO` can be set an encoding with the `#set_encoding` method. When this is
# set, all string operations (`gets`, `gets_to_end`, `read_char`, `<<`, `print`, `puts`
# `printf`) will write in the given encoding, and read from the given encoding.
# Byte operations (`read`, `write`, `read_byte`, `write_byte`) never do
# Byte operations (`read`, `write`, `read_byte`, `write_byte`, `getb_to_end`) never do
# encoding/decoding operations.
#
# If an encoding is not set, the default one is UTF-8.
Expand Down Expand Up @@ -546,6 +546,7 @@ abstract class IO
# ```
# io = IO::Memory.new "hello world"
# io.gets_to_end # => "hello world"
# io.gets_to_end # => ""
# ```
def gets_to_end : String
String.build do |str|
Expand All @@ -565,6 +566,19 @@ abstract class IO
end
end

# Reads the rest of this `IO` data as a writable `Bytes`.
#
# ```
# io = IO::Memory.new Bytes[0, 1, 3, 6, 10, 15]
# io.getb_to_end # => Bytes[0, 1, 3, 6, 10, 15]
# io.getb_to_end # => Bytes[]
# ```
def getb_to_end : Bytes
io = IO::Memory.new
IO.copy(self, io)
io.to_slice
end

# Reads a line from this `IO`. A line is terminated by the `\n` character.
# Returns `nil` if called at the end of this `IO`.
#
Expand Down
24 changes: 18 additions & 6 deletions src/io/memory.cr
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,31 @@ class IO::Memory < IO
@pos = @bytesize
end

# :inherit:
def gets_to_end : String
return super if @encoding

check_open

pos = Math.min(@pos, @bytesize)

if pos == @bytesize
if @pos >= @bytesize
""
else
String.new(@buffer + @pos, @bytesize - @pos).tap do
@pos = @bytesize
end
str = String.new(@buffer + @pos, @bytesize - @pos)
@pos = @bytesize
str
end
end

# :inherit:
def getb_to_end : Bytes
check_open

if @pos >= @bytesize
Bytes.new(0)
else
bytes = Slice.new(@buffer + @pos, @bytesize - @pos).dup
@pos = @bytesize
bytes
end
end

Expand Down