Ara.T.Howard said:
I want to clone a filedescriptor, but no matter
what I try I becomes ugly. The nice solution doesn't
seems to work.
[snip]
doesn't this do it?
[snip]
f2 = f1.dup
[snip]
Hmmm bad proof of concept.. Therefore I will have to
tell the full story: Im writing a file-iterator which both can go
forward and backwards. #dup doesn't work here, only
the long ugly expression I showed you in the first mail.
By using #dup then my clone test fails. I have absolutely
no idea why #dup is yielding nil here.... maybe bug?
server> ruby test_file.rb
Loaded suite XTestFile
Started
..F.
Finished in 0.042698 seconds.
1) Failure:
test_clone1(XTestFile) [test_file.rb:106]:
<101> expected but was
<nil>.
4 tests, 5 assertions, 1 failures, 0 errors
server>
By using @file.clone.reopen(@file), then it works, but I
am not confident that it really works (because its
really ugly).
server> ruby test_file.rb
Loaded suite XTestFile
Started
....
Finished in 0.006764 seconds.
4 tests, 6 assertions, 0 failures, 0 errors
server>
The testcase looks like
def test_clone1
@i.next(2)
assert_equal("c"[0], @i.current)
i2 = @i.clone
begin
i2.next(2)
assert_equal("e"[0], i2.current)
# check that clone were harmless
assert_equal("c"[0], @i.current)
ensure
i2.close
end
end
I have attached the source code for. In order to run it
you will need to fetch my 'iterator' package.
http://raa.ruby-lang.org/list.rhtml?name=iterator
require 'test/unit'
require 'iterator'
module Iterator
class File < Base
def initialize(file)
@file = file
end
attr_reader :file
def clone
#cfd = IO.new(@file.fileno, 'r')
#cfd = @file.clone
#cfd = @file.dup
cfd = @file.clone.reopen(@file) # BOOM BOOM BOOM... this clone is ugly
#puts "FD=#{@file.fileno} CLONE=#{cfd.fileno}"
self.class.new(cfd)
end
def close
@file.close
end
def first
@file.rewind
self
end
def last
@file.seek(0, IO::SEEK_END)
self
end
def has_next?
not @file.eof?
end
def next1
@file.seek(1, IO::SEEK_CUR)
end
def current
byte = @file.getc
@file.seek(-1, IO::SEEK_CUR)
byte
end
def has_prev?
(@file.pos > 0)
end
def prev1
@file.seek(-1, IO::SEEK_CUR)
end
def current_prev
@file.seek(-1, IO::SEEK_CUR)
@file.getc
end
end
end # module Iterator
class XTestFile < Test::Unit::TestCase
def setup
@data = "abcdefg"
#@i = @data.create_iterator # yields integers between 0..255
@filename = "____filedata"
File.open(@filename, "w+") do |f|
f.write(@data)
end
@file = File.open(@filename, "r")
@i = Iterator::File.new(@file)
end
def teardown
@i.close
raise "@file not closed" unless @file.closed?
end
def test_forward1
result = []
while @i.has_next?
result << @i.current
@i.next
end
assert_equal("abcdefg", result.map{|byte| byte.chr}.join)
end
def test_backward1
@i.last
result = []
while @i.has_prev?
result << @i.current_prev
@i.prev
end
result.reverse!
assert_equal("abcdefg", result.map{|byte| byte.chr}.join)
end
def test_backward2
rev = @i.last.reverse
result = []
while rev.has_next?
result << rev.current
rev.next
end
result.reverse!
assert_equal("abcdefg", result.map{|byte| byte.chr}.join)
ensure
rev.close
end
def test_clone1
@i.next(2)
assert_equal("c"[0], @i.current)
i2 = @i.clone
begin
i2.next(2)
assert_equal("e"[0], i2.current)
# check that clone were harmless
assert_equal("c"[0], @i.current)
ensure
i2.close
end
end
end
if $0 == __FILE__
require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(XTestFile)
end
BTW: I am using CVS-head version of Ruby.
server> ruby -v
ruby 1.9.0 (2004-05-17) [i386-freebsd5.1]
server>