lib/io/splice.rb in io_splice-1.0.0 vs lib/io/splice.rb in io_splice-2.0.0
- old
+ new
@@ -3,17 +3,20 @@
class IO
module Splice
- # the version of IO::Splice, currently 0.1.0
- VERSION = '1.0.0'
+ # the version of IO::Splice, currently 2.0.0
+ VERSION = '2.0.0'
- # The maximum capacity of the pipe in bytes.
+ # The maximum default capacity of the pipe in bytes.
# Under stock Linux, this is 65536 bytes as of 2.6.11, and 4096 before
# We detect this at runtime as it is easy to recompile the kernel
# and set a new value.
+ # Starting with Linux 2.6.35, pipe capacity will be tunable
+ # and this will only represent the default capacity of a
+ # newly-created pipe.
PIPE_CAPA = begin
rd, wr = IO.pipe
buf = ' ' * PIPE_BUF
n = 0
begin
@@ -22,9 +25,73 @@
break
end while true
wr.close
rd.close
n
+ end
+
+ # copies the contents of the IO object given by +src+ to +dst+
+ # If len is specified, then only len bytes are copied. Otherwise
+ # the copy will be until EOF is reached on the +src+.
+ # +src+ and +dst+ must be IO objects or respond to +to_io+
+ def self.copy_stream(src, dst, len = nil, src_offset = nil)
+ src.kind_of?(String) and src = File.open(src, 'rb')
+ dst.kind_of?(String) and dst = File.open(dst, 'wb')
+ src, dst = src.to_io, dst.to_io
+ rv = len
+ src.sysseek(src_offset) if src_offset
+ if src.stat.pipe? || dst.stat.pipe?
+ if len
+ while len > 0
+ nr = len > PIPE_CAPA ? PIPE_CAPA : len
+ nr = IO.splice(src, nil, dst, nil, nr, F_MOVE)
+ if nr == 0
+ raise EOFError, "unexpected EOF with #{len} bytes left"
+ end
+ len -= nr
+ end
+ else
+ rv = 0
+ begin
+ nr = IO.splice(src, nil, dst, nil, PIPE_CAPA, F_MOVE)
+ rv += nr
+ rescue EOFError
+ break
+ end while true
+ end
+ else
+ begin
+ r, w = IO.pipe
+ if len
+ while len > 0
+ nr = len > PIPE_CAPA ? PIPE_CAPA : len
+ nr_src = copy_stream(src, w, nr)
+ nr_src == nr or
+ raise RuntimeError, "short splice from: #{nr_src} != #{nr}"
+ nr_dst = copy_stream(r, dst, nr)
+ nr_dst == nr or
+ raise RuntimeError, "short splice to: #{nr_dst} != #{nr}"
+ len -= nr
+ end
+ else
+ rv = 0
+ begin
+ nr = IO.splice(src, nil, w, nil, PIPE_CAPA, F_MOVE)
+ rv += nr
+ begin
+ nr -= IO.splice(r, nil, dst, nil, nr, F_MOVE)
+ end while nr > 0
+ rescue EOFError
+ break
+ end while true
+ end
+ ensure
+ r.close
+ w.close
+ end
+ end
+
+ rv
end
end
end