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
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
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
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
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
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
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
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
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
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
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
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
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
Returns self
. Just for compatibility with IO
.
# File lib/io/like.rb 91 def binmode 92 self 93 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.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
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
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
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
Returns false
. Override this to return true
when creating duplexed IO
objects.
# File lib/io/like.rb 170 def duplexed? 171 false 172 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.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
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
Raises NotImplementedError.
# File lib/io/like.rb 240 def fcntl(*args) 241 raise NotImplementedError, 'not implemented' 242 end
Returns nil
. Just for compatibility with IO
.
# File lib/io/like.rb 248 def fileno 249 nil 250 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.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
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
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
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
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
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
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
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
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
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
Returns nil
. Just for compatibility with IO
.
# File lib/io/like.rb 452 def path 453 nil 454 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.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
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
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.rb 514 def print(*args) 515 args << $_ if args.empty? 516 first_arg = true 517 args.each do |arg| 518 # Write a field separator before writing each argument after the first 519 # one unless no field separator is specified. 520 if first_arg then 521 first_arg = false 522 elsif ! $,.nil? then 523 write($,) 524 end 525 526 # If the argument is nil, write 'nil'; otherwise, write the stringified 527 # form of the argument. 528 if arg.nil? then 529 write('nil') 530 else 531 write(arg) 532 end 533 end 534 535 # Write the output record separator if one is specified. 536 write($\) unless $\.nil? 537 nil 538 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.rb 554 def printf(*args) 555 write(sprintf(*args)) 556 nil 557 end
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Returns ios.
# File lib/io/like.rb 1109 def to_io 1110 self 1111 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.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
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
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
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