module IO::Like_1_8_6

This module provides most of the basic input and output functions of IO objects as implemented in Ruby version 1.8.6. Its use is supported on all versions of Ruby. See the general documentation of IO::Like for a description of how to create a class capable of using this module.

Include this module explicitly rather than IO::Like if the including class should always behave like Ruby 1.8.6 IO no matter what version of Ruby is running the class.

IO::Like is a module which provides most of the basic input and output functions of IO objects using methods named unbuffered_read, unbuffered_write, and unbuffered_seek.

The definition of this particular module is equivalent to whatever version-specific module provides the closest interface to the IO implementation of the Ruby interpreter running this library. For example, IO::Like will be equivalent to IO::Like_1_8_6 under Ruby version 1.8.6 while it will be equivalent to IO::Like_1_8_7 under Ruby version 1.8.7.

When considering any of the IO::Like modules for use in a class, the following documentation holds true.

Readers

In order to use this module to provide input methods, a class which includes it must provide the unbuffered_read method which takes one argument, a length, as follows:

def unbuffered_read(length)
  ...
end

This method must return at most length bytes as a String, raise EOFError if reading begins at the end of data, and raise SystemCallError on error. Errno::EAGAIN should be raised if there is no data to return immediately and the read operation should not block. Errno::EINTR should be raised if the read operation is interrupted before any data is read.

In 1.9 the returned string is expected to have ‘binary’ encoding.

Writers

In order to use this module to provide output methods, a class which includes it must provide the unbuffered_write method which takes a single string argument as follows:

def unbuffered_write(string)
  ...
end

In 1.9 the supplied string argument will have ‘binary’ encoding.

This method must either return the number of bytes written to the stream, which may be less than the length of string in bytes, OR must raise an instance of SystemCallError. Errno::EAGAIN should be raised if no data can be written immediately and the write operation should not block. Errno::EINTR should be raised if the write operation is interrupted before any data is written.

Seekers

In order to use this module to provide seeking methods, a class which includes it must provide the unbuffered_seek method which takes two required arguments, an offset and a start position, as follows:

def unbuffered_seek(offset, whence)
  ...
end

This method must return the new position within the data stream relative to the beginning of the stream and should raise SystemCallError on error. offset can be any integer and whence can be any of IO::SEEK_SET, IO::SEEK_CUR, or IO::SEEK_END. They are interpreted together as follows:

      whence | resulting position
-------------+------------------------------------------------------------
IO::SEEK_SET | Add offset to the position of the beginning of the stream.
-------------+------------------------------------------------------------
IO::SEEK_CUR | Add offset to the current position of the stream.
-------------+------------------------------------------------------------
IO::SEEK_END | Add offset to the position of the end of the stream.

Duplexed Streams

In order to create a duplexed stream where writing and reading happen independently of each other, override the duplexed? method to return true and then provide the unbuffered_read and unbuffered_write methods. Do NOT provide an unbuffered_seek method or the contents of the internal read and write buffers may be lost unexpectedly.


NOTE: Due to limitations of Ruby’s finalizer, IO::Like#close is not automatically called when the object is garbage collected, so it must be explicitly called when the object is no longer needed or risk losing whatever data remains in the internal write buffer.

Non-blocking Streams

As above unbuffered_read and unbuffered_write should raise Errno::EAGAIN if they should not block.

The read_nonblock and write_nonblock methods of IO::Like will attempt to call nonblock=(true) on the underlying stream before calling unbuffered_read or unbuffered_write. This is the equivalent of Ruby setting the O_NONBLOCK flag on traditional file descriptor based IO.

The default implementation of nonblock= raises Errno::EBADF. For streams where unbuffered_read is always non blocking this can be overridden with a no-op.

Nonblocking streams should also provide a more optimal implementation of read_ready? and write_ready? which by default simply calls Kernel.sleep(1) and is called by the blocking read and write methods in response to Errno::EAGAIN.

Public Instance Methods

ios << obj → ios click to toggle source

Writes obj to the stream using write and returns ios. obj is converted to a String using to_s.

   # File lib/io/like-1.8.6.rb
20 def <<(obj)
21   write(obj)
22   self
23 end
binmode → ios click to toggle source

Returns self. Just for compatibility with IO.

   # File lib/io/like-1.8.6.rb
29 def binmode
30   self
31 end
close → nil click to toggle source

Arranges for closed? to return true. Raises IOError if closed? already returns true. For duplexed objects, calls close_read and close_write. For non-duplexed objects, calls flush if writable? returns true and then sets a flag so that closed? will return true.

   # File lib/io/like-1.8.6.rb
41 def close
42   raise IOError, 'closed stream' if closed?
43   __io_like__close_read
44   flush if writable?
45   __io_like__close_write
46   nil
47 end
close_read → nil click to toggle source

Closes the read end of a duplexed object or the whole object if the object is read-only.

Raises IOError if closed? returns true. Raises IOError for duplexed objects if called more than once. Raises IOError for non-duplexed objects if writable? returns true.

   # File lib/io/like-1.8.6.rb
59 def close_read
60   raise IOError, 'closed stream' if closed?
61   if __io_like__closed_read? || ! duplexed? && writable? then
62     raise IOError, 'closing non-duplex IO for reading'
63   end
64   if duplexed? then
65     __io_like__close_read
66   else
67     close
68   end
69   nil
70 end
close_write → nil click to toggle source

Closes the write end of a duplexed object or the whole object if the object is write-only.

Raises IOError if closed? returns true. Raises IOError for duplexed objects if called more than once. Raises IOError for non-duplexed objects if readable? returns true.

   # File lib/io/like-1.8.6.rb
82 def close_write
83   raise IOError, 'closed stream' if closed?
84   if __io_like__closed_write? || ! duplexed? && readable? then
85     raise IOError, 'closing non-duplex IO for reading'
86   end
87   if duplexed? then
88     flush
89     __io_like__close_write
90   else
91     close
92   end
93   nil
94 end
closed? → true or false click to toggle source

Returns true if this object is closed or otherwise unusable for read and write operations.

    # File lib/io/like-1.8.6.rb
101 def closed?
102   (__io_like__closed_read? || ! readable?) &&
103   (__io_like__closed_write? || ! writable?)
104 end
duplexed? → true or false click to toggle source

Returns false. Override this to return true when creating duplexed IO objects.

    # File lib/io/like-1.8.6.rb
111 def duplexed?
112   false
113 end
each(sep_string = $/) { |line| block } → ios
Alias for: each_line
each_byte { |byte| block } → ios click to toggle source

Reads each byte (0..255) from the stream using getc and calls the given block once for each byte, passing the byte as an argument.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks. Aside from that exception and the conversion of EOFError results into nil results, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
127 def each_byte
128   while (byte = getc) do
129     yield(byte)
130   end
131   self
132 end
each_line(sep_string = $/) { |line| block } → ios click to toggle source

Reads each line from the stream using gets and calls the given block once for each line, passing the line as an argument.

NOTE: When sep_string is not nil, this method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks. Aside from that exception and the conversion of EOFError results into nil results, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
147 def each_line(sep_string = $/)
148   while (line = gets(sep_string)) do
149     yield(line)
150   end
151   self
152 end
Also aliased as: each
eof → true or false
Alias for: eof?
eof? → true or false click to toggle source

Returns true if there is no more data to read.

This works by using getc to fetch the next character and using ungetc to put the character back if one was fetched. It may be a good idea to replace this implementation in derivative classes.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks. Aside from that exception and the conversion of EOFError results into nil results, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
171 def eof?
172   if (char = getc) then
173     ungetc(char)
174     return false
175   end
176   true
177 end
Also aliased as: eof
fcntl click to toggle source

Raises NotImplementedError.

    # File lib/io/like-1.8.6.rb
184 def fcntl(*args)
185   raise NotImplementedError, 'not implemented'
186 end
fileno → nil click to toggle source

Returns nil. Just for compatibility with IO.

    # File lib/io/like-1.8.6.rb
192 def fileno
193   nil
194 end
fill_size → integer click to toggle source

Returns the number of bytes to read as a block whenever the internal buffer needs to be refilled. Unless set explicitly via fill_size=, this defaults to 4096.

Raises IOError if closed? returns true. Raises IOError if the stream is not opened for reading.

    # File lib/io/like-1.8.6.rb
205 def fill_size
206   raise IOError, 'closed stream' if closed?
207   raise IOError, 'not opened for reading' unless readable?
208 
209   @__io_like__fill_size ||= 4096
210 end
fill_size = integer → integer click to toggle source

Sets the number of bytes to read as a block whenever the internal read buffer needs to be refilled. The new value must be a number greater than or equal to 0. Setting this to 0 effectively disables buffering.

Raises IOError if closed? returns true. Raises IOError if the stream is not opened for reading.

    # File lib/io/like-1.8.6.rb
222 def fill_size=(fill_size)
223   raise IOError, 'closed stream' if closed?
224   raise IOError, 'not opened for reading' unless readable?
225 
226   unless fill_size >= 0 then
227     raise ArgumentError, "non-positive fill_size #{fill_size} given"
228   end
229   @__io_like__fill_size = fill_size
230 end
flush → ios click to toggle source

Flushes the internal write buffer to the underlying data stream.

Regardless of the blocking status of the data stream or interruptions during writing, this method will block until either all the data is flushed or until an error is raised.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_write. Therefore, this method always blocks if unable to flush the internal write buffer. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_write.

    # File lib/io/like-1.8.6.rb
249 def flush
250   begin
251     __io_like__buffered_flush
252   rescue Errno::EAGAIN, Errno::EINTR
253     retry if write_ready?
254   end
255   self
256 end
flush_size → integer click to toggle source

Returns the number of bytes at which the internal write buffer is flushed automatically to the data stream. Unless set explicitly via flush_size=, this defaults to 4096.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

    # File lib/io/like-1.8.6.rb
267 def flush_size
268   raise IOError, 'closed stream' if closed?
269   raise IOError, 'not opened for writing' unless writable?
270 
271   @__io_like__flush_size ||= 4096
272 end
flush_size = integer → integer click to toggle source

Sets the number of bytes at which the internal write buffer is flushed automatically to the data stream. The new value must be a number greater than or equal to 0. Setting this to 0 effectively disables buffering.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

    # File lib/io/like-1.8.6.rb
284 def flush_size=(flush_size)
285   raise IOError, 'closed stream' if closed?
286   raise IOError, 'not opened for writing' unless writable?
287 
288   unless flush_size >= 0 then
289     raise ArgumentError, "non-positive flush_size #{flush_size} given"
290   end
291   @__io_like__flush_size = flush_size
292 end
fsync click to toggle source

Flush data to disk, default is not supported

    # File lib/io/like-1.8.6.rb
298 def fsync()
299   nil
300 end
getc → nil or integer click to toggle source

Calls readchar and either returns the result or nil if readchar raises EOFError.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true. Raises all errors raised by unbuffered_read except for EOFError.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks. Aside from that exception and the conversion of EOFError results into nil results, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
318 def getc
319   readchar
320 rescue EOFError
321   nil
322 end
gets(sep_string = $/) → nil or string click to toggle source

Calls readline with sep_string as an argument and either returns the result or nil if readline raises EOFError. If readline returns some data, $. is set to the value of lineno.

NOTE: Due to limitations of MRI up to version 1.9.x when running managed (Ruby) code, this method fails to set $_ to the returned data; however, other implementations may allow it.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true. Raises all errors raised by unbuffered_read except for EOFError.

NOTE: When sep_string is not nil, this method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method will always block in that case. Aside from that exception, this method will raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
345 def gets(sep_string = $/)
346   # Set the last read line in the global.
347   $_ = readline(sep_string)
348   # Set the last line number in the global.
349   $. = lineno
350   # Return the last read line.
351   $_
352 rescue EOFError
353   nil
354 end
isatty → false click to toggle source

Returns false. Just for compatibility with IO.

Raises IOError if closed? returns true.

    # File lib/io/like-1.8.6.rb
362 def isatty
363   raise IOError, 'closed stream' if closed?
364   false
365 end
Also aliased as: tty?
lineno → integer click to toggle source

Returns the number of times gets was called and returned non-nil data. By default this is the number of lines read, but calling gets or any of the other line-based reading methods with a non-default value for sep_string or after changing $/ will affect this.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

    # File lib/io/like-1.8.6.rb
379 def lineno
380   raise IOError, 'closed stream' if closed?
381   raise IOError, 'not opened for reading' unless readable?
382   @__io_like__lineno ||= 0
383 end
lineno = lineno → lineno click to toggle source

Sets the current line number to the given value. $. is updated by the next call to gets. If the object given is not an Integer, it is converted to one using its to_int method.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

    # File lib/io/like-1.8.6.rb
395 def lineno=(integer)
396   raise IOError, 'closed stream' if closed?
397   raise IOError, 'not opened for reading' unless readable?
398   if integer.nil? then
399     raise TypeError, 'no implicit conversion from nil to integer'
400   elsif ! integer.respond_to?(:to_int) then
401     raise TypeError, "can't convert #{integer.class} into Integer"
402   end
403   @__io_like__lineno = integer.to_int
404 end
nonblock=(blocking_mode) click to toggle source

read_nonblock, write_nonblock will call nonblock=(true) prior to calling unbuffered_read or unbuffered_write

The default implementation raises Errno::EBADF to indicate that nonblocking operations are not supported. IO implementations that are always nonblocking should override with a no-op

    # File lib/io/like-1.8.6.rb
415 def nonblock=(blocking_mode)
416   raise Errno::EBADF
417 end
path → nil click to toggle source

Returns nil. Just for compatibility with IO.

    # File lib/io/like-1.8.6.rb
423 def path
424   nil
425 end
pos → integer click to toggle source

Returns the current offest of ios.

Raises IOError if closed? returns true. Raises Errno::ESPIPE unless seekable? returns true.

As a side effect, the internal write buffer is flushed unless this is a writable, non-duplexed object. This is for compatibility with the behavior of IO#pos.

NOTE: Because this method relies on unbuffered_seek and unbuffered_write (when the internal write buffer is not empty), it will also raise the same errors and block at the same times as those functions.

    # File lib/io/like-1.8.6.rb
460 def pos
461   # Flush the internal write buffer for writable, non-duplexed objects.
462   __io_like__buffered_flush if writable? && ! duplexed?
463   __io_like__buffered_seek(0, IO::SEEK_CUR)
464 end
Also aliased as: tell
pos = position → position click to toggle source

Sets the data position to position by calling seek.

As a side effect, the internal read and write buffers are flushed.

Raises IOError if closed? returns true. Raises Errno::ESPIPE unless seekable? returns true.

NOTE: Because this method relies on unbuffered_seek and unbuffered_write (when the internal write buffer is not empty), it will also raise the same errors and block at the same times as those functions.

    # File lib/io/like-1.8.6.rb
440 def pos=(position)
441   seek(position, IO::SEEK_SET)
442   position
443 end
print([obj, ...]) → nil click to toggle source

Writes the given object(s), if any, to the stream using write after converting them to strings by calling their to_s methods. If no objects are given, $_ is used. The field separator ($,) is written between successive objects if it is not nil. The output record separator ($\) is written after all other data if it is not nil.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_write. Therefore, this method always blocks if unable to immediately write [obj, ...] completely. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_write.

printf(format_string [, obj, ...]) → nil click to toggle source

Writes the String returned by calling Kernel.sprintf using the given arguments.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_write. Therefore, this method always blocks if unable to immediately write its arguments completely. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_write.

    # File lib/io/like-1.8.6.rb
526 def printf(*args)
527   write(sprintf(*args))
528   nil
529 end
putc(obj) → obj click to toggle source

If obj is a String, write the first byte; otherwise, convert obj to an Integer using its to_int method and write the low order byte.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_write. Therefore, this method always blocks if unable to immediately write obj completely. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_write.

    # File lib/io/like-1.8.6.rb
546 def putc(obj)
547   char = case obj
548          when String
549            obj[0].chr
550          else
551            raise TypeError unless obj.respond_to?(:to_int)
552            [obj.to_int].pack('V')[0].chr
553          end
554   write(char)
555   obj
556 end
puts([obj, ...]) → nil click to toggle source

Writes the given object(s), if any, to the stream using write after converting them to strings using their to_s methods. Unlike print, Array instances are recursively processed. A record separator character is written after each object which does not end with the record separator already. If no objects are given, a single record separator is written.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_write. Therefore, this method always blocks if unable to immediately write [obj, ...] completely. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_write.

NOTE: In order to be compatible with IO#puts, the record separator is currently hardcoded to be a single newline ("\n") even though the documentation implies that the output record separator ($\) should be used.

    # File lib/io/like-1.8.6.rb
582 def puts(*args)
583   # Set the output record separator such that this method is compatible with
584   # IO#puts.
585   ors = "\n"
586 
587   # Write only the record separator if no arguments are given.
588   if args.length == 0 then
589     write(ors)
590     return
591   end
592 
593   # Write each argument followed by the record separator.  Recursively
594   # process arguments which are Array instances.
595   __io_like__array_flatten(args) do |string|
596       write(string || 'nil')
597       write(ors) if string.nil? || string.index(ors, -ors.length).nil?
598   end
599   nil
600 end
read([length[, buffer]]) → nil, buffer, or string click to toggle source

If length is specified and is a positive integer, at most length bytes are returned. Truncated data will occur if there is insufficient data left to fulfill the request. If the read starts at the end of data, nil is returned.

If length is unspecified or nil, an attempt to return all remaining data is made. Partial data will be returned if a low-level error is raised after some data is retrieved. If no data would be returned at all, an empty String is returned.

If buffer is specified, it will be converted to a String using its to_str method if necessary and will be filled with the returned data if any.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

NOTE: Because this method relies on unbuffered_read, it will also raise the same errors and block at the same times as that function.

    # File lib/io/like-1.8.6.rb
624 def read(length = nil, buffer = nil)
625   # Check the validity of the method arguments.
626   unless length.nil? || length >= 0 then
627     raise ArgumentError, "negative length #{length} given"
628   end
629   buffer = buffer.nil? ? '' : buffer.to_str
630   buffer.slice!(0..-1) unless buffer.empty?
631 
632   if length.nil? then
633     # Read and return everything.
634     begin
635       loop do
636         buffer << __io_like__buffered_read(4096)
637       end
638     rescue EOFError
639       # Ignore this.
640     rescue SystemCallError
641       # Reraise the error if there is nothing to return.
642       raise if buffer.empty?
643     end
644   else
645     # Read and return up to length bytes.
646     begin
647       buffer << __io_like__buffered_read(length)
648     rescue EOFError
649       # Return nil to the caller at end of file when requesting a specific
650       # amount of data.
651       return nil
652     end
653   end
654   buffer
655 end
read_nonblock(length[, buffer]) → string or buffer click to toggle source

Returns at most length bytes from the data stream using only the internal read buffer if the buffer is not empty.

If internal buffer is empty sets nonblocking mode via nonblock=(true) and then reads from the underlying stream

Raises Errno::EBADF if nonblocking mode is not supported Raises EOFError when there is no more data in the stream. Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

This method will raise errors directly from buffered_read to be handled by the caller.

    # File lib/io/like-1.8.6.rb
889 def read_nonblock(length, buffer = nil)
890   __io_like__readpartial(length, buffer, true)
891 end
read_ready? → true or false click to toggle source

Returns true when the stream may be read without error, false otherwise. This method will block until one of the conditions is known.

This default implementation of read_ready? is a hack which should be able to work for both real IO objects and IO-like objects; however, it is inefficient since it merely sleeps for 1 second and then returns true as long as readable? returns true. IO.select should be used for real IO objects to wait for a readable condition on platforms with support for IO.select. Other solutions should be found as necessary to improve this implementation on a case by case basis.

Basically, this method should be overridden in derivative classes.

    # File lib/io/like-1.8.6.rb
674 def read_ready?
675   return false unless readable?
676   sleep(1)
677   true
678 end
readable? → true or false click to toggle source

Returns true if the stream is both open and readable, false otherwise.

This implementation checks to see if unbuffered_read is defined in order to make its determination. Override this if the implementing class always provides the unbuffered_read method but may not always be open in a readable mode.

    # File lib/io/like-1.8.6.rb
690 def readable?
691   ! __io_like__closed_read? && respond_to?(:unbuffered_read, true)
692 end
readbytes(length) → string click to toggle source

Reads and returns length bytes from the data stream.

Raises EOFError if reading begins at the end of the stream. Raises IOError if closed? returns true. Raises IOError unless readable? returns true. Raises TruncatedDataError if insufficient data is immediately available to satisfy the request.

In the case of TruncatedDataError being raised, the retrieved data can be fetched from the data attribute of the exception.

This method is basically copied from IO#readbytes.

NOTE: Because this method relies on unbuffered_read, it will also raise the same errors and block at the same times as that function.

    # File lib/io/like-1.8.6.rb
712 def readbytes(length)
713   buffer = read(length)
714   if buffer.nil? then
715     raise EOFError, "end of file reached"
716   end
717   if buffer.length < length then
718     raise TruncatedDataError.new("data truncated", buffer)
719   end
720   buffer
721 end
readchar → integer click to toggle source

Returns the next 8-bit byte (0..255) from the stream.

Raises EOFError when there is no more data in the stream. Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
736 def readchar
737   __io_like__buffered_read(1)[0]
738 rescue Errno::EAGAIN, Errno::EINTR
739   retry if read_ready?
740 end
readline(sep_string = $/) → string click to toggle source

Returns the next line from the stream, where lines are separated by sep_string. Increments lineno by 1 for each call regardless of the value of sep_string.

If sep_string is not nil and not a String, it is first converted to a String using its to_str method and processing continues as follows.

If sep_string is nil, a line is defined as the remaining contents of the stream. Partial data will be returned if a low-level error of any kind is raised after some data is retrieved. This is equivalent to calling read without any arguments except that this method will raise an EOFError if called at the end of the stream.

If sep_string is an empty String, a paragraph is returned, where a paragraph is defined as data followed by 2 or more successive newline characters. A maximum of 2 newlines are returned at the end of the returned data. Fewer may be returned if the stream ends before at least 2 successive newlines are seen.

Any other value for sep_string is used as a delimiter to mark the end of a line. The returned data includes this delimiter unless the stream ends before the delimiter is seen.

In any case, the end of the stream terminates the current line.

Raises EOFError when there is no more data in the stream. Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

NOTE: When sep_string is not nil, this method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method will always block in that case. Aside from that exception, this method will raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
781 def readline(sep_string = $/)
782   # Ensure that sep_string is either nil or a String.
783   unless sep_string.nil? || sep_string.kind_of?(String) then
784     sep_string = sep_string.to_str
785   end
786 
787   buffer = ''
788   begin
789     if sep_string.nil? then
790       # A nil line separator means that the user wants to capture all the
791       # remaining input.
792       loop do
793         buffer << __io_like__buffered_read(4096)
794       end
795     else
796       begin
797         # Record if the user requested paragraphs rather than lines.
798         paragraph_requested = sep_string.empty?
799         # An empty line separator string indicates that the user wants to
800         # return paragraphs.  A pair of newlines in the stream is used to
801         # mark this.
802         sep_string = "\n\n" if paragraph_requested
803 
804         if paragraph_requested then
805           # If the user requested paragraphs instead of lines, we need to
806           # consume and discard all newlines remaining at the front of the
807           # input.
808           char = __io_like__buffered_read(1)
809           char = __io_like__buffered_read(1) while char == "\n"
810           # Put back the last character.
811           ungetc(char[0])
812         end
813 
814         # Add each character from the input to the buffer until either the
815         # buffer has the right ending or the end of the input is reached.
816         while buffer.index(sep_string, -sep_string.length).nil? do
817           buffer << __io_like__buffered_read(1)
818         end
819 
820         if paragraph_requested then
821           # If the user requested paragraphs instead of lines, we need to
822           # consume and discard all newlines remaining at the front of the
823           # input.
824           char = __io_like__buffered_read(1)
825           char = __io_like__buffered_read(1) while char == "\n"
826           # Put back the last character.
827           ungetc(char[0])
828         end
829       rescue Errno::EAGAIN, Errno::EINTR
830         retry if read_ready?
831       end
832     end
833   rescue EOFError, SystemCallError
834     # Reraise the error if there is nothing to return.
835     raise if buffer.empty?
836   end
837   # Increment the number of times this method has returned a "line".
838   self.lineno += 1
839   buffer
840 end
readlines(sep_string = $/) → array click to toggle source

Returns an Array containing the lines in the stream using each_line.

If sep_string is nil, a line is defined as the remaining contents of the stream. If sep_string is not a String, it is converted to one using its to_str method. If sep_string is empty, a paragraph is returned, where a paragraph is defined as data followed by 2 or more successive newline characters (only 2 newlines are returned at the end of the returned data).

In any case, the end of the stream terminates the current line.

Raises EOFError when there is no more data in the stream. Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

NOTE: When sep_string is not nil, this method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
866 def readlines(sep_string = $/)
867   lines = []
868   each_line(sep_string) { |line| lines << line }
869   lines
870 end
readpartial(length[, buffer]) → string or buffer click to toggle source

Returns at most length bytes from the data stream using only the internal read buffer if the buffer is not empty. Falls back to reading from the stream if the buffer is empty. Blocks if no data is available from either the internal read buffer or the data stream regardless of whether or not the data stream would block.

Raises EOFError when there is no more data in the stream. Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_read. Therefore, this method always blocks (via read_ready?) if unable to immediately return length bytes. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_read.

    # File lib/io/like-1.8.6.rb
911 def readpartial(length, buffer = nil)
912     __io_like__readpartial(length, buffer, false)
913 end
rewind → 0 click to toggle source

Sets the position of the file pointer to the beginning of the stream and returns 0 when complete. The lineno attribute is reset to 0 if successful and the stream is readable according to readable?.

As a side effect, the internal read and write buffers are flushed.

Raises IOError if closed? returns true. Raises Errno::ESPIPE unless seekable? returns true.

NOTE: Because this method relies on unbuffered_seek and unbuffered_write (when the internal write buffer is not empty), it will also raise the same errors and block at the same times as those functions.

    # File lib/io/like-1.8.6.rb
931 def rewind
932   seek(0, IO::SEEK_SET)
933   self.lineno = 0 if readable?
934   0
935 end
seek(offset[, whence]) → 0 click to toggle source

Sets the current data position to offset based on the setting of whence. If whence is unspecified or IO::SEEK_SET, offset counts from the beginning of the data. If whence is IO::SEEK_END, offset counts from the end of the data (offset should be negative here). If whence is IO::SEEK_CUR, offset is relative to the current position.

As a side effect, the internal read and write buffers are flushed except when seeking relative to the current position (whence is IO::SEEK_CUR) to a location within the internal read buffer.

Raises IOError if closed? returns true. Raises Errno::ESPIPE unless seekable? returns true.

NOTE: Because this method relies on unbuffered_seek and unbuffered_write (when the internal write buffer is not empty), it will also raise the same errors and block at the same times as those functions.

    # File lib/io/like-1.8.6.rb
958 def seek(offset, whence = IO::SEEK_SET)
959   __io_like__buffered_seek(offset, whence)
960   0
961 end
seekable? → true or false click to toggle source

Returns true if the stream is seekable, false otherwise.

This implementation always returns false for duplexed objects and checks to see if unbuffered_seek is defined in order to make its determination otherwise. Override this if the implementing class always provides the unbuffered_seek method but may not always be seekable.

    # File lib/io/like-1.8.6.rb
973 def seekable?
974   ! duplexed? && respond_to?(:unbuffered_seek, true)
975 end
sync → true or false click to toggle source

Returns true if the internal write buffer is currently being bypassed, false otherwise.

Raises IOError if closed? returns true.

    # File lib/io/like-1.8.6.rb
984 def sync
985   raise IOError, 'closed stream' if closed?
986   @__io_like__sync ||= false
987 end
sync = boolean → boolean click to toggle source

When set to true the internal write buffer will be bypassed. Any data currently in the buffer will be flushed prior to the next output operation. When set to false, the internal write buffer will be enabled.

Raises IOError if closed? returns true.

     # File lib/io/like-1.8.6.rb
 998 def sync=(sync)
 999   raise IOError, 'closed stream' if closed?
1000   @__io_like__sync = sync ? true : false
1001 end
sysread(length) → string click to toggle source

Reads and returns up to length bytes directly from the data stream, bypassing the internal read buffer.

Returns "" if length is 0 regardless of the status of the data stream. This is for compatibility with IO#sysread.

Raises EOFError if reading begins at the end of the stream. Raises IOError if the internal read buffer is not empty. Raises IOError if closed? returns true.

NOTE: Because this method relies on unbuffered_read, it will also raise the same errors and block at the same times as that function.

     # File lib/io/like-1.8.6.rb
1019 def sysread(length, buffer = nil)
1020   buffer = buffer.nil? ? '' : buffer.to_str
1021   buffer.slice!(0..-1) unless buffer.empty?
1022   return buffer if length == 0
1023 
1024   raise IOError, 'closed stream' if closed?
1025   raise IOError, 'not opened for reading' unless readable?
1026   unless __io_like__internal_read_buffer.empty? then
1027     raise IOError, 'sysread on buffered IO'
1028   end
1029 
1030   # Flush the internal write buffer for writable, non-duplexed objects.
1031   __io_like__buffered_flush if writable? && ! duplexed?
1032 
1033   buffer << unbuffered_read(length)
1034 end
sysseek(offset[, whence]) → integer click to toggle source

Sets the current data position to offset based on the setting of whence. If whence is unspecified or IO::SEEK_SET, offset counts from the beginning of the data. If whence is IO::SEEK_END, offset counts from the end of the data (offset should be negative here). If whence is IO::SEEK_CUR, offset is relative to the current position.

Raises IOError if the internal read buffer is not empty. Raises IOError if closed? returns true. Raises Errno::ESPIPE unless seekable? returns true.

NOTE: Because this method relies on unbuffered_seek, it will also raise the same errors and block at the same times as that function.

     # File lib/io/like-1.8.6.rb
1053 def sysseek(offset, whence = IO::SEEK_SET)
1054   raise IOError, 'closed stream' if closed?
1055   raise Errno::ESPIPE unless seekable?
1056   unless __io_like__internal_read_buffer.empty? then
1057     raise IOError, 'sysseek on buffered IO'
1058   end
1059   unless __io_like__internal_write_buffer.empty? then
1060     warn('warning: sysseek on buffered IO')
1061   end
1062 
1063   unbuffered_seek(offset, whence)
1064 end
syswrite(string) → integer click to toggle source

Writes string directly to the data stream, bypassing the internal write buffer and returns the number of bytes written.

As a side effect for non-duplex objects, the internal read buffer is flushed.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: Because this method relies on unbuffered_write, it will also raise the same errors and block at the same times as that function.

     # File lib/io/like-1.8.6.rb
1080 def syswrite(string)
1081   raise IOError, 'closed stream' if closed?
1082   raise IOError, 'not opened for writing' unless writable?
1083   unless __io_like__internal_write_buffer.empty? then
1084     warn('warning: syswrite on buffered IO')
1085   end
1086 
1087   # Flush the internal read buffer and set the unbuffered position to the
1088   # buffered position when dealing with non-duplexed objects.
1089   unless duplexed? || __io_like__internal_read_buffer.empty? then
1090     unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1091     __io_like__internal_read_buffer.slice!(0..-1)
1092   end
1093 
1094   unbuffered_write(string)
1095 end
tell
Alias for: pos
to_io → ios click to toggle source

Returns ios.

     # File lib/io/like-1.8.6.rb
1101 def to_io
1102   self
1103 end
tty?
Alias for: isatty
ungetc(integer) → nil click to toggle source

Calls unread with integer.chr as an argument.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

     # File lib/io/like-1.8.6.rb
1112 def ungetc(integer)
1113   unread(integer.chr)
1114 end
unread(string) → nil click to toggle source

Pushes the given string onto the front of the internal read buffer and returns nil. If string is not a String, it is converted to one using its to_s method.

Raises IOError if closed? returns true. Raises IOError unless readable? returns true.

     # File lib/io/like-1.8.6.rb
1125 def unread(string)
1126   raise IOError, 'closed stream' if closed?
1127   raise IOError, 'not opened for reading' unless readable?
1128   __io_like__internal_read_buffer.insert(0, string.to_s)
1129   nil
1130 end
writable? → true or false click to toggle source

Returns true if the stream is both open and writable, false otherwise.

This implementation checks to see if unbuffered_write is defined in order to make its determination. Override this if the implementing class always provides the unbuffered_write method but may not always be open in a writable mode.

     # File lib/io/like-1.8.6.rb
1166 def writable?
1167   ! __io_like__closed_write? && respond_to?(:unbuffered_write, true)
1168 end
write(string) → integer click to toggle source

Writes the given string to the stream and returns the number of bytes written. If string is not a String, its to_s method is used to convert it into one. The entire contents of string are written, blocking as necessary even if the data stream does not block.

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

NOTE: This method ignores Errno::EAGAIN and Errno::EINTR raised by unbuffered_write. Therefore, this method always blocks if unable to immediately write string completely. Aside from that exception, this method will also raise the same errors and block at the same times as unbuffered_write.

     # File lib/io/like-1.8.6.rb
1187 def write(string)
1188   string = string.to_s
1189   return 0 if string.empty?
1190 
1191   bytes_written = 0
1192   while bytes_written < string.length do
1193     begin
1194       bytes_written +=
1195         __io_like__buffered_write(string.to_s.slice(bytes_written..-1), false)
1196     rescue Errno::EAGAIN, Errno::EINTR
1197       retry if write_ready?
1198     end
1199   end
1200   bytes_written
1201 end
write_nonblock(string) → integer click to toggle source

Writes the given string to the stream and returns the number of bytes written. If string is not a String, its to_s method is used to convert it into one.

As many bytes as possible are written without blocking or SystemCallEerror from unbuffered_write is passed directly through to be handled by the caller

Raises IOError if closed? returns true. Raises IOError unless writable? returns true.

     # File lib/io/like-1.8.6.rb
1216 def write_nonblock(string)
1217   return __io_like__buffered_write(string.to_s, true)
1218 end
write_ready? → true or false click to toggle source

Returns true when the stream may be written without error, false otherwise. This method will block until one of the conditions is known.

This default implementation of write_ready? is a hack which should be able to work for both real IO objects and IO-like objects; however, it is inefficient since it merely sleeps for 1 second and then returns true as long as closed? returns false. IO.select should be used for real IO objects to wait for a writeable condition on platforms with support for IO.select. Other solutions should be found as necessary to improve this implementation on a case by case basis.

Basically, this method should be overridden in derivative classes.

     # File lib/io/like-1.8.6.rb
1150 def write_ready?
1151   return false unless writable?
1152   sleep(1)
1153   true
1154 end

Private Instance Methods

__io_like__array_flatten(array,seen = []) { |nil| ... } click to toggle source

This method yields the flattened elements of array as a string suitable for puts. seen is a list of # object IDs to detect recursive array nesting

This method exists only because Array#join apparently behaves in an implementation dependent manner when joining recursive arrays and so does not always produce the expected results. Specifically, MRI 1.8.6 and 1.8.7 behave as follows:

x = []
x << 1 << x << 2
x.join(', ')              => "1, 1, [...], 2, 2"

The expected and necessary result for use with puts is:

"1, [...], 2"

Things get progressively worse as the nesting and recursion become more convoluted.

     # File lib/io/like-1.8.6.rb
1490 def __io_like__array_flatten(array,seen = [],&block)
1491   seen.push(array.object_id)
1492   array.each do |item|
1493 
1494     if item.nil?
1495       yield nil
1496     elsif item.kind_of?(Array)
1497       if seen.include?(item.object_id)
1498         yield '[...]'
1499       else
1500         __io_like__array_flatten(item,seen,&block)
1501       end
1502     else
1503       yield item.to_s
1504     end
1505   end
1506   seen.pop
1507 end
__io_like__buffered_flush → 0 click to toggle source

Attempts to completely flush the internal write buffer to the data stream.

Raises IOError unless writable? returns true.

NOTE: Because this method relies on unbuffered_write, it raises all errors raised by unbuffered_write and blocks when unbuffered_write blocks.

     # File lib/io/like-1.8.6.rb
1232 def __io_like__buffered_flush
1233   raise IOError, 'closed stream' if closed?
1234   raise IOError, 'not opened for writing' unless writable?
1235 
1236   until __io_like__internal_write_buffer.empty? do
1237     __io_like__internal_write_buffer.slice!(
1238       0, unbuffered_write(__io_like__internal_write_buffer)
1239     )
1240   end
1241   0
1242 end
__io_like__buffered_read(length) → string click to toggle source

Reads at most length bytes first from an internal read buffer followed by the underlying stream if necessary and returns the resulting buffer.

Raises EOFError if the internal read buffer is empty and reading begins at the end of the stream. Raises IOError unless readable? returns true.

NOTE: Because this method relies on unbuffered_read, it raises all errors raised by unbuffered_read and blocks when unbuffered_read blocks whenever the internal read buffer is unable to fulfill the request.

     # File lib/io/like-1.8.6.rb
1258 def __io_like__buffered_read(length)
1259   # Check the validity of the method arguments.
1260   raise ArgumentError, "non-positive length #{length} given" if length < 0
1261 
1262   raise IOError, 'closed stream' if closed?
1263   raise IOError, 'not opened for reading' unless readable?
1264 
1265   # Flush the internal write buffer for writable, non-duplexed objects.
1266   __io_like__buffered_flush if writable? && ! duplexed?
1267 
1268   # Ensure that the internal read buffer has at least enough data to satisfy
1269   # the request.
1270   if __io_like__internal_read_buffer.length < length then
1271     unbuffered_length = length - __io_like__internal_read_buffer.length
1272     unbuffered_length = fill_size if unbuffered_length < fill_size
1273 
1274     begin
1275       __io_like__internal_read_buffer << unbuffered_read(unbuffered_length)
1276     rescue EOFError, SystemCallError
1277       # Reraise the error if there is no data to return.
1278       raise if __io_like__internal_read_buffer.empty?
1279     end
1280   end
1281 
1282   # Read from the internal read buffer.
1283   buffer = __io_like__internal_read_buffer.slice!(0, length)
1284 
1285   buffer
1286 end
__io_like__buffered_seek(offset[, whence]) → integer click to toggle source

Sets the current data position to offset based on the setting of whence. If whence is unspecified or IO::SEEK_SET, offset counts from the beginning of the data. If whence is IO::SEEK_END, offset counts from the end of the data (offset should be negative here). If whence is IO::SEEK_CUR, offset is relative to the current position.

As a side effect, the internal read and write buffers are flushed except when seeking relative to the current position (whence is IO::SEEK_CUR) to a location within the internal read buffer.

Raises Errno::ESPIPE unless seekable? returns true.

See seek for the usage of offset and whence.

NOTE: Because this method relies on unbuffered_seek and unbuffered_write (when the internal write buffer is not empty), it will raise the same errors and block at the same times as those functions.

     # File lib/io/like-1.8.6.rb
1354 def __io_like__buffered_seek(offset, whence = IO::SEEK_SET)
1355   raise IOError, 'closed stream' if closed?
1356   raise Errno::ESPIPE unless seekable?
1357 
1358   if whence == IO::SEEK_CUR && offset == 0 then
1359     # The seek is only determining the current position, so return the
1360     # buffered position based on the read buffer if it's not empty and the
1361     # write buffer otherwise.
1362     __io_like__internal_read_buffer.empty? ?
1363       unbuffered_seek(0, IO::SEEK_CUR) +
1364         __io_like__internal_write_buffer.length :
1365       unbuffered_seek(0, IO::SEEK_CUR) -
1366         __io_like__internal_read_buffer.length
1367   elsif whence == IO::SEEK_CUR && offset > 0 &&
1368         __io_like__internal_write_buffer.empty? &&
1369         offset <= __io_like__internal_read_buffer.length then
1370     # The seek is within the read buffer, so just discard a sufficient
1371     # amount of the buffer and report the new buffered position.
1372     __io_like__internal_read_buffer.slice!(0, offset)
1373     unbuffered_seek(0, IO::SEEK_CUR) -
1374       __io_like__internal_read_buffer.length
1375   else
1376     # The seek target is outside of the buffers, so flush the buffers and
1377     # jump to the new position.
1378     if whence == IO::SEEK_CUR then
1379       # Adjust relative offsets based on the current buffered offset.
1380       offset += __io_like__internal_read_buffer.empty? ?
1381         __io_like__internal_write_buffer.length :
1382         -__io_like__internal_read_buffer.length
1383     end
1384 
1385     # Flush the internal buffers.
1386     __io_like__internal_read_buffer.slice!(0..-1)
1387     __io_like__buffered_flush if writable?
1388 
1389     # Move the data stream's position as requested.
1390     unbuffered_seek(offset, whence)
1391   end
1392 end
__io_like__buffered_write(string) → integer click to toggle source

Writes string to the internal write buffer and returns the number of bytes written. If the internal write buffer is overfilled by string, it is repeatedly flushed until that last of string is consumed. A partial write will occur if part of string fills the internal write buffer but the internal write buffer cannot be immediately flushed due to the underlying stream not blocking when unable to accept more data.

NOTE: Because this method relies on unbuffered_write, it raises all errors raised by unbuffered_write and blocks when unbuffered_write blocks whenever the internal write buffer is unable to fulfill the request.

     # File lib/io/like-1.8.6.rb
1409 def __io_like__buffered_write(string, nonblock = false)
1410   raise IOError, 'closed stream' if closed?
1411   raise IOError, 'not opened for writing' unless writable?
1412 
1413   # Flush the internal read buffer and set the unbuffered position to the
1414   # buffered position when dealing with non-duplexed objects.
1415   unless duplexed? || __io_like__internal_read_buffer.empty? then
1416     unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1417     __io_like__internal_read_buffer.slice!(0..-1)
1418   end
1419 
1420   bytes_written = 0
1421 
1422   if sync || nonblock || __io_like__internal_write_buffer.length + string.length >= flush_size then
1423     # Flush the internal write buffer and then bypass it when in synchronous
1424     # mode or the tipping point for the write buffer would be surpassed by this
1425     # request.
1426     __io_like__nonblock() if nonblock
1427     __io_like__buffered_flush
1428     bytes_written = unbuffered_write(string)
1429   else
1430     # The buffer can absorb the entire request.
1431     __io_like__internal_write_buffer << string
1432     bytes_written = string.length
1433   end
1434   return bytes_written
1435 end
__io_like__close_read() click to toggle source

Arranges for __io_like__closed_read? to return true.

     # File lib/io/like-1.8.6.rb
1454 def __io_like__close_read
1455   @__io_like__closed_read = true
1456   nil
1457 end
__io_like__close_write() click to toggle source

Arranges for __io_like__closed_write? to return true.

     # File lib/io/like-1.8.6.rb
1466 def __io_like__close_write
1467   @__io_like__closed_write = true
1468   nil
1469 end
__io_like__closed_read?() click to toggle source

Returns true if this object has been closed for reading; otherwise, returns false.

     # File lib/io/like-1.8.6.rb
1449 def __io_like__closed_read?
1450   @__io_like__closed_read ||= false
1451 end
__io_like__closed_write?() click to toggle source

Returns true if this object has been closed for writing; otherwise, returns false.

     # File lib/io/like-1.8.6.rb
1461 def __io_like__closed_write?
1462   @__io_like__closed_write ||= false
1463 end
__io_like__internal_read_buffer() click to toggle source

Returns a reference to the internal read buffer.

     # File lib/io/like-1.8.6.rb
1438 def __io_like__internal_read_buffer
1439   @__io_like__read_buffer ||= ''
1440 end
__io_like__internal_write_buffer() click to toggle source

Returns a reference to the internal write buffer.

     # File lib/io/like-1.8.6.rb
1443 def __io_like__internal_write_buffer
1444   @__io_like__write_buffer ||= ''
1445 end
__io_like__nonblock() click to toggle source

Puts the underlying stream into blocking mode

See read_nonblock, write_nonblock nonblock=

     # File lib/io/like-1.8.6.rb
1327 def __io_like__nonblock
1328   self.nonblock = true
1329 end
__io_like__readpartial(length,buffer,nonblock) → string click to toggle source

read_nonblock and read_partial are identical except for the way they handle exceptions from unbuffered_read.

     # File lib/io/like-1.8.6.rb
1293 def __io_like__readpartial(length, buffer, nonblock)
1294   # Check the validity of the method arguments.
1295   unless length >= 0 then
1296     raise ArgumentError, "negative length #{length} given"
1297   end
1298   buffer = '' if buffer.nil?
1299   # Flush the buffer.
1300   buffer.slice!(0..-1)
1301 
1302   # set nonblocking if necessary
1303   __io_like__nonblock if nonblock
1304 
1305   # Read and return up to length bytes.
1306   if __io_like__internal_read_buffer.empty? then
1307     begin
1308       buffer << __io_like__buffered_read(length)
1309     rescue Errno::EINTR, Errno::EAGAIN
1310       if !nonblock && read_ready? then retry else raise end
1311     end
1312   else
1313     raise IOError, 'closed stream' if closed?
1314     raise IOError, 'not opened for reading' unless readable?
1315 
1316     buffer << __io_like__internal_read_buffer.slice!(0, length)
1317   end
1318   buffer
1319 end