This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.
| Performing Random Access on "Read-Once" Input Streams | ||
|---|---|---|
| Code | Expected | Actual |
require 'socket'
require 'stringio'
sock = TCPSocket.open("www.example.com", 80)
sock.write("GET /\n")
file = StringIO.new(sock.read)
file.read(10) |
"<HTML>\r\n<H" | "<HTML>\r\n<H" |
file.rewind file.read(10) |
"<HTML>\r\n<H" | "<HTML>\r\n<H" |
file.pos = 90 file.read(15) |
" this web page " | " this web page " |
class BufferedIO
def initialize(io)
@buff = StringIO.new
@source = io
@pos = 0
end
def read(x=nil)
to_read = x ? to_read = x+@buff.pos-@buff.size : nil
_append(@source.read(to_read)) if !to_read or to_read > 0
@buff.read(x)
end
def pos=(x)
read(x-@buff.pos) if x > @buff.size
@buff.pos = x
end
def seek(x, whence=IO::SEEK_SET)
case whence
when IO::SEEK_SET then self.pos=(x)
when IO::SEEK_CUR then self.pos=(@buff.pos+x)
when IO::SEEK_END then read; self.pos=(@buff.size-x) # Note: this reads all the socket data.
end
pos
end
# Some methods can simply be delegated to the buffer.
["pos", "rewind", "tell"].each do |m|
module_eval "def #{m}\n@buff.#{m}\nend"
end
private
def _append(s)
@buff << s
@buff.pos -= s.size
end
end
sock = TCPSocket.open("www.example.com", 80)
sock.write("GET /\n")
file = BufferedIO.new(sock)
file.read(10) |
"<HTML>\r\n<H" | "<HTML>\r\n<H" |
file.rewind |
0 | 0 |
file.read(10) |
"<HTML>\r\n<H" | "<HTML>\r\n<H" |
file.pos = 90 |
90 | 90 |
file.read(15) |
" this web page " | " this web page " |
file.seek(-10, IO::SEEK_CUR) |
95 | 95 |
file.read(10) |
" web page " | " web page " |
class BufferedIO
def readline
oldpos = @buff.pos
line = @buff.readline unless @buff.eof?
if !line or line[-1] != ?\n
_append(@source.readline) # Finish the line
@buff.pos = oldpos # Go back to where we were
line = @buff.readline # Read the line again
end
line
end
end
file.readline |
"by typing "example.com",\r\n" | "by typing "example.com",\r\n" |