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.
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
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
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
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.
Contributions for bug fixes, documentation, extensions, tests, etc. are encouraged. Please read the file HACKING for details.