lib/io/splice.rb in io_splice-2.2.0 vs lib/io/splice.rb in io_splice-2.2.0.18.g3025
- old
+ new
@@ -1,120 +1,114 @@
# -*- encoding: binary -*-
require 'io_splice_ext'
-class IO
+module IO::Splice
- module Splice
+ # the version of IO::Splice, currently 2.2.0
+ VERSION = '2.2.0'
- # the version of IO::Splice, currently 2.2.0
- VERSION = '2.2.0'
+ # 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
+ n += wr.write_nonblock(buf)
+ rescue Errno::EAGAIN
+ break
+ end while true
+ wr.close
+ rd.close
+ n
+ end
- # 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
- n += wr.write_nonblock(buf)
- rescue Errno::EAGAIN
- 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 and
+ # +EOFError+ is raised if fewer than +len+ bytes could be 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)
+ close = []
+ src.kind_of?(String) and close << (src = File.open(src))
+ dst.kind_of?(String) and close << (dst = File.open(dst, "w"))
+ src, dst = src.to_io, dst.to_io
+ rv = len
+ src.sysseek(src_offset) if src_offset
+ select_args = selectable(src, dst)
- # 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 Splice.copy_stream(src, dst, len = nil, src_offset = nil)
- close = []
- src.kind_of?(String) and close << (src = File.open(src, 'rb'))
- dst.kind_of?(String) and close << (dst = File.open(dst, 'wb'))
- src, dst = src.to_io, dst.to_io
- rv = len
- src.sysseek(src_offset) if src_offset
- select_args = selectable(src, dst)
-
- if src.stat.pipe? || dst.stat.pipe?
- if len
- len -= full(src, dst, len, select_args) until len == 0
- else
- rv = 0
- begin
- rv += partial(src, dst, PIPE_CAPA, select_args)
- rescue EOFError
- break
- end while true
+ if src.stat.pipe? || dst.stat.pipe?
+ if len
+ len -= full(src, dst, len, select_args) until len == 0
+ else
+ rv = 0
+ while n = partial(src, dst, PIPE_CAPA, select_args)
+ rv += n
end
+ end
+ else
+ r, w = tmp = IO.pipe
+ close.concat(tmp)
+ if len
+ while len != 0 && n = partial(src, w, len, select_args)
+ len -= full(r, dst, n, select_args)
+ end
else
- r, w = tmp = IO.pipe
- close.concat(tmp)
- if len
- while len != 0
- nr = partial(src, w, len, select_args)
- len -= full(r, dst, nr, select_args)
- end
- else
- rv = 0
- begin
- nr = partial(src, w, PIPE_CAPA, select_args)
- rv += full(r, dst, nr, select_args)
- rescue EOFError
- break
- end while true
+ rv = 0
+ while n = partial(src, w, PIPE_CAPA, select_args)
+ rv += full(r, dst, n, select_args)
end
end
-
- rv
- ensure
- close.each { |io| io.close }
end
- # splice the full amount specified from +src+ to +dst+
- # Either +dst+ or +src+ must be a pipe. +dst+ and +src+
- # may BOTH be pipes in Linux 2.6.31 or later.
- # This will block and wait for IO completion of +len+
- # bytes. Returns the nubmer of bytes actually spliced (always +len+)
- # The +_select_args+ parameter is reserved for internal use and
- # may be removed in future versions. Do not write code that
- # depends on +_select_args+.
- def Splice.full(src, dst, len, _select_args = selectable(src, dst))
- nr = len
- nr -= partial(src, dst, nr, _select_args) until nr == 0
- len
- end
+ rv
+ ensure
+ close.each { |io| io.close }
+ end
- # splice up to +len+ bytes from +src+ to +dst+.
- # Either +dst+ or +src+ must be a pipe. +dst+ and +src+
- # may BOTH be pipes in Linux 2.6.31 or later.
- # Returns the number of bytes actually spliced.
- # Like IO#readpartial, this never returns Errno::EAGAIN
- # The +_select_args+ parameter is reserved for internal use and
- # may be removed in future versions. Do not write code that
- # depends on +_select_args+.
- def Splice.partial(src, dst, len, _select_args = selectable(src, dst))
- begin
- IO.splice(src, nil, dst, nil, len, F_MOVE)
- rescue Errno::EAGAIN
- IO.select(*_select_args)
- retry
- end
+ # splice the full amount specified from +src+ to +dst+
+ # Either +dst+ or +src+ must be a pipe. +dst+ and +src+
+ # may BOTH be pipes in Linux 2.6.31 or later.
+ # This will block and wait for IO completion of +len+
+ # Raises +EOFError+ if end of file is reached.
+ # bytes. Returns the number of bytes actually spliced (always +len+)
+ # The +_select_args+ parameter is reserved for internal use and
+ # may be removed in future versions. Do not write code that
+ # depends on +_select_args+.
+ def self.full(src, dst, len, _select_args = selectable(src, dst))
+ nr = len
+ while nr > 0
+ n = partial(src, dst, nr, _select_args) or
+ raise EOFError, "end of file reached"
+ nr -= n
end
+ len
+ end
- # returns an array suitable for splat-ing to IO.select for blocking I/O
- def Splice.selectable(src, dst)
- rv = []
- src.stat.pipe? or rv[0] = [ src ]
- dst.stat.pipe? or rv[1] = [ dst ]
- rv
- end
+ # splice up to +len+ bytes from +src+ to +dst+.
+ # Either +dst+ or +src+ must be a pipe. +dst+ and +src+
+ # may BOTH be pipes in Linux 2.6.31 or later.
+ # Returns the number of bytes actually spliced.
+ # Like IO#readpartial, this never returns Errno::EAGAIN
+ # The +_select_args+ parameter is reserved for internal use and
+ # may be removed in future versions. Do not write code that
+ # depends on +_select_args+.
+ def self.partial(src, dst, len, _select_args = selectable(src, dst))
+ begin
+ rv = IO.trysplice(src, nil, dst, nil, len, F_MOVE)
+ end while rv == :EAGAIN and IO.select(*_select_args)
+ rv
+ end
+ # returns an array suitable for splat-ing to IO.select for blocking I/O
+ def self.selectable(src, dst)
+ rv = []
+ src.stat.pipe? or rv[0] = [ src ]
+ dst.stat.pipe? or rv[1] = [ dst ]
+ rv
end
end