[RCR] IO#readn

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

It's annoying to test for it in the application.

Regards,

  Michael

don't you think the code will be just as long/annoying with a begin/rescue
block?

-a

···

On Sun, 20 Jun 2004, Michael Neumann wrote:

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

It's annoying to test for it in the application.

Regards,

Michael

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it; and a weed grows, even though we do
not love it. --Dogen

===============================================================================

Michael Neumann wrote:

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

No, as I wouldn't use a rescue clause in this case. It's better to crash
early than proceed with a wrong value.

I never liked it that read(4) might return only 3 characters.

Regards,

  Michael

···

On Sun, Jun 20, 2004 at 01:33:18AM +0900, Ara.T.Howard wrote:

On Sun, 20 Jun 2004, Michael Neumann wrote:

>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
>
>It's annoying to test for it in the application.
>
>Regards,
>
> Michael

don't you think the code will be just as long/annoying with a begin/rescue
block?

[snip]

I never liked it that read(4) might return only 3 characters.

Wouldn't it be better then to change the behavier of #read itself, so
it fails per default in case the specified number of bytes cannot be read.

with ruby2 we should try to break as much as possible, and hopefully
get it right.

#readn smells too much like workaround :slight_smile:

···

On Saturday 19 June 2004 19:01, Michael Neumann wrote:

--
Simon Strandgaard

but another read may give one more byte - then you'd have your 4? even if one
implemented IO#read(n) i'd think you'd want:

   class IO
     def readn n
       buf = ''
       buf << read(n - buf.size) until buf.size == n
       buf
     end
   end

which give you what you want (n bytes), or throws EOFError.

-a

···

On Sun, 20 Jun 2004, Michael Neumann wrote:

On Sun, Jun 20, 2004 at 01:33:18AM +0900, Ara.T.Howard wrote:

On Sun, 20 Jun 2004, Michael Neumann wrote:

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

It's annoying to test for it in the application.

Regards,

Michael

don't you think the code will be just as long/annoying with a begin/rescue
block?

No, as I wouldn't use a rescue clause in this case. It's better to crash
early than proceed with a wrong value.

I never liked it that read(4) might return only 3 characters.

Regards,

Michael

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it; and a weed grows, even though we do
not love it. --Dogen

===============================================================================

Right. You have my vote for it!

But I fear, as #read resembles the UNIX read(2) syscall, this change
will not happen in Ruby2.

Regards,

  Michael

···

On Sun, Jun 20, 2004 at 02:07:51AM +0900, Simon Strandgaard wrote:

On Saturday 19 June 2004 19:01, Michael Neumann wrote:
[snip]
>
> I never liked it that read(4) might return only 3 characters.
>

Wouldn't it be better then to change the behavier of #read itself, so
it fails per default in case the specified number of bytes cannot be read.

with ruby2 we should try to break as much as possible, and hopefully
get it right.

I agree, a method called to read n bytes should raise an exception when it
cannot.

  Sean O'Dell

···

On Saturday 19 June 2004 10:07, Simon Strandgaard wrote:

On Saturday 19 June 2004 19:01, Michael Neumann wrote:
[snip]

> I never liked it that read(4) might return only 3 characters.

Wouldn't it be better then to change the behavier of #read itself, so
it fails per default in case the specified number of bytes cannot be read.

with ruby2 we should try to break as much as possible, and hopefully
get it right.

#readn smells too much like workaround :slight_smile:

[...]

I agree, a method called to read n bytes should raise an exception when it
cannot.

Except that the semantics of read() specify that _at most_ n bytes will
be read. There are important cases where you want these semantics, such
as when reading from a non-blocking socket or pipe or when reading a
file in chunks without wanting to bother to find out what exactly the
size of the last chunk will be (which can be impossible if the file is
not seekable).

    Reimer Behrends

···

Sean O'Dell (sean@celsoft.com) wrote:

Yep, you're right...I guess that would apply even in a scripted environment.

  Sean O'Dell

···

On Saturday 19 June 2004 11:58, Reimer Behrends wrote:

Sean O'Dell (sean@celsoft.com) wrote:
[...]

> I agree, a method called to read n bytes should raise an exception when
> it cannot.

Except that the semantics of read() specify that _at most_ n bytes will
be read. There are important cases where you want these semantics, such
as when reading from a non-blocking socket or pipe or when reading a
file in chunks without wanting to bother to find out what exactly the
size of the last chunk will be (which can be impossible if the file is
not seekable).

exactly. if don't like the way it works now, try writing code which reads
from network socket using a read(n) which throws exceptions. THAT will be
ugly...

-a

···

On Sat, 19 Jun 2004, Reimer Behrends wrote:

Sean O'Dell (sean@celsoft.com) wrote:
[...]

I agree, a method called to read n bytes should raise an exception when it
cannot.

Except that the semantics of read() specify that _at most_ n bytes will
be read. There are important cases where you want these semantics, such
as when reading from a non-blocking socket or pipe or when reading a
file in chunks without wanting to bother to find out what exactly the
size of the last chunk will be (which can be impossible if the file is
not seekable).

    Reimer Behrends

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it; and a weed grows, even though we do
not love it. --Dogen

===============================================================================