module IO::Like
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
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
Returns self
. Just for compatibility with IO
.
# File lib/io/like-1.8.6.rb 29 def binmode 30 self 31 end
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
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
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
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
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
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
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
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
Raises NotImplementedError
.
# File lib/io/like-1.8.6.rb 184 def fcntl(*args) 185 raise NotImplementedError, 'not implemented' 186 end
Returns nil
. Just for compatibility with IO
.
# File lib/io/like-1.8.6.rb 192 def fileno 193 nil 194 end
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
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
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
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
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
Flush data to disk, default is not supported
# File lib/io/like-1.8.6.rb 298 def fsync() 299 nil 300 end
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
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
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
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
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
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
Returns nil
. Just for compatibility with IO
.
# File lib/io/like-1.8.6.rb 423 def path 424 nil 425 end
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
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
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.
# File lib/io/like-1.8.6.rb 486 def print(*args) 487 args << $_ if args.empty? 488 first_arg = true 489 args.each do |arg| 490 # Write a field separator before writing each argument after the first 491 # one unless no field separator is specified. 492 if first_arg then 493 first_arg = false 494 elsif ! $,.nil? then 495 write($,) 496 end 497 498 # If the argument is nil, write 'nil'; otherwise, write the stringified 499 # form of the argument. 500 if arg.nil? then 501 write('nil') 502 else 503 write(arg) 504 end 505 end 506 507 # Write the output record separator if one is specified. 508 write($\) unless $\.nil? 509 nil 510 end
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Returns ios.
# File lib/io/like-1.8.6.rb 1101 def to_io 1102 self 1103 end
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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