module IO::Like

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.

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.

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

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.

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.rb
82 def <<(obj)
83   write(obj)
84   self
85 end
__io_like__array_join(array, separator, seen = []) click to toggle source

This method joins the elements of array together with separator between each element and returns the result. seen is a list of object IDs representing arrays which have already started processing.

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.rb
1431 def __io_like__array_join(array, separator, seen = [])
1432   seen.push(array.object_id)
1433   need_separator = false
1434   result = array.inject('') do |memo, item|
1435     memo << separator if need_separator
1436     need_separator = true
1437 
1438     memo << if item.kind_of?(Array) then
1439               if seen.include?(item.object_id) then
1440                 '[...]'
1441               else
1442                 __io_like__array_join(item, separator, seen)
1443               end
1444             else
1445               item.to_s
1446             end
1447   end
1448   seen.pop
1449 
1450   result
1451 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.rb
1218 def __io_like__buffered_flush
1219   raise IOError, 'closed stream' if closed?
1220   raise IOError, 'not opened for writing' unless writable?
1221 
1222   until __io_like__internal_write_buffer.empty? do
1223     __io_like__internal_write_buffer.slice!(
1224       0, unbuffered_write(__io_like__internal_write_buffer)
1225     )
1226   end
1227   0
1228 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.rb
1242 def __io_like__buffered_read(length)
1243   # Check the validity of the method arguments.
1244   raise ArgumentError, "non-positive length #{length} given" if length < 0
1245 
1246   raise IOError, 'closed stream' if closed?
1247   raise IOError, 'not opened for reading' unless readable?
1248 
1249   # Flush the internal write buffer for writable, non-duplexed objects.
1250   __io_like__buffered_flush if writable? && ! duplexed?
1251 
1252   # Ensure that the internal read buffer has at least enough data to satisfy
1253   # the request.
1254   if __io_like__internal_read_buffer.length < length then
1255     unbuffered_length = length - __io_like__internal_read_buffer.length
1256     unbuffered_length = fill_size if unbuffered_length < fill_size
1257 
1258     begin
1259       __io_like__internal_read_buffer << unbuffered_read(unbuffered_length)
1260     rescue EOFError, SystemCallError
1261       # Reraise the error if there is no data to return.
1262       raise if __io_like__internal_read_buffer.empty?
1263     end
1264   end
1265 
1266   # Read from the internal read buffer.
1267   buffer = __io_like__internal_read_buffer.slice!(0, length)
1268 
1269   buffer
1270 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.rb
1292 def __io_like__buffered_seek(offset, whence = IO::SEEK_SET)
1293   raise IOError, 'closed stream' if closed?
1294   raise Errno::ESPIPE unless seekable?
1295 
1296   if whence == IO::SEEK_CUR && offset == 0 then
1297     # The seek is only determining the current position, so return the
1298     # buffered position based on the read buffer if it's not empty and the
1299     # write buffer otherwise.
1300     __io_like__internal_read_buffer.empty? ?
1301       unbuffered_seek(0, IO::SEEK_CUR) +
1302         __io_like__internal_write_buffer.length :
1303       unbuffered_seek(0, IO::SEEK_CUR) -
1304         __io_like__internal_read_buffer.length
1305   elsif whence == IO::SEEK_CUR && offset > 0 &&
1306         __io_like__internal_write_buffer.empty? &&
1307         offset <= __io_like__internal_read_buffer.length then
1308     # The seek is within the read buffer, so just discard a sufficient
1309     # amount of the buffer and report the new buffered position.
1310     __io_like__internal_read_buffer.slice!(0, offset)
1311     unbuffered_seek(0, IO::SEEK_CUR) -
1312       __io_like__internal_read_buffer.length
1313   else
1314     # The seek target is outside of the buffers, so flush the buffers and
1315     # jump to the new position.
1316     if whence == IO::SEEK_CUR then
1317       # Adjust relative offsets based on the current buffered offset.
1318       offset += __io_like__internal_read_buffer.empty? ?
1319         __io_like__internal_write_buffer.length :
1320         -__io_like__internal_read_buffer.length
1321     end
1322 
1323     # Flush the internal buffers.
1324     __io_like__internal_read_buffer.slice!(0..-1)
1325     __io_like__buffered_flush if writable?
1326 
1327     # Move the data stream's position as requested.
1328     unbuffered_seek(offset, whence)
1329   end
1330 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.rb
1346 def __io_like__buffered_write(string)
1347   raise IOError, 'closed stream' if closed?
1348   raise IOError, 'not opened for writing' unless writable?
1349 
1350   # Flush the internal read buffer and set the unbuffered position to the
1351   # buffered position when dealing with non-duplexed objects.
1352   unless duplexed? || __io_like__internal_read_buffer.empty? then
1353     unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1354     __io_like__internal_read_buffer.slice!(0..-1)
1355   end
1356 
1357   bytes_written = 0
1358   if sync then
1359     # Flush the internal write buffer and then bypass it when in synchronous
1360     # mode.
1361     __io_like__buffered_flush
1362     bytes_written = unbuffered_write(string)
1363   else
1364     if __io_like__internal_write_buffer.length + string.length >= flush_size then
1365       # The tipping point for the write buffer would be surpassed by this
1366       # request, so flush everything.
1367       __io_like__buffered_flush
1368       bytes_written = unbuffered_write(string)
1369     else
1370       # The buffer can absorb the entire request.
1371       __io_like__internal_write_buffer << string
1372       bytes_written = string.length
1373     end
1374   end
1375   return bytes_written
1376 end
__io_like__close_read() click to toggle source

Arranges for #__io_like__closed_read? to return true.

     # File lib/io/like.rb
1395 def __io_like__close_read
1396   @__io_like__closed_read = true
1397   nil
1398 end
__io_like__close_write() click to toggle source

Arranges for #__io_like__closed_write? to return true.

     # File lib/io/like.rb
1407 def __io_like__close_write
1408   @__io_like__closed_write = true
1409   nil
1410 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.rb
1390 def __io_like__closed_read?
1391   @__io_like__closed_read ||= false
1392 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.rb
1402 def __io_like__closed_write?
1403   @__io_like__closed_write ||= false
1404 end
__io_like__internal_read_buffer() click to toggle source

Returns a reference to the internal read buffer.

     # File lib/io/like.rb
1379 def __io_like__internal_read_buffer
1380   @__io_like__read_buffer ||= ''
1381 end
__io_like__internal_write_buffer() click to toggle source

Returns a reference to the internal write buffer.

     # File lib/io/like.rb
1384 def __io_like__internal_write_buffer
1385   @__io_like__write_buffer ||= ''
1386 end
binmode → ios click to toggle source

Returns self. Just for compatibility with IO.

   # File lib/io/like.rb
91 def binmode
92   self
93 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.rb
102 def close
103   raise IOError, 'closed stream' if closed?
104   __io_like__close_read
105   flush if writable?
106   __io_like__close_write
107   nil
108 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.rb
119 def close_read
120   raise IOError, 'closed stream' if closed?
121   if __io_like__closed_read? || ! duplexed? && writable? then
122     raise IOError, 'closing non-duplex IO for reading'
123   end
124   if duplexed? then
125     __io_like__close_read
126   else
127     close
128   end
129   nil
130 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.rb
141 def close_write
142   raise IOError, 'closed stream' if closed?
143   if __io_like__closed_write? || ! duplexed? && readable? then
144     raise IOError, 'closing non-duplex IO for reading'
145   end
146   if duplexed? then
147     flush
148     __io_like__close_write
149   else
150     close
151   end
152   nil
153 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.rb
160 def closed?
161   (__io_like__closed_read? || ! readable?) &&
162   (__io_like__closed_write? || ! writable?)
163 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.rb
170 def duplexed?
171   false
172 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.rb
185 def each_byte
186   while (byte = getc) do
187     yield(byte)
188   end
189   self
190 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.rb
204 def each_line(sep_string = $/)
205   while (line = gets(sep_string)) do
206     yield(line)
207   end
208   self
209 end
Also aliased as: each
eof → true or false
Alias for: eof?

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.rb
227 def eof?
228   if (char = getc) then
229     ungetc(char)
230     return false
231   end
232   true
233 end
Also aliased as: eof
fcntl click to toggle source

Raises NotImplementedError.

    # File lib/io/like.rb
240 def fcntl(*args)
241   raise NotImplementedError, 'not implemented'
242 end
fileno → nil click to toggle source

Returns nil. Just for compatibility with IO.

    # File lib/io/like.rb
248 def fileno
249   nil
250 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.rb
261 def fill_size
262   raise IOError, 'closed stream' if closed?
263   raise IOError, 'not opened for reading' unless readable?
264 
265   @__io_like__fill_size ||= 4096
266 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.rb
277 def fill_size=(fill_size)
278   raise IOError, 'closed stream' if closed?
279   raise IOError, 'not opened for reading' unless readable?
280 
281   unless fill_size >= 0 then
282     raise ArgumentError, "non-positive fill_size #{fill_size} given"
283   end
284   @__io_like__fill_size = fill_size
285 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.rb
304 def flush
305   begin
306     __io_like__buffered_flush
307   rescue Errno::EAGAIN, Errno::EINTR
308     retry if write_ready?
309   end
310   self
311 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.rb
322 def flush_size
323   raise IOError, 'closed stream' if closed?
324   raise IOError, 'not opened for writing' unless writable?
325 
326   @__io_like__flush_size ||= 4096
327 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.rb
338 def flush_size=(flush_size)
339   raise IOError, 'closed stream' if closed?
340   raise IOError, 'not opened for writing' unless writable?
341 
342   unless flush_size >= 0 then
343     raise ArgumentError, "non-positive flush_size #{flush_size} given"
344   end
345   @__io_like__flush_size = flush_size
346 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.rb
363 def getc
364   readchar
365 rescue EOFError
366   nil
367 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.rb
389 def gets(sep_string = $/)
390   # Set the last read line in the global.
391   $_ = readline(sep_string)
392   # Set the last line number in the global.
393   $. = lineno
394   # Return the last read line.
395   $_
396 rescue EOFError
397   nil
398 end
isatty → false click to toggle source

Returns false. Just for compatibility with IO.

Raises IOError if closed? returns true.

    # File lib/io/like.rb
406 def isatty
407   raise IOError, 'closed stream' if closed?
408   false
409 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.rb
422 def lineno
423   raise IOError, 'closed stream' if closed?
424   raise IOError, 'not opened for reading' unless readable?
425   @__io_like__lineno ||= 0
426 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.rb
437 def lineno=(integer)
438   raise IOError, 'closed stream' if closed?
439   raise IOError, 'not opened for reading' unless readable?
440   if integer.nil? then
441     raise TypeError, 'no implicit conversion from nil to integer'
442   elsif ! integer.respond_to?(:to_int) then
443     raise TypeError, "can't convert #{integer.class} into Integer"
444   end
445   @__io_like__lineno = integer.to_int
446 end
path → nil click to toggle source

Returns nil. Just for compatibility with IO.

    # File lib/io/like.rb
452 def path
453   nil
454 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.rb
489 def pos
490   # Flush the internal write buffer for writable, non-duplexed objects.
491   __io_like__buffered_flush if writable? && ! duplexed?
492   __io_like__buffered_seek(0, IO::SEEK_CUR)
493 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.rb
469 def pos=(position)
470   seek(position, IO::SEEK_SET)
471   position
472 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.rb
554 def printf(*args)
555   write(sprintf(*args))
556   nil
557 end
putc(obj) → obj click to toggle source

If obj is a String, write the first byte; otherwise, convert obj to a 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.rb
573 def putc(obj)
574   char = case obj
575          when String
576            obj[0].chr
577          else
578            [obj.to_int].pack('V')[0].chr
579          end
580   write(char)
581   obj
582 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.rb
606 def puts(*args)
607   # Set the output record separator such that this method is compatible with
608   # IO#puts.
609   ors = "\n"
610 
611   # Write only the record separator if no arguments are given.
612   if args.length == 0 then
613     write(ors)
614     return
615   end
616 
617   # Write each argument followed by the record separator.  Recursively
618   # process arguments which are Array instances.
619   args.each do |arg|
620     line = arg.nil? ?
621              'nil' :
622              arg.kind_of?(Array) ?
623                __io_like__array_join(arg, ors) :
624                arg.to_s
625     line += ors if line.index(ors, -ors.length).nil?
626     write(line)
627   end
628 
629   nil
630 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.rb
654 def read(length = nil, buffer = nil)
655   # Check the validity of the method arguments.
656   unless length.nil? || length >= 0 then
657     raise ArgumentError, "negative length #{length} given"
658   end
659   buffer = buffer.nil? ? '' : buffer.to_str
660   buffer.slice!(0..-1) unless buffer.empty?
661 
662   if length.nil? then
663     # Read and return everything.
664     begin
665       loop do
666         buffer << __io_like__buffered_read(4096)
667       end
668     rescue EOFError
669       # Ignore this.
670     rescue SystemCallError
671       # Reraise the error if there is nothing to return.
672       raise if buffer.empty?
673     end
674   else
675     # Read and return up to length bytes.
676     begin
677       buffer << __io_like__buffered_read(length)
678     rescue EOFError
679       # Return nil to the caller at end of file when requesting a specific
680       # amount of data.
681       return nil
682     end
683   end
684   buffer
685 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 closed? returns false. 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.rb
702 def read_ready?
703   return false unless readable?
704   sleep(1)
705   true
706 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.rb
717 def readable?
718   ! __io_like__closed_read? && respond_to?(:unbuffered_read, true)
719 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.rb
738 def readbytes(length)
739   buffer = read(length)
740   if buffer.nil? then
741     raise EOFError, "end of file reached"
742   end
743   if buffer.length < length then
744     raise TruncatedDataError.new("data truncated", buffer)
745   end
746   buffer
747 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.rb
762 def readchar
763   __io_like__buffered_read(1)[0]
764 rescue Errno::EAGAIN, Errno::EINTR
765   retry if read_ready?
766 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.rb
 805   def readline(sep_string = $/)
 806     # Ensure that sep_string is either nil or a String.
 807     unless sep_string.nil? || sep_string.kind_of?(String) then
 808       sep_string = sep_string.to_str
 809     end
 810 
 811     buffer = ''
 812     begin
 813       if sep_string.nil? then
 814         # A nil line separator means that the user wants to capture all the
 815         # remaining input.
 816         loop do
 817           buffer << __io_like__buffered_read(4096)
 818         end
 819       else
 820         begin
 821           # Record if the user requested paragraphs rather than lines.
 822           paragraph_requested = sep_string.empty?
 823           # An empty line separator string indicates that the user wants to
 824           # return paragraphs.  A pair of newlines in the stream is used to
 825           # mark this.
 826           sep_string = "\n\n" if paragraph_requested
 827 
 828           # Add each character from the input to the buffer until either the
 829           # buffer has the right ending or the end of the input is reached.
 830           while buffer.index(sep_string, -sep_string.length).nil? &&
 831                 (char = __io_like__buffered_read(1)) do
 832             buffer << char
 833           end
 834 
 835           if paragraph_requested then
 836             # If the user requested paragraphs instead of lines, we need to
 837             # consume and discard all newlines remaining at the front of the
 838             # input.
 839             while char == "\n" && (char = __io_like__buffered_read(1)) do
 840               nil
 841             end
 842             # Put back the last character.
 843             ungetc(char[0])
 844           end
 845         rescue Errno::EAGAIN, Errno::EINTR
 846           retry if read_ready?
 847         end
 848       end
 849     rescue EOFError, SystemCallError
 850       # Reraise the error if there is nothing to return.
 851       raise if buffer.empty?
 852     end
 853     # Increment the number of times this method has returned a "line".
 854     self.lineno += 1
 855     buffer
 856   end
 857 
 858   # call-seq:
 859   #   ios.readlines(sep_string = $/) -> array
 860   #
 861   # Returns an Array containing the lines in the stream using #each_line.
 862   #
 863   # If _sep_string_ is +nil+, a line is defined as the remaining contents of
 864   # the stream.  If _sep_string_ is not a String, it is converted to one using
 865   # its +to_str+ method.  If _sep_string_ is empty, a paragraph is returned,
 866   # where a paragraph is defined as data followed by 2 or more successive
 867   # newline characters (only 2 newlines are returned at the end of the
 868   # returned data).
 869   #
 870   # In any case, the end of the stream terminates the current line.
 871   #
 872   # Raises EOFError when there is no more data in the stream.  Raises IOError
 873   # if #closed? returns +true+.  Raises IOError unless #readable? returns
 874   # +true+.
 875   #
 876   # <b>NOTE:</b> When _sep_string_ is not +nil+, this method ignores
 877   # Errno::EAGAIN and Errno::EINTR raised by #unbuffered_read.  Therefore,
 878   # this method always blocks.  Aside from that exception, this method will
 879   # also raise the same errors and block at the same times as
 880   # #unbuffered_read.
 881   def readlines(sep_string = $/)
 882     lines = []
 883     each_line(sep_string) { |line| lines << line }
 884     lines
 885   end
 886 
 887   # call-seq:
 888   #   ios.readpartial(length[, buffer]) -> string or buffer
 889   #
 890   # Returns at most _length_ bytes from the data stream using only the
 891   # internal read buffer if the buffer is not empty.  Falls back to reading
 892   # from the stream if the buffer is empty.  Blocks if no data is available
 893   # from either the internal read buffer or the data stream regardless of
 894   # whether or not the data stream would block.
 895   #
 896   # Raises EOFError when there is no more data in the stream.  Raises IOError
 897   # if #closed? returns +true+.  Raises IOError unless #readable? returns
 898   # +true+.
 899   #
 900   # <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
 901   # #unbuffered_read.  Therefore, this method always blocks if unable to
 902   # immediately return _length_ bytes.  Aside from that exception, this method
 903   # will also raise the same errors and block at the same times as
 904   # #unbuffered_read.
 905   def readpartial(length, buffer = nil)
 906     # Check the validity of the method arguments.
 907     unless length >= 0 then
 908       raise ArgumentError, "negative length #{length} given"
 909     end
 910     buffer = '' if buffer.nil?
 911     # Flush the buffer.
 912     buffer.slice!(0..-1)
 913 
 914     # Read and return up to length bytes.
 915     if __io_like__internal_read_buffer.empty? then
 916       begin
 917         buffer << __io_like__buffered_read(length)
 918       rescue Errno::EAGAIN, Errno::EINTR
 919         retry if read_ready?
 920       end
 921     else
 922       raise IOError, 'closed stream' if closed?
 923       raise IOError, 'not opened for reading' unless readable?
 924 
 925       buffer << __io_like__internal_read_buffer.slice!(0, length)
 926     end
 927     buffer
 928   end
 929 
 930   # call-seq:
 931   #   ios.rewind           -> 0
 932   #
 933   # Sets the position of the file pointer to the beginning of the stream and
 934   # returns 0 when complete.  The lineno attribute is reset to 0 if
 935   # successful and the stream is readable according to #readable?.
 936   #
 937   # As a side effect, the internal read and write buffers are flushed.
 938   #
 939   # Raises IOError if #closed? returns +true+.  Raises Errno::ESPIPE unless
 940   # #seekable? returns +true+.
 941   #
 942   # <b>NOTE:</b> Because this method relies on #unbuffered_seek and
 943   # #unbuffered_write (when the internal write buffer is not empty), it will
 944   # also raise the same errors and block at the same times as those functions.
 945   def rewind
 946     seek(0, IO::SEEK_SET)
 947     self.lineno = 0 if readable?
 948     0
 949   end
 950 
 951   # call-seq:
 952   #   seek(offset[, whence]) -> 0
 953   #
 954   # Sets the current data position to _offset_ based on the setting of
 955   # _whence_.  If _whence_ is unspecified or IO::SEEK_SET, _offset_ counts
 956   # from the beginning of the data.  If _whence_ is IO::SEEK_END, _offset_
 957   # counts from the end of the data (_offset_ should be negative here).  If
 958   # _whence_ is IO::SEEK_CUR, _offset_ is relative to the current position.
 959   #
 960   # As a side effect, the internal read and write buffers are flushed except
 961   # when seeking relative to the current position (whence is IO::SEEK_CUR) to
 962   # a location within the internal read buffer.
 963   #
 964   # Raises IOError if #closed? returns +true+.  Raises Errno::ESPIPE unless
 965   # #seekable? returns +true+.
 966   #
 967   # <b>NOTE:</b> Because this method relies on #unbuffered_seek and
 968   # #unbuffered_write (when the internal write buffer is not empty), it will
 969   # also raise the same errors and block at the same times as those functions.
 970   def seek(offset, whence = IO::SEEK_SET)
 971     __io_like__buffered_seek(offset, whence)
 972     0
 973   end
 974 
 975   # call-seq:
 976   #   ios.seekable?        -> true or false
 977   #
 978   # Returns +true+ if the stream is seekable, +false+ otherwise.
 979   #
 980   # This implementation always returns +false+ for duplexed objects and
 981   # checks to see if #unbuffered_seek is defined in order to make its
 982   # determination otherwise.  Override this if the implementing class always
 983   # provides the #unbuffered_seek method but may not always be seekable.
 984   def seekable?
 985     ! duplexed? && respond_to?(:unbuffered_seek, true)
 986   end
 987 
 988   # call-seq:
 989   #   ios.sync             -> true or false
 990   #
 991   # Returns true if the internal write buffer is currently being bypassed,
 992   # false otherwise.
 993   #
 994   # Raises IOError if #closed? returns +true+.
 995   def sync
 996     raise IOError, 'closed stream' if closed?
 997     @__io_like__sync ||= false
 998   end
 999 
1000   # call-seq:
1001   #   ios.sync = boolean   -> boolean
1002   #
1003   # When set to +true+ the internal write buffer will be bypassed.  Any data
1004   # currently in the buffer will be flushed prior to the next output
1005   # operation.  When set to +false+, the internal write buffer will be
1006   # enabled.
1007   #
1008   # Raises IOError if #closed? returns +true+.
1009   def sync=(sync)
1010     raise IOError, 'closed stream' if closed?
1011     @__io_like__sync = sync ? true : false
1012   end
1013 
1014   # call-seq:
1015   #   ios.sysread(length)  -> string
1016   #
1017   # Reads and returns up to _length_ bytes directly from the data stream,
1018   # bypassing the internal read buffer.
1019   #
1020   # Returns <tt>""</tt> if _length_ is 0 regardless of the status of the data
1021   # stream.  This is for compatibility with IO#sysread.
1022   #
1023   # Raises EOFError if reading begins at the end of the stream.  Raises
1024   # IOError if the internal read buffer is not empty.  Raises IOError if
1025   # #closed? returns +true+.
1026   #
1027   # <b>NOTE:</b> Because this method relies on #unbuffered_read, it will also
1028   # raise the same errors and block at the same times as that function.
1029   def sysread(length, buffer = nil)
1030     buffer = buffer.nil? ? '' : buffer.to_str
1031     buffer.slice!(0..-1) unless buffer.empty?
1032     return buffer if length == 0
1033 
1034     raise IOError, 'closed stream' if closed?
1035     raise IOError, 'not opened for reading' unless readable?
1036     unless __io_like__internal_read_buffer.empty? then
1037       raise IOError, 'sysread on buffered IO'
1038     end
1039 
1040     # Flush the internal write buffer for writable, non-duplexed objects.
1041     __io_like__buffered_flush if writable? && ! duplexed?
1042 
1043     buffer << unbuffered_read(length)
1044   end
1045 
1046   # call-seq:
1047   #   ios.sysseek(offset[, whence]) -> integer
1048   #
1049   # Sets the current data position to _offset_ based on the setting of
1050   # _whence_.  If _whence_ is unspecified or IO::SEEK_SET, _offset_ counts
1051   # from the beginning of the data.  If _whence_ is IO::SEEK_END, _offset_
1052   # counts from the end of the data (_offset_ should be negative here).  If
1053   # _whence_ is IO::SEEK_CUR, _offset_ is relative to the current position.
1054   #
1055   # Raises IOError if the internal read buffer is not empty.  Raises IOError
1056   # if #closed? returns +true+.  Raises Errno::ESPIPE unless #seekable?
1057   # returns +true+.
1058   #
1059   # <b>NOTE:</b> Because this method relies on #unbuffered_seek, it will also
1060   # raise the same errors and block at the same times as that function.
1061   def sysseek(offset, whence = IO::SEEK_SET)
1062     raise IOError, 'closed stream' if closed?
1063     raise Errno::ESPIPE unless seekable?
1064     unless __io_like__internal_read_buffer.empty? then
1065       raise IOError, 'sysseek on buffered IO'
1066     end
1067     unless __io_like__internal_write_buffer.empty? then
1068       warn('warning: sysseek on buffered IO')
1069     end
1070 
1071     unbuffered_seek(offset, whence)
1072   end
1073 
1074   # call-seq:
1075   #   ios.syswrite(string) -> integer
1076   #
1077   # Writes _string_ directly to the data stream, bypassing the internal write
1078   # buffer and returns the number of bytes written.
1079   #
1080   # As a side effect for non-duplex objects, the internal read buffer is
1081   # flushed.
1082   #
1083   # Raises IOError if #closed? returns +true+.  Raises IOError unless
1084   # #writable? returns +true+.
1085   #
1086   # <b>NOTE:</b> Because this method relies on #unbuffered_write, it will also
1087   # raise the same errors and block at the same times as that function.
1088   def syswrite(string)
1089     raise IOError, 'closed stream' if closed?
1090     raise IOError, 'not opened for writing' unless writable?
1091     unless __io_like__internal_write_buffer.empty? then
1092       warn('warning: syswrite on buffered IO')
1093     end
1094 
1095     # Flush the internal read buffer and set the unbuffered position to the
1096     # buffered position when dealing with non-duplexed objects.
1097     unless duplexed? || __io_like__internal_read_buffer.empty? then
1098       unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1099       __io_like__internal_read_buffer.slice!(0..-1)
1100     end
1101 
1102     unbuffered_write(string)
1103   end
1104 
1105   # call-seq:
1106   #   ios.to_io            -> ios
1107   #
1108   # Returns _ios_.
1109   def to_io
1110     self
1111   end
1112 
1113   # call-seq:
1114   #   ios.ungetc(integer)  -> nil
1115   #
1116   # Calls #unread with <tt>integer.chr</tt> as an argument.
1117   #
1118   # Raises IOError if #closed? returns +true+.  Raises IOError unless
1119   # #readable? returns +true+.
1120   def ungetc(integer)
1121     unread(integer.chr)
1122   end
1123 
1124   # call-seq:
1125   #   ios.unread(string)  -> nil
1126   #
1127   # Pushes the given string onto the front of the internal read buffer and
1128   # returns +nil+.  If _string_ is not a String, it is converted to one using
1129   # its +to_s+ method.
1130   #
1131   # Raises IOError if #closed? returns +true+.  Raises IOError unless
1132   # #readable? returns +true+.
1133   def unread(string)
1134     raise IOError, 'closed stream' if closed?
1135     raise IOError, 'not opened for reading' unless readable?
1136     __io_like__internal_read_buffer.insert(0, string.to_s)
1137     nil
1138   end
1139 
1140   # call-seq:
1141   #   ios.write_ready?        -> true or false
1142   #
1143   # Returns +true+ when the stream may be written without error, +false+
1144   # otherwise.  This method will block until one of the conditions is known.
1145   #
1146   # This default implementation of #write_ready? is a hack which should be
1147   # able to work for both real IO objects and IO-like objects; however, it is
1148   # inefficient since it merely sleeps for 1 second and then returns +true+ as
1149   # long as #closed? returns +false+.  IO.select should be used for real
1150   # IO objects to wait for a writeable condition on platforms with support for
1151   # IO.select.  Other solutions should be found as necessary to improve this
1152   # implementation on a case by case basis.
1153   #
1154   # Basically, this method should be overridden in derivative classes.
1155   def write_ready?
1156     return false unless writable?
1157     sleep(1)
1158     true
1159   end
1160 
1161   # call-seq:
1162   #   ios.writable?        -> true or false
1163   #
1164   # Returns +true+ if the stream is both open and writable, +false+ otherwise.
1165   #
1166   # This implementation checks to see if #unbuffered_write is defined in order
1167   # to make its determination.  Override this if the implementing class always
1168   # provides the #unbuffered_write method but may not always be open in a
1169   # writable mode.
1170   def writable?
1171     ! __io_like__closed_write? && respond_to?(:unbuffered_write, true)
1172   end
1173 
1174   # call-seq:
1175   #   ios.write(string)    -> integer
1176   #
1177   # Writes the given string to the stream and returns the number of bytes
1178   # written.  If _string_ is not a String, its +to_s+ method is used to
1179   # convert it into one.  The entire contents of _string_ are written,
1180   # blocking as necessary even if the data stream does not block.
1181   #
1182   # Raises IOError if #closed? returns +true+.  Raises IOError unless
1183   # #writable? returns +true+.
1184   #
1185   # <b>NOTE:</b> This method ignores Errno::EAGAIN and Errno::EINTR raised by
1186   # #unbuffered_write.  Therefore, this method always blocks if unable to
1187   # immediately write _string_ completely.  Aside from that exception, this
1188   # method will also raise the same errors and block at the same times as
1189   # #unbuffered_write.
1190   def write(string)
1191     string = string.to_s
1192     return 0 if string.empty?
1193 
1194     bytes_written = 0
1195     while bytes_written < string.length do
1196       begin
1197         bytes_written +=
1198           __io_like__buffered_write(string.to_s.slice(bytes_written..-1))
1199       rescue Errno::EAGAIN, Errno::EINTR
1200         retry if write_ready?
1201       end
1202     end
1203     bytes_written
1204   end
1205 
1206   private
1207 
1208   # call-seq:
1209   #   ios.__io_like__buffered_flush   -> 0
1210   #
1211   # Attempts to completely flush the internal write buffer to the data stream.
1212   #
1213   # Raises IOError unless #writable? returns +true+.
1214   #
1215   # <b>NOTE:</b> Because this method relies on #unbuffered_write, it raises
1216   # all errors raised by #unbuffered_write and blocks when #unbuffered_write
1217   # blocks.
1218   def __io_like__buffered_flush
1219     raise IOError, 'closed stream' if closed?
1220     raise IOError, 'not opened for writing' unless writable?
1221 
1222     until __io_like__internal_write_buffer.empty? do
1223       __io_like__internal_write_buffer.slice!(
1224         0, unbuffered_write(__io_like__internal_write_buffer)
1225       )
1226     end
1227     0
1228   end
1229 
1230   # call-seq:
1231   #   ios.__io_like__buffered_read(length) -> string
1232   #
1233   # Reads at most _length_ bytes first from an internal read buffer followed
1234   # by the underlying stream if necessary and returns the resulting buffer.
1235   #
1236   # Raises EOFError if the internal read buffer is empty and reading begins at
1237   # the end of the stream.  Raises IOError unless #readable? returns +true+.
1238   #
1239   # <b>NOTE:</b> Because this method relies on #unbuffered_read, it raises all
1240   # errors raised by #unbuffered_read and blocks when #unbuffered_read blocks
1241   # whenever the internal read buffer is unable to fulfill the request.
1242   def __io_like__buffered_read(length)
1243     # Check the validity of the method arguments.
1244     raise ArgumentError, "non-positive length #{length} given" if length < 0
1245 
1246     raise IOError, 'closed stream' if closed?
1247     raise IOError, 'not opened for reading' unless readable?
1248 
1249     # Flush the internal write buffer for writable, non-duplexed objects.
1250     __io_like__buffered_flush if writable? && ! duplexed?
1251 
1252     # Ensure that the internal read buffer has at least enough data to satisfy
1253     # the request.
1254     if __io_like__internal_read_buffer.length < length then
1255       unbuffered_length = length - __io_like__internal_read_buffer.length
1256       unbuffered_length = fill_size if unbuffered_length < fill_size
1257 
1258       begin
1259         __io_like__internal_read_buffer << unbuffered_read(unbuffered_length)
1260       rescue EOFError, SystemCallError
1261         # Reraise the error if there is no data to return.
1262         raise if __io_like__internal_read_buffer.empty?
1263       end
1264     end
1265 
1266     # Read from the internal read buffer.
1267     buffer = __io_like__internal_read_buffer.slice!(0, length)
1268 
1269     buffer
1270   end
1271 
1272   # call-seq:
1273   #   ios.__io_like__buffered_seek(offset[, whence]) -> integer
1274   #
1275   # Sets the current data position to _offset_ based on the setting of
1276   # _whence_.  If _whence_ is unspecified or IO::SEEK_SET, _offset_ counts
1277   # from the beginning of the data.  If _whence_ is IO::SEEK_END, _offset_
1278   # counts from the end of the data (_offset_ should be negative here).  If
1279   # _whence_ is IO::SEEK_CUR, _offset_ is relative to the current position.
1280   #
1281   # As a side effect, the internal read and write buffers are flushed except
1282   # when seeking relative to the current position (whence is IO::SEEK_CUR) to
1283   # a location within the internal read buffer.
1284   #
1285   # Raises Errno::ESPIPE unless #seekable? returns +true+.
1286   #
1287   # See #seek for the usage of _offset_ and _whence_.
1288   #
1289   # <b>NOTE:</b> Because this method relies on #unbuffered_seek and
1290   # #unbuffered_write (when the internal write buffer is not empty), it will
1291   # raise the same errors and block at the same times as those functions.
1292   def __io_like__buffered_seek(offset, whence = IO::SEEK_SET)
1293     raise IOError, 'closed stream' if closed?
1294     raise Errno::ESPIPE unless seekable?
1295 
1296     if whence == IO::SEEK_CUR && offset == 0 then
1297       # The seek is only determining the current position, so return the
1298       # buffered position based on the read buffer if it's not empty and the
1299       # write buffer otherwise.
1300       __io_like__internal_read_buffer.empty? ?
1301         unbuffered_seek(0, IO::SEEK_CUR) +
1302           __io_like__internal_write_buffer.length :
1303         unbuffered_seek(0, IO::SEEK_CUR) -
1304           __io_like__internal_read_buffer.length
1305     elsif whence == IO::SEEK_CUR && offset > 0 &&
1306           __io_like__internal_write_buffer.empty? &&
1307           offset <= __io_like__internal_read_buffer.length then
1308       # The seek is within the read buffer, so just discard a sufficient
1309       # amount of the buffer and report the new buffered position.
1310       __io_like__internal_read_buffer.slice!(0, offset)
1311       unbuffered_seek(0, IO::SEEK_CUR) -
1312         __io_like__internal_read_buffer.length
1313     else
1314       # The seek target is outside of the buffers, so flush the buffers and
1315       # jump to the new position.
1316       if whence == IO::SEEK_CUR then
1317         # Adjust relative offsets based on the current buffered offset.
1318         offset += __io_like__internal_read_buffer.empty? ?
1319           __io_like__internal_write_buffer.length :
1320           -__io_like__internal_read_buffer.length
1321       end
1322 
1323       # Flush the internal buffers.
1324       __io_like__internal_read_buffer.slice!(0..-1)
1325       __io_like__buffered_flush if writable?
1326 
1327       # Move the data stream's position as requested.
1328       unbuffered_seek(offset, whence)
1329     end
1330   end
1331 
1332   # call-seq:
1333   #   ios.__io_like__buffered_write(string) -> integer
1334   #
1335   # Writes _string_ to the internal write buffer and returns the number of
1336   # bytes written.  If the internal write buffer is overfilled by _string_, it
1337   # is repeatedly flushed until that last of _string_ is consumed.  A partial
1338   # write will occur if part of _string_ fills the internal write buffer but
1339   # the internal write buffer cannot be immediately flushed due to the
1340   # underlying stream not blocking when unable to accept more data.
1341   #
1342   # <b>NOTE:</b> Because this method relies on #unbuffered_write, it raises
1343   # all errors raised by #unbuffered_write and blocks when #unbuffered_write
1344   # blocks whenever the internal write buffer is unable to fulfill the
1345   # request.
1346   def __io_like__buffered_write(string)
1347     raise IOError, 'closed stream' if closed?
1348     raise IOError, 'not opened for writing' unless writable?
1349 
1350     # Flush the internal read buffer and set the unbuffered position to the
1351     # buffered position when dealing with non-duplexed objects.
1352     unless duplexed? || __io_like__internal_read_buffer.empty? then
1353       unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1354       __io_like__internal_read_buffer.slice!(0..-1)
1355     end
1356 
1357     bytes_written = 0
1358     if sync then
1359       # Flush the internal write buffer and then bypass it when in synchronous
1360       # mode.
1361       __io_like__buffered_flush
1362       bytes_written = unbuffered_write(string)
1363     else
1364       if __io_like__internal_write_buffer.length + string.length >= flush_size then
1365         # The tipping point for the write buffer would be surpassed by this
1366         # request, so flush everything.
1367         __io_like__buffered_flush
1368         bytes_written = unbuffered_write(string)
1369       else
1370         # The buffer can absorb the entire request.
1371         __io_like__internal_write_buffer << string
1372         bytes_written = string.length
1373       end
1374     end
1375     return bytes_written
1376   end
1377 
1378   # Returns a reference to the internal read buffer.
1379   def __io_like__internal_read_buffer
1380     @__io_like__read_buffer ||= ''
1381   end
1382 
1383   # Returns a reference to the internal write buffer.
1384   def __io_like__internal_write_buffer
1385     @__io_like__write_buffer ||= ''
1386   end
1387 
1388   # Returns +true+ if this object has been closed for reading; otherwise,
1389   # returns +false+.
1390   def __io_like__closed_read?
1391     @__io_like__closed_read ||= false
1392   end
1393 
1394   # Arranges for #__io_like__closed_read? to return +true+.
1395   def __io_like__close_read
1396     @__io_like__closed_read = true
1397     nil
1398   end
1399 
1400   # Returns +true+ if this object has been closed for writing; otherwise,
1401   # returns +false+.
1402   def __io_like__closed_write?
1403     @__io_like__closed_write ||= false
1404   end
1405 
1406   # Arranges for #__io_like__closed_write? to return +true+.
1407   def __io_like__close_write
1408     @__io_like__closed_write = true
1409     nil
1410   end
1411 
1412   # This method joins the elements of _array_ together with _separator_
1413   # between each element and returns the result.  _seen_ is a list of object
1414   # IDs representing arrays which have already started processing.
1415   #
1416   # This method exists only because Array#join apparently behaves in an
1417   # implementation dependent manner when joining recursive arrays and so does
1418   # not always produce the expected results.  Specifically, MRI 1.8.6 and
1419   # 1.8.7 behave as follows:
1420   #
1421   #   x = []
1422   #   x << 1 << x << 2
1423   #   x.join(', ')              => "1, 1, [...], 2, 2"
1424   #
1425   # The expected and necessary result for use with #puts is:
1426   #
1427   #   "1, [...], 2"
1428   #
1429   # Things get progressively worse as the nesting and recursion become more
1430   # convoluted.
1431   def __io_like__array_join(array, separator, seen = [])
1432     seen.push(array.object_id)
1433     need_separator = false
1434     result = array.inject('') do |memo, item|
1435       memo << separator if need_separator
1436       need_separator = true
1437 
1438       memo << if item.kind_of?(Array) then
1439                 if seen.include?(item.object_id) then
1440                   '[...]'
1441                 else
1442                   __io_like__array_join(item, separator, seen)
1443                 end
1444               else
1445                 item.to_s
1446               end
1447     end
1448     seen.pop
1449 
1450     result
1451   end
1452 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.rb
881 def readlines(sep_string = $/)
882   lines = []
883   each_line(sep_string) { |line| lines << line }
884   lines
885 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 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.rb
905 def readpartial(length, buffer = nil)
906   # Check the validity of the method arguments.
907   unless length >= 0 then
908     raise ArgumentError, "negative length #{length} given"
909   end
910   buffer = '' if buffer.nil?
911   # Flush the buffer.
912   buffer.slice!(0..-1)
913 
914   # Read and return up to length bytes.
915   if __io_like__internal_read_buffer.empty? then
916     begin
917       buffer << __io_like__buffered_read(length)
918     rescue Errno::EAGAIN, Errno::EINTR
919       retry if read_ready?
920     end
921   else
922     raise IOError, 'closed stream' if closed?
923     raise IOError, 'not opened for reading' unless readable?
924 
925     buffer << __io_like__internal_read_buffer.slice!(0, length)
926   end
927   buffer
928 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.rb
945 def rewind
946   seek(0, IO::SEEK_SET)
947   self.lineno = 0 if readable?
948   0
949 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.rb
970 def seek(offset, whence = IO::SEEK_SET)
971   __io_like__buffered_seek(offset, whence)
972   0
973 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.rb
984 def seekable?
985   ! duplexed? && respond_to?(:unbuffered_seek, true)
986 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.rb
995 def sync
996   raise IOError, 'closed stream' if closed?
997   @__io_like__sync ||= false
998 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.rb
1009 def sync=(sync)
1010   raise IOError, 'closed stream' if closed?
1011   @__io_like__sync = sync ? true : false
1012 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.rb
1029 def sysread(length, buffer = nil)
1030   buffer = buffer.nil? ? '' : buffer.to_str
1031   buffer.slice!(0..-1) unless buffer.empty?
1032   return buffer if length == 0
1033 
1034   raise IOError, 'closed stream' if closed?
1035   raise IOError, 'not opened for reading' unless readable?
1036   unless __io_like__internal_read_buffer.empty? then
1037     raise IOError, 'sysread on buffered IO'
1038   end
1039 
1040   # Flush the internal write buffer for writable, non-duplexed objects.
1041   __io_like__buffered_flush if writable? && ! duplexed?
1042 
1043   buffer << unbuffered_read(length)
1044 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.rb
1061 def sysseek(offset, whence = IO::SEEK_SET)
1062   raise IOError, 'closed stream' if closed?
1063   raise Errno::ESPIPE unless seekable?
1064   unless __io_like__internal_read_buffer.empty? then
1065     raise IOError, 'sysseek on buffered IO'
1066   end
1067   unless __io_like__internal_write_buffer.empty? then
1068     warn('warning: sysseek on buffered IO')
1069   end
1070 
1071   unbuffered_seek(offset, whence)
1072 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.rb
1088 def syswrite(string)
1089   raise IOError, 'closed stream' if closed?
1090   raise IOError, 'not opened for writing' unless writable?
1091   unless __io_like__internal_write_buffer.empty? then
1092     warn('warning: syswrite on buffered IO')
1093   end
1094 
1095   # Flush the internal read buffer and set the unbuffered position to the
1096   # buffered position when dealing with non-duplexed objects.
1097   unless duplexed? || __io_like__internal_read_buffer.empty? then
1098     unbuffered_seek(-__io_like__internal_read_buffer.length, IO::SEEK_CUR)
1099     __io_like__internal_read_buffer.slice!(0..-1)
1100   end
1101 
1102   unbuffered_write(string)
1103 end
Alias for: pos
to_io → ios click to toggle source

Returns ios.

     # File lib/io/like.rb
1109 def to_io
1110   self
1111 end
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.rb
1120 def ungetc(integer)
1121   unread(integer.chr)
1122 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.rb
1133 def unread(string)
1134   raise IOError, 'closed stream' if closed?
1135   raise IOError, 'not opened for reading' unless readable?
1136   __io_like__internal_read_buffer.insert(0, string.to_s)
1137   nil
1138 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.rb
1170 def writable?
1171   ! __io_like__closed_write? && respond_to?(:unbuffered_write, true)
1172 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.rb
1190 def write(string)
1191   string = string.to_s
1192   return 0 if string.empty?
1193 
1194   bytes_written = 0
1195   while bytes_written < string.length do
1196     begin
1197       bytes_written +=
1198         __io_like__buffered_write(string.to_s.slice(bytes_written..-1))
1199     rescue Errno::EAGAIN, Errno::EINTR
1200       retry if write_ready?
1201     end
1202   end
1203   bytes_written
1204 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.rb
1155 def write_ready?
1156   return false unless writable?
1157   sleep(1)
1158   true
1159 end