Michael said:
Hi,
I suggest to add a method readn to the IO class (and to StringIO,
Socket...), which behaves similar to read(n), but raises an exception if
the returned string is not of size n.
class IO
def readn(n)
str = read(n)
raise if str.nil? or str.size != n
str
end
end
Here's an option that gives the programmer the option of chosing whether
to to use "at most" or "exactly" semantics. As bonus, it also allows "at
least" and "0 or N, but nothing in between" semantics.
Also, since it doesn't accept a Fixnum argument, it forces the
programmer to be clear about the chosen semantics.
----
module ReadExt
def read_inclusive(enum = nil)
str = read(enum && enum.max)
str_size = str ? str.size : 0
if enum and not enum.include?(str_size)
raise RangeError
end
str
end
end
require 'stringio'
class IO; include ReadExt; end
class StringIO; include ReadExt; end
io = StringIO.new
io.write(('a'..'z').to_a)
io.rewind
p io.read_inclusive(20..30) # ==> "abcdefghijklmnopqrstuvwxyz"
p io.read_inclusive # ==> ""
begin
p io.read_inclusive(5..5)
rescue RangeError
puts "nothing left to read" # ==> nothing left to read
end
io.rewind
p io.read_inclusive(0..10) # ==> "abcdefghij"
io.rewind
p io.read_inclusive(20..20) # ==> "abcdefghijklmnopqrst"
begin
io.rewind
p io.read_inclusive(30..30)
rescue RangeError
puts "alphabet underflow" # ==> alphabet underflow
end
io.rewind
p io.read_inclusive # ==> "abcdefghijklmnopqrstuvwxyz"
p io.read_inclusive(0..100) # ==> nil
io.rewind
3.times do
# automatically checks for "complete" blocks of 13
p io.read_inclusive([0,13])
# ==> "abcdefghijklm"
# ==> "nopqrstuvwxyz"
# ==> nil
end