IO::Like - in the Likeness of IO
The IO::Like module provides all of the methods of typical IO implementations such as File; most importantly the read, write, and seek series of methods. A class which includes IO::Like needs to provide only a few methods in order to enable the higher level methods. Buffering is automatically provided by default for the methods which normally provide it in IO.
See the documentation for IO::Like for more details regarding the necessary methods.
License
Copyright © 2008,2009 Jeremy Bopp <jeremy at bopp dot net>
Licensed under the same terms as Ruby – See the included LICENSE file for details
Some parts licensed under the same terms as the rubyspec project – See the included LEGAL and LICENSE.rubyspec files for details
Installation/Removal
Download the GEM file and install it with:
% sudo gem install io-like-VERSION.gem
or directly with:
% sudo gem install io-like
Removal is the same in either case:
% sudo gem uninstall io-like
Example
More examples can be found in the examples directory of the source distribution.
A simple ROT13 codec:
gem 'io-like' # Use require_gem for rubygems versions older than 0.9.0.
require 'io/like'
class ROT13Filter
include IO::Like
def self.open(delegate_io)
filter = new(delegate_io)
return filter unless block_given?
begin
yield(filter)
ensure
filter.close unless filter.closed?
end
end
def initialize(delegate_io)
@delegate_io = delegate_io
end
private
def encode_rot13(string)
result = string.dup
0.upto(result.length) do |i|
case result[i]
when 65..90
result[i] = (result[i] - 52) % 26 + 65
when 97..122
result[i] = (result[i] - 84) % 26 + 97
end
end
result
end
def unbuffered_read(length)
encode_rot13(@delegate_io.sysread(length))
end
def unbuffered_seek(offset, whence = IO::SEEK_SET)
@delegate_io.sysseek(offset, whence)
end
def unbuffered_write(string)
@delegate_io.syswrite(encode_rot13(string))
end
end
File.open('normal_file.txt', 'w') do |f|
f.puts('This is a test')
end
File.open('rot13_file.txt', 'w') do |f|
ROT13Filter.open(f) do |rot13|
rot13.puts('This is a test')
end
end
File.open('normal_file.txt') do |f|
ROT13Filter.open(f) do |rot13|
puts(rot13.read) # -> Guvf vf n grfg
end
end
File.open('rot13_file.txt') do |f|
ROT13Filter.open(f) do |rot13|
puts(rot13.read) # -> This is a test
end
end
File.open('normal_file.txt') do |f|
ROT13Filter.open(f) do |rot13|
rot13.pos = 5
puts(rot13.read) # -> vf n grfg
end
end
File.open('rot13_file.txt') do |f|
ROT13Filter.open(f) do |rot13|
rot13.pos = 5
puts(rot13.read) # -> is a test
end
end
File.open('normal_file.txt') do |f|
ROT13Filter.open(f) do |rot13|
ROT13Filter.open(rot13) do |rot26| # ;-)
puts(rot26.read) # -> This is a test
end
end
end
Known Bugs/Limitations
-
Only up to version 1.8.6 of Ruby’s IO interface is implemented. Version 1.8.7 and eventually 1.9.0/2.0.0 support are coming soon.
-
Ruby’s finalization capabilities fall a bit short in a few respects, and as a result, it is impossible to cause the close, close_read, or close_write methods to be called automatically when an including class is garbage collected. Define a class open method in the manner of File.open which guarantees that an appropriate close method will be called after executing a block. Other than that, be diligent about calling the close methods.
Contributing
Contributions for bug fixes, documentation, extensions, tests, etc. are encouraged. Please read the file HACKING for details.